1#!/usr/local/bin/perl -w
2
3# This is another simple functionality test.  It tests sessions that
4# are composed of objects (also called "object sessions").  It is
5# simpler than sessions.perl in many ways.
6
7use strict;
8use lib '../lib';
9use POE;
10
11#==============================================================================
12# Counter is an object that roughly approximates "child" sessions from
13# the sessions.perl test.  It counts for a little while, then stops.
14
15package Counter;
16use strict;
17use POE::Session;
18
19#------------------------------------------------------------------------------
20# This is a normal Perl object method.  It creates a new Counter
21# instance and returns a reference to it.  It's also possible for the
22# object to wrap itself in a Session within the constructor.
23# Self-wrapping objects are explored in other examples.
24
25sub new {
26  my ($type, $name) = @_;
27  print "Session ${name}'s object created.\n";
28  bless { 'name' => $name }, $type;
29}
30
31#------------------------------------------------------------------------------
32# This is a normal Perl object method.  It destroys a Counter object,
33# doing any late cleanup on the object.  This is different than the
34# _stop event handler, which handles late cleanup on the object's
35# Session.
36
37sub DESTROY {
38  my $self = shift;
39  print "Session $self->{name}'s object destroyed.\n";
40}
41
42#------------------------------------------------------------------------------
43# This method is an event handler.  It sets the session in motion
44# after POE sends the standard _start event.
45
46sub _start {
47  my ($object, $session, $heap, $kernel) = @_[OBJECT, SESSION, HEAP, KERNEL];
48                                        # register a signal handler
49  $kernel->sig('INT', 'sigint');
50                                        # initialize the counter
51  $heap->{'counter'} = 0;
52                                        # hello, world!
53  print "Session $object->{'name'} started.\n";
54
55  $kernel->post($session, 'increment');
56}
57
58#------------------------------------------------------------------------------
59# This method is an event handler, too.  It cleans up after receiving
60# POE's standard _stop event.
61
62sub _stop {
63  my ($object, $kernel, $heap) = @_[OBJECT, KERNEL, HEAP];
64
65  print "Session $object->{'name'} stopped after $heap->{'counter'} loops.\n";
66}
67
68#------------------------------------------------------------------------------
69# This method is an event handler.  It will be registered as a SIGINT
70# handler so that the session can acknowledge the signal.
71
72sub sigint {
73  my ($object, $from, $signal_name) = @_[OBJECT, SENDER, ARG0];
74
75  print "$object->{'name'} caught SIG$signal_name from $from\n";
76                                        # did not handle the signal
77  return 0;
78}
79
80#------------------------------------------------------------------------------
81# This method is an event handler.  It does most of counting work.  It
82# loops by posting events back to itself.  The session exits when
83# there is nothing left to do; this event handler causes that
84# condition when it stops posting events.
85
86sub increment {
87  my ($object, $kernel, $session, $heap) = @_[OBJECT, KERNEL, SESSION, HEAP];
88
89  $heap->{'counter'}++;
90
91  if ($heap->{counter} % 2) {
92    $kernel->state('runtime_state', $object);
93  }
94  else {
95    $kernel->state('runtime_state');
96  }
97
98  print "Session $object->{'name'}, iteration $heap->{'counter'}.\n";
99
100  if ($heap->{'counter'} < 5) {
101    $kernel->post($session, 'increment');
102    $kernel->yield('runtime_state', $heap->{counter});
103  }
104  else {
105    # no more events.  since there is nothing left to do, the session exits.
106  }
107}
108
109#------------------------------------------------------------------------------
110# This state is added on every even count.  It's removed on every odd
111# one.  Every count posts an event here.
112
113sub runtime_state {
114  my ($self, $iteration) = @_[OBJECT, ARG0];
115  print( 'Session ', $self->{name},
116         ' received a runtime_state event during iteration ',
117         $iteration, "\n"
118       );
119}
120
121#==============================================================================
122# Create ten Counter objects, and wrap them in sessions.
123
124package main;
125
126foreach my $name (qw(one two three four five six seven eight nine ten)) {
127  POE::Session->create(
128    object_states => [
129      Counter->new($name) => [ qw(_start _stop increment sigint) ]
130    ],
131  );
132}
133
134$poe_kernel->run();
135
136exit;
137