Dear Jorge, dear Raphael,

thank you both for your kind reply. In particular, I found it important to learn about the use of Value.failed! Still, I probably should have told you from the beginning what I am actually after :)

The following procedure ConcurrentFind does already what I want to do. I want a higher-order function which returns an element from a given list Xs for which a given Boolean function F returns true. However, this function should not completely block on undetermined list elements if some later list element would already be a hit.

Brief background info: I want to use ConcurrentFind in CSPs quasi as some form of a selection constraint for arbitrary values, more specifically for objects containing variables. ConcurrentFind (and its brother ConcurrentFilter) is used to delay constraint applications until enough information became available during the search process to decide to which objects/variables the constraints in question are applied. I use this as an alternative to FD.impl and friends. For example, my function F may internally call some reified constraint and transform its result into a Boolean (e.g., {MyConstraint} == 1). Some constraints are then applied to the object returned by ConcurrentFind.


/** %% Find some element in Xs for which F returns true. The Result is not necessarily the first 'matching' element in Xs, but ConcurrentFind returns a result as soon as enough information is available to decide for any element. %% Inefficient version: after ConcurrentFind already found an element, concurrent threads may still continue running.
%% */
proc {ConcurrentFind Xs F ?Result}
   {ForAll Xs proc {$ X}
                 thread
                    %% blocks until X is sufficiently determined
                    if {F X} andthen {IsFree Result}
                    then Result = X
                    end
                 end
              end}
end


Here is an example which demonstrates its use. Note that the second element of Xs is never determined and still ConcurrentFind returns a matching value.

declare
Xs = [1 _ 2 _ 3 _ 2]
Y = {ConcurrentFind Xs fun {$ X} X > 3 end}
{Browse Y}


%% Y will be either 5 or 6 (whoever comes first)
thread {Nth Xs 4} = 5 end
thread {Nth Xs 6} = 6 end


Now, the issue with this version of ConcurrentFind is that there still may be 'pending' threads after ConcurrentFind returned. If used as a 'selection constraint' as sketched above, many threads may still be pending because many values in Xs may not be determined enough for F to return anything. Can I somehow terminate those threads?

Here is a _not-working_ example demonstrating the idea, but this version always throws an exception kernel(deadThread <SomeThread>). What does this exception mean and is there a way to prevent it? Jorge, I am sorry -- I tried to understand why this exception does not happen in the example you gave, but I don't see why.


%% BUGGY: Causes exception: kernel(deadThread <SomeThread>)
proc {ConcurrentFind2 Xs F ?Result}
   Threads  = {Map Xs proc {$ X T}
                         thread
                            T = {Thread.this}
                            if {F X} andthen {IsFree Result}
                            then Result = X
                            end
                         end
                      end}
in
   {Wait Result}
   {ForAll Threads Thread.terminate}
end

Thank you very much!

Best
Torsten

On Mar 14, 2008, at 2:53 PM, Raphael Collet wrote:
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 mozart- [EMAIL PROTECTED]
http://www.mozart-oz.org/mailman/listinfo/mozart-users

--
Torsten Anders
Interdisciplinary Centre for Computer Music Research
University of Plymouth
Office: +44-1752-233667
Private: +44-1752-558917
http://strasheela.sourceforge.net
http://www.torsten-anders.de




_________________________________________________________________________________
mozart-users mailing list                               
[email protected]
http://www.mozart-oz.org/mailman/listinfo/mozart-users

Reply via email to