Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Big documentation rewrite

  • Loading branch information...
commit d8788af8423935475cb3289e2faa2419cc9681fd 1 parent 8d8e66d
@rcaputo authored
View
40 Changes
@@ -15,12 +15,48 @@ make dist on it! 0.0910 is ``v0_0910''! For example:
,----- To Do -----
|
-| Overhaul Kernel and Session manpages' DESCRIPTIONs.
| Create a test program for fork and sigchld.
-| Don't forget to document the Tk support.
+| Still can't get Event to compile on 5.6.0+OS/2 or 5.005+61+FreeBSD;
+| be sure to mark Event experimental in the new documentation.
+| Make a test for Tk.
+| Make a test for Event, when it can be made to work.
+| Split the samples out into a separate distribution.
|
`-----------------
+0.1004 2000.05.21
+-----------------
+
+Rewrote the POE, POE::Kernel and POE::Session manpages. Documented Tk
+support. Documented Event support, but it's not in yet.
+
+t/04_select.t assumed that two-argument syswrite was legal, but it
+isn't back in 5.005_02. Added a length() call to make it legal on
+older perls. Thanks again, a-mused!
+
+alarm_add() would enqueue an alarm for an undefined state. Fixed it
+to ignore such requests.
+
+The call() method did not reliably set $! to zero on success. Now it
+does.
+
+(!!!) Added parameter checking and return values to the timed event
+functions: alarm, alarm_add, delay, and delay_add.
+
+(!!!) alarm() and alarm_add() no longer clip past times to time(2).
+Instead, events posted for the past will be entered into the
+appropriate places in POE's time-ordered alarm/delay queue. The
+obvious results will occur.
+
+(!!!) Changed POE::Kernel::alias_* to return 0 on success or an error
+code on failure. They no longer touch $!.
+
+(!!!) Changed POE::Kernel::state to return 0 on success or an error
+code on failure. It no longer touches $!.
+
+(!!!) Changed POE::Kernel::refcount_(in|de)crement to return the new
+reference count on success or undef on failure.
+
0.1003 2000.05.12
-----------------
View
258 README
@@ -1,251 +1,55 @@
$Id$
-TABLE OF CONTENTS
-=================
-Table of Contents; About POE; Compatibility (Non-Requirements and
-Requirements); Availability; Support Resources; Installing and
-Testing; The Future
+The bulk of this README's information has migrated to the POE manpage.
-ABOUT POE
-=========
+As POE moves closer towards the Common Sense axis, it sometimes
+diverges away from the Backwards Compatible axis. If this version is
+being installed over a previous one, please check the Changes file to
+see what it might break. Interface changes usually are documented.
-"POE" is an acronym for Perl Object Environment. This may change to
-Persistent Object Environment.
-First and foremost, it is a programming framework for event-driven
-state machines.
+POE may be installed through the CPAN shell in the usual CPAN shell
+manner. It typically is:
-POE includes high-level, functional interfaces for select, alarms,
-sockets and file I/O. The interfaces are robust but incomplete.
+ perl -MCPAN -e 'install POE'
-From different vantage points, POE may look like other things:
+It involves a little more work if you have an older CPAN shell:
- It may seem to be a cooperative multithreading model.
- It may be interpreted as a portable component architecture.
+ perl -MCPAN -e shell
+ install POE
-Because it implements a low-level programming concept, POE can do many
-things.
+POE can also be installed manually. The latest CPAN version can be
+found at <ftp://ftp.cpan.org/pub/CPAN/authors/id/R/RC/RCAPUTO/> or in
+a similarl named directory at your favorite CPAN mirror. The most
+recent development snapshot, which only rarely contains heinous
+showstopper bugs, is available from the author's web site at
+<http://www.newts.org/~troc/poe.html>.
-COMPATIBILITY
-=============
+Downloading and unpacking the distribution are left as an exercise for
+the reader. To "build" and test it afterwards:
-General
--------
-
-POE has been tested with as many Perl versions as the author (and
-testing pool) can find. This includes Linux, FreeBSD, and OS/2, all
-of which support enough of POSIX to run POE. 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://testers.cpan.org/search?request=dist&dist=POE
-
-If you have news about breakage or success that's not documented,
-please let me know. Thank you!
-
-
-Windows
--------
-
-The half-tested Windows support that was removed in 0.0806 turns out
-to be necessary and useful. It was put back in version 0.0807, and at
-least one Windows user, Douglas Couch <purdue.edu!dscouch>, has found
-joy using POE.
-
-Doug reports that POE works with the latest stable ActivePerl, prior
-to (but not including) version 5.6.0 RC1. He says that the 5.6.0
-version includes fork() and other Unix compatibilities, but it still
-definitely seems to be beta level code.
-
-As of this writing, 5.6.0 has gone through its remaining release
-candidates and is in early "golden" distribution, so mileage most
-probably will vary.
-
-He writes:
-
- I've done some preliminary testing of the 0.0903 version and the
- re-addition of the Win32 support seems to be a success. I'll do
- some more intensive testing in the next few days to make sure
- nothing else is broken that I haven't missed.
-
-And later:
-
- After testing out my own program and having no problems with the
- newest version (with Win32 support), I thought I'd test out some of
- the samples and relay my results.
-
- filterchange.perl and preforkedserver.perl both contain fork
- commands which are still unsupported by ActiveState's port of Perl,
- so they were both unsuccessful. (this was anticipated for anything
- containing fork)
-
- ref-type.perl, refsender.perl, thrash.perl and wheels2.perl all ran
- up against the same unsupported POSIX macro. According to the error
- message, my vendor's POSIX doesn't support the macro EINPROGRESS ...q
-
- Other than those particular problems all of the other sample scripts
- ran fine.
-
-And later, after it was suggested to remove the EINPROGRESS code:
-
- > ... and running something that connects to an outbound server,
- > such as samples/proxy.perl. The normal "connection in progress"
- > state will become a failure, and the proxy will die in "connect"
- > with an error number and name.
-
- Ummmm... would you believe I did this and couldn't get it to break?
- I think I need to play a bit with the proxy settings in the sample,
- I couldn't make it do an http proxy, but I also couldn't make it
- break.
-
-... so POE includes a fake EINPROGRESS constant on MSWin32 systems.
-
-P.S.: If you've just skipped ahead to read about Windows, you should
-skip back one section, to the General compatibility information, which
-may still apply.
-
-
-MacOS
------
-
-Macintosh users have rumored that POE might work on MacOS, but none of
-them have stepped forward with actual failure or success reports. It
-would be greatly appreciated if someone could confirm or deny
-something. Anything? Bueller?
-
-
-Non-requirements
-----------------
-
-POE is compatible with fork(), but it is only used upon request. This
-distribution includes a sample server that uses a pool of forked
-children.
-
-POE will use Time::HiRes, if it's available. Nothing untoward should
-happen if it's not, unless you use one of the sample programs that
-absolutely requires it.
-
-POE currently uses no XS in its implementation. It should work
-wherever a sufficiently complete version of Perl does.
-
-
-Requirements
-------------
-
-As of version 0.1001, POE requires Filter::Call::Util, from the Filter
-distribution. It uses this module in POE::Preprocessor, which is a
-source filter that preprocesses macros, constants and enumerations.
-Filter 1.17 does not compile properly for threaded builds, so you will
-need 1.18 or later. If you can only acquire version 1.17 of the
-source filters modules, then also apply the patch posted to
-perl5-porters in this message:
-
- Message-Id: <E12YUJG-00042g-00@mserv1a.u-net.net>
-
-For portability, POE uses POSIX system calls and constants. There
-should be no problem running it on systems that have sufficient POSIX
-support.
-
-Some of POE's sample programs 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, and it's checked
-first. The Reference filter can also use Compress::Zlib upon request,
-but it works without it too.
-
-Filter::HTTPD requires a small world of modules: HTTP::Status;
-HTTP::Request; HTTP::Date and URI::URL.
-
-The httpd.perl sample program uses Filter::HTTPD, which uses all that
-other stuff.
-
-The preforkedserver.perl sample program uses POE::Kernel::fork(),
-which in turn uses the fork() built-in. This may or 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
-============
-
-The latest stable release of POE is available three ways:
-
-1:
-
- ``perl -MCPAN -e shell'' Then type ``install POE'' at the CPAN
- prompt.
-
-2:
-
- In the /authors/id/R/RC/RCAPUTO/ on your favorite CPAN mirror. This
- is where the CPAN shell gets it.
-
- 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.
-
-3:
-
- Beta versions of the next release are available from the author.
- They 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.
-
- Relatively stable betas are available from the POE web page, at
- <http://www.newts.org/~troc/>.
-
-
-SUPPORT RESOURCES
-=================
-
-Places on the Internet where you can find more information about POE:
-
-
-POE has a mailing list thanks to Arturn Bergman. You may subscribe to
-it by sending e-mail:
-
- From: (the address to which you want your mail sent)
- To: poe-help@vogon.se
- Subject: (anything will do)
-
- Anything will do for the body.
-
-All forms of feedback are welcome.
-
-
-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/>.
+ perl Makefile.PL
+ make test
+The POE manpage discusses system requirements and compatibility
+issues. You can preview it with:
-INSTALLING AND TESTING
-======================
+ perldoc ./POE.pm
-If you've been using POE since before 0.06, please, PLEASE read the
-Changes file before installing. Many things have been broken between
-versions 0.05 and 0.06.
+There are several sample programs in the samples subdirectory. The
+POE manpage briefly explains them.
-To build and test this distribution, type:
+ ls -l samples
- perl Makefile.PL
- make
- make test
+Finally you can install it:
-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.
+ make install
-Once everything looks good, POE can be installed by typing:
- make install
+Good luck, and thank you for reading!
--- Rocco Caputo / troc@netrus.net / Thank you for reading.
+-- Rocco Caputo / troc@netrus.net
View
1,066 lib/POE.pm
@@ -7,7 +7,7 @@ use strict;
use Carp;
use vars qw($VERSION);
-$VERSION = 0.1003;
+$VERSION = 0.1004;
sub import {
my $self = shift;
@@ -43,220 +43,420 @@ __END__
=head1 NAME
-POE - A Perl Object Environment
+POE - a persistent object environment
=head1 SYNOPSIS
- # Basic usage:
+ #!/usr/bin/perl -w
+ use strict;
+ # Use POE!
use POE;
- # create initial sessions here
+
+ # Every machine is required to have a special state, _start, which
+ # is used to the machine it has been successfully instantiated.
+ # $_[KERNEL] is a reference to the process' global POE::Kernel
+ # instance; $_[HEAP] is the session instance's local storage;
+ # $_[SESSION] is a reference to the session instance itself.
+
+ sub state_start {
+ my ($kernel, $heap, $session) = @_[KERNEL, HEAP, SESSION];
+ print "Session ", $session->ID, " has started.\n";
+ $heap->{count} = 0;
+ $kernel->yield('increment');
+ }
+
+ sub state_increment {
+ my ($kernel, $heap, $session) = @_[KERNEL, HEAP, SESSION];
+ print "Session ", $session->ID, " counted to ", ++$heap->{count}, ".\n";
+ $kernel->yield('increment') if $heap->{count} < 10;
+ }
+
+ # The _stop state is special but not required. POE uses it to tell
+ # a session instance that it is about to be destroyed. Stop states
+ # contain last-minute resource cleanup, which often isn't necessary
+ # since POE destroys $_[HEAP], and resource destruction cascades
+ # down from there.
+
+ sub state_stop {
+ print "Session ", $_[SESSION]->ID, " has stopped.\n";
+ }
+
+ # Start ten instances of a session. POE::Session constructors map
+ # state names to the code that handles them.
+
+ for (0..9) {
+ POE::Session->create(
+ inline_states =>
+ { _start => \&state_start,
+ increment => \&state_increment,
+ _stop => \&state_stop,
+ }
+ );
+ }
+
+ # Start the kernel, which will run as long as there are sessions.
+
$poe_kernel->run();
exit;
- # Typical usage:
+=head1 DESCRIPTION
+
+POE is an acronym of "Persistent Object Environment". It originally
+was designed as the core of a persistent object server where clients
+and autonomous objects could interact in a sort of "agent space". It
+was, in this regard, very much like a MUD. Evolution, however, seems
+to have other plans.
+
+POE's heart is a framework for event driven state machines. This
+heart has two chambers: an event dispatcher and state machines that
+are driven by dispatched events. The modules are, respectively,
+POE::Kernel and POE::Session.
+
+The remainder of POE consists of modules that help perform high-level
+functions. For example, POE::Wheel::ReadWrite encapsulates the logic
+for select-based I/O. Module dependencies always point towards lower
+level code. POE::Kernel and POE::Session, being at the lowest level,
+need none of the others. Since they are always required, they will be
+used whenever POE itself is.
+
+=head1 USING POE
+
+Using POE modules can be pretty tedious. Consider this example, which
+pulls in the necessary modules for a line-based TCP server:
+
+ use POE::Kernel;
+ use POE::Session;
+ use POE::Wheel::SocketFactory;
+ use POE::Wheel::ReadWrite;
+ use POE::Filter::Line;
+ use POE::Driver::SysRW;
+
+Using POE directly optimizes this for laziness in two ways. First, it
+brings in POE::Kernel and POE::Session for you. Second, subsequent
+modules can be passed as parameters to the POE module without the
+"POE::" prefix.
+
+The preceding example can then be written as:
use POE qw( Wheel::SocketFactory Wheel::ReadWrite
- Driver::SysRW Filter::Line
+ Filter::Line Driver::SysRW
);
- # create initial sessions here
+
+=head1 WRITING POE PROGRAMS
+
+Basic POE programs consist of four parts.
+
+=over 2
+
+=item *
+
+Preliminary program setup
+
+This is the usual overhead for writing a Perl program: a C<#!> line,
+perhaps some C<use> statements to import things, and maybe some global
+variables or configuration constants. It's all pretty standard stuff.
+
+ #!/usr/bin/perl -w
+ use strict;
+ use POE;
+
+=item *
+
+Define the program's states
+
+Here's where the code for each state is defined. In a procedural
+program, it would be where subroutines are defined. This part is
+optional in smaller programs, since states may be defined as inline
+anonymous coderefs when machines are instantiated.
+
+ sub state_start {
+ ...
+ }
+
+ sub state_increment {
+ ...
+ }
+
+ sub state_stop {
+ ...
+ }
+
+=item *
+
+Instantiate initial machines
+
+POE's kernel stops when there are no more sessions to generate or
+receive transition events. A corolary to this rule: The kernel won't
+even begin unless a session first has been created. The SYNOPSIS
+example starts ten state machines to illustrate how POE may simulate
+threads through cooperative timeslicing. In other words, several
+things may be run "concurrently" by taking a little care in their
+design.
+
+ for (0..9) {
+ POE::Session->create(
+ inline_states =>
+ { _start => \&state_start,
+ increment => \&state_increment,
+ _stop => \&state_stop,
+ }
+ );
+ }
+
+=item *
+
+Start the kernel
+
+Almost nothing will happen until the event dispatcher starts. A
+corolary to this rule: Nothing of much consequence will happen until
+the kernel is started. As was previously mentioned, the kernel won't
+return until everything is finished. This usually (but not
+necessarily) means the entire program is done, so it's common to exit
+or otherwise let the program end afterwards.
+
$poe_kernel->run();
exit;
-=head1 DESCRIPTION
+=back
+
+
+=head1 POE's ARCHITECTURE
+
+POE is built in distinct strata: Each layer requires the ones beneath
+it but not the ones above it, allowing programs to use as much code as
+they need but no more. The layers are:
+
+=over 2
+
+=item *
+
+Events layer
+
+This was already discussed earlier. It consists of an event
+dispatcher, POE::Kernel, and POE::Session, which is a generic state
+machine.
+
+=item *
+
+The "Wheels" I/O abstraction
+
+POE::Wheel is conceptually similar to a virus. When one is
+instantiated, it injects its code into the host session. The code
+consists of some unspecified states that perform a particular job.
+Unlike viruses, wheels remove their code when destroyed.
+
+POE comes with four wheels so far:
+
+=over 2
+
+=item *
+
+POE::Wheel::FollowTail
+
+FollowTail follows the tail of an ever-growing file. It's useful for
+watching logs or pipes.
+
+=item *
+
+POE::Wheel::ListenAccept
+
+ListenAccept performs ye olde non-blocking socket listen and accept.
+It's depreciated by SocketFactory, which does all that and more.
+
+=item *
+
+POE::Wheel::ReadWrite
+
+ReadWrite is the star of the POE::Wheel family. It performs buffered
+I/O on unbuffered, non-blocking filehandles. It almost acts like a
+Unix stream, only the line disciplines don't yet support push and pop.
+
+ReadWrite uses two other classes to do its dirty work: Driver and
+Filter. Drivers do all the work, reading and/or writing from
+filehandles. Filters do all the other work, translating serialized
+raw streams to and from logical data chunks.
+
+Drivers first:
+
+=over 2
+
+=item *
+
+POE::Driver::SysRW
+
+This is the only driver currently available. It performs sysread and
+syswrite on behalf of Wheel::ReadWrite. Other drivers, such as
+SendRecv, are possible, but so far there hasn't been a need for them.
+
+=back
+
+Filters next:
+
+=over 2
+
+=item *
+
+POE::Filter::HTTPD
+
+This filter parses input as HTTP requests, translating them into
+HTTP::Request objects. It accepts responses from the program as
+HTTP::Response objects, serializing them back into streamable HTTP
+responses.
+
+=item *
+
+POE::Filter::Line
+
+The Line filter parses incoming streams into lines and serializes
+outgoing lines into streams. It's very basic.
+
+=item *
+
+POE::Filter::Reference
+
+The Reference filter is used for sending Perl structures between POE
+programs. The sender provides references to structures, and
+Filter::Reference serializes them with Storable, FreezeThaw, or a
+serializer of your choice. Data may optionally be compressed if Zlib
+is installed.
+
+The receiving side of this filter takes serialized data and thaws it
+back into perl data structures. It returns a reference to the
+reconstituted data.
+
+=item *
+
+POE::Filter::Stream
+
+Filter::Stream does nothing of consequence. It passes data through
+without any change.
+
+=back
+
+=item *
+
+POE::Wheel::SocketFactory
+
+SocketFactory creates sockets. When creating connectionless sockets,
+such as UDP, it returns a fully formed socket right away. For
+connecting sockets which may take some time to establish, it returns
+when a connection finally is made. Listening socket factories may
+return several sockets, one for each successfully accepted incoming
+connection.
+
+=back
+
+=back
+
+=head1 POE COMPONENTS
+
+A POE component consists of one or more state machines that
+encapsulates a very high level procedure. For example,
+POE::Component::IRC (not included) performs nearly all the functions
+of a fully featured IRC client. This frees programmers from the
+tedium of working directly with the protocol, instead letting them
+focus on what the client will actually do.
+
+POE comes with only one core component, POE::Component::Server::TCP.
+It is a thin wrapper around POE::Wheel::SocketFactory, providing the
+wheel with some common default states. This reduces the overhoad
+needed to create TCP servers to its barest minimum.
+
+To-do: Publish a POE component SDK, which should amonut to little more
+than some recommended design guidelines and MakeMaker templates for
+CPAN publication.
+
+=head1 Support Modules
+
+Finally, there are some modules which aren't directly used but come
+with POE. These include POE::Preprocessor and the virtual base
+classes: POE::Component, POE::Driver, POE::Filter and POE::Wheel.
+
+POE::Preprocessor is a macro processor. POE::Kernel and POE::Session
+use it to inline common code, making the modules faster and easier to
+maintain. There seem to be two drawbacks, however: Code is more
+difficult to examine from the Perl debugger, and programs take a
+little longer to start. The compile-time penalty is negligible in the
+types of long-running programs POE excels at, however.
+
+POE::Component exists merely to explain the POE::Component subclasses,
+as do POE::Driver, POE::Filter and POE::Wheel. Their manpages also
+discuss options and methods which are common across all their
+subclasses.
-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 resembles 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 24 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.
+=head1 ASCII ART
+
+The ASCII art is gone. If you want pretty pictures, contact the
+author. He's been looking for excuses to sit down with a graphics
+program.
+
+=head1 OBJECT LAYER
+
+The object layer has fallen into disrepair again, and the author is
+considering splitting it out as a separate Component. If you've been
+looking forward to it, let him know so he'll have an excuse to
+continue with it.
+
+=head1 SAMPLE PROGRAMS
+
+The POE contains 28 sample programs as of this writing. They reside
+in the archive's ./poe/samples directory. The author is considering
+moving them to a separate distribution to cut back on the archive's
+size.
+
+Please contact the author or the POE mailing list if you'd like to see
+something that isn't here.
+
+=head2 Tutorials
+
+POE's documentation is merely a reference. It may not explain why
+things happen or how to do things with POE. The tutorial samples are
+meant to compensate for this in some small ways.
+
+=over 2
+
+=item *
+
+tutorial-chat.perl
+
+This is the first and only tutorial to date. It implements a simple
+chat server (not web chat) with rambling narrative comments.
+
+=back
=head2 Events Layer Examples
-These sample programs demonstrate and exercise POE's events layer and
-resource management functions.
+These examples started life as test programs, but the t/*.t type tests
+are thousands of times terrificer. Now the examples exist mainly as
+just examples.
-=over 4
+=over 2
=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.
+newer POE::Session->create constructor rather than the original
+POE::Session->new one.
=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.
+The "forkbomb" test doesn't really use fork, but it applies the
+fork-til-you-puke concept to POE's sessions. Every session starts two
+more and exits. It has a 200 session limit to keep it from eating
+resources forever.
=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.
+The "names" test demonstrates two concepts: how to reference sessions
+by name, and how to communicate between sessions with an asynchronous
+ENQ/ACK protocol.
=item *
@@ -270,250 +470,383 @@ named object methods.
objsessions.perl
This program is essentially the same as sessions.perl, but it uses
-object methods as states instead of inline code references.
+object methods as states instead of inline coderefs.
=item *
packagesessions.perl
This program is essentially the same as sessions.perl, but it uses
-package functions as states instead of inline code references.
+package methods as states instead of inline coderefs.
=item *
-poing.perl
-
-This is a quick and dirty multiple-host icmp ping program. Actually,
-it's getting better as creatures feep; it may be useful enough to be a
-separate program. It requires a vt100 or ANSI terminal. It needs to
-be run by root, since it expects to open a raw socket for ICMP
-pinging.
+queue.perl
-I thank Russell Mosemann <mose@ccsn.edu> for the Net::Ping module,
-which I "borrowed" heavily from. Net::Ping is the route of choice if
-you don't need parallel ping capability.
+In this example, a single session is created to manage others beneath
+it. The main session keeps a pool of children to perform asynchronous
+tasks. Children stop as their tasks are completed, so the job queue
+controller spawns new ones to continue the work. The pool size is
+limited to constrain the example's resource use.
=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
+The "selects" example shows how to use POE's interface to select(2).
+It creates a simple chargen server and a client to visit it. The
client will disconnect after receiving a few lines from the server.
-The server will remain active, and it will accept telnet connections.
+The server will remain active until it receives SIGINT, and it will
+accept further socket connections.
=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.
+This program is a basic example of Session construction, destruction
+and maintenance. It's much more system friendly than forkbomb.perl.
=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.
+The "signals" example shows how sessions can watch for signals. It
+creates two sessions that wait for signals and periodically post soft
+signals to themselves. Soft signals avoid the underlying operating
+system, posting signal events directly through POE. This also allows
+simulated and fictitious signals.
=back
=head2 I/O Layer Examples
-These sample programs demonstrate and exercise POE's default I/O
-layer.
+These examples show how to use the Wheels abstraction.
-=over 4
+=over 2
=item *
fakelogin.perl
-This program tests the ability for POE::Wheel instances to change the
-events they emit. The port it listens on can be specified on the
-command line. Its default listen port is 23.
+The "fakelogin" example tests Wheels' ability to change the events
+they emit. The port it listens on can be specified on the command
+line, and it listens on port 23 by default.
=item *
filterchange.perl
-This program tests the ability for POE::Wheel instances to change the
-filters they use to process information.
+This example tests POE::Wheel::ReadWrite's ability to change the
+filter it's using while it runs.
=item *
followtail.perl
-This program tests POE::Wheel::FollowTail, a read-only wheel that
-follows the end of an ever-growing file.
+This program shows how to use 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.
+It creates 21 sessions: 10 that generate fictitious log files, 10 that
+follow the ends of these logs, and one timer loop to make sure none of
+the other 20 are blocking. SIGINT will cause the program to clean up
+its /tmp files and stop.
=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
+This is a test of the nifty POE::Filter::HTTPD module. The author can
+say it's nifty because he didn't write it. The sample will try
+binding to port 80 of INADDR_ANY, but it can be given a new port on
+the command line.
=item *
-ref-type.perl
+proxy.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.
+This is a simple TCP port forwarder.
=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.
+ref-type.perl
-To run this test, first start refserver, then run refsender. Check
-refserver's STDOUT to see if it received some data.
+The "ref-type" sample shows how POE::Filter::Reference can use
+specified serialization methods. It's part of Philip Gwyn's work on
+POE::Component::IKC, an XML based RPC package.
=item *
-socketfactory.perl
+refsender.perl and refserver.perl
+
+These samples use POE::Filter::Reference to pass copies of blessed and
+unblessed data between processes. The standard Storable caveats (such
+as its inability to freeze and thaw coderefs) apply.
-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.
+refserver.perl should be run first, then refsender. Check refserver's
+STDOUT to see what it received.
=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 exhaustion,
-netstat will report a lot of sockets in various WAIT states, and
-thrash.perl will show an abnormally low connections/second rate.
+This is a harsh wheel test. It sets up a simple TCP daytime server
+and a pool of clients within the same process. The clients
+continually visit the server, creating and destroying several sockets
+a second. The test will run faster (and thus be harsher on the
+system) if it is split into two processes.
=item *
udp.perl
-Udp shows how to use UDP sockets with Kernel::select calls.
+The "udp" sample shows how to create UDP sockets with IO::Socket and
+use them in POE. It was a proof of concept for the SocketFactory
+wheel's UDP support.
=item *
watermarks.perl
-This program is a cross between wheels.perl (wheel-based server) and
-selects.perl (chargen service). It creates a chargen service (on port
-32019) that uses watermark events to pause output when the unflushed
-write buffer reaches about 512 bytes. It resumes spewing chargen
-output when the client finally reads what's waiting for it.
+High and low watermarks are a recent addition to the ReadWrite wheel.
+This program revisits the author's good friend, the chargen server,
+this time implementing flow control.
-There currently is no program to act as a slow client for it. Telnet
-or other raw TCP clients may work, especially if the client is running
-at maximum niceness.
+Seeing it in action requires a slow client. Telnet or other raw TCP
+clients may work, especially if they are running at maximum niceness.
=item *
wheels.perl
-This program is a basic rot13 server. It is a basic test of the whole
-premise of wheels.
+This program is a basic rot13 server. It was used as an early test
+program for the whole Wheel abstraction's premise.
=item *
wheels2.perl
-Wheels2 shows how to use separate input and output filehandles with
-wheels. It's a simple raw tcp socket client, piping between a client
-socket and stdio (in cooked mode).
+The "wheels2" sample shows how to use separate input and output
+filehandles with a wheel. It's a simple tcp socket client, piping
+betwene a socket and stdio. Stdio is in cooked mode, with all its
+caveats.
=back
=head2 Object Layer Examples
-This program illustrates POE's Object Layer, which is still in early
-development.
+As was previously said, the object layer has fallen once again into
+disrepair. However, the olayer.perl sample program illustrates its
+current state.
-=over 4
+=head2 Proofs of Concepts
+
+These programs are prototypes for strange and wonderful concepts.
+They push POE's growth by stretching its capabilities to extrems and
+seeing where it hurts.
+
+=over 2
=item *
-olayer.perl
+preforkedserver.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.
+This example shows how to write pre-forking servers with POE. It
+tends to dump core after a while, however, due signal issues in Perl,
+so it's not recommended as an example of a long running server.
+
+One work-around is to comment out the yield('_stop') calls (there are
+two). These were added to cycle child servers. The idea was borrowed
+from Apache, which only did this to thwart runaway children. POE
+shouldn't leak memory, so churning the children shouldn't be needed.
+
+Still, it is a good test for one of POE's weaknesses. This thorn in
+the author's side will remain enabled.
+
+=item *
+
+tk.perl
+
+The "tk" example is a prototype of POE's Tk support. It sets up a Tk
+main window populated with some buttons and status displays. The
+buttons and displays demonstrate FIFO, alarm and file events in the Tk
+environment.
=back
-=head2 Proofs of Concepts
+=head1 COMPATIBILITY ISSUES
+
+POE has tested favorably on as many Perl versions as the author can
+find or harass people into trying. This includes Linux, FreeBSD, OS/2
+and at least one unspecified version of Windows. As far as I can
+tell, nobody ever has tried it on any version of MacOS.
+
+POE has been tested with Perl versions as far back as 5.004_03 and as
+recent as 5.6.0. The CPAN testers are a wonderful bunch of people who
+have dedicated resources to running new modules on a variety of
+platforms. The latest POE tests are visible at
+<http://testers.cpan.org/search?request=dist&dist=POE>. Thanks,
+people!
+
+Please let the author know of breakage or success that hasn't been
+covered already. Thanks!
-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.
+Specific issues:
-=over 4
+=over 2
=item *
-poing.perl
+Various Unices
+
+No known problems.
+
+=item *
-Poing is a ping program that can check multiple hosts at the same
-time. Historical information scrolls across the screen in a "strip
-chart" fashion. It's great for listening to the seismology of your
-local network (no, it's not deliberately a Quake reference).
+OS/2
-Poing's event-driven pinger "borrows" heavily from Net::Ping.
+No known problems.
=item *
-preforkedserver.perl
+Windows
-This program demonstrates a way to write pre-forking servers with POE.
-It tends to dump core after a while. Perl still isn't safe with
-signals, especially in a long-running daemon process.
+Windows support lapsed in version 0.0806 when I took out some code I
+wasn't sure was working. Well, it was, and removing it broke POE on
+Windows.
-One work-around is to comment out the yield('_stop') calls (there are
-two). They only exist to cycle the child servers. That idea was
-borrowed from Apache, which only did it to thwart memory leaks. POE
-shouldn't leak memory, so churning the children shouldn't be needed.
+Douglas Couch reported that POE worked with the latest stable
+ActivePerl prior to version 5.6.0-RC1. He said that RC1 supported
+fork and other Unix compatibilities, but it still seemed like beta
+level code. I hope this changed with the release of 5.6.0-GA.
+
+Douglas writes:
+
+ I've done some preliminary testing of the 0.0903 version and the
+ re-addition of the Win32 support seems to be a success. I'll do
+ some more intensive testing in the next few days to make sure
+ nothing else is broken that I haven't missed.
+
+And later:
+
+ After testing out my own program and having no problems with the
+ newest version (with Win32 support), I thought I'd test out some of
+ the samples and relay my results.
+
+ filterchange.perl and preforkedserver.perl both contain fork
+ commands which are still unsupported by ActiveState's port of Perl,
+ so they were both unsuccessful. (this was anticipated for anything
+ containing fork)
+
+ ref-type.perl, refsender.perl, thrash.perl and wheels2.perl all ran
+ up against the same unsupported POSIX macro. According to the error
+ message, my vendor's POSIX doesn't support the macro EINPROGRESS.
+
+ [EINPROGRESS is fixed as of version 0.1003; see the Changes]
+
+ Other than those particular problems all of the other sample scripts
+ ran fine.
=item *
-proxy.perl
+MacOS
+
+I have heard rumors from MacOS users that POE might work with MacPerl,
+but so far nobody has stepped forward with an actual status report.
+
+=back
-This program demonstrates a way to write TCP forwarders with POE.
+=head1 SYSTEM REQUIREMENTS
+
+=over 2
=item *
-tutorial-chat.perl
+Recommendations
+
+POE would like to see certain functions, but it doesn't strictly
+require them. For example, the sample programs use fork() in a few
+places, but POE doesn't require it to run.
+
+If Time::HiRes is present, POE will use it to achieve better accuracy
+in its select timeouts. This makes alarms and delays more accurate,
+but POE is designed to work without it as well.
+
+POE includes no XS, and therefore it doesn't require a C compiler. It
+should work wherever a sufficiently complete version of Perl does.
+
+=item *
+
+Hard Requirements
+
+POE requires Filter::Call::Util starting with version 0.1001. This is
+part of the source filter package, Filter, version 1.18 or later. The
+dependency is coded into Makefile.PL, and the CPAN shell can fetch and
+install this automatically for you.
+
+POE uses POSIX system calls and constants for portability. There
+should be no problems using it on systems that have sufficient POSIX
+support.
+
+Some of POE's sample programs require a recent IO bundle, but you get
+that for free with recent versions of Perl.
+
+=item *
+
+Optional Requirements
+
+If you intend to use Filter::Reference, then you will need either the
+Storable or FreezeThaw module, or some other freeze/thaw package.
+Storable tends to be the fastest, and it's checked first.
+Filter::Reference can also use Compress::Zlib upon request, but it's
+not required.
+
+Filter::HTTPD requires a small world of modules, including
+HTTP::Status; HTTP::Request; HTTP::Date and URI::URL. The httpd.perl
+sample program uses Filter::HTTPD, which uses all that other stuff.
+
+The preforkedserver.perl sample program uses POE::Kernel::fork(),
+which in turn requires the fork() built-in function. This may or 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 modules.
+
+=back
+
+=head1 SUPPORT RESOURCES
+
+These are Internet resources where you may find more information about
+POE.
+
+=over 2
+
+=item *
+
+The POE Mailing List
+
+POE has a mailing list thanks to Artur Bergman and Vogon Solutions.
+You may subscribe to it by sending e-mail:
+
+ To: poe-help@vogon.se
+ Subject: (anything will do)
+
+ Anything will do for the message body.
-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.
+All forms of feedback are welcome.
+
+=item *
+
+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/poe.html>.
=back
=head1 SEE ALSO
-=over 4
+This is a summary of POE's modules.
+
+=over 2
=item *
@@ -525,8 +858,11 @@ POE::Kernel; POE::Session
I/O Layer
-POE::Driver; POE::Driver::SysRW POE::Filter; POE::Filter::HTTPD;
-POE::Filter::Line; POE::Filter::Reference; POE::Filter::Stream;
+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
@@ -534,98 +870,158 @@ POE::Wheel::ReadWrite; POE::Wheel::SocketFactory
Object Layer
-POE::Curator; POE::Object; POE::Repository; POE::Repository::Array;
+These modules are in limbo at the moment.
+
+POE::Curator; POE::Object; POE::Repository; POE::Attribute::Array;
POE::Runtime
+=item *
+
+Components
+
+POE::Component; POE::Component::Server::TCP
+
+=item *
+
+Supporting cast
+
+POE::Preprocessor
+
=back
=head1 BUGS
-The Object Layer is still in early design and implementation, so it's
-not documented yet.
+The Object Layer is still in early design, so it's not documented yet.
-There are no automated regression tests.
+There need to be more automated regression tests in the t/*.t
+directory. Please suggest tests; the author is short on ideas here.
-=head1 AUTHORS & COPYRIGHTS
+The documentation is in the process of another revision. Here is a
+progress report:
-POE is brought to you by the following people:
+ POE rewritten 2000.05.15
+ README rewritten 2000.05.16
+ POE::Kernel rewritten 2000.05.19
+ POE::Session rewritten 2000.05.21
-=head2 Contributors
+ POE::Component queued
+ POE::Component::Server::TCP queued
+ POE::Driver queued
+ POE::Driver::SysRW queued
+ POE::Filter queued
+ POE::Filter::HTTPD queued
+ POE::Filter::Line queued
+ POE::Filter::Reference queued
+ POE::Filter::Stream queued
+ POE::Preprocessor queued
+ POE::Wheel queued
+ POE::Wheel::FollowTail queued
+ POE::Wheel::ListenAccept queued
+ POE::Wheel::ReadWrite queued
+ POE::Wheel::SocketFactory queued
-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.
+=head1 AUTHORS & COPYRIGHT
-=over 4
+POE is the combined effort of more people than I can remember
+sometimes. If I've forgotten someone, please let me know.
+
+=over 2
+
+=item *
+
+Addi
+
+Addi is <e-mail unknown>.
+
+Addi has tested POE and POE::Component::IRC on the Windows platform,
+finding bugs and testing fixes. You'll see his name sprinkled
+throughout the Changes file.
=item *
Artur Bergman
-Artur Bergman is <vogon-solutions.com!artur>.
+Artur Bergman is <artur@vogon-solutions.com>.
-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.
+Artur has contributed many hours and ideas. He's also the author of
+Filter::HTTPD and Filter::Reference, as well as bits and pieces
+throughout POE. His intangible contributions include feedback,
+testing, conceptual planning and inspiration. POE would never have
+come this far without his support.
+
+=item *
+
+Douglas Couch
+
+Douglas Couch is <dscouch@purdue.edu>
+
+Douglas was the brave soul who stepped forward to offer valuable
+testing on the Windows platforms. His reports helped get POE working
+on Win32 and are summarized earlier in this document.
=item *
Philip Gwyn
-Philip Gwyn is <artware.qc.ca!gwynp>.
+Philip Gwyn is <gwynp@artware.qc.ca>.
-He has extended the Wheels I/O abstraction to allow filters to be
-changed at runtime. He has enhanced Filter::Reference to support
+Philip extended the Wheels I/O abstraction to allow filters to be
+changed at runtime and provided patches to add the eminently cool
+Kernel and Session IDs. He also 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.
+the discovery and/or destruction of several bugs (see the Changes
+file) and a thorough code review around version 0.06.
=item *
Dave Paris
-Dave Paris is <w3works.com!dparis>.
+Dave Paris is <dparis@w3works.com>. He often goes by the nickname
+"a-mused".
-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.
+Dave tested and benchmarked POE around version 0.05, discovering some
+subtle (and not so subtle) timing problems. The pre-forking server
+was his idea. Versions 0.06 and later should scale to higher loads
+because of his work. His intangible contributions include lots of
+testing and feedback, some of which is visible in the Changes file.
=item *
Robert Seifer
-Robert Seifer is <?!?>.
+Robert Seifer is <e-mail unknown>. He rotates IRC nicknames
+regularly.
-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.
+Robert contributed entirely too much time, both his own and his
+computers, towards the detection and eradication of a memory
+corruption bug that POE tickled in earlier Perl versions. In the end,
+his work produced a simple compile-time hack that worked around a
+problem relating to anonymous subs, scope and @{} processing.
=item *
Others?
-Have I forgotten someone? Please let me know.
+Anyone who has been forgotten, please contact me.
=back
=head2 Author
-=over 4
+=over 2
=item *
Rocco Caputo
-Rocco Caputo is <netrus.net!troc>. POE is his brainchild.
+Rocco Caputo is <troc+poe@netrus.net>. POE is his brainchild.
-Except where otherwise noted, POE is Copyright 1998-1999 Rocco Caputo.
+Except where otherwise noted, POE is Copyright 1998-2000 Rocco Caputo.
All rights reserved. POE is free software; you may redistribute it
and/or modify it under the same terms as Perl itself.
+=back
+
+Thank you for reading!
+
=cut
View
1,402 lib/POE/Kernel.pm
@@ -160,12 +160,6 @@ macro test_resolve (<name>,<resolved>) {
}
}
-macro clip_time_to_now (<time>) {
- if (<time> < (my $now = time())) {
- <time> = $now;
- }
-}
-
# MACROS END <-- search tag for editing
#------------------------------------------------------------------------------
@@ -216,23 +210,23 @@ BEGIN {
defined &TRACE_DEFAULT or eval 'sub TRACE_DEFAULT () { 0 }';
- {% define_trace QUEUE %}
- {% define_trace PROFILE %}
- {% define_trace SELECT %}
{% define_trace EVENTS %}
{% define_trace GARBAGE %}
+ {% define_trace PROFILE %}
+ {% define_trace QUEUE %}
{% define_trace REFCOUNT %}
+ {% define_trace SELECT %}
# See the notes for TRACE_DEFAULT, except read ASSERT and assert
# where you see TRACE and trace.
defined &ASSERT_DEFAULT or eval 'sub ASSERT_DEFAULT () { 0 }';
- {% define_assert SELECT %}
{% define_assert GARBAGE %}
+ {% define_assert REFCOUNT %}
{% define_assert RELATIONS %}
+ {% define_assert SELECT %}
{% define_assert SESSIONS %}
- {% define_assert REFCOUNT %}
}
# Determine whether Tk is loaded. If it is, set a constant that
@@ -1779,6 +1773,8 @@ sub yield {
\@etc,
time(), (caller)[1,2]
);
+
+ undef;
}
#------------------------------------------------------------------------------
@@ -1804,12 +1800,14 @@ sub call {
# deterministic programs, but the difficulty can be ameliorated if
# programmers set some base rules and stick to them.
+ my $return_value =
+ $self->_dispatch_state( $session, $self->[KR_ACTIVE_SESSION],
+ $state_name, ET_USER,
+ \@etc,
+ time(), (caller)[1,2], undef
+ );
$! = 0;
- return $self->_dispatch_state( $session, $self->[KR_ACTIVE_SESSION],
- $state_name, ET_USER,
- \@etc,
- time(), (caller)[1,2], undef
- );
+ return $return_value;
}
#------------------------------------------------------------------------------
@@ -1841,6 +1839,8 @@ sub alarm {
my ($self, $state, $time, @etc) = @_;
my $kr_active_session = $self->[KR_ACTIVE_SESSION];
+ return EINVAL unless defined $state;
+
# Remove all previous instances of the alarm.
my $index = scalar(@{$self->[KR_ALARMS]});
while ($index--) {
@@ -1860,21 +1860,22 @@ sub alarm {
}
# Add the new alarm if it includes a time.
- if ($time) {
- {% clip_time_to_now $time %}
+ if (defined $time) {
$self->_enqueue_alarm( $kr_active_session, $kr_active_session,
$state, ET_ALARM,
[ @etc ],
$time, (caller)[1,2]
);
}
+
+ return 0;
}
# Add an alarm without clobbenig previous alarms of the same name.
sub alarm_add {
my ($self, $state, $time, @etc) = @_;
- {% clip_time_to_now $time %}
+ return EINVAL unless defined $state and defined $time;
my $kr_active_session = $self->[KR_ACTIVE_SESSION];
$self->_enqueue_alarm( $kr_active_session, $kr_active_session,
@@ -1882,25 +1883,35 @@ sub alarm_add {
[ @etc ],
$time, (caller)[1,2]
);
+
+ return 0;
}
# Add a delay, which is just an alarm relative to the current time.
sub delay {
my ($self, $state, $delay, @etc) = @_;
+
+ return EINVAL unless defined $state;
+
if (defined $delay) {
$self->alarm($state, time() + $delay, @etc);
}
else {
$self->alarm($state, 0);
}
+
+ return 0;
}
# Add a delay without clobbering previous delays of the same name.
sub delay_add {
my ($self, $state, $delay, @etc) = @_;
- if (defined $delay) {
- $self->alarm_add($state, time() + $delay, @etc);
- }
+
+ return EINVAL unless defined $state and defined $delay;
+
+ $self->alarm_add($state, time() + $delay, @etc);
+
+ return 0;
}
#==============================================================================
@@ -2152,24 +2163,28 @@ sub select {
$self->_internal_select($session, $handle, $state_r, VEC_RD);
$self->_internal_select($session, $handle, $state_w, VEC_WR);
$self->_internal_select($session, $handle, $state_e, VEC_EX);
+ return 0;
}
# Only manipulate the read select.
sub select_read {
my ($self, $handle, $state) = @_;
$self->_internal_select($self->[KR_ACTIVE_SESSION], $handle, $state, 0);
+ return 0;
};
# Only manipulate the write select.
sub select_write {
my ($self, $handle, $state) = @_;
$self->_internal_select($self->[KR_ACTIVE_SESSION], $handle, $state, 1);
+ return 0;
};
# Only manipulate the expedite select.
sub select_expedite {
my ($self, $handle, $state) = @_;
$self->_internal_select($self->[KR_ACTIVE_SESSION], $handle, $state, 2);
+ return 0;
};
# Turn off a handle's write vector bit without doing
@@ -2193,7 +2208,7 @@ sub select_pause_write {
);
}
- return 1;
+ return 0;
}
# Turn on a handle's write vector bit without doing garbage-collection
@@ -2230,11 +2245,8 @@ sub alias_set {
# Don't overwrite another session's alias.
if (exists $self->[KR_ALIASES]->{$name}) {
- if ($self->[KR_ALIASES]->{$name} != $kr_active_session) {
- $! = EEXIST;
- return 0;
- }
- return 1;
+ return EEXIST if $self->[KR_ALIASES]->{$name} != $kr_active_session;
+ return 0;
}
$self->[KR_ALIASES]->{$name} = $kr_active_session;
@@ -2242,7 +2254,7 @@ sub alias_set {
{% ses_refcount_inc $kr_active_session %}
- return 1;
+ return 0;
}
# Public interface for removing aliases.
@@ -2250,19 +2262,12 @@ sub alias_remove {
my ($self, $name) = @_;
my $kr_active_session = $self->[KR_ACTIVE_SESSION];
- unless (exists $self->[KR_ALIASES]->{$name}) {
- $! = ESRCH;
- return 0;
- }
-
- if ($self->[KR_ALIASES]->{$name} != $kr_active_session) {
- $! = EPERM;
- return 0;
- }
+ return ESRCH unless exists $self->[KR_ALIASES]->{$name};
+ return EPERM if $self->[KR_ALIASES]->{$name} != $kr_active_session;
{% remove_alias $kr_active_session, $name %}
- return 1;
+ return 0;
}
sub alias_resolve {
@@ -2340,7 +2345,11 @@ sub refcount_increment {
")"
);
};
+
+ return $self->[KR_SESSIONS]->{$session}->[SS_EXTRA_REFS]->{$tag};
}
+
+ $! = ESRCH;
undef;
}
@@ -2371,7 +2380,11 @@ sub refcount_decrement {
);
};
+ return $self->[KR_SESSIONS]->{$session}->[SS_EXTRA_REFS]->{$tag};
}
+
+ $! = ESRCH;
+ undef;
}
#==============================================================================
@@ -2467,11 +2480,10 @@ sub state {
$state_code,
$state_alias
);
- return 1;
+ return 0;
}
# no such session
- $! = ESRCH;
- return 0;
+ return ESRCH;
}
###############################################################################
@@ -2487,128 +2499,137 @@ __END__
=head1 NAME
-POE::Kernel - POE Event Queue and Resource Manager
+POE::Kernel - an event dispatcher and resource watcher
=head1 SYNOPSIS
- ### A minimal POE program.
+The POE manpage includes and describes a sample program.
+
+To use POE's event loop:
+
+ use POE;
+
+To have POE encapsulate Tk's event loop:
+
+ use Tk;
+ use POE;
+
+To have POE encapsulate Event's event loop (not yet implemented, since
+Event refuses to compile):
+
+ use Event;
+ use POE;
+
+Methods to manage the process' global Kernel instance:
+
+ # Retrieve the kernel's unique identifier.
+ $kernel_id = $kernel->ID;
+
+ # Run the event loop, only returning when it has no more sessions to
+ # dispatche events to.
+ $kernel->run( );
- #!/usr/bin/perl -w
- use strict; # It's a good idea, anyway.
- use POE; # This includes Kernel and Session.
- new POE::Session( ... ); # This is an initial bootstrap Session.
- $poe_kernel->run(); # Run until all sessions exit.
- exit; # Program's over. Be seeing you!
+ # "Safe" fork. Safety comes from blocking SIGCHLD and starting an
+ # internal waitpid loop to reap children. This is experimental and
+ # may better be served with a high level fork/exec function.
+ # Consider feedback to be solicited.
+ $pid = $kernel->fork( );
- ### Methods to manage events.
+FIFO event methods:
- # Post an event to some session.
+ # Post an event to an arbitrary session.
$kernel->post( $session, $state_name, @state_args );
- # Post an event to this session.
+ # Post an event back to the current session.
$kernel->yield( $state_name, @state_args );
- # Call a state right now, and return what it returns. States'
- # return values are always scalars.
- $state_returns = $kernel->call( $session, $state_name, @state_args );
+ # Synchronous state call, bypassing the event queue and returning
+ # the state's return value directly.
+ $state_return_value = $kernel->call( $session, $state_name, @state_args );
- ### Methods to manage timed events. These events are dispatched
- ### some time in the future, rather than in FIFO order.
+Alarm and delay methods:
- # Post an event to be delivered at an absolute epoch time. This
- # clears pending alarms for the same state name.
+ # Post an event which will be delivered at an absolute Unix epoch
+ # time. This clears previous timed events for the same state.
$kernel->alarm( $state_name, $epoch_time, @state_args );
- # Post an additional alarm. This leaves existing alarms for the
- # same state name in the queue.
+ # Post an additional alarm, leaving existing ones in the queue.
$kernel->alarm_add( $state_name, $epoch_time, @state_args );
- # Post an event to be delivered some number of seconds from now.
- # This clears pending delays for the same state name.
+ # Post an event which will be delivered after some number of
+ # seconds. This clears previous timed events for the same state.
$kernel->delay( $state_name, $seconds, @state_args );
- # Post an additional delay. This leaves existing delays for the
- # same state name in the queue.
+ # Post an additional delay, leaving existing ones in the queue.
$kernel->delay_add( $state_name, $seconds, @state_args );
- # Return the state names of pending alarms.
+ # Return the names of pending timed events.
@state_names = $kernel->queue_peek_alarms( );
- ### Alias management methods. Aliases are symbolic names for
- ### sessions. Sessions may have more than one alias.
+Symbolic name, or session alias methods:
- # Set an alias for the current session. Status is either 1 for
- # success or 0 for failure. If it returs 0, then $! is set to a
- # reason for the failure.
+ # Set an alias for the current session.
$status = $kernel->alias_set( $alias );
- # Clear an alias for the current session. Status is either 1 for
- # success or 0 for failure. If it returns 0, then $! is set to a
- # reason for the failure.
+ # Clear an alias for the current session:
$status = $kernel->alias_remove( $alias );
- # Resolve an alias into a session reference. This is mostly
- # obsolete since most kernel methods perform session resolution
- # internally. Returns a session reference, or undef on failure. If
- # it returns undef, then $! is set to a reason for the failure.
+ # Resolve an alias into a session reference. Most POE::Kernel
+ # methods do this for you.
$session_reference = $kernel->alias_resolve( $alias );
- ### Select management methods. Selects monitor filehandles for
- ### activity. Select states are called synchronously so they can
- ### immediately deal with the filehandle activity.
+ # Resolve a session ID to a session reference. The alias_resolve
+ # method does this as well, but this is faster.
+ $session_reference = $kernel->ID_id_to_session( $session_id );
- # Invoke a state when a filehandle holds something that can be read.
- $kernel->select_read( $file_handle, $state_name );
+ # Return a session ID for a session reference. It is functionally
+ # equivalent to $session->ID.
+ $session_id = $kernel->ID_session_to_id( $session_reference );
+
+Filehandle watcher methods:
- # Clear a previous read select from a filehandle.
+ # Watch for read readiness on a filehandle. Clear a read select
+ # from a filehandle.
+ $kernel->select_read( $file_handle, $state_name );
$kernel->select_read( $file_handle );
- # Invoke a state when a filehandle has room for something to be
- # written into it.
+ # Watch for write readiness on a filehandle. Clear a write select
+ # from a filehandle.
$kernel->select_write( $file_handle, $state_name );
-
- # Clear a previous write select from a filehandle.
$kernel->select_write( $file_handle );
- # Invoke a state when a filehandle has out-of-band data to be read.
- $kernel->select_expedite( $file_handle, $state_name );
+ # Pause and resume write readiness watching. These have lower
+ # overhead than full select_write() calls.
+ $kernel->select_pause_write( $file_handle );
+ $kernel->select_resume_write( $file_handle );
+ # Watch for out-of-bound (expedited) read readiness on a filehandle.
# Clear an expedite select from a filehandle.
+ $kernel->select_expedite( $file_handle, $state_name );
$kernel->select_expedite( $file_handle );
# Set and/or clear a combination of selects in one call.
$kernel->select( $file_handle,
- $read_state_name, # or undef to remove it
- $write_state_name, # or undef to remove it
- $expedite_state_same, # or undef to remove it
+ $read_state_name, # or undef to clear it
+ $write_state_name, # or undef to clear it
+ $expedite_state_same, # or undef to clear it
);
- # Pause a write select. This temporarily causes an existing write
- # select to ignore filehandle activity. It has less overhead than
- # select_write( $file_handle ).
- $kernel->select_pause_write( $file_handle );
+Signal watcher and generator methods:
- # Resume a write select. This re-enables events from a paused write
- # select.
- $kernel->select_resume_write( $file_handle );
-
- ### Signal management methods.
+ # Map a signal name to its handler state. Clear a signal-to-handler
+ # mapping.
+ $kernel->sig( $signal_name, $state_name );
+ $kernel->sig( $signal_name );
- # Post a signal to a particular session. These "soft" signals are
- # posted through POE's event queue, and they don't involve the
- # underlying operating system. They are not restricted to the
- # signals that the OS supports; in fact, POE uses fictitious ZOMBIE
- # and IDLE signals internally.
+ # Simulate a system signal by posting it through POE rather than
+ # through the underlying OS.
$kernel->signal( $session, $signal_name );
- # Map a signal name to a state which will handle it.
- $kernel->sig( $signal_name, $handler_state );
+State management methods:
- # Clear a signal handler.
- $kernel->sig( $signal_name );
-
- ### State management methods. These allow sessions to modify their
- ### states at runtime. See the POE::Session manpage for details
+ # Remove an existing state from the current machine.
+ $kernel->state( $state_name );
# Add a new inline state, or replace an existing one.
$kernel->state( $state_name, $code_reference );
@@ -2621,743 +2642,952 @@ POE::Kernel - POE Event Queue and Resource Manager
# The object method may be different from the state name.
$kernel->state( $state_name, $object_ref_or_package_name, $method_name );
- # Remove an existing state.
- $kernel->state( $state_name );
+External reference count methods:
- ### Manage session IDs. The kernel instance also has an ID since it
- ### acts like a session in many ways.
+ # Increment a session's external reference count.
+ $kernel->refcount_increment( $session_id, $refcount_name );
- # Fetch the kernel's unique ID.
- $kernel_id = $kernel->ID;
+ # Decrement a session's external reference count.
+ $kernel->refcount_decrement( $session_id, $refcount_name );
- # Resolve an ID into a session reference. $kernel->alias_resolve
- # has been overloaded to also recognize session IDs, but this is
- # faster.
- $session = $kernel->ID_id_to_session( $id );
+Exported symbols:
- # Resolve a session reference into its ID. $session->ID is
- # syntactic sugar for this call.
- $id = $kernel->ID_session_to_id( $session );
+ # A reference to the global POE::Kernel instance.
+ $poe_kernel
- ### Manage external reference counts. This is an experimental
- ### feature. There is no guarantee that it will work, nor is it
- ### guaranteed to exist in the future. The functions work by
- ### session ID because session references themselves would hold
- ### reference counts that prevent Perl's garbage collection from
- ### doing the right thing.
+ # This is the Tk widget POE uses to access Tk's event loop. It's
+ # only meaningful when Tk is used; otherwise it's undef.
+ $poe_tk_main_window
- # Increment an external reference count, by name. These references
- # keep a session alive.
- $kernel->refcount( $session_id, $refcount_name );
+=head1 DESCRIPTION
- # Decrement an external reference count.
- $kernel->refcount( $session_id, $refcount_name );
+The "Event" module documentation is incorrect. I am having trouble
+building Event on FreeBSD or OS/2, so the Event support is only in the
+planning phase. The rest of the code should quickly fall into place
+once Event is working. This time documentation is ahead of
+development! :)
- ### Manage processes. This is an experimental feature. There is no
- ### guarantee that it will work, nor is it guaranteed to exist in
- ### the future.
+POE::Kernel is an event dispatcher and resource watcher. It provides
+a consistent interface to the most common event loop features whether
+the underlying architecture is its own, Perl/Tk's, or Event's. Other
+loop features can be integrated with POE through POE::Session's
+postback() method.
- # Fork a process "safely". It sets up a nonblocking waitpid loop to
- # reap children instead of relying on SIGCH?LD, which is problematic
- # in plain Perl. It returns whatever fork() would.
- $fork_retval = $kernel->fork();
+=head1 USING POE::Kernel
-=head1 DESCRIPTION
+The POE manpage describes a shortcut for using several POE modules at
+once.
-This description is out of date as of version 0.1001, but the synopsis
-is accurate. The description will be fixed shortly.
+POE::Kernel supports three Perl event loops: Its own select loop,
+included with POE and coded in Perl; Tk's loop, which enables POE to
+interact with users through a graphical front end; and Event's loop,
+which is written in C for maximum performance.
-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.
+POE::Kernel uses its own loop by default, but it will adapt to
+whichever external event loop is loaded before it:
-=head1 EXPORTED SYMBOLS
+ # Use POE's select loop.
+ use POE::Kernel;
-POE::Kernel exports $poe_kernel, a reference to the program's single
-kernel instance. This mainly is used in the main package, so that
-$poe_kernel->run() may be called cleanly.
+ # Use Tk's event loop.
+ use Tk;
+ use POE::Kernel;
-Sessions' states should endeavor to use $_[KERNEL], since $poe_kernel
-may not be available, or it may be different than the kernel actually
-invoking the object.
+ # Use Event's loop.
+ use Event;
+ use POE::Kernel;
-=head1 PUBLIC KERNEL METHODS
+It also is possible to enable assertions and debugging traces by
+defining the constants that enable them before POE::Kernel does.
+Every definition follows the form:
+
+ sub POE::Kernel::ASSERT_SOMETHING () { 1 }
+
+Assertions are quiet until something wrong has been detected, and then
+they die right away with an error. Their main use is for sanity
+checks in POE's test suite. Traces, on the other hand, are never
+fatal, but they're terribly noisy.
+
+Both assertions and traces incur performance penalties, so they should
+be used sparingly, if at all. They all are off by default.
+
+Assertions will be discussed first.
+
+=over 2
-POE::Kernel contains methods to manage the kernel itself, sessions,
-and resources such as files, signals and alarms.
+=item ASSERT_DEFAULT
-Many of the public Kernel methods generate events. Please see the
-"PREDEFINED EVENTS AND PARAMETERS" section in POE::Session's
-documentation.
+The value of ASSERT_DEFAULT is used as the default value for the other
+assertion constants. Setting this true is a quick and reliable way to
+ensure that all assertions are enabled.
-Some Kernel methods accept a C<$session> reference. These allow
-events to be dispatched to arbitrary sessions. For example, a program
-can post a state transition event almost anywhere:
+=item ASSERT_GARBAGE
- $kernel->post( $destination_session, $state_to_invoke );
+Enabling ASSERT_GARBAGE has POE::Kernel verify its internal record
+keeping against sane conditions. In particular, it ensures that
+sessions have released all their resources before destroying them.
-On the other hand, there are methods that don't let programs specify
-destinations. The events generated by these methods, if any, will be
-dispatched to the current session. For example, setting an alarm:
+=item ASSERT_REFCOUNT
- $kernel->alarm( $state_to_invoke, $when_to_invoke_it );
+Setting ASSERT_REFCOUNT true enables checks for negative reference
+counts and nonzero reference counts in destroyed sessions. It
+complements ASSERT_GARBAGE.
-=head2 Kernel Management Methods
+=item ASSERT_RELATIONS
-=over 4
+Enabling ASSERT_RELATIONS turns on parent/child referential integrity
+checks.
-=item *
+=item ASSERT_SELECT
-POE::Kernel::run()
+Setting ASSERT_SELECT true enables extra error checking in
+POE::Kernel's select logic. It has no effect if POE is using an
+external event loop.
-POE::Kernel::run() starts the kernel's event loop. It will not return
-until all its sessions have stopped. There are two corollaries to
-this rule: It will return immediately if there are no sessions; and if
-sessions never exit, neither will run().
+=item ASSERT_SESSIONS
+
+POE::Kernel normally discards events that are posted to nonexistent
+sessions. This is a deliberate feature, but it means that certain
+typographical errors can go unnoticed.
+
+A true ASSERT_SESSIONS constant will cause POE to check session
+resolution and die if an unknown session is referenced. This may
+catch problems that are otherwise difficult to spot.
=back
-=head2 Event Management Methods
+Then there are the trace options.
-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.
+=over 2
-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.
+=item TRACE_DEFAULT
-To learn more about events and the information they convey, please see
-"PREDEFINED EVENTS AND PARAMETERS" in the POE::Session documentation.
+TRACE_DEFAULT works like ASSERT_DEFAULT except for traces. That is,
+its value is used as the default for the other trace constants.
+Setting it true is a quick and reliable way to turn on every type of
+trace.
-=over 4
+=item TRACE_EVENTS
-=item *
+The music goes around and around, and it comes out here. Enabling
+TRACE_EVENTS causes POE::Kernel to tell you what happens to FIFO and
+alarm events: when they're enqueued, dispatched or discarded, and what
+their states return.
-POE::Kernel::post( $destination, $state, @args )
+=item TRACE_GARBAGE
-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().
+TRACE_GARBAGE shows what's keeping sessions alive. It's useful for
+determining why a session simply refuses to die.
-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.
+=item TRACE_PROFILE
-POE::Kernel::post returns undef on failure, or an unspecified defined
-value on success. $! is set to the reason why the post failed.
+This trace constant switches on state profiling, causing POE::Kernel
+to keep a count of every state it dispatches. It displays a frequency
+report when the event loop finishes.
-=item *
+=item TRACE_QUEUE
-POE::Kernel::yield( $state, @args )
+TRACE_QUEUE complements TRACE_EVENTS. When enabled, it traces the
+contents of POE's event queues, giving some insight into how events
+are ordered. This has become less relevant since the alarm and FIFO
+queues have separated.
-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 TRACE_REFCOUNT
-=item *
+Setting TRACE_REFCOUNT to true enables debugging output whenever an
+external reference count changes.
-POE::Kernel::call( $session, $state, $args )
+=item TRACE_SELECT
-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.
+TRACE_SELECT enables or disables statistics about POE::Kernel's
+default select loop's select parameters and 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.
+=back
-Until that bug is pinned down and fixed, if your program dumps core
-with a SIGSEGV, try changing your call()s to post()s.
+=head1 POE::Kernel Exports
+
+POE::Kernel exports two symbols for your coding enjoyment: $poe_kernel
+and $poe_tk_main_window. POE::Kernel is implicitly used by POE
+itself, so using POE gets you POE::Kernel (and its exports) for free.
+
+=over 2
-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.
+=item $poe_kernel
-=item *
+This contains a reference to the process' POE::Kernel instance. It's
+mainly useful for getting at the kernel from places other than states.
+For example, most programs call C<$poe_kernel->run()> to run its event
+loop.
-POE::Kernel::queue_peek_alarms()
+States rarely need to use $poe_kernel directly since they receive a
+copy of it in $_[KERNEL].
-Peeks at the current session's event queue, returning a list of
-pending alarms. The list is empty if no alarms are pending. The
-list's order is undefined as of version 0.0904 (it's really in time
-order, but that may change).
+=item $poe_tk_main_window
+
+POE creates a MainWindow to use Tk's event loop. Rather than waste a
+window, it exports a reference to it as $poe_tk_main_window. Programs
+can use this like a plain Tk MainWindow, which is exactly what it is.
=back
-=head2 Alarm Management Methods
+=head1 PRIVATE KERNEL METHODS
+
+The private kernel methods are private. All the usual "here there be
+private methods" caveats apply. As such, they won't be documented
+here. The terminally curious, however, will note that POE::Kernel
+contains a lot of comments.
+
+=head1 PUBLIC KERNEL METHODS
+
+This section discusses in more detail the POE::Kernel methods that
+appear in the SYNOPSIS. It uses the same syntax conventions as the
+perlfunc manpage.
+
+=head2 Methods to manage the process' global Kernel instance
-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).
+=over 2
+
+=item ID
+
+Return the POE::Kernel instance's unique identifier.
+
+Every POE::Kernel instance is assigned an ID at birth. This ID tries
+to differentiate any given instance from all the others, even if they
+exist on the same machine. The ID is a hash of the machine's name and
+the kernel's instantiation time and process ID.
+
+ ~/perl/poe$ perl -wl -MPOE -e 'print $poe_kernel->ID'
+ rocco.homenet-39240c97000001d8
+
+=item run
+
+Runs the chosen event loop, returning only after every session has
+stopped. It returns immediately if no sessions have yet been started.
-If Time::HiRes is available, POE will use it to achieve better
-resolution on enqueued events.
+ $poe_kernel->run();
+ exit;
-=over 4
+The run() method does not return a meaningful value.
-=item *
+=item fork
-POE::Kernel::alarm( $state, $time, @args )
+POE::Kernel's fork mimics fork(2)'s semantics, returning the child's
+PID in the parent process, 0 in the child process, or undef if fork
+failed.
-The alarm() method enqueues an event for the current session 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.
+It bypasses Perl's signal handling problems by polling for stopped
+children with waitpid(2).
+
+=back
+
+=head2 FIFO event methods
+
+Events posted with these methods are dispatched back to sessions in
+first-in/first-out order (in case you didn't know what FIFO meant).
+
+Sessions will not spontaneously stop if they have pending FIFO events.
+In other words, FIFO events keep sessions alive.
+
+=over 2
-alarm() ensures that its alarm is the only one queued for the current
-session and given state. It does this by scouring the queue and
-removing all others matching the combination of session and state. As
-of 0.0908, the alarm_add() method can post additional alarms without
-scouring previous ones away.
+=item post SESSION, STATE_NAME, PARAMETER_LIST
-@args are passed to the alarm handler as C<@_[ARG0..$#_]>.
+=item post SESSION, STATE_NAME
-It is possible to remove alarms from the queue by posting an alarm
-without additional parameters. This triggers the queue scour without
-posting an alarm. For example:
+Posts an event for STATE_NAME in SESSION. If a PARAMETER_LIST is
+included, its values will be used as arguments to STATE_NAME.
- $kernel->alarm( $state ); # Removes the alarm for $state
+ $_[KERNEL]->post( $session, 'do_this' );
+ $_[KERNEL]->post( $session, 'do_that', $with_this, $and_this );
+ $_[KERNEL]->post( $session, 'do_that', @with_these );
-As of version 0.0904, the alarm() function will only remove alarms.
-Other types of events will remain in the queue.
+The post() method a boolean value indicating whether the event was
+enqueued successfully. The $! variable will explain why post()
+failed.
-=item *
+=over 2
-POE::Kernel::alarm_add( $state, $time, @args )
+=item * ESRCH
-The alarm_add() method enqueues an event for the current session 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_add() call synonymous to
-post() but with some extra overhead.
+POE cannot find SESSION.
-Unlike alarm(), however, it does not scour the queue for previous
-alarms matching the current session/state pair. Since it doesn't
-scour, adding an empty alarm won't clear others from the queue.
+=back
-This function may be faster than alarm() since the scour phase is
-skipped.
+=item yield STATE_NAME, PARAMETER_LIST
-=item *
+=item yield STATE_NAME
-POE::Kernel::delay( $state, $seconds, @args )
+Posts an event for STATE_NAME in the current session. If a
+PARAMETER_LIST is included, its values will be used as arguments to
+STATE_NAME. Observant readers will note that this is just post() to
+the current session.
-The delay() method is an alias for:
+Events posted with yield() must propagate through POE's FIFO before
+they're dispatched. This effectively yields FIFO time to other
+sessions which already have events enqueued.
- $kernel->alarm( $state, time() + $seconds, @args );
+ $kernel->yield( 'do_this' );
+ $kernel->yield( 'do_that', @with_these );
-However it silently uses Time::HiRes if it's available, so time()
-automagically has an increased resolution when it can. This saves
-programs from having to figure out whether Time::HiRes is available
-themselves.
+The yield() method does not return a meaningful value.
-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:
+=item call SESSION, STATE_NAME, PARAMETER_LIST
- $kernel->delay( $state ); # Removes the delay for $state
+=item call SESSION, STATE_NAME
-As of version 0.0904, the delay() function will only remove alarms.
-Other types of events will remain in the queue.
+Calls STATE_NAME in a SESSION, bypassing the FIFO. Values from the
+optional PARAMETER_LIST will be passed as arguments to STATE_NAME at
+dispatch time. The call() method returns its status in $!, which is 0
+for success or a nonzero reason for failure.
-=item *
+ $return_value = $kernel->call( 'do_this_now' );
-POE::Kernel::delay_add( $state, $seconds, @args )
+POE uses call() to dispatch some resource events without FIFO latency.
+Filehandle watchers, for example, would continue noticing a handle's
+readiness until the it was serviced by a state. This could result in
+several redundant readiness events being enqueued before the first one
+was dispatched.
-The delay_add() method works like delay(), but it allows duplicate
-alarms. It is equivalent to:
+Reasons why call() might fail:
- $kernel->alarm_add( $state, time() + $seconds, @args );
+=over 2
-The "empty delay" syntax is meaningless since alarm_add() does not
-scour the queue for duplicates.
+=item * ESRCH
-This function may be faster than delay() since the scour phase is
-skipped.
+POE disbelieves in SESSION.
=back
-=head2 Alias Management Methods
+=head2 Alarm and delay methods
+
+POE also manages timed events. These are events that should be
+dispatched after at a certain time or after some time has elapsed.
+Alarms and delays always are enqueued for the current session, so a
+SESSION parameter is not needed.
+
+POE's timed events fall into two major categories: ones which are to
+be dispatched at an absolute time, and ones that will be dispatched
+after a certain amount of time has elapsed.
+
+Each category is further divided into methods that clear previous
+timed events before posting new ones, and methods that post timed
+events in addition to the ones already in the queue.
+
+POE will use Time::HiRes to increase timed events' accuracy. It will
+use the less accurate time(2) if Time::HiRes isn't available.
-Aliases allow sessions to be referenced by name instead of by session
-reference. They also allow s