--- AnyEvent-Fork-RPC/RPC.pm 2013/08/31 16:35:33 1.31 +++ AnyEvent-Fork-RPC/RPC.pm 2016/05/21 07:11:09 1.40 @@ -177,7 +177,7 @@ =head2 Example 2: Asynchronous Backend This example implements multiple count-downs in the child, using -L timers. While this is a bit silly (one could use timers in te +L timers. While this is a bit silly (one could use timers in the parent just as well), it illustrates the ability to use AnyEvent in the child and the fact that responses can arrive in a different order then the requests. @@ -393,7 +393,7 @@ use AnyEvent; -our $VERSION = 1.1; +our $VERSION = 1.22; =item my $rpc = AnyEvent::Fork::RPC::run $fork, $function, [key => value...] @@ -465,7 +465,7 @@ By overriding this you can prolong the life of a RPC process after e.g. the parent has exited by running the event loop in the provided function (or simply calling it, for example, when your child process uses L you -could provide L as C function). +could provide L as C function). Of course, in that case you are responsible for exiting at the appropriate time and not returning from @@ -496,8 +496,10 @@ transferred between the processes. For this, they have to be frozen and thawed in both parent and child processes. -By default, only octet strings can be passed between the processes, which -is reasonably fast and efficient and requires no extra modules. +By default, only octet strings can be passed between the processes, +which is reasonably fast and efficient and requires no extra modules +(the C distribution does not provide these extra +serialiser modules). For more complicated use cases, you can provide your own freeze and thaw functions, by specifying a string with perl source code. It's supposed to @@ -509,16 +511,20 @@ pre-load it into your L process, or you can add a C or C statement into the serialiser string. Or both. -Here are some examples - some of them are also available as global +Here are some examples - all of them are also available as global variables that make them easier to use. =over 4 -=item octet strings - C<$AnyEvent::Fork::RPC::STRING_SERIALISER> +=item C<$AnyEvent::Fork::RPC::STRING_SERIALISER> - octet strings only -This serialiser concatenates length-prefixes octet strings, and is the -default. That means you can only pass (and return) strings containing -character codes 0-255. +This serialiser (currently the default) concatenates length-prefixes octet +strings, and is the default. That means you can only pass (and return) +strings containing character codes 0-255. + +The main advantages of this serialiser are the high speed and that it +doesn't need another module. The main disadvantage is that you are very +limited in what you can pass - only octet strings. Implementation: @@ -527,7 +533,30 @@ sub { unpack "(w/a*)*", shift } ) -=item json - C<$AnyEvent::Fork::RPC::JSON_SERIALISER> +=item C<$AnyEvent::Fork::RPC::CBOR_XS_SERIALISER> - uses L + +This serialiser creates CBOR::XS arrays - you have to make sure the +L module is installed for this serialiser to work. It can be +beneficial for sharing when you preload the L module in a template +process. + +L is about as fast as the octet string serialiser, but supports +complex data structures (similar to JSON) and is faster than any of the +other serialisers. If you have the L module available, it's the +best choice. + +The encoder enables C (so this serialisation method can +encode cyclic and self-referencing data structures). + +Implementation: + + use CBOR::XS (); + ( + sub { CBOR::XS::encode_cbor_sharing \@_ }, + sub { @{ CBOR::XS::decode_cbor shift } } + ) + +=item C<$AnyEvent::Fork::RPC::JSON_SERIALISER> - uses L or L This serialiser creates JSON arrays - you have to make sure the L module is installed for this serialiser to work. It can be beneficial for @@ -545,7 +574,7 @@ sub { @{ JSON::decode_json shift } } ) -=item storable - C<$AnyEvent::Fork::RPC::STORABLE_SERIALISER> +=item C<$AnyEvent::Fork::RPC::STORABLE_SERIALISER> - L This serialiser uses L, which means it has high chance of serialising just about anything you throw at it, at the cost of having @@ -560,7 +589,7 @@ sub { @{ Storable::thaw shift } } ) -=item portable storable - C<$AnyEvent::Fork::RPC::NSTORABLE_SERIALISER> +=item C<$AnyEvent::Fork::RPC::NSTORABLE_SERIALISER> - portable Storable This serialiser also uses L, but uses it's "network" format to serialise data, which makes it possible to talk to different @@ -585,7 +614,8 @@ =cut our $STRING_SERIALISER = '(sub { pack "(w/a*)*", @_ }, sub { unpack "(w/a*)*", shift })'; -our $JSON_SERIALISER = 'use JSON (); (sub { JSON::encode_json \@_ }, sub { @{ JSON::decode_json shift } })'; +our $CBOR_XS_SERIALISER = 'use CBOR::XS (); (sub { CBOR::XS::encode_cbor_sharing \@_ }, sub { @{ CBOR::XS::decode_cbor shift } })'; +our $JSON_SERIALISER = 'use JSON (); (sub { JSON::encode_json \@_ }, sub { @{ JSON::decode_json shift } })'; our $STORABLE_SERIALISER = 'use Storable (); (sub { Storable::freeze \@_ }, sub { @{ Storable::thaw shift } })'; our $NSTORABLE_SERIALISER = 'use Storable (); (sub { Storable::nfreeze \@_ }, sub { @{ Storable::thaw shift } })'; @@ -631,7 +661,7 @@ my $module = "AnyEvent::Fork::RPC::" . ($arg{async} ? "Async" : "Sync"); $self->require ($module) - ->send_arg ($function, $arg{init}, $serialiser, $arg{done} || "CORE::exit") + ->send_arg ($function, $arg{init}, $serialiser, $arg{done} || "$module\::do_exit") ->run ("$module\::run", sub { $fh = shift; @@ -755,6 +785,12 @@ See the examples section earlier in this document for some actual examples. +Note: the event data, like any data send to the parent, might not be sent +immediatelly but queued for later sending, so there is no guarantee that +the event has been sent to the parent when the call returns - when you +e.g. exit directly after calling this function, the parent might never +receive the event. + =back =head2 PROCESS EXIT @@ -788,7 +824,7 @@ listens for another request by the parent, it might detect that the socket was closed (e.g. because the parent exited). It will sotp listening for new requests and instead try to write out any remaining data (if any) or -simply check whether the socket cna be written to. After this, the RPC +simply check whether the socket can be written to. After this, the RPC process is effectively done - no new requests are incoming, no outstanding request data can be written back. @@ -798,8 +834,9 @@ continue. This is why the asynchronous backend explicitly calls C when -it is done (it will raise an exception under other circumstances, which -might lead to the process not exiting on it's own). +it is done (under other circumstances, such as when there is an I/O error +and there is outstanding data to write, it will log a fatal message via +L, also causing the program to exit). You can override this by specifying a function name to call via the C parameter instead. @@ -868,7 +905,8 @@ problems. Alternatively, the parent could limit the amount of rpc calls that are outstanding. -Blocking use of condvars is not supported. +Blocking use of condvars is not supported (in the main thread, outside of +e.g. L threads). Using event-based modules such as L, L, L and so on is easy. @@ -944,7 +982,7 @@ =head1 EXCEPTIONS There are no provisions whatsoever for catching exceptions at this time - -in the child, exeptions might kill the process, causing calls to be lost +in the child, exceptions might kill the process, causing calls to be lost and the parent encountering a fatal error. In the parent, exceptions in the result callback will not be caught and cause undefined behaviour.