POEx::Role::SessionInstantiation.3pm

Langue: en

Autres versions - même langue

Version: 2009-05-29 (debian - 07/07/09)

Section: 3 (Bibliothèques de fonctions)

NAME

POEx::Role::SessionInstantiation - A Moose::Role for plain old Perl objects in a POE context

SYOPSIS

     package My::Class;
     use 5.010;
     use MooseX::Declare;
 
     # using the role instantly makes it a POE::Session upon instantiation
     class My::Class with POEx::Role::SessionInstantiation
     {
         # declared methods are all exposed as events to POE
         sub foo
         {
             my ($self, @args) = @_;
 
             # This event is not only added through POE but also added as a 
             # method to each instance that happens to have 'foo' fired
 
             # Access to POE information is done through the 'poe' accessor
             $self->poe->kernel->state
             (
                 'added_event',
                 sub
                 {
                     say 'added_event has fired'
                 }
             );
 
             # Some sugar to access the kernel's yield method
             # This will push the 'bar' method into POE's event queue
             $self->yield('bar');
         }
 
         sub bar
         {
             my ($self, @args) = @_;
 
             # $self is also safe to pass as a session reference
             # Or you can pass along $self->ID()
             $self->post($self, 'baz')
         }
 
         sub baz
         {
             my ($self, @args) = @_;
 
             # call also works too
             $self->call($self, 'added_event';
         }
     }
 
     1;
 
     # Constructing the session takes all the normal options
     my $session = My::Class->new({ options => { trace => 1 } });
 
     # Still need to call ->run();
     POE::Kernel->run();
 
 

DESCRIPTION

POEx::Role::SessionInstantiation provides a nearly seamless integration for non-POE objects into a POE environment. It does this by handling the POE stuff behind the scenes including allowing per instances method changes, session registration to the Kernel, and providing some defaults like setting an alias if supplied via the attribute or constructor argument, or defining a _default that warns if your object receives an event that it does not have.

This role exposes your class' methods as POE events.

ATTRIBUTES

heap is: rw, isa: Any, default: {}, lazy: yes
A traditional POE::Session provides a set aside storage space for the session context and that space is provided via argument to event handlers. With this Role, your object gains its own heap storage via this attribute.
options is: rw, isa: HashRef, default: {}, lazy: yes
In following the POE::Session API, sessions can take options that do various things related to tracing and debugging. By default, tracing => 1, will turn on tracing of POE event firing to your object. debug => 1, currently does nothing but more object level tracing maybe enabled in future versions.
args is: rw, isa: ArrayRef, default: [], lazy: yes
POE::Session's constructor provides a mechanism for passing arguments that will end up as arguments to the _start event handler. This is the exact same thing.
alias is: rw, isa: Str, clearer: clear_alias, trigger: registers alias
This attribute controls your object's alias to POE. POE allows for more than one alias to be assigned to any given session, but this attribute only assumes a single alias will not attempt to keep track of all the aliases. Last alias set will be what is returned. Calling the clearer will remove the last alias set from POE and unset it. You must be inside a valid POE context for the trigger to actually fire (ie, inside a event handler that has been invoked from POE). While this can be set at construction time, it won't be until _start that it will actually register with POE. If you override _start, don't forget to set this attribute again ( $self->alias($self->alias); ) or else your alias will never get registered with POE.
ID is: ro, isa: Int
This attribute will return what your POE assigned Session ID is. Must only be accessed after your object has been fully built (ie. after any BUILD methods). This ID can be used, in addition to a reference to yourself, and your defined alias, by other Sessions for addressing events sent through POE to your object.
poe is: ro, isa: Object
The poe attribute provides runtime context for your object methods. It contains an anonymous object with it's own attributes and methods. Runtime context is built for each individual event handler invocation and then torn down to avoid context crosstalk. It is important to only access this attribute from within a POE invoked event handler.

POE ATTRIBUTES

sender is: rw, isa: POE::Kernel | POE::Session | ->does(SessionInstant.)
The sender of the current event can be access from here. Semantically the same as $_[+SENDER].
state is: rw, isa: Str
The state fired. This should match the current method name (unless of course within the _default event handler, then it will be the event name that was invoked but did not exist in your object instance.
[qw/file line from/] is: rw, isa: Maybe[Str]
These attributes provide tracing information from within POE. From is actually not used in POE::Session as far as I can tell, but it is available just in case.
kernel is: rw, isa: POE::Kernel
This is actually the POE::Kernel singleton provided as a little sugar instead of requiring use of $poe_kernel, etc. To make sure you are currently within a POE context, check this attribute for definedness.

POE PRIVATE METHODS
clear()
This will clear the all of the current context information.
restore($poe)
This will take another anonymous poe object and restore state.
clone()
This will clone the current anonymous poe object and return it.

METHODS

[qw/post yield call/]
These are provided as sugar for the respective POE::Kernel methods.
_start
Provides a default _start event handler that will be invoked from POE once the Session is registered with POE. The default method only takes the alias attribute and sets it again to activate the trigger. If this is overridden, don't forget to set the alias again so the trigger can execute.
_stop
Provides a default _stop event handler that will be invoked from POE once the Session's refcount from within POE has reached zero (no pending events, no event sources, etc). The default method merely clears out the alias.
_default
Provides a _default event handler to catch any POE event invocations that your instance does not actually have. Will 'warn' about the nonexistent state. A big difference from POE::Session is that the state and arguments are not rebundled upon invocation of this event handler. Instead the attempted state will be available in the poe attribute and the arguments will be pass normally as an array.

METHOD MODIFIERS

after 'BUILD
All of the magic for turning the constructed object into a Session happens in this method. If a BUILD is not provided, a stub exists to make sure this advice is executed.

NOTES

Like all dangerous substances, this Role needs a big fat warning. It should be noted thoroughly that this Role performs some pretty heinous magic to accomplish a polished and consistent transformation of your class into a Session.
PER INSTANCE METHOD CHANGES
This Role enables your /objects/ to have method changes. You read that right. POE allows Sessions to have runtime event handler modification. It is sort of required to support wheels and whatever. Anyhow, to support that functionality class level changes are executed via Moose::Meta::Class to add/change/remove methods as events are added, changed, and removed via POE. But how is that possible, you ask, to make class level changes without affecting all of the other instances? An anonymous clone of the composed class is created and the object is reblessed into that new clone that has changes for each change to the events that occurs. This segregates changes so that they only affect the individual object involved.

This functionality should likely be broken out into its own evil module, but that is a job for another day.

BREAKING POE ENCAPSULATION
POE internally tracks Sessions by their stringified reference. So how do make changes to references, such as reblessing them into different classes, and not break POE? You do some scary crap. Stringification is overloaded (via overload pragma) to return the original string from the instance before changes are made to it and it is reblessed. The original string is stored in the orig attribute. POE also does reference comparisons as well to check if the current session is the same as the one it just got and so != and == are also overloaded to do string comparisons of references. But what about the reference that is already stored by POE? The reference is overwritten in one spot (where POE stores its Sessions) and is done every time an event change takes place.
OVERLOAD PRAGMA IN A ROLE? WTF?
Moose does the right thing, mostly, when it comes to the overload pragma in a Role. The methods defined are composed appropriate, but the magic doesn't make it through the composition. So the magic must be enabled manually. This includes messing with the symbol table of the composed class. This happens inside the after 'BUILD' advice, and also during event handler changes from POE (the anonymous classes need to have the magic enabled each time). So what is the moral to this? If you need to overload "", !=, or == in your composed class things will likely break. You have been warned.

So please heed the warnings and don't blame me if this summons the terrasque into your datacenter and you left your +5 gear at home.

AUTHOR

Copyright 2009 Nicholas Perez. Released and distributed under the GPL.