Skip to content


Subversion checkout URL

You can clone with
Download ZIP


Immediate state transitions in POE::NFA #12

merged 3 commits into from

2 participants


I've run into a situation where POE::NFAs posting of state transitions into POEs event queue has become an issue. My machine processes a string of events and the output of the machine is completely dependant upon the type and order of previous events. As such, when an event causes a state change, I expect the change to happen immediately, because of and regardless of any not-yet-dispatched events in the event queue.

The crux of my issue is that due to NFAs non-immediate state transitions, the output of the machine is vastly different depending on whether or not the event queue contains any events at any point during its operation. While there are certainly ways to mitigate or eliminate the queuing of the next event to be processed until after the state change has been posted, this is not desirable nor always possible.

In my readings, I stumbled across a thread [ ] from over a decade[!] ago regarding this same issue. From my understanding, the core issue has not been completely resolved. I have implemented an 'immediate' option for POE::NFA that, when enabled, causes state changes to be sent with 'call' rather than with 'post', which resolves the aforementioned issue. I am hardly partial to my commits, but I would certainly appreciate further discussion on this topic.

David Huebner

@rcaputo rcaputo merged commit 88d27d6 into rcaputo:master

Thank you for the pull request. If it passes 'make test', I'll ship it.

I'm a bit more relaxed than I was a decade ago. I like that it's an option, and I like that the default behavior maintains compatibility. It would have been a little nicer to combine commits ffbd225 and 71b1647 before sending the pull request, but I'm not going to be a jerk and reject your pull request for that.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Commits on Apr 19, 2012
  1. @hubie
Commits on Apr 24, 2012
  1. @hubie

    Added a bit of documentation about the new immediate option as well a…

    hubie authored
    …s how POE::NFA operates by default.
  2. @hubie
This page is out of date. Refresh to see the latest.
Showing with 29 additions and 10 deletions.
  1. +29 −10 lib/POE/
39 lib/POE/
@@ -16,6 +16,7 @@ sub SPAWN_RUNSTATE () { 'runstate' }
sub OPT_TRACE () { 'trace' }
sub OPT_DEBUG () { 'debug' }
sub OPT_DEFAULT () { 'default' }
+sub OPT_IMMEDIATE () { 'immediate' }
sub EN_DEFAULT () { '_default' }
sub EN_START () { '_start' }
@@ -745,8 +746,7 @@ sub callback {
sub goto_state {
my ($self, $new_state, $entry_event, @entry_args) = @_;
- if (defined $self->[SELF_CURRENT]) {
+ if (defined $self->[SELF_CURRENT] && !$self->[SELF_OPTIONS]->{+OPT_IMMEDIATE}) {
$new_state, $entry_event, @entry_args
@@ -767,16 +767,30 @@ sub stop {
sub call_state {
my ($self, $return_event, $new_state, $entry_event, @entry_args) = @_;
- $POE::Kernel::poe_kernel->post(
- $return_event,
- $new_state, $entry_event, @entry_args
- );
+ if ($self->[SELF_OPTIONS]->{+OPT_IMMEDIATE}) {
+ $POE::Kernel::poe_kernel->call(
+ $return_event,
+ $new_state, $entry_event, @entry_args
+ );
+ }
+ else {
+ $POE::Kernel::poe_kernel->post(
+ $return_event,
+ $new_state, $entry_event, @entry_args
+ );
+ }
sub return_state {
my ($self, @entry_args) = @_;
- $POE::Kernel::poe_kernel->post( $self, NFA_EN_POP_STATE, @entry_args );
+ if ($self->[SELF_OPTIONS]->{+OPT_IMMEDIATE}) {
+ $POE::Kernel::poe_kernel->call( $self, NFA_EN_POP_STATE, @entry_args );
+ }
+ else {
+ $POE::Kernel::poe_kernel->post( $self, NFA_EN_POP_STATE, @entry_args );
+ }
@@ -951,10 +965,15 @@ machine is in C<state_2>, method C<method_1> will be called on $object_2.
C<package_states> is very similar, but instead of using an $object, you
pass in a C<Package::Name>
-The C<runstate> parameter allows C<RUNSTATE> to be initialized differently
-at instantiation time. C<RUNSTATE>, like heaps, are usually anonymous hashrefs,
+The C<runstate> parameter allows C<RUNSTATE> to be initialized differently
+at instantiation time. C<RUNSTATE>, like heaps, are usually anonymous hashrefs,
but C<runstate> may set them to be array references or even objects.
+State transitions are not necessarily executed immediately by default. Rather,
+they are placed in POEs event queue behind any currently pending events.
+Enabling the C<immediate> option causes state transitions to occur immediately,
+regardless of any queued events.
=head2 goto_state NEW_STATE[, ENTRY_EVENT[, EVENT_ARGS]]
goto_state() puts the machine into a new state. If an ENTRY_EVENT is
Something went wrong with that request. Please try again.