| IO-Lambda documentation | view source | Contained in the IO-Lambda distribution. |
IO::Lambda::Thread - wait for blocking code using threads
The module implements a lambda wrapper that allows to asynchronously wait for
a blocking code. The wrapping is done so that the code is executed in another
thread's context. IO::Lambda::Thread provides bidirectional communication
between threads, that is based on a shared socket between parent and child
threads. The socket can be also used by the caller for its own needs, if necessary
( see IO::Lambda::Message ).
use IO::Lambda qw(:lambda);
use IO::Lambda::Thread qw(threaded);
lambda {
context 0.1, threaded {
sleep(1);
return "hello!";
};
any_tail {
if ( @_) {
print "done: ", $_[0]-> peek, "\n";
} else {
print "not yet\n";
again;
}
};
}-> wait;
A special replacement for thread-> create, that not only creates a
thread, but also creates a socket between the parent and child threads. The
socket is important for getting an asynchronous notification when the child
thread has finished, because there is no portable way to get that signal
otherwise. That means that this socket must be closed and the thread must be
join'ed to avoid problems. For example:
my ( $thread, $reader) = new_thread( $sub {
my $writer = shift;
print $writer, "Hello world!\n";
}, 1 );
print while <$reader>;
close($reader);
$thread-> join;
Note that join is a blocking call, so one needs to be sure that the thread
indeed is finished before joining it. By default, the child thread closes
its side of the socket, thus making the parent side readable. However, the
child code can also hijack the socket for its own needs, so if that
functionality is needed, one must create an extra layer of communication that
ensures that the child code is properly exited, so that the parent can
reliably call join without blocking (see IO::Lambda::Message, that
is destined exactly for this use).
$code is executed in another thread's context, and is passed the communication
socket ( if $pass_socket is set to 1 ). $code is also passed @param.
Data returned from the code can be retrieved from join.
Creates a lambda, that executes $code in a newly created thread.
The lambda finishes when the $code and the thread are finished,
and returns results returned by $code.
Note, that this lambda, if terminate'd between after being started and
before being finished, has no chance to wait for completion of the
associated thread, and so Perl will complain. To deal with that, obtain the
thread object manually and wait for the thread:
my $l = threaded { 42 };
$l-> start;
....
$l-> terminate;
# synchronously
$l-> thread-> join;
# or asynchronously
context $l-> socket;
readable { $l-> thread-> join };
Returns the associated thread object. Valid only for lambdas created with
threaded.
Returns the associated communication socket. Valid only for lambdas created
with threaded.
Threading in Perl is fragile, so errors like the following:
Unbalanced string table refcount: (1) for "GEN1" during global destruction
are due to some obscure Perl bugs. They are triggered, in my experience, when a child thread tries to deallocate scalars that it thinks belongs to that thread. This can be sometimes avoided with explicit cleaning up of scalars that may be visible in threads. For example, calls as
IO::Lambda::clear
and
undef $my_lambda; # or other scalars, whatever
inexplicably hush these errors.
Errors like this
Perl exited with active threads:
1 running and unjoined
0 finished and unjoined
0 running and detached
are triggered when child threads weren't properly joined. Make sure
your lambdas are finished properly. Use env IO_LAMBDA_DEBUG=thread
to find out the details.
This is a known bug, f.ex. http://rt.perl.org/rt3//Public/Bug/Display.html?id=70974
suggests adding the @_ = (); construct at random places as a workaround.
This is a known bug, http://rt.perl.org/rt3/Ticket/Display.html?id=70748 . I observed in on win32 only. No workaround is known however.
AnyEvent doesn't work with threads, so this module most probably won't work too when AnyEvent is selected for IO::Lambda::Loop.
Dmitry Karasik, <dmitry@karasik.eu.org>.
| IO-Lambda documentation | view source | Contained in the IO-Lambda distribution. |