>   $thread  = new Thread \&func     , @args;
>   $thread  = new Thread sub { ... }, @args;
>        async { ... };
>   $result  = join $thread;
>
>   critical { ... };   # one thread at a time in this block
>
> =item C<async> BLOCK
>
> Executes BLOCK in a separate thread. Syntactically, C<async> BLOCK
> works like C<do> BLOCK. In particular, it does not return a C<Thread>
> object. If you want the thread object, use one of the C<new> C<Thread>
> forms shown above.
Ooh!  Ooh!  Call on me!  Call on me!
The async BLOCK won't know it's value for quite some time.  This means that
it's a semi-lazy expression generator...

So,
$bignum = do {factorial(1024)}; # is equivlent to just plain
factorial(1024);
will compute $bignum now, ignoring the rest of the code on the thread until
we're done.
$bignum = async {factorial(1024)};
will work on computing $bignum while still executing code, and block on use
of $bignum if we aren't finished yet (or just make those expressions
semi-lazy on this one?)
$bignum = lazy {factorial(1024)}; # should be lazy factorial(1024)?
won't work on computing $bignum until we use it.

> =head2 Critical section
>
> C<critical> is a new keyword. Syntactically, it works like C<do>.
>
>   critical { ... };
>
> The interpreter guarantees that only one thread at a time can execute
> a C<critical> block.
You should specify that a critical block is temprorly like a do {} block
too -- the inner BLOCK is completely run before any code after it.

> =head2 Event
>
> Events have two states: I<set> and I<reset>. Threads I<wait> on an
> event; the C<wait> call blocks until the event is set.
Might I suggest that things will be cleaner if events have the states
"signaled" and "unsignaled", rather then set and reset?  For one thing,
reset implies that it was previously set, and thereby implies that "set" is
the default.  Secondly, that way their signaled state works is obvious.


> =item I<$ok> = wait_all(@objects)
>
> Blocks until all of the synchronization I<@objects> are signaled.
> C<wait_all> does not change the state of any object until all the
> objects are signaled. This prevents deadlock, at least between
> competing wait functions.
>
> Returns true on success, false on error. An error occurs if an element
> of I<@objects> is not a synchronization object.


> =head2 Mutexes
> I dropped the lock($scalar) call from this interface in favor of
> Mutexes. The two features provide roughly the same functionality,
> so this is partly a matter style. One possible reason to prefer
> mutexes is to simplify implementation of C<wait_all> and
> C<wait_one>.
On the other hand, a lock($scalar) would provide for an easy way to
automaticly release your mutexes.  Thus, I suggest another primitive:
critical $lock BLOCK, which runs BLOCK with $lock held (with held being
defined as approprate for the $lock).


> =head2 C<die>
>
> I dropped the I<$thread>->C<eval> call from this interface, and didn't
> say what happens if a thread C<die>s. There are several possibilities

> The exception is propagated to any thread that C<join>s it.
> The interpreter prints C<$@> on stderr and exits.
> The thread just quietly goes away.
First off, I think that this is probably best left to the error handling
RFCs and not this one.

That said, however...
I think that the try stack should unwind all the way through the new Thread
call -- that is, that the catches for the block that the thread was started
in should be the ones in question.

If the thread has been join()d, however, we need to do somthing about them.
I'd say that the join() should die in the same way that the thread did; the
reason that join() is named like it is is that you're "joining" the thread
back into the "tapestry" of the program, so the join()d point should behaive
like the original function did.

    -=- James Mastros

Reply via email to