File Coverage

blib/lib/AnyEvent/Emitter.pm
Criterion Covered Total %
statement 43 44 97.7
branch 11 14 78.5
condition 1 2 50.0
subroutine 12 12 100.0
pod 7 8 87.5
total 74 80 92.5


line stmt bran cond sub pod time code
1             package AnyEvent::Emitter;
2 2     2   39671 use strict;
  2         3  
  2         91  
3 2     2   9 use Scalar::Util qw(blessed weaken);
  2         2  
  2         249  
4              
5             our $VERSION = 0.01;
6              
7 2   50 2   11 use constant DEBUG => $ENV{EVENTEMITTER_DEBUG} || 0;
  2         13  
  2         1361  
8              
9             sub new {
10 4     4 0 13 my $class = shift;
11 4         9 my $reference = { events => {} };
12 4         10 return bless( $reference, $class );
13             }
14              
15 1 50   1 1 6 sub catch { $_[0]->on(error => $_[1]) and return $_[0] }
16              
17             sub emit {
18 28     28 1 848 my ($self, $name) = (shift, shift);
19              
20 28 100       54 if (my $s = $self->{events}{$name}) {
21 18         12 warn "-- Emit $name in @{[blessed $self]} (@{[scalar @$s]})\n" if DEBUG;
22 18         22 for my $cb (@$s) { $self->$cb(@_) }
  26         52  
23             }
24             else {
25 10         9 warn "-- Emit $name in @{[blessed $self]} (0)\n" if DEBUG;
26 10 50       22 die "@{[blessed $self]}: $_[0]" if $name eq 'error';
  0         0  
27             }
28              
29 26         78 return $self;
30             }
31              
32 8     8 1 293 sub has_subscribers { !!shift->{events}{shift()} }
33              
34 19 50   19 1 450 sub on { push @{$_[0]{events}{$_[1]}}, $_[2] and return $_[2] }
  19         73  
35              
36             sub once {
37 11     11 1 256 my ($self, $name, $cb) = @_;
38              
39 11         21 weaken $self;
40 11         7 my $wrapper;
41             $wrapper = sub {
42 10     10   14 $self->unsubscribe($name => $wrapper);
43 10         19 $cb->(@_);
44 11         26 };
45 11         16 $self->on($name => $wrapper);
46 11         13 weaken $wrapper;
47              
48 11         19 return $wrapper;
49             }
50              
51 13 100   13 1 750 sub subscribers { shift->{events}{shift()} || [] }
52              
53             sub unsubscribe {
54 15     15 1 18 my ($self, $name, $cb) = @_;
55              
56             # One
57 15 100       20 if ($cb) {
58 14         11 $self->{events}{$name} = [grep { $cb ne $_ } @{$self->{events}{$name}}];
  22         55  
  14         28  
59 14 100       9 delete $self->{events}{$name} unless @{$self->{events}{$name}};
  14         35  
60             }
61              
62             # All
63 1         4 else { delete $self->{events}{$name} }
64              
65 15         19 return $self;
66             }
67              
68              
69             1;
70              
71             =encoding utf8
72              
73             =head1 NAME
74              
75             AnyEvent::Emitter - Event emitter base class (Mojo::Emitter porting).
76              
77             =head1 SYNOPSIS
78              
79             package Cat;
80             use 5.010;
81             use base 'AnyEvent::Emitter';
82              
83             # Emit events
84             sub poke {
85             my $self = shift;
86             $self->emit(roar => 3);
87             }
88              
89             package main;
90              
91             # Subscribe to events
92             my $tiger = Cat->new;
93             $tiger->on(roar => sub {
94             my ($tiger, $times) = @_;
95             say 'RAWR!' for 1 .. $times;
96             });
97             $tiger->poke;
98              
99             =head1 DESCRIPTION
100              
101             L is a simple base class for event emitting objects(Mojo::Emitter porting).
102              
103             =head1 EVENTS
104              
105             L can emit the following events.
106              
107             =head2 error
108              
109             $e->on(error => sub {
110             my ($e, $err) = @_;
111             ...
112             });
113              
114             This is a special event for errors, it will not be emitted directly by this
115             class but is fatal if unhandled.
116              
117             $e->on(error => sub {
118             my ($e, $err) = @_;
119             say "This looks bad: $err";
120             });
121              
122             =head1 METHODS
123              
124             =head2 catch
125              
126             $e = $e->catch(sub {...});
127              
128             Subscribe to L event.
129              
130             # Longer version
131             $e->on(error => sub {...});
132              
133             =head2 emit
134              
135             $e = $e->emit('foo');
136             $e = $e->emit('foo', 123);
137              
138             Emit event.
139              
140             =head2 has_subscribers
141              
142             my $bool = $e->has_subscribers('foo');
143              
144             Check if event has subscribers.
145              
146             =head2 on
147              
148             my $cb = $e->on(foo => sub {...});
149              
150             Subscribe to event.
151              
152             $e->on(foo => sub {
153             my ($e, @args) = @_;
154             ...
155             });
156              
157             =head2 once
158              
159             my $cb = $e->once(foo => sub {...});
160              
161             Subscribe to event and unsubscribe again after it has been emitted once.
162              
163             $e->once(foo => sub {
164             my ($e, @args) = @_;
165             ...
166             });
167              
168             =head2 subscribers
169              
170             my $subscribers = $e->subscribers('foo');
171              
172             All subscribers for event.
173              
174             # Unsubscribe last subscriber
175             $e->unsubscribe(foo => $e->subscribers('foo')->[-1]);
176              
177             =head2 unsubscribe
178              
179             $e = $e->unsubscribe('foo');
180             $e = $e->unsubscribe(foo => $cb);
181              
182             Unsubscribe from event.
183              
184             =head1 DEBUGGING
185              
186             You can set the C environment variable to get some
187             advanced diagnostics information printed to C.
188              
189             EMITTER_DEBUG=1
190              
191             =head1 SEE ALSO
192              
193             L
194              
195             =cut