Boost.Future & review of C++0x accepted libraries implementations

Hi, The Anthony Future + Packaged task proposals have been adopted by the C++ Standard. Is there a sense to review both Futures libraries together? Can we accept the Braddock library if it not conforms to the standard? As the interface and the design rationale for libraries already adopted by the C++ Standard such Chrono seem to be out of the scope of a review, which is the contents expected for such libraries to be adopted? Do we need a different review process? BTW, the threadpool library uses Braddock Future library. Thanks, Vicente

Am Donnerstag, 20. November 2008 15:37:10 schrieb vicente.botet:
Hi,
The Anthony Future + Packaged task proposals have been adopted by the C++ Standard.
good you post a link to this information, please.
Is there a sense to review both Futures libraries together? Can we accept the Braddock library if it not conforms to the standard?
That's the question - Braddocks Future library has more features (callback functionality).
As the interface and the design rationale for libraries already adopted by the C++ Standard such Chrono seem to be out of the scope of a review, which is the contents expected for such libraries to be adopted? Do we need a different review process?
BTW, the threadpool library uses Braddock Future library.
I can easily exchange the future implementation - chaining tasks and lazy task evaluation will not be available with the lib from Anthony. reagards, Oliver

k-oli@gmx.de writes:
Am Donnerstag, 20. November 2008 15:37:10 schrieb vicente.botet:
Hi,
The Anthony Future + Packaged task proposals have been adopted by the C++ Standard.
good you post a link to this information, please.
It was accepted at the October 2008 C++ standards meeting. I wrote a list of the concurrency related papers here: http://www.justsoftwaresolutions.co.uk/cplusplus/cplusplus-standards-committ... The latest C++0x working draft (which includes those papers, and which is the "feature complete" committee draft out for voting at the moment) is at: http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2008/n2798.pdf Anthony -- Anthony Williams Author of C++ Concurrency in Action | http://www.manning.com/williams Custom Software Development | http://www.justsoftwaresolutions.co.uk Just Software Solutions Ltd, Registered in England, Company Number 5478976. Registered Office: 15 Carrallack Mews, St Just, Cornwall, TR19 7UL, UK

Am Donnerstag, 20. November 2008 18:19:12 schrieb Anthony Williams:
k-oli@gmx.de writes: The latest C++0x working draft (which includes those papers, and which is the "feature complete" committee draft out for voting at the moment) is at:
How has the jss::packaged_task to be used with boost::thread? X x; jss::packaged_task< std::string > tsk( boost::bind( & X::execute, x) ); jss::shared_future< std::string > f( tsk.get_future() ); boost::thread t( boost::bind( & jss::packaged_task< std::string >::operator(), tsk) ); t.join(); std::cout << f.get() << std::endl; Does not compile because packaged_task is noncopyable. In the C++0x working draft std::move( tsk) was used - but how to do it with the current boost release? Oliver

k-oli@gmx.de writes:
Am Donnerstag, 20. November 2008 18:19:12 schrieb Anthony Williams:
k-oli@gmx.de writes: The latest C++0x working draft (which includes those papers, and which is the "feature complete" committee draft out for voting at the moment) is at:
How has the jss::packaged_task to be used with boost::thread?
X x; jss::packaged_task< std::string > tsk( boost::bind( & X::execute, x) ); jss::shared_future< std::string > f( tsk.get_future() ); boost::thread t( boost::bind( & jss::packaged_task< std::string >::operator(), tsk) ); t.join(); std::cout << f.get() << std::endl;
Does not compile because packaged_task is noncopyable. In the C++0x working draft std::move( tsk) was used - but how to do it with the current boost release?
boost::thread t(boost::move(tsk)); Anthony -- Anthony Williams Author of C++ Concurrency in Action | http://www.manning.com/williams Custom Software Development | http://www.justsoftwaresolutions.co.uk Just Software Solutions Ltd, Registered in England, Company Number 5478976. Registered Office: 15 Carrallack Mews, St Just, Cornwall, TR19 7UL, UK

----- Original Message ----- From: "Anthony Williams" <anthony.ajw@gmail.com> To: <boost@lists.boost.org> Sent: Thursday, November 20, 2008 10:28 PM Subject: Re: [boost] Boost.Future & review of C++0x accepted librariesimplementations
k-oli@gmx.de writes:
Am Donnerstag, 20. November 2008 18:19:12 schrieb Anthony Williams:
k-oli@gmx.de writes:
X x; jss::packaged_task< std::string > tsk( boost::bind( & X::execute, x) ); jss::shared_future< std::string > f( tsk.get_future() ); boost::thread t( boost::bind( & jss::packaged_task< std::string >::operator(), tsk) ); t.join(); std::cout << f.get() << std::endl;
Does not compile because packaged_task is noncopyable. In the C++0x working draft std::move( tsk) was used - but how to do it with the current boost release?
boost::thread t(boost::move(tsk));
Hi, Now that we have futures and packaged_task we are not too far from the Kevin proposal so the final use can write joiner<std::string> j = threader::launch_in_thread(bind( & X::execute, x)); std::cout << j.get() << std::endl; instead of packaged_task< std::string > tsk( bind( & X::execute, x) ); shared_future< std::string > f( tsk.get_future() ); thread t(move(tsk)); t.join(); std::cout << f.get() << std::endl; Note. This code has of course not compiled. class threader { public: template <typename Nullary> joiner<result_of<Nullary> > launch_in_thread(Nullary f) { return joiner<result_type>(f); } }; template <typename ResultType> class joiner { struct data { shared_future< ResultType > fut_; thread th_; template <typename Nullary> data() packaged_task<ResultType> tsk(f); fut_ = tsk.get_future(); th_ = boost::move(tsk)); } shared_ptr<data> data_; public: template <typename Nullary> // requires result_of<Nullary>::type is equal to ResultType joiner(Nullary f) : data_(new data(f) {} // move semantics from a shared_ptr // .... void join() {th_.join();} ResultType get() {th_.join(); return fut_.get();} }; Best, Vicente

Am Donnerstag, 20. November 2008 22:28:21 schrieb Anthony Williams:
k-oli@gmx.de writes:
Am Donnerstag, 20. November 2008 18:19:12 schrieb Anthony Williams:
k-oli@gmx.de writes: The latest C++0x working draft (which includes those papers, and which is the "feature complete" committee draft out for voting at the moment) is at:
How has the jss::packaged_task to be used with boost::thread?
X x; jss::packaged_task< std::string > tsk( boost::bind( & X::execute, x) ); jss::shared_future< std::string > f( tsk.get_future() ); boost::thread t( boost::bind( & jss::packaged_task< std::string >::operator(), tsk) ); t.join(); std::cout << f.get() << std::endl;
Does not compile because packaged_task is noncopyable. In the C++0x working draft std::move( tsk) was used - but how to do it with the current boost release?
boost::thread t(boost::move(tsk));
Doesn't compile (gcc-4.3): conversion from 'jss::packaged_task<std::basic_string<char, std::char_traits<char>, std::allocator<char> > >' to non-scalar type 'boost::detail::thread_move_t<boost::thread>' requested Any ideas? Oliver

----- Original Message ----- From: <k-oli@gmx.de> To: <boost@lists.boost.org> Sent: Friday, November 21, 2008 6:05 AM Subject: Re: [boost] Boost.Future & review of C++0x accepted librariesimplementations
Am Donnerstag, 20. November 2008 22:28:21 schrieb Anthony Williams:
k-oli@gmx.de writes:
Am Donnerstag, 20. November 2008 18:19:12 schrieb Anthony Williams:
k-oli@gmx.de writes: The latest C++0x working draft (which includes those papers, and which is the "feature complete" committee draft out for voting at the moment) is at:
How has the jss::packaged_task to be used with boost::thread?
X x; jss::packaged_task< std::string > tsk( boost::bind( & X::execute, x) ); jss::shared_future< std::string > f( tsk.get_future() ); boost::thread t( boost::bind( & jss::packaged_task< std::string >::operator(), tsk) ); t.join(); std::cout << f.get() << std::endl;
Does not compile because packaged_task is noncopyable. In the C++0x working draft std::move( tsk) was used - but how to do it with the current boost release?
boost::thread t(boost::move(tsk));
Doesn't compile (gcc-4.3):
conversion from 'jss::packaged_task<std::basic_string<char, std::char_traits<char>, std::allocator<char> > >' to non-scalar type 'boost::detail::thread_move_t<boost::thread>' requested
Any ideas?
Try to decompose the probleme detail::thread_move_t< jss::packaged_task< std::string > > mtsk(tsk) boost::thread t(mtsk); and see what is wrong. HTH, Vicente

k-oli@gmx.de writes:
Am Donnerstag, 20. November 2008 22:28:21 schrieb Anthony Williams:
k-oli@gmx.de writes:
Am Donnerstag, 20. November 2008 18:19:12 schrieb Anthony Williams:
k-oli@gmx.de writes: The latest C++0x working draft (which includes those papers, and which is the "feature complete" committee draft out for voting at the moment) is at:
How has the jss::packaged_task to be used with boost::thread?
X x; jss::packaged_task< std::string > tsk( boost::bind( & X::execute, x) ); jss::shared_future< std::string > f( tsk.get_future() ); boost::thread t( boost::bind( & jss::packaged_task< std::string >::operator(), tsk) ); t.join(); std::cout << f.get() << std::endl;
Does not compile because packaged_task is noncopyable. In the C++0x working draft std::move( tsk) was used - but how to do it with the current boost release?
boost::thread t(boost::move(tsk));
Doesn't compile (gcc-4.3):
conversion from 'jss::packaged_task<std::basic_string<char, std::char_traits<char>, std::allocator<char> > >' to non-scalar type 'boost::detail::thread_move_t<boost::thread>' requested
Any ideas?
That's not the error message I get :-) It's supposed to be taken care of with the move overload in boost/thread/detail/move.hpp that binds to any T convertible to thread_move_t<T> (which packaged_task is). Apparently that's broken. To make it work, just provide an overload for packaged_task namespace boost { template<typename T> detail::thread_move_t<jss::packaged_task<T> > move(jss::packaged_task<T>& t) { return detail::thread_move_t<jss::packaged_task<T> >(t); } } Anthony -- Anthony Williams Author of C++ Concurrency in Action | http://www.manning.com/williams Custom Software Development | http://www.justsoftwaresolutions.co.uk Just Software Solutions Ltd, Registered in England, Company Number 5478976. Registered Office: 15 Carrallack Mews, St Just, Cornwall, TR19 7UL, UK

Anthony Williams wrote: [...]
http://www.justsoftwaresolutions.co.uk/cplusplus/cplusplus-standards-committ...
Thanks for the summary. Starting with basics, I've read http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2008/n2748.html (N2748: Strong Compare and Exchange) and I think that n2748's compare_exchange_strong() is very under-specified regarding intended x86's CAS incarnation: E.g. (pseudo code, sorry for eventual bugs) do { loaded = load_reserved(); if (loaded != expected) { expected = loaded; return false; } } while (!store_conditional(desired)); return true; vs. do { loaded = load_reserved(); stored = (result = (loaded == expected)) ? desired : loaded; } while (!store_conditional(stored)); return expected = loaded, result; The first one may result in 'dangling' reservations (which is OK) and doesn't attempt to perform a store on comparison failure. The second one is most closely matching x86's CAS (it always performs a store, even in failure case). The first one provides better performance in failure case but can not be used as a 'fake' RMW to achieve 'write atomicity' visibility on platforms without write atomicity (like Power). See http://www.decadentplace.org.uk/pipermail/cpp-threads/2005-September/000610.... (But note that in the meantime (post 2005 docs) Intel and AMD both seem to have declared existence of write atomicity on their platforms. That is not the case for Power, AFAIK.) Also, just a thought: Given all that 'weak' and 'strong' CAS story, why not standardize something along the lines of (impl. for CAS/non-native LR(LL)-SC platforms) load_reserved_weak() { return reserved = load(); // static thread-local variable } store_conditional_weak(value) { return compare_exchange_weak(reserved, value); } ? regards, alexander.

Alexander Terekhov <terekhov@web.de> writes:
Anthony Williams wrote: [...]
http://www.justsoftwaresolutions.co.uk/cplusplus/cplusplus-standards-committ...
Thanks for the summary.
Starting with basics, I've read
http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2008/n2748.html (N2748: Strong Compare and Exchange)
and I think that n2748's compare_exchange_strong() is very under-specified regarding intended x86's CAS incarnation:
E.g. (pseudo code, sorry for eventual bugs)
do { loaded = load_reserved(); if (loaded != expected) { expected = loaded; return false; } } while (!store_conditional(desired)); return true;
vs.
do { loaded = load_reserved(); stored = (result = (loaded == expected)) ? desired : loaded; } while (!store_conditional(stored)); return expected = loaded, result;
The first one may result in 'dangling' reservations (which is OK) and doesn't attempt to perform a store on comparison failure.
The second one is most closely matching x86's CAS (it always performs a store, even in failure case).
The first one provides better performance in failure case but can not be used as a 'fake' RMW to achieve 'write atomicity' visibility on platforms without write atomicity (like Power).
See
http://www.decadentplace.org.uk/pipermail/cpp-threads/2005-September/000610....
(But note that in the meantime (post 2005 docs) Intel and AMD both seem to have declared existence of write atomicity on their platforms. That is not the case for Power, AFAIK.)
Thanks. I had been concerned about the ordering guarantees on failure, but hadn't got round to raising an issue. I'll do so today.
Also, just a thought:
Given all that 'weak' and 'strong' CAS story, why not standardize something along the lines of
(impl. for CAS/non-native LR(LL)-SC platforms)
load_reserved_weak() { return reserved = load(); // static thread-local variable }
store_conditional_weak(value) { return compare_exchange_weak(reserved, value); }
Are you suggesting these be added to the atomic types? Interesting. I'll raise that separately and see what people say. Anthony -- Anthony Williams Author of C++ Concurrency in Action | http://www.manning.com/williams Custom Software Development | http://www.justsoftwaresolutions.co.uk Just Software Solutions Ltd, Registered in England, Company Number 5478976. Registered Office: 15 Carrallack Mews, St Just, Cornwall, TR19 7UL, UK

Anthony Williams wrote: [...]
Given all that 'weak' and 'strong' CAS story, why not standardize something along the lines of
(impl. for CAS/non-native LR(LL)-SC platforms)
load_reserved_weak() { return reserved = load(); // static thread-local variable }
store_conditional_weak(value) { return compare_exchange_weak(reserved, value); }
Are you suggesting these be added to the atomic types?
That would help regarding portability of LR-SC based code that doesn't need ABA*** safety of load_reserved_strong/store_conditional_strong. That would also put pressure on vendors to introduce native LR-SC and on programmers to use LR-SC which is much better primitive than CAS. ***) http://en.wikipedia.org/wiki/ABA_problem regards, alexander.

Alexander Terekhov <terekhov@web.de> writes:
Anthony Williams wrote: [...]
Given all that 'weak' and 'strong' CAS story, why not standardize something along the lines of
(impl. for CAS/non-native LR(LL)-SC platforms)
load_reserved_weak() { return reserved = load(); // static thread-local variable }
store_conditional_weak(value) { return compare_exchange_weak(reserved, value); }
Are you suggesting these be added to the atomic types?
That would help regarding portability of LR-SC based code that doesn't need ABA*** safety of load_reserved_strong/store_conditional_strong. That would also put pressure on vendors to introduce native LR-SC and on programmers to use LR-SC which is much better primitive than CAS.
In raised this on the committee list, and there didn't seem any support for this idea. LR/SC has to be used at a low level to use the native instructions, and is therefore not sufficiently useful to make it worthwhile adding. I won't pursue it further. If you feel strongly about this, I suggest you try and get your National Body to add a comment on the CD asking for this. Anthony -- Anthony Williams Author of C++ Concurrency in Action | http://www.manning.com/williams Custom Software Development | http://www.justsoftwaresolutions.co.uk Just Software Solutions Ltd, Registered in England, Company Number 5478976. Registered Office: 15 Carrallack Mews, St Just, Cornwall, TR19 7UL, UK

Alexander Terekhov <terekhov@web.de> writes:
Anthony Williams wrote: [...]
http://www.justsoftwaresolutions.co.uk/cplusplus/cplusplus-standards-committ...
Thanks for the summary.
Starting with basics, I've read
http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2008/n2748.html (N2748: Strong Compare and Exchange)
and I think that n2748's compare_exchange_strong() is very under-specified regarding intended x86's CAS incarnation:
E.g. (pseudo code, sorry for eventual bugs)
do { loaded = load_reserved(); if (loaded != expected) { expected = loaded; return false; } } while (!store_conditional(desired)); return true;
vs.
do { loaded = load_reserved(); stored = (result = (loaded == expected)) ? desired : loaded; } while (!store_conditional(stored)); return expected = loaded, result;
The first one may result in 'dangling' reservations (which is OK) and doesn't attempt to perform a store on comparison failure.
The second one is most closely matching x86's CAS (it always performs a store, even in failure case).
The first one provides better performance in failure case but can not be used as a 'fake' RMW to achieve 'write atomicity' visibility on platforms without write atomicity (like Power).
In writing this up for the committee, it occurred to me that if you specify memory_order_release for failure then that may require the second implementation in order to get the required store. Also, the compare_exchange functions are specified as being "atomic RMW operations", so that implies a store to me. Anthony -- Anthony Williams Author of C++ Concurrency in Action | http://www.manning.com/williams Custom Software Development | http://www.justsoftwaresolutions.co.uk Just Software Solutions Ltd, Registered in England, Company Number 5478976. Registered Office: 15 Carrallack Mews, St Just, Cornwall, TR19 7UL, UK

Hi Olivier, ----- Original Message ----- From: <k-oli@gmx.de> To: <boost@lists.boost.org> Sent: Thursday, November 20, 2008 5:51 PM Subject: Re: [boost] Boost.Future & review of C++0x accepted librariesimplementations
Am Donnerstag, 20. November 2008 15:37:10 schrieb vicente.botet:
Hi,
The Anthony Future + Packaged task proposals have been adopted by the C++ Standard.
good you post a link to this information, please.
Done by Anthony.
Is there a sense to review both Futures libraries together? Can we accept the Braddock library if it not conforms to the standard?
That's the question - Braddocks Future library has more features (callback functionality).
Yes it have more but also less.
BTW, the threadpool library uses Braddock Future library.
I can easily exchange the future implementation - chaining tasks and lazy task evaluation will not be available with the lib from Anthony.
As I was not aware of that until yesterday, I though that every body in Boost should know that posting a specific post. My post was more to signal this fact to you in order you take the measures you consider the better.
participants (5)
-
Alexander Terekhov
-
Anthony Williams
-
k-oli@gmx.de
-
Vicente Botet
-
vicente.botet