> >> async_result<double> res; > >> thread t(bind(res.call(), a, b, c)); > >> // do something else > >> d = res.value(); // Explicitly waits for the thread to return a > >> value? > > > > This does the same, indeed. Starting a thread this way is just a little > > more complex (and -- in my view -- less obvious to read) than writing > > thread t = spawn(foo)(a,b,c); > > Not sure I agree about "less obvious to read". If your syntax had been > thread t = spawn(foo, a, b, c); > I think you'd have a bit more of an argument here. And I certainly could > fold the binding directly into boost::thread so that my syntax would > become: > > thread t(res.call(), a, b, c); > > I could even eliminate the ".call()" syntax with some implicit > conversions, but I dislike that for the obvious reasons. I specifically > chose not to include syntactic binding in boost::thread a long time ago, > because I prefer the explicit seperation of concerns. So, where you think > my syntax is "less obvious to read", I think it's "more explicit".
If you do all this, then you'll probably almost arrive at the code I posted :-) Still, keeping the analogy to the usual call foo(a,b,c), I prefer the arguments to foo in a separate pair of parentheses. However, there is another point that I guess will make your approach very hard: assume void foo(int, double, char); and a potential constructor for your thread class template <typename A, typename B, typename C> thread (void (*p)(A,B,C), A, B, C); Then you can write foo(1,1,1) and arguments will be converted automatically. However, you cannot write thread t(foo, 1, 1, 1); since template parameters must be exact matches. There really is no other way than to first get at the argument types in a first step, and pass the arguments in a second step. You _need_ two sets of parentheses to get the conversions. > > Actually it does duplicate the work, but not because I am stubborn. We > > have an existing implementation for a couple of years, and the present > > version just evolved from this. However, there's a second point: when > > starting threads, you have a relatively clear picture as to how long > > certain objects are needed, and one can avoid several copying steps if > > one does some things by hand. It's short anyway, tuple type and tie > > function are your friend here. > > I'm not sure how you avoid copies here. Since you have control over lifetimes of objects, you can pass references instead of copies at various places. > > t->kill (); > > t->suspend (); > > Someone sees that there's a function yield() but doesn't have the time > > to read the documentation, what will he assume what yield() does? > > How does "someone see that there's a function yield()" with out also > seeing that it's static? No need to read documentation for that, as it's > an explicit part of the functions signature. Seeing it used in someone else's code? Just not being careful when reading the signature? I think it's the same argument as with void* : if applied correctly it's ok, but in general it's considered harmful. W. ------------------------------------------------------------------------- Wolfgang Bangerth email: [EMAIL PROTECTED] www: http://www.ticam.utexas.edu/~bangerth/ _______________________________________________ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost