Browse files

Minor edits to POE and POE::Kernel. Major revisions to POE::Session.

Still nowhere near done, however.
  • Loading branch information...
rcaputo committed Oct 26, 2007
1 parent 2bda6a9 commit 19bfcd5761534d2d0b36a171db4e87c282651e10
Showing with 176 additions and 58 deletions.
  1. +4 −0 lib/
  2. +11 −1 lib/POE/
  3. +161 −57 lib/POE/
@@ -152,6 +152,10 @@ driven task. They also customize event dispatch to a particular
calling convention. POE::NFA, for example, is more of a proper state
machine. CPAN has several other kinds of sessions.
+Everything ultimately builds on these classes or the concepts they
+implement. If you're short on time, the things to read besides this
+are L<POE::Kernel> and L<POE::Session>.
=head2 Layer 2: Wheels, Filters, and Drivers
POE::Wheel objects are dynamic mix-ins for POE::Session instances.
@@ -2521,7 +2521,7 @@ POE::Kernel - an event-based application kernel in Perl
-In the spirit of Perl, there are a lot of other ways to do it.
+In the spirit of Perl, there are a lot of other ways to use POE.
@@ -2534,6 +2534,10 @@ POE::Kernel is not an event loop in itself. For that it uses one of
several available POE::Loop interface modules. See CPAN for modules
in the POE::Loop namespace.
+POE's documentation assumes the reader understands the @_ offset
+constants (KERNEL, HEAP, ARG0, etc.). The curious or confused reader
+will find more detailed explanation in L<POE::Session>.
=head1 USING POE
=head2 Literally Using POE
@@ -2610,6 +2614,12 @@ take exclusive control of a program's time, if necessary.
Every POE-based application needs at least one session. Code cannot
run "within POE" without being a part of some session.
+Sessions in POE::Kernel should not be confused with
+L<POE::Session|POE::Session> even though the two are inextricably
+associated. POE::Session adapts POE::Kernel's dispatcher to a
+particular calling convention. Other POE::Session classes exist on
+CPAN. Some radically alter the way event handlers are called.
=head2 Session Lifespans
"Session" as a term is somewhat overloaded. There are two related
@@ -749,75 +749,188 @@ __END__
=head1 NAME
-POE::Session - an event driven abstract state machine
+POE::Session - the basis for cooperative, event-driven tasks in POE
- # Import POE::Session constants.
- use POE::Session;
+ use POE; # auto-includes POE::Kernel and POE::Session
- # Inline or coderef states.
inline_states => {
- state_one => \&coderef_one,
- state_two => sub { ... },
+ _start => sub { $_[KERNEL]->yield("next") },
+ next => sub {
+ print "tick...\n";
+ $_[KERNEL]->delay(next => 1);
+ },
+ );
+ POE::Kernel->run();
+ exit;
- # Plain and mapped object states.
- object_states => [
- $object_one => [ 'state_three', 'state_four', 'state_five' ],
- $object_two => { state_nine => 'method_nine' },
- ],
+POE::Session can also dispatch to object and class methods through
+object_states and package_states callbacks.
- # Plain and mapped package states.
- package_states => [
- $package_one => [ 'state_six', 'state_seven', 'state_eight' ],
- $package_two => { state_ten => 'method_ten' },
- ],
- # Parameters for the session's _start state.
- args => [ argument_zero, argument_one, ... ],
+POE::Session (and its subclasses) translates events from POE::Kernel's
+generic dispatcher into particular calling conventions suitable for
+application code. In design pattern parlance, POE::Session classes
+are adapters between POE::Kernel and application code.
- # Initial options. See the option() method.
- options => \%options,
+The L<sessions|POE::Kernel/Sessions> that POE::Kernel manages are more
+like generic task structures. Unfortunately these two disparate
+concepts have virtually identical names.
- # Change the session's heap representation.
- heap => [ ],
- );
+The documentation will refer to event handlers as "states" in certain
+unavoidable situations. Sessions were originally meant to be
+event-driven state machines, but their purposes evolved over time.
+Some of the legacy vocabulary lives on in the code for backward
+compatibility, however.
-Other methods:
+Confusingly, L<POE::NFA> is a class for implementing actual
+event-driven state machines. Its documentation uses "state" in the
+proper sense.
- # Retrieve a session's unique identifier.
- $session_id = $session->ID;
+=head1 USING POE::Session
- # Retrieve a reference to the session's heap.
- $session_heap = $session->get_heap();
+POE::Session has two main purposes. First, it maps event names to the
+code that will handle them. Second, it maps a consistent event
+dispatch interface to those handlers.
- # Set or clear session options.
- $session->option( trace => 1, default => 1 );
- $session->option( trace );
+Consider the SYNOPSIS for example. A POE::Session instance is
+created with two C<inline_states>, each mapping an event name
+("_start" and "next") to an inline subroutine. POE::Session ensures
+that $_[KERNEL] and so on are meaningful within an event handler.
- # Create a postback, then invoke it and pass back additional
- # information.
- $postback_coderef = $session->postback( $state_name, @state_args );
- $postback_coderef->( @additional_args );
+Event handlers may also be object or class methods, using
+C<object_states> and C<package_states> respectively. The create()
+syntax is different than for C<inline_states>, but the calling
+convention is nearly identical.
- # Or do the same thing synchronously
- $callback_coderef = $session->callback( $state_name, @state_args );
- $retval = $callback_coderef->( @additional_args );
+Notice that the created POE::Session object has not been saved to a
+variable. The new POE::Session object gives itself to POE::Kernel,
+which then manages it and all the resources it uses.
+It's possible to keep references to new POE::Session objects, but it's
+not usually necessary. And if an application is not careful about
+cleaning up these references, they may leak memory when POE::Kernel
+would normally destroy them.
+=head2 POE::Session's Calling Convention
+The biggest syntactical hurdle most people have with POE is
+POE::Session's unconventional calling convention. For example:
+ sub handle_event {
+ my ($kernel, $heap, $parameter) = @_[KERNEL, HEAP, ARG0];
+ ...;
+ }
+Or the use fo $_[KERNEL], $_[HEAP] and $_[ARG0] inline, as is done
+in most examples.
+What's going on here is rather basic. Perl passes parameters into
+subroutines or methods using the @_ array. KERNEL, HEAP, ARG0 and
+others are constants exported by POE::Session (which is included for
+free when a program uses POE).
+So $_[KERNEL] is an event handler's KERNELth parameter. @_[HEAP,
+ARG0] is a slice of @_ containing the HEAPth and ARG0th parameters.
+While this looks odd, it's perfectly plain and legal Perl syntax. POE
+uses it for a few reasons:
+1. In the common case, passing parameters in @_ is faster than passing
+hash or array references and then dereferencing them in the handler.
+2. Typos in hash-based parameter lists are either subtle runitme
+errors or requires constant runtime checking. Constants are either
+known at compile time, or are clear compile-time errors.
+3. Referencing @_ offsets by constants allows parameters to move
+the future without breaking application code.
+4. Most event handlers don't need all of @_. Slices allow handlers to
+use only the parameters they're interested in.
+=head2 POE::Session Parameters
+Event handlers receive most of their runtime context in up to nine
+callback parameters. POE::Kernel provides many of them.
+=head3 $_[OBJECT]
+POE::Session parameters are positional, so shifting off a $self in a
+method-based handler would invalidate everything else. Since Perl
+provides $self in $_[0] as a rule, OBJECT is always 0 and $_[OBJECT]
+is always $self.
-POE::Session combines a runtime context with an event driven state
-machine. Together they implement a simple cooperatively timesliced
+Inline states have no $self. $_[OBJECT] is undef in this case.
-Sessions receive their timeslices as events from POE::Kernel. Each
-event has two fields, a state name and a session identifier. These
-fields describe the code to run and the context to run it in,
-respectively. Events carry several other fields which will be
-discussed in the "Predefined Event Fields" section.
+It's often useful for method-based event handlers to call other
+methods in the same object. $_[OBJECT] helps this happen.
+=head3 $_[SESSION]
+This is a reference to the session receiving an event. It may be used
+as the destination for a post(), call() or some other POE::Kernel
+method. POE::Session also has some methods of its own.
+=head3 $_[KERNEL]
+The KERNELth parameter is a reference to the application's singleton
+POE::Kernel instance. It is most often used to call POE::Kernel
+methods from event handlers.
+=head3 $_[HEAP]
+Every POE::Session object contains its own variable namespace known as
+the session's HEAP. It is modeled and named after process memory
+heaps (not priority heaps). Heaps are by default anonymous hash
+references, but they may be initialized in create() to be almost
+anything. POE::Session itself never uses $_[HEAP], although some POE
+components do.
+=head3 $_[STATE]
+The STATEth handler parameter contains the name of the event being
+dispatched in the current callback. This can be important since
+there's no enforced correlation between an event name and the name of
+a subroutine or method assigned to be its handler.
+=head3 $_[SENDER]
+Events must come from somewhere. $_[SENDER] contains the currently
+dispatched event's source. This may be identical to $_[KERNEL] in
+events that are generated by POE::Kernel.
+TODO - There are a number of exceptions. Document them? Here or in
+the POE::Kernel methods that generate the exceptional events?
+These parameters are a form of caller(), but they describe where the
+event originated in a program's code. CALLER_FILE and CALLER_LINE are
+fairly plain. CALLER_STATE contains the name of the event that was
+being handled when the event was created, or when the event watcher
+that ultimately created the event was registered.
+=head3 @_[ARG0..ARG9] or @_[ARG0..$#_]
+$_[ARG0] through the end of @_ contain parameters provided by
+application code, event watchers, or higher-level libraries. These
+parameters are guaranteed to be at the end of @_ so that @_[ARG0..$#_]
+will always catch them all.
+$#_ is the index of the last value in @_. Blame Perl if it looks odd.
+It's merely the $#array syntax where the array name is an underscore.
+=head2 Event Handlers are Re-Entrant
+-><- new docs above, old docs below
States are re-entrant since they are invoked with their runtime
contexts. Although it's not usually necessary, this re-entrancy
@@ -1647,15 +1760,6 @@ POE::Session contains a two debugging assertions, for now.
=over 2
-ASSERT_DEFAULT is used as the default value for all the other assert
-constants. Setting it true is a quick and reliably way to ensure all
-Session assertions are enabled.
-Session's ASSERT_DEFAULT inherits Kernel's ASSERT_DEFAULT value unless
Setting ASSERT_STATES to true causes every Session to warn when they

0 comments on commit 19bfcd5

Please sign in to comment.