File Coverage

blib/lib/Object/Event.pm
Criterion Covered Total %
statement 207 260 79.6
branch 63 98 64.2
condition 15 27 55.5
subroutine 25 32 78.1
pod 15 15 100.0
total 325 432 75.2


line stmt bran cond sub pod time code
1             package Object::Event;
2 20     20   751953 use common::sense;
  20         60  
  20         144  
3 20     20   18710 use Carp qw/croak/;
  20         42  
  20         2272  
4 20     20   27577 use AnyEvent::Util qw/guard/;
  20         722359  
  20         2939  
5              
6 20     20   32792 use sort 'stable';
  20         14256  
  20         138  
7              
8             our $DEBUG = $ENV{PERL_OBJECT_EVENT_DEBUG};
9              
10             =head1 NAME
11              
12             Object::Event - A class that provides an event callback interface
13              
14             =head1 VERSION
15              
16             Version 1.23
17              
18             =cut
19              
20             our $VERSION = '1.23';
21              
22             =head1 SYNOPSIS
23              
24             package foo;
25             use Object::Event;
26              
27             our @ISA = qw/Object::Event/;
28              
29             package main;
30             my $o = foo->new;
31              
32             my $regguard = $o->reg_cb (foo => sub {
33             print "I got an event, with these args: $_[1], $_[2], $_[3]\n";
34             });
35              
36             $o->event (foo => 1, 2, 3);
37              
38             $o->unreg_cb ($regguard);
39             # or just:
40             $regguard = undef;
41              
42              
43             =head1 DESCRIPTION
44              
45             This module was mainly written for L, L,
46             L and L to provide a consistent API for registering and
47             emitting events. Even though I originally wrote it for those modules I released
48             it separately in case anyone may find this module useful.
49              
50             For more comprehensive event handling see also L and L.
51              
52             This class provides a simple way to extend a class, by inheriting from
53             this class, with an event callback interface.
54              
55             You will be able to register callbacks for events, identified by their names (a
56             string) and call them later by invoking the C method with the event name
57             and some arguments.
58              
59             There is even a syntactic sugar which allows to call methods on the instances
60             of L-derived classes, to invoke events. For this feature see
61             the L section of this document.
62              
63             =head1 PERFORMANCE
64              
65             In the first version as presented here no special performance optimisations
66             have been applied. So take care that it is fast enough for your purposes. At
67             least for modules like L the overhead is probably not
68             noticeable, as other technologies like XML already waste a lot more CPU cycles.
69             Also I/O usually introduces _much_ larger/longer overheads than this simple
70             event interface.
71              
72             =head1 FUNCTIONS
73              
74             =over 4
75              
76             =item Object::Event::register_priority_alias ($alias, $priority)
77              
78             This package function will add a global priority alias.
79             If C<$priority> is undef the alias will be removed.
80              
81             There are 4 predefined aliases:
82              
83             before => 1000
84             ext_before => 500
85             ext_after => -500
86             after => -1000
87              
88             See also the C method for more information about aliases.
89              
90             =cut
91              
92             our %PRIO_MAP = (
93             before => 1000,
94             ext_before => 500,
95             ext_after => -500,
96             after => -1000
97             );
98              
99             sub register_priority_alias {
100 2     2 1 43 my ($alias, $prio) = @_;
101 2         4 $PRIO_MAP{$alias} = $prio;
102              
103 2 50       8 unless (defined $PRIO_MAP{$alias}) {
104 0         0 delete $PRIO_MAP{$alias}
105             }
106             }
107              
108             =back
109              
110             =head1 METHODS
111              
112             =over 4
113              
114             =item Object::Event->new (%args)
115              
116             =item Your::Subclass::Of::Object::Event->new (%args)
117              
118             This is the constructor for L,
119             it will create a blessed hash reference initialized with C<%args>.
120              
121             =cut
122              
123             sub new {
124 28     28 1 4759 my $this = shift;
125 28   33     194 my $class = ref ($this) || $this;
126 28         73 my $self = { @_ };
127 28         77 bless $self, $class;
128              
129 28         209 $self->init_object_events;
130              
131 28         101 return $self
132             }
133              
134             =item $obj->init_object_events ()
135              
136             This method should only be called if you are not able to call the C
137             constructor of this class. Then you need to call this method to initialize
138             the event system.
139              
140             =cut
141              
142             sub init_object_events {
143 28     28 1 55 my ($self) = @_;
144              
145 28         61 my $pkg = ref $self;
146              
147 28 100       41 _init_methods ($pkg) unless *{"$pkg\::__OE_METHODS"}{HASH};
  28         280  
148              
149 28         484 $self->{__oe_cb_gen} = "a"; # generation counter
150              
151 26         191 $self->{__oe_events} = {
152             map {
153 26         13631 ($_ => [@{${"$pkg\::__OE_METHODS"}{$_}}])
  26         30  
  28         130  
154 28         58 } keys %{"$pkg\::__OE_METHODS"}
155             };
156             }
157              
158             =item $obj->set_exception_cb ($cb->($exception, $eventname))
159              
160             This method installs a callback that will be called when some other
161             event callback threw an exception. The first argument to C<$cb>
162             will be the exception and the second the event name.
163              
164             =cut
165              
166             sub set_exception_cb {
167 5     5 1 1371 my ($self, $cb) = @_;
168 5         16 $self->{__oe_exception_cb} = $cb;
169             }
170              
171             =item $guard = $obj->reg_cb ($eventname => $cb->($obj, @args), ...)
172              
173             =item $guard = $obj->reg_cb ($eventname => $prio, $cb->($obj, @args), ...)
174              
175             This method registers a callback C<$cb1> for the event with the
176             name C<$eventname1>. You can also pass multiple of these eventname => callback
177             pairs.
178              
179             The return value C<$guard> will be a guard that represents the set of callbacks
180             you have installed. You can either just "forget" the contents of C<$guard> to
181             unregister the callbacks or call C with that ID to remove those
182             callbacks again. If C is called in a void context no guard is returned
183             and you have no chance to unregister the registered callbacks.
184              
185             The first argument for callbacks registered with the C function will
186             always be the master object C<$obj>.
187              
188             The return value of the callbacks are ignored. If you need to pass
189             any information from a handler to the caller of the event you have to
190             establish your own "protocol" to do this. I recommend to pass an array
191             reference to the handlers:
192              
193             $obj->reg_cb (event_foobar => sub {
194             my ($self, $results) = @_;
195             push @$results, time / 30;
196             });
197              
198             my @results;
199             $obj->event (event_foobar => \@results);
200             for (@results) {
201             # ...
202             }
203              
204             The order of the callbacks in the call chain of the event depends on their
205             priority. If you didn't specify any priority (see below) they get the default
206             priority of 0, and are appended to the other priority 0 callbacks.
207             The higher the priority number, the earlier the callbacks gets called in the chain.
208              
209             If C<$eventname1> starts with C<'before_'> the callback gets a priority
210             of 1000, and if it starts with C<'ext_before_'> it gets the priority 500.
211             C<'after_'> is mapped to the priority -1000 and C<'ext_after_'> to -500.
212              
213             If you want more fine grained control you can pass an array reference
214             instead of the event name:
215              
216             ($eventname1, $prio) = ('test_abc', 100);
217             $obj->reg_cb ([$eventname1, $prio] => sub {
218             ...
219             });
220              
221             =cut
222              
223             our @DEBUG_STACK;
224              
225             sub _debug_cb {
226 0     0   0 my ($callback) = @_;
227              
228             sub {
229 0     0   0 my @a = @_;
230 0         0 my $dbcb = $_[0]->{__oe_cbs}->[0]->[0];
231 0         0 my $nam = $_[0]->{__oe_cbs}->[2];
232 0         0 push @DEBUG_STACK, $dbcb;
233              
234 0         0 my $pad = " " x scalar @DEBUG_STACK;
235              
236 0         0 printf "%s-> %s\n", $pad, $dbcb->[3];
237              
238 0         0 eval { $callback->(@a) };
  0         0  
239 0         0 my $e = $@;
240              
241 0         0 printf "%s<- %s\n", $pad, $dbcb->[3];
242              
243 0         0 pop @DEBUG_STACK;
244              
245 0 0       0 die $e if $e;
246             ()
247 0         0 };
  0         0  
248              
249             }
250             sub _print_event_debug {
251 0     0   0 my ($ev) = @_;
252 0         0 my $pad = " " x scalar @DEBUG_STACK;
253 0         0 my ($pkg, $file, $line) = caller (1);
254 0         0 for my $path (@INC) {
255 0 0       0 last if $file =~ s/^\Q$path\E\/?//;
256             }
257 0         0 printf "%s!! %s @ %s:%d (%s::)\n", $pad, $ev, $file, $line, $pkg
258             }
259              
260             sub _register_event_struct {
261 56     56   122 my ($self, $event, $prio, $gen, $callback, $debug) = @_;
262              
263 56   50     184 my $reg = ($self->{__oe_events} ||= {});
264 56         82 my $idx = 0;
265 56   100     209 $reg->{$event} ||= [];
266 56         91 my $evlist = $reg->{$event};
267              
268 56         115 for my $ev (@$evlist) {
269 106 100       244 last if $ev->[0] < $prio;
270 87         142 $idx++;
271             }
272              
273 56         80 my $cb = $callback;
274 56 50       161 $cb = _debug_cb ($callback) if $DEBUG > 1;
275              
276 56         342 splice @$evlist, $idx, 0, [$prio, "$callback|$gen", undef, $debug, $cb];
277             }
278              
279             sub reg_cb {
280 35     35 1 5210 my ($self, @args) = @_;
281              
282 35         89 my $debuginfo = caller;
283 35 50       140 if ($DEBUG > 0) {
284 0         0 my ($pkg,$file,$line) = caller;
285 0         0 for my $path (@INC) {
286 0 0       0 last if $file =~ s/^\Q$path\E\/?//;
287             }
288 0         0 $debuginfo = sprintf "%s:%d (%s::)", $file, $line, $pkg;
289             }
290              
291 35         102 my $gen = $self->{__oe_cb_gen}++; # get gen counter
292              
293 35         55 my @cbs;
294 35         108 while (@args) {
295 56         160 my ($ev, $sec) = (shift @args, shift @args);
296              
297 56         101 my ($prio, $cb) = (0, undef);
298              
299 56 100       138 if (ref $sec) {
300 42         298 for my $prefix (keys %PRIO_MAP) {
301 145 100       1734 if ($ev =~ s/^(\Q$prefix\E)_//) {
302 16         32 $prio = $PRIO_MAP{$prefix};
303 16         35 last;
304             }
305             }
306              
307 42         88 $cb = $sec;
308              
309             } else {
310 14         19 $prio = $sec;
311 14         22 $cb = shift @args;
312             }
313              
314 56         345 $self->_register_event_struct ($ev, $prio, $gen, $cb, $debuginfo);
315 56         179 push @cbs, $cb;
316             }
317              
318             defined wantarray
319 8 50   8   1316 ? \(my $g = guard { if ($self) { $self->unreg_cb ($_, $gen) for @cbs } })
  8         53  
320 35 100       236 : ()
321             }
322              
323             =item $obj->unreg_cb ($cb)
324              
325             Removes the callback C<$cb> from the set of registered callbacks.
326              
327             =cut
328              
329             sub unreg_cb {
330 27     27 1 1018 my ($self, $cb, $gen) = @_;
331              
332 27 100       86 if (ref ($cb) eq 'REF') {
333             # we've got a guard object
334 4         8 $$cb = undef;
335 4         38 return;
336             }
337              
338 23 50       52 return unless defined $cb; # some small safety against bad arguments
339              
340 23         40 my $evs = $self->{__oe_events};
341              
342             # $gen is neccessary for the times where we use the guard to remove
343             # something, because we only have the callback as ID we need to track the
344             # generation of the registration for these:
345             #
346             # my $cb = sub { ... };
347             # my $g = $o->reg_cb (a => $cb);
348             # $g = $o->reg_cb (a => $cb);
349 23 100       110 my ($key, $key_len) = defined $gen
350             ? ("$cb|$gen", length "$cb|$gen")
351             : ("$cb", length "$cb");
352 23         50 for my $reg (values %$evs) {
353 28         198 @$reg = grep { (substr $_->[1], 0, $key_len) ne $key } @$reg;
  102         405  
354             }
355             }
356              
357             =item my $handled = $obj->event ($eventname, @args)
358              
359             Emits the event C<$eventname> and passes the arguments C<@args> to the
360             callbacks. The return value C<$handled> is a true value in case some handler
361             was found and run. It returns false if no handler was found (see also the
362             C method below). Basically: It returns the same value as the
363             C method.
364              
365             Please note that an event can be stopped and reinvoked while it is being
366             handled.
367              
368             See also the specification of the before and after events in C above.
369              
370             NOTE: Whenever an event is emitted the current set of callbacks registered
371             to that event will be used. So, if you register another event callback for the
372             same event that is executed at the moment, it will be called the B time
373             when the event is emitted. Example:
374              
375             $obj->reg_cb (event_test => sub {
376             my ($obj) = @_;
377              
378             print "Test1\n";
379             $obj->unreg_me;
380              
381             $obj->reg_cb (event_test => sub {
382             my ($obj) = @_;
383             print "Test2\n";
384             $obj->unreg_me;
385             });
386             });
387              
388             $obj->event ('event_test'); # prints "Test1"
389             $obj->event ('event_test'); # prints "Test2"
390              
391             =cut
392              
393             sub event {
394 48     48 1 14432 my ($self, $ev, @arg) = @_;
395              
396 48         69 my @cbs;
397              
398 48 100       218 if (ref ($ev) eq 'ARRAY') {
399 1         3 @cbs = @$ev;
400              
401             } else {
402 47   100     187 my $evs = $self->{__oe_events}->{$ev} || [];
403 47         119 @cbs = @$evs;
404             }
405              
406             ######################
407             # Legacy code start
408             ######################
409 48 100       147 if ($self->{__oe_forwards}) {
410             # we are inserting a forward callback into the callchain.
411             # first search the start of the 0 priorities...
412 1         2 my $idx = 0;
413 1         18 for my $ev (@cbs) {
414 0 0       0 last if $ev->[0] <= 0;
415 0         0 $idx++;
416             }
417              
418             # then splice in the stuff
419             my $cb = sub {
420 1     1   2 for my $fw (keys %{$self->{__oe_forwards}}) {
  1         4  
421 1         2 my $f = $self->{__oe_forwards}->{$fw};
422 1         3 local $f->[0]->{__oe_forward_stop} = 0;
423 1         2 eval {
424 1         4 $f->[1]->($self, $f->[0], $ev, @arg);
425             };
426 1 50       23 if ($@) {
    50          
427 0 0       0 if ($self->{__oe_exception_cb}) {
428 0         0 $self->{__oe_exception_cb}->($@, $ev);
429             } else {
430 0         0 warn "unhandled callback exception on forward event "
431             . "($ev, $self, $f->[0], @arg): $@\n";
432             }
433             } elsif ($f->[0]->{__oe_forward_stop}) {
434 0         0 $self->stop_event;
435             }
436             }
437 1         6 };
438              
439 1         6 splice @cbs, $idx, 0, [0, "$cb", undef, undef, $cb];
440             }
441             ######################
442             # Legacy code end
443             ######################
444              
445 48 50       161 _print_event_debug ($ev) if $DEBUG > 1;
446              
447 48 100       139 return unless @cbs;
448              
449 37         150 local $self->{__oe_cbs} = [\@cbs, \@arg, $ev];
450 37         73 eval {
451 37         227 $cbs[0]->[4]->($self, @arg), shift @cbs while @cbs;
452             ()
453 33         443 };
454 37 100       147 if ($@) {
455 4 100 100     29 if (not ($self->{__oe_exception_rec})
    100          
456             && $self->{__oe_exception_cb}) {
457 2         8 local $self->{__oe_exception_rec} = [$ev, $self, @arg];
458 2         8 $self->{__oe_exception_cb}->($@, $ev);
459              
460             } elsif ($self->{__oe_exception_rec}) {
461 1         2 warn "recursion through exception callback "
462 1         14 . "(@{$self->{__oe_exception_rec}}) => "
463             . "($ev, $self, @arg): $@\n";
464             } else {
465 1         11 warn "unhandled callback exception on event ($ev, $self, @arg): $@\n";
466             }
467             }
468              
469             1 # handlers ran
470 37         190 }
471              
472             =item my $bool = $obj->handles ($eventname)
473              
474             This method returns true if any event handler has been setup for
475             the event C<$eventname>.
476              
477             It returns false if that is not the case.
478              
479             =cut
480              
481             sub handles {
482 6     6 1 1022 my ($self, $ev) = @_;
483              
484 6         51 exists $self->{__oe_events}->{$ev}
485 6 50       26 && @{$self->{__oe_events}->{$ev}} > 0
486             }
487              
488             =item $obj->event_name
489              
490             Returns the name of the currently executed event.
491              
492             =cut
493              
494             sub event_name {
495 1     1 1 11 my ($self) = @_;
496 1 50       4 return unless $self->{__oe_cbs};
497 1         8 $self->{__oe_cbs}->[2]
498             }
499              
500             =item $obj->unreg_me
501              
502             Unregisters the currently executed callback.
503              
504             =cut
505              
506             sub unreg_me {
507 5     5 1 37 my ($self) = @_;
508 5 50 33     19 return unless $self->{__oe_cbs} && @{$self->{__oe_cbs}->[0]};
  5         26  
509 5         36 $self->unreg_cb ($self->{__oe_cbs}->[0]->[0]->[1])
510             }
511              
512             =item $continue_cb = $obj->stop_event
513              
514             This method stops the execution of callbacks of the current
515             event, and returns (in non-void context) a callback that will
516             let you continue the execution.
517              
518             =cut
519              
520             sub stop_event {
521 6     6 1 106 my ($self) = @_;
522              
523 6 50 33     26 return unless $self->{__oe_cbs} && @{$self->{__oe_cbs}->[0]};
  6         34  
524              
525 6         8 my $r;
526              
527 6 100       18 if (defined wantarray) {
528 1         2 my @ev = ([@{$self->{__oe_cbs}->[0]}], @{$self->{__oe_cbs}->[1]});
  1         4  
  1         3  
529 1         1 shift @{$ev[0]}; # shift away current cb
  1         2  
530 1     1   561 $r = sub { $self->event (@ev) }
531 1         6 }
532              
533             # XXX: Old legacy code for forwards!
534 6         12 $self->{__oe_forward_stop} = 1;
535              
536 6         9 @{$self->{__oe_cbs}->[0]} = ();
  6         13  
537              
538 6         25 $r
539             }
540              
541             =item $obj->add_forward ($obj, $cb)
542              
543             B Just for backward compatibility for L
544             version 0.4.
545              
546             =cut
547              
548             sub add_forward {
549 1     1 1 15 my ($self, $obj, $cb) = @_;
550 1         7 $self->{__oe_forwards}->{$obj} = [$obj, $cb];
551             }
552              
553             =item $obj->remove_forward ($obj)
554              
555             B Just for backward compatibility for L
556             version 0.4.
557              
558             =cut
559              
560             sub remove_forward {
561 0     0 1 0 my ($self, $obj) = @_;
562 0         0 delete $self->{__oe_forwards}->{$obj};
563 0 0       0 if (scalar (keys %{$self->{__oe_forwards}}) <= 0) {
  0         0  
564 0         0 delete $self->{__oe_forwards};
565             }
566             }
567              
568             sub _event {
569 0     0   0 my $self = shift;
570 0         0 $self->event (@_)
571             }
572              
573             =item $obj->remove_all_callbacks ()
574              
575             This method removes all registered event callbacks from this object.
576              
577             =cut
578              
579             sub remove_all_callbacks {
580 1     1 1 3 my ($self) = @_;
581 1         3 $self->{__oe_events} = {};
582 1         8 delete $self->{__oe_exception_cb};
583             }
584              
585             =item $obj->events_as_string_dump ()
586              
587             This method returns a string dump of all registered event callbacks.
588             This method is only for debugging purposes.
589              
590             =cut
591              
592             sub events_as_string_dump {
593 0     0 1 0 my ($self) = @_;
594 0         0 my $str = '';
595 0         0 for my $ev (keys %{$self->{__oe_events}}) {
  0         0  
596 0         0 my $evr = $self->{__oe_events}->{$ev};
597 0         0 $str .=
598             "$ev:\n"
599 0         0 . join ('', map { sprintf " %5d %s\n", $_->[0], $_->[3] } @$evr)
600             . "\n";
601             }
602             $str
603 0         0 }
604              
605             =back
606              
607             =head1 EVENT METHODS
608              
609             You can define static methods in a package that act as event handler.
610             This is done by using Perl's L functionality. To make
611             a method act as event handler you need to add the C attribute
612             to it.
613              
614             B Please note that for this to work the methods need to be defined at
615             compile time. This means that you are not able to add event handles using
616             C!
617              
618             B Perl's attributes have a very basic syntax, you have to take
619             care to not insert any whitespace, the attribute must be a single
620             string that contains no whitespace. That means: C is not the
621             same as C!
622              
623             Here is an example:
624              
625             package foo;
626             use base qw/Object::Event/;
627              
628             sub test : event_cb { print "test event handler!\n" }
629              
630             package main;
631             my $o = foo->new;
632             $o->test (); # prints 'test event handler!'
633             $o->event ('test'); # also prints 'test event handler!'!
634              
635             In case you want to set a priority use this syntax:
636              
637             sub test : event_cb(-1000) { ... }
638              
639             Or:
640              
641             sub test : event_cb(after) { ... }
642              
643             You may want to have a look at the tests of the L
644             distribution for more examples.
645              
646             =head2 ALIASES
647              
648             If you want to define multiple event handlers as package method
649             you can use the C attribute with an additional argument:
650              
651             package foo;
652             use base qw/Object::Event/;
653              
654             sub test : event_cb { # default prio is always 0
655             print "middle\n";
656             }
657              
658             sub test_last : event_cb(-1,test) {
659             print "after\n";
660             }
661              
662             sub test_first : event_cb(1,test) {
663             print "before\n";
664             }
665              
666             package main;
667             my $o = foo->new;
668             $o->test (); # prints "after\n" "middle\n" "before\n"
669             $o->event ('test'); # prints the same
670             $o->test_first (); # also prints the same
671              
672             B Please note that if you don't provide any order the methods
673             are sorted I:
674              
675             package foo;
676             use base qw/Object::Event/;
677              
678             sub test : event_cb { # default prio is always 0
679             print "middle\n";
680             }
681              
682             sub x : event_cb(, test) { # please note the empty element before the ','!
683             print "after\n";
684             }
685              
686             sub a : event_cb(, test) {
687             print "before\n";
688             }
689              
690             package main;
691             my $o = foo->new;
692             $o->test (); # prints "after\n" "middle\n" "before\n"
693             $o->event ('test'); # prints the same
694             $o->x (); # also prints the same
695              
696             =head2 ALIAS ORDERING
697              
698             The ordering of how the methods event handlers are called if they
699             are all defined for the same event is strictly defined:
700              
701             =over 4
702              
703             =item 1.
704              
705             Ordering of the methods for the same event in the inheritance hierarchy
706             is always dominated by the priority of the event callback.
707              
708             =item 2.
709              
710             Then if there are multiple methods with the same priority the place in the
711             inheritance hierarchy defines in which order the methods are executed. The
712             higher up in the hierarchy the class is, the earlier it will be called.
713              
714             =item 3.
715              
716             Inside a class the name of the method for the event decides which event is
717             executed first. (All if the priorities are the same)
718              
719             =back
720              
721             =cut
722              
723             our %ATTRIBUTES;
724              
725             sub FETCH_CODE_ATTRIBUTES {
726 0     0   0 my ($pkg, $ref) = @_;
727 0 0       0 return () unless exists $ATTRIBUTES{$pkg};
728 0 0       0 return () unless exists $ATTRIBUTES{$pkg}->{"$ref"};
729              
730 0         0 my $a = $ATTRIBUTES{$pkg}->{"$ref"};
731              
732 0 0 0     0 'event_cb' . (
733             ($a->[0] ne '' || defined ($b->[1]))
734             ? "($a->[0],$b->[1])"
735             : ''
736             )
737             }
738              
739             sub MODIFY_CODE_ATTRIBUTES {
740 37     37   35138 my ($pkg, $ref, @attrs) = @_;
741 38         52 grep {
742 37         61 my $unhandled = 1;
743              
744 38 100       242 if ($_ =~ /^event_cb (?:
745             \(
746             \s* ([^\),]*) \s*
747             (?: , \s* ([^\)]+) \s* )?
748             \)
749             )?$/x) {
750 37         224 $ATTRIBUTES{$pkg}->{"$ref"} = [$1, $2];
751 37         64 $unhandled = 0;
752             }
753              
754             $unhandled
755 38         134 } @attrs;
756             }
757              
758             sub _init_methods {
759 51     51   109 my ($pkg) = @_;
760              
761 51         76 my $pkg_meth = \%{"$pkg\::__OE_METHODS"};
  51         172  
762              
763 51         77 for my $superpkg (@{"$pkg\::ISA"}) { # go recursively into super classes
  51         238  
764 34 50       326 next unless $superpkg->isa ("Object::Event"); # skip non O::E
765              
766             # go into the class if we have not already been there
767 34         417 _init_methods ($superpkg)
768 34 100       53 unless *{"$superpkg\::__OE_METHODS"}{HASH};
769              
770             # add the methods of the $superpkg to our own
771 34         57 for (keys %{"$superpkg\::__OE_METHODS"}) {
  34         187  
772 21 50       28 push @{$pkg_meth->{$_}}, @{${"$superpkg\::__OE_METHODS"}{$_} || []};
  21         155  
  21         23  
  21         150  
773             }
774             }
775              
776 51         224 my %mymethds;
777              
778             # now check each package symbol
779 51         72 for my $realmeth (keys %{"$pkg\::"}) {
  51         463  
780              
781 948         940 my $coderef = *{"$pkg\::$realmeth"}{CODE};
  948         3105  
782 948 100       3055 next unless exists $ATTRIBUTES{$pkg}->{"$coderef"}; # skip unattributed methods
783 36         84 my $m = $ATTRIBUTES{$pkg}->{"$coderef"}; # $m = [$prio, $event_name]
784              
785 36         59 my $meth = $realmeth;
786              
787 36 100       97 if (defined $m->[1]) { # assign alias
788 12         22 $meth = $m->[1];
789             }
790              
791 36         49 my $cb = $coderef;
792 36 50       102 $cb = _debug_cb ($coderef) if $DEBUG > 1;
793              
794 34         365 push @{$mymethds{$meth}}, [
  36         273  
795             (exists $PRIO_MAP{$m->[0]} # set priority
796             ? $PRIO_MAP{$m->[0]}
797             : 0+$m->[0]),
798             "$coderef", # callback id
799             $realmeth, # original method name
800             $pkg . '::' . $realmeth, # debug info
801             $cb # the callback
802              
803             # only replace if defined, otherwise declarations without definitions will
804             # replace the $cb/$coderef with something that calls itself recursively.
805              
806 36 100       55 ] if defined &{"$pkg\::$realmeth"};
    100          
807              
808             #d# warn "REPLACED $pkg $meth (by $realmeth) => $coderef ($m->[1])\n";
809              
810 36         89 _replace_method ($pkg, $realmeth, $meth);
811             }
812              
813             # sort my methods by name
814 51         266 for my $ev (keys %mymethds) {
815 25         83 @{$mymethds{$ev}} =
  12         34  
816 25         78 sort { $a->[2] cmp $b->[2] }
817 25         39 @{$mymethds{$ev}};
818             }
819              
820             # add my methods to the super class method list
821 25         57 push @{$pkg_meth->{$_}}, @{$mymethds{$_}}
  25         120  
822 51         353 for keys %mymethds;
823              
824             # sort by priority over all, stable to not confuse names
825 51         197 for my $ev (keys %$pkg_meth) {
826 33         341 @{$pkg_meth->{$ev}} =
  59         240  
827 33         92 sort { $b->[0] <=> $a->[0] }
828 33         44 @{$pkg_meth->{$ev}};
829             }
830             }
831              
832             sub _replace_method {
833 36     36   86 my ($pkg, $meth, $ev) = @_;
834              
835 36         297 *{"$pkg\::$meth"} = sub {
836 24     24   3089 my ($self, @arg) = @_;
837              
838 24 50       84 _print_event_debug ($ev) if $DEBUG > 1;
839              
840             # either execute callbacks of the object or
841             # alternatively (if non present) the inherited ones
842 1         90 my @cbs = @{
843 24         32 $self->{__oe_events}->{$ev}
844 24 100 66     150 || ${"$pkg\::__OE_METHODS"}{$ev}
845             || []};
846              
847             # inline the code of the C method.
848 24         98 local $self->{__oe_cbs} = [\@cbs, \@arg, $ev];
849 24         42 eval {
850 24         121 $cbs[0]->[4]->($self, @arg), shift @cbs while @cbs;
851             ()
852 21         481 };
853              
854 24 100       105 if ($@) {
855 3 100 66     21 if (not ($self->{__oe_exception_rec})
    50          
856             && $self->{__oe_exception_cb}) {
857              
858 2         7 local $self->{__oe_exception_rec} = [$ev, $self, @arg];
859 2         8 $self->{__oe_exception_cb}->($@, $ev);
860              
861             } elsif ($self->{__oe_exception_rec}) {
862 1         2 warn "recursion through exception callback "
863 1         21 . "(@{$self->{__oe_exception_rec}}) => "
864             . "($ev, $self, @arg): $@\n";
865              
866             } else {
867 0         0 warn "unhandled callback exception on event "
868             . "($ev, $self, @arg): $@\n";
869             }
870             }
871              
872 24         105 @cbs > 0
873 36         197 };
874             }
875              
876             =head1 DEBUGGING
877              
878             There exists a package global variable called C<$DEBUG> that control debugging
879             capabilities.
880              
881             Set it to 1 to produce a slightly extended C output.
882              
883             Set it to 2 and all events will be dumped in a tree of event invocations.
884              
885             You can set the variable either in your main program:
886              
887             $Object::Event::DEBUG = 2;
888              
889             Or use the environment variable C:
890              
891             export PERL_OBJECT_EVENT_DEBUG=2
892              
893             =head1 AUTHOR
894              
895             Robin Redeker, C<< >>, JID: C<< >>
896              
897             =head1 SUPPORT
898              
899             You can find documentation for this module with the perldoc command.
900              
901             perldoc Object::Event
902              
903             You can also look for information at:
904              
905             =over 4
906              
907             =item * AnnoCPAN: Annotated CPAN documentation
908              
909             L
910              
911             =item * CPAN Ratings
912              
913             L
914              
915             =item * RT: CPAN's request tracker
916              
917             L
918              
919             =item * Search CPAN
920              
921             L
922              
923             =back
924              
925             =head1 ACKNOWLEDGEMENTS
926              
927             Thanks go to:
928              
929             - Mons Anderson for suggesting the 'handles' method and
930             the return value of the 'event' method and reporting bugs.
931              
932             =head1 COPYRIGHT & LICENSE
933              
934             Copyright 2009-2011 Robin Redeker, all rights reserved.
935              
936             This program is free software; you can redistribute it and/or modify it
937             under the same terms as Perl itself.
938              
939             =cut
940              
941             1;