[thread] test_lock* and test_move* failures on trunk

Hello, a number of platforms currently fail to compile these tests with an error message similar to the following: cxx: Error: ../boost/thread/pthread/thread.hpp, line 169: more than one instance of overloaded function "boost::bind" matches the argument list: (ambovlfun) function template "boost::bind<R,F,A1>(F, A1)" function template "boost::bind(R (T::*)(), A1)" The code in question reads: template <class F,class A1> thread(F f,A1 a1): thread_info(make_thread_info(boost::bind<void>(f,a1))) { start_thread(); } and it is used like this (in test_lock_concept.cpp): struct ... { void locking_thread() { ... } ... void operator()() { .... boost::thread t(&this_type::locking_thread,this); } }; Looking at the bind documentation, the syntax for using bind with pointers to members is either bind(&X::f, args) or bind<R>(mem_fn(&X::f), args) So there are three possible fixes: 1) make_thread_info(boost::bind(f,a1)) 2) make_thread_info(boost::bind<void>(mem_fn(f),a1)) 3) boost::thread t(mem_fn(&this_type::locking_thread),this); Every one of those makes the compile error go away. Option 1) might be the most flexible, 2) is probably too restrictive, and 3) is the least intrusive, as it only modifies the tests. Would the thread maintainer please decide on a fix and then commit it? Best regards, Markus

Markus Schöpflin:
Hello,
a number of platforms currently fail to compile these tests with an error message similar to the following:
cxx: Error: ../boost/thread/pthread/thread.hpp, line 169: more than one instance of overloaded function "boost::bind" matches the argument list: (ambovlfun) function template "boost::bind<R,F,A1>(F, A1)" function template "boost::bind(R (T::*)(), A1)"
The code in question reads:
template <class F,class A1> thread(F f,A1 a1): thread_info(make_thread_info(boost::bind<void>(f,a1))) { start_thread(); }
The best fix here is probably boost::bind( boost::type<void>(), f, a1 )
1) make_thread_info(boost::bind(f,a1))
This will fail when f is a function object without a result_type typedef.
2) make_thread_info(boost::bind<void>(mem_fn(f),a1))
This will fail when f is not a member pointer. It seems that these will be exposed by test_thread_launching. It only misses the cases "ordinary function with arguments" and "member pointer". The alternative syntax should work in all cases; can you please test it?

"Peter Dimov" <pdimov@pdimov.com> writes:
boost::bind( boost::type<void>(), f, a1 )
Never mind, this doesn't work for member pointers. Ugh.
It should work now (as of revision 45619).
Does bind<void>(&X::f,a1) work, or do I need the type<> parameter? Thanks, Anthony -- Anthony Williams | Just Software Solutions Ltd Custom Software Development | http://www.justsoftwaresolutions.co.uk Registered in England, Company Number 5478976. Registered Office: 15 Carrallack Mews, St Just, Cornwall, TR19 7UL

Peter Dimov wrote:
Markus Schöpflin:
Hello,
a number of platforms currently fail to compile these tests with an error message similar to the following:
cxx: Error: ../boost/thread/pthread/thread.hpp, line 169: more than one instance of overloaded function "boost::bind" matches the argument list: (ambovlfun) function template "boost::bind<R,F,A1>(F, A1)" function template "boost::bind(R (T::*)(), A1)"
The code in question reads:
template <class F,class A1> thread(F f,A1 a1): thread_info(make_thread_info(boost::bind<void>(f,a1))) { start_thread(); }
The best fix here is probably
boost::bind( boost::type<void>(), f, a1 )
This fails (CXX 7.1 on Tru64) with: cxx: Error: ../../../boost/mem_fn.hpp, line 342: a pointer to a bound function may only be used to call the function (boundfuncalled) detected during: instantiation of "R &boost::_mfi::dm<R, T>::operator()(T *) const followed by a few 100 lines of error context.
1) make_thread_info(boost::bind(f,a1))
This will fail when f is a function object without a result_type typedef.
2) make_thread_info(boost::bind<void>(mem_fn(f),a1))
This will fail when f is not a member pointer.
It seems that these will be exposed by test_thread_launching. It only misses the cases "ordinary function with arguments" and "member pointer".
The alternative syntax should work in all cases; can you please test it?
See above for results. Do you consider it to be a compiler problem? Hmm, maybe modifying the tests to use boost::thread t(mem_fn(&this_type::locking_thread),this) would be the easiest way out? Markus

Peter Dimov wrote:
Markus Schöpflin:
Hmm, maybe modifying the tests to use
boost::thread t(mem_fn(&this_type::locking_thread),this)
would be the easiest way out?
We do want the straightforward syntax thread( &this_type::locking_thread, this ) to work in user code.
Yes, of course that would be nice. But is it possible?

Markus Schöpflin <markus.schoepflin@comsoft.de> writes:
a number of platforms currently fail to compile these tests with an error message similar to the following:
cxx: Error: ../boost/thread/pthread/thread.hpp, line 169: more than one instance of overloaded function "boost::bind" matches the argument list: (ambovlfun) function template "boost::bind<R,F,A1>(F, A1)" function template "boost::bind(R (T::*)(), A1)"
The code in question reads:
template <class F,class A1> thread(F f,A1 a1): thread_info(make_thread_info(boost::bind<void>(f,a1))) { start_thread(); } Would the thread maintainer please decide on a fix and then commit it?
Could you try adding the following overload of the thread constructor to boost/thread/pthread/thread.hpp template <class T,class R,class P1,class A1> thread(R (T::*f)(P1),A1 a1): thread_info(make_thread_info(boost::bind<void>(boost::mem_fn(f),a1))) { start_thread(); } If that makes the problem go away, I'll commit the change. Anthony -- Anthony Williams | Just Software Solutions Ltd Custom Software Development | http://www.justsoftwaresolutions.co.uk Registered in England, Company Number 5478976. Registered Office: 15 Carrallack Mews, St Just, Cornwall, TR19 7UL

Anthony Williams wrote:
Could you try adding the following overload of the thread constructor to boost/thread/pthread/thread.hpp
template <class T,class R,class P1,class A1> thread(R (T::*f)(P1),A1 a1): thread_info(make_thread_info(boost::bind<void>(boost::mem_fn(f),a1))) { start_thread(); }
If that makes the problem go away, I'll commit the change.
I tried, but the compiler prefers the other constructor when resolving the overload, so the error persists. Markus

Markus Schöpflin:
Anthony Williams wrote:
Could you try adding the following overload of the thread constructor to boost/thread/pthread/thread.hpp
template <class T,class R,class P1,class A1> thread(R (T::*f)(P1),A1 a1):
thread_info(make_thread_info(boost::bind<void>(boost::mem_fn(f),a1))) { start_thread(); }
If that makes the problem go away, I'll commit the change.
I tried, but the compiler prefers the other constructor when resolving the overload, so the error persists.
Try template <class T, class R, class A1> thread(R (T::*f)(),A1 a1): without the P1. This would only work for no-argument non-const member functions though. More overloads are needed to cover all cases. I'll think about fixing that somehow on the bind side. A more systematic thread::thread test that covers all possibilities would be nice to have.

Peter Dimov wrote:
Try
template <class T, class R, class A1> thread(R (T::*f)(),A1 a1):
without the P1. This would only work for no-argument non-const member functions though. More overloads are needed to cover all cases. I'll think about fixing that somehow on the bind side. A more systematic thread::thread test that covers all possibilities would be nice to have.
In the mean while I already tried template <class T,class A1> thread(void (T::*f)(),A1 a1): which worked, so I think your suggestion will work too. Markus

"Peter Dimov" <pdimov@pdimov.com> writes:
Markus Schöpflin:
Anthony Williams wrote:
Could you try adding the following overload of the thread constructor to boost/thread/pthread/thread.hpp
template <class T,class R,class P1,class A1> thread(R (T::*f)(P1),A1 a1):
thread_info(make_thread_info(boost::bind<void>(boost::mem_fn(f),a1))) { start_thread(); }
If that makes the problem go away, I'll commit the change.
I tried, but the compiler prefers the other constructor when resolving the overload, so the error persists.
Try
template <class T, class R, class A1> thread(R (T::*f)(),A1 a1):
without the P1.
Oops. I was too quick off the mark, and forgot that the first argument was the "this" pointer.
This would only work for no-argument non-const member functions though. More overloads are needed to cover all cases. I'll think about fixing that somehow on the bind side.
Shall I hold off committing a fix to boost::thread for now, then?
A more systematic thread::thread test that covers all possibilities would be nice to have.
I've updates test_thread_launching to cover more options Anthony -- Anthony Williams | Just Software Solutions Ltd Custom Software Development | http://www.justsoftwaresolutions.co.uk Registered in England, Company Number 5478976. Registered Office: 15 Carrallack Mews, St Just, Cornwall, TR19 7UL

Anthony Williams:
Shall I hold off committing a fix to boost::thread for now, then?
I've taken the liberty of fixing it to use type<void>(), extending it to 9 arguments and adding a member function test. Please take a look at revision 45621; I hope I didn't do anything wrong. We'll probably want to add a normal function test along the same lines, and possibly use variadic templates when available. As a note, it seems that the two thread classes (win32, pthread) need to be refactored in some way since now they can desync. For example, the win32 thread uses rvalue references, and the pthread one does not.

"Peter Dimov" <pdimov@pdimov.com> writes:
Anthony Williams:
Shall I hold off committing a fix to boost::thread for now, then?
I've taken the liberty of fixing it to use type<void>(), extending it to 9 arguments and adding a member function test. Please take a look at revision 45621; I hope I didn't do anything wrong. We'll probably want to add a normal function test along the same lines, and possibly use variadic templates when available.
Thank you. Much appreciated.
As a note, it seems that the two thread classes (win32, pthread) need to be refactored in some way since now they can desync. For example, the win32 thread uses rvalue references, and the pthread one does not.
Yes. I think that the implementations are more similar than they are different. The rvalue reference stuff is a work in progress. Anthony -- Anthony Williams | Just Software Solutions Ltd Custom Software Development | http://www.justsoftwaresolutions.co.uk Registered in England, Company Number 5478976. Registered Office: 15 Carrallack Mews, St Just, Cornwall, TR19 7UL
participants (3)
-
Anthony Williams
-
Markus Schöpflin
-
Peter Dimov