qpid-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Manuel Teira <mte...@tid.es>
Subject Re: qpid (cpp) on solaris + Sun Studio 12
Date Wed, 28 May 2008 09:03:38 GMT
Manuel Teira escribió:
> Manuel Teira escribió:
>   
>> Alan Conway escribió:
>>
>>     
>>> Manuel Teira wrote:
>>>
>>>
>>>       
>>>> Some new info about this problem.
>>>>
>>>> I was not able to exactly reproduce the issue with an stanalone and
>>>> meaninfull source, but have found a way to pass the compilation (other
>>>> than commenting everything, of course). The problem, I think, is related
>>>> with the std::lower_bound invocation, as shown before:
>>>>
>>>> "/opt/SUNWspro/prod/include/CC/stlport4/stl/_algo.h", line 491:
>>>> Information: Instantiating
>>>> std::__lower_bound<qpid::Range<qpid::framing::SequenceNumber>*,
>>>>                                  qpid::framing::SequenceNumber,
>>>>                                  std::less<qpid::framing::SequenceNumber>,
>>>>                                  long>
>>>> (qpid::Range<qpid::framing::SequenceNumber>*,
>>>> qpid::Range<qpid::framing::SequenceNumber>*,
>>>> const qpid::framing::SequenceNumber&,
>>>> std::less<qpid::framing::SequenceNumber>,
>>>> long*).
>>>>
>>>> All the pain begins (I think) with the fact that the first template type
>>>> (the iterator) is not valid to travel through the value type. And this
>>>> is produced (I guess) by the call, in RangeSet<T>::addRange(const
>>>> Range<T> &r) :
>>>>
>>>> typename Ranges::iterator i =
>>>>        std::lower_bound(ranges.begin(), ranges.end(), r.begin());
>>>>
>>>> That way, we are passing two valid Range<T>::iterator types and a T
>>>> value. changing that with:
>>>>
>>>> typename Ranges::iterator i = std::lower_bound(ranges.begin(),
>>>> ranges.end(), r);
>>>>
>>>> it passes the compilation with the Sun Studio 12.
>>>>
>>>>
>>>>         
>>> Hum. Odd. The point of lower_bound(i,j,x) is to evaluate *i < x.
>>> Range<T> has an operator< for T but not for Range<T> so I don't
understand
>>> how solaris is satisfying *i < x. when x is a Range<T>
>>>
>>> I tried the same thing myself and the GNU compiler didn't choke either so there
>>> clearly is some conversion sequence that allows the < comparison but it doesn't
>>> give the right answer because the RangeSet unit tests fail.
>>>
>>> HOWEVER: the simple and obvious step of adding:
>>>
>>>      bool operator<(const Range<T>& r) const { return end_ <
r.begin_; }
>>>
>>> to RangeSet makes the whole thing work beautifully so I bet it'll now build for
>>> you - comitted in revision 660647
>>>
>>>
>>>       
>> It does. Thanks a lot!
>>
>>
>>     
>>>> Perhaps the GNU compiler is able to instantiate a whole Range<T> from
>>>> the r.begin() argument? However, the Range<T>::Range(const T &t)
>>>> constructor is declared as explicit. So, I don't think that should be
>>>> the problem
>>>>
>>>> As an outline, does it make sense to pass to std::lower_bound iterators
>>>> not compatible with the value argument?
>>>>
>>>>
>>>>         
>>> Hah! No it does not. Turns out that one of the requirements on lower_bound is
>>> that "ForwardIterator's value type is the same type as LessThanComparable."
>>> I was under the mistaken impression that it was only required for *i < x to
be a
>>> valid expression.
>>>
>>> So this whole thing is my goof, thanks for sticking with it.
>>>
>>>
>>>       
>> You're welcome.
>>
>>     
>>> Cheers,
>>> Alan.
>>> .
>>>
>>>
>>>
>>>       
>> Well, the compiling effort is progressing. I have a fresh
>> libqpidcommon.so.0.1.0 but some other frightening errors arised in the
>> broker side. Once again, I'm not able to figure out what is causing this
>> one:
>>
>> ource='qpid/broker/SemanticState.cpp'
>> object='qpid/broker/SemanticState.lo' libtool=yes \
>> DEPDIR=.deps depmode=none /bin/bash ../build-aux/depcomp \
>> /bin/bash ../libtool --tag=CXX    --mode=compile CC -m64 -mt
>> -library=stlport4 -DHAVE_CONFIG_H -I. -Igen -I./gen
>> -I/opt/dslap/contrib/include -c -o qpid/broker/SemanticState.lo
>> qpid/broker/SemanticState.cpp
>>  CC -m64 -mt -library=stlport4 -DHAVE_CONFIG_H -I. -Igen -I./gen
>> -I/opt/dslap/contrib/include -c qpid/broker/SemanticState.cpp  -KPIC
>> -DPIC -o qpid/broker/.libs/SemanticState.o
>> "./qpid/sys/posix/Mutex.h", line 96: Warning (Anachronism): Formal
>> argument 2 of type extern "C" void(*)() in call to pthread_once(_once*,
>> extern "C" void(*)()) is being passed void(*)().
>> "./qpid/sys/posix/Mutex.h", line 105: Warning (Anachronism): Formal
>> argument 2 of type extern "C" void(*)() in call to pthread_once(_once*,
>> extern "C" void(*)()) is being passed void(*)().
>> "./qpid/sys/posix/Thread.h", line 67: Warning (Anachronism): Formal
>> argument 3 of type extern "C" void*(*)(void*) in call to
>> pthread_create(unsigned*, const _pthread_attr*, extern "C"
>> void*(*)(void*), void*) is being passed void*(*)(void*).
>> "./qpid/sys/posix/Thread.h", line 71: Warning (Anachronism): Formal
>> argument 3 of type extern "C" void*(*)(void*) in call to
>> pthread_create(unsigned*, const _pthread_attr*, extern "C"
>> void*(*)(void*), void*) is being passed void*(*)(void*).
>> "/opt/SUNWspro/prod/include/CC/stlport4/stl/_function.h", line 164:
>> Error: Formal argument __r of type qpid::broker::DeliveryRecord& in call
>> to std::mem_fun1_ref_t<void, qpid::broker::DeliveryRecord,
>> qpid::broker::TransactionContext*>::operator()(qpid::broker::DeliveryRecord&,
>> qpid::broker::TransactionContext*) const requires an lvalue.
>> "/opt/SUNWspro/prod/include/CC/stlport4/stl/_algo.h", line 65:
>> Where: While instantiating "std::binder2nd<std::mem_fun1_ref_t<void,
>> qpid::broker::DeliveryRecord,
>> qpid::broker::TransactionContext*>>::operator()(const
>> qpid::broker::DeliveryRecord&) const".
>> "/opt/SUNWspro/prod/include/CC/stlport4/stl/_algo.h", line 65:
>> Where: Instantiated from non-template code.
>> 1 Error(s) and 4 Warning(s) detected.
>>
>> The compiler is not giving me the offending source line, but just
>> looking at the points of SemanticState.cpp where a DeliveryRecord method
>> with a TransactionContext* argument is called using a bind2nd, has
>> brought me to these two choices:
>> line 418:      for_each(start, end,
>> bind2nd(mem_fun_ref(&DeliveryRecord::dequeue), 0));
>> line 684:      for_each(range.start, range.end,
>> bind2nd(mem_fun_ref(&DeliveryRecord::accept), 0));
>>
>> Commenting out those two lines, leads to this other error:
>>
>> "/opt/SUNWspro/prod/include/CC/stlport4/stl/_function.h", line 164:
>> Error: Formal argument __r of type qpid::broker::DeliveryRecord& in call
>> to std::mem_fun1_ref_t<void, qpid::broker::DeliveryRecord,
>> bool>::operator()(qpid::broker::DeliveryRecord&, bool) const requires an
>> lvalue.
>> "/opt/SUNWspro/prod/include/CC/stlport4/stl/_algo.h", line 65:
>> Where: While instantiating "std::binder2nd<std::mem_fun1_ref_t<void,
>> qpid::broker::DeliveryRecord, bool>>::operator()(const
>> qpid::broker::DeliveryRecord&) const".
>> "/opt/SUNWspro/prod/include/CC/stlport4/stl/_algo.h", line 65:
>> Where: Instantiated from non-template code.
>>
>> Probably produced by line 639:
>>
>>     for_each(start, end, bind2nd(mem_fun_ref(&DeliveryRecord::release),
>> setRedelivered));
>>
>> as it's the only method in DeliveryRecord accepting a bool as argument.
>>
>> I've read somewhere that std::for_each is not intended to modify the
>> traversed sequence. But I'm not sure if "modifying" means the elements
>> or the sequence itself. I've written this little test:
>>
>> #include <iostream>
>> #include <vector>
>> #include <algorithm>
>> #include <functional>
>>
>> using namespace std;
>>
>> class Item {
>> public:
>>   Item(int i): m_i(i) {};
>>   void setIndex(int i) { m_i = i; }
>>   int getIndex() const { return m_i; }
>>   void printTo(ostream *os) const { *os << "Item[" << m_i << "]
"; }
>> private:
>>   int m_i;
>> };
>>
>> int main(int argc, char *argv[])
>> {
>>   vector<Item> items;
>>   items.push_back(Item(0));
>>   items.push_back(Item(1));
>>   items.push_back(Item(2));
>>   //for_each(items.begin(), items.end(),
>> bind2nd(mem_fun_ref(&Item::setIndex), 0));
>>   for_each(items.begin(), items.end(),
>> bind2nd(mem_fun_ref(&Item::printTo), &cout));
>> }
>>
>> Note the first for_each call, commented out. GNU g++ is able to compile
>> and run that program without problem, even without commenting the first
>> for_each call. So, it's able to call a non-const method on the iterated
>> sequence. But that is not true for Sun Studio 12:
>>
>> -bash-3.00$ CC -o for_each for_each.cc
>> "/opt/SUNWspro/prod/include/CC/Cstd/./functional", line 327: Error:
>> Formal argument p of type Item& in call to std::mem_fun1_ref_t<void,
>> Item, int>::operator()(Item&, int) const requires an lvalue.
>> "/opt/SUNWspro/prod/include/CC/Cstd/./algorithm.cc", line 64:     Where:
>> While instantiating "std::binder2nd<std::mem_fun1_ref_t<void, Item,
>> int>>::operator()(const Item&) const".
>> "/opt/SUNWspro/prod/include/CC/Cstd/./algorithm.cc", line 64:     Where:
>> Instantiated from std::for_each<Item*,
>> std::binder2nd<std::mem_fun1_ref_t<void, Item, int>>>(Item*, Item*,
>> std::binder2nd<std::mem_fun1_ref_t<void, Item, int>>).
>> "for_each.cc", line 24:     Where: Instantiated from non-template code.
>> 1 Error(s) detected.
>>
>>
>> Perhaps the problem is in the Sun CC STL binder2nd implementation:
>>
>> template <class _Operation>
>> class binder2nd
>>   : public unary_function<typename
>> __BINARY_ARG(_Operation,first_argument_type),
>>                           typename __BINARY_ARG(_Operation,result_type)> {
>> protected:
>>   _Operation _M_op;
>>   typename _Operation::second_argument_type value;
>> public:
>>   binder2nd(const _Operation& __x,
>>             const typename _Operation::second_argument_type& __y)
>>       : _M_op(__x), value(__y) {}
>>   typename _Operation::result_type
>>   operator()(const typename _Operation::first_argument_type& __x) const {
>>     return _M_op(__x, value);
>>   }
>> };
>>
>> The operator() has a const reference argument, and I think it's
>> triggering the problem. Isn't this restricting binder2nd to only call
>> const methods on the passed object?
>>
>> Confused greetings.
>>
>> --
>> Manuel.
>>
>>     
> It seems that this same problem is explained here:
>
> http://www.progdoc.de/papers/adapter_binder/adapter_binder/adapter_binder.html
>
>
> .
>
>   
Yes, yes. I'm sorry for feeling the forum with short posts. I will try 
to collect more information to minimize the number of posts. However, 
after reading that document, I've reached the conclusion that without a 
binder2nd specialization for mem_fun_ref, this is not going to work 
(perhaps the gnu STL is providing such a specialization). What I've 
made, since the boost::bind is already used in some parts of that source 
code, is to migrate every bind2nd + mem_fun_ref combination to a 
boost::bind approach, resulting in the following patch:

-bash-3.00$ svn diff src/qpid/broker/SemanticState.cpp
Index: src/qpid/broker/SemanticState.cpp
===================================================================
--- src/qpid/broker/SemanticState.cpp   (revision 660842)
+++ src/qpid/broker/SemanticState.cpp   (working copy)
@@ -50,7 +50,6 @@
 namespace broker {
 
 using std::mem_fun_ref;
-using std::bind2nd;
 using boost::intrusive_ptr;
 using namespace qpid::broker;
 using namespace qpid::framing;
@@ -387,12 +386,12 @@
 {
     {
         ack_iterator start = cumulative ? unacked.begin() :
-            find_if(unacked.begin(), unacked.end(), 
bind2nd(mem_fun_ref(&DeliveryRecord::matchOrAfter), first));
+            find_if(unacked.begin(), unacked.end(), 
boost::bind(mem_fun_ref(&DeliveryRecord::matchOrAfter), _1, first));
         ack_iterator end = start;
        
         if (cumulative || first != last) {
             //need to find end (position it just after the last record 
in range)
-            end = find_if(start, unacked.end(), 
bind2nd(mem_fun_ref(&DeliveryRecord::after), last));
+            end = find_if(start, unacked.end(), 
boost::bind(mem_fun_ref(&DeliveryRecord::after), _1, last));
         } else if (start != unacked.end()) {
             //just acked single element (move end past it)
             ++end;
@@ -410,12 +409,12 @@
                 //unacked and record it against that transaction:
                 TxOp::shared_ptr txAck(new DtxAck(accumulatedAck, 
unacked));
                 //then remove that slice from the unacked record:
-                
unacked.remove_if(bind2nd(mem_fun_ref(&DeliveryRecord::coveredBy), 
&accumulatedAck));
+                
unacked.remove_if(boost::bind(mem_fun_ref(&DeliveryRecord::coveredBy), 
_1, &accumulatedAck));
                 accumulatedAck.clear();
                 dtxBuffer->enlist(txAck);   
             }
         } else {
-            for_each(start, end, 
bind2nd(mem_fun_ref(&DeliveryRecord::dequeue), 0));
+          for_each(start, end, 
boost::bind(mem_fun_ref(&DeliveryRecord::dequeue), _1, 
(TransactionContext*)0));
             unacked.erase(start, end);
         }
     }//end of lock scope for delivery lock (TODO this is ugly, make it 
prettier)
@@ -470,7 +469,7 @@
         unacked.clear();
         for_each(copy.rbegin(), copy.rend(), 
mem_fun_ref(&DeliveryRecord::requeue));
     }else{
-        for_each(unacked.begin(), unacked.end(), 
bind2nd(mem_fun_ref(&DeliveryRecord::redeliver), this));       
+        for_each(unacked.begin(), unacked.end(), 
boost::bind(mem_fun_ref(&DeliveryRecord::redeliver), _1, this));       
         //unconfirmed messages re redelivered and therefore have their
         //id adjusted, confirmed messages are not and so the ordering
         //w.r.t id is lost
@@ -605,7 +604,7 @@
 
 AckRange SemanticState::findRange(DeliveryId first, DeliveryId last)
 {   
-    ack_iterator start = find_if(unacked.begin(), unacked.end(), 
bind2nd(mem_fun_ref(&DeliveryRecord::matchOrAfter), first));
+    ack_iterator start = find_if(unacked.begin(), unacked.end(), 
boost::bind(mem_fun_ref(&DeliveryRecord::matchOrAfter), _1, first));
     ack_iterator end = start;
     
     if (start != unacked.end()) {
@@ -614,7 +613,7 @@
             ++end;
         } else {
             //need to find end (position it just after the last record 
in range)
-            end = find_if(start, unacked.end(), 
bind2nd(mem_fun_ref(&DeliveryRecord::after), last));
+            end = find_if(start, unacked.end(), 
boost::bind(mem_fun_ref(&DeliveryRecord::after), _1, last));
         }
     }
     return AckRange(start, end);
@@ -633,7 +632,7 @@
     //to release in reverse order to keep the original transfer order
     DeliveryRecords::reverse_iterator start(range.end);
     DeliveryRecords::reverse_iterator end(range.start);
-    for_each(start, end, bind2nd(mem_fun_ref(&DeliveryRecord::release), 
setRedelivered));
+    for_each(start, end, 
boost::bind(mem_fun_ref(&DeliveryRecord::release), _1, setRedelivered));
 }
 
 void SemanticState::reject(DeliveryId first, DeliveryId last)
@@ -681,7 +680,7 @@
 
         }
     } else {
-        for_each(range.start, range.end, 
bind2nd(mem_fun_ref(&DeliveryRecord::accept), 0));
+      for_each(range.start, range.end, 
boost::bind(mem_fun_ref(&DeliveryRecord::accept), _1, 
(TransactionContext*)0));
         unacked.remove_if(mem_fun_ref(&DeliveryRecord::isRedundant));
     }
 }


Any comment on these changes?

Regards.



Mime
View raw message