File Coverage

blib/lib/MooseX/Event/Role.pm
Criterion Covered Total %
statement 77 111 69.3
branch 12 28 42.8
condition 7 10 70.0
subroutine 12 12 100.0
pod 6 6 100.0
total 114 167 68.2


line stmt bran cond sub pod time code
1             # ABSTRACT: A Node style event Role for Moose
2             package MooseX::Event::Role;
3             {
4             $MooseX::Event::Role::VERSION = 'v0.2.0';
5             }
6 3     3   15 use MooseX::Event ();
  3         13  
  3         64  
7 3     3   14 use Any::Moose 'Role';
  3         7  
  3         14  
8              
9             has '_listeners' => (isa=>'HashRef', is=>'ro', default=>sub{ {} });
10             has '_aliases' => (isa=>'HashRef', is=>'ro', default=>sub{ {} });
11              
12              
13             has 'current_event' => (isa=>'Str|Undef', is=>'rw');
14              
15              
16             MooseX::Event::has_event('new_listener');
17              
18              
19             sub event_exists {
20 28     28 1 32 my $self = shift;
21 28         37 my( $event ) = @_;
22 28         168 return $self->can("event:$event");
23             }
24              
25              
26             sub on {
27 8     8 1 60 my $self = shift;
28 8         18 my( $event, $listener, @wrappers ) = @_;
29 8 50       23 if ( ! $self->event_exists($event) ) {
30 0         0 die "Event $event does not exist";
31             }
32 8   100     53 $self->_listeners->{$event} ||= [];
33 8   100     42 $self->_aliases->{$event} ||= {};
34 8 50 66     9 if ( ! @{$self->_listeners->{$event}} and $self->can('activate_event') ) {
  8         88  
35 0         0 $self->activate_event($event);
36             }
37 8         10 my @aliases;
38 8         112 my $wrapped = $listener;
39 8         25 for ( reverse(@wrappers), reverse(@MooseX::Event::listener_wrappers) ) {
40 2         7 push @aliases, 0+$wrapped;
41 2         6 $wrapped = $_->( $wrapped );
42             }
43 8         46 $self->_aliases->{$event}{0+$wrapped} = \@aliases;
44 8         19 for ( @aliases ) {
45 2         13 $self->_aliases->{$event}{$_} = $wrapped;
46             }
47 8         26 $self->emit('new_listener', $event, $wrapped);
48 8         9 push @{ $self->_listeners->{$event} }, $wrapped;
  8         151  
49 8         24 return $wrapped;
50             }
51              
52              
53             sub once {
54 2     2 1 1058 my $self = shift;
55             $self->on( @_, sub {
56 2     2   9 my($listener) = @_;
57 2         3 my $wrapped;
58             $wrapped = sub {
59 2         6 my $self = shift;
60 2         11 $self->remove_listener($self->current_event=>$wrapped);
61 2         3 $wrapped=undef;
62 2         8 goto $listener;
63 2         9 };
64 2         7 return $wrapped;
65 2         16 });
66             }
67              
68             BEGIN {
69              
70              
71             my $emit_stock = sub {
72 16     16   40 my $self = shift;
73 16         31 my( $event, @args ) = @_;
74 16 50       31 if ( ! $self->event_exists($event) ) {
75 0         0 die "Event $event does not exist";
76             }
77 16 100       75 return unless exists $self->_listeners->{$event};
78 8         22 my $ce = $self->current_event;
79 8         34 $self->current_event( $event );
80 8         10 foreach ( @{ $self->_listeners->{$event} } ) {
  8         36  
81 6         1616 $_->($self,@args);
82             }
83 8         963 $self->current_event($ce);
84 8         20 return;
85 3     3   19 };
86              
87              
88             my $emit_coro = sub {
89 0         0 my $self = shift;
90 0         0 my( $event, @args ) = @_;
91 0 0       0 if ( ! $self->event_exists($event) ) {
92 0         0 die "Event $event does not exist";
93             }
94 0 0       0 return unless exists $self->_listeners->{$event};
95              
96 0         0 foreach my $todo ( @{ $self->_listeners->{$event} } ) {
  0         0  
97 0         0 my $ce;
98             &Coro::async( sub {
99             &Coro::on_enter( sub {
100 0         0 $ce = $self->current_event;
101 0         0 $self->current_event($event);
102 0         0 });
103 0         0 $todo->(@_);
104             &Coro::on_leave( sub {
105 0         0 $self->current_event($ce);
106 0         0 });
107 0         0 }, $self, @args );
108             }
109 0         0 Coro::cede();
110              
111 0         0 return;
112 3         1047 };
113              
114              
115             sub emit {
116 3     3   10925 no warnings 'redefine';
  3         5  
  3         229  
117 16 50   16 1 70 if ( defined *Coro::async{CODE} ) {
118 0         0 *emit = $emit_coro;
119 0         0 goto $emit_coro;
120             }
121             else {
122 16         29 *emit = $emit_stock;
123 16         39 goto $emit_stock;
124             }
125             }
126              
127             }
128              
129              
130             sub remove_all_listeners {
131 2     2 1 12 my $self = shift;
132 2 50       11 if ( @_ ) {
133 2         4 my( $event ) = @_;
134 2         16 delete $self->_listeners->{$event};
135 2         12 delete $self->_aliases->{$event};
136 2 50       26 if ( $self->can('deactivate_event') ) {
137 0         0 $self->deactivate_event($event);
138             }
139             }
140             else {
141 0 0       0 if ( $self->can('deactivate_event') ) {
142 0         0 for ( keys %{$self->_listeners} ) {
  0         0  
143 0         0 $self->deactivate_event($_);
144             }
145             }
146 0         0 %{ $self->_listeners } = ();
  0         0  
147 0         0 %{ $self->_aliases } = ();
  0         0  
148             }
149             }
150              
151              
152             sub remove_listener {
153 4     4 1 21 my $self = shift;
154 4         8 my( $event, $listener ) = @_;
155 4 50       8 if ( ! $self->event_exists($event) ) {
156 0         0 die "Event $event does not exist";
157             }
158 4 50       19 return unless exists $self->_listeners->{$event};
159            
160 4         18 my $aliases = $self->_aliases->{$event}{0+$listener};
161 4         16 delete $self->_aliases->{$event}{0+$listener};
162            
163 4 50       13 if ( ref $aliases eq "ARRAY" ) {
164 4         10 for ( @$aliases ) {
165 2         10 delete $self->_aliases->{$event}{$_};
166             }
167             }
168             else {
169 0         0 $listener = $aliases;
170             }
171              
172 4         22 $self->_listeners->{$event} =
173 4         16 [ grep { $_ != $listener } @{ $self->_listeners->{$event} } ];
  4         18  
174            
175 4 50 33     6 if ( ! @{$self->_listeners->{$event}} and $self->can('deactivate_event') ) {
  4         41  
176 0           $self->deactivate_event($event);
177             }
178             }
179              
180             1;
181              
182              
183             __END__