File Coverage

blib/lib/IO/Async/Loop/POE.pm
Criterion Covered Total %
statement 105 107 98.1
branch 28 36 77.7
condition 3 3 100.0
subroutine 36 36 100.0
pod 12 12 100.0
total 184 194 94.8


line stmt bran cond sub pod time code
1             # You may distribute under the terms of either the GNU General Public License
2             # or the Artistic License (the same terms as Perl itself)
3             #
4             # (C) Paul Evans, 2010-2012 -- leonerd@leonerd.org.uk
5              
6             package IO::Async::Loop::POE;
7              
8 15     15   837333 use strict;
  15         29  
  15         497  
9 15     15   81 use warnings;
  15         27  
  15         754  
10              
11             our $VERSION = '0.05';
12 15     15   81 use constant API_VERSION => '0.49';
  15         23  
  15         960  
13              
14 15     15   75 use base qw( IO::Async::Loop );
  15         24  
  15         17797  
15             IO::Async::Loop->VERSION( '0.49' );
16              
17 15     15   234534 use Carp;
  15         42  
  15         1065  
18              
19 15     15   17712 use POE::Kernel 1.293;
  15         359152  
  15         142  
20 15     15   843803 use POE::Session;
  15         53020  
  15         120  
21              
22             # Placate POE warning that we didn't call this
23             # It won't do anything yet as we have no sessions
24             POE::Kernel->run();
25              
26             =head1 NAME
27              
28             C - use C with C
29              
30             =head1 SYNOPSIS
31              
32             use IO::Async::Loop::POE;
33              
34             my $loop = IO::Async::Loop::POE->new();
35              
36             $loop->add( ... );
37              
38             $loop->add( IO::Async::Signal->new(
39             name => 'HUP',
40             on_receipt => sub { ... },
41             ) );
42              
43             $loop->loop_forever();
44              
45             =head1 DESCRIPTION
46              
47             This subclass of L uses L to perform its work.
48              
49             The entire C system is represented by a single long-lived session
50             within the C core. It fully supports sharing the process space with
51             C; such resources as signals are properly shared between both event
52             systems.
53              
54             =head1 CONSTRUCTOR
55              
56             =cut
57              
58             =head2 $loop = IO::Async::Loop::POE->new( %args )
59              
60             This function returns a new instance of a C object.
61             It takes the following named arguments:
62              
63             =over 8
64              
65             =back
66              
67             =cut
68              
69             sub new
70             {
71 14     14 1 196 my $class = shift;
72 14         34 my ( %args ) = @_;
73              
74 14         161 my $self = $class->SUPER::__new( %args );
75              
76 14         784 my $kernelref = \($self->{kernel} = undef);
77              
78             $self->{session} = POE::Session->create(
79             inline_states => {
80             _start => sub {
81 14     14   11849 $_[KERNEL]->alias_set( "IO::Async" );
82 14         573 $$kernelref = $_[KERNEL];
83             },
84              
85             invoke => sub {
86             # CODEref is always in the last position, but what that is varies
87             # given the different events use different initial args
88 55     55   17800350 $_[-1]->();
89             },
90              
91             select_read => sub {
92 7     7   509 $_[KERNEL]->select_read( $_[ARG0], invoke => $_[ARG1] );
93             },
94             unselect_read => sub {
95 6     6   339 $_[KERNEL]->select_read( $_[ARG0] );
96             },
97             select_write => sub {
98 3     3   145 $_[KERNEL]->select_write( $_[ARG0], invoke => $_[ARG1] );
99             },
100             unselect_write => sub {
101 3     3   113 $_[KERNEL]->select_write( $_[ARG0] );
102             },
103              
104             alarm_set => sub {
105 1     1   54 $_[KERNEL]->alarm_set( invoke => $_[ARG0], $_[ARG1] );
106             },
107             delay_set => sub {
108 126     126   6939 $_[KERNEL]->delay_set( invoke => $_[ARG0], $_[ARG1] );
109             },
110             alarm_remove => sub {
111 127     127   8245 $_[KERNEL]->alarm_remove( $_[ARG0] );
112             },
113              
114             sig => sub {
115 7 100   7   401 $_[KERNEL]->sig( $_[ARG0], ( $_[ARG0] eq "CHLD" ) ? "invoke_child" : "invoke_signal", $_[ARG1] );
116             },
117             unsig => sub {
118 2     2   78 $_[KERNEL]->sig( $_[ARG0] );
119             },
120             invoke_signal => sub {
121 5     5   1722 $_[-1]->();
122 5         53 $_[KERNEL]->sig_handled;
123             },
124              
125             sig_child => sub {
126 9     9   1954 $_[KERNEL]->sig_child( $_[ARG0], invoke_child => $_[ARG1] );
127             },
128             unsig_child => sub {
129 1     1   48 $_[KERNEL]->sig_child( $_[ARG0] );
130             },
131             invoke_child => sub {
132 12     12   1408 $_[-1]->( $_[ARG1], $_[ARG2] ); # $pid, $dollarq
133             },
134             }
135 14         514 );
136              
137 14         1841 return $self;
138             }
139              
140             sub _call
141             {
142 292     292   513 my $self = shift;
143 292         1497 $self->{kernel}->call( $self->{session}, @_ );
144             }
145              
146             sub loop_once
147             {
148 112     112 1 26474 my $self = shift;
149 112         237 my ( $timeout ) = @_;
150              
151 112 100 100     1183 if( defined $timeout and $timeout == 0 ) {
152 1         7 $self->{kernel}->run_one_timeslice;
153 1         140 return;
154             }
155              
156 111         213 my $timer_id;
157 111 100       367 if( defined $timeout ) {
158 94     27   689 $timer_id = $self->_call( delay_set => $timeout, sub { } );
  27         133  
159             }
160              
161 111         9110 $self->{kernel}->run_one_timeslice;
162              
163 111         3383193 $self->_call( alarm_remove => $timer_id );
164             }
165              
166             sub watch_io
167             {
168 8     8 1 251733 my $self = shift;
169 8         34 my %params = @_;
170              
171 8 50       33 my $handle = $params{handle} or die "Need a handle";
172              
173 8 100       28 if( my $on_read_ready = $params{on_read_ready} ) {
174 7         30 $self->_call( select_read => $handle, $on_read_ready );
175             }
176              
177 8 100       858 if( my $on_write_ready = $params{on_write_ready} ) {
178 3         8 $self->_call( select_write => $handle, $on_write_ready );
179             }
180             }
181              
182             sub unwatch_io
183             {
184 7     7 1 5617 my $self = shift;
185 7         49 my %params = @_;
186              
187 7 50       29 my $handle = $params{handle} or die "Need a handle";
188              
189 7 100       23 if( my $on_read_ready = $params{on_read_ready} ) {
190 6         17 $self->_call( unselect_read => $handle );
191             }
192              
193 7 100       811 if( my $on_write_ready = $params{on_write_ready} ) {
194 3         9 $self->_call( unselect_write => $handle );
195             }
196             }
197              
198             sub watch_time
199             {
200 27     27 1 34692 my $self = shift;
201 27         274 my %params = @_;
202              
203 27 50       174 my $code = $params{code} or croak "Expected 'code' as CODE ref";
204              
205 27 100       206 if( defined $params{at} ) {
    50          
206 1         5 return $self->_call( alarm_set => $params{at}, $code );
207             }
208             elsif( defined $params{after} ) {
209 26         148 return $self->_call( delay_set => $params{after}, $code );
210             }
211             else {
212 0         0 croak "Expected either 'at' or 'after'";
213             }
214             }
215              
216             sub unwatch_time
217             {
218 15     15 1 1941 my $self = shift;
219 15         22 my ( $id ) = @_;
220              
221 15         337 $self->_call( alarm_remove => $id );
222             }
223              
224             sub watch_signal
225             {
226 4     4 1 2824 my $self = shift;
227 4         7 my ( $signal, $code ) = @_;
228              
229 4 100       198 exists $SIG{$signal} or croak "Cannot watch signal '$signal' - bad signal name";
230              
231 3         10 $self->_call( sig => $signal, $code );
232             }
233              
234             sub unwatch_signal
235             {
236 2     2 1 1737 my $self = shift;
237 2         3 my ( $signal ) = @_;
238              
239 2         5 $self->_call( unsig => $signal );
240             }
241              
242             sub watch_idle
243             {
244 6     6 1 5455 my $self = shift;
245 6         24 my %params = @_;
246              
247 6 50       20 my $when = delete $params{when} or croak "Expected 'when'";
248              
249 6 50       20 my $code = delete $params{code} or croak "Expected 'code' as a CODE ref";
250              
251 6 50       17 $when eq "later" or croak "Expected 'when' to be 'later'";
252              
253 6         17 return $self->_call( delay_set => 0, $code );
254             }
255              
256             sub unwatch_idle
257             {
258 1     1 1 86 my $self = shift;
259 1         2 my ( $id ) = @_;
260              
261 1         3 $self->_call( alarm_remove => $id );
262             }
263              
264             sub watch_child
265             {
266 13     13 1 31977 my $self = shift;
267 13         114 my ( $pid, $code ) = @_;
268              
269 13 100       164 if( $pid ) {
270 9         270 $self->_call( sig_child => $pid, $code );
271             }
272             else {
273 4         24 $self->_call( sig => "CHLD", $code );
274             }
275             }
276              
277             sub unwatch_child
278             {
279 1     1 1 144 my $self = shift;
280 1         2 my ( $pid ) = @_;
281              
282 1 50       6 if( $pid ) {
283 1         3 $self->_call( unsig_child => $pid );
284             }
285             else {
286 0           $self->_call( unsig => "CHLD" );
287             }
288             }
289              
290             =head1 AUTHOR
291              
292             Paul Evans
293              
294             =cut
295              
296             0x55AA;