Newer Older
214 lines | 5.519kb
add files
Yuki Kimoto authored on 2014-03-26
1
package Mojo::Reactor;
2
use Mojo::Base 'Mojo::EventEmitter';
3

            
4
use Carp 'croak';
5
use IO::Poll qw(POLLERR POLLHUP POLLIN);
6
use Mojo::Loader;
7

            
8
sub again { croak 'Method "again" not implemented by subclass' }
9

            
10
sub detect {
11
  my $try = $ENV{MOJO_REACTOR} || 'Mojo::Reactor::EV';
12
  return Mojo::Loader->new->load($try) ? 'Mojo::Reactor::Poll' : $try;
13
}
14

            
15
sub io { croak 'Method "io" not implemented by subclass' }
16

            
17
sub is_readable {
18
  my ($self, $handle) = @_;
19

            
20
  my $test = $self->{test} ||= IO::Poll->new;
21
  $test->mask($handle, POLLIN);
22
  $test->poll(0);
23
  my $result = $test->handles(POLLIN | POLLERR | POLLHUP);
24
  $test->remove($handle);
25

            
26
  return !!$result;
27
}
28

            
29
sub is_running { croak 'Method "is_running" not implemented by subclass' }
30
sub one_tick   { croak 'Method "one_tick" not implemented by subclass' }
31
sub recurring  { croak 'Method "recurring" not implemented by subclass' }
32
sub remove     { croak 'Method "remove" not implemented by subclass' }
33
sub start      { croak 'Method "start" not implemented by subclass' }
34
sub stop       { croak 'Method "stop" not implemented by subclass' }
35
sub timer      { croak 'Method "timer" not implemented by subclass' }
36
sub watch      { croak 'Method "watch" not implemented by subclass' }
37

            
38
1;
39

            
40
=encoding utf8
41

            
42
=head1 NAME
43

            
44
Mojo::Reactor - Low level event reactor base class
45

            
46
=head1 SYNOPSIS
47

            
48
  package Mojo::Reactor::MyEventLoop;
49
  use Mojo::Base 'Mojo::Reactor';
50

            
51
  $ENV{MOJO_REACTOR} ||= 'Mojo::Reactor::MyEventLoop';
52

            
53
  sub again      {...}
54
  sub io         {...}
55
  sub is_running {...}
56
  sub one_tick   {...}
57
  sub recurring  {...}
58
  sub remove     {...}
59
  sub start      {...}
60
  sub stop       {...}
61
  sub timer      {...}
62
  sub watch      {...}
63

            
64
=head1 DESCRIPTION
65

            
66
L<Mojo::Reactor> is an abstract base class for low level event reactors.
67

            
68
=head1 EVENTS
69

            
70
L<Mojo::Reactor> inherits all events from L<Mojo::EventEmitter> and can emit
71
the following new ones.
72

            
73
=head2 error
74

            
75
  $reactor->on(error => sub {
76
    my ($reactor, $err) = @_;
77
    ...
78
  });
79

            
80
Emitted for exceptions caught in callbacks, fatal if unhandled. Note that if
81
this event is unhandled or fails it might kill your program, so you need to be
82
careful.
83

            
84
  $reactor->on(error => sub {
85
    my ($reactor, $err) = @_;
86
    say "Something very bad happened: $err";
87
  });
88

            
89
=head1 METHODS
90

            
91
L<Mojo::Reactor> inherits all methods from L<Mojo::EventEmitter> and
92
implements the following new ones.
93

            
94
=head2 again
95

            
96
  $reactor->again($id);
97

            
98
Restart active timer. Meant to be overloaded in a subclass.
99

            
100
=head2 detect
101

            
102
  my $class = Mojo::Reactor->detect;
103

            
104
Detect and load the best reactor implementation available, will try the value
105
of the MOJO_REACTOR environment variable, L<Mojo::Reactor::EV> or
106
L<Mojo::Reactor::Poll>.
107

            
108
  # Instantiate best reactor implementation available
109
  my $reactor = Mojo::Reactor->detect->new;
110

            
111
=head2 io
112

            
113
  $reactor = $reactor->io($handle => sub {...});
114

            
115
Watch handle for I/O events, invoking the callback whenever handle becomes
116
readable or writable. Meant to be overloaded in a subclass.
117

            
118
  # Callback will be invoked twice if handle becomes readable and writable
119
  $reactor->io($handle => sub {
120
    my ($reactor, $writable) = @_;
121
    say $writable ? 'Handle is writable' : 'Handle is readable';
122
  });
123

            
124
=head2 is_readable
125

            
126
  my $bool = $reactor->is_readable($handle);
127

            
128
Quick non-blocking check if a handle is readable, useful for identifying
129
tainted sockets.
130

            
131
=head2 is_running
132

            
133
  my $bool = $reactor->is_running;
134

            
135
Check if reactor is running. Meant to be overloaded in a subclass.
136

            
137
=head2 one_tick
138

            
139
  $reactor->one_tick;
140

            
141
Run reactor until an event occurs. Note that this method can recurse back into
142
the reactor, so you need to be careful. Meant to be overloaded in a subclass.
143

            
144
  # Don't block longer than 0.5 seconds
145
  my $id = $reactor->timer(0.5 => sub {});
146
  $reactor->one_tick;
147
  $reactor->remove($id);
148

            
149
=head2 recurring
150

            
151
  my $id = $reactor->recurring(0.25 => sub {...});
152

            
153
Create a new recurring timer, invoking the callback repeatedly after a given
154
amount of time in seconds. Meant to be overloaded in a subclass.
155

            
156
  # Invoke as soon as possible
157
  $reactor->recurring(0 => sub { say 'Reactor tick.' });
158

            
159
=head2 remove
160

            
161
  my $bool = $reactor->remove($handle);
162
  my $bool = $reactor->remove($id);
163

            
164
Remove handle or timer. Meant to be overloaded in a subclass.
165

            
166
=head2 start
167

            
168
  $reactor->start;
169

            
170
Start watching for I/O and timer events, this will block until L</"stop"> is
171
called. Note that some reactors stop automatically if there are no events
172
being watched anymore. Meant to be overloaded in a subclass.
173

            
174
=head2 stop
175

            
176
  $reactor->stop;
177

            
178
Stop watching for I/O and timer events. Meant to be overloaded in a subclass.
179

            
180
=head2 timer
181

            
182
  my $id = $reactor->timer(0.5 => sub {...});
183

            
184
Create a new timer, invoking the callback after a given amount of time in
185
seconds. Meant to be overloaded in a subclass.
186

            
187
  # Invoke as soon as possible
188
  $reactor->timer(0 => sub { say 'Next tick.' });
189

            
190
=head2 watch
191

            
192
  $reactor = $reactor->watch($handle, $readable, $writable);
193

            
194
Change I/O events to watch handle for with true and false values. Meant to be
195
overloaded in a subclass. Note that this method requires an active I/O
196
watcher.
197

            
198
  # Watch only for readable events
199
  $reactor->watch($handle, 1, 0);
200

            
201
  # Watch only for writable events
202
  $reactor->watch($handle, 0, 1);
203

            
204
  # Watch for readable and writable events
205
  $reactor->watch($handle, 1, 1);
206

            
207
  # Pause watching for events
208
  $reactor->watch($handle, 0, 0);
209

            
210
=head1 SEE ALSO
211

            
212
L<Mojolicious>, L<Mojolicious::Guides>, L<http://mojolicio.us>.
213

            
214
=cut