File Coverage

blib/lib/POE/Loop/Mojo_IOLoop.pm
Criterion Covered Total %
statement 101 113 89.3
branch 25 34 73.5
condition 7 11 63.6
subroutine 22 26 84.6
pod 0 13 0.0
total 155 197 78.6


line stmt bran cond sub pod time code
1 33     33   939957 use strict;
  33         93  
  33         1394  
2              
3             package POE::Loop::Mojo_IOLoop;
4              
5 33     33   15086 use POE::Loop::PerlSignals;
  33         21439  
  33         1380  
6              
7             our $VERSION = '0.001';
8              
9             =for poe_tests
10             BEGIN { $ENV{POE_EVENT_LOOP} = 'POE::Loop::Mojo_IOLoop' }
11             BEGIN { $ENV{MOJO_REACTOR} ||= 'Mojo::Reactor::Poll' }
12             sub skip_tests {
13             return "Mojo::IOLoop tests require the Mojo::IOLoop module" if (
14             do { eval "use Mojo::IOLoop"; $@ }
15             );
16             if (shift eq '00_info') {
17             my $reactor = Mojo::IOLoop->singleton->reactor;
18             diag("Using reactor $reactor");
19             }
20             }
21              
22             =cut
23              
24             package
25             POE::Kernel;
26              
27 33     33   625 use Mojo::IOLoop;
  33         102072  
  33         465  
28 33     33   644 use Time::HiRes;
  33         44  
  33         270  
29 33     33   3314 use Scalar::Util;
  33         49  
  33         1770  
30              
31 33   50 33   137 use constant MOJO_DEBUG => $ENV{POE_LOOP_MOJO_DEBUG} || 0;
  33         41  
  33         36399  
32              
33             my $_timer_id;
34             my $_idle_id;
35             my @fileno_watcher;
36             my $_async_check;
37             my $DIE_MESSAGE;
38              
39             # Loop construction and destruction.
40              
41             sub loop_initialize {
42 49     49 0 744252 my $self = shift;
43            
44 49         423 my $class = Scalar::Util::blessed(Mojo::IOLoop->singleton->reactor);
45 49 50       2172 if ($class eq 'Mojo::Reactor::EV') {
46             # Workaround to ensure perl signal handlers are called
47 0     0   0 $_async_check = EV::check(sub { });
  0         0  
48             # EV will ignore exceptions unless this is set
49 0         0 $EV::DIED = \&_die_handler;
50             }
51            
52 49         75 warn "-- Initialized loop with reactor $class\n" if MOJO_DEBUG;
53            
54 49 50       282 unless (defined $_idle_id) {
55 49         336 $_idle_id = Mojo::IOLoop->next_tick(\&_loop_resume_timer);
56             }
57             }
58              
59             sub loop_finalize {
60 45     45 0 4169 my $self = shift;
61            
62 45         74 warn "-- Finalized loop\n" if MOJO_DEBUG;
63            
64 45         177 foreach my $fd (0..$#fileno_watcher) {
65 474 50       839 POE::Kernel::_warn(
66             "Filehandle watcher for fileno $fd is defined during loop finalize"
67             ) if defined $fileno_watcher[$fd];
68             }
69            
70 45         214 $self->loop_ignore_all_signals();
71 45         289 undef $_async_check;
72             }
73              
74             sub _die_handler {
75 0     0   0 warn "-- Died $@\n" if MOJO_DEBUG;
76            
77             # EV doesn't let you rethrow an error here, so we have
78             # to stop the loop and get the error later
79 0         0 $DIE_MESSAGE = $@;
80            
81             # This will cause the EV::run call in loop_run to return,
82             # and cause the process to die.
83 0         0 EV::break();
84             }
85              
86             # Signal handler maintenance functions.
87              
88 0     0 0 0 sub loop_attach_uidestroy {
89             # does nothing
90             }
91              
92             # Maintain time watchers.
93              
94             sub loop_resume_time_watcher {
95 1210     1210 0 720942 my ($self, $next_time) = @_;
96            
97 1210         2836 $next_time -= Time::HiRes::time;
98 1210 100       2846 $next_time = 0 if $next_time < 0;
99            
100 1210         1074 warn "-- Resume time watcher in ${next_time}s\n" if MOJO_DEBUG;
101            
102 1210 100       3041 Mojo::IOLoop->remove($_timer_id) if defined $_timer_id;
103 1210         21426 $_timer_id = Mojo::IOLoop->timer($next_time => \&_loop_event_callback);
104             }
105              
106             sub loop_reset_time_watcher {
107 415     415 0 1418163 my ($self, $next_time) = @_;
108            
109 415         502 warn "-- Reset time watcher to $next_time\n" if MOJO_DEBUG;
110            
111 415 100       2177 Mojo::IOLoop->remove($_timer_id) if defined $_timer_id;
112 415         17108 undef $_timer_id;
113 415         1011 $self->loop_resume_time_watcher($next_time);
114             }
115              
116             sub _loop_resume_timer {
117 441 50   441   49073 Mojo::IOLoop->remove($_idle_id) if defined $_idle_id;
118 441         542 undef $_idle_id;
119 441         1356 $poe_kernel->loop_resume_time_watcher($poe_kernel->get_next_event_time());
120             }
121              
122 198     198 0 471413 sub loop_pause_time_watcher {
123             # does nothing
124             }
125              
126             # Maintain filehandle watchers.
127              
128             sub loop_watch_filehandle {
129 264     264 0 561927 my ($self, $handle, $mode) = @_;
130 264         625 my $fileno = fileno $handle;
131            
132 264 50       839 confess "POE::Loop::Mojo_IOLoop does not support MODE_EX" if $mode == MODE_EX;
133 264 50 66     1249 confess "Unknown mode $mode" unless $mode == MODE_RD or $mode == MODE_WR;
134            
135 264         253 warn "-- Watch filehandle $fileno, mode $mode\n" if MOJO_DEBUG;
136            
137             # Set up callback if needed
138 264 100       620 unless (defined $fileno_watcher[$fileno]) {
139             Mojo::IOLoop->singleton->reactor->io($handle => sub {
140 486     486   8251291 my ($reactor, $writable) = @_;
141 486         1024 _loop_select_callback($fileno, $writable);
142 195         1345 });
143             }
144            
145 264         18570 $fileno_watcher[$fileno][$mode] = 1;
146            
147 264         692 _update_select_watcher($handle);
148             }
149              
150             sub loop_ignore_filehandle {
151 260     260 0 212183 my ($self, $handle, $mode) = @_;
152 260         477 my $fileno = fileno $handle;
153            
154 260         295 warn "-- Ignore filehandle $fileno, mode $mode\n" if MOJO_DEBUG;
155            
156 260         446 undef $fileno_watcher[$fileno][$mode];
157            
158 260         523 _update_select_watcher($handle);
159             }
160              
161             sub loop_pause_filehandle {
162 229     229 0 51608 my ($self, $handle, $mode) = @_;
163 229         404 my $fileno = fileno $handle;
164            
165 229         246 warn "-- Pause filehandle $fileno, mode $mode\n" if MOJO_DEBUG;
166            
167 229         363 $fileno_watcher[$fileno][$mode] = 0;
168            
169 229         434 _update_select_watcher($handle);
170             }
171              
172             sub loop_resume_filehandle {
173 198     198 0 140913 my ($self, $handle, $mode) = @_;
174 198         431 my $fileno = fileno $handle;
175            
176 198         203 warn "-- Resume filehandle $fileno, mode $mode\n" if MOJO_DEBUG;
177            
178 198         356 $fileno_watcher[$fileno][$mode] = 1;
179            
180 198         406 _update_select_watcher($handle);
181             }
182              
183             sub _update_select_watcher {
184 951     951   1109 my ($handle) = @_;
185 951         1227 my $fileno = fileno $handle;
186            
187 951         1035 my ($read, $write) = @{$fileno_watcher[$fileno]}[MODE_RD(),MODE_WR()];
  951         1715  
188            
189             # Don't remove watcher unless both read and write have been ignored
190 951 100 100     3615 if (defined $read or defined $write) {
191 760         2369 Mojo::IOLoop->singleton->reactor->watch($handle, $read, $write);
192             } else {
193 191         1102 Mojo::IOLoop->singleton->reactor->remove($handle);
194 191         12631 undef $fileno_watcher[$fileno];
195             }
196             }
197              
198             # Timer callback to dispatch events.
199              
200             sub _loop_event_callback {
201 559     559   18792967 my $self = $poe_kernel;
202            
203 559         612 warn "-- Timer callback\n" if MOJO_DEBUG;
204            
205 559         1822 $self->_data_ev_dispatch_due();
206 559         28838 $self->_test_if_kernel_is_idle();
207            
208 559         89696 undef $_timer_id;
209            
210 559 100       1740 if ($self->get_event_count()) {
211 407         3653 $_idle_id = Mojo::IOLoop->next_tick(\&_loop_resume_timer);
212             }
213            
214             # Transferring control back to Mojo::IOLoop; this is idle time.
215             }
216              
217             # Mojo::IOLoop filehandle callback to dispatch selects.
218              
219             sub _loop_select_callback {
220 486     486   586 my $self = $poe_kernel;
221 486         797 my ($fileno, $writable) = @_;
222            
223 486 100       1024 my $mode = $writable ? MODE_WR : MODE_RD;
224            
225             # Make sure this callback is actually registered
226 486 50       1161 return unless defined $fileno_watcher[$fileno];
227            
228             # Workaround for write-only mode receiving read callback
229 486 100       1109 unless ($fileno_watcher[$fileno][$mode]) {
230 1 50 33     7 if ($mode == MODE_RD and $fileno_watcher[$fileno][MODE_WR()]) {
231             # Use write callback
232 1         2 $mode = MODE_WR;
233             } else {
234 0         0 return;
235             }
236             }
237            
238 486         424 warn "-- Select callback for filehandle $fileno, mode $mode\n"
239             if MOJO_DEBUG;
240            
241 486         1440 $self->_data_handle_enqueue_ready($mode, $fileno);
242 486         431954 $self->_test_if_kernel_is_idle();
243             }
244              
245             # The event loop itself.
246              
247 0     0 0 0 sub loop_do_timeslice {
248             }
249              
250             sub loop_run {
251 45     45 0 4708985 warn "-- Loop run\n" if MOJO_DEBUG;
252 45         352 Mojo::IOLoop->start;
253            
254 45 50       2201 if (defined $DIE_MESSAGE) {
255 0         0 my $message = $DIE_MESSAGE;
256 0         0 undef $DIE_MESSAGE;
257 0         0 die $message;
258             }
259             }
260              
261             sub loop_halt {
262 45     45 0 280598 warn "-- Loop halt\n" if MOJO_DEBUG;
263 45         272 Mojo::IOLoop->stop;
264             }
265              
266             =head1 NAME
267              
268             POE::Loop::Mojo_IOLoop - a bridge that allows POE to be driven by Mojo::IOLoop
269              
270             =head1 SYNOPSIS
271              
272             See L.
273              
274             use POE qw(Loop::Mojo_IOLoop);
275            
276             use POE::Kernel { loop => Mojo::IOLoop };
277            
278             BEGIN { $ENV{POE_EVENT_LOOP} = 'POE::Loop::Mojo_IOLoop' }
279             use POE;
280              
281             =head1 DESCRIPTION
282              
283             L implements the interface documented in L.
284             Therefore it has no documentation of its own. Please see L for more
285             details.
286              
287             When using L with L, the loop must be set explicitly or
288             L will detect multiple event loops and fail. You can set the event loop
289             by setting the environment variable C to
290             C before L is loaded, or by including it in the
291             C directive when initially loading L. See
292             L for more information.
293              
294             =head1 BUGS
295              
296             Report any issues on the public bugtracker.
297              
298             =head1 AUTHOR
299              
300             Dan Book, C
301              
302             =head1 COPYRIGHT AND LICENSE
303              
304             Copyright 2015, Dan Book.
305              
306             This library is free software; you may redistribute it and/or modify it under
307             the terms of the Artistic License version 2.0.
308              
309             =head1 SEE ALSO
310              
311             L, L, L, L
312              
313             =cut
314              
315             1;