--- AnyEvent-MP/MP.pm 2009/10/01 13:19:03 1.96 +++ AnyEvent-MP/MP.pm 2009/10/06 01:31:22 1.101 @@ -32,11 +32,23 @@ # create a port on another node my $port = spawn $node, $initfunc, @initdata; + # destroy a prot again + kil $port; # "normal" kill + kil $port, my_error => "everything is broken"; # error kill + # monitoring mon $localport, $cb->(@msg) # callback is invoked on death mon $localport, $otherport # kill otherport on abnormal death mon $localport, $otherport, @msg # send message on death + # temporarily execute code in port context + peval $port, sub { die "kill the port!" }; + + # execute callbacks in $SELF port context + my $timer = AE::timer 1, 0, psub { + die "kill the port, delayed"; + }; + =head1 CURRENT STATUS bin/aemp - stable. @@ -145,12 +157,12 @@ use base "Exporter"; -our $VERSION = $AnyEvent::MP::Kernel::VERSION; +our $VERSION = 1.21; our @EXPORT = qw( NODE $NODE *SELF node_of after configure - snd rcv mon mon_guard kil psub spawn cal + snd rcv mon mon_guard kil psub peval spawn cal port ); @@ -438,12 +450,52 @@ $port } +=item peval $port, $coderef[, @args] + +Evaluates the given C<$codref> within the contetx of C<$port>, that is, +when the code throews an exception the C<$port> will be killed. + +Any remaining args will be passed to the callback. Any return values will +be returned to the caller. + +This is useful when you temporarily want to execute code in the context of +a port. + +Example: create a port and run some initialisation code in it's context. + + my $port = port { ... }; + + peval $port, sub { + init + or die "unable to init"; + }; + +=cut + +sub peval($$) { + local $SELF = shift; + my $cb = shift; + + if (wantarray) { + my @res = eval { &$cb }; + _self_die if $@; + @res + } else { + my $res = eval { &$cb }; + _self_die if $@; + $res + } +} + =item $closure = psub { BLOCK } Remembers C<$SELF> and creates a closure out of the BLOCK. When the closure is executed, sets up the environment in the same way as in C callbacks, i.e. runtime errors will cause the port to get Ced. +The effect is basically as if it returned C<< sub { peval $SELF, sub { +BLOCK } } >>. + This is useful when you register callbacks from C callbacks: rcv delayed_reply => sub { @@ -729,8 +781,8 @@ then the callback will be called without any arguments after the time-out elapsed and the port is Ced. -If no time-out is given, then the local port will monitor the remote port -instead, so it eventually gets cleaned-up. +If no time-out is given (or it is C), then the local port will +monitor the remote port instead, so it eventually gets cleaned-up. Currently this function returns the temporary port, but this "feature" might go in future versions unless you can make a convincing case that @@ -789,7 +841,8 @@ Erlang relies on special naming and DNS to work everywhere in the same way. AEMP relies on each node somehow knowing its own address(es) (e.g. by -configuration or DNS), but will otherwise discover other odes itself. +configuration or DNS), and possibly the addresses of some seed nodes, but +will otherwise discover other nodes (and their IDs) itself. =item * Erlang has a "remote ports are like local ports" philosophy, AEMP uses "local ports are like remote ports". @@ -824,9 +877,9 @@ =item * Erlang suffers from silent message loss, AEMP does not. -Erlang makes few guarantees on messages delivery - messages can get lost -without any of the processes realising it (i.e. you send messages a, b, -and c, and the other side only receives messages a and c). +Erlang implements few guarantees on messages delivery - messages can get +lost without any of the processes realising it (i.e. you send messages a, +b, and c, and the other side only receives messages a and c). AEMP guarantees correct ordering, and the guarantee that after one message is lost, all following ones sent to the same port are lost as well, until