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   57985625 use warnings;
  137         531  
  137         11411  
7 137     137   882 use strict;
  137         304  
  137         3945  
8 137     137   71782 use POE::Loop::PerlSignals;
  137         154325  
  137         5421  
9 137     137   2230 use EV;
  137         449  
  137         252533  
10              
11             our $VERSION = '0.15';
12              
13             my %methods;
14             sub _backend_name {
15 1 50   1   251838 return undef unless defined( my $backend = shift );
16 1 50       17 %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 12933 50   12933 0 100537 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 4522810 my $self = shift;
73            
74 201 50       801 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         8267 $_watcher_timer = EV::periodic( 0, 0, 0, \&_loop_timer_callback );
81            
82             # Workaround so perl signals are handled
83 201     2672   1879 $_async_watcher = EV::check(sub { });
84            
85 201         1660 $EV::DIED = \&_die_handler;
86             }
87              
88             # Timer callback to dispatch events.
89             sub _loop_timer_callback {
90 1849     1849   4527 my $self = $poe_kernel;
91            
92 1849 50       6800 EV_DEBUG && warn "_loop_timer_callback, at " . time() . "\n";
93              
94 1849         10444 $self->_data_ev_dispatch_due();
95 1849         14688 $self->_test_if_kernel_is_idle();
96              
97             # Transferring control back to EV; this is idle time.
98             }
99              
100             sub loop_finalize {
101 184     184 0 27346 my $self = shift;
102            
103 184 50       925 EV_DEBUG && warn "loop_finalize\n";
104            
105 184         1195 foreach my $fd ( 0 .. $#fileno_watcher ) {
106 2929 100       5746 next unless defined $fileno_watcher[ $fd ];
107 817         1693 foreach my $mode ( EV::READ, EV::WRITE ) {
108 1634 50       3918 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 184         1175 $self->loop_ignore_all_signals();
117 184         3864 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 23549046 EV_DEBUG && warn "loop_run\n";
130            
131 184         7241 EV::run();
132            
133 184 50       34447 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 184 50   184 0 1292386 EV_DEBUG && warn "loop_halt\n";
142            
143 184         1185 $_watcher_timer->stop();
144 184         395 undef $_watcher_timer;
145            
146 184         885 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 1464     1464 0 4178932 my ( $self, $next_time ) = @_;
167 1464 50 33     11246 ( $_watcher_timer and $next_time ) or return;
168            
169 1464 50       6179 EV_DEBUG && warn "loop_resume_time_watcher( $next_time, in " . ( $next_time - time() ) . " )\n";
170              
171 1464         8998 $_watcher_timer->set($next_time);
172 1464         6001 $_watcher_timer->start();
173             }
174              
175             sub loop_reset_time_watcher {
176 1477     1477 0 7837759 my ( $self, $next_time ) = @_;
177 1477 50 33     11453 ( $_watcher_timer and $next_time ) or return;
178            
179 1477 50       4400 EV_DEBUG && warn "loop_reset_time_watcher( $next_time, in " . ( $next_time - time() ) . " )\n";
180            
181 1477         8274 $_watcher_timer->set($next_time);
182 1477         6364 $_watcher_timer->start();
183             }
184              
185             sub loop_pause_time_watcher {
186 653 100   653 0 3146902 $_watcher_timer or return;
187            
188 469 50       1731 EV_DEBUG && warn "loop_pause_time_watcher()\n";
189            
190 469         2907 $_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   9713 return EV::READ if $_[0] == MODE_RD;
200 556 50       13415 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 6224939 my ( $self, $handle, $mode ) = @_;
210              
211 1317         5625 my $fileno = fileno($handle);
212 1317         5780 my $watcher = $fileno_watcher[ $fileno ]->[ $mode ];
213              
214 1317 50       5749 if ( defined $watcher ) {
215 0         0 $watcher->stop();
216 0         0 undef $fileno_watcher[ $fileno ]->[ $mode ];
217             }
218            
219 1317 50       6012 EV_DEBUG && warn "loop_watch_filehandle( $handle ($fileno), $mode )\n";
220              
221 1317         5732 $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 1176     1176 0 1723008 my ( $self, $handle, $mode ) = @_;
230              
231 1176         3371 my $fileno = fileno($handle);
232 1176         3049 my $watcher = $fileno_watcher[ $fileno ]->[ $mode ];
233              
234 1176 50       4623 return if !defined $watcher;
235            
236 1176 50       14017 EV_DEBUG && warn "loop_ignore_filehandle( $handle ($fileno), $mode )\n";
237              
238 1176         8378 $watcher->stop();
239            
240 1176         6619 undef $fileno_watcher[ $fileno ]->[ $mode ];
241             }
242              
243             sub loop_pause_filehandle {
244 1145     1145 0 1165623 my ( $self, $handle, $mode ) = @_;
245              
246 1145         2569 my $fileno = fileno($handle);
247              
248 1145         5874 $fileno_watcher[ $fileno ]->[ $mode ]->stop();
249            
250 1145 50       2858 EV_DEBUG && warn "loop_pause_filehandle( $handle ($fileno), $mode )\n";
251             }
252              
253             sub loop_resume_filehandle {
254 988     988 0 2749128 my ( $self, $handle, $mode ) = @_;
255              
256 988         2377 my $fileno = fileno($handle);
257            
258 988         5375 $fileno_watcher[ $fileno ]->[ $mode ]->start();
259            
260 988 50       2384 EV_DEBUG && warn "loop_resume_filehandle( $handle ($fileno), $mode )\n";
261             }
262              
263             sub _loop_filehandle_callback {
264 2295     2295   164246 my ( $watcher, $ev_mode ) = @_;
265            
266 2295 50       6195 EV_DEBUG && warn "_loop_filehandle_callback( " . $watcher->fh . ", $ev_mode )\n";
267              
268 2295 50       8155 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 2295         16660 $poe_kernel->_data_handle_enqueue_ready( $mode, $watcher->fh );
276            
277 2295         2863694 $poe_kernel->_test_if_kernel_is_idle();
278             }
279              
280             1;
281              
282             __END__