NAME
POE::Session::Multiplex - POE session with object multiplexing
SYNOPSIS
use POE;
use POE::Session::Multiplex;
My::Component->spawn( @args );
$poe_kernel->run;
package My::Component;
sub spawn {
my( $package, @args ) = @_;
POE::Session::Multiplex->create(
package_states => [
$package => [ qw( _start ) ]
'My::Component::Object' =>
[qw( fetch decode back )]
]
args => [ @args ]
);
}
##### To add an object to the session:
my $obj = My::Component::Object->new();
$_[SESSION]->object( $name, $obj );
# or
$_[SESSION]->object_register( name => $name, object => $obj );
##### To remove an object
$_[SESSION]->object_unregister( $name );
##### Address an event to the current object:
my $state = ev"state";
##### To build a session/event tuple addressed to the current object
my $rsvp = rsvp "state";
# this tuple would be useful for getting a response from another session
$poe_kernel->post( $session=>'fetch', $params, rsvp"fetch_back" );
# and in the 'fetch' handler, you could reply with:
my $rsvp = $_[ARG1];
$poe_kernel->post( @$rsvp, $reply );
##### Posting to a specific object from inside the session
$poe_kernel->yield( evo( $name, $state ), @args );
##### Posting to a specific object from outside the session
$poe_kernel->post( evos( $session, $name, $state ), @args );
$poe_kernel->post( $session, evo( $name, $state ), @args );
DESCRIPTION
POE::Session::Multiplex allows you to have multiple object handling event from a single POE::Session.
A standard POE design is to have one POE::Session per object and to address each object using session IDs or aliases. POE::Session::Multiplex takes the oposite approach; there is only one session and each object is addressed by manipulating the event name.
The advantage is that you save the overhead of multiple sessions. While session creation is very fast, the POE kernel garbage collection must continually verify that each session should still be alive. For a system with many sessions this could represent a non-trivial task.
POE::Session::Multiplex provides handy routines to do the event name manipulation. See "HELPER FUNCTIONS".
To make an object available via multiplexing, that object must be registered with the session with "object_register".
Objects pass to the session via object_states
are currently not multiplexed, though their events are available to objects of the same class. This could change in the future.
Event methods
POE::Session::Multiplex makes sure that a given event handler method has been set up for a given object. That is, if you define an event for a certain class, that event is not available for objects of other classes, unless they are descendents of the first class.
For example, a session is created with the following.
POE::Session::Multiplex->create(
# ...
package_states => [
Class1 => [ qw( load save ) ],
Class2 => [ qw( marshall demarshall ) ],
],
# ...
);
Objects of Class1
are only accessible via the load
and save
events and objects of Class2
are only accessible via marshall
and demarshall
, unless Class2
is a sub-class of Class1
.
POE::Session::Multiplex does the same thing with object_states
. UNIVERSAL::isa is used to verify that 2 objects are of the same class.
Examples
When creating a socket factory, we use "ev" to create an event name addressed to the current object:
use POE::Wheel::SocketFactory;
sub open_connection {
my( $self, $params ) = @_[OBJECT, ARG0];
$self->{wheel} = POE::Wheel::SocketFactory->new(
%$params,
SuccessEvent => ev "connected",
FailureEvent => ev "error"
);
}
When sending a request to another session, we use "rsvp" to create an event that is addressed tot he current object and session:
$poe_kernel->post( $session, 'sum',
[ 1, 2, 3, 4 ], rsvp "reply"
);
$session
's sum event handler would then be: sub sum_handler { my( $array, $reply ) = @_[ ARG0, ARG1 ]; my $tot = 0; foreach ( @$array ) { $tot += $_ } $_[KERNEL]->post( @$reply, $tot ); }
This could also have been implemented as:
$poe_kernel->post( $session, 'sum',
[ 1, 2, 3, 4 ], ev "reply"
);
sub sum_handler {
my( $array, $reply ) = @_[ ARG0, ARG1 ];
# ...
$_[KERNEL]->post( $_[SENDER], $reply, $tot );
}
Limits
It is impossible to multiplex events that are sent from the POE kernel. Specifically, _start
, _stop
and _child
can not be multiplexed.
Object Names
POE::Session::Multiplex requires each object to have a name. If you do not supply one when registering an object, the method __name
is called to fetch the name. This is a crude form of meta-object protocol. If your object does not implement the __name
method, a name is generated from the stringised object reference.
Note
This documentation tries to consistently use the proper term 'event' to refer to POE's confusingly named 'state'.
Event Names
Currently POE::Session::Multiplex uses event names of the form NAME->EVENT
to address EVENT
to the object named NAME
. BUT YOU MUST NOT DEPEND ON THIS BEHAVIOUR. It could very well change to EVENT@NAME
or anything else in the future. Please use the event helper functions provided.
METHODS
create
POE::Session::Multiplex->create( @lots_of_stuff );
Creates a new multiplexed POE::Session. No new parameters are defined by POE::Session::Multiplex. Parameters of interest to this module are package_states
and object_states
; they define event -> object method mappings that are also used by POE::Session::Multiplex. Objects referenced in ojbect_states
are currently not multiplexed.
object_register
$_[SESSION]->object_register( $object );
$_[SESSION]->object_register( name => $name,
object => $object,
events => $events
);
Register a new $object
named $name
with the session. Optionally creating POE states in $events
.
- object
-
The object to be registered with the session. Required.
- name
-
The name of the object being registered. If omitted, object_register will attempt to get an object name via a
__name
method call. If this method isn't available, a stringised object reference is used. - events
-
Optional hashref or arrayref of POE events to create. If it is a hashref, keys are POE event names, values are the names of event handler methods.
events => { load => 'load_handler', save => 'save_handler }
If you create POE events with an object, they are available to other objects of the same class. However, they will be removed when this object is unregistered. If you do not want this, use "package_register".
object_get
my $obj = $_[SESSION]->object_get( $name );
Returns the object named $name
.
object_list
my @list = $_[SESSION]->object_list;
Returns a list of names of all the currently registered objects.
object_unregister
$_[SESSION]->object_unregister( $name );
$_[SESSION]->object_unregister( $self );
Unregisters an object. This makes the object unavailable for events. Any POE events created when the object was registered are removed.
object
# Register an object
$_[SESSION]->object( $name => $self, $events );
$_[SESSION]->object( $self, $events );
# Unregister an object
$_[SESSION]->object( $name );
$_[SESSION]->object( $self );
Syntactic sugar for "object_register" or "object_unregister".
package_register
$_[SESSION]->package_register( $package, $events );
Creates the POE events defined in $events
as package methods of $package
. This also makes the events available to all objects of class $package
.
It is not currently possible to unregister a package.
HELPER FUNCTIONS
POE::Session::Multiplex exports a few helper functions for manipulating.
ev
$event = ev "handler";
$poe_kernel->yield( ev"handler" );
Returns an event name that is addressed to a handler of the current object. Obviously may only be called from within a multiplexed event.
evo
$state = evo( $name, "handler" );
$poe_kernel->yield( ev"handler" );
Returns an event name addressed to a handler of the $nameed object. Used when you want to address a specific object.
evs
$poe_kernel->post( evs "handler", @args );
Returns session/event tuple addressed to handler of the current object. Obviously may only be called from within a multiplexed event.
evos
$poe_kernel->post( evos( $session, $name, "handler" ), @args );
Returns session/event tuple addressed to a handler of the $nameed object in $session. Currently syntatic sugar for:
$poe_kernel->post( $session, evo( $name, "handler" ), @args );
rsvp
my $rsvp = rsvp "handler";
Returns an opaque object that may be used to post an event addressed to a handler of the current object. Obviously may only be called from within a multiplexed event.
rsvp
is used by object to create postbacks. You may pass the returned object to other objects or sessions. They reply with:
$poe_kernel->post( @$rsvp, @answer );
FYI, rsvp is from the French Repondez, s'il vous plais. Answer, please in English.
POE::Session::PlainCall
It is unfortunately impossible to have clean multiple inheritance of POE::Session. However, POE::Session::Multiplex is compatible with POE::Session::PlainCall. It does this by checking its inheritance and implementing a few of POE::Session::PlainCall's methods.
If you wish to use both, create a session class as follows:
package My::Session;
use base qw( POE::Session::Multiplex POE::Session::PlainCall );
Then use that class to create your sessions:
My::Session->create(
package_states => [],
args => \@args
);
SEE ALSO
POE and POE::Session for details of POE.
POE::Stage for the final solution
AUTHOR
Philip Gwyn, <gwyn-at-cpan.org>
COPYRIGHT AND LICENSE
Copyright (C) 2009 by Philip Gwyn
This library is free software; you can redistribute it and/or modify it under the same terms as Perl itself, either Perl version 5.8.8 or, at your option, any later version of Perl 5 you may have available.