
Stefan Seefeld wrote:
David Abrahams wrote:
Is everyone convinced that propagating the exception into the joining thread is the right behavior or even semantically sensible?
I'm not.
For me exceptions are conceptually associated with call stacks. While I can see a generalization of this concept to be valid in environments such as CORBA where a simulation of a synchronous call graph is provided, I think the situation in multi-threaded environments is quite different.
If someone wants to use multi-threading and make it look as a single call stack from the outside, he can always add translators that add exception marshalling on a higher level. I don't think a low level generic threading library should care about that.
It seems to me that most thread participants (pun not intended) are missing the point. You can execute a function object in a thread. That function object can, in the general case, return a value. When you join() that thread, you should be able to retrieve the return value of the function object. (Here's your call graph.) Now, in C++ functions actually can return either a value or an exception. That is, int f(); can return an int or throw an exception. Hence, when you execute that f in a thread, you should be able later to call int thread::join(); and it should return whatever f returned. Obviously, if f has thrown an exception, there is no int to return, so join() should throw an exception, too. What kind of exception should join() throw? It would make sense to replicate the original, wouldn't it? Note that you can't add exception marshalling on a higher level (with the current interface) because you can't access a thread's state (to retrieve its return value or exception) from another thread.