
On Mar 21, 2007, at 7:30 PM, Emil Dotchevski wrote:
For this use case, N2184 argues that the use case should be supported
with a higher-level library which sits non-intrusively on top of std::thread. My preferred name for this is std::shared_future (though std::tr2::shared_future is a more likely name). shared_future would be copyable, multi-joinable, and would deliver both normal and exceptional results from an asynchronous job when the shared_future is joined with.
The advantage of putting this functionality in a separate class is that it costs space and time.
Assuming that the copyable semantics are commonly useful, is it easier to build them on top of N2184 than on top of, say pthreads (which has been ported to Windows too and is therefore competing with N2184 as the base of such higher level interface)?
Yes, I believe shared_future is more easily implemented in terms of N2184 than pthreads. Exception safety alone is a significant win. If a parent thread which owns a pthread_t on the stack experiences an exception (such as cancellation) propagating through the stack frame, it must explicitly deal with the pthread_t. N2184 automates this concern, first canceling the child thread, and then detaching it. A raw pthread_t would not only ignore the cancellation of the parent thread, it would also leak the pthread_t, never joining with it, nor detaching it. Indeed, N2184 is meant to be little more than an RAII wrapper around pthread semantics.
Speaking of which, on certain operating systems, pthreads probably is a good base for implementing the N2184 interface, but that way we're going from copyable handles to non-copyable handles. And now you're saying I can build copyable handles interface on top of N2184? I could be missing something important, but this doesn't make sense to me.
Peter Dimov and Ion Gaztanaga have both implemented shared ownership thread manager objects (i.e. future) on top of boost::thread (non- intrusively). I'm extremely grateful for their ground breaking proof of concept work showing that we don't need a copyable low level to support a copyable higher level.
Proof that it is possible is one thing, but is it trivial?
The current technique is to layer on top of a std::thread a std::mutex and std::condition that synchronize access using a function adaptor. It is difficult for me to characterize this as trivial or not. I am now used to it and find it relatively easy. But I also remember having trouble coming up with this solution. So I fully support std::supported encapsulations of this effort. On the other hand if you force the std::lib to put mutexes and condition variables inside std::thread (or whatever the lowest level is called), then you remove the possibility that some clients who don't need this overhead don't have to pay for it. Analogy: Do you want a mutex inside of ostream::sentry or not?
And fwiw, N2184::thread delivers a std::thread which I believe has the more common motivations for a copyable std::thread: You can return it from factory functions and you can put into std::containers. These actions will only require movability, not copyability, in C++0X.
You can do all that with shared handles too, even in current STL containers. I wasn't comparing N2184 to boost::thread, I was comparing it to N2178.
Sorry. I meant to say that a unique-ownership std::thread can provide this functionality (return from factory functions, place in containers) cheaper than a shared-ownership std::thread can, at least on pthread-based platforms. -Howard