File Coverage

blib/lib/POE/Loop/EV.pm
Criterion Covered Total %
statement 81 94 86.1
branch 32 60 53.3
condition 2 6 33.3
subroutine 21 24 87.5
pod 0 14 0.0
total 136 198 68.6


line stmt bran cond sub pod time code
1             package POE::Loop::EV;
2              
3             # EV.pm (libev) event loop bridge
4             # $Id: EV.pm 27 2008-01-29 19:42:57Z andyg $
5              
6 137     137   5592426 use warnings;
  137         246  
  137         4834  
7 137     137   487 use strict;
  137         188  
  137         2226  
8 137     137   51136 use POE::Loop::PerlSignals;
  137         76601  
  137         3184  
9 137     137   948 use EV;
  137         163  
  137         119930  
10              
11             our $VERSION = '0.14';
12              
13             my %methods;
14             sub _backend_name {
15 1 50   1   513 return undef unless defined( my $backend = shift );
16 1 50       13 %methods = (
17             EV::BACKEND_SELECT() => 'select',
18             EV::BACKEND_POLL() => 'poll',
19             EV::BACKEND_EPOLL() => 'epoll',
20             EV::BACKEND_KQUEUE() => 'kqueue',
21             EV::BACKEND_DEVPOLL() => 'devpoll',
22             EV::BACKEND_PORT() => 'port',
23             ) unless keys %methods;
24 1         3 return $methods{ $backend };
25             }
26              
27             =for poe_tests
28             use EV;
29             BEGIN { $ENV{POE_EVENT_LOOP} = 'POE::Loop::EV'; $ENV{POE_LOOP_USES_POLL} = 1 if EV::backend() == EV::BACKEND_POLL(); }
30             sub skip_tests {
31             return "wheel_readwrite test disabled for 'kqueue'"
32             if EV::backend() == EV::BACKEND_KQUEUE() && $_[0] eq 'wheel_readwrite';
33             if ($_[0] eq '00_info') {
34             my %methods = ( # duplicated for generated tests
35             EV::BACKEND_SELECT() => 'select',
36             EV::BACKEND_POLL() => 'poll',
37             EV::BACKEND_EPOLL() => 'epoll',
38             EV::BACKEND_KQUEUE() => 'kqueue',
39             EV::BACKEND_DEVPOLL() => 'devpoll',
40             EV::BACKEND_PORT() => 'port',
41             );
42             my $method = $methods{ EV::backend() };
43             diag("Using default EV backend '$method'");
44             }
45             return undef;
46             }
47              
48             =cut
49              
50             # Everything plugs into POE::Kernel.
51             package # hide me from PAUSE
52             POE::Kernel;
53              
54             # Loop debugging
55 12828 50   12828 0 65373 sub EV_DEBUG () { $ENV{POE_EV_DEBUG} || 0 }
56              
57             # Global EV timer object
58             my $_watcher_timer;
59              
60             # Global list of EV filehandle objects, indexed by fd number
61             my @fileno_watcher;
62              
63             my $_async_watcher;
64              
65             my $DIE_MESSAGE;
66              
67             ############################################################################
68             # Initialization, Finalization, and the Loop itself
69             ############################################################################
70              
71             sub loop_initialize {
72 201     201 0 3426128 my $self = shift;
73            
74 201 50       536 if ( EV_DEBUG ) {
75 0         0 my $method = POE::Loop::EV::_backend_name( EV::backend() );
76 0         0 warn "loop_initialize, EV is using method: $method\n";
77             }
78              
79             # Set up the global timer object
80 201         2477 $_watcher_timer = EV::periodic( 0, 0, 0, \&_loop_timer_callback );
81            
82             # Workaround so perl signals are handled
83 201     2630   1349 $_async_watcher = EV::check(sub { });
84            
85 201         589 $EV::DIED = \&_die_handler;
86             }
87              
88             # Timer callback to dispatch events.
89             sub _loop_timer_callback {
90 1830     1830   3413 my $self = $poe_kernel;
91            
92 1830 50       3656 EV_DEBUG && warn "_loop_timer_callback, at " . time() . "\n";
93              
94 1830         7148 $self->_data_ev_dispatch_due();
95 1829         5835 $self->_test_if_kernel_is_idle();
96              
97             # Transferring control back to EV; this is idle time.
98             }
99              
100             sub loop_finalize {
101 183     183 0 17028 my $self = shift;
102            
103 183 50       419 EV_DEBUG && warn "loop_finalize\n";
104            
105 183         864 foreach my $fd ( 0 .. $#fileno_watcher ) {
106 2234 100       3414 next unless defined $fileno_watcher[ $fd ];
107 787         863 foreach my $mode ( EV::READ, EV::WRITE ) {
108 1574 50       2605 if ( defined $fileno_watcher[ $fd ]->[ $mode ] ) {
109 0         0 POE::Kernel::_warn(
110             "Mode $mode watcher for fileno $fd is defined during loop finalize"
111             );
112             }
113             }
114             }
115            
116 183         698 $self->loop_ignore_all_signals();
117 183         2351 undef $_async_watcher;
118             }
119              
120       0 0   sub loop_attach_uidestroy {
121             # does nothing, no UI
122             }
123              
124       0 0   sub loop_do_timeslice {
125             # does nothing
126             }
127              
128             sub loop_run {
129 184 50   184 0 16173817 EV_DEBUG && warn "loop_run\n";
130            
131 184         131773 EV::run();
132            
133 183 50       17582 if ( defined $DIE_MESSAGE ) {
134 0         0 my $message = $DIE_MESSAGE;
135 0         0 undef $DIE_MESSAGE;
136 0         0 die $message;
137             }
138             }
139              
140             sub loop_halt {
141 183 50   183 0 939219 EV_DEBUG && warn "loop_halt\n";
142            
143 183         679 $_watcher_timer->stop();
144 183         287 undef $_watcher_timer;
145            
146 183         667 EV::break();
147             }
148              
149             sub _die_handler {
150 0 0   0   0 EV_DEBUG && warn "_die_handler( $@ )\n";
151            
152             # EV doesn't let you rethrow an error here, so we have
153             # to stop the loop and get the error later
154 0         0 $DIE_MESSAGE = $@;
155            
156             # This will cause the EV::run call in loop_run to return,
157             # and cause the process to die.
158 0         0 EV::break();
159             }
160              
161             ############################################################################
162             # Timer code
163             ############################################################################
164              
165             sub loop_resume_time_watcher {
166 1452     1452 0 2675044 my ( $self, $next_time ) = @_;
167 1452 50 33     8671 ( $_watcher_timer and $next_time ) or return;
168            
169 1452 50       2208 EV_DEBUG && warn "loop_resume_time_watcher( $next_time, in " . ( $next_time - time() ) . " )\n";
170              
171 1452         4610 $_watcher_timer->set($next_time);
172 1452         4009 $_watcher_timer->start();
173             }
174              
175             sub loop_reset_time_watcher {
176 1444     1444 0 4914912 my ( $self, $next_time ) = @_;
177 1444 50 33     7765 ( $_watcher_timer and $next_time ) or return;
178            
179 1444 50       2332 EV_DEBUG && warn "loop_reset_time_watcher( $next_time, in " . ( $next_time - time() ) . " )\n";
180            
181 1444         4441 $_watcher_timer->set($next_time);
182 1444         3653 $_watcher_timer->start();
183             }
184              
185             sub loop_pause_time_watcher {
186 640 100   640 0 1752690 $_watcher_timer or return;
187            
188 457 50       1011 EV_DEBUG && warn "loop_pause_time_watcher()\n";
189            
190 457         1627 $_watcher_timer->stop();
191             }
192              
193             ############################################################################
194             # Filehandle code
195             ############################################################################
196              
197             # helper function, not a method
198             sub _mode_to_ev {
199 1317 100   1317   6376 return EV::READ if $_[0] == MODE_RD;
200 556 50       4822 return EV::WRITE if $_[0] == MODE_WR;
201              
202 0 0       0 confess "POE::Loop::EV does not support MODE_EX"
203             if $_[0] == MODE_EX;
204              
205 0         0 confess "Unknown mode $_[0]";
206             }
207              
208             sub loop_watch_filehandle {
209 1317     1317 0 2338782 my ( $self, $handle, $mode ) = @_;
210              
211 1317         2616 my $fileno = fileno($handle);
212 1317         2574 my $watcher = $fileno_watcher[ $fileno ]->[ $mode ];
213              
214 1317 50       4141 if ( defined $watcher ) {
215 0         0 $watcher->stop();
216 0         0 undef $fileno_watcher[ $fileno ]->[ $mode ];
217             }
218            
219 1317 50       2497 EV_DEBUG && warn "loop_watch_filehandle( $handle ($fileno), $mode )\n";
220              
221 1317         2287 $fileno_watcher[ $fileno ]->[ $mode ] = EV::io(
222             $fileno,
223             _mode_to_ev($mode),
224             \&_loop_filehandle_callback,
225             );
226             }
227              
228             sub loop_ignore_filehandle {
229 1173     1173 0 776784 my ( $self, $handle, $mode ) = @_;
230              
231 1173         1810 my $fileno = fileno($handle);
232 1173         1557 my $watcher = $fileno_watcher[ $fileno ]->[ $mode ];
233              
234 1173 50       2731 return if !defined $watcher;
235            
236 1173 50       1896 EV_DEBUG && warn "loop_ignore_filehandle( $handle ($fileno), $mode )\n";
237              
238 1173         3690 $watcher->stop();
239            
240 1173         4114 undef $fileno_watcher[ $fileno ]->[ $mode ];
241             }
242              
243             sub loop_pause_filehandle {
244 1143     1143 0 325012 my ( $self, $handle, $mode ) = @_;
245              
246 1143         1551 my $fileno = fileno($handle);
247              
248 1143         2996 $fileno_watcher[ $fileno ]->[ $mode ]->stop();
249            
250 1143 50       1463 EV_DEBUG && warn "loop_pause_filehandle( $handle ($fileno), $mode )\n";
251             }
252              
253             sub loop_resume_filehandle {
254 988     988 0 697382 my ( $self, $handle, $mode ) = @_;
255              
256 988         1358 my $fileno = fileno($handle);
257            
258 988         2743 $fileno_watcher[ $fileno ]->[ $mode ]->start();
259            
260 988 50       1296 EV_DEBUG && warn "loop_resume_filehandle( $handle ($fileno), $mode )\n";
261             }
262              
263             sub _loop_filehandle_callback {
264 2273     2273   84215 my ( $watcher, $ev_mode ) = @_;
265            
266 2273 50       3860 EV_DEBUG && warn "_loop_filehandle_callback( " . $watcher->fh . ", $ev_mode )\n";
267              
268 2273 50       5299 my $mode = ( $ev_mode == EV::READ )
    100          
269             ? MODE_RD
270             : ( $ev_mode == EV::WRITE )
271             ? MODE_WR
272             : confess "Invalid mode occured in POE::Loop::EV IO callback: $ev_mode";
273              
274             # ->fh is actually the fileno, since that's what we called EV::io with
275 2273         8676 $poe_kernel->_data_handle_enqueue_ready( $mode, $watcher->fh );
276            
277 2273         1494300 $poe_kernel->_test_if_kernel_is_idle();
278             }
279              
280             1;
281              
282             __END__