NAME
IO::Lambda::Thread - wait for blocking code using threads
DESCRIPTION
The module implements a lambda wrapper that allows to asynchronously wait for 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, which is based on a shared socket between parent and child threads. This socket can be used by the caller for its own needs, if necessary.
SYNOPSIS
use IO::Lambda qw(:lambda);
use IO::Lambda::Thread qw(threaded);
lambda {
context 0.1, threaded {
select(undef,undef,undef,0.8);
return "hello!";
};
any_tail {
if ( @_) {
print "done: ", $_[0]-> peek, "\n";
} else {
print "not yet\n";
again;
}
};
}-> wait;
API
- new_thread ( $options = (), $pass_socket, $code, @param) -> ($thread, $socket)
-
A special replacement for
thread-> create
, that not only creates a thread, but also creates a socket between the parent and child threads. That 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 bejoin
'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 might want to be sure that the thread is indeed finished before calling it. By default, the child thread will close 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 will ensure that the child code is properly exited, so that the parent can reliably calljoin
without blocking.$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 fromjoin
. - threaded($code) :: () -> ( @results )
-
Creates a lambda, that will execute
$code
in a newly created thread. The lambda will finish when the$code
and the thread are finished, and will return results returned by$code
.Note, that this lambda, if
terminate
'd after between being started and being finished, will have 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; read { $l-> thread-> join };
- thread($lambda)
-
Returns the associated thread object. Valid only for lambdas created with
threaded
. - socket($lambda)
-
Returns the associated communication socket. Valid only for lambdas created with
threaded
.
BUGS
Threading in Perl is fragile, so errors like the following:
Unbalanced string table refcount: (1) for "GEN1" during global
destruction
are due some hidden 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
strangely 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 properly completed.
SEE ALSO
AUTHOR
Dmitry Karasik, <dmitry@karasik.eu.org>.