1POE::NFA(3)           User Contributed Perl Documentation          POE::NFA(3)
2
3
4

NAME

6       POE::NFA - an event-driven state machine (nondeterministic finite
7       automaton)
8

SYNOPSIS

10         use POE::Kernel;
11         use POE::NFA;
12         use POE::Wheel::ReadLine;
13
14         # Spawn an NFA and enter its initial state.
15         POE::NFA->spawn(
16           inline_states => {
17             initial => {
18               setup => \&setup_stuff,
19             },
20             state_login => {
21               on_entry => \&login_prompt,
22               on_input => \&save_login,
23             },
24             state_password => {
25               on_entry => \&password_prompt,
26               on_input => \&check_password,
27             },
28             state_cmd => {
29               on_entry => \&command_prompt,
30               on_input => \&handle_command,
31             },
32           },
33         )->goto_state(initial => "setup");
34
35         POE::Kernel->run();
36         exit;
37
38         sub setup_stuff {
39           $_[RUNSTATE]{io} = POE::Wheel::ReadLine->new(
40             InputEvent => 'on_input',
41           );
42           $_[MACHINE]->goto_state(state_login => "on_entry");
43         }
44
45         sub login_prompt { $_[RUNSTATE]{io}->get('Login: '); }
46
47         sub save_login {
48           $_[RUNSTATE]{login} = $_[ARG0];
49           $_[MACHINE]->goto_state(state_password => "on_entry");
50         }
51
52         sub password_prompt { $_[RUNSTATE]{io}->get('Password: '); }
53
54         sub check_password {
55           if ($_[RUNSTATE]{login} eq $_[ARG0]) {
56             $_[MACHINE]->goto_state(state_cmd => "on_entry");
57           }
58           else {
59             $_[MACHINE]->goto_state(state_login => "on_entry");
60           }
61         }
62
63         sub command_prompt { $_[RUNSTATE]{io}->get('Cmd: '); }
64
65         sub handle_command {
66           $_[RUNSTATE]{io}->put("  <<$_[ARG0]>>");
67           if ($_[ARG0] =~ /^(?:quit|stop|exit|halt|bye)$/i) {
68             $_[RUNSTATE]{io}->put('Bye!');
69             $_[MACHINE]->stop();
70           }
71           else {
72             $_[MACHINE]->goto_state(state_cmd => "on_entry");
73           }
74         }
75

DESCRIPTION

77       POE::NFA implements a different kind of POE session: A non-
78       deterministic finite automaton.  Let's break that down.
79
80       A finite automaton is a state machine with a bounded number of states
81       and transitions.  Technically, POE::NFA objects may modify themselves
82       at run time, so they aren't really "finite".  Run-time modification
83       isn't currently supported by the API, so plausible deniability is
84       maintained!
85
86       Deterministic state machines are ones where all possible transitions
87       are known at compile time.  POE::NFA is "non-deterministic" because
88       transitions may change based on run-time conditions.
89
90       But more simply, POE::NFA is like POE::Session but with banks of event
91       handlers that may be swapped according to the session's run-time state.
92       Consider the SYNOPSIS example, which has "on_entry" and "on_input"
93       handlers that do different things depending on the run-time state.
94       POE::Wheel::ReadLine throws "on_input", but different things happen
95       depending whether the session is in its "login", "password" or
96       "command" state.
97
98       POE::NFA borrows heavily from POE::Session, so this document will only
99       discuss the differences.  Please see POE::Session for things which are
100       similar.
101

PUBLIC METHODS

103       This document mainly focuses on the differences from POE::Session.
104
105   get_current_state
106       Each machine state has a name.  get_current_state() returns the name of
107       the machine's current state.  get_current_state() is mainly used to
108       retrieve the state of some other machine.  It's easier (and faster) to
109       use $_[STATE] in a machine's own event handlers.
110
111   get_runstate
112       get_runstate() returns the machine's current runstate.  Runstates are
113       equivalent to POE::Session HEAPs, so this method does pretty much the
114       same as POE::Session's get_heap().  It's easier (and faster) to use
115       $_[RUNSTATE] in a machine's own event handlers, however.
116
117   spawn STATE_NAME => HANDLERS_HASHREF[, ...]
118       spawn() is POE::NFA's constructor.  The name reflects the idea that new
119       state machines are spawned like threads or processes rather than
120       instantiated like objects.
121
122       The machine itself is defined as a list of state names and hashes that
123       map events to handlers within each state.
124
125         my %states = (
126           state_1 => {
127             event_1 => \&handler_1,
128             event_2 => \&handler_2,
129           },
130           state_2 => {
131             event_1 => \&handler_3,
132             event_2 => \&handler_4,
133           },
134         );
135
136       A single event may be handled by many states.  The proper handler will
137       be called depending on the machine's current state.  For example, if
138       "event_1" is dispatched while the machine is in "state_2", then
139       handler_3() will be called to handle the event.  The state -> event ->
140       handler map looks like this:
141
142         $machine{state_2}{event_1} = \&handler_3;
143
144       Instead of "inline_states", "object_states" or "package_states" may be
145       used. These map the events of a state to an object or package method
146       respectively.
147
148         object_states => {
149           state_1 => [
150             $object_1 => [qw(event_1 event_2)],
151           ],
152           state_2 => [
153             $object_2 => {
154               event_1 => method_1,
155               event_2 => method_2,
156             }
157           ]
158         }
159
160       In the example above, in the case of "event_1" coming in while the
161       machine is in "state_1", method "event_1" will be called on $object_1.
162       If the machine is in "state_2", method "method_1" will be called on
163       $object_2.
164
165       "package_states" is very similar, but instead of using an $object, you
166       pass in a "Package::Name"
167
168       The "runstate" parameter allows "RUNSTATE" to be initialized
169       differently at instantiation time. "RUNSTATE", like heaps, are usually
170       anonymous hashrefs, but "runstate" may set them to be array references
171       or even objects.
172
173       State transitions are not necessarily executed immediately by default.
174       Rather, they are placed in POEs event queue behind any currently
175       pending events.  Enabling the "immediate" option causes state
176       transitions to occur immediately, regardless of any queued events.
177
178   goto_state NEW_STATE[, ENTRY_EVENT[, EVENT_ARGS]]
179       goto_state() puts the machine into a new state.  If an ENTRY_EVENT is
180       specified, then that event will be dispatched after the machine enters
181       the new state.  EVENT_ARGS, if included, will be passed to the entry
182       event's handler via "ARG0..$#_".
183
184         # Switch to the next state.
185         $_[MACHINE]->goto_state( 'next_state' );
186
187         # Switch to the next state, and call a specific entry point.
188         $_[MACHINE]->goto_state( 'next_state', 'entry_event' );
189
190         # Switch to the next state; call an entry point with some values.
191         $_[MACHINE]->goto_state( 'next_state', 'entry_event', @parameters );
192
193   stop
194       stop() forces a machine to stop.  The machine will also stop gracefully
195       if it runs out of things to do, just like POE::Session.
196
197       stop() is heavy-handed.  It will force resources to be cleaned up.
198       However, circular references in the machine's "RUNSTATE" are not POE's
199       responsibility and may cause memory leaks.
200
201         $_[MACHINE]->stop();
202
203   call_state RETURN_EVENT, NEW_STATE[, ENTRY_EVENT[, EVENT_ARGS]]
204       call_state() is similar to goto_state(), but it pushes the current
205       state on a stack.  At some later point, a handler can call
206       return_state() to pop the call stack and return the machine to its old
207       state.  At that point, a "RETURN_EVENT" will be posted to notify the
208       old state of the return.
209
210         $machine->call_state( 'return_here', 'new_state', 'entry_event' );
211
212       As with goto_state(), "ENTRY_EVENT" is the event that will be emitted
213       once the machine enters its new state.  "ENTRY_ARGS" are parameters
214       passed to the "ENTRY_EVENT" handler via "ARG0..$#_".
215
216   return_state [RETURN_ARGS]
217       return_state() returns to the most recent state in which call_state()
218       was invoked.  If the preceding call_state() included a return event
219       then its handler will be invoked along with some optional
220       "RETURN_ARGS".  The "RETURN_ARGS" will be passed to the return handler
221       via "ARG0..$#_".
222
223         $_[MACHINE]->return_state( 'success', @success_values );
224
225   Methods that match POE::Session
226       The following methods behave identically to the ones in POE::Session.
227
228       ID
229       option
230       postback
231       callback
232
233   About new() and create()
234       POE::NFA's constructor is spawn(), not new() or create().
235

PREDEFINED EVENT FIELDS

237       POE::NFA's predefined event fields are the same as POE::Session's with
238       the following three exceptions.
239
240   MACHINE
241       "MACHINE" is equivalent to Session's "SESSION" field.  It holds a
242       reference to the current state machine, and is useful for calling its
243       methods.
244
245       See POE::Session's "SESSION" field for more information.
246
247         $_[MACHINE]->goto_state( $next_state, $next_state_entry_event );
248
249   RUNSTATE
250       "RUNSTATE" is equivalent to Session's "HEAP" field.  It holds an
251       anonymous hash reference which POE is guaranteed not to touch.  Data
252       stored in "RUNSTATE" will persist between handler invocations.
253
254   STATE
255       "STATE" contains the name of the machine's current state.  It is not
256       equivalent to anything from POE::Session.
257
258   EVENT
259       "EVENT" is equivalent to Session's "STATE" field.  It holds the name of
260       the event which invoked the current handler.  See POE::Session's
261       "STATE" field for more information.
262

PREDEFINED EVENT NAMES

264       POE::NFA defines four events of its own.  These events are used
265       internally and may not be overridden by application code.
266
267       See POE::Session's "PREDEFINED EVENT NAMES" section for more
268       information about other predefined events.
269
270       The events are: "poe_nfa_goto_state", "poe_nfa_push_state",
271       "poe_nfa_pop_state", "poe_nfa_stop".
272
273       Yes, all the internal events begin with "poe_nfa_".  More may be
274       forthcoming, but they will always begin the same way.  Therefore please
275       do not define events beginning with "poe_nfa_".
276

SEE ALSO

278       Many of POE::NFA's features are taken directly from POE::Session.
279       Please see POE::Session for more information.
280
281       The SEE ALSO section in POE contains a table of contents covering the
282       entire POE distribution.
283

BUGS

285       See POE::Session's documentation.
286
287       POE::NFA is not as feature-complete as POE::Session.  Your feedback is
288       appreciated.
289

AUTHORS & COPYRIGHTS

291       Please see POE for more information about authors and contributors.
292
293
294
295perl v5.30.0                      2019-07-26                       POE::NFA(3)
Impressum