RE: [boost] Re: future of boost.threads

From: David Abrahams [mailto:dave@boost-consulting.com]
Of course you cannot portably pass all exceptions, but you may be able to pass all the ones that use standard types.
And what if the std library or somebody else throws exceptions *derived* from the standard types?
If it is not a recognized corba exception what the ACE TAO does is eat it with a catch(...) and then throws a corba system exception on the other side. Glen

Glen Knowles wrote:
From: David Abrahams [mailto:dave@boost-consulting.com]
Of course you cannot portably pass all exceptions, but you may be able to pass all the ones that use standard types.
And what if the std library or somebody else throws exceptions *derived* from the standard types?
If it is not a recognized corba exception what the ACE TAO does is eat it with a catch(...) and then throws a corba system exception on the other side.
yes, so all exceptions that are allowed to pass have to be explicitely declared as such. If it is not declared, a special standard exception will be thrown (or may be something equivalent to 'unexpected'). If it is derived from a declared one, it will be sliced. Regards, Stefan

On Mon, 09 Feb 2004 14:55:39 -0500, Stefan Seefeld wrote
Glen Knowles wrote:
If it is not a recognized corba exception what the ACE TAO does is eat it with a catch(...) and then throws a corba system exception on the other side.
yes, so all exceptions that are allowed to pass have to be explicitely declared as such. If it is not declared, a special standard exception will be thrown (or may be something equivalent to 'unexpected').
The object request broker throws CORBA::Unknown if it catches an exception not in the interface specification. BTW, I like the idea someone else suggested of using a typelist to specify known exception types.... Jeff

-----Original Message----- From: boost-bounces@lists.boost.org [mailto:boost-bounces@lists.boost.org] On Behalf Of Jeff Garland
BTW, I like the idea someone else suggested of using a typelist to specify known exception types....
It seems like someone brought this idea up the last time exceptions and threads were discussed. I also agree with the poster who suggested that this solution be independent of Boost.Thread so it can be used in other cases where exceptions cannot be propagated normally. A typelist based solution could easily be generic enough for this.

Stefan Seefeld <seefeld@sympatico.ca> writes:
Glen Knowles wrote:
Of course you cannot portably pass all exceptions, but you may be able to pass all the ones that use standard types.
And what if the std library or somebody else throws exceptions *derived* from the standard types? If it is not a recognized corba exception what the ACE TAO does is eat it with a catch(...) and then throws a corba system exception on
From: David Abrahams [mailto:dave@boost-consulting.com] the other side.
yes, so all exceptions that are allowed to pass have to be explicitely declared as such. If it is not declared, a special standard exception will be thrown (or may be something equivalent to 'unexpected'). If it is derived from a declared one, it will be sliced.
Is everyone convinced that propagating the exception into the joining thread is the right behavior or even semantically sensible? -- Dave Abrahams Boost Consulting www.boost-consulting.com

David Abrahams wrote: [...]
thrown (or may be something equivalent to 'unexpected'). If it is derived from a declared one, it will be sliced.
Is everyone convinced that propagating the exception into the joining thread is the right behavior or even semantically sensible?
I'm convinced that propagating *unexpected* exceptions into the joining thread is totally wrong and insensible. regards, alexander.

-----Original Message----- From: boost-bounces@lists.boost.org [mailto:boost-bounces@lists.boost.org] On Behalf Of Alexander Terekhov
Is everyone convinced that propagating the exception into the joining thread is the right behavior or even semantically sensible?
I'm convinced that propagating *unexpected* exceptions into the joining thread is totally wrong and insensible.
I agree with that completely. I think we need a tool that: 1) Can be used across boundaries (inside one process) that exceptions cannot pass. I.E. threads, other languages (like Python, VB), or OS callbacks like windows message handlers. 2) Can be provided with a specify a set of exceptions to be caught across this boundary. 3) Can relay some information to the caller about which exception was caught. Candidates currently are copies of the exception, with the risk of slicing, or cloning, which is intrusive. I don't have any opinion off of the top of my head about whether or not this mechanism should automatically throw the copies or clones of these exceptions. In the case of thread groups it seems like a list of exceptions would be better. Propagation feels more appropriate if you want to think of one thread (or a windows modal dialog) returning a value.

At Monday 2004-02-09 15:30, you wrote:
David Abrahams wrote: [...]
thrown (or may be something equivalent to 'unexpected'). If it is derived from a declared one, it will be sliced.
Is everyone convinced that propagating the exception into the joining thread is the right behavior or even semantically sensible?
I'm convinced that propagating *unexpected* exceptions into the joining thread is totally wrong and insensible.
would you rather abort the application??
regards, alexander.
_______________________________________________ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Victor A. Wagner Jr. http://rudbek.com The five most dangerous words in the English language: "There oughta be a law"

Victor A. Wagner, Jr. wrote:
would you rather abort the application??
Isn't an unexpected exception a programming error? We shouldn't be incorporating stuff to protect against programming errors, they should be caught by other means IMO Russell

Russel wrote:
Victor A. Wagner, Jr. wrote:
would you rather abort the application??
Isn't an unexpected exception a programming error?
Ok. I can buy that.
We shouldn't be incorporating stuff to protect against programming errors, they should be caught by other means IMO
Not protecting means aborting, right? I agree with Victor, although I might not use his hard tone ;-) I have "only" been doing this since 1979, so I am not real old-school like Victor, but I must say that it seems to be better to have the system survive in spite of a slight programming error. Most MLOC programs have those; especially multi-threaded MLOCs. There seem to be two schools here: (1) the Standardists, striving to follow The Standard verbatim, and (2) the Pragmatics, trying to see how different mechanisms would affect their daily struggles with real problems. In my extremely humble opinion, the Standardist have to diverge into various imaginative interpretations of The Text in order to extrapolate its constraints on multi-threading. The truth is, as discussed before, The Standard does not even mention the word "thread." In my still very humble opinion, The Standard does not even allow for multi-threading at all, i.e., Standard C++ is a single-threaded creature, as manifested by its sequential defining execution model. /David

David Bergman wrote:
There seem to be two schools here: (1) the Standardists, striving to follow The Standard verbatim, and (2) the Pragmatics, trying to see how different mechanisms would affect their daily struggles with real problems.
Sorry, that's nonsense. Nobody in the world is (1), and the only reason to bring up this hypothetical school division is as an excuse to write broken code that happens to work today.

Peter wrote:
David Bergman wrote:
There seem to be two schools here: (1) the Standardists,
striving to
follow The Standard verbatim, and (2) the Pragmatics, trying to see how different mechanisms would affect their daily struggles with real problems.
Sorry, that's nonsense. Nobody in the world is (1), and the only reason to bring up this hypothetical school division is as an excuse to write broken code that happens to work today.
Thanks, I love it when someone labels another person's observations as nonsensical. In fact, I sometimes pertain to that Standardist school, so they are not necessarily schools with full-time alumni. /David

Peter wrote:
David Bergman wrote:
There seem to be two schools here: (1) the Standardists,
striving to
follow The Standard verbatim, and (2) the Pragmatics, trying to see how different mechanisms would affect their daily struggles with real problems.
Sorry, that's nonsense. Nobody in the world is (1), and the only reason to bring up this hypothetical school division is as an excuse to write broken code that happens to work today.
I believe in coherence and logics, but that is not necessarily derived only by interpreting The Standard, especially when threads are concerned, i.e., there might be other soures for coherence. I am a Theorist, with too many millions of lines of code under my belt not to be a Pragmatic at times. And, yes, I think following The Standard as closely as possible provide for good foundation for both solid theories and working implementations. If you are looking to bash junior developers, "if"-ing their ways through life, look elsewhere. /David

At Tuesday 2004-02-10 08:45, you wrote:
David Bergman wrote:
There seem to be two schools here: (1) the Standardists, striving to follow The Standard verbatim, and (2) the Pragmatics, trying to see how different mechanisms would affect their daily struggles with real problems.
Sorry, that's nonsense.
with exactly (no more, no less) respect than you showed David Peter, I think you simply "don't get it".
Nobody in the world is (1), and the only reason to bring up this hypothetical school division is as an excuse to write broken code that happens to work today.
your definition of "broken" apparently doesn't match mine. I wish to be able to view a thread invocation as a delayed (possibly remote) procedure call, which _may_ return something (including an exception). Insistance that I cannot do that seems pointlessly pedantic? You haven't shown _why_ it's pointless. I say it's a useful technique, you say it's rubbish. Adopting what I want in this instance allows me to work and does _nothing_ to what you do. Adopting your point of view, prevents me from implementing some solutions. Which way do you want to play the game?
_______________________________________________ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Victor A. Wagner Jr. http://rudbek.com The five most dangerous words in the English language: "There oughta be a law"

Victor A. Wagner, Jr. wrote:
At Tuesday 2004-02-10 08:45, you wrote:
David Bergman wrote:
There seem to be two schools here: (1) the Standardists, striving to follow The Standard verbatim, and (2) the Pragmatics, trying to see how different mechanisms would affect their daily struggles with real problems.
Sorry, that's nonsense.
with exactly (no more, no less) respect than you showed David
Peter, I think you simply "don't get it".
Yes, it does seem so. I honestly don't get it, "it" being the relationship between the distinction between Standardists and Pragmatics and the thread discussion.
Nobody in the world is (1), and the only reason to bring up this hypothetical school division is as an excuse to write broken code that happens to work today.
your definition of "broken" apparently doesn't match mine. I wish to be able to view a thread invocation as a delayed (possibly remote) procedure call, which _may_ return something (including an exception). Insistance that I cannot do that seems pointlessly pedantic? You haven't shown _why_ it's pointless.
I don't need to. I haven't claimed that it's pointless, "it" being the ability to view the thread invocation as a delayed procedure call.
I say it's a useful technique, you say it's rubbish.
No, I did not.
Adopting what I want in this instance allows me to work and does _nothing_ to what you do. Adopting your point of view, prevents me from implementing some solutions.
I don't think that my point of view is what you think it is.

....ping pong shouting match omitted....
Sorry to see this thread has degenerated. Since I'm at least partially responsible for starting this mess, maybe I can help slow it down by getting back to the facts: 1) Clearly propagating an exception isn't always the correct model. In my experience I've written a few server apps and most of the time the threads contain their own exceptions and that makes perfect sense. 2) I believe exception propagation can be a useful model at times, as do apparently a few others. Evidence aside from my experience is other libraries that offer/use this capability. 3) So, it would be nice if this could be worked into the design of boost::threads. But as I believe I said earlier I hardly believe it is the most important capability that should be added to Boost threads. Seems to me we can put it on the nice to prototype if someone has time and move on... Jeff

At Tuesday 2004-02-10 17:11, you wrote:
Victor A. Wagner, Jr. wrote: [deleted]
Peter, I think you simply "don't get it".
Yes, it does seem so. I honestly don't get it, "it" being the relationship between the distinction between Standardists and Pragmatics and the thread discussion. [deleted] I don't think that my point of view is what you think it is.
given that I normally agree with you I'm beginning to think I mis-interpreted your comments here apology tendered
_______________________________________________ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Victor A. Wagner Jr. http://rudbek.com The five most dangerous words in the English language: "There oughta be a law"

Victor A. Wagner, Jr. wrote:
At Tuesday 2004-02-10 17:11, you wrote:
I don't think that my point of view is what you think it is.
given that I normally agree with you I'm beginning to think I mis-interpreted your comments here apology tendered
It's only fair since I probably misinterpreted David Bergman's remark, for which I owe him an apology. David, please accept my sincere apologies. While I think I kept up with the technical content, I must have missed the rest of the context that prompted your response.

Peter wrote:
Victor A. Wagner, Jr. wrote:
At Tuesday 2004-02-10 17:11, you wrote:
I don't think that my point of view is what you think it is.
given that I normally agree with you I'm beginning to think I mis-interpreted your comments here apology tendered
It's only fair since I probably misinterpreted David Bergman's remark, for which I owe him an apology.
David, please accept my sincere apologies. While I think I kept up with the technical content, I must have missed the rest of the context that prompted your response.
To complete our meta loop, I too apologize for wasting bandwidth with rhetorics. I think we all want to either improve or clarify the Boost.Thread framework, to suit both the theoretic and pragmatic sides of ourselves. I posted a list of the (what I consider to be) three aspectes of the thread library under discussion, although I think it was HTML:ed by my mail client :-( I have not used Boost.Thread for the last year, so I will catch up today (I am using PThreads in a financial project, and would love to have an incentive to switch to Boost.Thread anyway...) and look at how one could introduce typelists specifying the *expected* exceptions to the "thread manager," suggested by Brock, me, and others. /David

David Bergman wrote:
I agree with Victor, although I might not use his hard tone ;-)
I have "only" been doing this since 1979, so I am not real old-school like Victor, but I must say that it seems to be better to have the system survive in spite of a slight programming error. Most MLOC programs have those; especially multi-threaded MLOCs.
There seem to be two schools here: (1) the Standardists, striving to follow The Standard verbatim, and (2) the Pragmatics, trying to see how different mechanisms would affect their daily struggles with real problems.
I disagree. The last product I worked on, we went with this approach. Even asserts threw exceptions which were caught, so the thread didn't terminate the app. If this happened during data acquisition, we could still save the data. But I see asserts as program logic error, and if the program isn't doing as expected, what to do you do? Ignore it and allow the user to use the data? Trust data from something that went wrong? It can get worse: in win32, access violations get turned into exceptions (in Borland's VCL library, anyway), which would then just be treated as an unexpected exception, but it actually means something really bad has happened. Should we still save the data and continue? This may come back to the question of should errors such as access violations (seg faults?) etc be turned into exceptions, but IMO, unexpected exceptions means you don't know what happened, and therefore I wouldn't trust results from a run where something unexpected happened, and in the case of the AV, you don't know the state of the system after such an error so is it really safe to try and continue? We took the approach at the time that it was (because we knew which thread was causing the odd problem and did trust that it didn't affect the data) but I don't think it should be standard practice. We coded to handle unknown errors which we knew were coming in but couldn't pin them down. But we did this in a specific place for a specific problem, I don't think it should be done as a matter of practice. Thanks Russell

"Victor A. Wagner, Jr." wrote: [...]
I'm convinced that propagating *unexpected* exceptions into the joining thread is totally wrong and insensible.
would you rather abort the application??
Absolutely. That said, feel free to catch anything/everything but please don't impose this silliness on me. The only problem with respect to threads/futures is that the dynamic context in which exceptions are thrown (in the "joinee" thread) is "detached" (in space and time) from the dynamic context that is supposed to "decide" (my means of try handler(s) or lack thereof) whether this or that exception is expected or unexpected. That leads to the conclusion that a typelist of expected (to be caught in the joinee thread and "re-rasied" in the joiner thread at join point) exceptions shall be specified at thread/future creation time. regards, alexander.

At Tuesday 2004-02-10 03:21, you wrote:
"Victor A. Wagner, Jr." wrote: [...]
I'm convinced that propagating *unexpected* exceptions into the joining thread is totally wrong and insensible.
would you rather abort the application??
Absolutely.
fine, don't catch any exceptions when you do the join(), your system will crash gloriously.
That said, feel free to catch anything/everything but please don't impose this silliness on me. The only problem with respect to threads/futures is that the dynamic context in which exceptions are thrown (in the "joinee" thread) is "detached" (in space and time) from the dynamic context that is supposed to "decide" (my means of try handler(s) or lack thereof) whether this or that exception is expected or unexpected.
I suggest again, that you view the thread creation and later join as the dispatch / results portion of a normal function call. If you cannot see that as at least one possible use of threads, then there isn't any point in further discussion with you.
That leads to the conclusion that a typelist of expected (to be caught in the joinee thread and "re-rasied" in the joiner thread at join point) exceptions shall be specified at thread/future creation time.
I submit the argument against throw specifications (see all the relevant literature).
regards, alexander.
_______________________________________________ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Victor A. Wagner Jr. http://rudbek.com The five most dangerous words in the English language: "There oughta be a law"

Alexander Terekhov wrote:
David Abrahams wrote: [...]
thrown (or may be something equivalent to 'unexpected'). If it is derived from a declared one, it will be sliced.
Is everyone convinced that propagating the exception into the joining thread is the right behavior or even semantically sensible?
I'm convinced that propagating *unexpected* exceptions into the joining thread is totally wrong and insensible.
Maybe, for some meaning of "unexpected". One case where "propagating" exceptions is wrong is when the thread is not supposed to be joined. Since exception propagation is done on join(), the end result would be threads dying silently on an uncaught exception. This has already been proven to be a problem in practice; hence, the default behavior should be to terminate() when an exception escapes from the thread function. The other case where propagation would be wrong is when the thread has been terminated by an exception that indicates a programming error. On the surface, this implies that we need a mechanism to label some exceptions "call terminate()" (or equivalently, label some exceptions "propagate" and call terminate() on the rest.) However, we already have such a mechanism. It is called "exception specification". I see no good reason to duplicate it on a library level.

Peter Dimov wrote: [...]
One case where "propagating" exceptions is wrong is when the thread is not supposed to be joined.
When the thread is not supposed to be joined, then all expected exceptions [e.g. thread cancelation or exit] should be caught (but "ignored") and all unexpected exceptions should still terminate the entire process at throw point (that's not the way how exception specification work currently). Some exceptions listed in this or that throw spec may be expected and some not. (Perfect forwarding might help somewhat here. ;-) ) regards, alexander.

Alexander Terekhov wrote:
Peter Dimov wrote: [...]
One case where "propagating" exceptions is wrong is when the thread is not supposed to be joined.
When the thread is not supposed to be joined, then all expected exceptions [e.g. thread cancelation or exit] should be caught (but "ignored") and all unexpected exceptions should still terminate the entire process
Yes, that's exactly what I had in mind.
at throw point
We can't do this from the library side.
(that's not the way how exception specification work currently).
We can't change this from the library side either. ;-)

On Tue, 10 Feb 2004 15:59:35 +0200, Peter Dimov <pdimov@mmltd.net> wrote:
Alexander Terekhov wrote:
David Abrahams wrote: [...]
thrown (or may be something equivalent to 'unexpected'). If it is derived from a declared one, it will be sliced.
Is everyone convinced that propagating the exception into the joining thread is the right behavior or even semantically sensible?
I'm convinced that propagating *unexpected* exceptions into the joining thread is totally wrong and insensible.
Maybe, for some meaning of "unexpected".
I think it all depends on the context. If you are doing multithreading in the traditional sense then yes, propogating the exception is odd. But another type of multithreading is one which Boost.Threads encourages, and that is calling a function synchronously to the main thread of execution. It seems only a logical progression to allow the user access to the return value of the called function, and you can't do that (IMO) without propogating an exception of some sort in the situation where there is no resurn value. Why not give the user the option of how an exception is propagated. It won't hurt the purists at all because they can easily carry on using boost::thread which will not propagate exceptions. This is something I've often emulated by passing reference's to thread functions, and I would find a helper to do this useful in the real world frequently. That said, I don't think that boost::thread should be changed to add this capability, boost::thread implies the traditional type of multithreading to me. I've implemented a class async_call that does basically what Victor suggested, implemented as a wrapper around boost::thread. Use : int f(); try { async_call<int [, my_exception [, ...]]> async_f(f); int x = async_f.result(); } catch (my_exception e) { // ... } NOTE: In the event of an exception not listed being thrown by the thread function, std::bad_exception is currently thrown, I'm not sure if that is ideal behaviour or not. Sam

"Is everyone convinced that propagating the exception into the joining thread is the right behavior or even semantically sensible?"
as a novice user of concurrent programming ( especially when compared to the level here in the boost list ), may i ask whether it is going to be possible to identify the throwing thread or not? here's why i am asking this: let's say i have two threads reading two different files and one of them throws ios_base::failure. this information by itself is meaningless if i catch it in the master thread as i don't have a way of identifying the source. currently, we employ a different mechanism ( using pthreads for now; wishing to switch to boost.threads ): each thread has its own error code in a shared container and if they want to report an error, they write to that container. that way, we know which thread is reporting what error and we can handle it. elegant? not at all but it works so i wonder if propagating exceptions from worker threads to the master thread is gonna have some comparable functionality? ( worker/master architecture is the only model we commonly use so i can't really talk for other thread architectures ). if it doesn't, i think the best a programmer like myself can do is to catch ( ... ) and then still use the shared error code container to resolve the issue am i misunderstanding this mechanism or is it gonna be like i described above? burch
Stefan Seefeld <seefeld <at> sympatico.ca> writes:
Glen Knowles wrote:
Of course you cannot portably pass all exceptions, but you may be able to pass all the ones that use standard types.
And what if the std library or somebody else throws exceptions *derived* from the standard types? If it is not a recognized corba exception what the ACE TAO does is eat it with a catch(...) and then throws a corba system exception on
From: David Abrahams [mailto:dave <at> boost-consulting.com] the other side.
yes, so all exceptions that are allowed to pass have to be explicitely declared as such. If it is not declared, a special standard exception will be thrown (or may be something equivalent to 'unexpected'). If it is derived from a declared one, it will be sliced.
Is everyone convinced that propagating the exception into the joining thread is the right behavior or even semantically sensible?

At Monday 2004-02-09 16:08, you wrote:
"Is everyone convinced that propagating the exception into the joining thread is the right behavior or even semantically sensible?"
as a novice user of concurrent programming ( especially when compared to the level here in the boost list ), may i ask whether it is going to be possible to identify the throwing thread or not?
here's why i am asking this: let's say i have two threads reading two different files and one of them throws ios_base::failure. this information by itself is meaningless if i catch it in the master thread as i don't have a way of identifying the source. currently, we employ a different mechanism ( using pthreads for now; wishing to switch to boost.threads ): each thread has its own error code in a shared container and if they want to report an error, they write to that container. that way, we know which thread is reporting what error and we can handle it. elegant? not at all but it works
so i wonder if propagating exceptions from worker threads to the master thread is gonna have some comparable functionality? ( worker/master architecture is the only model we commonly use so i can't really talk for other thread architectures ). if it doesn't, i think the best a programmer like myself can do is to catch ( ... ) and then still use the shared error code container to resolve the issue
am i misunderstanding this mechanism or is it gonna be like i described above?
I haven't looked at boost::thread closely at all, but I'd guessed that "start_thread()" would have returned some sort of handle, and "join(somehandle)" is how you do it. I believe this is sufficient for your needs. Now, I may be _completely_ wrong on how boost::threads works, I didn't write it.
burch
Stefan Seefeld <seefeld <at> sympatico.ca> writes:
Glen Knowles wrote:
Of course you cannot portably pass all exceptions, but you may be able to pass all the ones that use standard types.
And what if the std library or somebody else throws exceptions *derived* from the standard types? If it is not a recognized corba exception what the ACE TAO does is eat it with a catch(...) and then throws a corba system exception on
From: David Abrahams [mailto:dave <at> boost-consulting.com] the other side.
yes, so all exceptions that are allowed to pass have to be explicitely declared as such. If it is not declared, a special standard exception will be thrown (or may be something equivalent to 'unexpected'). If it is derived from a declared one, it will be sliced.
Is everyone convinced that propagating the exception into the joining thread is the right behavior or even semantically sensible?
_______________________________________________ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Victor A. Wagner Jr. http://rudbek.com The five most dangerous words in the English language: "There oughta be a law"

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. Regards, Stefan

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.

"Peter Dimov" <pdimov@mmltd.net> writes:
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.
Makes sense to me. I guess I just wanted to know if it was as simple as that. -- Dave Abrahams Boost Consulting www.boost-consulting.com

-----Original Message----- From: boost-bounces@lists.boost.org [mailto:boost-bounces@lists.boost.org]On Behalf Of Stefan Seefeld Sent: Tuesday, February 10, 2004 1:54 PM To: Boost mailing list Subject: Re: [boost] Re: future of boost.threads
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.
i think the same. exceptions result in call unwinding and eventually being caught, or "falling out the bottom". activities tightly bound to the call stack. anything that attempts to "propagate" exceptions across threads would be doing something distinct to what the C++ spec describes, i guess. would it be "more correct" to allow a thread to be notified of an exception in another thread? at which point it could throw (a completely distinct) exception; along the lines of "throw trusty_worker_barfed". the significant difference being that the new exception does not attempt to assume the type+value of the original exception. preserves definition of exception. allows a thread (or threads) to respond to exceptional activity in another and sidesteps the issue of copying (i.e. slicing). at the obvious cost of actual type+value of the original. a "lossy propagation" model? BTW: should the propagation question extend to threads in other processes? except for the obvious difficulty of transfer to another address space it would seem a relevant question with all the refs to ACE+TAO SW

At Monday 2004-02-09 18:34, you wrote:
-----Original Message----- From: boost-bounces@lists.boost.org [mailto:boost-bounces@lists.boost.org]On Behalf Of Stefan Seefeld Sent: Tuesday, February 10, 2004 1:54 PM To: Boost mailing list Subject: Re: [boost] Re: future of boost.threads
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.
i think the same. exceptions result in call unwinding and eventually being caught, or "falling out the bottom". activities tightly bound to the call stack.
consider the call to join() what's the big hoo-haw about it getting some information back from the thread? and if there's info, then there might be an exception as part of it.
anything that attempts to "propagate" exceptions across threads would be doing something distinct to what the C++ spec describes, i guess.
Hey, if you seem to be offended by this, how about a NEW function called wait_for_and_report_results(somethreadhandle) ?? would it be ok for that function to throw? Why not? It's beginning to look like there are different models that all use "threading" as an implementation technique. These models apparently also differ on what should happen if a "thread goes bad". I've been doing embedded systems since 1971 "crashing" the computer is NOT an acceptable answer. Short of catastrophic failure of the computer system itself, all errors must be given to the program in one fashion or another so that it can attempt to recover.
would it be "more correct" to allow a thread to be notified of an exception in another thread? at which point it could throw (a completely distinct) exception; along the lines of "throw trusty_worker_barfed". the significant difference being that the new exception does not attempt to assume the type+value of the original exception.
preserves definition of exception. allows a thread (or threads) to respond to exceptional activity in another and sidesteps the issue of copying (i.e. slicing). at the obvious cost of actual type+value of the original.
a "lossy propagation" model?
BTW: should the propagation question extend to threads in other processes? except for the obvious difficulty of transfer to another address space it would seem a relevant question with all the refs to ACE+TAO
SW
_______________________________________________ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Victor A. Wagner Jr. http://rudbek.com The five most dangerous words in the English language: "There oughta be a law"

-----Original Message----- From: boost-bounces@lists.boost.org [mailto:boost-bounces@lists.boost.org]On Behalf Of Victor A. Wagner, Jr. Sent: Tuesday, February 10, 2004 7:17 PM To: Boost mailing list Subject: RE: [boost] Re: future of boost.threads
At Monday 2004-02-09 18:34, you wrote:
-----Original Message----- From: boost-bounces@lists.boost.org [mailto:boost-bounces@lists.boost.org]On Behalf Of Stefan Seefeld Sent: Tuesday, February 10, 2004 1:54 PM To: Boost mailing list Subject: Re: [boost] Re: future of boost.threads
David Abrahams wrote:
Is everyone convinced that propagating the exception into the joining thread is the right behavior or even semantically sensible?
<snip>
i think the same. exceptions result in call unwinding and eventually being caught, or "falling out the bottom". activities tightly bound to the call stack.
consider the call to join() what's the big hoo-haw about it getting some information back from the thread? and if there's info, then there might be an exception as part of it.
this thread is quite complex. a good chunk of that is probably attributable to "sprawl" which i suspect i have contributed to. i now understand (i hope) the original question to be specifically related to the handling of exceptions at the point of "join". if boost can formalize the behaviour at this point using facillities such as typelists then i'm happy with that (impressively staggered would be closer to the truth). if i understand boost::threads well enough then my answer to the original question is yes, it is the right behaviour and yes it is semantically sensible. some kind of typelist specification seems complex, but also consistent (with existing exception model) and powerful. i'm guessing there will be "normal default" behaviour where no typelist is given and that this behaviour will be manifested in the joining thread, i.e. the worker thread should not "fall out the bottom" due to passing of "bad" code (the functor). i'm happy to leave implementation of all that to the gods :-)
anything that attempts to "propagate" exceptions across threads would be doing something distinct to what the C++ spec describes, i guess.
Hey, if you seem to be offended by this, how about a NEW function called wait_for_and_report_results(somethreadhandle) ?? would it be ok for that function to throw? Why not?
not offended. concerned at most :-) concerned about blurring of the definition of what an exception is. very comfortable with the emerging "error handling model for boost::thread join". the new model involves the throw+catch of one exception and a related (propagated) throw of a new, distinct exception. cheers, scott

At Monday 2004-02-09 14:19, you wrote:
Stefan Seefeld <seefeld@sympatico.ca> writes:
Glen Knowles wrote:
Of course you cannot portably pass all exceptions, but you may be able to pass all the ones that use standard types.
And what if the std library or somebody else throws exceptions *derived* from the standard types? If it is not a recognized corba exception what the ACE TAO does is eat it with a catch(...) and then throws a corba system exception on
From: David Abrahams [mailto:dave@boost-consulting.com] the other side.
yes, so all exceptions that are allowed to pass have to be explicitely declared as such. If it is not declared, a special standard exception will be thrown (or may be something equivalent to 'unexpected'). If it is derived from a declared one, it will be sliced.
Is everyone convinced that propagating the exception into the joining thread is the right behavior or even semantically sensible?
I consider it equivalent to the asking for the results of a function whose execution was delayed. Most people only consider marshalling, dispatching, and results as a single step in which exceptions clearly make sense. I don't see the big difference when we split them up into different pieces. I further don't see a big distinction between the above and beginning a thread and join()ing it.
-- Dave Abrahams Boost Consulting www.boost-consulting.com
_______________________________________________ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Victor A. Wagner Jr. http://rudbek.com The five most dangerous words in the English language: "There oughta be a law"
participants (13)
-
Alexander Terekhov
-
Brock Peabody
-
Burc Arpat
-
David Abrahams
-
David Bergman
-
Glen Knowles
-
Jeff Garland
-
Peter Dimov
-
Russell Hind
-
Sam Partington
-
scott
-
Stefan Seefeld
-
Victor A. Wagner, Jr.