File Coverage

blib/lib/IO/Ppoll.pm
Criterion Covered Total %
statement 65 70 92.8
branch 15 26 57.6
condition n/a
subroutine 15 16 93.7
pod 12 12 100.0
total 107 124 86.2


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