Dear Torsten,
Oz exceptions are attached to their thread. All threads are independent
and are not affected by exceptions in other threads. When you raise an
exception in a thread, stack frames are popped until a "catch" frame is
reached. If no "catch" frame is found, a default handler is called, and
the thread terminates. The default handler at the toplevel just prints
an error message. The default handler in a computation space makes the
space fail.
In your case, you can probably spawn those threads in a computation
space. If one of them fails, the space fails. All you have to do is to
wait until the space succeeds (all threads are terminated normally) or
fails (one of the threads crashed). The downside of that technique is
that there is no way to catch the exception from outside the space.
Another technique is to use *failed values*. A failed value is a
special value that encapsulates an exception, such that any attempt to
"use" the value raises the exception. A failed value can be used to
transmit an exception from a producer thread to its consumer thread(s).
See "Value.failed" at the bottom of the page
http://www.mozart-oz.org/documentation/base/node13.html#section.control.general
The following example shows how to execute a function Foo in a
concurrent thread, such that exception can be caught in the threads
using its result.
fun {Foo X Y Z}
X*Y+Z % may raise an exception if X is not a number, etc.
end
fun {BadConcurrentFoo X Y Z}
thread {Foo X Y Z} end % bad: the exception cannot be caught
end
fun {GoodConcurrentFoo X Y Z}
thread
try
{Foo X Y Z}
catch E then
{Value.failed E} % returns the exception in a failed value
end
end
end
try
W={GoodConcurrentFoo 2 4 ouch}
in
{Show success(W+5)} % '+' raises exception if W is a failed value
catch E then
{Show exception(E)}
end
You just have to make the thread you monitor return a result. The
result can be the conventional 'unit' in case of a normal termination,
and a failed value encapsulating any exception caught in the thread.
You will need a bit more stuff if you want to stop remaining threads,
but at least you can catch the exception outside its original thread.
Cheers,
raph
Torsten Anders wrote:
Dear all,
Sorry if I missed some section in the Oz documentation concerning this
issue.
How can I catch an exception raised in a (possibly nested) thread?
Please consider the dummy example below, which is simply an edited
version of an exception example in the tutorial. The difference is
solely that Eval raises an exception from within a thread. As a
consequence, it appears that the catch statement does never see this
exception -- it is instead reported by the top-level.
proc {Eval E}
thread
case E
of plus(X Y) then {Browse X+Y}
[] times(X Y) then {Browse X*Y}
else raise illFormedExpression(E) end
end
end
end
try
{ForAll [plus(5 10) times(6 11) min(7 10)] Eval}
catch
illFormedExpression(X) then {Browse '** '#X#' **'}
end
As I said, this is only a dummy example. What I actually want to do is
terminating a number of threads after one of them found a result, and I
though that raising an exception containing the result would be a clean
technique. BTW: I also tried terminating all my threads explicitly (see
code below). Yet this resulted in another exception -- namely
kernel(deadThread ...) ...) -- and so I was looking for alternative
solutions..
{ForAll MyThreads Thread.terminate}
Thank you!
Best
Torsten
_________________________________________________________________________________
mozart-users mailing list
[email protected]
http://www.mozart-oz.org/mailman/listinfo/mozart-users
_________________________________________________________________________________
mozart-users mailing list
[email protected]
http://www.mozart-oz.org/mailman/listinfo/mozart-users