File Coverage

blib/lib/IO/Async/Loop/POE.pm
Criterion Covered Total %
statement 104 106 98.1
branch 28 36 77.7
condition 3 3 100.0
subroutine 36 36 100.0
pod 12 12 100.0
total 183 193 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-2020 -- leonerd@leonerd.org.uk
5              
6             package IO::Async::Loop::POE;
7              
8 16     16   565916 use strict;
  16         50  
  16         390  
9 16     16   66 use warnings;
  16         24  
  16         553  
10              
11             our $VERSION = '0.06';
12 16     16   75 use constant API_VERSION => '0.76';
  16         20  
  16         895  
13              
14 16     16   75 use base qw( IO::Async::Loop );
  16         26  
  16         10700  
15             IO::Async::Loop->VERSION( '0.49' );
16              
17 16     16   217542 use Carp;
  16         26  
  16         826  
18              
19 16     16   10376 use POE::Kernel 1.293;
  16         370799  
  16         98  
20 16     16   348306 use POE::Session;
  16         42050  
  16         115  
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 new
59              
60             $loop = IO::Async::Loop::POE->new( %args )
61              
62             This function returns a new instance of a C object.
63             It takes the following named arguments:
64              
65             =over 8
66              
67             =back
68              
69             =cut
70              
71             sub new
72             {
73 15     15 1 610 my $class = shift;
74 15         38 my ( %args ) = @_;
75              
76 15         130 my $self = $class->SUPER::__new( %args );
77              
78 15         692 my $kernelref = \($self->{kernel} = undef);
79              
80             $self->{session} = POE::Session->create(
81             inline_states => {
82             _start => sub {
83 15     15   12635 $_[KERNEL]->alias_set( "IO::Async" );
84 15         559 $$kernelref = $_[KERNEL];
85             },
86              
87             invoke => sub {
88             # CODEref is always in the last position, but what that is varies
89             # given the different events use different initial args
90 56     56   16802939 $_[-1]->();
91             },
92              
93             select_read => sub {
94 7     7   409 $_[KERNEL]->select_read( $_[ARG0], invoke => $_[ARG1] );
95             },
96             unselect_read => sub {
97 6     6   298 $_[KERNEL]->select_read( $_[ARG0] );
98             },
99             select_write => sub {
100 5     5   303 $_[KERNEL]->select_write( $_[ARG0], invoke => $_[ARG1] );
101             },
102             unselect_write => sub {
103 5     5   178 $_[KERNEL]->select_write( $_[ARG0] );
104             },
105              
106             alarm_set => sub {
107 1     1   55 $_[KERNEL]->alarm_set( invoke => $_[ARG0], $_[ARG1] );
108             },
109             delay_set => sub {
110 143     143   7798 $_[KERNEL]->delay_set( invoke => $_[ARG0], $_[ARG1] );
111             },
112             alarm_remove => sub {
113 141     141   7925 $_[KERNEL]->alarm_remove( $_[ARG0] );
114             },
115              
116             sig => sub {
117 9 100   9   584 $_[KERNEL]->sig( $_[ARG0], ( $_[ARG0] eq "CHLD" ) ? "invoke_child" : "invoke_signal", $_[ARG1] );
118             },
119             unsig => sub {
120 2     2   98 $_[KERNEL]->sig( $_[ARG0] );
121             },
122             invoke_signal => sub {
123 6     6   2041 $_[-1]->();
124 6         48 $_[KERNEL]->sig_handled;
125             },
126              
127             sig_child => sub {
128 12     12   2385 $_[KERNEL]->sig_child( $_[ARG0], invoke_child => $_[ARG1] );
129             },
130             unsig_child => sub {
131 1     1   50 $_[KERNEL]->sig_child( $_[ARG0] );
132             },
133             invoke_child => sub {
134 19     19   3575 $_[-1]->( $_[ARG1], $_[ARG2] ); # $pid, $dollarq
135             },
136             }
137 15         387 );
138              
139 15         2009 return $self;
140             }
141              
142             sub _call
143             {
144 332     332   971 my $self = shift;
145 332         1378 $self->{kernel}->call( $self->{session}, @_ );
146             }
147              
148             sub loop_once
149             {
150 122     122 1 23166 my $self = shift;
151 122         244 my ( $timeout ) = @_;
152              
153 122 100 100     655 if( defined $timeout and $timeout == 0 ) {
154 1         4 $self->{kernel}->run_one_timeslice;
155 1         138 return;
156             }
157              
158 121         187 my $timer_id;
159 121 100       277 if( defined $timeout ) {
160 107     27   518 $timer_id = $self->_call( delay_set => $timeout, sub { } );
161             }
162              
163 121         10075 $self->{kernel}->run_one_timeslice;
164              
165 121         2939488 $self->_call( alarm_remove => $timer_id );
166             }
167              
168             sub watch_io
169             {
170 10     10 1 13954 my $self = shift;
171 10         28 my %params = @_;
172              
173 10 50       30 my $handle = $params{handle} or die "Need a handle";
174              
175 10 100       24 if( my $on_read_ready = $params{on_read_ready} ) {
176 7         26 $self->_call( select_read => $handle, $on_read_ready );
177             }
178              
179 10 100       732 if( my $on_write_ready = $params{on_write_ready} ) {
180 5         10 $self->_call( select_write => $handle, $on_write_ready );
181             }
182             }
183              
184             sub unwatch_io
185             {
186 9     9 1 16237 my $self = shift;
187 9         30 my %params = @_;
188              
189 9 50       25 my $handle = $params{handle} or die "Need a handle";
190              
191 9 100       21 if( my $on_read_ready = $params{on_read_ready} ) {
192 6         13 $self->_call( unselect_read => $handle );
193             }
194              
195 9 100       709 if( my $on_write_ready = $params{on_write_ready} ) {
196 5         11 $self->_call( unselect_write => $handle );
197             }
198             }
199              
200             sub watch_time
201             {
202 31     31 1 33318 my $self = shift;
203 31         258 my %params = @_;
204              
205 31 50       180 my $code = $params{code} or croak "Expected 'code' as CODE ref";
206              
207 31 100       110 if( defined $params{at} ) {
    50          
208 1         5 return $self->_call( alarm_set => $params{at}, $code );
209             }
210             elsif( defined $params{after} ) {
211 30         141 return $self->_call( delay_set => $params{after}, $code );
212             }
213             else {
214 0         0 croak "Expected either 'at' or 'after'";
215             }
216             }
217              
218             sub unwatch_time
219             {
220 19     19 1 2193 my $self = shift;
221 19         45 my ( $id ) = @_;
222              
223 19         60 $self->_call( alarm_remove => $id );
224             }
225              
226             sub watch_signal
227             {
228 5     5 1 3516 my $self = shift;
229 5         12 my ( $signal, $code ) = @_;
230              
231 5 100       173 exists $SIG{$signal} or croak "Cannot watch signal '$signal' - bad signal name";
232              
233 4         10 $self->_call( sig => $signal, $code );
234             }
235              
236             sub unwatch_signal
237             {
238 2     2 1 1630 my $self = shift;
239 2         4 my ( $signal ) = @_;
240              
241 2         3 $self->_call( unsig => $signal );
242             }
243              
244             sub watch_idle
245             {
246 6     6 1 4830 my $self = shift;
247 6         17 my %params = @_;
248              
249 6 50       17 my $when = delete $params{when} or croak "Expected 'when'";
250              
251 6 50       16 my $code = delete $params{code} or croak "Expected 'code' as a CODE ref";
252              
253 6 50       20 $when eq "later" or croak "Expected 'when' to be 'later'";
254              
255 6         13 return $self->_call( delay_set => 0, $code );
256             }
257              
258             sub unwatch_idle
259             {
260 1     1 1 114 my $self = shift;
261 1         2 my ( $id ) = @_;
262              
263 1         2 $self->_call( alarm_remove => $id );
264             }
265              
266             sub watch_process
267             {
268 17     17 1 34484 my $self = shift;
269 17         230 my ( $pid, $code ) = @_;
270              
271 17 100       158 if( $pid ) {
272 12         247 $self->_call( sig_child => $pid, $code );
273             }
274             else {
275 5         75 $self->_call( sig => "CHLD", $code );
276             }
277             }
278              
279             sub unwatch_process
280             {
281 1     1 1 155 my $self = shift;
282 1         2 my ( $pid ) = @_;
283              
284 1 50       3 if( $pid ) {
285 1         8 $self->_call( unsig_child => $pid );
286             }
287             else {
288 0           $self->_call( unsig => "CHLD" );
289             }
290             }
291              
292             =head1 AUTHOR
293              
294             Paul Evans
295              
296             =cut
297              
298             0x55AA;