biblesearch / mojo / lib / Mojo / EventEmitter.pm /
Newer Older
207 lines | 3.827kb
add files
Yuki Kimoto authored on 2014-03-26
1
package Mojo::EventEmitter;
2
use Mojo::Base -base;
3

            
4
use Scalar::Util qw(blessed weaken);
5

            
6
use constant DEBUG => $ENV{MOJO_EVENTEMITTER_DEBUG} || 0;
7

            
8
sub emit {
9
  my ($self, $name) = (shift, shift);
10

            
11
  if (my $s = $self->{events}{$name}) {
12
    warn "-- Emit $name in @{[blessed $self]} (@{[scalar @$s]})\n" if DEBUG;
13
    for my $cb (@$s) { $self->$cb(@_) }
14
  }
15
  else {
16
    warn "-- Emit $name in @{[blessed $self]} (0)\n" if DEBUG;
17
    die "@{[blessed $self]}: $_[0]" if $name eq 'error';
18
  }
19

            
20
  return $self;
21
}
22

            
23
sub emit_safe {
24
  my ($self, $name) = (shift, shift);
25

            
26
  if (my $s = $self->{events}{$name}) {
27
    warn "-- Emit $name in @{[blessed $self]} safely (@{[scalar @$s]})\n"
28
      if DEBUG;
29
    for my $cb (@$s) {
30
      $self->emit(error => qq{Event "$name" failed: $@})
31
        unless eval { $self->$cb(@_); 1 };
32
    }
33
  }
34
  else {
35
    warn "-- Emit $name in @{[blessed $self]} safely (0)\n" if DEBUG;
36
    die "@{[blessed $self]}: $_[0]" if $name eq 'error';
37
  }
38

            
39
  return $self;
40
}
41

            
42
sub has_subscribers { !!@{shift->subscribers(shift)} }
43

            
44
sub on {
45
  my ($self, $name, $cb) = @_;
46
  push @{$self->{events}{$name} ||= []}, $cb;
47
  return $cb;
48
}
49

            
50
sub once {
51
  my ($self, $name, $cb) = @_;
52

            
53
  weaken $self;
54
  my $wrapper;
55
  $wrapper = sub {
56
    $self->unsubscribe($name => $wrapper);
57
    $cb->(@_);
58
  };
59
  $self->on($name => $wrapper);
60
  weaken $wrapper;
61

            
62
  return $wrapper;
63
}
64

            
65
sub subscribers { shift->{events}{shift()} || [] }
66

            
67
sub unsubscribe {
68
  my ($self, $name, $cb) = @_;
69

            
70
  # One
71
  if ($cb) {
72
    $self->{events}{$name} = [grep { $cb ne $_ } @{$self->{events}{$name}}];
73
    delete $self->{events}{$name} unless @{$self->{events}{$name}};
74
  }
75

            
76
  # All
77
  else { delete $self->{events}{$name} }
78

            
79
  return $self;
80
}
81

            
82
1;
83

            
84
=encoding utf8
85

            
86
=head1 NAME
87

            
88
Mojo::EventEmitter - Event emitter base class
89

            
90
=head1 SYNOPSIS
91

            
92
  package Cat;
93
  use Mojo::Base 'Mojo::EventEmitter';
94

            
95
  # Emit events
96
  sub poke {
97
    my $self = shift;
98
    $self->emit(roar => 3);
99
  }
100

            
101
  package main;
102

            
103
  # Subscribe to events
104
  my $tiger = Cat->new;
105
  $tiger->on(roar => sub {
106
    my ($tiger, $times) = @_;
107
    say 'RAWR!' for 1 .. $times;
108
  });
109
  $tiger->poke;
110

            
111
=head1 DESCRIPTION
112

            
113
L<Mojo::EventEmitter> is a simple base class for event emitting objects.
114

            
115
=head1 EVENTS
116

            
117
L<Mojo::EventEmitter> can emit the following events.
118

            
119
=head2 error
120

            
121
  $e->on(error => sub {
122
    my ($e, $err) = @_;
123
    ...
124
  });
125

            
126
Emitted for event errors, fatal if unhandled.
127

            
128
  $e->on(error => sub {
129
    my ($e, $err) = @_;
130
    say "This looks bad: $err";
131
  });
132

            
133
=head1 METHODS
134

            
135
L<Mojo::EventEmitter> inherits all methods from L<Mojo::Base> and
136
implements the following new ones.
137

            
138
=head2 emit
139

            
140
  $e = $e->emit('foo');
141
  $e = $e->emit('foo', 123);
142

            
143
Emit event.
144

            
145
=head2 emit_safe
146

            
147
  $e = $e->emit_safe('foo');
148
  $e = $e->emit_safe('foo', 123);
149

            
150
Emit event safely and emit L</"error"> event on failure.
151

            
152
=head2 has_subscribers
153

            
154
  my $bool = $e->has_subscribers('foo');
155

            
156
Check if event has subscribers.
157

            
158
=head2 on
159

            
160
  my $cb = $e->on(foo => sub {...});
161

            
162
Subscribe to event.
163

            
164
  $e->on(foo => sub {
165
    my ($e, @args) = @_;
166
    ...
167
  });
168

            
169
=head2 once
170

            
171
  my $cb = $e->once(foo => sub {...});
172

            
173
Subscribe to event and unsubscribe again after it has been emitted once.
174

            
175
  $e->once(foo => sub {
176
    my ($e, @args) = @_;
177
    ...
178
  });
179

            
180
=head2 subscribers
181

            
182
  my $subscribers = $e->subscribers('foo');
183

            
184
All subscribers for event.
185

            
186
  # Unsubscribe last subscriber
187
  $e->unsubscribe(foo => $e->subscribers('foo')->[-1]);
188

            
189
=head2 unsubscribe
190

            
191
  $e = $e->unsubscribe('foo');
192
  $e = $e->unsubscribe(foo => $cb);
193

            
194
Unsubscribe from event.
195

            
196
=head1 DEBUGGING
197

            
198
You can set the MOJO_EVENTEMITTER_DEBUG environment variable to get some
199
advanced diagnostics information printed to C<STDERR>.
200

            
201
  MOJO_EVENTEMITTER_DEBUG=1
202

            
203
=head1 SEE ALSO
204

            
205
L<Mojolicious>, L<Mojolicious::Guides>, L<http://mojolicio.us>.
206

            
207
=cut