problems with boost bind and boost thread
Hi, I have problems with the attached code (test.cpp, extracted from the original class only with the relevant code). The member template constructor of CCycleThread takes an argument and passes this to boost bind. The binding is to a another member template method which is the thread function for boost thread: boost::thread(boost::bind(&CCycleThread::execute<T>,this,t) The template parameter type is deduced by the argument type passed by the user. If the type is an ordinary function the code works fine. If the argument itself is another boost bind object the compilation fails! I tested the following within the constructor: auto test = boost::bind(&CCycleThread::execute<T>,this,t) // -> ok test(); // -> compile error The call of the operator() of the bind object is the problem. Interestingly, if one binding is boost::bind and the other one is std::bind the code works. Any ideas what's the problem? How can I fix this? Using std and boost bind is more a hack than a real solution :/
Try:
m_thread.reset(new
boost::thread(boost::bind(&CCycleThread::execute<T>,this,boost::protect(t))));
The gist of the problem is that nested binds do not work the way you
expect. For an explanation, see:
http://www.boost.org/doc/libs/1_48_0/libs/bind/bind.html#nested_binds
-Gabe
On Thu, Mar 22, 2012 at 4:56 AM, Marco
Hi,
I have problems with the attached code (test.cpp, extracted from the original class only with the relevant code). The member template constructor of CCycleThread takes an argument and passes this to boost bind. The binding is to a another member template method which is the thread function for boost thread:
boost::thread(boost::bind(&CCycleThread::execute<T>,this,t)
The template parameter type is deduced by the argument type passed by the user.
If the type is an ordinary function the code works fine. If the argument itself is another boost bind object the compilation fails!
I tested the following within the constructor:
auto test = boost::bind(&CCycleThread::execute<T>,this,t) // -> ok test(); // -> compile error
The call of the operator() of the bind object is the problem.
Interestingly, if one binding is boost::bind and the other one is std::bind the code works. Any ideas what's the problem? How can I fix this? Using std and boost bind is more a hack than a real solution :/
_______________________________________________ Boost-users mailing list Boost-users@lists.boost.org http://lists.boost.org/mailman/listinfo.cgi/boost-users
I have problems with the attached code (test.cpp, extracted from the original class only with the relevant code). The member template constructor of CCycleThread takes an argument and passes this to boost bind. The binding is to a another member template method which is the thread function for boost thread:
boost::thread(boost::bind(&CCycleThread::execute<T>,this,t)
The template parameter type is deduced by the argument type passed by the user.
If the type is an ordinary function the code works fine. If the argument itself is another boost bind object the compilation fails!
, this, boost::protect(t)))); However, the problem is that now if a user passes a simple function
If the argument is a binder, you should wrap it with boost::protect
and specialize CCycleThread::execute accordingly:
m_thread.reset(new
boost::thread(boost::bind(&CCycleThread::execute
Hi, thanks for your hints (also to Gabriel Redner)! | I can't realise right now what type trait could be useful for this | purpose... I want co call a function or method in a separate thread periodically. Therefore my CCycleThread class starts the execute method as thread and calls the user function object in a loop. The user can pause, resume and finish the thread if he wishes. To separate the worker code from the threading code I build this wrapper around boost thread with pause and resume methods. class CCycleThread : boost::noncopyable { template<typename T> CCycleThread(T t) ... void pause() ... void resume() ... void finish() ... ... template<typename T> void execute(T t) { boost::unique_lockboost::mutex lock(m_mut,boost::defer_lock_t()); for(;;) { //check if the work should be paused or finished lock.lock(); while(!m_doWork) { //to do: inform user object about pause m_cond.wait(lock); } //to do: inform user object about resume if (m_finished) break; lock.unlock(); //do the work t(); } } }; And if the user passes a bind object than I have the binding of the binding.
I want co call a function or method in a separate thread periodically. Therefore my CCycleThread class starts the execute method as thread and calls the user function object in a loop. The user can pause, resume and finish the thread if he wishes. To separate the worker code from the threading code I build this wrapper around boost thread with pause and resume methods.
<...>
Yes, I understand why such a design can be uselful. What I said is
that I didn't realise how to separate binder/not-a-binder cases.
But after thinking a bit... actually, you can just define 2 function
templates in a straight-forward way:
// simple functor/function case
template<typename T>
CCycleThread(T t)
{
m_thread.reset(new
boost::thread(boost::bind(&CCycleThread::execute<T>, this, t)));
}
// binder case
template
, this, boost::protect(t)))); }
On 22/03/12 15:16, Igor R wrote:
I want co call a function or method in a separate thread periodically. Therefore my CCycleThread class starts the execute method as thread and calls the user function object in a loop. The user can pause, resume and finish the thread if he wishes. To separate the worker code from the threading code I build this wrapper around boost thread with pause and resume methods.
<...> Yes, I understand why such a design can be uselful. What I said is that I didn't realise how to separate binder/not-a-binder cases. But after thinking a bit... actually, you can just define 2 function templates in a straight-forward way:
// simple functor/function case template<typename T> CCycleThread(T t) { m_thread.reset(new boost::thread(boost::bind(&CCycleThread::execute<T>, this, t))); }
// binder case template
CCycleThread(boost::_bi::bind_t t) { m_thread.reset(new boost::thread(boost::bind(&CCycleThread::execute , this, boost::protect(t)))); }
Even simpler: just wrap the supplied function/binder in boost::function.
CCycleThread(boost::function
Yes, the boost function way was my workaround. But the nested binds are much more effectiv in calling the method than boost function.
participants (4)
-
Anthony Williams
-
Gabriel Redner
-
Igor R
-
Marco