
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: Saturday, September 06, 2008 8:39 AM Subject: Re: [boost] [thread_pool] Dependencies between tasks
Am Samstag, 6. September 2008 06:40:03 schrieb vicente.botet:
----- 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
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=b oos t-threadpool.2.tar.gz&directory=Concurrent%20Programming&.
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 don't know what you mean with store a task.
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.
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.
OK, this allows us to chain tasks. Is this function thread_safe?
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();
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?
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'
Sorry, I was seen an older documentation of the threadpool library. I see it now.
Vicente
_______________________________________________ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost