line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
package MooX::Role::POE::Emitter; |
2
|
|
|
|
|
|
|
$MooX::Role::POE::Emitter::VERSION = '1.001002'; |
3
|
4
|
|
|
4
|
|
45029
|
use strictures 2; |
|
4
|
|
|
|
|
39
|
|
|
4
|
|
|
|
|
197
|
|
4
|
|
|
|
|
|
|
|
5
|
4
|
|
|
4
|
|
1237
|
use feature 'state'; |
|
4
|
|
|
|
|
8
|
|
|
4
|
|
|
|
|
445
|
|
6
|
4
|
|
|
4
|
|
25
|
use Carp; |
|
4
|
|
|
|
|
7
|
|
|
4
|
|
|
|
|
365
|
|
7
|
4
|
|
|
4
|
|
26
|
use Scalar::Util 'reftype'; |
|
4
|
|
|
|
|
5
|
|
|
4
|
|
|
|
|
403
|
|
8
|
|
|
|
|
|
|
|
9
|
4
|
|
|
4
|
|
2835
|
use List::Objects::WithUtils; |
|
4
|
|
|
|
|
4046
|
|
|
4
|
|
|
|
|
30
|
|
10
|
4
|
|
|
4
|
|
402340
|
use List::Objects::Types -all; |
|
4
|
|
|
|
|
425830
|
|
|
4
|
|
|
|
|
74
|
|
11
|
4
|
|
|
4
|
|
27382
|
use Types::Standard -types; |
|
4
|
|
|
|
|
11
|
|
|
4
|
|
|
|
|
43
|
|
12
|
|
|
|
|
|
|
|
13
|
4
|
|
|
4
|
|
19654
|
use MooX::Role::Pluggable::Constants; |
|
4
|
|
|
|
|
1019
|
|
|
4
|
|
|
|
|
361
|
|
14
|
|
|
|
|
|
|
|
15
|
4
|
|
|
4
|
|
739
|
use POE; |
|
4
|
|
|
|
|
52998
|
|
|
4
|
|
|
|
|
38
|
|
16
|
|
|
|
|
|
|
|
17
|
|
|
|
|
|
|
sub E_TAG () { 'Emitter Running' } |
18
|
|
|
|
|
|
|
|
19
|
|
|
|
|
|
|
=pod |
20
|
|
|
|
|
|
|
|
21
|
|
|
|
|
|
|
=for Pod::Coverage E_TAG |
22
|
|
|
|
|
|
|
|
23
|
|
|
|
|
|
|
=cut |
24
|
|
|
|
|
|
|
|
25
|
|
|
|
|
|
|
|
26
|
4
|
|
|
4
|
|
74083
|
use Moo::Role; |
|
4
|
|
|
|
|
10
|
|
|
4
|
|
|
|
|
38
|
|
27
|
|
|
|
|
|
|
with 'MooX::Role::Pluggable'; |
28
|
|
|
|
|
|
|
|
29
|
|
|
|
|
|
|
|
30
|
|
|
|
|
|
|
has alias => ( |
31
|
|
|
|
|
|
|
lazy => 1, |
32
|
|
|
|
|
|
|
is => 'ro', |
33
|
|
|
|
|
|
|
isa => Str, |
34
|
|
|
|
|
|
|
predicate => 'has_alias', |
35
|
|
|
|
|
|
|
writer => 'set_alias', |
36
|
|
|
|
|
|
|
default => sub { my $self = shift; "$self" }, |
37
|
|
|
|
|
|
|
); |
38
|
|
|
|
|
|
|
|
39
|
|
|
|
|
|
|
around set_alias => sub { |
40
|
|
|
|
|
|
|
my ($orig, $self, $value) = @_; |
41
|
|
|
|
|
|
|
|
42
|
|
|
|
|
|
|
if ( $poe_kernel->alias_resolve( $self->session_id ) ) { |
43
|
|
|
|
|
|
|
$self->call( __emitter_reset_alias => $value ); |
44
|
|
|
|
|
|
|
$self->emit( $self->event_prefix . 'alias_set' => $value ); |
45
|
|
|
|
|
|
|
} |
46
|
|
|
|
|
|
|
|
47
|
|
|
|
|
|
|
$self->$orig($value) |
48
|
|
|
|
|
|
|
}; |
49
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
has event_prefix => ( |
51
|
|
|
|
|
|
|
lazy => 1, |
52
|
|
|
|
|
|
|
is => 'ro', |
53
|
|
|
|
|
|
|
isa => Str, |
54
|
|
|
|
|
|
|
predicate => 'has_event_prefix', |
55
|
|
|
|
|
|
|
writer => 'set_event_prefix', |
56
|
|
|
|
|
|
|
default => sub { 'emitted_' }, |
57
|
|
|
|
|
|
|
); |
58
|
|
|
|
|
|
|
|
59
|
|
|
|
|
|
|
has pluggable_type_prefixes => ( |
60
|
|
|
|
|
|
|
## Optionally remap PROCESS / NOTIFY types |
61
|
|
|
|
|
|
|
lazy => 1, |
62
|
|
|
|
|
|
|
is => 'ro', |
63
|
|
|
|
|
|
|
isa => HashObj, |
64
|
|
|
|
|
|
|
coerce => 1, |
65
|
|
|
|
|
|
|
predicate => 'has_pluggable_type_prefixes', |
66
|
|
|
|
|
|
|
writer => 'set_pluggable_type_prefixes', |
67
|
|
|
|
|
|
|
default => sub { |
68
|
|
|
|
|
|
|
hash( PROCESS => 'P', NOTIFY => 'N' ) |
69
|
|
|
|
|
|
|
}, |
70
|
|
|
|
|
|
|
); |
71
|
|
|
|
|
|
|
|
72
|
|
|
|
|
|
|
|
73
|
|
|
|
|
|
|
has object_states => ( |
74
|
|
|
|
|
|
|
lazy => 1, |
75
|
|
|
|
|
|
|
is => 'ro', |
76
|
|
|
|
|
|
|
isa => ArrayObj, |
77
|
|
|
|
|
|
|
coerce => 1, |
78
|
|
|
|
|
|
|
predicate => 'has_object_states', |
79
|
|
|
|
|
|
|
writer => 'set_object_states', |
80
|
|
|
|
|
|
|
trigger => 1, |
81
|
|
|
|
|
|
|
default => sub { array }, |
82
|
|
|
|
|
|
|
); |
83
|
|
|
|
|
|
|
|
84
|
|
|
|
|
|
|
sub _trigger_object_states { |
85
|
7
|
|
|
7
|
|
23187
|
my ($self, $states) = @_; |
86
|
|
|
|
|
|
|
|
87
|
7
|
50
|
|
|
|
38
|
$states = array(%$states) if reftype $states eq 'HASH'; |
88
|
|
|
|
|
|
|
|
89
|
7
|
50
|
33
|
|
|
52
|
confess "object_states() should be an ARRAY or HASH" |
90
|
|
|
|
|
|
|
unless ref $states and reftype $states eq 'ARRAY'; |
91
|
|
|
|
|
|
|
|
92
|
7
|
50
|
|
|
|
25
|
$states = array(@$states) unless is_ArrayObj $states; |
93
|
|
|
|
|
|
|
|
94
|
|
|
|
|
|
|
state $disallowed = array( qw/ |
95
|
|
|
|
|
|
|
_start |
96
|
|
|
|
|
|
|
_stop |
97
|
|
|
|
|
|
|
_default |
98
|
|
|
|
|
|
|
emit |
99
|
|
|
|
|
|
|
register |
100
|
|
|
|
|
|
|
unregister |
101
|
|
|
|
|
|
|
subscribe |
102
|
|
|
|
|
|
|
unsubscribe |
103
|
7
|
|
|
24
|
|
201
|
/ )->map(sub { $_ => 1 })->inflate; |
|
24
|
|
|
|
|
180
|
|
104
|
|
|
|
|
|
|
|
105
|
7
|
|
|
|
|
377
|
my $itr = $states->natatime(2); |
106
|
7
|
|
|
|
|
83
|
while (my (undef, $events) = $itr->()) { |
107
|
7
|
0
|
|
|
|
67
|
my $evarr = reftype $events eq 'ARRAY' ? array(@$events) |
|
|
50
|
|
|
|
|
|
108
|
|
|
|
|
|
|
: reftype $events eq 'HASH' ? array(keys %$events) |
109
|
|
|
|
|
|
|
: confess "Expected ARRAY or HASH but got $events"; |
110
|
|
|
|
|
|
|
$evarr->map( |
111
|
12
|
100
|
|
12
|
|
101
|
sub { confess "Disallowed handler: $_" if $disallowed->exists($_) } |
112
|
7
|
|
|
|
|
81
|
); |
113
|
|
|
|
|
|
|
} |
114
|
|
|
|
|
|
|
} |
115
|
|
|
|
|
|
|
|
116
|
|
|
|
|
|
|
|
117
|
|
|
|
|
|
|
has register_prefix => ( |
118
|
|
|
|
|
|
|
lazy => 1, |
119
|
|
|
|
|
|
|
is => 'ro', |
120
|
|
|
|
|
|
|
isa => Str, |
121
|
|
|
|
|
|
|
predicate => 'has_register_prefix', |
122
|
|
|
|
|
|
|
writer => 'set_register_prefix', |
123
|
|
|
|
|
|
|
## Emitter_register / Emitter_unregister |
124
|
|
|
|
|
|
|
default => sub { 'Emitter_' }, |
125
|
|
|
|
|
|
|
); |
126
|
|
|
|
|
|
|
|
127
|
|
|
|
|
|
|
has session_id => ( |
128
|
|
|
|
|
|
|
init_arg => undef, |
129
|
|
|
|
|
|
|
lazy => 1, |
130
|
|
|
|
|
|
|
is => 'ro', |
131
|
|
|
|
|
|
|
isa => Defined, |
132
|
|
|
|
|
|
|
predicate => 'has_session_id', |
133
|
|
|
|
|
|
|
writer => 'set_session_id', |
134
|
|
|
|
|
|
|
default => sub { -1 }, |
135
|
|
|
|
|
|
|
); |
136
|
|
|
|
|
|
|
|
137
|
|
|
|
|
|
|
has shutdown_signal => ( |
138
|
|
|
|
|
|
|
lazy => 1, |
139
|
|
|
|
|
|
|
is => 'ro', |
140
|
|
|
|
|
|
|
isa => Str, |
141
|
|
|
|
|
|
|
predicate => 'has_shutdown_signal', |
142
|
|
|
|
|
|
|
writer => 'set_shutdown_signal', |
143
|
|
|
|
|
|
|
default => sub { 'SHUTDOWN_EMITTER' }, |
144
|
|
|
|
|
|
|
); |
145
|
|
|
|
|
|
|
|
146
|
|
|
|
|
|
|
has __emitter_reg_sessions => ( |
147
|
|
|
|
|
|
|
lazy => 1, |
148
|
|
|
|
|
|
|
is => 'ro', |
149
|
|
|
|
|
|
|
isa => TypedHash[Object], |
150
|
|
|
|
|
|
|
default => sub { hash_of Object }, |
151
|
|
|
|
|
|
|
); |
152
|
|
|
|
|
|
|
|
153
|
|
|
|
|
|
|
|
154
|
|
|
|
|
|
|
has __emitter_reg_events => ( |
155
|
|
|
|
|
|
|
## ->{ $event }->{ $session_id } = 1 |
156
|
|
|
|
|
|
|
lazy => 1, |
157
|
|
|
|
|
|
|
is => 'ro', |
158
|
|
|
|
|
|
|
isa => TypedHash[ TypedHash[Int] ], |
159
|
|
|
|
|
|
|
coerce => 1, |
160
|
|
|
|
|
|
|
default => sub { hash_of TypedHash[Int] }, |
161
|
|
|
|
|
|
|
); |
162
|
|
|
|
|
|
|
|
163
|
|
|
|
|
|
|
|
164
|
|
|
|
|
|
|
sub _start_emitter { |
165
|
|
|
|
|
|
|
## Call to spawn Session. |
166
|
|
|
|
|
|
|
## my $emitter = MyClass->new( |
167
|
|
|
|
|
|
|
## alias => Emitter session alias |
168
|
|
|
|
|
|
|
## event_prefix => Session event prefix (emitted_) |
169
|
|
|
|
|
|
|
## register_prefix => _register/_unregister prefix (Emitter_) |
170
|
|
|
|
|
|
|
## object_states => Extra object_states for Session |
171
|
|
|
|
|
|
|
## )->_start_emitter(); |
172
|
4
|
|
|
4
|
|
3984
|
my ($self) = @_; |
173
|
|
|
|
|
|
|
|
174
|
4
|
|
|
|
|
11
|
my %types; |
175
|
4
|
100
|
|
|
|
27
|
if ( $self->has_pluggable_type_prefixes ) { |
176
|
1
|
|
50
|
|
|
4
|
$types{PROCESS} = $self->pluggable_type_prefixes->{PROCESS} ||= 'P'; |
177
|
1
|
|
50
|
|
|
997
|
$types{NOTIFY} = $self->pluggable_type_prefixes->{NOTIFY} ||= 'N'; |
178
|
|
|
|
|
|
|
} else { |
179
|
3
|
|
|
|
|
44
|
%types = ( PROCESS => 'P', NOTIFY => 'N' ); |
180
|
|
|
|
|
|
|
} |
181
|
|
|
|
|
|
|
|
182
|
4
|
|
|
|
|
55
|
$self->_pluggable_init( |
183
|
|
|
|
|
|
|
event_prefix => $self->event_prefix, |
184
|
|
|
|
|
|
|
reg_prefix => $self->register_prefix, |
185
|
|
|
|
|
|
|
types => \%types, |
186
|
|
|
|
|
|
|
); |
187
|
|
|
|
|
|
|
|
188
|
4
|
50
|
|
|
|
3790
|
POE::Session->create( |
189
|
|
|
|
|
|
|
object_states => [ |
190
|
|
|
|
|
|
|
|
191
|
|
|
|
|
|
|
$self => { |
192
|
|
|
|
|
|
|
'_start' => '__emitter_start', |
193
|
|
|
|
|
|
|
'_stop' => '__emitter_stop', |
194
|
|
|
|
|
|
|
'shutdown_emitter' => '__shutdown_emitter', |
195
|
|
|
|
|
|
|
|
196
|
|
|
|
|
|
|
'register' => '__emitter_register', |
197
|
|
|
|
|
|
|
'subscribe' => '__emitter_register', |
198
|
|
|
|
|
|
|
'unregister' => '__emitter_unregister', |
199
|
|
|
|
|
|
|
'unsubscribe' => '__emitter_unregister', |
200
|
|
|
|
|
|
|
'emit' => '__emitter_notify', |
201
|
|
|
|
|
|
|
|
202
|
|
|
|
|
|
|
'_default' => '__emitter_disp_default', |
203
|
|
|
|
|
|
|
'__emitter_real_default' => '_emitter_default', |
204
|
|
|
|
|
|
|
}, |
205
|
|
|
|
|
|
|
|
206
|
|
|
|
|
|
|
$self => [ qw/ |
207
|
|
|
|
|
|
|
__emitter_notify |
208
|
|
|
|
|
|
|
|
209
|
|
|
|
|
|
|
__emitter_timer_set |
210
|
|
|
|
|
|
|
__emitter_timer_del |
211
|
|
|
|
|
|
|
|
212
|
|
|
|
|
|
|
__emitter_sigdie |
213
|
|
|
|
|
|
|
|
214
|
|
|
|
|
|
|
__emitter_reset_alias |
215
|
|
|
|
|
|
|
|
216
|
|
|
|
|
|
|
__emitter_sig_shutdown |
217
|
|
|
|
|
|
|
/ ], |
218
|
|
|
|
|
|
|
|
219
|
|
|
|
|
|
|
( |
220
|
|
|
|
|
|
|
$self->has_object_states ? $self->object_states->all : () |
221
|
|
|
|
|
|
|
), |
222
|
|
|
|
|
|
|
|
223
|
|
|
|
|
|
|
], |
224
|
|
|
|
|
|
|
); |
225
|
|
|
|
|
|
|
|
226
|
4
|
|
|
|
|
727
|
$self |
227
|
|
|
|
|
|
|
} |
228
|
|
|
|
|
|
|
|
229
|
|
|
|
|
|
|
around '_pluggable_event' => sub { |
230
|
|
|
|
|
|
|
my ($orig, $self) = splice @_, 0, 2; |
231
|
|
|
|
|
|
|
|
232
|
|
|
|
|
|
|
## Overriden from Role::Pluggable |
233
|
|
|
|
|
|
|
## Receives plugin_error, plugin_add etc |
234
|
|
|
|
|
|
|
## Redispatch via emit() |
235
|
|
|
|
|
|
|
|
236
|
|
|
|
|
|
|
$self->emit( @_ ); |
237
|
|
|
|
|
|
|
}; |
238
|
|
|
|
|
|
|
|
239
|
|
|
|
|
|
|
|
240
|
|
|
|
|
|
|
### Public: |
241
|
|
|
|
|
|
|
|
242
|
|
|
|
|
|
|
sub timer { |
243
|
4
|
|
|
4
|
1
|
531
|
my ($self, $time, $event, @args) = @_; |
244
|
|
|
|
|
|
|
|
245
|
4
|
100
|
66
|
|
|
112
|
confess "timer() expected at least a time and event name" |
246
|
|
|
|
|
|
|
unless defined $time and defined $event; |
247
|
|
|
|
|
|
|
|
248
|
3
|
|
|
|
|
6
|
$self->call( __emitter_timer_set => $time, $event, @args ) |
249
|
|
|
|
|
|
|
} |
250
|
|
|
|
|
|
|
|
251
|
|
|
|
|
|
|
sub __emitter_timer_set { |
252
|
3
|
|
|
3
|
|
193
|
my ($kernel, $self) = @_[KERNEL, OBJECT]; |
253
|
3
|
|
|
|
|
6
|
my ($time, $event, @args) = @_[ARG0 .. $#_]; |
254
|
|
|
|
|
|
|
|
255
|
3
|
|
|
|
|
9
|
my $alarm_id = $poe_kernel->delay_set( $event, $time, @args ); |
256
|
|
|
|
|
|
|
|
257
|
3
|
50
|
|
|
|
147
|
$self->emit( $self->event_prefix . 'timer_set', |
258
|
|
|
|
|
|
|
$alarm_id, |
259
|
|
|
|
|
|
|
$event, |
260
|
|
|
|
|
|
|
$time, |
261
|
|
|
|
|
|
|
@args |
262
|
|
|
|
|
|
|
) if $alarm_id; |
263
|
|
|
|
|
|
|
|
264
|
3
|
|
|
|
|
8
|
$alarm_id |
265
|
|
|
|
|
|
|
} |
266
|
|
|
|
|
|
|
|
267
|
|
|
|
|
|
|
sub timer_del { |
268
|
2
|
|
|
2
|
1
|
253
|
my ($self, $alarm_id) = @_; |
269
|
|
|
|
|
|
|
|
270
|
2
|
100
|
|
|
|
99
|
confess "timer_del() expects an alarm ID" |
271
|
|
|
|
|
|
|
unless defined $alarm_id; |
272
|
|
|
|
|
|
|
|
273
|
1
|
|
|
|
|
6
|
$self->call( __emitter_timer_del => $alarm_id ); |
274
|
|
|
|
|
|
|
} |
275
|
|
|
|
|
|
|
|
276
|
|
|
|
|
|
|
sub __emitter_timer_del { |
277
|
1
|
|
|
1
|
|
63
|
my ($kernel, $self, $alarm_id) = @_[KERNEL, OBJECT, ARG0]; |
278
|
|
|
|
|
|
|
|
279
|
1
|
|
|
|
|
5
|
my @deleted = $poe_kernel->alarm_remove($alarm_id); |
280
|
1
|
50
|
|
|
|
36
|
return unless @deleted; |
281
|
|
|
|
|
|
|
|
282
|
0
|
|
|
|
|
0
|
my ($event, undef, $params) = @deleted; |
283
|
|
|
|
|
|
|
|
284
|
0
|
0
|
|
|
|
0
|
$self->emit( $self->event_prefix . 'timer_deleted', |
285
|
|
|
|
|
|
|
$alarm_id, |
286
|
|
|
|
|
|
|
$event, |
287
|
0
|
|
|
|
|
0
|
@{ $params || [] } |
288
|
|
|
|
|
|
|
); |
289
|
|
|
|
|
|
|
|
290
|
0
|
|
|
|
|
0
|
$params |
291
|
|
|
|
|
|
|
} |
292
|
|
|
|
|
|
|
|
293
|
|
|
|
|
|
|
## yield/call provide post()/call() frontends. |
294
|
|
|
|
|
|
|
sub yield { |
295
|
25
|
|
|
25
|
1
|
1421
|
my ($self, @args) = @_; |
296
|
|
|
|
|
|
|
|
297
|
25
|
|
|
|
|
74
|
$poe_kernel->post( $self->session_id, @args ); |
298
|
|
|
|
|
|
|
|
299
|
25
|
|
|
|
|
2568
|
$self |
300
|
|
|
|
|
|
|
} |
301
|
|
|
|
|
|
|
|
302
|
|
|
|
|
|
|
sub call { |
303
|
39
|
|
|
39
|
1
|
245
|
my ($self, @args) = @_; |
304
|
|
|
|
|
|
|
|
305
|
39
|
|
|
|
|
131
|
$poe_kernel->call( $self->session_id, @args ); |
306
|
|
|
|
|
|
|
|
307
|
39
|
|
|
|
|
2419
|
$self |
308
|
|
|
|
|
|
|
} |
309
|
|
|
|
|
|
|
|
310
|
|
|
|
|
|
|
sub emit { |
311
|
|
|
|
|
|
|
## Async NOTIFY event dispatch. |
312
|
18
|
|
|
18
|
1
|
996
|
my ($self, $event, @args) = @_; |
313
|
|
|
|
|
|
|
|
314
|
18
|
|
|
|
|
53
|
$self->yield( __emitter_notify => $event, @args ); |
315
|
|
|
|
|
|
|
|
316
|
18
|
|
|
|
|
32
|
$self |
317
|
|
|
|
|
|
|
} |
318
|
|
|
|
|
|
|
|
319
|
|
|
|
|
|
|
sub emit_now { |
320
|
|
|
|
|
|
|
## Synchronous NOTIFY event dispatch. |
321
|
1
|
|
|
1
|
1
|
5
|
my ($self, $event, @args) = @_; |
322
|
|
|
|
|
|
|
|
323
|
1
|
|
|
|
|
5
|
$self->call( __emitter_notify => $event, @args ); |
324
|
|
|
|
|
|
|
|
325
|
1
|
|
|
|
|
2
|
$self |
326
|
|
|
|
|
|
|
} |
327
|
|
|
|
|
|
|
|
328
|
|
|
|
|
|
|
sub process { |
329
|
11
|
|
|
11
|
1
|
1040
|
my ($self, $event, @args) = @_; |
330
|
|
|
|
|
|
|
## Dispatch PROCESS events. |
331
|
|
|
|
|
|
|
## process() events should _pluggable_process immediately |
332
|
|
|
|
|
|
|
## and return the EAT value. |
333
|
|
|
|
|
|
|
|
334
|
|
|
|
|
|
|
## Dispatched to P_$event : |
335
|
11
|
|
|
|
|
41
|
$self->_pluggable_process( PROCESS => $event, \@args ) |
336
|
|
|
|
|
|
|
} |
337
|
|
|
|
|
|
|
|
338
|
|
|
|
|
|
|
|
339
|
|
|
|
|
|
|
|
340
|
|
|
|
|
|
|
## Session ref-counting bits. |
341
|
|
|
|
|
|
|
{ package MooX::Role::POE::Emitter::RegisteredSession; |
342
|
|
|
|
|
|
|
$MooX::Role::POE::Emitter::RegisteredSession::VERSION = '1.001002'; |
343
|
4
|
|
|
4
|
|
10176
|
use Moo; |
|
4
|
|
|
|
|
10
|
|
|
4
|
|
|
|
|
36
|
|
344
|
|
|
|
|
|
|
has [qw/id refcount/] => ( is => 'rw', required => 1 ); |
345
|
|
|
|
|
|
|
} |
346
|
|
|
|
|
|
|
|
347
|
|
|
|
|
|
|
sub __get_ses_refc { |
348
|
9
|
|
|
9
|
|
133
|
my ($self, $sess_id) = @_; |
349
|
9
|
|
|
|
|
29
|
my $regsess_obj = $self->__emitter_reg_sessions->get($sess_id); |
350
|
9
|
50
|
|
|
|
360
|
return unless $regsess_obj; |
351
|
9
|
|
|
|
|
60
|
$regsess_obj->refcount |
352
|
|
|
|
|
|
|
} |
353
|
|
|
|
|
|
|
|
354
|
|
|
|
|
|
|
sub __reg_ses_id { |
355
|
9
|
|
|
9
|
|
19
|
my ($self, $sess_id) = @_; |
356
|
9
|
100
|
|
|
|
42
|
return if $self->__emitter_reg_sessions->exists($sess_id); |
357
|
5
|
|
|
|
|
2594
|
$self->__emitter_reg_sessions->set($sess_id => |
358
|
|
|
|
|
|
|
MooX::Role::POE::Emitter::RegisteredSession->new( |
359
|
|
|
|
|
|
|
id => $sess_id, |
360
|
|
|
|
|
|
|
refcount => 0 |
361
|
|
|
|
|
|
|
) |
362
|
|
|
|
|
|
|
); |
363
|
|
|
|
|
|
|
} |
364
|
|
|
|
|
|
|
|
365
|
|
|
|
|
|
|
sub __incr_ses_refc { |
366
|
9
|
|
|
9
|
|
22
|
my ($self, $sess_id) = @_; |
367
|
|
|
|
|
|
|
|
368
|
9
|
|
|
|
|
29
|
my $regsess_obj = $self->__emitter_reg_sessions->get($sess_id); |
369
|
9
|
50
|
|
|
|
370
|
unless (defined $regsess_obj) { |
370
|
0
|
|
|
|
|
0
|
confess "BUG; attempted to increase nonexistant refcount for '$sess_id'"; |
371
|
|
|
|
|
|
|
} |
372
|
|
|
|
|
|
|
|
373
|
9
|
|
|
|
|
30
|
$self->__emitter_reg_sessions->set($sess_id => |
374
|
|
|
|
|
|
|
MooX::Role::POE::Emitter::RegisteredSession->new( |
375
|
|
|
|
|
|
|
id => $sess_id, |
376
|
|
|
|
|
|
|
refcount => $regsess_obj->refcount + 1, |
377
|
|
|
|
|
|
|
) |
378
|
|
|
|
|
|
|
); |
379
|
|
|
|
|
|
|
|
380
|
9
|
|
|
|
|
914
|
$self->__emitter_reg_sessions->get($sess_id)->refcount |
381
|
|
|
|
|
|
|
} |
382
|
|
|
|
|
|
|
|
383
|
|
|
|
|
|
|
sub __decr_ses_refc { |
384
|
1
|
|
|
1
|
|
4
|
my ($self, $sess_id) = @_; |
385
|
|
|
|
|
|
|
|
386
|
1
|
|
|
|
|
6
|
my $regsess_obj = $self->__emitter_reg_sessions->get($sess_id); |
387
|
1
|
50
|
|
|
|
59
|
unless (defined $regsess_obj) { |
388
|
0
|
|
|
|
|
0
|
confess "BUG; attempted to decrease nonexistant refcount for '$sess_id'" |
389
|
|
|
|
|
|
|
} |
390
|
|
|
|
|
|
|
|
391
|
|
|
|
|
|
|
$self->__emitter_reg_sessions->set($sess_id => |
392
|
1
|
|
|
|
|
5
|
do { |
393
|
1
|
|
|
|
|
45
|
my $refc = $regsess_obj->refcount - 1; |
394
|
1
|
50
|
|
|
|
5
|
$refc = 0 if $refc < 0; # FIXME delete (and return above) instead? |
395
|
1
|
|
|
|
|
34
|
MooX::Role::POE::Emitter::RegisteredSession->new( |
396
|
|
|
|
|
|
|
id => $sess_id, |
397
|
|
|
|
|
|
|
refcount => $refc, |
398
|
|
|
|
|
|
|
) |
399
|
|
|
|
|
|
|
}, |
400
|
|
|
|
|
|
|
); |
401
|
|
|
|
|
|
|
} |
402
|
|
|
|
|
|
|
|
403
|
|
|
|
|
|
|
sub __emitter_drop_sessions { |
404
|
12
|
|
|
12
|
|
28
|
my ($self) = @_; |
405
|
|
|
|
|
|
|
|
406
|
12
|
|
|
|
|
39
|
for my $id ($self->__emitter_reg_sessions->keys->all) { |
407
|
4
|
|
|
|
|
286
|
my $count = $self->__get_ses_refc($id); |
408
|
4
|
|
|
|
|
20
|
while ( $count-- > 0 ) { |
409
|
8
|
|
|
|
|
180
|
$poe_kernel->refcount_decrement( $id, E_TAG ) |
410
|
|
|
|
|
|
|
} |
411
|
|
|
|
|
|
|
|
412
|
4
|
|
|
|
|
109
|
$self->__emitter_reg_sessions->delete($id) |
413
|
|
|
|
|
|
|
} |
414
|
|
|
|
|
|
|
|
415
|
|
|
|
|
|
|
1 |
416
|
12
|
|
|
|
|
774
|
} |
417
|
|
|
|
|
|
|
|
418
|
|
|
|
|
|
|
|
419
|
|
|
|
|
|
|
## Our Session's handlers: |
420
|
|
|
|
|
|
|
|
421
|
|
|
|
|
|
|
sub __emitter_notify { |
422
|
|
|
|
|
|
|
## Dispatch a NOTIFY event |
423
|
19
|
|
|
19
|
|
3378
|
my ($kernel, $self) = @_[KERNEL, OBJECT]; |
424
|
19
|
|
|
|
|
67
|
my ($event, @args) = @_[ARG0 .. $#_]; |
425
|
|
|
|
|
|
|
|
426
|
19
|
|
|
|
|
64
|
my $prefix = $self->event_prefix; |
427
|
|
|
|
|
|
|
|
428
|
|
|
|
|
|
|
## May have event_prefix (such as $prefix.'plugin_error') |
429
|
19
|
100
|
|
|
|
797
|
substr($event, 0, length($prefix), '') if index($event, $prefix) == 0; |
430
|
|
|
|
|
|
|
|
431
|
19
|
|
|
|
|
23
|
my %sessions; |
432
|
|
|
|
|
|
|
|
433
|
19
|
|
|
|
|
39
|
for my $registered_ev ('all', $event) { |
434
|
38
|
100
|
|
|
|
297
|
if (my $sess_hash = $self->__emitter_reg_events->get($registered_ev)) { |
435
|
28
|
|
|
28
|
|
794
|
$sess_hash->keys->visit(sub { $sessions{$_} = 1 }) |
436
|
19
|
|
|
|
|
774
|
} |
437
|
|
|
|
|
|
|
} |
438
|
|
|
|
|
|
|
|
439
|
19
|
|
|
|
|
823
|
my $meth = $prefix . $event; |
440
|
|
|
|
|
|
|
|
441
|
|
|
|
|
|
|
## Our own session will get ->event_prefix . $event first |
442
|
19
|
100
|
|
|
|
79
|
$kernel->call( $_[SESSION], $meth, @args ) |
443
|
|
|
|
|
|
|
if delete $sessions{ $_[SESSION]->ID }; |
444
|
|
|
|
|
|
|
|
445
|
|
|
|
|
|
|
## Dispatched to N_$event after our Session has been notified: |
446
|
19
|
100
|
|
|
|
227
|
unless ( $self->_pluggable_process('NOTIFY', $event, \@args) == EAT_ALL ) { |
447
|
|
|
|
|
|
|
## Notify subscribed sessions. |
448
|
17
|
|
|
|
|
4011
|
$kernel->call( $_ => $meth, @args ) for keys %sessions; |
449
|
|
|
|
|
|
|
} |
450
|
|
|
|
|
|
|
|
451
|
|
|
|
|
|
|
## Received emitted 'shutdown', drop sessions. |
452
|
19
|
100
|
|
|
|
1486
|
$self->__emitter_drop_sessions if $event eq 'shutdown'; |
453
|
|
|
|
|
|
|
} |
454
|
|
|
|
|
|
|
|
455
|
|
|
|
|
|
|
sub __emitter_start { |
456
|
|
|
|
|
|
|
## _start handler |
457
|
4
|
|
|
4
|
|
3709
|
my ($kernel, $self) = @_[KERNEL, OBJECT]; |
458
|
4
|
|
|
|
|
12
|
my ($session, $sender) = @_[SESSION, SENDER]; |
459
|
|
|
|
|
|
|
|
460
|
4
|
|
|
|
|
16
|
$self->set_session_id( $session->ID ); |
461
|
|
|
|
|
|
|
|
462
|
4
|
|
|
|
|
2233
|
$kernel->alias_set( $self->alias ); |
463
|
|
|
|
|
|
|
|
464
|
4
|
|
|
|
|
1907
|
$kernel->sig( DIE => '__emitter_sigdie' ); |
465
|
4
|
|
|
|
|
165
|
$kernel->sig( $self->shutdown_signal => '__emitter_sig_shutdown' ); |
466
|
|
|
|
|
|
|
|
467
|
4
|
50
|
|
|
|
188
|
unless ($sender == $kernel) { |
468
|
|
|
|
|
|
|
## Have a parent session. |
469
|
4
|
|
|
|
|
19
|
my $s_id = $sender->ID; |
470
|
4
|
|
|
|
|
32
|
$kernel->refcount_increment( $s_id, E_TAG ); |
471
|
4
|
|
|
|
|
148
|
$self->__reg_ses_id( $s_id ); |
472
|
4
|
|
|
|
|
4207
|
$self->__incr_ses_refc( $s_id ); |
473
|
|
|
|
|
|
|
|
474
|
|
|
|
|
|
|
## subscribe parent session to all notification events |
475
|
4
|
|
|
|
|
203
|
$self->__emitter_reg_events->{all}->{ $s_id } = 1; |
476
|
|
|
|
|
|
|
|
477
|
|
|
|
|
|
|
## Detach child session. |
478
|
4
|
|
|
|
|
9594
|
$kernel->detach_myself; |
479
|
|
|
|
|
|
|
} |
480
|
|
|
|
|
|
|
|
481
|
4
|
|
|
|
|
251
|
$self->call('emitter_started'); |
482
|
|
|
|
|
|
|
|
483
|
4
|
|
|
|
|
27
|
$self |
484
|
|
|
|
|
|
|
} |
485
|
|
|
|
|
|
|
|
486
|
|
|
|
|
|
|
sub __emitter_reset_alias { |
487
|
1
|
|
|
1
|
|
95
|
my ($kernel, $self) = @_[KERNEL, OBJECT]; |
488
|
1
|
|
|
|
|
7
|
$kernel->alias_set( $_[ARG0] ); |
489
|
|
|
|
|
|
|
} |
490
|
|
|
|
|
|
|
|
491
|
|
|
|
|
|
|
sub __emitter_disp_default { |
492
|
18
|
|
|
18
|
|
1530
|
my ($kernel, $self) = @_[KERNEL, OBJECT]; |
493
|
18
|
|
|
|
|
39
|
my ($event, $args) = @_[ARG0, ARG1]; |
494
|
|
|
|
|
|
|
|
495
|
18
|
100
|
|
|
|
54
|
if (ref $event eq 'CODE') { |
496
|
|
|
|
|
|
|
## Anonymous coderef callback. |
497
|
|
|
|
|
|
|
## Cute trick from dngor: |
498
|
|
|
|
|
|
|
## - Shove arguments back into @_ |
499
|
|
|
|
|
|
|
## (starting at ARG0 and replacing ARG0/ARG1) |
500
|
|
|
|
|
|
|
## - Set $_[STATE] to our coderef |
501
|
|
|
|
|
|
|
## (callback sub can retrieve itself via $_[STATE]) |
502
|
|
|
|
|
|
|
## - Replace current subroutine |
503
|
2
|
|
|
|
|
9
|
splice @_, ARG0, 2, @$args; |
504
|
2
|
|
|
|
|
3
|
$_[STATE] = $event; |
505
|
2
|
|
|
|
|
6
|
goto $event |
506
|
|
|
|
|
|
|
} else { |
507
|
16
|
|
|
|
|
50
|
$self->call( __emitter_real_default => $event, $args ); |
508
|
|
|
|
|
|
|
} |
509
|
|
|
|
|
|
|
} |
510
|
|
|
|
|
|
|
|
511
|
|
|
|
|
|
|
sub _emitter_default { |
512
|
16
|
|
|
16
|
|
2058
|
my ($kernel, $self) = @_[KERNEL, OBJECT]; |
513
|
16
|
|
|
|
|
35
|
my ($event, $args) = @_[ARG0, ARG1]; |
514
|
|
|
|
|
|
|
|
515
|
|
|
|
|
|
|
## Session received an unknown event. |
516
|
|
|
|
|
|
|
## Dispatch it to any appropriate P_$event handlers. |
517
|
|
|
|
|
|
|
|
518
|
16
|
100
|
66
|
|
|
159
|
$self->process( $event, @$args ) |
|
|
|
66
|
|
|
|
|
519
|
|
|
|
|
|
|
unless index($event, '_') == 0 |
520
|
|
|
|
|
|
|
or index($event, 'emitter_') == 0 |
521
|
|
|
|
|
|
|
and $event =~ /(?:started|stopped)$/; |
522
|
|
|
|
|
|
|
} |
523
|
|
|
|
|
|
|
|
524
|
|
|
|
|
|
|
sub __emitter_sig_shutdown { |
525
|
4
|
|
|
4
|
|
736
|
my ($kernel, $self) = @_[KERNEL, OBJECT]; |
526
|
4
|
|
|
|
|
12
|
$self->yield( shutdown_emitter => @_[ARG2 .. $#_] ) |
527
|
|
|
|
|
|
|
} |
528
|
|
|
|
|
|
|
|
529
|
|
|
|
|
|
|
sub __emitter_sigdie { |
530
|
0
|
|
|
0
|
|
0
|
my ($kernel, $self) = @_[KERNEL, OBJECT]; |
531
|
0
|
|
|
|
|
0
|
my $exh = $_[ARG1]; |
532
|
|
|
|
|
|
|
|
533
|
0
|
|
|
|
|
0
|
my $event = $exh->{event}; |
534
|
0
|
|
|
|
|
0
|
my $dest_id = $exh->{dest_session}->ID; |
535
|
0
|
|
|
|
|
0
|
my $errstr = $exh->{error_str}; |
536
|
|
|
|
|
|
|
|
537
|
0
|
|
|
|
|
0
|
warn |
538
|
|
|
|
|
|
|
"SIG_DIE: Event '$event' session '$dest_id'\n", |
539
|
|
|
|
|
|
|
" exception: $errstr\n"; |
540
|
|
|
|
|
|
|
|
541
|
0
|
|
|
|
|
0
|
$kernel->sig_handled; |
542
|
|
|
|
|
|
|
} |
543
|
|
|
|
|
|
|
|
544
|
|
|
|
|
|
|
sub __emitter_stop { |
545
|
|
|
|
|
|
|
## _stop handler |
546
|
4
|
|
|
4
|
|
1961
|
my ($kernel, $self) = @_[KERNEL, OBJECT]; |
547
|
|
|
|
|
|
|
|
548
|
4
|
|
|
|
|
22
|
$self->call('emitter_stopped'); |
549
|
|
|
|
|
|
|
} |
550
|
|
|
|
|
|
|
|
551
|
|
|
|
|
|
|
sub _shutdown_emitter { |
552
|
|
|
|
|
|
|
## Opposite of _start_emitter |
553
|
1
|
|
|
1
|
|
95
|
my $self = shift; |
554
|
|
|
|
|
|
|
|
555
|
1
|
|
|
|
|
4
|
$self->call( shutdown_emitter => @_ ); |
556
|
|
|
|
|
|
|
|
557
|
1
|
|
|
|
|
6
|
1 |
558
|
|
|
|
|
|
|
} |
559
|
|
|
|
|
|
|
|
560
|
|
|
|
|
|
|
sub __shutdown_emitter { |
561
|
6
|
|
|
6
|
|
484
|
my ($kernel, $self) = @_[KERNEL, OBJECT]; |
562
|
|
|
|
|
|
|
|
563
|
6
|
|
|
|
|
25
|
$kernel->alarm_remove_all; |
564
|
|
|
|
|
|
|
|
565
|
|
|
|
|
|
|
## Destroy plugin pipeline. |
566
|
6
|
|
|
|
|
381
|
$self->_pluggable_destroy; |
567
|
|
|
|
|
|
|
|
568
|
|
|
|
|
|
|
## Notify sessions. |
569
|
6
|
|
|
|
|
925
|
$self->emit( shutdown => @_[ARG0 .. $#_] ); |
570
|
|
|
|
|
|
|
|
571
|
|
|
|
|
|
|
## Drop sessions and we're spent. |
572
|
6
|
|
|
|
|
21
|
$self->call( unsubscribe => () ); |
573
|
6
|
|
|
|
|
19
|
$self->__emitter_drop_sessions; |
574
|
|
|
|
|
|
|
} |
575
|
|
|
|
|
|
|
|
576
|
|
|
|
|
|
|
|
577
|
|
|
|
|
|
|
## Handlers for listener sessions. |
578
|
|
|
|
|
|
|
sub __emitter_register { |
579
|
5
|
|
|
5
|
|
2390
|
my ($kernel, $self, $sender) = @_[KERNEL, OBJECT, SENDER]; |
580
|
5
|
|
|
|
|
17
|
my @events = @_[ARG0 .. $#_]; |
581
|
|
|
|
|
|
|
|
582
|
5
|
100
|
|
|
|
24
|
@events = 'all' unless @events; |
583
|
|
|
|
|
|
|
|
584
|
5
|
|
|
|
|
15
|
my $s_id = $sender->ID; |
585
|
|
|
|
|
|
|
|
586
|
|
|
|
|
|
|
## Add to our known sessions. |
587
|
5
|
|
|
|
|
28
|
$self->__reg_ses_id( $s_id ); |
588
|
|
|
|
|
|
|
|
589
|
5
|
|
|
|
|
310
|
for my $event (@events) { |
590
|
|
|
|
|
|
|
## Add session to registered event lists. |
591
|
5
|
|
|
|
|
20
|
$self->__emitter_reg_events->{$event}->{$s_id} = 1; |
592
|
|
|
|
|
|
|
|
593
|
|
|
|
|
|
|
## Make sure registered session hangs around |
594
|
|
|
|
|
|
|
## (until _unregister or shutdown) |
595
|
5
|
50
|
66
|
|
|
280
|
$kernel->refcount_increment( $s_id, E_TAG ) |
596
|
|
|
|
|
|
|
unless $s_id == $self->session_id |
597
|
|
|
|
|
|
|
or $self->__get_ses_refc($s_id); |
598
|
|
|
|
|
|
|
|
599
|
5
|
|
|
|
|
50
|
$self->__incr_ses_refc( $s_id ); |
600
|
|
|
|
|
|
|
} |
601
|
|
|
|
|
|
|
|
602
|
5
|
|
|
|
|
237
|
$kernel->post( $s_id => $self->event_prefix . 'registered', $self ) |
603
|
|
|
|
|
|
|
} |
604
|
|
|
|
|
|
|
|
605
|
|
|
|
|
|
|
sub __emitter_unregister { |
606
|
6
|
|
|
6
|
|
453
|
my ($kernel, $self, $sender) = @_[KERNEL, OBJECT, SENDER]; |
607
|
6
|
|
|
|
|
82
|
my @events = @_[ARG0 .. $#_]; |
608
|
|
|
|
|
|
|
|
609
|
|
|
|
|
|
|
## - An unsub without any arguments means "stop sending all events I |
610
|
|
|
|
|
|
|
## have subscribed to" |
611
|
|
|
|
|
|
|
## - An unsub for 'all' means "stop sending events I haven't asked for |
612
|
|
|
|
|
|
|
## by name" |
613
|
|
|
|
|
|
|
|
614
|
6
|
50
|
|
|
|
40
|
@events = $self->__emitter_reg_events->keys->all unless @events; |
615
|
|
|
|
|
|
|
|
616
|
6
|
|
|
|
|
485
|
my $s_id = $sender->ID; |
617
|
|
|
|
|
|
|
|
618
|
6
|
|
|
|
|
33
|
EV: for my $event (@events) { |
619
|
|
|
|
|
|
|
# intentional no Lowu, leave me for autoviv: |
620
|
6
|
100
|
|
|
|
20
|
unless (delete $self->__emitter_reg_events->{$event}->{$s_id}) { |
621
|
|
|
|
|
|
|
next EV |
622
|
5
|
|
|
|
|
336
|
} |
623
|
|
|
|
|
|
|
|
624
|
|
|
|
|
|
|
# Sessions left for this event? |
625
|
1
|
50
|
|
|
|
71
|
$self->__emitter_reg_events->delete($event) |
626
|
|
|
|
|
|
|
if $self->__emitter_reg_events->get($event)->is_empty; |
627
|
|
|
|
|
|
|
|
628
|
1
|
|
|
|
|
80
|
$self->__decr_ses_refc($s_id); |
629
|
|
|
|
|
|
|
|
630
|
1
|
50
|
|
|
|
114
|
unless ($self->__get_ses_refc($s_id)) { |
631
|
|
|
|
|
|
|
## No events left for this session. |
632
|
1
|
|
|
|
|
5
|
$self->__emitter_reg_sessions->delete($s_id); |
633
|
|
|
|
|
|
|
|
634
|
1
|
50
|
|
|
|
87
|
$kernel->refcount_decrement( $s_id, E_TAG ) |
635
|
|
|
|
|
|
|
unless $_[SESSION] == $sender; |
636
|
|
|
|
|
|
|
} |
637
|
|
|
|
|
|
|
|
638
|
|
|
|
|
|
|
} ## EV |
639
|
|
|
|
|
|
|
} |
640
|
|
|
|
|
|
|
|
641
|
|
|
|
|
|
|
1; |
642
|
|
|
|
|
|
|
|
643
|
|
|
|
|
|
|
|
644
|
|
|
|
|
|
|
=pod |
645
|
|
|
|
|
|
|
|
646
|
|
|
|
|
|
|
=for Pod::Coverage has_\S+ |
647
|
|
|
|
|
|
|
|
648
|
|
|
|
|
|
|
=head1 NAME |
649
|
|
|
|
|
|
|
|
650
|
|
|
|
|
|
|
MooX::Role::POE::Emitter - Pluggable POE event emitter role for cows |
651
|
|
|
|
|
|
|
|
652
|
|
|
|
|
|
|
=head1 SYNOPSIS |
653
|
|
|
|
|
|
|
|
654
|
|
|
|
|
|
|
## A POE::Session that can broadcast events to listeners: |
655
|
|
|
|
|
|
|
package My::EventEmitter; |
656
|
|
|
|
|
|
|
use POE; |
657
|
|
|
|
|
|
|
use Moo; |
658
|
|
|
|
|
|
|
with 'MooX::Role::POE::Emitter'; |
659
|
|
|
|
|
|
|
|
660
|
|
|
|
|
|
|
sub spawn { |
661
|
|
|
|
|
|
|
my ($self, %args) = @_; |
662
|
|
|
|
|
|
|
|
663
|
|
|
|
|
|
|
$self->set_object_states( |
664
|
|
|
|
|
|
|
[ |
665
|
|
|
|
|
|
|
$self => { |
666
|
|
|
|
|
|
|
## Add some extra handlers to our Emitter: |
667
|
|
|
|
|
|
|
'emitter_started' => '_emitter_started', |
668
|
|
|
|
|
|
|
'emitter_stopped' => '_emitter_stopped', |
669
|
|
|
|
|
|
|
}, |
670
|
|
|
|
|
|
|
|
671
|
|
|
|
|
|
|
## Include any object_states we had previously |
672
|
|
|
|
|
|
|
## (e.g. states added at construction time): |
673
|
|
|
|
|
|
|
( |
674
|
|
|
|
|
|
|
$self->has_object_states ? |
675
|
|
|
|
|
|
|
@{ $self->object_states } : () |
676
|
|
|
|
|
|
|
), |
677
|
|
|
|
|
|
|
|
678
|
|
|
|
|
|
|
## Maybe include from named arguments, for example: |
679
|
|
|
|
|
|
|
( |
680
|
|
|
|
|
|
|
ref $args{object_states} eq 'ARRAY' ? |
681
|
|
|
|
|
|
|
@{ $args{object_states} } : () |
682
|
|
|
|
|
|
|
), |
683
|
|
|
|
|
|
|
], |
684
|
|
|
|
|
|
|
); |
685
|
|
|
|
|
|
|
|
686
|
|
|
|
|
|
|
## Start our Emitter's POE::Session: |
687
|
|
|
|
|
|
|
$self->_start_emitter; |
688
|
|
|
|
|
|
|
} |
689
|
|
|
|
|
|
|
|
690
|
|
|
|
|
|
|
sub shutdown { |
691
|
|
|
|
|
|
|
my ($self) = @_; |
692
|
|
|
|
|
|
|
## .. do some cleanup, whatever .. |
693
|
|
|
|
|
|
|
$self->_shutdown_emitter; |
694
|
|
|
|
|
|
|
} |
695
|
|
|
|
|
|
|
|
696
|
|
|
|
|
|
|
sub _emitter_started { |
697
|
|
|
|
|
|
|
my ($kernel, $self) = @_[KERNEL, OBJECT]; |
698
|
|
|
|
|
|
|
## A POE state called when the emitter's session starts. |
699
|
|
|
|
|
|
|
## (Analogous to a normal '_start' handler) |
700
|
|
|
|
|
|
|
## Could load plugins, do initialization, etc. |
701
|
|
|
|
|
|
|
} |
702
|
|
|
|
|
|
|
|
703
|
|
|
|
|
|
|
sub _emitter_stopped { |
704
|
|
|
|
|
|
|
## Opposite of 'emitter_started' |
705
|
|
|
|
|
|
|
} |
706
|
|
|
|
|
|
|
|
707
|
|
|
|
|
|
|
sub do_something { |
708
|
|
|
|
|
|
|
my ($self, @things) = @_; |
709
|
|
|
|
|
|
|
# ... do some work ... |
710
|
|
|
|
|
|
|
# ... emit an event: |
711
|
|
|
|
|
|
|
$self->emit( did_stuff => @things ) |
712
|
|
|
|
|
|
|
} |
713
|
|
|
|
|
|
|
|
714
|
|
|
|
|
|
|
## A listening POE::Session: |
715
|
|
|
|
|
|
|
package My::Listener; |
716
|
|
|
|
|
|
|
use POE; |
717
|
|
|
|
|
|
|
|
718
|
|
|
|
|
|
|
sub spawn { |
719
|
|
|
|
|
|
|
# This spawn() takes an alias/session to subscribe to: |
720
|
|
|
|
|
|
|
my ($self, $alias_or_sessionID) = @_; |
721
|
|
|
|
|
|
|
|
722
|
|
|
|
|
|
|
POE::Session->create( |
723
|
|
|
|
|
|
|
## Set up a Session, etc |
724
|
|
|
|
|
|
|
object_states => [ |
725
|
|
|
|
|
|
|
$self => [ |
726
|
|
|
|
|
|
|
'emitted_did_stuff', |
727
|
|
|
|
|
|
|
# ... |
728
|
|
|
|
|
|
|
], |
729
|
|
|
|
|
|
|
], |
730
|
|
|
|
|
|
|
); |
731
|
|
|
|
|
|
|
|
732
|
|
|
|
|
|
|
## Subscribe to all events from $alias_or_sessionID: |
733
|
|
|
|
|
|
|
$poe_kernel->call( |
734
|
|
|
|
|
|
|
$alias_or_sessionID => subscribe => 'all' |
735
|
|
|
|
|
|
|
); |
736
|
|
|
|
|
|
|
} |
737
|
|
|
|
|
|
|
|
738
|
|
|
|
|
|
|
sub emitted_did_stuff { |
739
|
|
|
|
|
|
|
my ($kernel, $self) = @_[KERNEL, OBJECT]; |
740
|
|
|
|
|
|
|
## Received 'did_stuff' from Emitter |
741
|
|
|
|
|
|
|
my @things = @_[ARG0 .. $#_]; |
742
|
|
|
|
|
|
|
# ... |
743
|
|
|
|
|
|
|
} |
744
|
|
|
|
|
|
|
|
745
|
|
|
|
|
|
|
=head1 DESCRIPTION |
746
|
|
|
|
|
|
|
|
747
|
|
|
|
|
|
|
Consuming this L gives your class a L capable of |
748
|
|
|
|
|
|
|
processing events via loaded plugins and/or emitting them to registered |
749
|
|
|
|
|
|
|
"listener" sessions. |
750
|
|
|
|
|
|
|
|
751
|
|
|
|
|
|
|
It is derived from L by BINGOS, HINRIK, APOCAL |
752
|
|
|
|
|
|
|
et al, but with more cows ;-) and a few extra features (such as anonymous |
753
|
|
|
|
|
|
|
coderef callbacks; see L), as well as the |
754
|
|
|
|
|
|
|
faster plugin dispatch system that comes with L. |
755
|
|
|
|
|
|
|
|
756
|
|
|
|
|
|
|
The Emitter role consumes L, |
757
|
|
|
|
|
|
|
making your emitter pluggable (see the |
758
|
|
|
|
|
|
|
L documentation for plugin-related details). |
759
|
|
|
|
|
|
|
|
760
|
|
|
|
|
|
|
You do not need to create your own L; calling |
761
|
|
|
|
|
|
|
L will spawn one for you. |
762
|
|
|
|
|
|
|
|
763
|
|
|
|
|
|
|
You also get some useful sugar over POE event dispatch; see L. |
764
|
|
|
|
|
|
|
|
765
|
|
|
|
|
|
|
=head2 Creating an Emitter |
766
|
|
|
|
|
|
|
|
767
|
|
|
|
|
|
|
L contains an emitter that uses B methods to |
768
|
|
|
|
|
|
|
configure itself when C is called; attributes can, of course, |
769
|
|
|
|
|
|
|
be set when your Emitter is constructed: |
770
|
|
|
|
|
|
|
|
771
|
|
|
|
|
|
|
my $emitter = MyEmitter->new( |
772
|
|
|
|
|
|
|
alias => 'my_emitter', |
773
|
|
|
|
|
|
|
pluggable_type_prefixes => { |
774
|
|
|
|
|
|
|
NOTIFY => 'Notify', |
775
|
|
|
|
|
|
|
PROCESS => 'Proc', |
776
|
|
|
|
|
|
|
}, |
777
|
|
|
|
|
|
|
# . . . |
778
|
|
|
|
|
|
|
); |
779
|
|
|
|
|
|
|
|
780
|
|
|
|
|
|
|
=head3 Attributes |
781
|
|
|
|
|
|
|
|
782
|
|
|
|
|
|
|
Most of these can be altered via B methods at any time before |
783
|
|
|
|
|
|
|
L is called. Changing an emitter's configuration after it has |
784
|
|
|
|
|
|
|
been started may result in undesirable behavior ;-) |
785
|
|
|
|
|
|
|
|
786
|
|
|
|
|
|
|
Public attributes provide B prefixed predicates; e.g. |
787
|
|
|
|
|
|
|
B. |
788
|
|
|
|
|
|
|
|
789
|
|
|
|
|
|
|
=head4 alias |
790
|
|
|
|
|
|
|
|
791
|
|
|
|
|
|
|
B specifies the POE::Kernel alias used for our L; |
792
|
|
|
|
|
|
|
defaults to the stringified object. |
793
|
|
|
|
|
|
|
|
794
|
|
|
|
|
|
|
Set via B. If the emitter is running, a prefixed B |
795
|
|
|
|
|
|
|
event is emitted to notify listeners that need to know where to reach the emitter. |
796
|
|
|
|
|
|
|
|
797
|
|
|
|
|
|
|
=head4 event_prefix |
798
|
|
|
|
|
|
|
|
799
|
|
|
|
|
|
|
B is prepended to notification events before they are |
800
|
|
|
|
|
|
|
dispatched to listening sessions. It is also used for the plugin |
801
|
|
|
|
|
|
|
pipeline's internal events; see L |
802
|
|
|
|
|
|
|
for details. |
803
|
|
|
|
|
|
|
|
804
|
|
|
|
|
|
|
Defaults to C |
805
|
|
|
|
|
|
|
|
806
|
|
|
|
|
|
|
Set via B |
807
|
|
|
|
|
|
|
|
808
|
|
|
|
|
|
|
=head4 pluggable_type_prefixes |
809
|
|
|
|
|
|
|
|
810
|
|
|
|
|
|
|
B is a hash reference that can optionally be set |
811
|
|
|
|
|
|
|
to change the default L plugin handler prefixes for |
812
|
|
|
|
|
|
|
C and C (which default to C and C, respectively): |
813
|
|
|
|
|
|
|
|
814
|
|
|
|
|
|
|
my $emitter = $class->new( |
815
|
|
|
|
|
|
|
pluggable_type_prefixes => { |
816
|
|
|
|
|
|
|
PROCESS => 'P', |
817
|
|
|
|
|
|
|
NOTIFY => 'N', |
818
|
|
|
|
|
|
|
}, |
819
|
|
|
|
|
|
|
); |
820
|
|
|
|
|
|
|
|
821
|
|
|
|
|
|
|
Set via B |
822
|
|
|
|
|
|
|
|
823
|
|
|
|
|
|
|
=head4 object_states |
824
|
|
|
|
|
|
|
|
825
|
|
|
|
|
|
|
B is an array reference suitable for passing to |
826
|
|
|
|
|
|
|
L; the subclasses own handlers should be added to |
827
|
|
|
|
|
|
|
B prior to calling L. |
828
|
|
|
|
|
|
|
|
829
|
|
|
|
|
|
|
Set via B |
830
|
|
|
|
|
|
|
|
831
|
|
|
|
|
|
|
=head4 register_prefix |
832
|
|
|
|
|
|
|
|
833
|
|
|
|
|
|
|
B is prepended to 'register' and 'unregister' methods |
834
|
|
|
|
|
|
|
called on plugins at load time (see L). |
835
|
|
|
|
|
|
|
|
836
|
|
|
|
|
|
|
Defaults to I |
837
|
|
|
|
|
|
|
|
838
|
|
|
|
|
|
|
Set via B |
839
|
|
|
|
|
|
|
|
840
|
|
|
|
|
|
|
=head4 session_id |
841
|
|
|
|
|
|
|
|
842
|
|
|
|
|
|
|
B is our emitter's L ID, set when our Session is |
843
|
|
|
|
|
|
|
started via L"_start_emitter">. |
844
|
|
|
|
|
|
|
|
845
|
|
|
|
|
|
|
=head4 shutdown_signal |
846
|
|
|
|
|
|
|
|
847
|
|
|
|
|
|
|
B is the name of the L signal that will trigger a |
848
|
|
|
|
|
|
|
shutdown (used to shut down multiple Emitters). See L"Signals"> |
849
|
|
|
|
|
|
|
|
850
|
|
|
|
|
|
|
=head3 _start_emitter |
851
|
|
|
|
|
|
|
|
852
|
|
|
|
|
|
|
B<_start_emitter()> should be called on our object to spawn the actual |
853
|
|
|
|
|
|
|
L. It takes no arguments and should be called after the |
854
|
|
|
|
|
|
|
object has been configured. |
855
|
|
|
|
|
|
|
|
856
|
|
|
|
|
|
|
=head3 _shutdown_emitter |
857
|
|
|
|
|
|
|
|
858
|
|
|
|
|
|
|
B<_shutdown_emitter()> must be called to terminate the Emitter's |
859
|
|
|
|
|
|
|
L |
860
|
|
|
|
|
|
|
|
861
|
|
|
|
|
|
|
A 'shutdown' event will be emitted before sessions are dropped. |
862
|
|
|
|
|
|
|
|
863
|
|
|
|
|
|
|
=head2 Listening sessions |
864
|
|
|
|
|
|
|
|
865
|
|
|
|
|
|
|
=head3 Session event subscription |
866
|
|
|
|
|
|
|
|
867
|
|
|
|
|
|
|
An external L can subscribe to receive events via |
868
|
|
|
|
|
|
|
normal POE event dispatch by sending a C: |
869
|
|
|
|
|
|
|
|
870
|
|
|
|
|
|
|
$poe_kernel->post( $emitter->session_id, |
871
|
|
|
|
|
|
|
'subscribe', |
872
|
|
|
|
|
|
|
@events |
873
|
|
|
|
|
|
|
); |
874
|
|
|
|
|
|
|
|
875
|
|
|
|
|
|
|
Listening sessions are consumers; they cannot modify event arguments in |
876
|
|
|
|
|
|
|
any meaningful way, and will receive arguments as-normal (in @_[ARG0 .. |
877
|
|
|
|
|
|
|
$#_] like any other POE state). Plugins operate differently and receive |
878
|
|
|
|
|
|
|
references to arguments that can be modified -- see |
879
|
|
|
|
|
|
|
L for details. |
880
|
|
|
|
|
|
|
|
881
|
|
|
|
|
|
|
=head3 Session event unregistration |
882
|
|
|
|
|
|
|
|
883
|
|
|
|
|
|
|
An external Session can unregister subscribed events using the same syntax |
884
|
|
|
|
|
|
|
as above: |
885
|
|
|
|
|
|
|
|
886
|
|
|
|
|
|
|
$poe_kernel->post( $emitter->session_id, |
887
|
|
|
|
|
|
|
'unsubscribe', |
888
|
|
|
|
|
|
|
@events |
889
|
|
|
|
|
|
|
); |
890
|
|
|
|
|
|
|
|
891
|
|
|
|
|
|
|
If no events are specified, then any previously subscribed events are |
892
|
|
|
|
|
|
|
unregistered. |
893
|
|
|
|
|
|
|
|
894
|
|
|
|
|
|
|
Note that unsubscribing from 'all' does not carry the same behavior; that |
895
|
|
|
|
|
|
|
is to say, a subscriber can subscribe/unsubscribe for 'all' separately from |
896
|
|
|
|
|
|
|
some set of specifically named events. |
897
|
|
|
|
|
|
|
|
898
|
|
|
|
|
|
|
=head2 Receiving events |
899
|
|
|
|
|
|
|
|
900
|
|
|
|
|
|
|
=head3 Events delivered to listeners |
901
|
|
|
|
|
|
|
|
902
|
|
|
|
|
|
|
Events are delivered to subscribed listener sessions as normal POE events, |
903
|
|
|
|
|
|
|
with the configured L prepended and arguments available via |
904
|
|
|
|
|
|
|
C< @_[ARG0 .. $#_] > as normal. |
905
|
|
|
|
|
|
|
|
906
|
|
|
|
|
|
|
sub emitted_my_event { |
907
|
|
|
|
|
|
|
my ($kernel, $self) = @_[KERNEL, OBJECT]; |
908
|
|
|
|
|
|
|
my @args = @_[ARG0 .. $#_]; |
909
|
|
|
|
|
|
|
# . . . |
910
|
|
|
|
|
|
|
} |
911
|
|
|
|
|
|
|
|
912
|
|
|
|
|
|
|
See L"Session event subscription"> and L"emit"> |
913
|
|
|
|
|
|
|
|
914
|
|
|
|
|
|
|
=head3 Events delivered to this session |
915
|
|
|
|
|
|
|
|
916
|
|
|
|
|
|
|
The emitter's L provides a '_default' handler that |
917
|
|
|
|
|
|
|
redispatches unknown POE-delivered events to L |
918
|
|
|
|
|
|
|
(except for events prefixed with '_', which are reserved). |
919
|
|
|
|
|
|
|
|
920
|
|
|
|
|
|
|
You can change this behavior by overriding '_emitter_default' -- here's a |
921
|
|
|
|
|
|
|
direct adaption of the example from L: |
922
|
|
|
|
|
|
|
|
923
|
|
|
|
|
|
|
use Moo; |
924
|
|
|
|
|
|
|
use POE; |
925
|
|
|
|
|
|
|
with 'MooX::Role::POE::Emitter'; |
926
|
|
|
|
|
|
|
around '_emitter_default' => sub { |
927
|
|
|
|
|
|
|
my $orig = shift; |
928
|
|
|
|
|
|
|
my ($kernel, $self) = @_[KERNEL, OBJECT]; |
929
|
|
|
|
|
|
|
my ($event, $args) = @_[ARG0, ARG1]; |
930
|
|
|
|
|
|
|
|
931
|
|
|
|
|
|
|
## process(), then do something else, for example |
932
|
|
|
|
|
|
|
return if $self->process( $event, @$args ) == EAT_ALL; |
933
|
|
|
|
|
|
|
|
934
|
|
|
|
|
|
|
. . . |
935
|
|
|
|
|
|
|
}; |
936
|
|
|
|
|
|
|
|
937
|
|
|
|
|
|
|
(Note that due to internal redispatch $_[SENDER] will be the Emitter's |
938
|
|
|
|
|
|
|
Session.) |
939
|
|
|
|
|
|
|
|
940
|
|
|
|
|
|
|
=head2 EAT values |
941
|
|
|
|
|
|
|
|
942
|
|
|
|
|
|
|
L uses C constants to indicate event |
943
|
|
|
|
|
|
|
lifetime. |
944
|
|
|
|
|
|
|
|
945
|
|
|
|
|
|
|
If a plugin in the pipeline returns EAT_CLIENT or EAT_ALL, events |
946
|
|
|
|
|
|
|
are not dispatched to subscribed listening sessions; a dispatched NOTIFY |
947
|
|
|
|
|
|
|
event goes to your emitter's Session if it is subscribed to receive it, |
948
|
|
|
|
|
|
|
then to the plugin pipeline, and finally to other subscribed listener |
949
|
|
|
|
|
|
|
Sessions B a plugin returned EAT_CLIENT or EAT_ALL. |
950
|
|
|
|
|
|
|
|
951
|
|
|
|
|
|
|
See L"emit"> for more on dispatch behavior and event lifetime. See |
952
|
|
|
|
|
|
|
L for details regarding plugins. |
953
|
|
|
|
|
|
|
|
954
|
|
|
|
|
|
|
=head3 NOTIFY events |
955
|
|
|
|
|
|
|
|
956
|
|
|
|
|
|
|
B events are intended to be dispatched asynchronously to our own |
957
|
|
|
|
|
|
|
session, any loaded plugins in the pipeline, and subscribed listening |
958
|
|
|
|
|
|
|
sessions, respectively. |
959
|
|
|
|
|
|
|
|
960
|
|
|
|
|
|
|
See L. |
961
|
|
|
|
|
|
|
|
962
|
|
|
|
|
|
|
=head3 PROCESS events |
963
|
|
|
|
|
|
|
|
964
|
|
|
|
|
|
|
B events are intended to be processed by the plugin pipeline |
965
|
|
|
|
|
|
|
immediately; these are intended for message processing and similar |
966
|
|
|
|
|
|
|
synchronous action handled by plugins. |
967
|
|
|
|
|
|
|
|
968
|
|
|
|
|
|
|
Handlers for B events are prefixed with C |
969
|
|
|
|
|
|
|
|
970
|
|
|
|
|
|
|
See L. |
971
|
|
|
|
|
|
|
|
972
|
|
|
|
|
|
|
=head2 Sending events |
973
|
|
|
|
|
|
|
|
974
|
|
|
|
|
|
|
=head3 emit |
975
|
|
|
|
|
|
|
|
976
|
|
|
|
|
|
|
$self->emit( $event, @args ); |
977
|
|
|
|
|
|
|
|
978
|
|
|
|
|
|
|
B dispatches L"NOTIFY events"> -- these events are dispatched |
979
|
|
|
|
|
|
|
first to our own session (with L prepended), then any |
980
|
|
|
|
|
|
|
loaded plugins in the pipeline (with C prepended), then registered |
981
|
|
|
|
|
|
|
sessions (with L prepended): |
982
|
|
|
|
|
|
|
|
983
|
|
|
|
|
|
|
## With default event_prefix: |
984
|
|
|
|
|
|
|
$self->emit( 'my_event', @args ) |
985
|
|
|
|
|
|
|
# -> Dispatched to own session as 'emitted_my_event' |
986
|
|
|
|
|
|
|
# -> Dispatched to plugin pipeline as 'N_my_event' |
987
|
|
|
|
|
|
|
# -> Dispatched to registered sessions as 'emitted_my_event' |
988
|
|
|
|
|
|
|
# *unless* a plugin returned EAT_CLIENT or EAT_ALL |
989
|
|
|
|
|
|
|
|
990
|
|
|
|
|
|
|
See L"Receiving events">, L"EAT values"> |
991
|
|
|
|
|
|
|
|
992
|
|
|
|
|
|
|
=head3 emit_now |
993
|
|
|
|
|
|
|
|
994
|
|
|
|
|
|
|
$self->emit_now( $event, @args ); |
995
|
|
|
|
|
|
|
|
996
|
|
|
|
|
|
|
B synchronously dispatches L"NOTIFY events"> -- see |
997
|
|
|
|
|
|
|
L. |
998
|
|
|
|
|
|
|
|
999
|
|
|
|
|
|
|
=head3 process |
1000
|
|
|
|
|
|
|
|
1001
|
|
|
|
|
|
|
$self->process( $event, @args ); |
1002
|
|
|
|
|
|
|
|
1003
|
|
|
|
|
|
|
B calls registered plugin handlers for L"PROCESS events"> |
1004
|
|
|
|
|
|
|
immediately; these are B dispatched to listening sessions. |
1005
|
|
|
|
|
|
|
|
1006
|
|
|
|
|
|
|
Returns the same value as L. |
1007
|
|
|
|
|
|
|
|
1008
|
|
|
|
|
|
|
See L for details on pluggable |
1009
|
|
|
|
|
|
|
event dispatch. |
1010
|
|
|
|
|
|
|
|
1011
|
|
|
|
|
|
|
=head2 Methods |
1012
|
|
|
|
|
|
|
|
1013
|
|
|
|
|
|
|
These methods provide easy proxy mechanisms for issuing POE events and |
1014
|
|
|
|
|
|
|
managing timers within the context of the emitter's L. |
1015
|
|
|
|
|
|
|
|
1016
|
|
|
|
|
|
|
=head3 yield |
1017
|
|
|
|
|
|
|
|
1018
|
|
|
|
|
|
|
$self->yield( $poe_event, @args ); |
1019
|
|
|
|
|
|
|
|
1020
|
|
|
|
|
|
|
Provides an interface to L's yield/post() method, dispatching |
1021
|
|
|
|
|
|
|
POE events within the context of the emitter's session. |
1022
|
|
|
|
|
|
|
|
1023
|
|
|
|
|
|
|
The event can be either a named event/state dispatched to your Emitter's |
1024
|
|
|
|
|
|
|
L: |
1025
|
|
|
|
|
|
|
|
1026
|
|
|
|
|
|
|
$emitter->yield( 'some_event', @args ); |
1027
|
|
|
|
|
|
|
|
1028
|
|
|
|
|
|
|
... or an anonymous coderef, which is executed as if it were a named |
1029
|
|
|
|
|
|
|
POE state belonging to your Emitter: |
1030
|
|
|
|
|
|
|
|
1031
|
|
|
|
|
|
|
$emitter->yield( sub { |
1032
|
|
|
|
|
|
|
## $_[OBJECT] is the Emitter's object: |
1033
|
|
|
|
|
|
|
my ($kernel, $self) = @_[KERNEL, OBJECT]; |
1034
|
|
|
|
|
|
|
my @params = @_[ARG0 .. $#_]; |
1035
|
|
|
|
|
|
|
|
1036
|
|
|
|
|
|
|
## $_[STATE] is the current coderef |
1037
|
|
|
|
|
|
|
## Yield ourselves again, for example: |
1038
|
|
|
|
|
|
|
$self->yield( $_[STATE], @new_args ) |
1039
|
|
|
|
|
|
|
if $some_condition; |
1040
|
|
|
|
|
|
|
}, $some, $args ); |
1041
|
|
|
|
|
|
|
|
1042
|
|
|
|
|
|
|
Inside an anonymous coderef callback such as shown above, C<$_[OBJECT]> is |
1043
|
|
|
|
|
|
|
the Emitter's C<$self> object and C<$_[STATE]> contains the callback |
1044
|
|
|
|
|
|
|
coderef itself. |
1045
|
|
|
|
|
|
|
|
1046
|
|
|
|
|
|
|
=head3 call |
1047
|
|
|
|
|
|
|
|
1048
|
|
|
|
|
|
|
$self->call( $poe_event, @args ); |
1049
|
|
|
|
|
|
|
|
1050
|
|
|
|
|
|
|
The synchronous counterpart to L. |
1051
|
|
|
|
|
|
|
|
1052
|
|
|
|
|
|
|
=head3 timer |
1053
|
|
|
|
|
|
|
|
1054
|
|
|
|
|
|
|
my $alarm_id = $self->timer( |
1055
|
|
|
|
|
|
|
$delayed_seconds, |
1056
|
|
|
|
|
|
|
$event, |
1057
|
|
|
|
|
|
|
@args |
1058
|
|
|
|
|
|
|
); |
1059
|
|
|
|
|
|
|
|
1060
|
|
|
|
|
|
|
Set a timer in the context of the emitter's L. Returns the |
1061
|
|
|
|
|
|
|
POE alarm ID. |
1062
|
|
|
|
|
|
|
|
1063
|
|
|
|
|
|
|
The event can be either a named event/state or an anonymous coderef (see |
1064
|
|
|
|
|
|
|
L). |
1065
|
|
|
|
|
|
|
|
1066
|
|
|
|
|
|
|
A prefixed (L) 'timer_set' event is emitted when a timer is |
1067
|
|
|
|
|
|
|
set. Arguments are the alarm ID, the event name or coderef, the delay time, |
1068
|
|
|
|
|
|
|
and any event parameters, respectively. |
1069
|
|
|
|
|
|
|
|
1070
|
|
|
|
|
|
|
=head3 timer_del |
1071
|
|
|
|
|
|
|
|
1072
|
|
|
|
|
|
|
$self->timer_del( $alarm_id ); |
1073
|
|
|
|
|
|
|
|
1074
|
|
|
|
|
|
|
Clears a pending L. |
1075
|
|
|
|
|
|
|
|
1076
|
|
|
|
|
|
|
A prefixed (L) 'timer_deleted' event is emitted when a timer |
1077
|
|
|
|
|
|
|
is deleted. Arguments are the removed alarm ID, the event name or coderef, |
1078
|
|
|
|
|
|
|
and any event parameters, respectively. |
1079
|
|
|
|
|
|
|
|
1080
|
|
|
|
|
|
|
=head2 Signals |
1081
|
|
|
|
|
|
|
|
1082
|
|
|
|
|
|
|
=head3 Shutdown Signal |
1083
|
|
|
|
|
|
|
|
1084
|
|
|
|
|
|
|
The attribute L defines a POE signal that will trigger a |
1085
|
|
|
|
|
|
|
shutdown; it defaults to C: |
1086
|
|
|
|
|
|
|
|
1087
|
|
|
|
|
|
|
## Shutdown *all* emitters (with a default shutdown_signal()): |
1088
|
|
|
|
|
|
|
$poe_kernel->signal( $poe_kernel, 'SHUTDOWN_EMITTER' ); |
1089
|
|
|
|
|
|
|
|
1090
|
|
|
|
|
|
|
See L for details on L signals. |
1091
|
|
|
|
|
|
|
|
1092
|
|
|
|
|
|
|
=head1 SEE ALSO |
1093
|
|
|
|
|
|
|
|
1094
|
|
|
|
|
|
|
For details regarding POE, see L, L, L |
1095
|
|
|
|
|
|
|
|
1096
|
|
|
|
|
|
|
For details regarding Moo classes and Roles, see L, L, |
1097
|
|
|
|
|
|
|
L |
1098
|
|
|
|
|
|
|
|
1099
|
|
|
|
|
|
|
=head1 AUTHOR |
1100
|
|
|
|
|
|
|
|
1101
|
|
|
|
|
|
|
Jon Portnoy |
1102
|
|
|
|
|
|
|
|
1103
|
|
|
|
|
|
|
Written from the ground up, but conceptually derived from |
1104
|
|
|
|
|
|
|
L-0.06 copyright Hinrik Orn Sigurosson (HINRIK), |
1105
|
|
|
|
|
|
|
Chris Williams (BINGOS), APOCAL et al -- that will probably do you for |
1106
|
|
|
|
|
|
|
non-Moo(se) use cases; I needed something cow-like that worked with |
1107
|
|
|
|
|
|
|
L. |
1108
|
|
|
|
|
|
|
|
1109
|
|
|
|
|
|
|
Licensed under the same terms as Perl 5; see the license that came with your |
1110
|
|
|
|
|
|
|
Perl distribution for details. |
1111
|
|
|
|
|
|
|
|
1112
|
|
|
|
|
|
|
=cut |
1113
|
|
|
|
|
|
|
|