File Coverage

blib/lib/POE/Loop/EV.pm
Criterion Covered Total %
statement 76 91 83.5
branch 30 56 53.5
condition 2 6 33.3
subroutine 19 22 86.3
pod 0 14 0.0
total 127 189 67.2


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 130     130   8746227 use strict;
  130         299  
  130         5444  
7 130     130   59648 use POE::Loop::PerlSignals;
  130         95917  
  130         5845  
8              
9             our $VERSION = '0.12';
10              
11             =for poe_tests
12             sub skip_tests {
13             return "EV tests require the EV module" if (
14             do { eval "use EV"; $@ }
15             );
16             return "wheel_readwrite test disabled for kqueue"
17             if EV::backend() == EV::BACKEND_KQUEUE() && $_[0] eq 'wheel_readwrite';
18             }
19              
20             =cut
21              
22             # Everything plugs into POE::Kernel.
23             package # hide me from PAUSE
24             POE::Kernel;
25              
26 130     130   1131 use EV;
  130         202  
  130         131404  
27              
28             # Loop debugging
29 11602 50   11602 0 71293 sub EV_DEBUG () { $ENV{POE_EV_DEBUG} || 0 }
30              
31             # Global EV timer object
32             my $_watcher_timer;
33              
34             # Global list of EV filehandle objects, indexed by fd number
35             my @fileno_watcher;
36              
37             my $_async_watcher;
38              
39             my $DIE_MESSAGE;
40              
41             ############################################################################
42             # Initialization, Finalization, and the Loop itself
43             ############################################################################
44              
45             sub loop_initialize {
46 194     194 0 3074329 my $self = shift;
47            
48 194 50       711 if ( EV_DEBUG ) {
49 0         0 my $methods = {
50             EV::BACKEND_SELECT() => 'select',
51             EV::BACKEND_POLL() => 'poll',
52             EV::BACKEND_EPOLL() => 'epoll',
53             EV::BACKEND_KQUEUE() => 'kqueue',
54             EV::BACKEND_DEVPOLL() => 'devpoll',
55             EV::BACKEND_PORT() => 'port',
56             };
57            
58 0         0 warn "loop_initialize, EV is using method: " . $methods->{ EV::backend() } . "\n";
59             }
60              
61             # Set up the global timer object
62 194         2723 $_watcher_timer = EV::periodic( 0, 0, 0, \&_loop_timer_callback );
63            
64             # Workaround so perl signals are handled
65 194     2587   1354 $_async_watcher = EV::check(sub { });
  2587         109040576  
66            
67 194         811 $EV::DIED = \&_die_handler;
68             }
69              
70             # Timer callback to dispatch events.
71             sub _loop_timer_callback {
72 1795     1795   4227 my $self = $poe_kernel;
73            
74 1795 50       4460 EV_DEBUG && warn "_loop_timer_callback, at " . time() . "\n";
75              
76 1795         8410 $self->_data_ev_dispatch_due();
77 1795         6027 $self->_test_if_kernel_is_idle();
78              
79             # Transferring control back to EV; this is idle time.
80             }
81              
82             sub loop_finalize {
83 180     180 0 21260 my $self = shift;
84            
85 180 50       1158 EV_DEBUG && warn "loop_finalize\n";
86            
87 180         807 foreach my $fd ( 0 .. $#fileno_watcher ) {
88 2103 100       3613 next unless defined $fileno_watcher[ $fd ];
89 697         976 foreach my $mode ( EV::READ, EV::WRITE ) {
90 1394 50       3354 if ( defined $fileno_watcher[ $fd ]->[ $mode ] ) {
91 0         0 POE::Kernel::_warn(
92             "Mode $mode watcher for fileno $fd is defined during loop finalize"
93             );
94             }
95             }
96             }
97            
98 180         1069 $self->loop_ignore_all_signals();
99 180         1307 undef $_async_watcher;
100             }
101              
102 0     0 0 0 sub loop_attach_uidestroy {
103             # does nothing, no UI
104             }
105              
106 0     0 0 0 sub loop_do_timeslice {
107             # does nothing
108             }
109              
110             sub loop_run {
111 180 50   180 0 19281767 EV_DEBUG && warn "loop_run\n";
112            
113 180         137683 EV::run();
114            
115 180 50       21341 if ( defined $DIE_MESSAGE ) {
116 0         0 my $message = $DIE_MESSAGE;
117 0         0 undef $DIE_MESSAGE;
118 0         0 die $message;
119             }
120             }
121              
122             sub loop_halt {
123 180 50   180 0 1231779 EV_DEBUG && warn "loop_halt\n";
124            
125 180         1255 $_watcher_timer->stop();
126 180         334 undef $_watcher_timer;
127            
128 180         727 EV::break();
129             }
130              
131             sub _die_handler {
132 0 0   0   0 EV_DEBUG && warn "_die_handler( $@ )\n";
133            
134             # EV doesn't let you rethrow an error here, so we have
135             # to stop the loop and get the error later
136 0         0 $DIE_MESSAGE = $@;
137            
138             # This will cause the EV::run call in loop_run to return,
139             # and cause the process to die.
140 0         0 EV::break();
141             }
142              
143             ############################################################################
144             # Timer code
145             ############################################################################
146              
147             sub loop_resume_time_watcher {
148 1440     1440 0 3222397 my ( $self, $next_time ) = @_;
149 1440 50 33     9736 ( $_watcher_timer and $next_time ) or return;
150            
151 1440 50       2813 EV_DEBUG && warn "loop_resume_time_watcher( $next_time, in " . ( $next_time - time() ) . " )\n";
152              
153 1440         5550 $_watcher_timer->set($next_time);
154 1440         5039 $_watcher_timer->start();
155             }
156              
157             sub loop_reset_time_watcher {
158 1391     1391 0 5938906 my ( $self, $next_time ) = @_;
159 1391 50 33     9264 ( $_watcher_timer and $next_time ) or return;
160            
161 1391 50       3265 EV_DEBUG && warn "loop_reset_time_watcher( $next_time, in " . ( $next_time - time() ) . " )\n";
162            
163 1391         4811 $_watcher_timer->set($next_time);
164 1391         4605 $_watcher_timer->start();
165             }
166              
167             sub loop_pause_time_watcher {
168 634 100   634 0 2262998 $_watcher_timer or return;
169            
170 454 50       1310 EV_DEBUG && warn "loop_pause_time_watcher()\n";
171            
172 454         1948 $_watcher_timer->stop();
173             }
174              
175             ############################################################################
176             # Filehandle code
177             ############################################################################
178              
179             # helper function, not a method
180             sub _mode_to_ev {
181 1085 100   1085   7152 return EV::READ if $_[0] == MODE_RD;
182 475 50       5073 return EV::WRITE if $_[0] == MODE_WR;
183              
184 0 0       0 confess "POE::Loop::EV does not support MODE_EX"
185             if $_[0] == MODE_EX;
186              
187 0         0 confess "Unknown mode $_[0]";
188             }
189              
190             sub loop_watch_filehandle {
191 1085     1085 0 2411219 my ( $self, $handle, $mode ) = @_;
192              
193 1085         2377 my $fileno = fileno($handle);
194 1085         2713 my $watcher = $fileno_watcher[ $fileno ]->[ $mode ];
195              
196 1085 50       4034 if ( defined $watcher ) {
197 0         0 $watcher->stop();
198 0         0 undef $fileno_watcher[ $fileno ]->[ $mode ];
199             }
200            
201 1085 50       2459 EV_DEBUG && warn "loop_watch_filehandle( $handle ($fileno), $mode )\n";
202              
203 1085         2594 $fileno_watcher[ $fileno ]->[ $mode ] = EV::io(
204             $fileno,
205             _mode_to_ev($mode),
206             \&_loop_filehandle_callback,
207             );
208             }
209              
210             sub loop_ignore_filehandle {
211 1040     1040 0 822958 my ( $self, $handle, $mode ) = @_;
212              
213 1040         1990 my $fileno = fileno($handle);
214 1040         2062 my $watcher = $fileno_watcher[ $fileno ]->[ $mode ];
215              
216 1040 50       3279 return if !defined $watcher;
217            
218 1040 50       2212 EV_DEBUG && warn "loop_ignore_filehandle( $handle ($fileno), $mode )\n";
219              
220 1040         3187 $watcher->stop();
221            
222 1040         4919 undef $fileno_watcher[ $fileno ]->[ $mode ];
223             }
224              
225             sub loop_pause_filehandle {
226 923     923 0 212792 my ( $self, $handle, $mode ) = @_;
227              
228 923         1546 my $fileno = fileno($handle);
229              
230 923         3044 $fileno_watcher[ $fileno ]->[ $mode ]->stop();
231            
232 923 50       1547 EV_DEBUG && warn "loop_pause_filehandle( $handle ($fileno), $mode )\n";
233             }
234              
235             sub loop_resume_filehandle {
236 800     800 0 552606 my ( $self, $handle, $mode ) = @_;
237              
238 800         1542 my $fileno = fileno($handle);
239            
240 800         2762 $fileno_watcher[ $fileno ]->[ $mode ]->start();
241            
242 800 50       1293 EV_DEBUG && warn "loop_resume_filehandle( $handle ($fileno), $mode )\n";
243             }
244              
245             sub _loop_filehandle_callback {
246 1940     1940   91754 my ( $watcher, $ev_mode ) = @_;
247            
248 1940 50       3483 EV_DEBUG && warn "_loop_filehandle_callback( " . $watcher->fh . ", $ev_mode )\n";
249              
250 1940 50       5194 my $mode = ( $ev_mode == EV::READ )
    100          
251             ? MODE_RD
252             : ( $ev_mode == EV::WRITE )
253             ? MODE_WR
254             : confess "Invalid mode occured in POE::Loop::EV IO callback: $ev_mode";
255              
256             # ->fh is actually the fileno, since that's what we called EV::io with
257 1940         8373 $poe_kernel->_data_handle_enqueue_ready( $mode, $watcher->fh );
258            
259 1940         1704438 $poe_kernel->_test_if_kernel_is_idle();
260             }
261              
262             1;
263              
264             __END__