line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
# Copyright (c) 2011-17, Mitchell Cooper |
2
|
|
|
|
|
|
|
# |
3
|
|
|
|
|
|
|
# Evented::Object: a simple yet featureful base class event framework. |
4
|
|
|
|
|
|
|
# https://github.com/cooper/evented-object |
5
|
|
|
|
|
|
|
# |
6
|
|
|
|
|
|
|
package Evented::Object::Collection; # leave this package name the same FOREVER. |
7
|
|
|
|
|
|
|
|
8
|
13
|
|
|
13
|
|
96
|
use warnings; |
|
13
|
|
|
|
|
26
|
|
|
13
|
|
|
|
|
436
|
|
9
|
13
|
|
|
13
|
|
69
|
use strict; |
|
13
|
|
|
|
|
25
|
|
|
13
|
|
|
|
|
233
|
|
10
|
13
|
|
|
13
|
|
59
|
use utf8; |
|
13
|
|
|
|
|
26
|
|
|
13
|
|
|
|
|
77
|
|
11
|
13
|
|
|
13
|
|
388
|
use 5.010; |
|
13
|
|
|
|
|
43
|
|
12
|
|
|
|
|
|
|
|
13
|
13
|
|
|
13
|
|
110
|
use Scalar::Util qw(weaken blessed); |
|
13
|
|
|
|
|
50
|
|
|
13
|
|
|
|
|
820
|
|
14
|
13
|
|
|
13
|
|
109
|
use List::Util qw(min max); |
|
13
|
|
|
|
|
29
|
|
|
13
|
|
|
|
|
1513
|
|
15
|
13
|
|
|
13
|
|
88
|
use Carp qw(carp); |
|
13
|
|
|
|
|
28
|
|
|
13
|
|
|
|
|
23399
|
|
16
|
|
|
|
|
|
|
|
17
|
|
|
|
|
|
|
our $VERSION = '5.68'; |
18
|
|
|
|
|
|
|
our $events = $Evented::Object::events; |
19
|
|
|
|
|
|
|
our $props = $Evented::Object::props; |
20
|
|
|
|
|
|
|
|
21
|
|
|
|
|
|
|
my $dummy; |
22
|
|
|
|
|
|
|
my %boolopts = map { $_ => 1 } qw(safe return_check fail_continue); |
23
|
|
|
|
|
|
|
|
24
|
|
|
|
|
|
|
sub new { |
25
|
13
|
|
|
13
|
0
|
120
|
return bless { |
26
|
|
|
|
|
|
|
pending => {}, |
27
|
|
|
|
|
|
|
default_names => {}, |
28
|
|
|
|
|
|
|
names => {} |
29
|
|
|
|
|
|
|
}, shift; |
30
|
|
|
|
|
|
|
} |
31
|
|
|
|
|
|
|
|
32
|
|
|
|
|
|
|
sub push_callbacks { |
33
|
13
|
|
|
13
|
0
|
45
|
my ($collection, $callbacks, $names) = @_; |
34
|
13
|
|
|
|
|
72
|
my $pending = $collection->{pending}; |
35
|
13
|
|
|
|
|
39
|
my $my_names = $collection->{names}; |
36
|
|
|
|
|
|
|
|
37
|
|
|
|
|
|
|
# add to pending callbacks and callback name-to-ID mapping. |
38
|
13
|
|
|
|
|
78
|
@$pending { keys %$callbacks } = values %$callbacks; |
39
|
13
|
|
|
|
|
58
|
@$my_names{ keys %$names } = values %$names; |
40
|
|
|
|
|
|
|
|
41
|
|
|
|
|
|
|
# set default names for any callback names which were not found |
42
|
|
|
|
|
|
|
$collection->{default_names}{ $_->[2]{name} } ||= $_->[2]{id} |
43
|
13
|
|
33
|
|
|
255
|
for values %$callbacks; |
44
|
|
|
|
|
|
|
} |
45
|
|
|
|
|
|
|
|
46
|
|
|
|
|
|
|
# |
47
|
|
|
|
|
|
|
# Available fire options |
48
|
|
|
|
|
|
|
# ---------------------- |
49
|
|
|
|
|
|
|
# |
50
|
|
|
|
|
|
|
# safe calls all callbacks within eval blocks. |
51
|
|
|
|
|
|
|
# consumes no parameter. |
52
|
|
|
|
|
|
|
# |
53
|
|
|
|
|
|
|
# return_check causes the event to ->stop if any callback returns false |
54
|
|
|
|
|
|
|
# BUT IT WAITS until all have been fired. so if one returns false, |
55
|
|
|
|
|
|
|
# the rest will be called, but $fire->stopper will be true afterward. |
56
|
|
|
|
|
|
|
# consumes no parameter. |
57
|
|
|
|
|
|
|
# |
58
|
|
|
|
|
|
|
# caller specify an alternate [caller 1] value, mostly for internal use. |
59
|
|
|
|
|
|
|
# parameter = caller(1) info wrapped in an array reference. |
60
|
|
|
|
|
|
|
# |
61
|
|
|
|
|
|
|
# fail_continue if 'safe' is enabled and a callback raises an exception, it will |
62
|
|
|
|
|
|
|
# by default ->stop the fire. this option tells it to continue instead. |
63
|
|
|
|
|
|
|
# consumes no parameter. |
64
|
|
|
|
|
|
|
# |
65
|
|
|
|
|
|
|
# data some data to fire with the event. esp. good for things that might be |
66
|
|
|
|
|
|
|
# useful at times but not accessed frequently enough to be an argument. |
67
|
|
|
|
|
|
|
# parameter = the data. |
68
|
|
|
|
|
|
|
# |
69
|
|
|
|
|
|
|
sub fire { |
70
|
13
|
|
|
13
|
1
|
49
|
my ($collection, @options) = @_; |
71
|
|
|
|
|
|
|
|
72
|
|
|
|
|
|
|
# handle options. |
73
|
13
|
|
|
|
|
115
|
my ($caller, $data) = $collection->{caller}; |
74
|
13
|
|
|
|
|
74
|
while (@options) { |
75
|
13
|
|
|
|
|
39
|
my $opt = shift @options; |
76
|
|
|
|
|
|
|
|
77
|
13
|
100
|
|
|
|
50
|
if ($opt eq 'caller') { $caller = shift @options } # custom caller |
|
11
|
|
|
|
|
25
|
|
78
|
13
|
100
|
|
|
|
83
|
if ($opt eq 'data') { $data = shift @options } # fire data |
|
2
|
|
|
|
|
10
|
|
79
|
|
|
|
|
|
|
|
80
|
|
|
|
|
|
|
# boolean option. |
81
|
13
|
50
|
|
|
|
87
|
$collection->{$opt} = 1 if $boolopts{$opt}; |
82
|
|
|
|
|
|
|
|
83
|
|
|
|
|
|
|
} |
84
|
|
|
|
|
|
|
|
85
|
|
|
|
|
|
|
# create fire object. |
86
|
13
|
|
100
|
|
|
198
|
my $fire = Evented::Object::EventFire->new( |
87
|
|
|
|
|
|
|
caller => $caller ||= [caller 1], # $fire->caller |
88
|
|
|
|
|
|
|
data => $data, # $fire->data |
89
|
|
|
|
|
|
|
collection => $collection |
90
|
|
|
|
|
|
|
); |
91
|
|
|
|
|
|
|
|
92
|
|
|
|
|
|
|
# if it hasn't been sorted, do so now. |
93
|
13
|
50
|
|
|
|
114
|
$collection->sort if not $collection->{sorted}; |
94
|
13
|
50
|
|
|
|
64
|
my $callbacks = $collection->{sorted} or return $fire; |
95
|
|
|
|
|
|
|
|
96
|
|
|
|
|
|
|
# if return_check is enabled, add a callback to be fired last that will |
97
|
|
|
|
|
|
|
# check the return values. this is basically hackery using a dummy object. |
98
|
13
|
50
|
|
|
|
59
|
if ($collection->{return_check}) { |
99
|
0
|
|
|
|
|
0
|
my $cb = { |
100
|
|
|
|
|
|
|
name => 'eventedObject.returnCheck', |
101
|
|
|
|
|
|
|
caller => $caller, |
102
|
|
|
|
|
|
|
code => \&_return_check |
103
|
|
|
|
|
|
|
}; |
104
|
0
|
|
0
|
|
|
0
|
my $group = [ |
105
|
|
|
|
|
|
|
$dummy ||= Evented::Object->new, |
106
|
|
|
|
|
|
|
'returnCheck', |
107
|
|
|
|
|
|
|
[], |
108
|
|
|
|
|
|
|
"$dummy/returnCheck" |
109
|
|
|
|
|
|
|
]; |
110
|
0
|
|
|
|
|
0
|
push @$callbacks, [ |
111
|
|
|
|
|
|
|
-inf, # [0] $priority |
112
|
|
|
|
|
|
|
$group, # [1] $group |
113
|
|
|
|
|
|
|
$cb # [2] $cb |
114
|
|
|
|
|
|
|
]; |
115
|
0
|
|
|
|
|
0
|
$cb->{id} = "$$group[3]/$$cb{name}"; |
116
|
0
|
|
|
|
|
0
|
$collection->{pending}{ $cb->{id} } = $cb; |
117
|
|
|
|
|
|
|
} |
118
|
|
|
|
|
|
|
|
119
|
|
|
|
|
|
|
# call them. |
120
|
13
|
|
|
|
|
70
|
return $collection->_call_callbacks($fire); |
121
|
|
|
|
|
|
|
|
122
|
|
|
|
|
|
|
} |
123
|
|
|
|
|
|
|
|
124
|
|
|
|
|
|
|
# sorts the callbacks, trying its best to listen to before and after. |
125
|
|
|
|
|
|
|
sub sort : method { |
126
|
13
|
|
|
13
|
1
|
101
|
my $collection = shift; |
127
|
13
|
50
|
|
|
|
76
|
return unless $collection->{pending}; |
128
|
13
|
|
|
|
|
31
|
my %callbacks = %{ $collection->{pending} }; |
|
13
|
|
|
|
|
83
|
|
129
|
13
|
|
|
|
|
43
|
my (@sorted, %done, %waited); |
130
|
|
|
|
|
|
|
|
131
|
|
|
|
|
|
|
# iterate over the callback sets, |
132
|
|
|
|
|
|
|
# which are array refs of [ priority, group, cb ] |
133
|
13
|
|
|
|
|
44
|
my @callbacks = values %callbacks; |
134
|
13
|
|
|
|
|
69
|
while (my $set = shift @callbacks) { |
135
|
36
|
|
|
|
|
89
|
my ($priority, $group, $cb) = @$set; |
136
|
36
|
|
|
|
|
69
|
my $cb_id = $cb->{id}; |
137
|
36
|
|
|
|
|
62
|
my $group_id = $group->[3]; |
138
|
|
|
|
|
|
|
|
139
|
36
|
50
|
|
|
|
102
|
next if $done{$cb_id}; |
140
|
|
|
|
|
|
|
|
141
|
|
|
|
|
|
|
# a real priority exists already. |
142
|
36
|
100
|
66
|
|
|
169
|
if (defined $priority && $priority ne 'nan') { |
143
|
22
|
|
|
|
|
49
|
push @sorted, $set; |
144
|
22
|
|
|
|
|
45
|
$done{$cb_id} = 1; |
145
|
22
|
|
|
|
|
74
|
next; |
146
|
|
|
|
|
|
|
} |
147
|
|
|
|
|
|
|
|
148
|
|
|
|
|
|
|
|
149
|
|
|
|
|
|
|
# TODO: if before and afters cannot be resolved, the callback dependencies |
150
|
|
|
|
|
|
|
# are currently skipped. maybe there should be a way to specify that a callback |
151
|
|
|
|
|
|
|
# dependency is REQUIRED, meaning to skip the callback entirely if it cannot |
152
|
|
|
|
|
|
|
# be done. or maybe something more sophisticated that can prioritize the |
153
|
|
|
|
|
|
|
# befores and afters in this way. for now though, we will just try to not |
154
|
|
|
|
|
|
|
# specify impossible befores and afters. |
155
|
|
|
|
|
|
|
|
156
|
|
|
|
|
|
|
|
157
|
|
|
|
|
|
|
|
158
|
|
|
|
|
|
|
# callback priority determination can be postponed until another's |
159
|
|
|
|
|
|
|
# priority is determined. the maxmium number of times one particular |
160
|
|
|
|
|
|
|
# callback can be postponed is the number of total callbacks. |
161
|
14
|
|
|
|
|
28
|
my $wait_max = keys %callbacks; |
162
|
|
|
|
|
|
|
|
163
|
14
|
|
|
|
|
36
|
my $name_to_id = $collection->_group_names($group_id); |
164
|
|
|
|
|
|
|
my $get_befores_afters = sub { |
165
|
24
|
|
|
24
|
|
38
|
my ($key, @results) = shift; |
166
|
24
|
100
|
|
|
|
63
|
my $list = $cb->{$key} or return; |
167
|
18
|
100
|
|
|
|
50
|
$list = [ $list ] if ref $list ne 'ARRAY'; |
168
|
|
|
|
|
|
|
|
169
|
|
|
|
|
|
|
# for each callback name, find its priority. |
170
|
18
|
|
|
|
|
32
|
foreach my $their_name (@$list) { |
171
|
|
|
|
|
|
|
|
172
|
|
|
|
|
|
|
# map callback name to id, id to cbref, and cbref to priority. |
173
|
28
|
100
|
|
|
|
63
|
my $their_id = $name_to_id->{$their_name} or next; |
174
|
16
|
50
|
|
|
|
50
|
my $their_cb = $callbacks{$their_id} or next; |
175
|
16
|
|
|
|
|
32
|
my $their_p = $their_cb->[0]; |
176
|
|
|
|
|
|
|
|
177
|
|
|
|
|
|
|
# if their priority is nan, |
178
|
|
|
|
|
|
|
# we have to wait until it is determined. |
179
|
16
|
100
|
|
|
|
30
|
if ($their_p eq 'nan') { |
180
|
9
|
|
|
|
|
25
|
my $wait_key = "$cb_id $their_id"; |
181
|
|
|
|
|
|
|
push @callbacks, $set |
182
|
9
|
100
|
|
|
|
42
|
unless $waited{$key}++ > $wait_max; |
183
|
9
|
|
|
|
|
23
|
return 1; |
184
|
|
|
|
|
|
|
} |
185
|
|
|
|
|
|
|
|
186
|
7
|
|
|
|
|
23
|
push @results, $their_p; |
187
|
|
|
|
|
|
|
} |
188
|
|
|
|
|
|
|
|
189
|
9
|
|
|
|
|
30
|
return (undef, @results); |
190
|
14
|
|
|
|
|
65
|
}; |
191
|
|
|
|
|
|
|
|
192
|
14
|
100
|
|
|
|
33
|
my ($next, @befores) = $get_befores_afters->('before'); next if $next; |
|
14
|
|
|
|
|
55
|
|
193
|
10
|
100
|
|
|
|
19
|
($next, my @afters ) = $get_befores_afters->('after'); next if $next; |
|
10
|
|
|
|
|
50
|
|
194
|
|
|
|
|
|
|
|
195
|
|
|
|
|
|
|
# figure the ideal priority. |
196
|
5
|
50
|
66
|
|
|
34
|
if (@befores && @afters) { |
|
|
100
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
197
|
0
|
|
|
|
|
0
|
my $a_refpoint = min @afters; |
198
|
0
|
|
|
|
|
0
|
my $b_refpoint = max @befores; |
199
|
0
|
|
|
|
|
0
|
$priority = ($a_refpoint + $b_refpoint) / 2; |
200
|
|
|
|
|
|
|
} |
201
|
|
|
|
|
|
|
|
202
|
|
|
|
|
|
|
# only before. just have 1 higher priority. |
203
|
|
|
|
|
|
|
elsif (@befores) { |
204
|
3
|
|
|
|
|
33
|
my $refpoint = max @befores; |
205
|
3
|
|
|
|
|
10
|
$priority = ++$refpoint; |
206
|
|
|
|
|
|
|
} |
207
|
|
|
|
|
|
|
|
208
|
|
|
|
|
|
|
# only after. |
209
|
|
|
|
|
|
|
elsif (@afters) { |
210
|
2
|
|
|
|
|
15
|
my $refpoint = min @afters; |
211
|
2
|
|
|
|
|
7
|
$priority = --$refpoint; |
212
|
|
|
|
|
|
|
} |
213
|
|
|
|
|
|
|
|
214
|
5
|
50
|
|
|
|
36
|
$priority = 0 if $priority eq 'nan'; |
215
|
|
|
|
|
|
|
|
216
|
|
|
|
|
|
|
# done with this callback. |
217
|
5
|
|
|
|
|
12
|
$set->[0] = $priority; |
218
|
5
|
|
|
|
|
11
|
push @sorted, $set; |
219
|
5
|
|
|
|
|
47
|
$done{$cb_id} = 1; |
220
|
|
|
|
|
|
|
|
221
|
|
|
|
|
|
|
} |
222
|
|
|
|
|
|
|
|
223
|
|
|
|
|
|
|
# the final sort by numerical priority. |
224
|
13
|
|
|
|
|
90
|
$collection->{sorted} = [ sort { $b->[0] <=> $a->[0] } @sorted ]; |
|
23
|
|
|
|
|
85
|
|
225
|
|
|
|
|
|
|
|
226
|
|
|
|
|
|
|
} |
227
|
|
|
|
|
|
|
|
228
|
|
|
|
|
|
|
# Nov. 22, 2013 revision |
229
|
|
|
|
|
|
|
# ---------------------- |
230
|
|
|
|
|
|
|
# |
231
|
|
|
|
|
|
|
# collection a set of callbacks about to be fired. they might belong to multiple |
232
|
|
|
|
|
|
|
# objects or maybe even multiple events. they can each have their own |
233
|
|
|
|
|
|
|
# arguments, and they all have their own options, code references, etc. |
234
|
|
|
|
|
|
|
# |
235
|
|
|
|
|
|
|
# group represents the group to which a callback belongs. a group consists of |
236
|
|
|
|
|
|
|
# the associated evented object, event name, and arguments. |
237
|
|
|
|
|
|
|
# |
238
|
|
|
|
|
|
|
# This revision eliminates all of these nested structures by reworking the way |
239
|
|
|
|
|
|
|
# a callback collection works. A collection should be an array of callbacks. |
240
|
|
|
|
|
|
|
# This array, unlike before, will contain an additional element: an array |
241
|
|
|
|
|
|
|
# reference representing the "group." |
242
|
|
|
|
|
|
|
# |
243
|
|
|
|
|
|
|
# @collection = ( |
244
|
|
|
|
|
|
|
# [ $priority, $group, $cb ], |
245
|
|
|
|
|
|
|
# [ $priority, $group, $cb ], |
246
|
|
|
|
|
|
|
# ... |
247
|
|
|
|
|
|
|
# ) |
248
|
|
|
|
|
|
|
# |
249
|
|
|
|
|
|
|
# $group = $cb = |
250
|
|
|
|
|
|
|
# [ $eo, $event_name, $args, $id ] { code, caller, %opts } |
251
|
|
|
|
|
|
|
# |
252
|
|
|
|
|
|
|
# This format has several major advantages over the former one. Specifically, |
253
|
|
|
|
|
|
|
# it makes it very simple to determine which callbacks will be called in the |
254
|
|
|
|
|
|
|
# future, which ones have been called already, how many are left, etc. |
255
|
|
|
|
|
|
|
# |
256
|
|
|
|
|
|
|
|
257
|
|
|
|
|
|
|
# call the passed callback priority sets. |
258
|
|
|
|
|
|
|
sub _call_callbacks { |
259
|
13
|
|
|
13
|
|
43
|
my ($collection, $fire) = @_; |
260
|
13
|
|
|
|
|
94
|
my $ef_props = $fire->{$props}; |
261
|
|
|
|
|
|
|
|
262
|
|
|
|
|
|
|
# store the collection. |
263
|
13
|
50
|
|
|
|
75
|
my $remaining = $collection->{sorted} or return; |
264
|
13
|
|
|
|
|
37
|
$ef_props->{collection} = $collection; |
265
|
|
|
|
|
|
|
|
266
|
|
|
|
|
|
|
# call each callback. |
267
|
13
|
|
|
|
|
49
|
while (my $entry = shift @$remaining) { |
268
|
26
|
|
|
|
|
72
|
my ($priority, $group, $cb) = @$entry; |
269
|
26
|
|
|
|
|
64
|
my ($eo, $event_name, $args, $group_id) = @$group; |
270
|
|
|
|
|
|
|
|
271
|
|
|
|
|
|
|
# sanity check! |
272
|
26
|
50
|
33
|
|
|
218
|
blessed $eo && $eo->isa('Evented::Object') or return; |
273
|
|
|
|
|
|
|
|
274
|
|
|
|
|
|
|
# callback name-to-ID mapping is specific to each group. |
275
|
26
|
|
|
|
|
116
|
$ef_props->{callback_ids} = $collection->_group_names($group_id); |
276
|
|
|
|
|
|
|
|
277
|
|
|
|
|
|
|
# increment the callback counter. |
278
|
26
|
|
|
|
|
48
|
$ef_props->{callback_i}++; |
279
|
|
|
|
|
|
|
|
280
|
|
|
|
|
|
|
# set the evented object of this callback. |
281
|
|
|
|
|
|
|
# set the event name of this callback. |
282
|
26
|
|
|
|
|
55
|
$ef_props->{object} = $eo; weaken($ef_props->{object}); # $fire->object |
|
26
|
|
|
|
|
115
|
|
283
|
26
|
|
|
|
|
50
|
$ef_props->{name} = $event_name; # $fire->event_name |
284
|
|
|
|
|
|
|
|
285
|
|
|
|
|
|
|
# store identifiers. |
286
|
26
|
|
|
|
|
61
|
$ef_props->{callback_id} = my $cb_id = $cb->{id}; |
287
|
26
|
|
|
|
|
60
|
$ef_props->{group_id} = $group_id; |
288
|
|
|
|
|
|
|
|
289
|
|
|
|
|
|
|
# create info about the call. |
290
|
26
|
|
|
|
|
52
|
$ef_props->{callback_name} = $cb->{name}; # $fire->callback_name |
291
|
26
|
|
|
|
|
53
|
$ef_props->{callback_priority} = $priority; # $fire->callback_priority |
292
|
26
|
100
|
|
|
|
66
|
$ef_props->{callback_data} = $cb->{data} if defined $cb->{data}; # $fire->callback_data |
293
|
|
|
|
|
|
|
|
294
|
|
|
|
|
|
|
# this callback has been called already. |
295
|
26
|
50
|
|
|
|
110
|
next if $ef_props->{called}{$cb_id}; |
296
|
|
|
|
|
|
|
|
297
|
|
|
|
|
|
|
# this callback has probably been cancelled. |
298
|
26
|
100
|
|
|
|
92
|
next unless $collection->{pending}{$cb_id}; |
299
|
|
|
|
|
|
|
|
300
|
|
|
|
|
|
|
|
301
|
|
|
|
|
|
|
# determine arguments. |
302
|
|
|
|
|
|
|
# |
303
|
|
|
|
|
|
|
# no compat <3.0: used to always have obj unless specified with no_obj or later no_fire_obj. |
304
|
|
|
|
|
|
|
# no compat <2.9: with_obj -> eo_obj |
305
|
|
|
|
|
|
|
# compat: all later version had a variety of with_obj-like-options below. |
306
|
|
|
|
|
|
|
# |
307
|
25
|
|
|
|
|
60
|
my @cb_args = @$args; |
308
|
25
|
|
|
|
|
90
|
my $include_obj = grep $cb->{$_}, qw(with_eo with_obj with_evented_obj eo_obj); |
309
|
25
|
50
|
|
|
|
119
|
unshift @cb_args, $fire unless $cb->{no_fire_obj}; |
310
|
25
|
50
|
|
|
|
66
|
unshift @cb_args, $eo if $include_obj; |
311
|
|
|
|
|
|
|
|
312
|
|
|
|
|
|
|
# set return values. |
313
|
|
|
|
|
|
|
$ef_props->{last_return} = # set last return value. |
314
|
|
|
|
|
|
|
$ef_props->{return}{$cb_id} = # set this callback's return value. |
315
|
|
|
|
|
|
|
|
316
|
|
|
|
|
|
|
# call the callback with proper arguments. |
317
|
0
|
|
|
|
|
0
|
$collection->{safe} ? eval { $cb->{code}(@cb_args) } |
318
|
25
|
50
|
|
|
|
122
|
: $cb->{code}(@cb_args); |
319
|
|
|
|
|
|
|
|
320
|
|
|
|
|
|
|
# set $fire->called($cb) true, and set $fire->last to the callback's name. |
321
|
25
|
|
|
|
|
4321
|
$ef_props->{called}{$cb_id} = 1; |
322
|
25
|
|
|
|
|
63
|
$ef_props->{last_callback} = $cb->{name}; |
323
|
|
|
|
|
|
|
|
324
|
|
|
|
|
|
|
# no longer pending. |
325
|
25
|
|
|
|
|
55
|
delete $collection->{pending}{$cb_id}; |
326
|
|
|
|
|
|
|
|
327
|
|
|
|
|
|
|
# stop if eval failed. |
328
|
25
|
50
|
33
|
|
|
96
|
if ($collection->{safe} and my $err = $@) { |
329
|
0
|
|
|
|
|
0
|
chomp $err; |
330
|
|
|
|
|
|
|
$ef_props->{error}{$cb_id} = # not used for anything |
331
|
0
|
|
|
|
|
0
|
$ef_props->{exception} = $err; |
332
|
0
|
0
|
|
|
|
0
|
$fire->stop($err) unless $collection->{fail_continue}; |
333
|
|
|
|
|
|
|
} |
334
|
|
|
|
|
|
|
|
335
|
|
|
|
|
|
|
# if stop is true, $fire->stop was called. stop the iteration. |
336
|
25
|
100
|
|
|
|
157
|
if ($ef_props->{stop}) { |
337
|
1
|
|
|
|
|
4
|
$ef_props->{stopper} = $cb->{name}; # set $fire->stopper. |
338
|
1
|
|
|
|
|
3
|
last; |
339
|
|
|
|
|
|
|
} |
340
|
|
|
|
|
|
|
|
341
|
|
|
|
|
|
|
} |
342
|
|
|
|
|
|
|
|
343
|
|
|
|
|
|
|
# dispose of things that are no longer needed. |
344
|
13
|
|
|
|
|
81
|
delete @$ef_props{ qw( |
345
|
|
|
|
|
|
|
callback_name callback_priority |
346
|
|
|
|
|
|
|
callback_data callback_i object |
347
|
|
|
|
|
|
|
collection |
348
|
|
|
|
|
|
|
) }; |
349
|
|
|
|
|
|
|
|
350
|
|
|
|
|
|
|
# return the event object. |
351
|
13
|
|
|
|
|
31
|
$ef_props->{complete} = 1; |
352
|
13
|
|
|
|
|
142
|
return $fire; |
353
|
|
|
|
|
|
|
|
354
|
|
|
|
|
|
|
} |
355
|
|
|
|
|
|
|
|
356
|
|
|
|
|
|
|
sub _group_names { |
357
|
40
|
|
|
40
|
|
92
|
my ($collection, $group_id) = @_; |
358
|
40
|
|
66
|
|
|
147
|
return $collection->{group_names}{$group_id} ||= do { |
359
|
14
|
|
50
|
|
|
63
|
my $names_from_group = $collection->{names}{$group_id} || {}; |
360
|
14
|
|
|
|
|
35
|
my $default_names = $collection->{default_names}; |
361
|
14
|
|
|
|
|
106
|
my %names = (%$default_names, %$names_from_group); |
362
|
14
|
|
|
|
|
86
|
\%names |
363
|
|
|
|
|
|
|
} |
364
|
|
|
|
|
|
|
} |
365
|
|
|
|
|
|
|
|
366
|
|
|
|
|
|
|
sub _return_check { |
367
|
0
|
|
|
0
|
|
|
my $fire = shift; |
368
|
0
|
0
|
|
|
|
|
my %returns = %{ $fire->{$props}{return} || {} }; |
|
0
|
|
|
|
|
|
|
369
|
0
|
|
|
|
|
|
foreach my $cb_id (keys %returns) { |
370
|
0
|
0
|
|
|
|
|
next if $returns{$cb_id}; |
371
|
0
|
|
|
|
|
|
return $fire->stop("$cb_id returned false with return_check enabled"); |
372
|
|
|
|
|
|
|
} |
373
|
0
|
|
|
|
|
|
return 1; |
374
|
|
|
|
|
|
|
} |
375
|
|
|
|
|
|
|
|
376
|
|
|
|
|
|
|
1; |
377
|
|
|
|
|
|
|
|
378
|
|
|
|
|
|
|
=head1 NAME |
379
|
|
|
|
|
|
|
|
380
|
|
|
|
|
|
|
B - represents a group of pending |
381
|
|
|
|
|
|
|
L callbacks. |
382
|
|
|
|
|
|
|
|
383
|
|
|
|
|
|
|
=head1 DESCRIPTION |
384
|
|
|
|
|
|
|
|
385
|
|
|
|
|
|
|
L are returned by the evented object 'prepare' methods. They |
386
|
|
|
|
|
|
|
represent a group of callbacks that are about to be fired. Using collections |
387
|
|
|
|
|
|
|
allows you to prepare a fire ahead of time before executing it. You can also |
388
|
|
|
|
|
|
|
fire events with special options this way. |
389
|
|
|
|
|
|
|
|
390
|
|
|
|
|
|
|
=head1 METHODS |
391
|
|
|
|
|
|
|
|
392
|
|
|
|
|
|
|
|
393
|
|
|
|
|
|
|
=head2 $col->fire(@options) |
394
|
|
|
|
|
|
|
|
395
|
|
|
|
|
|
|
Fires the pending callbacks with the specified options, if any. If the callbacks |
396
|
|
|
|
|
|
|
have not yet been sorted, they are sorted before the event is fired. |
397
|
|
|
|
|
|
|
|
398
|
|
|
|
|
|
|
$eo->prepare(some_event => @arguments)->fire('safe'); |
399
|
|
|
|
|
|
|
|
400
|
|
|
|
|
|
|
B |
401
|
|
|
|
|
|
|
|
402
|
|
|
|
|
|
|
=over |
403
|
|
|
|
|
|
|
|
404
|
|
|
|
|
|
|
=item * |
405
|
|
|
|
|
|
|
|
406
|
|
|
|
|
|
|
B<@options> - I, a mixture of boolean and key:value options for the |
407
|
|
|
|
|
|
|
event fire. |
408
|
|
|
|
|
|
|
|
409
|
|
|
|
|
|
|
=back |
410
|
|
|
|
|
|
|
|
411
|
|
|
|
|
|
|
B<@options> - fire options |
412
|
|
|
|
|
|
|
|
413
|
|
|
|
|
|
|
=over |
414
|
|
|
|
|
|
|
|
415
|
|
|
|
|
|
|
=item * |
416
|
|
|
|
|
|
|
|
417
|
|
|
|
|
|
|
B - I, use an alternate C<[caller 1]> value for the event |
418
|
|
|
|
|
|
|
fire. This is typically only used internally. |
419
|
|
|
|
|
|
|
|
420
|
|
|
|
|
|
|
=item * |
421
|
|
|
|
|
|
|
|
422
|
|
|
|
|
|
|
B - I, if true, the event will yield that it was stopped |
423
|
|
|
|
|
|
|
if any of the callbacks return a false value. Note however that if one callbacks |
424
|
|
|
|
|
|
|
returns false, the rest will still be called. The fire object will only yield |
425
|
|
|
|
|
|
|
stopped status after all callbacks have been called and any number of them |
426
|
|
|
|
|
|
|
returned false. |
427
|
|
|
|
|
|
|
|
428
|
|
|
|
|
|
|
=item * |
429
|
|
|
|
|
|
|
|
430
|
|
|
|
|
|
|
B - I, wrap all callback calls in C for safety. if any of |
431
|
|
|
|
|
|
|
them fail, the event will be stopped at that point with the error. |
432
|
|
|
|
|
|
|
|
433
|
|
|
|
|
|
|
=item * |
434
|
|
|
|
|
|
|
|
435
|
|
|
|
|
|
|
B - I, if C above is enabled, this tells the fire |
436
|
|
|
|
|
|
|
to continue even if one of the callbacks fails. This could be dangerous if any |
437
|
|
|
|
|
|
|
of the callbacks expected a previous callback to be done when it actually |
438
|
|
|
|
|
|
|
failed. |
439
|
|
|
|
|
|
|
|
440
|
|
|
|
|
|
|
=item * |
441
|
|
|
|
|
|
|
|
442
|
|
|
|
|
|
|
B - I, a scalar value that can be fetched by |
443
|
|
|
|
|
|
|
C<< $fire->data >> from within the callbacks. Good for data that might be useful |
444
|
|
|
|
|
|
|
sometimes but not frequently enough to deserve a spot in the argument list. If |
445
|
|
|
|
|
|
|
C is a hash reference, its values can be fetched conveniently with |
446
|
|
|
|
|
|
|
C<< $fire->data('key') >>. |
447
|
|
|
|
|
|
|
|
448
|
|
|
|
|
|
|
=back |
449
|
|
|
|
|
|
|
|
450
|
|
|
|
|
|
|
=head2 $col->sort |
451
|
|
|
|
|
|
|
|
452
|
|
|
|
|
|
|
Sorts the callbacks according to C, C, and C options. |
453
|
|
|
|
|
|
|
|
454
|
|
|
|
|
|
|
=head1 AUTHOR |
455
|
|
|
|
|
|
|
|
456
|
|
|
|
|
|
|
L |
457
|
|
|
|
|
|
|
|
458
|
|
|
|
|
|
|
Copyright E 2011-2017. Released under New BSD license. |
459
|
|
|
|
|
|
|
|
460
|
|
|
|
|
|
|
Comments, complaints, and recommendations are accepted. Bugs may be reported on |
461
|
|
|
|
|
|
|
L. |