1 | package Mojo::Reactor;
|
---|
2 | use Mojo::Base 'Mojo::EventEmitter';
|
---|
3 |
|
---|
4 | use Carp 'croak';
|
---|
5 | use Config;
|
---|
6 | use Mojo::Loader 'load_class';
|
---|
7 |
|
---|
8 | my %DETECTED;
|
---|
9 |
|
---|
10 | sub again { croak 'Method "again" not implemented by subclass' }
|
---|
11 |
|
---|
12 | sub detect {
|
---|
13 | my $default = 'Mojo::Reactor::' . ($Config{d_pseudofork} ? 'Poll' : 'EV');
|
---|
14 | my $try = $ENV{MOJO_REACTOR} || $default;
|
---|
15 | return $DETECTED{$try} ||= load_class($try) ? 'Mojo::Reactor::Poll' : $try;
|
---|
16 | }
|
---|
17 |
|
---|
18 | sub io { croak 'Method "io" not implemented by subclass' }
|
---|
19 | sub is_running { croak 'Method "is_running" not implemented by subclass' }
|
---|
20 | sub next_tick { croak 'Method "next_tick" not implemented by subclass' }
|
---|
21 | sub one_tick { croak 'Method "one_tick" not implemented by subclass' }
|
---|
22 | sub recurring { croak 'Method "recurring" not implemented by subclass' }
|
---|
23 | sub remove { croak 'Method "remove" not implemented by subclass' }
|
---|
24 | sub reset { croak 'Method "reset" not implemented by subclass' }
|
---|
25 | sub start { croak 'Method "start" not implemented by subclass' }
|
---|
26 | sub stop { croak 'Method "stop" not implemented by subclass' }
|
---|
27 | sub timer { croak 'Method "timer" not implemented by subclass' }
|
---|
28 | sub watch { croak 'Method "watch" not implemented by subclass' }
|
---|
29 |
|
---|
30 | 1;
|
---|
31 |
|
---|
32 | =encoding utf8
|
---|
33 |
|
---|
34 | =head1 NAME
|
---|
35 |
|
---|
36 | Mojo::Reactor - Low-level event reactor base class
|
---|
37 |
|
---|
38 | =head1 SYNOPSIS
|
---|
39 |
|
---|
40 | package Mojo::Reactor::MyEventLoop;
|
---|
41 | use Mojo::Base 'Mojo::Reactor';
|
---|
42 |
|
---|
43 | sub again {...}
|
---|
44 | sub io {...}
|
---|
45 | sub is_running {...}
|
---|
46 | sub next_tick {...}
|
---|
47 | sub one_tick {...}
|
---|
48 | sub recurring {...}
|
---|
49 | sub remove {...}
|
---|
50 | sub reset {...}
|
---|
51 | sub start {...}
|
---|
52 | sub stop {...}
|
---|
53 | sub timer {...}
|
---|
54 | sub watch {...}
|
---|
55 |
|
---|
56 | =head1 DESCRIPTION
|
---|
57 |
|
---|
58 | L<Mojo::Reactor> is an abstract base class for low-level event reactors, like
|
---|
59 | L<Mojo::Reactor::EV> and L<Mojo::Reactor::Poll>.
|
---|
60 |
|
---|
61 | =head1 EVENTS
|
---|
62 |
|
---|
63 | L<Mojo::Reactor> inherits all events from L<Mojo::EventEmitter> and can emit
|
---|
64 | the following new ones.
|
---|
65 |
|
---|
66 | =head2 error
|
---|
67 |
|
---|
68 | $reactor->on(error => sub {
|
---|
69 | my ($reactor, $err) = @_;
|
---|
70 | ...
|
---|
71 | });
|
---|
72 |
|
---|
73 | Emitted for exceptions caught in callbacks, fatal if unhandled. Note that if
|
---|
74 | this event is unhandled or fails it might kill your program, so you need to be
|
---|
75 | careful.
|
---|
76 |
|
---|
77 | $reactor->on(error => sub {
|
---|
78 | my ($reactor, $err) = @_;
|
---|
79 | say "Something very bad happened: $err";
|
---|
80 | });
|
---|
81 |
|
---|
82 | =head1 METHODS
|
---|
83 |
|
---|
84 | L<Mojo::Reactor> inherits all methods from L<Mojo::EventEmitter> and implements
|
---|
85 | the following new ones.
|
---|
86 |
|
---|
87 | =head2 again
|
---|
88 |
|
---|
89 | $reactor->again($id);
|
---|
90 |
|
---|
91 | Restart timer. Meant to be overloaded in a subclass. Note that this method
|
---|
92 | requires an active timer.
|
---|
93 |
|
---|
94 | =head2 detect
|
---|
95 |
|
---|
96 | my $class = Mojo::Reactor->detect;
|
---|
97 |
|
---|
98 | Detect and load the best reactor implementation available, will try the value
|
---|
99 | of the C<MOJO_REACTOR> environment variable, L<Mojo::Reactor::EV> or
|
---|
100 | L<Mojo::Reactor::Poll>.
|
---|
101 |
|
---|
102 | # Instantiate best reactor implementation available
|
---|
103 | my $reactor = Mojo::Reactor->detect->new;
|
---|
104 |
|
---|
105 | =head2 io
|
---|
106 |
|
---|
107 | $reactor = $reactor->io($handle => sub {...});
|
---|
108 |
|
---|
109 | Watch handle for I/O events, invoking the callback whenever handle becomes
|
---|
110 | readable or writable. Meant to be overloaded in a subclass.
|
---|
111 |
|
---|
112 | # Callback will be executed twice if handle becomes readable and writable
|
---|
113 | $reactor->io($handle => sub {
|
---|
114 | my ($reactor, $writable) = @_;
|
---|
115 | say $writable ? 'Handle is writable' : 'Handle is readable';
|
---|
116 | });
|
---|
117 |
|
---|
118 | =head2 is_running
|
---|
119 |
|
---|
120 | my $bool = $reactor->is_running;
|
---|
121 |
|
---|
122 | Check if reactor is running. Meant to be overloaded in a subclass.
|
---|
123 |
|
---|
124 | =head2 next_tick
|
---|
125 |
|
---|
126 | my $undef = $reactor->next_tick(sub {...});
|
---|
127 |
|
---|
128 | Execute callback as soon as possible, but not before returning or other
|
---|
129 | callbacks that have been registered with this method, always returns C<undef>.
|
---|
130 | Meant to be overloaded in a subclass.
|
---|
131 |
|
---|
132 | =head2 one_tick
|
---|
133 |
|
---|
134 | $reactor->one_tick;
|
---|
135 |
|
---|
136 | Run reactor until an event occurs. Note that this method can recurse back into
|
---|
137 | the reactor, so you need to be careful. Meant to be overloaded in a subclass.
|
---|
138 |
|
---|
139 | # Don't block longer than 0.5 seconds
|
---|
140 | my $id = $reactor->timer(0.5 => sub {});
|
---|
141 | $reactor->one_tick;
|
---|
142 | $reactor->remove($id);
|
---|
143 |
|
---|
144 | =head2 recurring
|
---|
145 |
|
---|
146 | my $id = $reactor->recurring(0.25 => sub {...});
|
---|
147 |
|
---|
148 | Create a new recurring timer, invoking the callback repeatedly after a given
|
---|
149 | amount of time in seconds. Meant to be overloaded in a subclass.
|
---|
150 |
|
---|
151 | =head2 remove
|
---|
152 |
|
---|
153 | my $bool = $reactor->remove($handle);
|
---|
154 | my $bool = $reactor->remove($id);
|
---|
155 |
|
---|
156 | Remove handle or timer. Meant to be overloaded in a subclass.
|
---|
157 |
|
---|
158 | =head2 reset
|
---|
159 |
|
---|
160 | $reactor->reset;
|
---|
161 |
|
---|
162 | Remove all handles and timers. Meant to be overloaded in a subclass.
|
---|
163 |
|
---|
164 | =head2 start
|
---|
165 |
|
---|
166 | $reactor->start;
|
---|
167 |
|
---|
168 | Start watching for I/O and timer events, this will block until L</"stop"> is
|
---|
169 | called. Note that some reactors stop automatically if there are no events being
|
---|
170 | watched anymore. Meant to be overloaded in a subclass.
|
---|
171 |
|
---|
172 | # Start reactor only if it is not running already
|
---|
173 | $reactor->start unless $reactor->is_running;
|
---|
174 |
|
---|
175 | =head2 stop
|
---|
176 |
|
---|
177 | $reactor->stop;
|
---|
178 |
|
---|
179 | Stop watching for I/O and timer events. Meant to be overloaded in a subclass.
|
---|
180 |
|
---|
181 | =head2 timer
|
---|
182 |
|
---|
183 | my $id = $reactor->timer(0.5 => sub {...});
|
---|
184 |
|
---|
185 | Create a new timer, invoking the callback after a given amount of time in
|
---|
186 | seconds. Meant to be overloaded in a subclass.
|
---|
187 |
|
---|
188 | =head2 watch
|
---|
189 |
|
---|
190 | $reactor = $reactor->watch($handle, $readable, $writable);
|
---|
191 |
|
---|
192 | Change I/O events to watch handle for with true and false values. Meant to be
|
---|
193 | overloaded in a subclass. Note that this method requires an active I/O watcher.
|
---|
194 |
|
---|
195 | # Watch only for readable events
|
---|
196 | $reactor->watch($handle, 1, 0);
|
---|
197 |
|
---|
198 | # Watch only for writable events
|
---|
199 | $reactor->watch($handle, 0, 1);
|
---|
200 |
|
---|
201 | # Watch for readable and writable events
|
---|
202 | $reactor->watch($handle, 1, 1);
|
---|
203 |
|
---|
204 | # Pause watching for events
|
---|
205 | $reactor->watch($handle, 0, 0);
|
---|
206 |
|
---|
207 | =head1 SEE ALSO
|
---|
208 |
|
---|
209 | L<Mojolicious>, L<Mojolicious::Guides>, L<https://mojolicious.org>.
|
---|
210 |
|
---|
211 | =cut
|
---|