File Coverage

blib/lib/Linux/Event/Watcher.pm
Criterion Covered Total %
statement 26 170 15.2
branch 4 64 6.2
condition 0 18 0.0
subroutine 8 27 29.6
pod 20 21 95.2
total 58 300 19.3


line stmt bran cond sub pod time code
1             package Linux::Event::Watcher;
2 13     13   183 use v5.36;
  13         37  
3 13     13   49 use strict;
  13         14  
  13         266  
4 13     13   40 use warnings;
  13         16  
  13         801  
5              
6             our $VERSION = '0.012';
7              
8 13     13   73 use Carp qw(croak);
  13         38  
  13         2284  
9 13     13   54 use Scalar::Util qw(weaken);
  13         16  
  13         472  
10 13     13   55 use Linux::Event::XS ();
  13         14  
  13         12101  
11              
12             # NOTE:
13             # This object is intentionally lightweight. It is a handle and a data container.
14             # The Loop owns policy and backend interactions; Watcher methods delegate into Loop.
15              
16 0     0 0 0 sub new ($class, %args) {
  0         0  
  0         0  
  0         0  
17 0         0 my $loop = delete $args{loop};
18 0         0 my $fh = delete $args{fh};
19 0         0 my $fd = delete $args{fd};
20              
21 0         0 my $read = delete $args{read};
22 0         0 my $write = delete $args{write};
23 0         0 my $error = delete $args{error};
24              
25 0         0 my $data = delete $args{data};
26 0         0 my $edge_triggered = delete $args{edge_triggered};
27 0         0 my $oneshot = delete $args{oneshot};
28              
29 0 0       0 croak "unknown args: " . join(", ", sort keys %args) if %args;
30              
31 0 0       0 croak "loop is required" if !$loop;
32 0 0       0 croak "fh is required" if !$fh;
33 0 0       0 croak "fd is required" if !defined $fd;
34              
35 0 0 0     0 if (defined $read && ref($read) ne 'CODE') {
36 0         0 croak "read must be a coderef or undef";
37             }
38 0 0 0     0 if (defined $write && ref($write) ne 'CODE') {
39 0         0 croak "write must be a coderef or undef";
40             }
41 0 0 0     0 if (defined $error && ref($error) ne 'CODE') {
42 0         0 croak "error must be a coderef or undef";
43             }
44              
45            
46             # Store a weak reference to the filehandle to avoid ownership and to detect closes.
47             # If the user drops/closes the handle, the weak ref becomes undef and dispatch will auto-purge.
48 0 0       0 weaken($fh) if ref($fh);
49              
50             # Default enablement: if a handler exists, it's enabled.
51 0 0       0 my $read_enabled = $read ? 1 : 0;
52 0 0       0 my $write_enabled = $write ? 1 : 0;
53 0 0       0 my $error_enabled = $error ? 1 : 0;
54              
55 0 0       0 return bless {
    0          
56             loop => $loop,
57             fh => $fh,
58             fd => int($fd),
59              
60             data => $data,
61              
62             read_cb => $read,
63             write_cb => $write,
64             error_cb => $error,
65              
66             read_enabled => $read_enabled,
67             write_enabled => $write_enabled,
68             error_enabled => $error_enabled,
69              
70             edge_triggered => $edge_triggered ? 1 : 0,
71             oneshot => $oneshot ? 1 : 0,
72              
73             active => 1,
74             }, $class;
75             }
76              
77 0     0 1 0 sub loop ($self) { return $self->{loop} }
  0         0  
  0         0  
  0         0  
78 0     0 1 0 sub fh ($self) { return $self->{fh} }
  0         0  
  0         0  
  0         0  
79 0     0 1 0 sub fd ($self) { return $self->{fd} }
  0         0  
  0         0  
  0         0  
80              
81 1 50   1 1 6 sub is_active ($self) { return $self->{active} ? 1 : 0 }
  1         2  
  1         1  
  1         7  
82              
83 0     0 1 0 sub data ($self, @args) {
  0         0  
  0         0  
  0         0  
84 0 0       0 if (@args) {
85 0         0 $self->{data} = $args[0];
86             }
87 0         0 return $self->{data};
88             }
89              
90 0     0 1 0 sub edge_triggered ($self, @args) {
  0         0  
  0         0  
  0         0  
91 0 0       0 if (@args) {
92 0 0       0 $self->{edge_triggered} = $args[0] ? 1 : 0;
93 0         0 $self->{loop}->_watcher_update($self);
94             }
95 0 0       0 return $self->{edge_triggered} ? 1 : 0;
96             }
97              
98 0     0 1 0 sub oneshot ($self, @args) {
  0         0  
  0         0  
  0         0  
99 0 0       0 if (@args) {
100 0 0       0 $self->{oneshot} = $args[0] ? 1 : 0;
101 0         0 $self->{loop}->_watcher_update($self);
102             }
103 0 0       0 return $self->{oneshot} ? 1 : 0;
104             }
105              
106 0     0 1 0 sub on_read ($self, $cb = undef) {
  0         0  
  0         0  
  0         0  
107 0 0 0     0 if (defined $cb && ref($cb) ne 'CODE') {
108 0         0 croak "read handler must be a coderef or undef";
109             }
110 0         0 $self->{read_cb} = $cb;
111              
112             # If a handler is installed and read was disabled, do not silently enable.
113             # Callers can explicitly enable_read() if desired.
114 0 0       0 if (!$cb) {
115 0         0 $self->{read_enabled} = 0;
116             }
117              
118 0         0 $self->{loop}->_watcher_update($self);
119 0         0 return $self;
120             }
121              
122 0     0 1 0 sub on_write ($self, $cb = undef) {
  0         0  
  0         0  
  0         0  
123 0 0 0     0 if (defined $cb && ref($cb) ne 'CODE') {
124 0         0 croak "write handler must be a coderef or undef";
125             }
126 0         0 $self->{write_cb} = $cb;
127              
128 0 0       0 if (!$cb) {
129 0         0 $self->{write_enabled} = 0;
130             }
131              
132 0         0 $self->{loop}->_watcher_update($self);
133 0         0 return $self;
134             }
135              
136              
137 0     0 1 0 sub on_error ($self, $cb = undef) {
  0         0  
  0         0  
  0         0  
138 0 0 0     0 if (defined $cb && ref($cb) ne 'CODE') {
139 0         0 croak "error handler must be a coderef or undef";
140             }
141 0         0 $self->{error_cb} = $cb;
142              
143 0 0       0 if (!$cb) {
144 0         0 $self->{error_enabled} = 0;
145             }
146              
147             # Note: error interest is not an epoll subscription bit; epoll reports ERR regardless.
148             # This method only controls dispatch.
149 0         0 $self->{loop}->_watcher_update($self);
150 0         0 return $self;
151             }
152              
153 0     0 1 0 sub enable_error ($self) {
  0         0  
  0         0  
154 0         0 $self->{error_enabled} = 1;
155 0         0 $self->{loop}->_watcher_update($self);
156 0         0 return $self;
157             }
158              
159 0     0 1 0 sub disable_error ($self) {
  0         0  
  0         0  
160 0         0 $self->{error_enabled} = 0;
161 0         0 $self->{loop}->_watcher_update($self);
162 0         0 return $self;
163             }
164              
165 0     0 1 0 sub enable_read ($self) {
  0         0  
  0         0  
166 0         0 $self->{read_enabled} = 1;
167 0         0 $self->{loop}->_watcher_update($self);
168 0         0 return $self;
169             }
170              
171 0     0 1 0 sub disable_read ($self) {
  0         0  
  0         0  
172 0         0 $self->{read_enabled} = 0;
173 0         0 $self->{loop}->_watcher_update($self);
174 0         0 return $self;
175             }
176              
177 0     0 1 0 sub enable_write ($self) {
  0         0  
  0         0  
178 0         0 $self->{write_enabled} = 1;
179 0         0 $self->{loop}->_watcher_update($self);
180 0         0 return $self;
181             }
182              
183 0     0 1 0 sub disable_write ($self) {
  0         0  
  0         0  
184 0         0 $self->{write_enabled} = 0;
185 0         0 $self->{loop}->_watcher_update($self);
186 0         0 return $self;
187             }
188              
189 0 0   0 1 0 sub read_enabled ($self) { return $self->{read_enabled} ? 1 : 0 }
  0         0  
  0         0  
  0         0  
190 0 0   0 1 0 sub write_enabled ($self) { return $self->{write_enabled} ? 1 : 0 }
  0         0  
  0         0  
  0         0  
191 0 0   0 1 0 sub error_enabled ($self) { return $self->{error_enabled} ? 1 : 0 }
  0         0  
  0         0  
  0         0  
192              
193 10     10 1 22393 sub cancel ($self) {
  10         18  
  10         18  
194 10 100       29 return 0 if !$self->{active};
195 9 50       227 return Linux::Event::XS::loop_cancel_watcher($self->{loop}, $self) ? 1 : 0;
196             }
197              
198             1;
199              
200             __END__