File Coverage

blib/lib/IO/Ppoll.pm
Criterion Covered Total %
statement 66 71 92.9
branch 11 18 61.1
condition n/a
subroutine 15 16 93.7
pod 12 12 100.0
total 104 117 88.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, 2008-2015 -- leonerd@leonerd.org.uk
5              
6             package IO::Ppoll;
7              
8 5     5   79653 use strict;
  5         10  
  5         130  
9 5     5   24 use warnings;
  5         10  
  5         137  
10              
11 5     5   35 use Carp;
  5         6  
  5         529  
12              
13             our $VERSION = '0.12';
14              
15 5     5   23 use Exporter 'import';
  5         8  
  5         4618  
16             our @EXPORT = qw(
17             POLLIN
18             POLLOUT
19             POLLERR
20             POLLHUP
21             POLLNVAL
22             );
23              
24             require POSIX;
25              
26             require XSLoader;
27             XSLoader::load( __PACKAGE__, $VERSION );
28              
29             =head1 NAME
30              
31             C - Object interface to Linux's C call
32              
33             =head1 SYNOPSIS
34              
35             use IO::Ppoll qw( POLLIN POLLOUT );
36             use POSIX qw( sigprocmask SIG_BLOCK SIGHUP );
37              
38             my $ppoll = IO::Ppoll->new();
39             $ppoll->mask( $input_handle => POLLIN );
40             $ppoll->mask( $output_handle => POLLOUT );
41              
42             $SIG{HUP} = sub { print "SIGHUP happened\n"; };
43             sigprocmask( SIG_BLOCK, POSIX::SigSet->new( SIGHUP ), undef );
44              
45             # If a SIGHUP happens, it can only happen during this poll
46             $ppoll->poll( $timeout );
47              
48             $input_ev = $poll->events( $input_handle );
49              
50             =head1 DESCRIPTION
51              
52             C is a simple interface to Linux's C system call. It
53             provides an interface that is drop-in compatible with L. The object
54             stores a signal mask that will be in effect during the actual C
55             system call and has additional methods for manipulating the signal mask.
56              
57             The C system call atomically switches the process's signal mask to
58             that provided by the call, waits identically to C, then switches it
59             back again. This allows a program to safely wait on either file handle IO or
60             signals, without needing such tricks as a self-connected pipe or socket.
61              
62             The usual way in which this is used is to block the signals the application is
63             interested in during the normal running of code. Whenever the C wait
64             is entered the process signal mask will be switched to that stored in the
65             object. If there are any pending signals, the Linux kernel will then deliver
66             them and make C return -1 with C set to C. If no
67             signals are pending, it will wait as a normal C would. This guarantees
68             the signals will only be delivered during the C wait, when it would
69             be safe to do so.
70              
71             =cut
72              
73             =head1 CONSTRUCTOR
74              
75             =cut
76              
77             =head2 new
78              
79             $ppoll = IO::Ppoll->new()
80              
81             Returns a new instance of an C object. It will contain no file
82             handles and its signal mask will be empty.
83              
84             =cut
85              
86             sub new
87             {
88 4     4 1 46 my $class = shift;
89              
90 4         101 my $self = bless {
91             fds => "",
92             nfds => 0,
93             handles => [],
94             sigmask => POSIX::SigSet->new(),
95             }, $class;
96              
97 4         13 return $self;
98             }
99              
100             =head1 METHODS
101              
102             =cut
103              
104             =head2 mask
105              
106             $mask = $ppoll->mask( $handle )
107              
108             Returns the current mask bits for the given IO handle
109              
110             $ppoll->mask( $handle, $newmask )
111              
112             Sets the mask bits for the given IO handle. If C<$newmask> is 0, the handle
113             will be removed.
114              
115             =cut
116              
117             sub mask
118             {
119 9     9 1 44 my $self = shift;
120 9         16 my ( $handle, $newmask ) = @_;
121              
122 9         15 my $fd = fileno $handle;
123 9 50       23 defined $fd or croak "Expected a filehandle";
124              
125 9 100       21 if( @_ > 1 ) {
126 5 100       11 if( $newmask ) {
127 4         13 $self->{handles}->[$fd] = $handle;
128 4         21 mas_events( $self->{fds}, $self->{nfds}, $fd, 0, $newmask );
129             }
130             else {
131 1         3 delete $self->{handles}->[$fd];
132 1         7 del_events( $self->{fds}, $self->{nfds}, $fd );
133             }
134             }
135             else {
136 4         24 return get_events( $self->{fds}, $self->{nfds}, $fd );
137             }
138             }
139              
140             =head2 mask_add
141              
142             =head2 mask_del
143              
144             $ppoll->mask_add( $handle, $addmask )
145              
146             $ppoll->mask_del( $handle, $delmask )
147              
148             I
149              
150             Convenient shortcuts to setting or clearing one or more bits in the mask of a
151             handle. Equivalent, respectively, to the following lines
152              
153             $ppoll->mask( $handle, $ppoll->mask( $handle ) | $addmask )
154              
155             $ppoll->mask( $handle, $ppoll->mask( $handle ) & ~$delmask )
156              
157             Specifically note that C<$maskbits> contains bits to remove from the mask.
158              
159             =cut
160              
161             sub mask_add
162             {
163 1     1 1 2 my $self = shift;
164 1         2 my ( $handle, $addbits ) = @_;
165              
166 1         3 my $fd = fileno $handle;
167 1 50       7 defined $fd or croak "Expected a filehandle";
168              
169 1         7 mas_events( $self->{fds}, $self->{nfds}, $fd, ~0, $addbits );
170             }
171              
172             sub mask_del
173             {
174 1     1 1 3 my $self = shift;
175 1         4 my ( $handle, $delbits ) = @_;
176              
177 1         2 my $fd = fileno $handle;
178 1 50       8 defined $fd or croak "Expected a filehandle";
179              
180 1         7 mas_events( $self->{fds}, $self->{nfds}, $fd, ~$delbits, 0 );
181             }
182              
183             =head2 poll
184              
185             $ret = $ppoll->poll( $timeout )
186              
187             Call the C system call. If C<$timeout> is not supplied then no
188             timeout value will be passed to the system call. Returns the result of the
189             system call, which is the number of filehandles that have non-zero events, 0
190             on timeout, or -1 if an error occurred (including being interrupted by a
191             signal). If -1 is returned, C<$!> will contain the error.
192              
193             =cut
194              
195             sub poll
196             {
197 3     3 1 924 my $self = shift;
198 3         7 my ( $timeout ) = @_;
199              
200             # do_poll wants timeout in miliseconds
201 3 50       13 $timeout *= 1000 if defined $timeout;
202              
203 3         100298 return do_poll( $self->{fds}, $self->{nfds}, $timeout, $self->{sigmask} );
204             }
205              
206             =head2 events
207              
208             $bits = $ppoll->events( $handle )
209              
210             Returns the event mask which represents the events that happened on the
211             filehandle during the last call to C.
212              
213             =cut
214              
215             sub events
216             {
217 3     3 1 542 my $self = shift;
218 3         5 my ( $handle ) = @_;
219              
220 3         7 my $fd = fileno $handle;
221 3 50       10 defined $fd or croak "Expected a filehandle";
222              
223 3         18 return get_revents( $self->{fds}, $self->{nfds}, $fd );
224             }
225              
226             =head2 remove
227              
228             $ppoll->remove( $handle )
229              
230             Removes the handle from the list of file descriptors for the next poll.
231              
232             =cut
233              
234             sub remove
235             {
236 1     1 1 19 my $self = shift;
237 1         4 my ( $handle ) = @_;
238              
239 1         3 $self->mask( $handle, 0 );
240             }
241              
242             =head2 handles
243              
244             @handles = $ppoll->handles( $bits )
245              
246             Returns a list of handles. If C<$bits> is not given then all of the handles
247             will be returned. If C<$bits> is given then the list will only contain handles
248             which reported at least one of the bits specified during the last C
249             call.
250              
251             =cut
252              
253             sub handles
254             {
255 4     4 1 863 my $self = shift;
256 4         5 my ( $events ) = @_;
257              
258 4         6 my @fds;
259 4 100       13 if( @_ ) {
260 1         6 @fds = get_fds_for( $self->{fds}, $self->{nfds}, $events );
261             }
262             else {
263 3         18 @fds = get_fds( $self->{fds}, $self->{nfds} );
264             }
265              
266 4         12 my $handle_map = $self->{handles};
267 4         18 return map { $handle_map->[$_] } @fds;
  2         25  
268             }
269              
270             =head2 sigmask
271              
272             $sigset = $ppoll->sigmask
273              
274             Returns the C object in which the signal mask is stored. Since
275             this is a reference to the object the C object uses, any
276             modifications made to it will be reflected in the signal mask given to the
277             C system call.
278              
279             $ppoll->sigmask( $newsigset )
280              
281             Sets the C object in which the signal mask is stored. Usually
282             this is not required, as a new C is initialised with an empty set,
283             and the C and C methods can be used to modify
284             it.
285              
286             =cut
287              
288             sub sigmask
289             {
290 0     0 1 0 my $self = shift;
291 0         0 my ( $newmask ) = @_;
292              
293 0 0       0 if( @_ ) {
294 0         0 $self->{sigmask} = $newmask;
295             }
296             else {
297 0         0 return $self->{sigmask};
298             }
299             }
300              
301             =head2 sigmask_add
302              
303             $ppoll->sigmask_add( @signals )
304              
305             Adds the given signals to the signal mask. These signals will be blocked
306             during the C call.
307              
308             =cut
309              
310             sub sigmask_add
311             {
312 2     2 1 960 my $self = shift;
313 2         6 my @signals = @_;
314              
315 2         17 $self->{sigmask}->addset( $_ ) foreach @signals;
316             }
317              
318             =head2 sigmask_del
319              
320             $ppoll->sigmask_del( @signals )
321              
322             Removes the given signals from the signal mask. These signals will not be
323             blocked during the C call, and may be delivered while C is
324             waiting.
325              
326             =cut
327              
328             sub sigmask_del
329             {
330 1     1 1 2 my $self = shift;
331 1         2 my @signals = @_;
332              
333 1         7 $self->{sigmask}->delset( $_ ) foreach @signals;
334             }
335              
336             =head2 sigmask_ismember
337              
338             $present = $ppoll->sigmask_ismember( $signal )
339              
340             Tests if the given signal is present in the signal mask.
341              
342             =cut
343              
344             sub sigmask_ismember
345             {
346 3     3 1 10 my $self = shift;
347 3         4 my ( $signal ) = @_;
348              
349 3         71 return $self->{sigmask}->ismember( $signal );
350             }
351              
352             =head1 SEE ALSO
353              
354             =over 4
355              
356             =item *
357              
358             L - Object interface to system poll call
359              
360             =item *
361              
362             C - wait for some event on a file descriptor (Linux manpages)
363              
364             =item *
365              
366             L - a Loop using an IO::Ppoll object
367              
368             =back
369              
370             =head1 AUTHOR
371              
372             Paul Evans
373              
374             =cut
375              
376             0x55AA;