Dear Jorge, dear Raphael,
again, thank you both for your informative reply.
Best
Torsten
On Mar 14, 2008, at 9:55 PM, Raphael Collet wrote:
Jorge Marques Pelizzoni wrote:
That's very important indeed. I just didn't mention that because
it really
does not apply to your case. Anyway, Raphael's advice is always worth
taking :o)
You're right. I focused too much on the message title. In fact your
problem is not really about exceptions...
%% 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
You see, here you already have a race condition. And this innocent
looking
procedure might well produce (unwanted) failure. Imagine that
there are
two threads that have just finished {F X} with True, for different
Xs. One
thread tests {IsFree Result} and is preempted just after that;
while the
other is activated and also gets True in {IsFree Result}. Mess is
likely
to ensue.
Correct! IsFree is an evil function: it looks nice, but it's not!
The correct way to write ConcurrentFind is use some mutual exclusion
device when accessing Result (as in my Spawner example). Here I'll
use a
more explicit such device (there I used a cell to perform mutual
exclusion):
(...)
declare
proc {ConcurrentFind2 Xs F ?Result}
L = {NewLock}
Threads = {Map Xs proc {$ X T}
thread
T = {Thread.this}
if {F X} then
lock L then
if {IsFree Result} then Result = X
end
end
end
{Wait _}
end
end}
in
{Wait Result}
{ForAll Threads Thread.terminate}
end
I like the trick to never let a thread terminate normally. But I
don't
like locks... Here is an alternative solution, that uses a port
instead
of a lock. The threads do not bind Result themselves, instead they
send
the value on the port if it the test is positive. The first value
sent
on the port is taken as the ConcurrentFind's result. No need for
explicit mutual exclusion, and no need for IsFree.
proc {ConcurrentFind3 Xs F ?Result}
S P={NewPort S}
Threads = {Map Xs proc {$ X T}
thread
T={Thread.this}
if {F X} then {Send P X} end
{Wait _}
end
end}
in
Result = S.1 % wait for first value sent
{ForAll Threads Thread.terminate}
end
Cheers,
raph
______________________________________________________________________
___________
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