line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
# Copyright (c) 2011-16, 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
|
|
74
|
use warnings; |
|
13
|
|
|
|
|
25
|
|
|
13
|
|
|
|
|
326
|
|
9
|
13
|
|
|
13
|
|
57
|
use strict; |
|
13
|
|
|
|
|
26
|
|
|
13
|
|
|
|
|
240
|
|
10
|
13
|
|
|
13
|
|
57
|
use utf8; |
|
13
|
|
|
|
|
23
|
|
|
13
|
|
|
|
|
53
|
|
11
|
13
|
|
|
13
|
|
320
|
use 5.010; |
|
13
|
|
|
|
|
38
|
|
12
|
|
|
|
|
|
|
|
13
|
13
|
|
|
13
|
|
61
|
use Scalar::Util qw(weaken blessed); |
|
13
|
|
|
|
|
22
|
|
|
13
|
|
|
|
|
643
|
|
14
|
13
|
|
|
13
|
|
75
|
use List::Util qw(min max); |
|
13
|
|
|
|
|
34
|
|
|
13
|
|
|
|
|
1130
|
|
15
|
13
|
|
|
13
|
|
115
|
use Carp qw(carp); |
|
13
|
|
|
|
|
24
|
|
|
13
|
|
|
|
|
16020
|
|
16
|
|
|
|
|
|
|
|
17
|
|
|
|
|
|
|
our $VERSION = '5.63'; |
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
|
97
|
return bless { |
26
|
|
|
|
|
|
|
pending => {}, |
27
|
|
|
|
|
|
|
default_names => {}, |
28
|
|
|
|
|
|
|
names => {} |
29
|
|
|
|
|
|
|
}, shift; |
30
|
|
|
|
|
|
|
} |
31
|
|
|
|
|
|
|
|
32
|
|
|
|
|
|
|
sub push_callbacks { |
33
|
13
|
|
|
13
|
0
|
36
|
my ($collection, $callbacks, $names) = @_; |
34
|
13
|
|
|
|
|
57
|
my $pending = $collection->{pending}; |
35
|
13
|
|
|
|
|
29
|
my $my_names = $collection->{names}; |
36
|
|
|
|
|
|
|
|
37
|
|
|
|
|
|
|
# add to pending callbacks and callback name-to-ID mapping. |
38
|
13
|
|
|
|
|
61
|
@$pending { keys %$callbacks } = values %$callbacks; |
39
|
13
|
|
|
|
|
51
|
@$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
|
|
|
183
|
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
|
0
|
44
|
my ($collection, @options) = @_; |
71
|
|
|
|
|
|
|
|
72
|
|
|
|
|
|
|
# handle options. |
73
|
13
|
|
|
|
|
46
|
my ($caller, $data) = $collection->{caller}; |
74
|
13
|
|
|
|
|
52
|
while (@options) { |
75
|
13
|
|
|
|
|
35
|
my $opt = shift @options; |
76
|
|
|
|
|
|
|
|
77
|
13
|
100
|
|
|
|
53
|
if ($opt eq 'caller') { $caller = shift @options } # custom caller |
|
11
|
|
|
|
|
24
|
|
78
|
13
|
100
|
|
|
|
48
|
if ($opt eq 'data') { $data = shift @options } # fire data |
|
2
|
|
|
|
|
5
|
|
79
|
|
|
|
|
|
|
|
80
|
|
|
|
|
|
|
# boolean option. |
81
|
13
|
50
|
|
|
|
64
|
$collection->{$opt} = 1 if $boolopts{$opt}; |
82
|
|
|
|
|
|
|
|
83
|
|
|
|
|
|
|
} |
84
|
|
|
|
|
|
|
|
85
|
|
|
|
|
|
|
# create fire object. |
86
|
13
|
|
100
|
|
|
130
|
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
|
|
|
|
124
|
$collection->sort if not $collection->{sorted}; |
94
|
13
|
50
|
|
|
|
68
|
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
|
|
|
|
55
|
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
|
|
|
|
|
82
|
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
|
0
|
35
|
my $collection = shift; |
127
|
13
|
50
|
|
|
|
52
|
return unless $collection->{pending}; |
128
|
13
|
|
|
|
|
30
|
my %callbacks = %{ $collection->{pending} }; |
|
13
|
|
|
|
|
66
|
|
129
|
13
|
|
|
|
|
37
|
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
|
|
|
|
|
73
|
while (my $set = shift @callbacks) { |
135
|
35
|
|
|
|
|
86
|
my ($priority, $group, $cb) = @$set; |
136
|
35
|
|
|
|
|
73
|
my $cb_id = $cb->{id}; |
137
|
35
|
|
|
|
|
84
|
my $group_id = $group->[3]; |
138
|
|
|
|
|
|
|
|
139
|
35
|
50
|
|
|
|
95
|
next if $done{$cb_id}; |
140
|
|
|
|
|
|
|
|
141
|
|
|
|
|
|
|
# a real priority exists already. |
142
|
35
|
100
|
66
|
|
|
224
|
if (defined $priority && $priority ne 'nan') { |
143
|
22
|
|
|
|
|
55
|
push @sorted, $set; |
144
|
22
|
|
|
|
|
52
|
$done{$cb_id} = 1; |
145
|
22
|
|
|
|
|
80
|
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
|
13
|
|
|
|
|
23
|
my $wait_max = keys %callbacks; |
162
|
|
|
|
|
|
|
|
163
|
13
|
|
|
|
|
34
|
my $name_to_id = $collection->_group_names($group_id); |
164
|
|
|
|
|
|
|
my $get_befores_afters = sub { |
165
|
22
|
|
|
22
|
|
44
|
my ($key, @results) = shift; |
166
|
22
|
100
|
|
|
|
57
|
my $list = $cb->{$key} or return; |
167
|
17
|
100
|
|
|
|
44
|
$list = [ $list ] if ref $list ne 'ARRAY'; |
168
|
|
|
|
|
|
|
|
169
|
|
|
|
|
|
|
# for each callback name, find its priority. |
170
|
17
|
|
|
|
|
34
|
foreach my $their_name (@$list) { |
171
|
|
|
|
|
|
|
|
172
|
|
|
|
|
|
|
# map callback name to id, id to cbref, and cbref to priority. |
173
|
27
|
100
|
|
|
|
67
|
my $their_id = $name_to_id->{$their_name} or next; |
174
|
15
|
50
|
|
|
|
36
|
my $their_cb = $callbacks{$their_id} or next; |
175
|
15
|
|
|
|
|
24
|
my $their_p = $their_cb->[0]; |
176
|
|
|
|
|
|
|
|
177
|
|
|
|
|
|
|
# if their priority is nan, |
178
|
|
|
|
|
|
|
# we have to wait until it is determined. |
179
|
15
|
100
|
|
|
|
35
|
if ($their_p eq 'nan') { |
180
|
8
|
|
|
|
|
16
|
my $wait_key = "$cb_id $their_id"; |
181
|
|
|
|
|
|
|
push @callbacks, $set |
182
|
8
|
100
|
|
|
|
27
|
unless $waited{$key}++ > $wait_max; |
183
|
8
|
|
|
|
|
17
|
return 1; |
184
|
|
|
|
|
|
|
} |
185
|
|
|
|
|
|
|
|
186
|
7
|
|
|
|
|
17
|
push @results, $their_p; |
187
|
|
|
|
|
|
|
} |
188
|
|
|
|
|
|
|
|
189
|
9
|
|
|
|
|
24
|
return (undef, @results); |
190
|
13
|
|
|
|
|
49
|
}; |
191
|
|
|
|
|
|
|
|
192
|
13
|
100
|
|
|
|
50
|
my ($next, @befores) = $get_befores_afters->('before'); next if $next; |
|
13
|
|
|
|
|
49
|
|
193
|
9
|
100
|
|
|
|
18
|
($next, my @afters ) = $get_befores_afters->('after'); next if $next; |
|
9
|
|
|
|
|
39
|
|
194
|
|
|
|
|
|
|
|
195
|
|
|
|
|
|
|
# figure the ideal priority. |
196
|
5
|
50
|
66
|
|
|
33
|
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
|
|
|
|
|
17
|
my $refpoint = max @befores; |
205
|
3
|
|
|
|
|
9
|
$priority = ++$refpoint; |
206
|
|
|
|
|
|
|
} |
207
|
|
|
|
|
|
|
|
208
|
|
|
|
|
|
|
# only after. |
209
|
|
|
|
|
|
|
elsif (@afters) { |
210
|
2
|
|
|
|
|
8
|
my $refpoint = min @afters; |
211
|
2
|
|
|
|
|
5
|
$priority = --$refpoint; |
212
|
|
|
|
|
|
|
} |
213
|
|
|
|
|
|
|
|
214
|
5
|
50
|
|
|
|
26
|
$priority = 0 if $priority eq 'nan'; |
215
|
|
|
|
|
|
|
|
216
|
|
|
|
|
|
|
# done with this callback. |
217
|
5
|
|
|
|
|
11
|
$set->[0] = $priority; |
218
|
5
|
|
|
|
|
9
|
push @sorted, $set; |
219
|
5
|
|
|
|
|
39
|
$done{$cb_id} = 1; |
220
|
|
|
|
|
|
|
|
221
|
|
|
|
|
|
|
} |
222
|
|
|
|
|
|
|
|
223
|
|
|
|
|
|
|
# the final sort by numerical priority. |
224
|
13
|
|
|
|
|
80
|
$collection->{sorted} = [ sort { $b->[0] <=> $a->[0] } @sorted ]; |
|
23
|
|
|
|
|
101
|
|
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
|
|
47
|
my ($collection, $fire) = @_; |
260
|
13
|
|
|
|
|
66
|
my $ef_props = $fire->{$props}; |
261
|
|
|
|
|
|
|
|
262
|
|
|
|
|
|
|
# store the collection. |
263
|
13
|
50
|
|
|
|
45
|
my $remaining = $collection->{sorted} or return; |
264
|
13
|
|
|
|
|
47
|
$ef_props->{collection} = $collection; |
265
|
|
|
|
|
|
|
|
266
|
|
|
|
|
|
|
# call each callback. |
267
|
13
|
|
|
|
|
55
|
while (my $entry = shift @$remaining) { |
268
|
26
|
|
|
|
|
61
|
my ($priority, $group, $cb) = @$entry; |
269
|
26
|
|
|
|
|
59
|
my ($eo, $event_name, $args, $group_id) = @$group; |
270
|
|
|
|
|
|
|
|
271
|
|
|
|
|
|
|
# sanity check! |
272
|
26
|
50
|
33
|
|
|
198
|
blessed $eo && $eo->isa('Evented::Object') or return; |
273
|
|
|
|
|
|
|
|
274
|
|
|
|
|
|
|
# callback name-to-ID mapping is specific to each group. |
275
|
26
|
|
|
|
|
79
|
$ef_props->{callback_ids} = $collection->_group_names($group_id); |
276
|
|
|
|
|
|
|
|
277
|
|
|
|
|
|
|
# increment the callback counter. |
278
|
26
|
|
|
|
|
58
|
$ef_props->{callback_i}++; |
279
|
|
|
|
|
|
|
|
280
|
|
|
|
|
|
|
# set the evented object of this callback. |
281
|
|
|
|
|
|
|
# set the event name of this callback. |
282
|
26
|
|
|
|
|
51
|
$ef_props->{object} = $eo; weaken($ef_props->{object}); # $fire->object |
|
26
|
|
|
|
|
76
|
|
283
|
26
|
|
|
|
|
46
|
$ef_props->{name} = $event_name; # $fire->event_name |
284
|
|
|
|
|
|
|
|
285
|
|
|
|
|
|
|
# store identifiers. |
286
|
26
|
|
|
|
|
72
|
$ef_props->{callback_id} = my $cb_id = $cb->{id}; |
287
|
26
|
|
|
|
|
56
|
$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
|
|
|
|
|
52
|
$ef_props->{callback_priority} = $priority; # $fire->callback_priority |
292
|
26
|
100
|
|
|
|
79
|
$ef_props->{callback_data} = $cb->{data} if defined $cb->{data}; # $fire->callback_data |
293
|
|
|
|
|
|
|
|
294
|
|
|
|
|
|
|
# this callback has been called already. |
295
|
26
|
50
|
|
|
|
73
|
next if $ef_props->{called}{$cb_id}; |
296
|
|
|
|
|
|
|
|
297
|
|
|
|
|
|
|
# this callback has probably been cancelled. |
298
|
26
|
100
|
|
|
|
84
|
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
|
|
|
|
|
50
|
my @cb_args = @$args; |
308
|
25
|
|
|
|
|
87
|
my $include_obj = grep $cb->{$_}, qw(with_eo with_obj with_evented_obj eo_obj); |
309
|
25
|
50
|
|
|
|
85
|
unshift @cb_args, $fire unless $cb->{no_fire_obj}; |
310
|
25
|
50
|
|
|
|
64
|
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
|
|
|
|
97
|
: $cb->{code}(@cb_args); |
319
|
|
|
|
|
|
|
|
320
|
|
|
|
|
|
|
# set $fire->called($cb) true, and set $fire->last to the callback's name. |
321
|
25
|
|
|
|
|
3812
|
$ef_props->{called}{$cb_id} = 1; |
322
|
25
|
|
|
|
|
62
|
$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
|
|
|
91
|
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
|
|
|
|
145
|
if ($ef_props->{stop}) { |
337
|
1
|
|
|
|
|
3
|
$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
|
|
|
|
|
63
|
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
|
|
|
|
|
30
|
$ef_props->{complete} = 1; |
352
|
13
|
|
|
|
|
117
|
return $fire; |
353
|
|
|
|
|
|
|
|
354
|
|
|
|
|
|
|
} |
355
|
|
|
|
|
|
|
|
356
|
|
|
|
|
|
|
sub _group_names { |
357
|
39
|
|
|
39
|
|
90
|
my ($collection, $group_id) = @_; |
358
|
39
|
|
66
|
|
|
149
|
return $collection->{group_names}{$group_id} ||= do { |
359
|
14
|
|
50
|
|
|
52
|
my $names_from_group = $collection->{names}{$group_id} || {}; |
360
|
14
|
|
|
|
|
38
|
my $default_names = $collection->{default_names}; |
361
|
14
|
|
|
|
|
65
|
my %names = (%$default_names, %$names_from_group); |
362
|
14
|
|
|
|
|
67
|
\%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; |