File Coverage

blib/lib/POE/Loop/Mojo_IOLoop.pm
Criterion Covered Total %
statement 101 109 92.6
branch 26 34 76.4
condition 7 11 63.6
subroutine 22 26 84.6
pod 0 13 0.0
total 156 193 80.8


line stmt bran cond sub pod time code
1 35     35   1061221 use strict;
  35         77  
  35         1122  
2 35     35   203 use warnings;
  35         62  
  35         1849  
3              
4             package POE::Loop::Mojo_IOLoop;
5              
6 35     35   16851 use POE::Loop::PerlSignals;
  35         26918  
  35         1667  
7              
8             our $VERSION = '0.003';
9              
10             =for poe_tests
11             BEGIN { $ENV{POE_EVENT_LOOP} = 'POE::Loop::Mojo_IOLoop' }
12             BEGIN { $ENV{MOJO_REACTOR} ||= 'Mojo::Reactor::Poll' }
13             BEGIN { $ENV{POE_LOOP_USES_POLL} = 1 }
14             use Mojo::IOLoop;
15             sub skip_tests {
16             if ($_[0] eq '00_info') {
17             my $reactor = Mojo::IOLoop->singleton->reactor;
18             diag("Using reactor $reactor");
19             }
20             return undef;
21             }
22              
23             =cut
24              
25             package
26             POE::Kernel;
27              
28 35     35   869 use Mojo::IOLoop;
  35         191698  
  35         596  
29 35     35   829 use Time::HiRes;
  35         51  
  35         321  
30              
31 35   50 35   4012 use constant MOJO_DEBUG => $ENV{POE_LOOP_MOJO_DEBUG} || 0;
  35         51  
  35         42543  
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 51     51 0 742220 my $self = shift;
43            
44 51         486 my $reactor = Mojo::IOLoop->singleton->reactor;
45 51 50       1577 if ($reactor->isa('Mojo::Reactor::EV')) {
46             # Workaround to ensure perl signal handlers are called
47 0     0   0 $_async_check = EV::check(sub { });
48             # EV will ignore exceptions unless this is set
49 0         0 $EV::DIED = \&_die_handler;
50             }
51            
52 51         84 warn "-- Initialized loop with reactor $reactor\n" if MOJO_DEBUG;
53            
54 51 50       283 unless (defined $_idle_id) {
55 51         306 $_idle_id = Mojo::IOLoop->next_tick(\&_loop_resume_timer);
56             }
57             }
58              
59             sub loop_finalize {
60 46     46 0 5645 my $self = shift;
61            
62 46         67 warn "-- Finalized loop\n" if MOJO_DEBUG;
63            
64 46         216 foreach my $fd (0..$#fileno_watcher) {
65 475 50       796 POE::Kernel::_warn(
66             "Filehandle watcher for fileno $fd is defined during loop finalize"
67             ) if defined $fileno_watcher[$fd];
68             }
69            
70 46         225 $self->loop_ignore_all_signals();
71 46         294 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   sub loop_attach_uidestroy {
89             # does nothing
90             }
91              
92             # Maintain time watchers.
93              
94             sub loop_resume_time_watcher {
95 1209     1209 0 805763 my ($self, $next_time) = @_;
96            
97 1209         2925 $next_time -= Time::HiRes::time;
98 1209 100       3209 $next_time = 0 if $next_time < 0;
99            
100 1209         1032 warn "-- Resume time watcher in ${next_time}s\n" if MOJO_DEBUG;
101            
102 1209 100       3355 Mojo::IOLoop->remove($_timer_id) if defined $_timer_id;
103 1209         13991 $_timer_id = Mojo::IOLoop->timer($next_time => \&_loop_event_callback);
104             }
105              
106             sub loop_reset_time_watcher {
107 414     414 0 1790192 my ($self, $next_time) = @_;
108            
109 414         568 warn "-- Reset time watcher to $next_time\n" if MOJO_DEBUG;
110            
111 414 100       2323 Mojo::IOLoop->remove($_timer_id) if defined $_timer_id;
112 414         9825 undef $_timer_id;
113 414         1090 $self->loop_resume_time_watcher($next_time);
114             }
115              
116             sub _loop_resume_timer {
117 438 50   438   33784 Mojo::IOLoop->remove($_idle_id) if defined $_idle_id;
118 438         541 undef $_idle_id;
119 438         1216 $poe_kernel->loop_resume_time_watcher($poe_kernel->get_next_event_time());
120             }
121              
122       197 0   sub loop_pause_time_watcher {
123             # does nothing
124             }
125              
126             # Maintain filehandle watchers.
127              
128             sub loop_watch_filehandle {
129 330     330 0 827210 my ($self, $handle, $mode) = @_;
130 330         783 my $fileno = fileno $handle;
131            
132 330 50       1117 confess "POE::Loop::Mojo_IOLoop does not support MODE_EX" if $mode == MODE_EX;
133 330 50 66     1965 confess "Unknown mode $mode" unless $mode == MODE_RD or $mode == MODE_WR;
134            
135 330         327 warn "-- Watch filehandle $fileno, mode $mode\n" if MOJO_DEBUG;
136            
137             # Set up callback if needed
138 330 100       794 unless (defined $fileno_watcher[$fileno]) {
139             Mojo::IOLoop->singleton->reactor->io($handle => sub {
140 610     610   8337434 my ($reactor, $writable) = @_;
141 610         1190 _loop_select_callback($fileno, $writable);
142 253         2213 });
143             }
144            
145 330         12519 $fileno_watcher[$fileno][$mode] = 1;
146            
147 330         814 _update_select_watcher($handle);
148             }
149              
150             sub loop_ignore_filehandle {
151 294     294 0 300683 my ($self, $handle, $mode) = @_;
152 294         606 my $fileno = fileno $handle;
153            
154 294         306 warn "-- Ignore filehandle $fileno, mode $mode\n" if MOJO_DEBUG;
155            
156 294         512 undef $fileno_watcher[$fileno][$mode];
157            
158 294         714 _update_select_watcher($handle);
159             }
160              
161             sub loop_pause_filehandle {
162 288     288 0 133637 my ($self, $handle, $mode) = @_;
163 288         708 my $fileno = fileno $handle;
164            
165 288         326 warn "-- Pause filehandle $fileno, mode $mode\n" if MOJO_DEBUG;
166            
167 288         470 $fileno_watcher[$fileno][$mode] = 0;
168            
169 288         568 _update_select_watcher($handle);
170             }
171              
172             sub loop_resume_filehandle {
173 248     248 0 294908 my ($self, $handle, $mode) = @_;
174 248         490 my $fileno = fileno $handle;
175            
176 248         269 warn "-- Resume filehandle $fileno, mode $mode\n" if MOJO_DEBUG;
177            
178 248         445 $fileno_watcher[$fileno][$mode] = 1;
179            
180 248         527 _update_select_watcher($handle);
181             }
182              
183             sub _update_select_watcher {
184 1160     1160   1372 my ($handle) = @_;
185 1160         1284 my $fileno = fileno $handle;
186            
187 1160         1119 my ($read, $write) = @{$fileno_watcher[$fileno]}[MODE_RD(),MODE_WR()];
  1160         2200  
188            
189             # Don't remove watcher unless both read and write have been ignored
190 1160 100 100     5108 if (defined $read or defined $write) {
191 939         3165 Mojo::IOLoop->singleton->reactor->watch($handle, $read, $write);
192             } else {
193 221         1312 Mojo::IOLoop->singleton->reactor->remove($handle);
194 221         4278 undef $fileno_watcher[$fileno];
195             }
196             }
197              
198             # Timer callback to dispatch events.
199              
200             sub _loop_event_callback {
201 549     549   18671364 my $self = $poe_kernel;
202            
203 549         622 warn "-- Timer callback\n" if MOJO_DEBUG;
204            
205 549         1937 $self->_data_ev_dispatch_due();
206 549         23622 $self->_test_if_kernel_is_idle();
207            
208 549         96716 undef $_timer_id;
209            
210 549 100       1689 if ($self->get_event_count()) {
211 400         5064 $_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 610     610   680 my $self = $poe_kernel;
221 610         909 my ($fileno, $writable) = @_;
222            
223 610 100       1216 my $mode = $writable ? MODE_WR : MODE_RD;
224            
225             # Make sure this callback is actually registered
226 610 50       1548 return unless defined $fileno_watcher[$fileno];
227            
228             # Workaround for write-only mode receiving read callback
229 610 100       1232 unless ($fileno_watcher[$fileno][$mode]) {
230 37 100 33     168 if ($mode == MODE_RD and $fileno_watcher[$fileno][MODE_WR()]) {
231             # Use write callback
232 1         1 $mode = MODE_WR;
233             } else {
234 36         75 return;
235             }
236             }
237            
238 574         439 warn "-- Select callback for filehandle $fileno, mode $mode\n"
239             if MOJO_DEBUG;
240            
241 574         1651 $self->_data_handle_enqueue_ready($mode, $fileno);
242 574         576803 $self->_test_if_kernel_is_idle();
243             }
244              
245             # The event loop itself.
246              
247       0 0   sub loop_do_timeslice {
248             }
249              
250             sub loop_run {
251 46     46 0 4187997 warn "-- Loop run\n" if MOJO_DEBUG;
252 46         408 Mojo::IOLoop->start;
253            
254 46 50       1720 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 46     46 0 277778 warn "-- Loop halt\n" if MOJO_DEBUG;
263 46         313 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;