|
NAMEPOE::Component::Generic - A POE component that provides non-blocking access to a blocking object. SYNOPSIS use POE::Component::Generic;
my $telnet = POE::Component::Generic->spawn(
# required; main object is of this class
package => 'Net::Telnet',
# optional; Options passed to Net::Telnet->new()
object_options => [ ],
# optional; You can use $poco->session_id() instead
alias => 'telnet',
# optional; 1 to turn on debugging
debug => 1,
# optional; 1 to see the child's STDERR
verbose => 1,
# optional; Options passed to the internal session
options => { trace => 1 },
# optional; describe package signatures
packages => {
'Net::Telnet' => {
# Methods that require coderefs, and keep them after they
# return.
# The first arg is converted to a coderef
postbacks => { option_callback=>0 }
},
'Other::Package' => {
# only these methods are exposed
methods => [ qw( one two ) ],
# Methods that require coderefs, but don't keep them
# after they return
callbacks => [ qw( two ) ]
}
}
);
# Start your POE session, then...
$telnet->open( { event => 'result' }, "rainmaker.wunderground.com");
# result state
sub result {
my ($kernel, $ref, $result) = @_[KERNEL, ARG0, ARG1];
if( $ref->{error} ) {
die join(' ', @{ $ref->{error} ) . "\n";
}
print "connected: $result\n";
}
# Setup a postback
$telnet->option_callback( {}, "option_back" );
# option_back state
sub option_back {
my( $obj, $option, $is_remote,
$is_enabled, $was_enabled, $buf_position) = @_[ARG0..$#_];
# See L<Net::Telnet> for a discussion of the above.
# NOTE: Callbacks and postbacks can't currently receive objects.
}
# Use a callback
# Pretend that $other was created as a proxy to an Other::Package object
$other->two( {}, sub { warn "I was called..." } );
my $code = $session->postback( "my_state" );
$other->two( {}, $code );
DESCRIPTIONPOE::Component::Generic is a POE component that provides a non-blocking wrapper around any object. This allows you to build a POE component from existing code with minimal effort. The following documentation is a tad opaque and complicated. This is unavoidable; the problem POE::Component::Generic solves is complicated. POE::Component::Generic works by forking a child process with POE::Wheel::Run and creating the blocking object in the child process. Method calls on the object are then serialised and sent to the child process to be handled by the object there. The returned value is serialised and sent to the parent process, where it is posted back to the caller as a POE event. Communication is done via the child's "STDIN" and "STDOUT". This means that all method arguments and return values must survive serialisation. If you need to pass coderefs or other data that can't be serialised, use "callbacks" or "postbacks". If you want to have multiple objects within a single child process, you will have to create "factories" that create the objects. Method calls are wrapped in "eval" in the child process so that errors may be propagated back to your session. See "OUTPUT". Output to "STDERR" in the child, that is from your object, is shown only if "debug" or "verbose" is set. "STDOUT" in the child, that is from your object, is redirected to STDERR and will be shown in the same circomstances. METHODSspawn my $obj = POE::Component::Generic->spawn( $package );
my $obj = POE::Component::Generic->spawn( %arguments );
Create the POE::Component::Generic component. Takes either a single scalar, which is assumed to be a package name, or a hash of arguments, of which all but "package" are optional.
shutdownShut the component down, doing all the magic so that POE may exit. The child process will exit, causing "DESTROY" to be called on your object. The child process will of course wait if the object is in a blocking method. It is assumed that your object won't prevent the child from exiting. If you want your object to live longer (say for some long-running activity) please fork off a grand-child. Shutdown that this is also a POE event, which means you can not call a method named 'shutdown' on your object. Shuting down if there are responses pending (see "OUTPUT" below) is undefined. Calling "shutdown" will not cause the kernel to exit if you have other components or sessions keeping POE from doing so. kill$generic->kill(SIGNAL) Sends sub-process a "SIGNAL". You may send things like SIGTERM or SIGKILL. This is a violent way to shutdown the component, but is necessary if you want to implement a timeout on your blocking code. session_idTakes no arguments, returns the POE::Session ID of the component. Useful if you don't want to use aliases. METHOD CALLSThere are 4 ways of calling methods on the object. All methods need a data hashref that will be handed back to the return event. This data hash is discussed in the "INPUT" section. postPost events to the object. First argument is the event to post, second is the data hashref, following arguments are sent as arguments in the resultant post. $poe_kernel->post( $alias => 'open',
{ event => 'result' }, "localhost" );
This will call the "open" method on your object with one parameter: "localhost". The method's return value is posted to "result" in the current session. yieldThis method provides an alternative object based means of asynchronisly calling methods on the object. First argument is the method to call, second is the data hashref (described in "INPUT"), following arguments are sent as arguments to the resultant post. $generic->yield( open => { event => 'result' }, "localhost" );
callThis method provides an alternative object based means of synchronisly calling methods on the object. First argument is the event to call, second is the data hashref (described in "INPUT"), following arguments are following arguments are sent as arguments to the resultant call. $generic->call( open => { event => 'result' }, "localhost" );
Call returns a request ID which may be matched with the response. NOT IMPLEMENTED. The difference between call and yield is that call by-passes POE's event queue and the request is potentially sent faster to the child process. psuedo-methodAll methods of the object can also be called directly, but the first argument must be the data hashref as noted in the "INPUT" section. $generic->open( { event => 'opened' }, "localhost" );
INPUTEach method call requires a data hashref as it's first argument. The data hashref may have the following keys.
Note that at some point in the future this data hashref is going to be a full object for better encapsulation. OUTPUTYou may specify a response event for each method call. "ARG0" of this event handler contains the data hashref. "ARG1..$#_" are the returned values, if any.
SUB-CLASSINGIt might be desirable to overload the following methods in a sub-class of POE::Component::Generic. __is_method_name sub __is_method_name {
my( $package, $pk, $sub ) = @_;
# ...
}
Must return true if $sub is a valid object method of $pk. Must return false otherwise. Method names are verified when a package specified with "spawn"'s "packages" argument is scanned for methods. The default implementation tries to reject constants ($sub ending in non-uppercase), private methods ($sub begining with "_") and common subroutines (ie, Carp). HELPER METHODSThese methods will help you writing components based on POE::Component::Generic. Argument processingCallbacks and postbacks expect the arguments are in order. This is a pain for your users and isn't really the POE-way. Instead, your method may accept a hash, and then convert it into the argument list. For a given event FOO, there are 2 possible arguments:
You may use the following 2 methods to help convert the arguments into the appropriate type for a given situaion. They return undef() if the argument isn't present. This so you may use the following idiom and it will Just Work: sub method {
my( $self, %args ) = @_;
my @args;
foreach my $ev ( qw(Stdin Stdout Close) ) {
push @args, $self->__postback_argument( $ev, \%args );
}
$self->true_method( @args );
}
__callback_argumentmy $coderef = $self->__callback_argument( $event, \%args ); Converts argument into a coderef appropriate for "callbacks". Returns "$args{ "${event}Sub" }" if present. If present, converts "$args{ "${event}Event" }" to a coderef and returns that. Returns undef() otherwise. __postback_argumentConverts argument into a POE event call appropriate for "postbacks". Returns "$args{ "${event}Event" }" if present. If present, converts "$args{ "${event}Sub" }" to a state of the current session and returns a call to that. NOT YET IMPLEMENTED. Returns undef() otherwise. STATUSFor your comfort and conveinence, the child process updates $O to tell you what it is doing. On many systems, $O is available via "/proc/$PID/cmdline". AUTHORPhilip Gwyn <gwyn-at-cpan.org> Based on work by David Davis <xantus@cpan.org> SEE ALSOPOE RATINGPlease rate this module. <http://cpanratings.perl.org/rate/?distribution=POE-Component-Generic> BUGSProbably. Report them here: <http://rt.cpan.org/NoAuth/ReportBug.html?Queue=POE%3A%3AComponent%3A%3AGeneric> CREDITSBinGOs for POE::Component::Win32::Service that helped xantus get started. David Davis for POE::Component::Net::Telnet on which this is originally based. COPYRIGHT AND LICENSECopyright 2006-2009,2011 by Philip Gwyn; Copyright 2005 by David Davis and Teknikill Software. This library is free software; you can redistribute it and/or modify it under the same terms as Perl itself.
|