[thread_pool] Dependencies between tasks

Hi, the tread_pool pattern is very useful to improve parallelism. But sometimes we need to constraint this parallelism, for example when several task are related to the same 'instance' it could be safer to sequence them. Is there a mechanism that allows to do thinks like that on the thread_pool library? Best, Vicente

sequencing the access to the instance would be equivalent to chaining the tasks (== chained tasks are executed after each other -> as a sequence). take a look at thread_pool at the vault http://www.boostpro.com/vault/index.php?action=downloadfile&filename=boost-threadpool.2.tar.gz&directory=Concurrent%20Programming&. Oliver

----- Original Message ----- From: "Kowalke Oliver (QD IT PA SI)" <Oliver.Kowalke@qimonda.com> To: <boost@lists.boost.org> Sent: Friday, September 05, 2008 8:46 AM Subject: Re: [boost] [thread_pool] Dependencies between tasks
Do you mean that each time the user wants to sequence tasks she/he needs * chain the task to the stored one * store the last task I had already recovered your compressed file as other post let know. Please could you point me where the chaining task is described? Thanks, Vicente

Am Samstag, 6. September 2008 06:40:03 schrieb vicente.botet:
I don't know what you mean with sore a task. signature of chained_submit: template< typename Act, typename T > task< typename result_of< Act() >::type > chained_submit( Act const& act, task< T > & t); The function object act which should be passed to the thread pool is chained to the task t. This means - the function object act will be executed by I worker thread if the task t was finished. struct A { void f( std::string const& str) { printf("A::f(): %s\n", str.c_str() ); } }; struct B { void g() { printf("B::g()\n"); } }; A a; B b; tp::pool< tp::fixed, tp::unbounded_channel< tp::fifo > > pool( tp::max_poolsize( 5) ); tp::task< void > t1( pool.submit( boost::bind( & A::f, a, "abc", 2) ) ); tp::task< void > t2( pool.chained_submit( boost::bind( & A::f, a, "efg", 1), t1) ); tp::task< void > t3( pool.chained_submit( boost::bind( & A::f, a, "hij", 0), t2) ); pool.submit( boost::bind( & B::g, b) ); t3.get_future().wait();
I had already recovered your compressed file as other post let know. Please could you point me where the chaining task is described?
example_chained_submit and in the docu chapter 'Submiting Tasks'
Thanks, Vicente
Oliver

----- Original Message ----- From: <k-oli@gmx.de> To: <boost@lists.boost.org> Sent: Saturday, September 06, 2008 8:39 AM Subject: Re: [boost] [thread_pool] Dependencies between tasks
Well, in order to chain a task a need to have a reference to the task. This is what I meant by store a task.
OK, this allows us to chain tasks. Is this function thread_safe?
This works well as soon as we have a reference to the task t1 when we submit the task t2, and t2 when we submit the task t3. The storage of the last_task submited to the pool for a given instance is needed when the code is not linear but cyclic and the problem appears when these tasks have different types. Suppose that the function called return different types, std::string and std::size. class A { std::string f( ) { return "***********"; } std::size g( ) { return 5; } }; A a, b; void h( ) { // do a expensive task } Image also that a function f will be called cyclically with values that depends on the user input while () { // get an int from cin in variable v f(v); } This function will depending onthe parameter submit different actions, but no action can be done in parallel for the same instance void f(int i) { switch (i) { case 1: tp::task<std::string> t1( pool.chained_submit(boost::bind(& A::f,a), last_task)); last_task = t1; // forward t1to other program logic needing the result of a.f() break; case 2: tp::task<std::size> t2( pool.chained_submit(boost::bind(& A::g,a), last_task)); last_task = t2; // forward t2 to other program logic needing the result of a.g() break; case 3: pool.submit(h); break; // other cases ... } } How last_task can be declared and initialized? As a task can be constructed only by submiting a function to a pool we can submit a function that do nothing. void do_nothing( ) { } tp::task<???> last_task(pool.submit(do_nothing)); What would be the type of last_task that provides the following functions: tp::task<???>(tp::task<void>); template<typename Act, typename T> tp::task< typename result_of< Act() >::type > chained_submit( Act const& act,tp::task<???> & t); tp::task<???>& operator=(tp::task<std::size>); tp::task<???>& operator=(tp::task<std::string>); The first function is matched by void. As chained_submit do not use at all the value stored on the future of the task, a void task coul be enough also, but we need a means to copy tp::task<T> on a tp::task<void>. I think that the future library allows already something like that, i.e. a future<void> can be used to wait for a future<T>. Do you think that this void specialization for task<void> can be added to your library? Another idea, why not define the chained_submit with a future instead of a task as parameter?
Sorry, I was seen an older documentation of the threadpool library. I see it now. Vicente

Am Samstag, 6. September 2008 15:02:28 schrieb vicente.botet:
Well, in order to chain a task a need to have a reference to the task. This is what I meant by store a task.
ok
OK, this allows us to chain tasks. Is this function thread_safe?
yes
This works well as soon as we have a reference to the task t1 when we submit the task t2, and t2 when we submit the task t3.
you need at least one task becuase you have to tell the pool after which action/task completion the new one should be executed/chained to. Without how should the pool know to which task you refering to.
no - the retunr type doesn't matter.
I would not do this because a task referes to a specific action submitted to the pool (remeber task interruption etc.). I suggest tot use the future instead.
Because submit functions from the pool return a task object thatswhy task objects are used as parameters. But you can use the future<T>::add_calback() function too. Oliver

----- Original Message ----- From: <k-oli@gmx.de> To: <boost@lists.boost.org> Sent: Saturday, September 06, 2008 8:42 PM Subject: Re: [boost] [thread_pool] Dependencies between tasks
I've not said at any moment that we don't need a task reference.
For what the return type doesn't matter?
I don't see the relation with task interruption, could you elaborate more on that? Which use case have you in mind?
I suggest tot use the future instead.
Do you mean that it is up to the user to chain the tasks using future<T>::add_calback()?
IMHO, this is not a deep rational. If all what is needed to chain a task is a future why not provide this interface? If you ADD another prototype for chained_submit taking as boost::future<T>& f instead of a tp::task<T> & t template<typename Act, typename T> tp::task< typename result_of< Act() >::type > chained_submit( Act const& act,boost::future<T> &f ) { shared_lock< shared_mutex > lk( mtx_state_); if ( terminated_() ) throw task_rejected("pool ist terminated"); if ( terminateing_() ) throw task_rejected("pool ist terminateing"); typedef typename result_of< Act() >::type R; detail::interrupter intr; promise< R > prom; channel_item itm( future_wrapper< R >( act, prom), intr); fut.add_callback( bind( ( channel_iterator ( channel::*)( channel_item const&) ) & channel::put, ref( channel_), itm) ); return task< R >( prom, intr); } The implementation of the current chained_submit will just forward the call passing the future of the task. task< typename result_of< Act() >::type > chained_submit( Act const& act, task< T > & tsk) { return chained_submit(act, tsk.get_future());}
But you can use the future<T>::add_calback() function too.
I'm not sure if you mean that my use case (example) can be implemented with chained_submit or not? If it can be implemented, as the use case (example) is quite simple, please could you complete the code example to show how you will implement it? Regards, Vicente

Hello Vicente, I've uploaded a new version of threadpool wich incorporates your suggestions regarding to chained_submit. http://www.boostpro.com/vault/index.php?action=downloadfile&filename=boost-threadpool.4.tar.gz&directory=Concurrent%20Programming& regards, Oliver Am Samstag, 6. September 2008 15:02:28 schrieb vicente.botet:

----- Original Message ----- From: <k-oli@gmx.de> To: <boost@lists.boost.org> Sent: Wednesday, September 10, 2008 12:20 PM Subject: Re: [boost] [thread_pool] Dependencies between tasks
Hello Olivier, I've take a look. If I'm not wrong you have added the chained_submit with futures, isn't it? Thanks a lot ______________________ Vicente Juan Botet Escribá
participants (4)
-
Giovanni Piero Deretta
-
k-oli@gmx.de
-
Kowalke Oliver (QD IT PA SI)
-
vicente.botet