File Coverage

blib/lib/IO/Ppoll.pm
Criterion Covered Total %
statement 56 61 91.8
branch 9 14 64.2
condition n/a
subroutine 13 14 92.8
pod 10 10 100.0
total 88 99 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,2009 -- leonerd@leonerd.org.uk
5              
6             package IO::Ppoll;
7              
8 5     5   118757 use strict;
  5         11  
  5         207  
9 5     5   26 use warnings;
  5         9  
  5         165  
10              
11 5     5   36 use Carp;
  5         10  
  5         611  
12              
13             our $VERSION = '0.11';
14              
15 5     5   43 use Exporter 'import';
  5         26  
  5         7630  
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 $ppoll = IO::Ppoll->new()
78              
79             Returns a new instance of an C object. It will contain no file
80             handles and its signal mask will be empty.
81              
82             =cut
83              
84             sub new
85             {
86 4     4 1 48 my $class = shift;
87              
88 4         109 my $self = bless {
89             fds => "",
90             nfds => 0,
91             handles => [],
92             sigmask => POSIX::SigSet->new(),
93             }, $class;
94              
95 4         16 return $self;
96             }
97              
98             =head1 METHODS
99              
100             =cut
101              
102             =head2 $mask = $ppoll->mask( $handle )
103              
104             Returns the current mask bits for the given IO handle
105              
106             =head2 $ppoll->mask( $handle, $newmask )
107              
108             Sets the mask bits for the given IO handle. If C<$newmask> is 0, the handle
109             will be removed.
110              
111             =cut
112              
113             sub mask
114             {
115 7     7 1 76 my $self = shift;
116 7         12 my ( $handle, $newmask ) = @_;
117              
118 7         14 my $fd = fileno $handle;
119 7 50       78 defined $fd or croak "Expected a filehandle";
120              
121 7 100       20 if( @_ > 1 ) {
122 5 100       11 if( $newmask ) {
123 4         14 $self->{handles}->[$fd] = $handle;
124 4         23 set_events( $self->{fds}, $self->{nfds}, $fd, $newmask );
125             }
126             else {
127 1         3 delete $self->{handles}->[$fd];
128 1         7 del_events( $self->{fds}, $self->{nfds}, $fd );
129             }
130             }
131             else {
132 2         17 return get_events( $self->{fds}, $self->{nfds}, $fd );
133             }
134             }
135              
136             =head2 $ret = $ppoll->poll( $timeout )
137              
138             Call the C system call. If C<$timeout> is not supplied then no
139             timeout value will be passed to the system call. Returns the result of the
140             system call, which is the number of filehandles that have non-zero events, 0
141             on timeout, or -1 if an error occurred (including being interrupted by a
142             signal). If -1 is returned, C<$!> will contain the error.
143              
144             =cut
145              
146             sub poll
147             {
148 3     3 1 1702 my $self = shift;
149 3         7 my ( $timeout ) = @_;
150              
151             # do_poll wants timeout in miliseconds
152 3 50       17 $timeout *= 1000 if defined $timeout;
153              
154 3         100229 return do_poll( $self->{fds}, $self->{nfds}, $timeout, $self->{sigmask} );
155             }
156              
157             =head2 $bits = $ppoll->events( $handle )
158              
159             Returns the event mask which represents the events that happened on the
160             filehandle during the last call to C.
161              
162             =cut
163              
164             sub events
165             {
166 3     3 1 897 my $self = shift;
167 3         4 my ( $handle ) = @_;
168              
169 3         7 my $fd = fileno $handle;
170 3 50       11 defined $fd or croak "Expected a filehandle";
171              
172 3         18 return get_revents( $self->{fds}, $self->{nfds}, $fd );
173             }
174              
175             =head2 $ppoll->remove( $handle )
176              
177             Removes the handle from the list of file descriptors for the next poll.
178              
179             =cut
180              
181             sub remove
182             {
183 1     1 1 3 my $self = shift;
184 1         3 my ( $handle ) = @_;
185              
186 1         4 $self->mask( $handle, 0 );
187             }
188              
189             =head2 @handles = $ppoll->handles( $bits )
190              
191             Returns a list of handles. If C<$bits> is not given then all of the handles
192             will be returned. If C<$bits> is given then the list will only contain handles
193             which reported at least one of the bits specified during the last C
194             call.
195              
196             =cut
197              
198             sub handles
199             {
200 4     4 1 1228 my $self = shift;
201 4         6 my ( $events ) = @_;
202              
203 4         7 my @fds;
204 4 100       12 if( @_ ) {
205 1         5 @fds = get_fds_for( $self->{fds}, $self->{nfds}, $events );
206             }
207             else {
208 3         16 @fds = get_fds( $self->{fds}, $self->{nfds} );
209             }
210              
211 4         9 my $handle_map = $self->{handles};
212 4         16 return map { $handle_map->[$_] } @fds;
  2         17  
213             }
214              
215             =head2 $sigset = $ppoll->sigmask
216              
217             Returns the C object in which the signal mask is stored. Since
218             this is a reference to the object the C object uses, any
219             modifications made to it will be reflected in the signal mask given to the
220             C system call.
221              
222             =head2 $ppoll->sigmask( $newsigset )
223              
224             Sets the C object in which the signal mask is stored. Usually
225             this is not required, as a new C is initialised with an empty set,
226             and the C and C methods can be used to modify
227             it.
228              
229             =cut
230              
231             sub sigmask
232             {
233 0     0 1 0 my $self = shift;
234 0         0 my ( $newmask ) = @_;
235              
236 0 0       0 if( @_ ) {
237 0         0 $self->{sigmask} = $newmask;
238             }
239             else {
240 0         0 return $self->{sigmask};
241             }
242             }
243              
244             =head2 $ppoll->sigmask_add( @signals )
245              
246             Adds the given signals to the signal mask. These signals will be blocked
247             during the C call.
248              
249             =cut
250              
251             sub sigmask_add
252             {
253 2     2 1 1774 my $self = shift;
254 2         6 my @signals = @_;
255              
256 2         22 $self->{sigmask}->addset( $_ ) foreach @signals;
257             }
258              
259             =head2 $ppoll->sigmask_del( @signals )
260              
261             Removes the given signals from the signal mask. These signals will not be
262             blocked during the C call, and may be delivered while C is
263             waiting.
264              
265             =cut
266              
267             sub sigmask_del
268             {
269 1     1 1 3 my $self = shift;
270 1         3 my @signals = @_;
271              
272 1         10 $self->{sigmask}->delset( $_ ) foreach @signals;
273             }
274              
275             =head2 $present = $ppoll->sigmask_ismember( $signal )
276              
277             Tests if the given signal is present in the signal mask.
278              
279             =cut
280              
281             sub sigmask_ismember
282             {
283 3     3 1 41 my $self = shift;
284 3         6 my ( $signal ) = @_;
285              
286 3         30 return $self->{sigmask}->ismember( $signal );
287             }
288              
289             =head1 SEE ALSO
290              
291             =over 4
292              
293             =item *
294              
295             L - Object interface to system poll call
296              
297             =item *
298              
299             C - wait for some event on a file descriptor (Linux manpages)
300              
301             =item *
302              
303             L - a Loop using an IO::Ppoll object
304              
305             =back
306              
307             =head1 AUTHOR
308              
309             Paul Evans
310              
311             =cut
312              
313             0x55AA;