Browse files

Initial revision

  • Loading branch information...
0 parents commit e04939cc4c201ebe6c3d5218c8e1df0e87f543f0 @rcaputo committed Mar 21, 2003
Showing with 402 additions and 0 deletions.
  1. +7 −0 trunk/MANIFEST
  2. +28 −0 trunk/Makefile.PL
  3. +237 −0 trunk/MessageBased.pm
  4. +94 −0 trunk/README
  5. +36 −0 trunk/t/01_basic.t
7 trunk/MANIFEST
@@ -0,0 +1,7 @@
+# $Id$
+CHANGES
+MANIFEST
+Makefile.PL
+MessageBased.pm
+README
+t/01_basic.t
28 trunk/Makefile.PL
@@ -0,0 +1,28 @@
+#!/usr/bin/perl
+# $Id$
+
+use ExtUtils::MakeMaker;
+
+WriteMakefile
+ ( NAME => 'POE::Session::MessageBased',
+
+ ( ($^O eq 'MacOS')
+ ? ()
+ : ( AUTHOR => 'Rocco Caputo <rcaputo@cpan.org>',
+ ABSTRACT => 'Message-based events for POE (no @_ slices)',
+ )
+ ),
+
+ VERSION_FROM => 'MessageBased.pm',
+ PM => { 'MessageBased.pm' => '$(INST_LIBDIR)/MessageBased.pm'
+ },
+ dist =>
+ { 'COMPRESS' => 'gzip -9f',
+ 'SUFFIX' => 'gz',
+ PREOP => ( 'cvs-log.perl | ' .
+ 'tee ./$(DISTNAME)-$(VERSION)/CHANGES > ./CHANGES'
+ ),
+ },
+ PREREQ_PM => { 'POE' => 0.25,
+ },
+ );
237 trunk/MessageBased.pm
@@ -0,0 +1,237 @@
+# $Id$
+# License and documentation are after __END__.
+
+# This is prototype code. It rummages around in its base class'
+# namespace for constants, among other unsavory things.
+
+# Artur Bergman suggests keeping a static Message object in the
+# Session itself, and reusing that instead of building and destroying
+# messages each time. That could be a little faster.
+
+package POE::Session::MessageBased;
+
+use warnings;
+use strict;
+
+use vars qw($VERSION);
+$VERSION = '0.01';
+
+use POE;
+use base qw(POE::Session);
+use POSIX qw(ENOSYS);
+
+sub _invoke_state {
+ my ($self, $source_session, $state, $etc, $file, $line) = @_;
+
+ # Trace the state invocation if tracing is enabled.
+
+ if ($self->[POE::Session::SE_OPTIONS]->{+POE::Session::OPT_TRACE}) {
+ warn( $POE::Kernel::poe_kernel->ID_session_to_id($self),
+ " -> $state (from $file at $line)\n"
+ );
+ }
+
+ # The desired destination state doesn't exist in this session.
+ # Attempt to redirect the state transition to _default.
+
+ unless (exists $self->[POE::Session::SE_STATES]->{$state}) {
+
+ # There's no _default either; redirection's not happening today.
+ # Drop the state transition event on the floor, and optionally
+ # make some noise about it.
+
+ unless ( exists
+ $self->[POE::Session::SE_STATES]->{+POE::Session::EN_DEFAULT}
+ ) {
+ $! = ENOSYS;
+ if ($self->[POE::Session::SE_OPTIONS]->{+POE::Session::OPT_DEFAULT}) {
+ warn( "a '$state' state was sent from $file at $line to session ",
+ $POE::Kernel::poe_kernel->ID_session_to_id($self),
+ ", but session ",
+ $POE::Kernel::poe_kernel->ID_session_to_id($self),
+ " has neither that state nor a _default state to handle it\n"
+ );
+ }
+ return undef;
+ }
+
+ # If we get this far, then there's a _default state to redirect
+ # the transition to. Trace the redirection.
+
+ if ($self->[POE::Session::SE_OPTIONS]->{+POE::Session::OPT_TRACE}) {
+ warn( $POE::Kernel::poe_kernel->ID_session_to_id($self),
+ " -> $state redirected to _default\n"
+ );
+ }
+
+ # Transmogrify the original state transition into a corresponding
+ # _default invocation.
+
+ $etc = [ $state, $etc ];
+ $state = POE::Session::EN_DEFAULT;
+ }
+
+ # If we get this far, then the state can be invoked. So invoke it
+ # already!
+
+ # Inline states are invoked this way.
+
+ if (ref($self->[POE::Session::SE_STATES]->{$state}) eq 'CODE') {
+ my $message = POE::Session::Message->new
+ ( undef, # object
+ $self, # session
+ $POE::Kernel::poe_kernel, # kernel
+ $self->[POE::Session::SE_NAMESPACE], # heap
+ $state, # state
+ $source_session, # sender
+ undef, # unused #6
+ $file, # caller file name
+ $line, # caller file line
+ $etc # args
+ );
+
+ return $self->[POE::Session::SE_STATES]->{$state}->($message, @$etc);
+ }
+
+ # Package and object states are invoked this way.
+
+ my ($object, $method) = @{$self->[POE::Session::SE_STATES]->{$state}};
+ my $message = POE::Session::Message->new
+ ( $self, # session
+ $POE::Kernel::poe_kernel, # kernel
+ $self->[POE::Session::SE_NAMESPACE], # heap
+ $state, # state
+ $source_session, # sender
+ undef, # unused #6
+ $file, # caller file name
+ $line, # caller file line
+ $etc # args
+ );
+
+ # Package/object are implied.
+ return $object->$method($message, @$etc);
+}
+
+package POE::Session::Message;
+
+use POE::Session;
+
+sub new {
+ my $class = shift;
+ my $self = bless [ @_ ], $class;
+ return $self;
+}
+
+sub object { $_[0]->[OBJECT] }
+sub session { $_[0]->[SESSION] }
+sub kernel { $_[0]->[KERNEL] }
+sub heap { $_[0]->[HEAP] }
+sub state { $_[0]->[STATE] }
+sub sender { $_[0]->[SENDER] }
+sub caller_file { $_[0]->[CALLER_FILE] }
+sub caller_line { $_[0]->[CALLER_LINE] }
+sub args { @{$_[0]->[ARG0]} }
+
+1;
+
+__END__
+
+=head1 NAME
+
+POE::Session::MessageBased - a message-based (not @_ based) POE::Session
+
+=head1 SYNOPSIS
+
+ use POE::Kernel;
+ use POE::Session::MessageBased;
+
+ POE::Session::MessageBased->create
+ ( inline_states =>
+ { _start => sub {
+ my $message = shift;
+ print "Started.\n";
+ $message->kernel->yield( count => 2 );
+ },
+ count => sub {
+ my ($message, $count) = @_;
+ print "Counted to $count.\n";
+ if ($count < 10) {
+ $message->kernel->yield( count => ++$count );
+ }
+ },
+ _stop => sub {
+ print "Stopped.\n";
+ }
+ },
+ );
+
+ POE::Kernel->run();
+
+=head1 DESCRIPTION
+
+POE::Session::MessageBased exists mainly to replace @_[KERNEL, etc.]
+with message objects that encapsulate various aspects of each event.
+It also exists as an example of a subclassed POE::Session, in case
+someone wants to create new callback or Session semantics.
+
+People generally balk at the @_[KERNEL, etc.] calling convention that
+POE uses by default. The author defends the position that this
+calling convention is a simple combination of common Perl features.
+Interested people can read
+http://poe.perl.org/?POE_FAQ/calling_convention for a more detailed
+account.
+
+Anyway, POE::Session::MessageBased subclasses POE::Session and works
+almost identically to it. The major change is the way event handlers
+(states) are called.
+
+Inline (coderef) handlers gather their parameters like this.
+
+ my ($message, @args) = @_;
+
+Package and object-oriented handlers receive an additional parameter
+representing the package or object. This is part of the common
+calling convention that Perl uses.
+
+ my ($package, $message, @args) = @_; # Package states.
+ my ($self, $message, @args) = @_; # Object states.
+
+The $message parameter is an instance of POE::Session::Message, which
+is not documented elsewhere. POE::Session::Message encapsulates every
+POE parameter and provides accessors for them.
+
+ POE::Session POE::Session::MessageBased
+ ------------------------ -----------------------------------
+ $_[OBJECT] $package, or $self
+ $_[SESSION] $message->session
+ $_[KERNEL] $message->kernel
+ $_[HEAP] $message->heap
+ $_[STATE] $message->state
+ $_[SENDER] $message->sender
+ $_[CALLER_FILE] $message->caller_file
+ $_[CALLER_LINE] $message->caller_line
+ @_[ARG0..$#_] $message->args (in list context)
+
+You do not need to use POE::Session::Message yourself. It is included
+in POE::Session::MessageBased itself.
+
+=head1 BUGS
+
+$message->args() always returns a list: @_[ARG0..$#_]. It would be
+nice to return a list reference in scalar context.
+
+This is experimental code. Please use it in small projects or
+prototypes of your own, then discuss the ugly bits with the POE
+mailing list. Subscription information is available by sending a
+blank message to <poe-help@perl.org>. Thank you.
+
+=head1 AUTHOR & LICENSE
+
+POE::Session::MessageBased is Copyright 2002-2003 by Rocco Caputo.
+All rights are reserved. POE::Session::MessageBased is free software;
+you may redistribute it and/or modify it under the same terms as Perl
+itself.
+
+The author may be contacted by e-mail via rcaputo@cpan.org.
+
+=cut
94 trunk/README
@@ -0,0 +1,94 @@
+NAME
+ POE::Session::MessageBased - a message-based (not @_
+ based) POE::Session
+
+SYNOPSIS
+ use POE::Kernel;
+ use POE::Session::MessageBased;
+
+ POE::Session::MessageBased->create
+ ( inline_states =>
+ { _start => sub {
+ my $message = shift;
+ print "Started.\n";
+ $message->kernel->yield( count => 2 );
+ },
+ count => sub {
+ my ($message, $count) = @_;
+ print "Counted to $count.\n";
+ if ($count < 10) {
+ $message->kernel->yield( count => ++$count );
+ }
+ },
+ _stop => sub {
+ print "Stopped.\n";
+ }
+ },
+ );
+
+ POE::Kernel->run();
+
+
+DESCRIPTION
+ POE::Session::MessageBased exists mainly to replace
+ @_[KERNEL, etc.] with message objects that encapsulate
+ various aspects of each event. It also exists as an exam-
+ ple of a subclassed POE::Session, in case someone wants to
+ create new callback or Session semantics.
+
+ People generally balk at the @_[KERNEL, etc.] calling con-
+ vention that POE uses by default. The author defends the
+ position that this calling convention is a simple combina-
+ tion of common Perl features. Interested people can read
+ http://poe.perl.org/?POE_FAQ/calling_convention for a more
+ detailed account.
+
+ Anyway, POE::Session::MessageBased subclasses POE::Session
+ and works almost identically to it. The major change is
+ the way event handlers (states) are called.
+
+ Inline (coderef) handlers gather their parameters like
+ this.
+
+ my ($message, @args) = @_;
+
+ Package and object-oriented handlers receive an additional
+ parameter representing the package or object. This is
+ part of the common calling convention that Perl uses.
+
+ my ($package, $message, @args) = @_; # Package states.
+ my ($self, $message, @args) = @_; # Object states.
+
+ The $message parameter is an instance of
+ POE::Session::Message, which is not documented elsewhere.
+ POE::Session::Message encapsulates every POE parameter and
+ provides accessors for them.
+
+ POE::Session POE::Session::MessageBased
+ ------------------------ -----------------------------------
+ $_[OBJECT] $package, or $self
+ $_[SESSION] $message->session
+ $_[KERNEL] $message->kernel
+ $_[HEAP] $message->heap
+ $_[STATE] $message->state
+ $_[SENDER] $message->sender
+ $_[CALLER_FILE] $message->caller_file
+ $_[CALLER_LINE] $message->caller_line
+ @_[ARG0..$#_] $message->args (in list context)
+
+ You do not need to use POE::Session::Message yourself. It
+ is included in POE::Session::MessageBased itself.
+
+BUGS
+ $message->args() always returns a list: @_[ARG0..$#_]. It
+ would be nice to return a list reference in scalar con-
+ text.
+
+AUTHOR & LICENSE
+ POE::Session::MessageBased is Copyright 2002-2003 by Rocco
+ Caputo. All rights are reserved. POE::Session::Message-
+ Based is free software; you may redistribute it and/or
+ modify it under the same terms as Perl itself.
+
+ The author may be contacted by e-mail via
+ rcaputo@cpan.org.
36 trunk/t/01_basic.t
@@ -0,0 +1,36 @@
+#!/usr/bin/perl
+# $Id$
+
+use warnings;
+use strict;
+
+use lib './blib/lib';
+use lib '../blib/lib';
+
+use POE::Kernel;
+use POE::Session::MessageBased;
+
+print "1..11\n";
+
+POE::Session::MessageBased->create
+ ( inline_states =>
+ { _start => sub {
+ my ($message, @params) = @_;
+ print "not " unless $message->isa("POE::Session::Message");
+ print "ok 1\n";
+ $message->kernel->yield( count => 2 );
+ },
+ count => sub {
+ my ($message, $count) = @_;
+ print "ok $count\n";
+ if ($count < 10) {
+ $message->kernel->yield( count => ++$count );
+ }
+ },
+ _stop => sub {
+ print "ok 11\n";
+ }
+ },
+ );
+
+$poe_kernel->run();

0 comments on commit e04939c

Please sign in to comment.