File Coverage

blib/lib/IO/Epoll.pm
Criterion Covered Total %
statement 108 129 83.7
branch 25 36 69.4
condition 7 11 63.6
subroutine 23 29 79.3
pod 9 19 47.3
total 172 224 76.7


line stmt bran cond sub pod time code
1             package IO::Epoll;
2              
3 3     3   59904 use 5.006;
  3         12  
  3         146  
4 3     3   21 use strict;
  3         6  
  3         105  
5 3     3   19 use warnings;
  3         10  
  3         108  
6 3     3   17 use Carp;
  3         4  
  3         268  
7              
8             require Exporter;
9 3     3   2941 use AutoLoader;
  3         7153  
  3         18  
10 3     3   3709 use POSIX ();
  3         25349  
  3         764  
11              
12             our @ISA = qw(Exporter);
13              
14             # Items to export into callers namespace by default. Note: do not export
15             # names by default without a very good reason. Use EXPORT_OK instead.
16             # Do not simply export all your public functions/methods/constants.
17              
18             # This allows declaration use IO::Epoll ':all';
19             # If you do not need this, moving things directly into @EXPORT or @EXPORT_OK
20             # will save memory.
21             our %EXPORT_TAGS = ( 'default' => [ qw(
22             EPOLLERR
23             EPOLLET
24             EPOLLHUP
25             EPOLLIN
26             EPOLLMSG
27             EPOLLOUT
28             EPOLLPRI
29             EPOLLRDBAND
30             EPOLLRDNORM
31             EPOLLWRBAND
32             EPOLLWRNORM
33             EPOLL_CTL_ADD
34             EPOLL_CTL_DEL
35             EPOLL_CTL_MOD
36             epoll_create
37             epoll_ctl
38             epoll_wait
39             epoll_pwait
40             ) ],
41             'compat' => [ qw(
42             POLLIN
43             POLLOUT
44             POLLERR
45             POLLHUP
46             POLLNVAL
47             POLLPRI
48             POLLRDNORM
49             POLLWRNORM
50             POLLRDBAND
51             POLLWRBAND
52             ) ] );
53              
54             our @EXPORT_OK = ( @{ $EXPORT_TAGS{'default'} },
55             @{ $EXPORT_TAGS{'compat'} } );
56              
57             our @EXPORT = qw(
58             EPOLLERR
59             EPOLLET
60             EPOLLHUP
61             EPOLLIN
62             EPOLLMSG
63             EPOLLOUT
64             EPOLLPRI
65             EPOLLRDBAND
66             EPOLLRDNORM
67             EPOLLWRBAND
68             EPOLLWRNORM
69             EPOLL_CTL_ADD
70             EPOLL_CTL_DEL
71             EPOLL_CTL_MOD
72             epoll_create
73             epoll_ctl
74             epoll_wait
75             epoll_pwait
76             );
77              
78             our $VERSION = '0.03';
79              
80             sub AUTOLOAD {
81             # This AUTOLOAD is used to 'autoload' constants from the constant()
82             # XS function.
83              
84 22     22   794 my $constname;
85 22         28 our $AUTOLOAD;
86 22         108 ($constname = $AUTOLOAD) =~ s/.*:://;
87 22 50       58 croak "&IO::Epoll::constant not defined" if $constname eq 'constant';
88 22         69 my ($error, $val) = constant($constname);
89 22 50       49 if ($error) { croak $error; }
  0         0  
90             {
91 3     3   27 no strict 'refs';
  3         6  
  3         4998  
  22         23  
92             # Fixed between 5.005_53 and 5.005_61
93             #XXX if ($] >= 5.00561) {
94             #XXX *$AUTOLOAD = sub () { $val };
95             #XXX }
96             #XXX else {
97 22     39   127 *$AUTOLOAD = sub { $val };
  39         477  
98             #XXX }
99             }
100 22         69 goto &$AUTOLOAD;
101             }
102              
103             require XSLoader;
104             XSLoader::load('IO::Epoll', $VERSION);
105              
106             # Preloaded methods go here.
107              
108             # IO::Poll Compatibility API
109              
110             # [0] maps fd's to requested masks
111             # [1] maps fd's to returned masks
112             # [2] maps fd's to handles
113             # [3] is the epoll fd
114             # [4] is the signal mask, if used. If present will use epoll_pwait() instead of epoll_wait()
115              
116             sub new
117             {
118 2     2 0 80 my $package = shift;
119 2         11 my $self = bless [ {}, {}, {}, undef, undef ] => $package;
120              
121 2         63 $self->[3] = epoll_create(15);
122 2 50       11 if ($self->[3] < 0) {
123 0 0       0 if ($! =~ /not implemented/) {
124 0         0 die "You need at least Linux 2.5.44 to use IO::Epoll";
125             }
126             else {
127 0         0 die "epoll_create: $!\n";
128             }
129             }
130 2         9 return $self;
131             }
132              
133             sub mask
134             {
135 9     9 1 19 my $self = shift;
136 9         13 my $io = shift;
137 9         22 my $fd = fileno $io;
138              
139 9 100       31 if (@_) {
140 6         10 my $mask = shift;
141              
142 6 100       16 if ($mask) {
143 3         3 my $combined_mask = $mask;
144 3         9 my $op = &EPOLL_CTL_ADD;
145 3 100       46 if ( exists $self->[0]{$fd} ) {
146 1         2 $combined_mask |= $_ foreach values %{ $self->[0]{$fd} };
  1         5  
147 1         3 $op = &EPOLL_CTL_MOD;
148             }
149 3 100       54 return if epoll_ctl($self->[3], $op, $fd, $combined_mask) < 0;
150 2         9 $self->[0]{$fd}{$io} = $mask;
151 2         5 $self->[2]{$io} = $io;
152             }
153             else {
154 3         31 delete $self->[0]{$fd}{$io};
155 3         10 delete $self->[2]{$io};
156              
157 3         9 my $op = &EPOLL_CTL_DEL;
158 3         7 my $combined_mask = 0;
159 3 100       5 if ( %{ $self->[0]{$fd} } ) {
  3         23  
160 1         2 $combined_mask |= $_ foreach values %{ $self->[0]{$fd} };
  1         6  
161 1         3 $op = &EPOLL_CTL_MOD;
162             }
163             else {
164 2         5 delete $self->[1]{$fd};
165 2         7 delete $self->[0]{$fd};
166             }
167 3 100       37 return if epoll_ctl($self->[3], $op, $fd, $combined_mask) < 0;
168             }
169             }
170              
171 7 100 100     53 return unless exists $self->[0]{$fd} and exists $self->[0]{$fd}{$io};
172 4         23 return $self->[0]{$fd}{$io};
173             }
174              
175             sub poll
176             {
177 6     6 1 46 my ($self, $timeout) = @_;
178              
179 6         17 $self->[1] = {};
180              
181             # Set max events to half the number of descriptors, to a minumum of 10
182 6         11 my $maxevents = int ((values %{ $self->[0] }) / 2);
  6         27  
183 6 50       22 $maxevents = 10 if $maxevents < 10;
184              
185 6 50       21 my $msec = defined $timeout ? $timeout * 1000 : -1;
186              
187 6         1306750 my $ret = epoll_pwait($self->[3], $maxevents, $msec, $self->[4]);
188 6 100       57 return -1 unless defined $ret;
189              
190 5         33 foreach my $event (@$ret) {
191 1         13 $self->[1]{$event->[0]} = $event->[1];
192             }
193 5         59 return scalar(@$ret);
194             }
195              
196             sub events
197             {
198 3     3 1 32 my $self = shift;
199 3         6 my $io = shift;
200 3         9 my $fd = fileno $io;
201              
202 3 100 66     24 if ( exists $self->[1]{$fd} && exists $self->[0]{$fd}{$io} ) {
203 2         10 return $self->[1]{$fd} & ($self->[0]{$fd}{$io} |
204             &EPOLLHUP | &EPOLLERR );
205             } else {
206 1         10 return 0;
207             }
208             }
209              
210             sub remove
211             {
212 3     3 1 98 my $self = shift;
213 3         8 my $io = shift;
214 3         12 $self->mask($io, 0);
215             }
216              
217             sub handles
218             {
219 3     3 1 19 my $self = shift;
220 3 50       9 return values %{ $self->[2] } unless @_;
  3         12  
221              
222 0   0     0 my $events = shift || 0;
223 0         0 my($fd, $ev, $io, $mask);
224 0         0 my @handles = ();
225              
226 0         0 while( ($fd, $ev) = each %{ $self->[1] } ) {
  0         0  
227 0         0 while ( ($io, $mask) = each %{ $self->[0]{$fd} } ) {
  0         0  
228 0         0 $mask |= &EPOLLHUP | &EPOLLERR; # must allow these
229 0 0       0 push @handles, $self->[2]{$io} if ($ev & $mask) & $events;
230             }
231             }
232 0         0 return @handles;
233             }
234              
235             # Close the epoll handle when object destroyed
236             sub DESTROY
237             {
238 2     2   3335 my $self = shift;
239              
240 2         306 POSIX::close($self->[3]);
241             }
242              
243             # IO::Ppoll API extension
244              
245             sub sigmask
246             {
247 6     6 1 8 my $self = shift;
248              
249 6 50       13 if( my ( $newmask ) = @_ ) {
250 0         0 $self->[4] = $newmask;
251             }
252             else {
253 6   66     41 $self->[4] ||= POSIX::SigSet->new();
254 6         44 return $self->[4];
255             }
256             }
257              
258             sub sigmask_add
259             {
260 2     2 1 1583 my $self = shift;
261 2         4 my @signals = @_;
262              
263 2         6 my $sigmask = $self->sigmask;
264 2         15 $sigmask->addset( $_ ) foreach @signals;
265             }
266              
267             sub sigmask_del
268             {
269 1     1 1 2 my $self = shift;
270 1         3 my @signals = @_;
271              
272 1         3 my $sigmask = $self->sigmask;
273 1         9 $sigmask->delset( $_ ) foreach @signals;
274             }
275              
276             sub sigmask_ismember
277             {
278 3     3 1 9 my $self = shift;
279 3         6 my ( $signal ) = @_;
280              
281 3         11 return $self->sigmask->ismember( $signal );
282             }
283              
284             # IO::Poll compatibility constants
285              
286             sub POLLNVAL () { 0 };
287 1     1 0 25 sub POLLIN () { &EPOLLIN };
288 3     3 0 92 sub POLLOUT () { &EPOLLOUT };
289 0     0 0 0 sub POLLERR () { &EPOLLERR };
290 0     0 0 0 sub POLLHUP () { &EPOLLHUP };
291 2     2 0 18 sub POLLPRI () { &EPOLLPRI };
292 0     0 0   sub POLLRDNORM () { &EPOLLRDNORM };
293 0     0 0   sub POLLWRNORM () { &EPOLLWRNORM };
294 0     0 0   sub POLLRDBAND () { &EPOLLRDBAND };
295 0     0 0   sub POLLWRBAND () { &EPOLLWRBAND };
296              
297             # Autoload methods go after =cut, and are processed by the autosplit program.
298              
299             1;
300             __END__