Skip to content
Browse files

Revised all the manpages. Split the manpages into separate PODs, and

put them at the end of each module.  Rewnote the POE.pm overview,
added some ASCII art, and threw away the "Design Goals" and related
hype.  Removed POE-TODO and POE-HINTS manpages.

Updated the README to be more readable.  Moved the mailing list and
web site information there.  Should either or both change, stale
information won't rot in a thousand manpages around the world.

Removed design notes from the ends of Kernel and Session, because docs
go there now.  Moved them to POE-TODO, which is now not included.

&POE::Session::create was broken-- I'm not sure how it worked to begin
with.  Fixed.

Revised the POE::Filter::HTTPD documentation to follow the rest of the
manpages' format.

(!!!) Minor interface change.  &POE::Session::option can now fetch
session option values without changing or deleting them in the
process.
  • Loading branch information...
1 parent 27516fe commit 0d6f19d18ff40a0e3d8413649e3522260899384a @rcaputo committed Jun 15, 1999
View
26 Changes
@@ -7,8 +7,8 @@ Changes marked with "(!!!)" may break backward compatibility.
Versions with "_xx" subversions are internal test releases.
-0.06_09 1999.06.??
-------------------
+0.06_09 1999.06.?? (!!!)
+------------------------
Updated samples/*sessions.perl to test $kernel->state(...) and
discovered that the documentation was wrong about this function.
@@ -20,6 +20,28 @@ package and object sessions.
Made POE::Session an array reference, as part of the reorganization of
POE's internals.
+Revised all the manpages. Split the manpages into separate PODs, and
+put them at the end of each module. Rewnote the POE.pm overview,
+added some ASCII art, and threw away the "Design Goals" and related
+hype. Removed POE-TODO and POE-HINTS manpages.
+
+Updated the README to be more readable. Moved the mailing list and
+web site information there. Should either or both change, stale
+information won't rot in a thousand manpages around the world.
+
+Removed design notes from the ends of Kernel and Session, because docs
+go there now. Moved them to POE-TODO, which is now not included.
+
+&POE::Session::create was broken-- I'm not sure how it worked to begin
+with. Fixed.
+
+Revised the POE::Filter::HTTPD documentation to follow the rest of the
+manpages' format.
+
+(!!!) Minor interface change. &POE::Session::option can now fetch
+session option values without changing or deleting them in the
+process.
+
0.06_08 1999.05.30
------------------
View
3 MANIFEST
@@ -2,10 +2,7 @@
Changes
MANIFEST
Makefile.PL
-POE-HINTS.pod
-POE-TODO.pod
POE.pm
-POE.pod
POE/Curator.pm
POE/Driver.pm
POE/Driver/SysRW.pm
View
148 README
@@ -1,85 +1,92 @@
$Id$
-APOLOGIES
-=========
-
-Version 0.06 breaks backward compatibility in several small but
-fundamental ways. As a result, programs written in earlier versions
-will not work correctly.
+TABLE OF CONTENTS
+=================
-These changes were not made lightly. They are the product much
-discussion, testing and benchmarking. I regret needing to make them,
-but I believe they have improved version 0.06 and helped shape POE's
-future for the better.
-
-Please accept my deepest apologies for breaking your code.
+Table of Contents; About POE; Compatibility (Non-Requirements and
+Requirements); Availability; Support Resources; Installing and Testing
ABOUT POE
=========
-POE is an acronym for Perl Object Environment.
-
-POE is a programming framework for event-driven state machines.
+"POE" is an acronym for Perl Object Environment.
-POE is a high-level, functional interface to select, alarm and IPC.
+First and foremost, it is a programming framework for event-driven
+state machines.
-POE is a cooperative multi-threading model, written only in Perl.
+POE includes high-level, functional interfaces for select, alarms,
+sockets and file I/O. The interfaces are robust but incomplete.
-POE is a component architecture.
+From different vantage points, POE may look like other things:
-POE does many things. The sample programs in the tests directory only
-begin to scratch the surface.
+ It may seem to be a cooperative multithreading model.
+ It may be interpreted as a portable component architecture.
-Despite all this, POE is actually pretty simple. It starts with a
-basic premise and builds upon it. Most of the things POE are, are
-just different ways of looking at it.
+Because it implements a low-level programming concept, POE can do many
+things.
COMPATIBILITY
=============
-POE has been tested with Perl 5.004_04, 5.005_02, 5.005_53 and
-5.005_54 on Linux, FreeBSD, HP-UX, Solaris7, and OS/2. For more
-detailed compatibility information, please see
-<http://www.connect.net/gbarr/cpan-test/by-dist/POE.html>.
+POE has been tested with as many Perl versions as the author (and
+testing pool) can find. It is known to work with older Perl versions,
+back to 5.004_03 (maybe earlier). It should also work with the latest
+stable release (the latest development release may also work). For
+the most recent compatibility results, see
+<http://www.perl.org/cpan-testers/results.cgi?request=dist&dist=POE>.
-As of this writing, POE does not work on Windows platforms. This has
-been traced to differences between Windows' and the rest of the
-world's ioctl and select calls.
+As of this writing, Windows seems to have broken ioctl constants, and
+its select returns strange values. POE should work on sufficiently
+POSIX systems, but Windows doesn't appear to be one of them.
-POE is suspected to work on MacOS. If someone could confirm or deny
+MacOS is suspected to support POE. If someone could confirm or deny
this, it would be greatly appreciated.
+Please let me or the list know if any of this is wrong. Thanks!
+
CPAN.pm will ensure that you have up-to-date copies of all the modules
-POE uses, even if you don't need them.
+POE uses. I'm not sure whether to consider this a bug or a feature,
+since most of POE's module requirements are only advisory.
+
Non-requirements:
+-----------------
+
+POE is compatible with fork(), but it is not used. This distribution
+includes a sample server that uses a pool of forked children.
-POE is compatible with fork(), but it doesn't require it.
+POE will use Time::HiRes, if it's available. Nothing untoward should
+happen if it's not.
+
+POE currently doesn't use XS modules, so you don't need a C compiler.
-If Time::HiRes is available, POE will use it to support
-high-resolution event timing. Nothing untoward happens if it's not.
Requirements:
+-------------
+
+For portability, POE uses POSIX system calls and constants. There
+should be no problem running it on systems that have sufficient POSIX
+support.
-POE uses POSIX for portability.
+Some of POE's sample programs require a recent IO bundle, but you get
+that for free with recent versions of Perl.
-Some of POE's tests require a recent IO bundle, but you get that for
-free with recent versions of Perl.
+Filter::Reference requires either Storable, FreezeThaw or some other
+freeze/thaw package. Storable tends to be fastest.
-If you plan on using Filter::Reference, you'll also need either
-Storable or FreezeThaw so it can freeze and thaw data between systems.
-Storable tends to be faster.
+Filter::HTTPD requires a small world of modules: HTTP::Status;
+HTTP::Request; HTTP::Date and URI::URL.
-If you plan on using Filter::HTTPD, you'll need a small world of
-modules to go with it: HTTP::Status; HTTP::Request; HTTP::Date; and
-URI::URL.
+The httpd.perl sample program uses Filter::HTTPD, which uses all that
+other stuff.
-tests/httpd.perl uses Filter::HTTPD, which uses all that other stuff.
+The preforkedserver.perl sample program uses fork(), which may not be
+available on your planet.
-tests/preforkedserver.perl uses fork(), which may not be available on
-your planet.
+Other sample programs may require other modules, but the required
+modules aren't required if you don't require those specific features.
AVAILABILITY
@@ -91,30 +98,39 @@ The latest stable release of POE is available three ways:
In the /authors/id/R/RC/RCAPUTO/ on your favorite CPAN mirror.
- Or at <http://www.cpan.org/authors/id/R/RC/RCAPUTO/>, if you don't
- have a favorite CPAN mirror.
+ If you don't have a favorite CPAN mirror, you really ought to pick
+ one. You can download and manually install the latest stable POE
+ from <http://www.cpan.org/authors/id/R/RC/RCAPUTO/> until then.
Beta versions of the next release are available from the author. They
-tend to be mostly stable.
+tend to be mostly stable, and other module and program authors tend to
+use them because they're incrementally better than what's on the CPAN.
+
+
+SUPPORT RESOURCES
+=================
+Places on the Internet where you can find more information about POE:
-CREDITS
-=======
+POE has a mailing list thanks to Arturn Bergman. You may subscribe to
+it by sending e-mail:
-Thanks to Artur Bergman <artur@vogon-solutions.com> (sky) for many
-useful suggestions and contributions. He has had a hand in the design
-and/or implementation of most of POE's improvements.
+ From: (the address to which you want your mail sent)
+ To: majordomo@vogon.se
+ Subject: (anything will do)
-Thanks to Dave Paris <dparis@w3works.com> (a-mused) for benchmark
-results, testing, feedback and suggestions. Version 0.06 runs much
-better under high loads thanks to his efforts.
+ subscribe poe
-Thanks to Robert Seifer (Crimson) for extreme debugging beyond the
-call of duty. And sanity.
+All forms of feedback are welcome.
-GETTING STARTED
-===============
+POE has a web site thanks to Johnathan Vail. The latest POE
+development snapshot, along with the Changes file and some other stuff
+can be found at <http://www.newts.org/~troc/>.
+
+
+INSTALLING AND TESTING
+======================
If you've been using POE since before 0.06, please, PLEASE read the
Changes file before installing. Many things have been broken between
@@ -126,12 +142,14 @@ To build and test this distribution, type:
make
make test
-Actually, 'make test' doesn't do anything important. The real tests
-exist within the tests directory, and just happen to be examples of
-how to use different parts of POE.
+Actually, 'make test' doesn't do anything important. The closest
+thing to real tests are the programs in the 'samples' directory.
+These show how to use various bits of POE, exercising each as a side
+effect.
Once everything looks good, POE can be installed by typing:
make install
+
-- Rocco Caputo / troc@netrus.net / Thank you for reading.
View
15 docs/POE-HINTS.outline
@@ -4,6 +4,21 @@ POE-HINTS - POE Hints
These are hints for using POE. It's sort of like a faq, only without
the questions.
+**Events and Things
+Events and event-like things can be confusing. Here are some gotchas
+people have noted.
+
+***Event Names vs. Code References
+The difference between code references and event names may at first be
+confusing. There have been reports of people trying to use them
+interchangeably, causing lots of mental pain when it doesn't work.
+
+Just about the only time a code reference is needed is when states are
+defined. After that, states should almost always be referenced by
+event name.
+
+Uh, this doesn't sound very convincing. I should probably go into it
+in a little more detail in the next revision.
**Session Resources
Session resources are things that the session and/or kernel manage
with high-level functions. These include alarms, selects and aliases.
View
222 docs/POE-TODO.outline
@@ -5,6 +5,9 @@ This is the author's wish-list and personal event queue. It's
included in the POE distribution so that others may read it and
comment on it.
+Actually, it's starting to turn into a crufty old list of ideas and
+some junk. So is the main POE manpage... time to revise!
+
Rocco plans get around to everything (within reason), eventually, but
the general convention is that whoever needs a feature first has dibs
on implementing it.
@@ -27,10 +30,16 @@ How do you start?
**High-Precedence Development Methodology Changes
***Rewrite the docs
***Move to CVS
+In progress. I'm comfortable with CVS on a personal level. The next
+step is to open it for anonymous updates. After that, set up author
+accounts.
***Split PODs back up, and put them in their respective files
+This should go along with "rewrite the docs".
***Lots of stuff doesn't make sense right now.
+Like this heading. What did I mean by that?
**Short-Term Core Features & Fixes
***Announce 0.06
+Oops... time to announce 0.07 :/
***Fix functions to test for C�undef� B�or� C�@_==1�
***If no B�ErrorState�, wheels should C�warn� with C�$!�
***Consolidate B�FailureState� and B�ErrorState�.
@@ -47,11 +56,11 @@ Also, from <http://osm7.cs.byu.edu/~eric/allegro.html>:
OSA has concepts to formalize just about everything one needs to model
a real world situation. Although OSA is an "integrated" modeling
scheme, that is all the parts work together, it can conveniently be
-seen as consisting of three parts: ORM, OBM, and OIM.
+seen as consisting of three parts: ORM, OBM, and OIM.
-ORM - Object-Relationship Model
-OBM - Object-Behavior Model
-OIM - Object-Interaction Model
+ORM = Object-Relationship Model
+OBM = Object-Behavior Model
+OIM = Object-Interaction Model
***POE::Simple
Leolo suggests POE::Simple::(Server|Client|Proxy), which would be
stratospheric-level interfaces to extremely common tasks. "Contrast
@@ -65,27 +74,34 @@ see is that contributions are more than just modules:
***POE::App
Stand-alone applications. POE itself would never include stand-alone
applications.
-***POE::Module
-Modules would be stand-alone "daemon" sessions that can be referred to
-by name. I suppose, to keep modules from stoping on each-other, the
-internal session name should be the same as the package name.
-
-Sean Puckett suggests that POE::Module plug-ins have a function that
-lets people/programs query what they can do, similar to CORBA or COM
-objects. That will let programs grok what they're capable of and
+***POE::Component
+It looks like POE::Component is the standard namespace chunk for
+third-party "black box" components. Sort of like Visual Age "parts",
+or Java "beans".
+
+The first one is POE::Component::IRC, which I really really need to
+look at.
+
+Sean Puckett suggests that POE::Components plug-ins have a function
+that lets people/programs query what they can do, similar to CORBA or
+COM objects. That will let programs grok what they're capable of and
dynamically link themselves to the modules they contain. Sounds neat;
I hope it's doable.
***Other types of contributions
-Filters, Drivers and Wheels. Where would they go?
-
-Would they all be incorporated into POE's "core" distribution? It may
-be time to back out a level and make "POE" a bundle. Others can then
-contribute into the POE packages without their code being in "POE"
-itself.
+Filters, Drivers and Wheels. Where would they go? As long as there
+are corresponding test programs, I can absorb them into the core
+distribution. Bigger ones may need to stay separate. If the
+interface and behavior is defined well enough, I can maintain them
+myself. With CVS, authors can support their own bits within the core
+distribution.
+
+Come to think of it, with CVS, everything could be maintained in one
+big, happy bundle. A monolithic distribution could turn people away,
+so maybe not...
***On the other hand
Then again, does it really matter? POE::App is just other peoples'
-programs, with a dependence on POE. POE::Module still is useful as a
-place for people to contribute hot-pluggable things.
+programs, with a dependence on POE. POE::Component still is useful as
+a place for people to contribute hot-pluggable things.
**Core Ideas Being Considered
***A new paradigm for driver/filter/wheel
Randal has a lot to say about SocketFactory:
@@ -127,7 +143,12 @@ Randal has a lot to say about SocketFactory:
This seems to mesh with the concept of chained filters, but it
addresses some things that haven't yet been considered. I have been
-asked to consider "SysV pushed drivers" and Unix streams.
+asked to consider "SysV pushed drivers" and Unix streams, and
+eventually I will.
+
+Wheels may become depreciated if the streams idea works better. At
+that point, I'll try to make Wheels an interface to Streams, and port
+everything over.
***Pre-defined state transition tables
Crimson mentioned something in kermit called "WART". My
interpretation of this is a yy-like table of state transitions
@@ -190,6 +211,9 @@ Add a constructor parameter and a method for specifying newlines.
Will need a way to submit regexps or multiple line separators, to
support the default case of having lots of different newlines to deal
with.
+
+Perhaps this would be better as a Filter::Record, with the option to
+accept fixed-width and terminated variable width records.
***%SIGNAL tied hash
This will emulate %SIG, but in a POE way. This will fabricate an
event name, register the coderef as a handler for it, and set sig(HUP)
@@ -226,9 +250,8 @@ have its uses.
While I can't justify remote signal() and state(), remote alarm() is
harmless enough. But who gets the $alarm_id?
-
***Automated Test Suite
-It's becoming unfun to run tests/*.perl before each release.
+It's becoming unfun to run samples/*.perl before each release.
***redo the Session::option(default)
1 = "internal" events; 2 = "user" events; 3 = all events
***Non-blocking DNS
@@ -262,6 +285,10 @@ This will work like Filter::Stream, but individual C
be kept separate. The actual implementation is still unknown; it may
stream data prepended by "chunk" lengths, or it may expect to work
with datagram sockets. There may be options for each.
+
+Or Filter::Record, which was discussed earlier in this document.
+Record could be either fixed-width (block) or variable-width
+(terminated).
***Add a Kernel function to list active sessions.
Taken care of by kernel hooks/extensions?
***Add a Kernel function to acquire details about a session.
@@ -373,6 +400,10 @@ has a working prototype of a multi-protocol chat server. IRC users
can "/server nexi.com 1617", then "/join #main" (channels aren't in
yet); telnet/mud users can connect to "nexi.com 1618". Everyone
shares the same chat stream, and 'web support will be on the way.
+
+Fimmtiu is the author of Net::IRC. He has been working on
+POE::Component::IRC, and the new module has entered limited beta
+testing (as of 6/4/1999).
**Module Ideas Being Considered
***Authentication API
Artur suggests that an API be defined so that diverse servers within a
@@ -388,8 +419,12 @@ cleartext passwords.
****SMTP server
****NNTP client
****NNTP server
+****Everything
+Implement the entire suite of Internet protocols. This could take
+some time....
***Extensions
-Artur has made excellent progress with kernel extensions.
+Artur has made excellent progress with kernel extensions. They aren't
+ready for public consumption, however.
Extensions (perhaps POE::Extension, or just a special kind of
POE::Module) are POE modules that register kernel hooks. They are, in
@@ -474,7 +509,8 @@ remote kernel lookup, for instance?
Artur has made excellent progress on system statistics, primarily as
an extension.
***POE::Module::Cron
-Artur says he's working on it.
+Artur says he's working on it. New alarm semantics may move most of
+the functionality into the Kernel.
***POE::Module::At
Listed for completeness.
**Wild Ideas
@@ -668,10 +704,6 @@ Anyway, here's the e-mail message:
AutoPOE would implement Philip Gwyn's idea, to auto-split and
translate Perl code into POE event handlers as part of an installation
process, rather than at runtime.
-***POE::Perl
-POE::Perl would take a different approach. It would try to manipulate
-Perl into cooperating with POE's event model. So far, the idea
-includes:
***POE::Module::VNC
VNC's home is <http://www.uk.research.att.com/vnc/>.
@@ -684,36 +716,55 @@ It sure would be interesting if POE could serve virtual desktops.
Interesting and scary, like a huge, mutant, radioactive lizard staring
in your car window, wondering if maybe it wants a crunchy snack with a
soft, gooey center. Or something.
+***POE::Perl
+POE::Perl would take a different approach. It would try to manipulate
+Perl into cooperating with POE's event model. So far, the idea
+includes:
****Overriding Perl's built-in functions
CORE::GLOBAL::sleep, for example, would register an alarm handler, and
set an alarm for it.
****Manipulating Perl's call stack
-CORE::GLOBAL::sleep would save the call stack going into the sleep()
-function, and simulate a return back to the kernel. When the alarm
-handler is called, the stack is reconstituted, and CORE::GLOBAL::sleep
-returns back to the session.
+CORE::GLOBAL::sleep (again, for example) would save the call stack
+going into the sleep() function, and simulate a return back to the
+kernel. When the alarm handler is called, the stack is reconstituted,
+and CORE::GLOBAL::sleep returns back to the session.
That's the idea, anyway. Perl may not like it.
***POP? bholzman's persistent objects; crimson is working on it?
+This never materialized, and now the Object Layer is starting to take
+form.
***$kernel->stop() and $kernel->run() to pause and resume the kernel?
Is this still necessary/useful?
***Filter::HTTPD needs to send responses directly... POE::Module::*?
-And a CGI-like interface.
+And a CGI-like interface. A POE::Filter subclass for form-based I/O
+(and split the current POE::Filter classes into stream and block
+categories while we're at it).
***Use threads, if available, requested and stable.
-Taken care of by kernel hooks?
+Taken care of by kernel hooks? No... I'm working on a new event model
+within Kernel and Session (see the comments after __END__ in each).
+This should make sessions and events flexible enough for the
+forseeable future.
+
+The changes should enable freezing and thawing sessions, concurrency
+using threads, and remote execution.
***Use fork, if available and requested.
Taken care of by kernel hooks?
***Distributed event queue
Enabled by kernel hooks/extensions? Anyway, this probably will be
implemented as a "poe_distributor" session that acts as an event
gateway to other systems.
+
+Philip Gwyn is working on remote calls and events. I've elected not
+to apply his patches for Kernel and Session IDs yet because the Kernel
+and Session guts are in flux.
***Load-balancing among distributed POE kernels.
Taken care of by kernel hooks?
***Filter::HTTP (user agent).
This is the client side. q[merlyn] thinks there's a non-blocking way
to use LWP, possibly by suppling the select loop logic for it, which
would work nicely.
***Rewrite Serv's curses widgets for POE.
+This would be SO cool... need... more... time!
***POE::Extension? POE::DeepMagic? An API for kernel extensions.
See the Kernel Hooks, above. Artur is working on this.
***Unique IDs
@@ -725,6 +776,11 @@ would it maintain the last SID in a file? It could also include
(somehow) the unix epoch time that the server was started.
Kernel IDs would be the process' network address and server port.
+
+Actually, the Object Layer should obviate the need for session and
+kernel IDs. The original plan was for sessions to be the threading
+model for object execution, and OBJECT IDs would identify which code
+gets what events.
**Object Layer
The object layer will consist of a few parts. As it's shaping up, it
should consist of the following classes.
@@ -742,7 +798,8 @@ repositories.
my $repository = new POE::Repository::MySQL( $login, $pass, $db );
# ... and so on
-The repository will not be a tied hash thing.
+The repository will not be a tied hash thing, because tied-hash things
+are relatively slow.
***Curator (object manager)
The Curator abstraction manages objects in the database. It will
provide a Perl-like access method to objects in the repository, and it
@@ -955,10 +1012,99 @@ a 'bot that you don't have to reset all the time is (IMO) the fabled
Object Layer.
So, this to-do is on hold 'til I can build an IRC 'bot.
+*CODE
+
+**Kernel
+
+name is public
+_name is friend
+__name is private
+
+sub _enqueue_event {
+ my ($self, $session_id, $source_id, $state, $priority, $time, $etc) = @_;
+}
+
+#------------------------------------------------------------------------------
+# Dispatch an event to the next session in the round-robin queue.
+# This also has the side-effect of testing sessions for activity; they
+# can be checked for resource starvation only when they've run out of
+# events. This should eliminate a lot of checks.
+
+sub _dispatch_next_event {
+ my ($self) = @_;
+
+ my $next_session = shift @{$self->[KR_SQUEUE]};
+ if ($next_session->_dispatch_event()) {
+ push @{$self->[KR_SQUEUE]}, $next_session;
+ }
+}
+
+
+# Theory of operation:
+#
+# Kernel keeps a master queue. This holds active sessions in a
+# time-based "priority" queue.
+#
+# The queue's "key" is the time that a session will next need
+# attention. This is the time of the next event in the session's
+# queue.
+#
+# The queue's "value" is a reference to the session (or perhaps
+# session ID) that points to the session for dispatching.
+#
+# So:
+
+my $kernel = bless {}, 'POE::Kernel';
+$kernel->[KR_MASTER_QUEUE] =
+ [ [ $time, $session ],
+ [ $time, $session ],
+ ...
+ ];
+
+# Sorted in $time order.
+#
+# Inser
+
+**Session
+#------------------------------------------------------------------------------
+# Enqueue an event.
+
+name is public
+_name is friend
+__name is private
+
+sub _enqueue_event {
+ my ($self, $sender, $state, $priority, $time, $etc) = @_;
+
+ # Place the event is the session's queue.
+
+ #
+ # If "concurrent" POE:
+ # Start or unblock the session's dispatch thread.
+ # End
+ #
+ # Return the number of events in the session's queues.
+
+}
+
+sub _dispatch_event {
+ my ($self) = @_;
+
+ # If "concurrent" POE:
+ # Return 1 if there are no events but the session has resources to keep it active.
+ # Return 0 if there are no events and the session is "stalled".
+ # Otherwise, "regular" POE:
+ # Dispatch an event, and return the number of events left in the queue.
+ # End
+}
+
+
*AUTHOR
POE is Copyright 1998 Rocco Caputo <troc@netrus.net>. All rights
reserved. POE is free software; you may redistribute it and/or modify
it under the same terms as Perl itself.
-Please see the main documentation for contributor information and
-other copyright notices.
+Individual bits of POE are copyright by their respective authors, but
+the licenses should all be the same. If you're worried about that
+sort of thing, please see the main documentation for contributor
+information and other copyright notices.
View
529 lib/POE.pm
@@ -1,12 +1,5 @@
# $Id$
-
-# Copyright 1998 Rocco Caputo <troc@netrus.net>. All rights reserved.
-# This program is free software; you can redistribute it and/or modify
-# it under the same terms as Perl itself.
-
-# Contributed portions of POE may be copyright by their respective
-# contributors. Please see `POE.pod`, `perldoc POE`, or `man POE` for
-# real documentation.
+# Copyrights and documentation are after __END__.
package POE;
@@ -46,3 +39,523 @@ sub new {
#------------------------------------------------------------------------------
1;
+__END__
+
+=head1 NAME
+
+POE - A Perl Object Environment
+
+=head1 SYNOPSIS
+
+ # Basic usage:
+
+ use POE;
+ # create initial sessions here
+ $poe_kernel->run();
+ exit;
+
+ # Typical usage:
+
+ use POE qw( Wheel::SocketFactory Wheel::ReadWrite
+ Driver::SysRW Filter::Line
+ );
+ # create initial sessions here
+ $poe_kernel->run();
+ exit;
+
+=head1 DESCRIPTION
+
+The POE distribution contains a handful of different modules, each
+doing something different.
+
+When a program uses the POE module, the mandatory POE::Kernel and
+POE::Session classes are included. Other modules may be included in
+the parameter to ``use POE''. POE.pm will prepend ``POE::'' to the
+module names for you.
+
+=head1 CONCEPTUAL OVERVIEW
+
+POE's features are separated into three major sections. Sections are
+called "layers" in the documentation because each builds atop others.
+
+ +-----------+ +--------------+
+ | I/O Layer | | Object Layer |
+ +-----------+ +--------------+
+ /|\ /|\ Commands (to events layer)
+ | |
+ | |
+ \|/ \|/ Events (from events layer)
+ +----------------------------+
+ | Events Layer |
+ +----------------------------+
+
+Events are also used to pass messages between Sessions.
+
+This is a description of each layer, starting with the lowest and
+working upwards:
+
+=head2 Events Layer
+
+POE's events layer consists of two classes. These classes are always
+included when a program uses POE. They may also be used separately
+wherever their exported constants are needed.
+
+POE::Kernel contains the state transition event queue and functions to
+manage resources (including events). Later on, these functions will
+be referred to as "resource commands". The Kernel will generate
+events to indicate when watched resources (via a resource command)
+become active.
+
+POE::Session instances are state machines. They consist of bundles of
+related states. States may be code references, object methods or
+package subroutines. States are invoked whenever a queued transition
+event is dispatched. State transitions may be enqueued by states
+themselves or by active resources.
+
+=head2 I/O Layer
+
+The I/O layer contains one or more libraries that abstract file I/O.
+Currently there is only one abstraction library, fondly known as
+"Wheels". The "Wheels" abstraction consists of groups of classes.
+
+One type of object does only low-level file I/O. These are the Driver
+objects.
+
+A second type of object translates between raw octet streams and
+protocol packets. These are the Filter objects.
+
+The final type of object provides a functional interface to file I/O,
+as well as the select logic to glue Drivers and Filters together.
+These are the Wheel objects.
+
+Here is a rough picture of the Wheels I/O abstraction:
+
+ +----------------------------------------------------------+
+ | Session |
+ | |
+ | +------------+ +-------+ +--------+ +--------+ |
+ | |States | | | | | | | |
+ | | | | | | | | | |
+ | |Command | | | | Filter | | | |
+ | |events --|->| |<--->| |--->| | |
+ | | | | Wheel | | | | Driver | |
+ | |Functions --|->| | +--------+ | |<--|--> File
+ | | | | | | | |
+ | |Response | | |-> Select Events ->| | |
+ | |events <-|--| | | | |
+ | +------------+ +-------+ +--------+ |
+ | | /|\ | /|\ |
+ | | | | | |
+ +---|----|----------|---|----------------------------------+
+ | | | |
+ | | | | Commands (Session -> Kernel)
+ | | | | & Events (Kernel -> Session)
+ \|/ | \|/ |
+ +----------------------------------------------------------+
+ | |
+ | Kernel |
+ | |
+ +----------------------------------------------------------+
+
+=head2 Object Layer
+
+The Object layer consists of one or more libraries that implement
+code objects. Currently there are two ways code objects can be
+created.
+
+First, code may exist as plain Perl subroutines, objects and
+packages. This is the oldest object layer, and it is often the best
+for most programming tasks.
+
+The second object layer is still in its infancy. Right now it
+consists of four classes:
+
+Curator. This is the object manager. It embodies inheritance,
+attribute fetching and storage, method invocation and security.
+
+Repository. This is the object database. It provides a consistent
+interface between the Curator and whatever database it hides.
+
+Object. This is a Perl representation of a Repository object. It
+hides the Curator and Repository behind an interface that resemmbles a
+plain Perl object.
+
+Runtime. This is a namespace where Object methods are run. It
+contains the public functions from Curator, Repository and Object, and
+it may one day run within a Safe compartment.
+
+The obligatory ASCII art:
+
+ +--------------------------------------------------+
+ | Runtime |
+ | +----------------+ |
+ | | Object Methods |-------> Public Functions |
+ | +----------------+ |
+ | /|\ | |
+ +----|---------------------------|-----------------+
+ | |
+ | Events | Commands
+ | \|/
+ +--------------------------------------------------+
+ | |
+ | +------------+ Curator |
+ | | | |
+ | | Sessions | +-------------------------------+
+ | | | |
+ | +------------+ | +------------+ +--======--+
+ | /|\ | |<->| Repository |<->| Database |
+ +-----|------|-----+ +------------+ +--======--+
+ | |
+ | | Events & Commands
+ | \|/
+ +--------------------------------------------------+
+ | |
+ | Kernel |
+ | |
+ +--------------------------------------------------+
+
+=head1 EXAMPLES
+
+As of this writing there are 22 sample programs. Each illustrates and
+tests some aspect of POE use. They are included in the POE
+distribution archive, but they are not installed. If POE was
+installed via the CPAN shell, then you should be able to find them in
+your .cpan/build/POE-(version) directory.
+
+=head2 Events Layer Examples
+
+These sample programs demonstrate and exercize POE's events layer and
+resource management functions.
+
+=over 4
+
+=item *
+
+create.perl
+
+This program is essentially the same as sessions.perl, but it uses the
+newer &POE::Session::create constructor rather than the original
+&POE::Session::new constructor.
+
+=item *
+
+forkbomb.perl
+
+This program is an extensive test of Session construction and
+destruction in the kernel. Despite the name, it does not use fork(2).
+By default, this program will stop after about 200 sessions, so it
+shouldn't run away with machines it's run on.
+
+Stopping forkbomb.perl with SIGINT is a good way to test signal
+propagation.
+
+=item *
+
+names.perl
+
+This program demonstrates the use of session aliases as a method of
+"daemonizing" sessions and communicating between them by name. It
+also shows how to do non-blocking inter-session communication with
+callback states.
+
+=item *
+
+objsessions.perl
+
+This program is essentially the same as sessions.perl, but it uses
+object methods as states instead of inline code references.
+
+=item *
+
+packagesessions.perl
+
+This program is essentially the same as sessions.perl, but it uses
+package functions as states instead of inline code references.
+
+=item *
+
+selects.perl
+
+This program exercises the POE::Kernel interface to select(2). It
+creates a simple chargen server, and a simple client to visit it. The
+client will disconnect after receiving a few lines from the server.
+The server will remain active.
+
+=item *
+
+sessions.perl
+
+This program is a basic test of Session construction, destruction and
+maintenance in the Kernel. It is much more friendly than
+forkbomb.perl. People who are new to POE may want to look at this
+test first.
+
+=item *
+
+signals.perl
+
+This program is a basic test of the POE::Kernel interface to system
+and Session signals. It creates two sessions that wait for signals
+and periodically send signals to themselves.
+
+=back
+
+=head2 I/O Layer Examples
+
+These sample programs demonstrate and exercize POE's default I/O
+layer.
+
+=over 4
+
+=item *
+
+fakelogin.perl
+
+This program tests the ability for POE::Wheel instances to change the
+events they emit.
+
+=item *
+
+filterchange.perl
+
+This program tests the ability for POE::Wheel instances to change the
+filters they use to process information.
+
+=item *
+
+followtail.perl
+
+This program tests POE::Wheel::FollowTail, a read-only wheel that
+follows the end of an ever-growing file.
+
+It creates 21 sessions: 10 log writers, 10 log followers, and one loop
+to make sure none of the other 20 are blocking. SIGINT should stop
+the program and clean up its /tmp files.
+
+=item *
+
+httpd.perl
+
+This program tests POE::Filter::HTTPD by implementing a very basic web
+server. It will try to bind to port 80 of every available interface,
+and it will not run if something has already bound to port 80. It
+will accept a new port number on the command line:
+
+ ./httpd.perl 8080
+
+=item *
+
+ref-type.perl
+
+This program tests the ability for POE::Filter::Reference to use
+specified serialization methods. It is part of Philip Gwyn's work on
+XML based RPC.
+
+=item *
+
+refsender.perl and refserver.perl
+
+These two programs test POE::Filter::Reference's ability to pass
+blessed and unblessed references between processes. The standard
+Storable caveats (such as the inability to freeze and thaw CODE
+references) apply.
+
+To run this test, first start refserver, then run refsender. Check
+refserver's STDOUT to see if it received some data.
+
+=item *
+
+socketfactory.perl
+
+This program tests POE::Wheel::SocetFactory, a high level wheel that
+creates listening and connecting sockets. It creates a server and
+client for each socket type it currently supports. The clients visit
+the servers and process some sample transactions.
+
+=item *
+
+thrash.perl
+
+This program tests the Wheel abstraction's ability to handle heavy
+loads. It creates a simple TCP daytime server and a pool of 5 clients
+within the same process. Each client connects to the server, accepts
+the current time, and destructs. The client pool creates replacements
+for destroyed clients, and so it goes.
+
+This program has been known to exhaust some systems' available
+sockets. On systems that are susceptible to socket exmaustion,
+netstat will report a lot of sockets in various WAIT states, and
+thrash.perl will show an abnormally low connections/second rate.
+
+=item *
+
+wheels.perl
+
+This program is a basic rot13 server. It is a basic test of the whole
+premise of wheels.
+
+=back
+
+=head2 Object Layer Examples
+
+This program illustrates POE's Object Layer, which is still in early
+development.
+
+=over 4
+
+=item *
+
+olayer.perl
+
+This program demonstrates some of the features of the early Object
+Layer implementation. It's also something of a reference standard, to
+make sure that the Object Layer is consistent and usable.
+
+=back
+
+=head2 Proofs of Concepts
+
+Proofs of concepts mainly show how to do something with POE. In some
+cases, they prove that the concept is possible, even though it wasn't
+considered while POE was being designed.
+
+=over 4
+
+=item *
+
+preforkedserver.perl
+
+This program demonstrates a way to write pre-forking servers with POE.
+
+=item *
+
+proxy.perl
+
+This program demonstrates a way to write TCP forwarders with POE.
+
+=item *
+
+tutorial-chat.perl
+
+This program is a heavily commented "chat" program. It contains a
+running narrative of what's going on and is intended to be both
+functional and educational.
+
+=back
+
+=head1 SEE ALSO
+
+=over 4
+
+=item *
+
+Events Layer
+
+POE::Kernel; POE::Session
+
+=item *
+
+I/O Layer
+
+POE::Driver; POE::Driver::SysRW POE::Filter; POE::Filter::HTTPD;
+POE::Filter::Line; POE::Filter::Reference; POE::Filter::Stream;
+POE::Wheel; POE::Wheel::FollowTail; POE::Wheel::ListenAccept;
+POE::Wheel::ReadWrite; POE::Wheel::SocketFactory
+
+=item *
+
+Object Layer
+
+POE::Curator; POE::Object; POE::Repository; POE::Repository::Array;
+POE::Runtime
+
+=back
+
+=head1 BUGS
+
+The Object Layer is still in early design and implementation, so it's
+not documented yet.
+
+=head1 AUTHORS & COPYRIGHTS
+
+POE is brought to you by the following people:
+
+=head2 Contributors
+
+All contributions are Copyright 1998-1999 by their respective
+contributors. All rights reserved. Contributions to POE are free
+software, and they may be redistributed and/or modified under the same
+terms as Perl itself.
+
+=over 4
+
+=item *
+
+Artur Bergman
+
+Artur Bergman is <vogon-solutions.com!artur>.
+
+He has contributed Filter::HTTPD and Filter::Reference. His
+intangible contributions include feedback, testing, conceptual
+planning and inspiration. POE would not be as far along without his
+support.
+
+=item *
+
+Philip Gwyn
+
+Philip Gwyn is <artware.qc.ca!gwynp>.
+
+He has extended the Wheels I/O abstraction to allow filters to be
+changed at runtim. He has enhanced Filter::Reference to support
+different serialization methods. His intangible contributions include
+feedback and quality assurance (bug finding). A lot of cleanup
+between 0.06 and 0.07 is a result of his keen eye. His other eye's
+not so bad either.
+
+=item *
+
+Dave Paris
+
+Dave Paris is <w3works.com!dparis>.
+
+His contributions include testing and benchmarking. He discovered
+some subtle (and not so subtle) timing problems in version 0.05. The
+pre-forking server test was his idea. Versions 0.06 and later should
+scale to higher loads because of his work.
+
+=item *
+
+Robert Seifer
+
+Robert Seifer is <?!?>.
+
+He contributed entirely too much time, both his own and his
+computer's, to the detection and eradication of a memory corruption
+bug that POE tickled in Perl. In the end, his work produced a patch
+that circumvents problems found relating to anonymous subs, scope and
+@{} processing.
+
+=item *
+
+Others?
+
+Have I forgotten someone? Please let me know.
+
+=back
+
+=head2 Author
+
+=over 4
+
+=item *
+
+Rocco Caputo
+
+Rocco Caputo is <netrus.net!troc>. POE is his brainchild.
+
+Except where otherwise noted, POE is Copyright 1998-1999 Rocco Caputo.
+All rights reserved. POE is free software; you may redistribute it
+and/or modify it under the same terms as Perl itself.
+
+=cut
View
89 lib/POE/Driver.pm
@@ -1,9 +1,5 @@
# $Id$
-# Copyright 1998 Rocco Caputo <troc@netrus.net>. All rights reserved.
-# This program is free software; you can redistribute it and/or modify
-# it under the same terms as Perl itself.
-
package POE::Driver;
use strict;
@@ -17,3 +13,88 @@ sub new {
#------------------------------------------------------------------------------
1;
+
+__END__
+
+=head1 NAME
+
+POE::Driver - POE Read/Write Abstraction
+
+=head1 SYNOPSIS
+
+ $driver = new POE::Driver::Something();
+ $arrayref_of_data_chunks = $driver->get($filehandle);
+ $queue_size = $driver->put($arrayref_of_data_chunks);
+ $queue_size = $driver->flush($filehandle);
+
+=head1 DESCRIPTION
+
+Drivers provide a generic interface for low-level file I/O. Wheels
+use this interface to read and write files, sockets, and things,
+without having to know the details for each.
+
+In theory, drivers should be pretty much interchangeable. In
+practice, there seems to be an impermeable barrier between the
+different SOCK_* types.
+
+=head1 PUBLIC DRIVER METHODS
+
+These methods are the generic Driver interface. Specific drivers may
+have additional methods.
+
+=over 4
+
+=item *
+
+POE::Driver::new()
+
+The new() method creates and initializes a new driver. Specific
+drivers may have different constructor parameters.
+
+=item *
+
+POE::Driver::get($filehandle)
+
+The get() method immediately tries to read information from a
+filehandle. It returns a reference to an array of received data
+chunks. The array may be empty if nothing could be read. The array
+reference it returns is a suitable parameter to POE::Filter::get().
+
+Wheels usually call the get() method from their read select states.
+
+=item *
+
+POE::Driver::put($arrayref_of_data_chunks)
+
+The put() method places raw data into the driver's output queue. Some
+drivers may flush data from the put() method. It accepts a reference
+to an array of writable chunks, and it returns the number of elements
+it its output queue.
+
+Wheels usually call the put() method from their own put() methods.
+
+=item *
+
+POE::Driver::flush($filehandle)
+
+The flush() method attempts to flush some data from the driver's
+output queue to the file. It returns the number of elements remaining
+in the output queue after the flush.
+
+Wheels usually call the flush() method from their write select states.
+
+=back
+
+=head1 SEE ALSO
+
+POE::Driver::SysRW
+
+=head1 BUGS
+
+There is no POE::Driver::SendRecv
+
+=head1 AUTHORS & COPYRIGHTS
+
+Please see the POE manpage.
+
+=cut
View
31 lib/POE/Driver/SysRW.pm
@@ -83,3 +83,34 @@ sub flush {
###############################################################################
1;
+
+__END__
+
+=head1 NAME
+
+POE::Driver::SysRW - POE sysread/syswrite Abstraction
+
+=head1 SYNOPSIS
+
+ $driver = new POE::Driver::SysRW();
+ $arrayref_of_data_chunks = $driver->get($filehandle);
+ $queue_size = $driver->put($arrayref_of_data_chunks);
+ $queue_size = $driver->flush($filehandle);
+
+=head1 DESCRIPTION
+
+This driver provides an abstract interface to sysread and syswrite.
+
+=head1 SEE ALSO
+
+POE::Driver
+
+=head1 BUGS
+
+Oh, probably some.
+
+=head1 AUTHORS & COPYRIGHTS
+
+Please see the POE manpage.
+
+=cut
View
122 lib/POE/Filter.pm
@@ -1,9 +1,5 @@
# $Id$
-# Copyright 1998 Rocco Caputo <troc@netrus.net>. All rights reserved.
-# This program is free software; you can redistribute it and/or modify
-# it under the same terms as Perl itself.
-
package POE::Filter;
use strict;
@@ -17,3 +13,121 @@ sub new {
#------------------------------------------------------------------------------
1;
+
+__END__
+
+=head1 NAME
+
+POE::Filter - POE Protocol Abstraction
+
+=head1 SYNOPSIS
+
+ $filter = new POE::Filter::Something();
+ $arrayref_of_logical_chunks =
+ $filter->get($arrayref_of_raw_chunks_from_driver);
+ $arrayref_of_streamable_chunks_for_driver =
+ $filter->put($arrayref_of_logical_chunks);
+
+=head1 DESCRIPTION
+
+Filters provide a generic interface for low and medium level
+protocols. Wheels use this interface to communicate in different
+protocols without necessarily having to know the details for each.
+
+In theory, filters should be interchangeable. In practice, stream and
+block protocols tend to be incompatible.
+
+=head1 PUBLIC FILTER METHODS
+
+These methods are the generic Filter interface. Specific filters may
+have additional methods.
+
+=over 4
+
+=item *
+
+POE::Filter::new()
+
+The new() method creates and initializes a new filter. Specific
+filters may have different constructor parameters.
+
+=item *
+
+POE::Filter::get($arrayref_of_raw_chunks_from_driver)
+
+The get() method translates raw stream data into logical units. It
+accepts a reference to an array of raw stream chunks as returned from
+POE::Driver::get(). It returns a reference to an array of complete
+logical data chunks. There may or may not be a 1:1 correspondence
+between raw stream chunks and logical data chunks.
+
+Some filters may buffer partial logical units until they are completed
+in subsequent get() calls.
+
+The get() method returns a reference to an empty array if the stream
+doesn't include enough information for a complete logical unit.
+
+=item *
+
+POE::Filter::put($arrayref_of_logical_chunks)
+
+The put() method takes a reference to an array of logical data chunks.
+It serializes them into streamable representations suitable for
+POE::Driver::put(). It returns the raw streamable versions in a
+different array reference.
+
+=item *
+
+POE::Filter::get_pending()
+
+The get_pending() method is part of wheels' buffer swapping mechanism.
+It clears the filter's input buffer and returns a copy of whatever was
+in it. It doesn't manipulate filters' output buffers because they
+don't exist (filters expect to receive entire logical data chunks from
+sessions, so there's no reason to buffer data and frame it).
+
+B<Please note that relying on the get_pending() method in networked
+settings require some forethought.> For instance, POE::Filter::Stream
+never buffers data.
+
+Switching filters usually requires some sort of flow control,
+otherwise it's easy to cause a race condition where one side sends the
+wrong type of information for the other side's current filter.
+Framing errors will enuse. Consider the following:
+
+Assume a server and client are using POE::Filter::Line. When the
+client asks the server to switch to POE::Filter::Reference, it should
+wait for the server's ACK or NAK before changing its own filter. This
+lets the client avoid sending referenced data while the server still
+is parsing lines.
+
+Here's something else to consider. Programs using POE::Wheel::put()
+on TCP sockets cannot rely on each put data chunk arriving separately
+on the receiving end of the connection. This is because TCP coalesces
+packets whenever possible, to minimize packet header overhead. There
+is a workaround, but it's not implemented in standard Perl:
+
+ The workaround is to disable Nagle's algorithm for the socket. This
+ involves setting the TCP_NODELAY socket option. It is not portable
+ or standard. Some systems will only disable Nagle's algorithm for
+ the entire TCP stack (thus all sockets, which may not be desirable).
+
+The filterchange.perl sample program copes with flow control while
+switching filters.
+
+=back
+
+=head1 SEE ALSO
+
+POE::Filter::HTTPD; POE::Filter::Line; POE::Filter::Reference;
+POE::Filter::Stream
+
+=head1 BUGS
+
+Oh, probably some.
+
+=head1 AUTHORS & COPYRIGHTS
+
+Please see the POE manpage.
+
+=cut
View
40 lib/POE/Filter/HTTPD.pm
@@ -1,16 +1,11 @@
# $Id$
-# Documentation exists after __END__
# Filter::HTTPD copyright 1998 Artur Bergman <artur@vogon.se>.
# Thanks go to Gisle Aas for his excellent HTTP::Daemon. Some of the
# get code was copied out if, unfournatly HTTP::Daemon is not easily
# subclassed for POE because of the blocking nature.
-# Copyright 1998 Rocco Caputo <troc@netrus.net>. All rights reserved.
-# This program is free software; you can redistribute it and/or modify
-# it under the same terms as Perl itself.
-
package POE::Filter::HTTPD;
use HTTP::Status;
use HTTP::Request;
@@ -189,43 +184,42 @@ EOT
###############################################################################
1;
+
__END__
=head1 NAME
-POE::Filter::HTTPD - Supports the HTTP 1.0 Protocol
+POE::Filter::HTTPD - POE HTTP 1.0 (Server Side) Protocol Abstraction
=head1 SYNOPSIS
$httpd = new POE::Filter::HTTPD();
-
- $http_response_as_string = $httpd->put($full_http_response_object);
-
- $http_request_object = $line->get($http_request_string);
-
+ $arrayref_with_http_response_as_string =
+ $httpd->put($full_http_response_object);
+ $arrayref_with_http_request_object =
+ $line->get($arrayref_of_raw_data_chunks_from_driver);
=head1 DESCRIPTION
-Breaks up a httpstream into a HTTP::Request object, accepts a HTTP::Response object that it sends back to the client.
+The HTTPD filter parses the first HTTP 1.0 request from an incoming
+stream into an HTTP::Request object. It accepts a single HTTP
+response object, and returns a HTTP 1.0 stream for sending.
-=head1 PUBLIC METHODS
+=head1 PUBLIC FILTER METHODS
-Please see C<POE::Filter> for explanations.
+Please see POE::Filter.
-=head1 EXAMPLES
+=head1 SEE ALSO
-Please see tests/httptest.perl for examples of C<POE::Filter::HTTPD>.
+POE::Filter; POE::Filter::Line; POE::Filter::Reference;
+POE::Filter::Stream
=head1 BUGS
-None known.
+Keepalive is not supported.
-=head1 CONTACT AND COPYRIGHT
+=head1 AUTHORS & COPYRIGHTS
-Copyright 1998 Rocco Caputo E<lt>troc@netrus.netE<gt>. All rights reserved.
-This program is free software; you can redistribute it and/or modify
-it under the same terms as Perl itself.
+Please see the POE manpage.
=cut
-
-
View
45 lib/POE/Filter/Line.pm
@@ -52,3 +52,48 @@ sub get_pending
###############################################################################
1;
+
+__END__
+
+=head1 NAME
+
+POE::Filter::Line - POE Line Protocol Abstraction
+
+=head1 SYNOPSIS
+
+ $filter = new POE::Filter::Line();
+ $arrayref_of_lines = $filter->get($arrayref_of_raw_chunks_from_driver);
+ $arrayref_of_streamable_chunks_for_driver = $filter->put($arrayref_of_lines);
+ $arrayref_of_streamable_chunks_for_driver = $filter->put($single_line);
+
+=head1 DESCRIPTION
+
+The Line filter translates streams to and from newline-separated
+lines. The lines it returns do not contain newlines. Neither should
+the lines given to it.
+
+Incoming newlines are recognized with the regexp
+C</(\x0D\x0A?|\x0A\x0D?)/>. Incomplete lines are buffered until a
+subsequent packet completes them.
+
+Outgoing lines have the network newline attached to them:
+C<"\x0D\x0A">.
+
+=head1 PUBLIC FILTER METHODS
+
+Please see POE::Filter.
+
+=head1 SEE ALSO
+
+POE::Filter; POE::Filter::HTTPD; POE::Filter::Reference;
+POE::Filter::Stream
+
+=head1 BUGS
+
+This filter's newlines are hardcoded.
+
+=head1 AUTHORS & COPYRIGHTS
+
+Please see the POE manpage.
+
+=cut
View
99 lib/POE/Filter/Reference.pm
@@ -115,3 +115,102 @@ sub get_pending
###############################################################################
1;
+
+__END__
+
+=head1 NAME
+
+POE::Filter::Reference - POE Freeze/Thaw Protocol Abstraction
+
+=head1 SYNOPSIS
+
+ $filter = new POE::Filter::Something();
+ $arrayref_of_perl_references =
+ $filter->get($arrayref_of_raw_chunks_from_driver);
+ $arrayref_of_serialized_perl_references =
+ $filter->put($arrayref_of_perl_references);
+
+=head1 DESCRIPTION
+
+The "put" half of this filter freezes referenced Perl structures into
+serialized versions for sending. The "get" half of this filter thaws
+serialized Perl structures back into references. This provides a
+handy way to ship data between processes and systems.
+
+Serializers should recognize that POE::Filter::Reference is used to
+ship data between systems with different byte orders.
+
+=head1 PUBLIC FILTER METHODS
+
+=over 4
+
+=item *
+
+POE::Filter::Reference::new( ... )
+
+The new() method creates and initializes the reference filter. It
+accepts an optional parameter to specify a serializer. The serializer
+may be a package or an object.
+
+A package serializer must have thaw() and either freeze() or nfreeze()
+functions. The nfreeze() function is recommended, because using
+network byte order everywhere prevents problems when crossing endian
+borders. These functions match Storable and FreezeThaw's call
+signatures.
+
+An object serializer must have thaw() and either freeze() or nfreeze()
+methods. The thaw() method accepts $self and a scalar; it should
+return a reference to the reconstituted data. The freeze() and
+nfreeze() methods receive $self and a reference; they should return a
+scalar with the reference's serialized representation.
+
+For example:
+
+ # Use the default filter (either Storable or FreezeThaw).
+ my $filter1 = new POE::Filter::Reference();
+
+ # Use Storable explicitly, specified by package name.
+ my $filter = new POE::Filter::Reference('Storable');
+
+ # Use an object.
+ my $filter = new POE::Filter::Reference($object);
+
+The new() method will try to require any packages it needs.
+
+The default behavior is to try Storable first, FreezeThaw second, and
+fail if neither is present. This is rapidly becoming moot because of
+the PM_PREREQ entry in Makefile.PL, which makes CPAN and ``make'' carp
+about requirements even when they aren't required.
+
+=item *
+
+POE::Filter::Reference::get($frozen_data)
+
+The get() method thaws streamed, frozen data into references.
+References will be blessed, if necessary. If the reference points to
+an object, be sure the receiving end has use'd it before calling its
+methods.
+
+=item *
+
+POE::Filter::Reference::put($reference)
+
+The put() method freezes references and returns their serialized,
+streamable representations.
+
+=back
+
+=head1 SEE ALSO
+
+POE::Filter; POE::Filter::HTTPD; POE::Filter::Line;
+POE::Filter::Stream
+
+=head1 BUGS
+
+Oh, probably some.
+
+=head1 AUTHORS & COPYRIGHTS
+
+Please see the POE manpage.
+
+=cut
View
37 lib/POE/Filter/Stream.pm
@@ -1,9 +1,5 @@
# $Id$
-# Copyright 1998 Rocco Caputo <troc@netrus.net>. All rights reserved.
-# This program is free software; you can redistribute it and/or modify
-# it under the same terms as Perl itself.
-
package POE::Filter::Stream;
use strict;
@@ -38,3 +34,36 @@ sub get_pending {} #we don't keep any state
###############################################################################
1;
+
+__END__
+
+=head1 NAME
+
+POE::Filter::Stream - POE Stream (Null) Protocol Abstraction
+
+=head1 SYNOPSIS
+
+ $filter = new POE::Filter::Stream();
+ $arrayref_of_logical_chunks =
+ $filter->get($arrayref_of_raw_chunks_from_driver);
+ $arrayref_of_streamable_chunks_for_driver =
+ $filter->put($arrayref_of_logical_chunks);
+
+=head1 DESCRIPTION
+
+This filter passes data through unchanged. It is a "null" filter.
+
+=head1 SEE ALSO
+
+POE::Filter; POE::Filter::HTTPD; POE::Filter::Line;
+POE::Filter::Reference; POE::Filter::Stream
+
+=head1 BUGS
+
+Oh, probably some.
+
+=head1 AUTHORS & COPYRIGHTS
+
+Please see the POE manpage.
+
+=cut
View
451 lib/POE/Kernel.pm
@@ -1,11 +1,5 @@
# $Id$
-# Copyright 1998 Rocco Caputo <troc@netrus.net>. All rights reserved.
-# This program is free software; you can redistribute it and/or modify
-# it under the same terms as Perl itself.
-
-###############################################################################
-
package POE::Kernel;
use strict;
@@ -752,6 +746,7 @@ sub _invoke_state {
sub session_create {
my $self = shift;
+ carp "POE::Kernel::session_create() is depreciated";
new POE::Session(@_);
}
@@ -1213,51 +1208,411 @@ new POE::Kernel();
__END__
-name is public
-_name is friend
-__name is private
+=head1 NAME
-sub _enqueue_event {
- my ($self, $session_id, $source_id, $state, $priority, $time, $etc) = @_;
-}
+POE::Kernel - POE Event Queue and Resource Manager
-#------------------------------------------------------------------------------
-# Dispatch an event to the next session in the round-robin queue.
-# This also has the side-effect of testing sessions for activity; they
-# can be checked for resource starvation only when they've run out of
-# events. This should eliminate a lot of checks.
+=head1 SYNOPSIS
-sub _dispatch_next_event {
- my ($self) = @_;
+ #!/usr/bin/perl -w
+ use strict;
+ use POE; # Includes POE::Kernel and POE::Session
+ new POE::Session( ... ); # Bootstrap sessions are here.
+ $poe_kernel->run(); # Run the kernel.
+ exit; # Exit when the kernel's done.
- my $next_session = shift @{$self->[KR_SQUEUE]};
- if ($next_session->_dispatch_event()) {
- push @{$self->[KR_SQUEUE]}, $next_session;
- }
-}
+ # Session management methods:
+ $kernel->session_create( ... );
+
+ # Event management methods:
+ $kernel->post( $session, $state, @args );
+ $kernel->yield( $state, @args );
+ $kernel->call( $session, $state, @args );
+
+ # Alarms and timers:
+ $kernel->alarm( $state, $time, @args );
+ $kernel->delay( $state, $seconds, @args );
+
+ # Aliases:
+ $status = $kernel->alias_set( $alias );
+ $status = $kernel->alias_remove( $alias );
+ $session_reference = $kernel->alias_resolve( $alias );
+
+ # Selects:
+ $kernel->select( $file_handle,
+ $read_state_name, # or undef to remove read state
+ $write_state_name, # or undef to remove write state
+ $expedite_state_same, # or undef to remove expedite state
+ );
+ $kernel->select_read( $file_handle, $read_state_name );
+ $kernel->select_write( $file_handle, $write_state_name );
+ $kernel->select_expedite( $file_handle, $expedite_state_name );
+
+ # Signals:
+ $kernel->sig( $signal_name, $state_name ); # Registers a handler.
+ $kernel->signal( $session, $signal_name ); # Posts a signal.
+
+ # States:
+ $kernel->state( $state_name, $code_reference ); # Inline state
+ $kernel->state( $method_name, $object_reference ); # Object state
+ $kernel->state( $function_name, $package_name ); # Package state
+
+=head1 DESCRIPTION
+
+POE::Kernel contains POE's event loop, select logic and resource
+management methods. There can only be one POE::Kernel per process,
+and it's created automatically the first time POE::Kernel is used.
+This simplifies signal delivery in the present and threads support in
+the future.
+
+=head1 PUBLIC KERNEL METHODS
+
+POE::Kernel contains methods to manage the kernel itself, sessions,
+and resources such as files, signals and alarms.
+
+=head2 Kernel Management Methods
+
+=over 4
+
+=item *
+
+POE::Kernel::run()
+
+POE::Kernel::run() starts the kernel's event loop. It will not until
+all its sessions have stopped. There are two corolaries to this rule:
+It will return immediately if there are no sessions; and if sessions
+never exit, neither will run().
+
+=back
+
+=head2 Session Management Methods
+
+=over 4
+
+=item *
+
+POE::Kernel::session_create(...)
+
+POE::Kernel::session_create(...) creates a new session in the kernel.
+It is an alias for POE::Session::new(...), and it accepts the same
+parameters. Please see POE::Session::new(...) for more information.
+
+As of version 0.07, POE::Session is a proper object with public
+methods and everything. Therefore session_create is depreciated
+starting with version 0.07.
+
+=back
+
+=head2 Event Management Methods
+
+Events tell sessions which state to invoke next. States are defined
+when sessions are created. States may also be added, removed or
+changed at runtime by POE::Kernel::state(), which acts on the current
+session.
+
+There are a few ways to send events to sessions. Events can be
+posted, in which case the kernel queues them and dispatches them in
+FIFO order. States can also be called immediately, bypassing the
+queue. Immediate calls can be useful for "critical sections"; for
+example, POE's I/O abstractions use call() to minimize event latency.
+
+=over 4
+
+=item *
+
+POE::Kernel::post( $destination, $state, @args )
+
+POE::Kernel::post places an event in the kernel's queue. The kernel
+dispatches queued events in FIFO order. When posted events are
+dispatched, their corresponding states are invoked in a scalar
+context, and their return values are discarded. Signal handlers work
+differently, but they're not invoked as a result of post().
+
+If a state's return value is important, there are at least two ways to
+get it. First, have the $destination post a return vent to its
+$_[SENDER]; second, use POE::Kernel::call() instead.
+
+POE::Kernel::post returns undef on failure, or an unspecified defined
+value on success. $! is set to the reason why the post failed.
+
+=item *
+
+POE::Kernel::yield( $state, @args )
+
+POE::Kernel::yield is an alias for posting an event to the current
+session. It does not immediately swap call stacks like yield() in
+real thread libraries might. If there's a way to do this in perl, I'd
+sure like to know.
+
+=item *
+
+POE::Kernel::call( $session, $state, $args)
+
+POE::Kernel::call immediately dispatches an event to a session.
+States invoked this way are evaluated in a scalar context, and call()
+returns their return values.
+
+call() can exercise bugs in perl and/or the C library (we're not
+really sure which just yet). This only seems to occur when one state
+(state1) is destroyed from another state (state0) as a result of
+state0 being called from state1.
+
+Until that bug is pinned down and fixed, if your program dumps core
+with a SIGSEGV, try changing your call()s to post()s.
+
+call() returns undef on failure. It may also return undef on success,
+if the called state returns success. What a mess. call() also sets
+$! to 0 on success, regardless of what it's set to in the called
+state.
+
+=back
+
+=head2 Alarm Management Methods
+
+Alarms are just events that are scheduled to be dispatched at some
+later time. POE's queue is a priority queue keyed on time, so these
+events go to the appropriate place in the queue. Posted events are
+really enqueued for "now" (defined as whatever time() returns).
+
+If Time::HiRes is available, POE will use it to achieve better
+resolution on enqueued events.
+
+=over 4
+
+=item *
+
+POE::Kernel::alarm( $state, $time, @args )
+
+The alarm() method enqueues an event with a future dispatch time,
+specified in seconds since whatever epoch time() uses (usually the
+UNIX epoch). If $time is in the past, it will be clipped to time(),
+making the alarm() call synonymous to post() but with some extra
+overhead.
+
+Alarms are keyed by state name. That is, there can be only one
+pending alarm for any given state. This is a design bug, and there
+are plans to fix it.
+
+It is possible to remove an alarm that hasn't yet been dispatched:
+
+ $kernel->alarm( $state ); # Removes the alarm for $state
+
+Subsequent alarms set for the same name will overwrite previous ones.
+This is useful for timeout timers that must be continually refreshed.
+
+The alarm() method can be misused to remove events from the kernel's
+queue. This happens because alarms are merely events scheduled for a
+future time. This behavior is considered to be a bug, and there are
+plans to fix it.
+
+=item *
+
+POE::Kernel::delay( $state, $seconds, @args );
+
+The delay() method is an alias for:
+
+ $kernel->alarm( $state, time() + $seconds, @args );
+
+However, because time() is called within the POE::Kernel package, it
+uses Time::HiRes if it's available. This saves programs from having
+to figure out if Time::HiRes is available themselves.
+
+All the details for POE::Kernel::alarm() apply to delay() as well.
+For example, delays may be removed by omitting the $seconds and @args
+parameters:
+
+ $kernel->delay( $state ); # Removes the delay for $state
+
+And delay() can be misused to remove events from the kernel's queue.
+Please see POE::Kernel::alarm() for more information.
+
+=back
+
+=head2 Alias Management Methods
+
+Aliases allow sessions to be referenced by name instead of by session
+reference. They also allow sessions to remain active without having
+selects or events. This provides support for "daemon" sessions that
+act as resources but don't necessarily have resources themselves.
+
+Aliases must be unique. Sessions may have more than one alias.
+
+=over 4
+
+=item *
+
+POE::Kernel::alias_set( $alias )
+
+The alias_set() method sets an alias for the current session.
+
+It returns 1 on success. On failure, it returns 0 and sets $! to one
+of:
+
+ EEXIST - The alias already exists for another session.
+
+=item *
+
+POE::Kernel::alias_remove( $alias )
+
+The alias_remove() method removes an alias for the current session.
+
+It returns 1 on success. On failure, it returns 0 and sets $! to one
+of:
+
+ ESRCH - The alias does not exist.
+ EPERM - The alias belongs to another session.
+
+=item *
+
+POE::Kernel::alias_resolve( $alias )
+
+The alias_resolve() method returns a session reference corresponding
+to the given alias. POE::Kernel does this internally, so it's usually
+not necessary.
+
+It returns a session reference on success. On failure, it returns
+undef and sets $! to one of:
+
+ ESRCH - The alias does not exist.
+
+=back
+
+=head2 Select Management Methods
+
+Selects are filehandle monitors. They generate events to indicate
+when activity occurs on the filehandles they watch. POE keeps track
+of how many selects are watching a filehandle, and it will close the
+file when nobody is looking at it.
+
+There are three types of select. Each corresponds to one of the bit
+vectors in Perl's four-argument select() function. "Read" selects
+generate events when files become ready for reading. "Write" selects
+generate events when files are available to be written to. "Expedite"
+selects generate events when files have out-of-band information to be
+read.
+
+=over 4
+
+=item *
+
+POE::Kernel::select( $filehandle, $rd_state, $wr_state, $ex_state )
+
+The select() method manipulates all three selects for a filehandle at
+the same time. Selects are added for each defined state, and selects
+are removed for undefined states.
+
+=item *
+
+POE::Kernel::select_read( $filehandle, $read_state )
+
+The select_read() method adds or removes a filehandle's read select.
+It leaves the other two unchanged.
+
+=item *
+
+POE::Kernel::select_write( $filehandle, $write_state )
+
+The select_write() method adds or removes a filehandle's write select.
+It leaves the other two unchanged.
+
+=item *
+
+POE::Kernel::select_expedite( $filehandle, $expedite_state )
+
+The select_expedite() method adds or removes a filehandle's expedite
+select. It leaves the other two unchanged.
+
+=back
+
+=head2 Signal Management Methods
+
+The kernel generates B<_signal> events when it receives signals from
+the operating system. Sessions may also send signals between
+themselves without involving the OS.
+
+The kernel determines whether or not signals have been handled by
+looking at B<_signal> states' return values. If the state returns
+logical true, then it means the signal was handled. If it returns
+false, then the kernel assumes the signal wasn't handled.
+
+POE will stop sessions if they don't handle some signals. These
+"terminal" signals are QUIT, INT, KILL, TERM and HUP.
+
+Finally, there is one fictitious signal that always stops a session:
+ZOMBIE. When the kernel runs out of events to dispatch, and when
+there are no alarms or selects to generate new events, it sends ZOMBIE
+to any remaining sessions. This lets these sessions (usually aliased
+"daemon" sessions) that nothing is left to do, and they're as good as
+dead anyway.
+
+It's normal for daemon sessions to receive ZOMBIE when all the
+sessions that may use them have gone away.
+
+=over 4
+
+=item *
+
+POE::Kernel::sig( $signal_name, $state_name )
+
+The sig() method registers a state to handle a particular signal.
+Only one state in any given session may be registered for a particular
+signal. Registering a second state for the same signal will replace
+the previous state with the new one.
+
+=item *
+
+POE::Kernel::signal( $session, $signal_name )
+
+The signal() method posts a signal event to a session. It uses the
+kernel's event queue, bypassing the operating system, so the signal's
+name is not limited to what the OS allows. For example, the kernel
+does something similar to post a fictitious ZOMBIE signal.
+
+ $kernel->signal($session, 'BOGUS'); # Not as bogus as it sounds.
+
+=back
+
+=head2 State Management Methods
+
+The kernel's state management method lets sessions add, change and
+remove states at runtime. Wheels use this to add and remove select
+states from sessions when they're created and destroyed.
+
+=over 4
+
+=item *
+
+POE::Kernel::state( $state_name, $code_reference )
+POE::Kernel::state( $method_name, $object_reference )
+POE::Kernel::state( $function_name, $package_name )
+
+The state() method has three different uses, each for adding, updating
+or removing a different kind of state. It manipulates states in the
+current session.
+
+ $kernel->state($state_name, $code_reference); # inline state
+ $kernel->state($method_name, $object_reference); # object state
+ $kernel->state($function_name, $package_name); # package state
+
+It returns 1 on success. On failure, it returns 0 and sets $! to one
+of:
+
+ ESRCH - Somehow, the current session does not exist.
+
+This function can only register or remove one state at a time.
+
+=back
+
+=head1 SEE ALSO
+
+POE; POE::Session
+
+=head1 BUGS
+
+Oh, probably some.
+
+=head1 AUTHORS & COPYRIGHTS
+Please see the POE manpage.
-# Theory of operation:
-#
-# Kernel keeps a master queue. This holds active sessions in a
-# time-based "priority" queue.
-#
-# The queue's "key" is the time that a session will next need
-# attention. This is the time of the next event in the session's
-# queue.
-#
-# The queue's "value" is a reference to the session (or perhaps
-# session ID) that points to the session for dispatching.
-#
-# So:
-
-my $kernel = bless {}, 'POE::Kernel';
-$kernel->[KR_MASTER_QUEUE] =
- [ [ $time, $session ],
- [ $time, $session ],
- ...
- ];
-
-# Sorted in $time order.
-#
-# Inser
+=cut
View
551 lib/POE/Session.pm
@@ -1,9 +1,5 @@
# $Id$
-# Copyright 1998 Rocco Caputo <troc@netrus.net>. All rights reserved.
-# This program is free software; you can redistribute it and/or modify
-# it under the same terms as Perl itself.
-
package POE::Session;
use strict;
@@ -136,9 +132,7 @@ sub create {
my %params = @params;
- my $self = bless { 'namespace' => { },
- 'options' => { },
- }, $type;
+ my $self = bless [ { }, { } ], $type;
if (exists $params{'args'}) {
if (ref($params{'args'}) eq 'ARRAY') {
@@ -298,57 +292,532 @@ sub register_state {
sub option {
my $self = shift;
- push(@_, 0) if (scalar(@_) & 1);
- my %parameters = @_;
+ my %return_values;
- while (my ($flag, $value) = each(%parameters)) {
+ while (@_ >= 2) {
+ my ($flag, $value) = splice(@_, 0, 2);
+ $flag = lc($flag);
+ # set the value, if defined
+ if (defined $value) {
# booleanize some handy aliases
- ($value = 1) if ($value =~ /^(on|yes)$/i);
- ($value = 0) if ($value =~ /^(no|off)$/i);
- # set or clear the option
- if ($value) {
- $self->[SE_OPTIONS]->{lc($flag)} = $value;
+ ($value = 1) if ($value =~ /^(on|yes|true)$/i);
+ ($value = 0) if ($value =~ /^(no|off|false)$/i);
+
+ $return_values{$flag} = $self->[SE_OPTIONS]->{$flag};
+ $self->[SE_OPTIONS]->{$flag} = $value;
}
+ # remove the value, if undefined
else {
- delete $self->[SE_OPTIONS]->{lc($flag)};
+ $return_values{$flag} = delete $self->[SE_OPTIONS]->{$flag};
}
}
+ # only one option? fetch it.
+ if (@_) {
+ my $flag = lc(shift);
+ $return_values{$flag} =
+ ( exists($self->[SE_OPTIONS]->{$flag})
+ ? $self->[SE_OPTIONS]->{$flag}
+ : undef
+ );
+ }
+ # only one option? return it
+ my @return_keys = keys(%return_values);
+ if (@return_keys == 1) {
+ return $return_values{$return_keys[0]};
+ }
+ else {
+ return \%return_values;
+ }
}
###############################################################################
1;
-
__END__
-#------------------------------------------------------------------------------
-# Enqueue an event.
+=head1 NAME
+
+POE::Session - POE State Machine
+
+=head1 SYNOPSIS
+
+ # Original inline session constructor:
+ new POE::Session(
+ name1 => \&name1_handler, # \&name1_handler handles the "name1" event
+ name2 => sub { ... }, # anonymous sub handles the "name2" event
+ \@start_args, # ARG0..ARGn for the session's _start handler
+ );
+
+ # Original package session constructor:
+ new POE::Session(
+ $package, [ 'name1', # $package->name1() handles "name1" event
+ 'name2', # $package->name2() handles "name2" event
+ ],
+ \@start_args, # ARG0..ARGn for the session's _start handler
+ );
+
+ # Original object session constructor:
+ my $object1 = new SomeObject(...);
+ my $object2 = new SomeOtherObject(...);
+ new POE::Session(
+ # $object1->name1() handles the "name1" event;
+ # $object1->name2() handles the "name2" event;
+ $object1 => [ 'name1', 'name2' ],
+ # $object2->name1() handles the "name3" event;
+ # $object2->name2() handles the "name3" event;
+ $object2 => [ 'name3', 'name4' ],
+ \@start_args, # ARG0..ARGn for the session's _start handler
+ );
-name is public
-_name is friend
-__name is private
+ # New constructor:
+ create POE::Session(
+ # ARG0..ARGn for the session's _start handler
+ args => \@args,
+ inline_states => { state1 => \&handler1, state2 => \&handler2, ... },
+ object_states => { $objref1 => \@methods2, $objref2 => \@methods2, ... },
+ package_states => { $package1 => \@function_names_1,
+ $package2 => \@function_names_2, ...
+ },
+ );
-sub _enqueue_event {
- my ($self, $sender, $state, $priority, $time, $etc) = @_;
+ # Set or clear some session options:
+ $session->option( trace => 1, default => 1 );
- # Place the event is the session's queue.
+=head1 DESCRIPTION
- #
- # If "concurrent" POE:
- # Start or unblock the session's dispatch thread.
- # End
- #
- # Return the number of events in the session's queues.
+(Note: Session constructors were changed in version 0.06. Processes
+no longer support multiple kernels. This made the $kernel parameter
+to session constructors obsolete, so it was removed.)
-}
+POE::Session is a generic state machine class. Session instances are
+driven by state transition events, dispatched by POE::Kernel.
-sub _dispatch_event {
- my ($self) = @_;
+Sessions are POE's basic, self-contained units of program execution.
+They are equivalent to operating system processes or threads. As part
+of their creation, sessions register themselves with the process'
+Kernel instance. The kernel will keep track of their resources, and
+perform garbage collection at appropriate times.
- # If "concurrent" POE:
- # Return 1 if there are no events but the session has resources to keep it active.
- # Return 0 if there are no events and the session is "stalled".
- # Otherwise, "regular" POE:
- # Dispatch an event, and return the number of events left in the queue.
- # End
-}
+=head1 PUBLIC METHODS
+
+=over 4
+
+=item *
+
+new
+
+POE::Session::new() is the original, highly overloaded constructor
+style. It creates a new POE::Session instance, populated with states
+given as its parameters.
+
+A reference to the new session will be given to the process' Kernel
+instance. The kernel will manage the session and its resources, and
+it expects perl to destroy the session when it releases its reference.
+
+The constructor will also return a reference to the new session. This
+reference may be used directly, but keeping a copy of it will prevent
+perl from garbage collecting the session when the kernel is done with
+it. Some uses for the session reference include posting "bootstrap"
+events to the session or manipulating the session's options with its
+option() method.
+
+Some people consider the new() constructor awkward, or "action at a
+distance". POE provides a semantically "sweeter" Kernel method,
+POE::Kernel::session_create() for these people. Please note, however,
+that session_create is depreciated as of version 0.06_09, since
+POE::Session has become a proper object.
+
+POE::Session::new() accepts pairs of parameters, with one exception.
+The first parameter in the pair determines the pair's type. The pairs
+may be used interchangeably:
+
+Inline states are described by a scalar and a coderef. The scalar is
+a string containing the state's name, which is also the name of the
+event that will trigger the state. The coderef is the Perl subroutine
+that will be called to handle the event.
+
+ new POE::Session( event_name => \&state_handler );
+
+Object states are described by an object reference and a reference to
+an array of method names. The named methods will be invoked to handle
+similarly named events.
+
+ my $object = new Object;
+ new POE::Session( $object => [ 'method1', 'method2', 'method3' ] );
+
+Package states are described by a package name and a reference to an
+array of subroutine names. The subroutines will handle events with
+the same names. If two or more packages are listed in the
+constructor, and the packages have matching subroutine names, then the
+last one wins.
+
+ new POE::Session( 'Package' => [ 'sub1', 'sub2', 'sub3' ] );
+
+Sessions may use any combination of Inline, Object and Package states:
+
+ my $object = new Object;
+ new POE::Sessio( event_name => \&state_handler,
+ $object => [ 'method1', 'method2', 'method3' ],
+ 'Package' => [ 'sub1', 'sub2', 'sub3' ]
+ );
+
+There is one parameter that isn't part of a pair. It is a stand-alone
+array or list reference, the contents of which are sent as arguments
+to the session's B<_start> state.
+
+=item *
+
+create
+
+POE::Session::create() is a new constructor style. It does not use
+parameter overloading and DWIM to discern different session types.
+
+Please see the SYNOPSIS for create() usage.
+
+=item *
+
+option
+
+POE::Session::option() stores, fetches or removes a session's option.
+Options are similar to environment variables.
+
+The option() method's behavior changed in version 0.06_09. It now
+supports fetching option values without changing or deleting the
+option.
+
+ $session->option( 'name1' ); # Fetches option 'name1'
+ $session->option( name2 => undef ); # Deletes option 'name2'
+ $session->option( name3 => 1, name4 => 2 ); # Sets 'name3' and 'name4'
+
+Actually, option() always returns the values of the options its
+passed. If more than one option is supplied in the parameters, then
+option() returns a reference to a hash containing names and previous
+values. If a single option is specified, then option() returns its
+value as a scalar.
+
+These are the options that POE currently uses internally. Others may
+be added later.
+
+=over 2
+
+=item *
+
+trace
+
+Accepts a logical true/false value. This option enables or disables a
+trace of events as they're dispatched to states.
+
+=item *
+
+default
+
+Accepts a logical true/false value. When the "default" option is
+enabled, POE will carp and confess about events that arrive but can't
+be dispatched. Note: The "default" option will not do anything if the
+session has a B<_default> state, because then every event can be
+dispatched.
+
+=back
+
+ $session->option( trace => 1, default => 0 );
+
+Logical values may be sent as either 1, 0, 'on', 'off', 'yes', 'no',
+'true' or 'false'.
+
+POE::Session::option() only changes the options that are present as
+parameters. Unspecified options are left alone.
+
+=back
+
+=head1 STATE PARAMETERS
+
+State parameters changed in version 0.06. Before 0.06, inline
+handlers received different parameters than object and package
+handlers. The call signatures have been unified in version 0.06.
+This breaks programs written with POE 0.05 or earlier. Thankfully,
+there aren't many.
+
+To prevent future breakage, POE::Session now exports constants for
+parameters' offsets into @_. Programs that use the constants are
+guaranteed not to break whenever states' call signatures change. Or,
+if parameters are removed, programs will break at compile time rather
+than mysteriously failing at runtime.
+
+Parameters may be used discretely:
+
+ $_[KERNEL]->yield('next_state');
+
+If several parameters are needed multiple times, it may be easier (and
+faster) to assign them to lexicals all at once with an array slice:
+
+ my ($kernel, $operation, $errnum, $errstr) =
+ @_[KERNEL, ARG0, ARG1, ARG2];
+
+The parameter constants are:
+
+=over 4
+
+=item *
+
+OBJECT
+
+The value in $_[OBJECT] is dependent on how the state was defined. It
+is undef for inline states. For object states, it contains a
+reference to the object that owns the method being called. For
+package states, it contains the name of the package the subroutine
+exists in.
+