ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/Coro/Event/Handle.pm
Revision: 1.16
Committed: Sun Mar 24 12:09:05 2002 UTC (22 years, 2 months ago) by root
Branch: MAIN
Changes since 1.15: +1 -1 lines
Log Message:
*** empty log message ***

File Contents

# User Rev Content
1 root 1.1 =head1 NAME
2    
3     Coro::Handle - non-blocking io with a blocking interface.
4    
5     =head1 SYNOPSIS
6    
7     use Coro::Handle;
8    
9     =head1 DESCRIPTION
10    
11     This module implements io-handles in a coroutine-compatible way, that is,
12     other coroutines can run while reads or writes block on the handle. It
13     does NOT inherit from IO::Handle but uses tied objects.
14    
15     =over 4
16    
17     =cut
18    
19     package Coro::Handle;
20    
21 root 1.10 no warnings qw(uninitialized);
22 root 1.9
23 root 1.1 use Errno ();
24     use base 'Exporter';
25    
26     $VERSION = 0.45;
27    
28     @EXPORT = qw(unblock);
29    
30     =item $fh = new_from_fh Coro::Handle $fhandle [, arg => value...]
31    
32     Create a new non-blocking io-handle using the given
33     perl-filehandle. Returns undef if no fhandle is given. The only other
34     supported argument is "timeout", which sets a timeout for each operation.
35    
36     =cut
37    
38     sub new_from_fh {
39     my $class = shift;
40     my $fh = shift or return;
41     my $self = do { local *Coro::Handle };
42    
43     my ($package, $filename, $line) = caller;
44     $filename =~ s/^.*[\/\\]//;
45    
46     tie $self, Coro::Handle::FH, fh => $fh, desc => "$filename:$line", @_;
47    
48 root 1.16 my $_fh = select bless \$self, ref $class ? ref $class : $class; $| = 1; select $_fh;
49 root 1.1 }
50    
51     =item $fh = unblock $fh
52    
53     This is a convinience function that just calls C<new_from_fh> on the given
54     filehandle. Use it to replace a normal perl filehandle by a non-blocking
55     equivalent.
56    
57     =cut
58    
59     sub unblock($) {
60     new_from_fh Coro::Handle $_[0];
61     }
62    
63     =item $fh->writable, $fh->readable
64    
65     Wait until the filehandle is readable or writable (and return true) or
66     until an error condition happens (and return false).
67    
68     =cut
69    
70 root 1.5 sub readable { Coro::Handle::FH::readable(tied ${$_[0]}) }
71     sub writable { Coro::Handle::FH::writable(tied ${$_[0]}) }
72 root 1.1
73     =item $fh->readline([$terminator])
74    
75     Like the builtin of the same name, but allows you to specify the input
76     record separator in a coroutine-safe manner (i.e. not using a global
77     variable).
78    
79     =cut
80    
81     sub readline { tied(${+shift})->READLINE(@_) }
82    
83     =item $fh->autoflush([...])
84    
85     Always returns true, arguments are being ignored (exists for compatibility
86     only). Might change in the future.
87    
88     =cut
89    
90     sub autoflush { !0 }
91    
92 root 1.9 =item $fh->fileno, $fh->close,
93     $fh->read, $fh->sysread, $fh->syswrite,
94     $fh->print, $fh->printf
95    
96     Work like their function equivalents (except read, which works like
97     sysread. You should not use the read function with Coro::Handles, it will
98     work but it's not efficient).
99 root 1.1
100     =cut
101    
102 root 1.9 sub read { Coro::Handle::FH::READ (tied ${$_[0]}, $_[1], $_[2], $_[3]) }
103     sub sysread { Coro::Handle::FH::READ (tied ${$_[0]}, $_[1], $_[2], $_[3]) }
104     sub syswrite { Coro::Handle::FH::WRITE (tied ${$_[0]}, $_[1], $_[2], $_[3]) }
105     sub print { Coro::Handle::FH::WRITE (tied ${+shift}, join "", @_) }
106     sub printf { Coro::Handle::FH::PRINTF(tied ${+shift}, @_) }
107     sub fileno { Coro::Handle::FH::FILENO(tied ${$_[0]}) }
108     sub close { Coro::Handle::FH::CLOSE (tied ${$_[0]}) }
109 root 1.1
110     =item $fh->timeout([...])
111    
112     The optional agrument sets the new timeout (in seconds) for this
113     handle. Returns the current (new) value.
114    
115     C<0> is a valid timeout, use C<undef> to disable the timeout.
116    
117     =cut
118    
119     sub timeout {
120 root 1.4 my $self = tied(${$_[0]});
121 root 1.6 if (@_ > 1) {
122     $self->[2] = $_[1];
123     $self->[5]->timeout($_[1]) if $self->[5];
124     $self->[6]->timeout($_[1]) if $self->[6];
125 root 1.1 }
126 root 1.6 $self->[2];
127 root 1.4 }
128    
129     =item $fh->fh
130    
131     Returns the "real" (non-blocking) filehandle. Use this if you want to
132     do operations on the file handle you cannot do using the Coro::Handle
133     interface.
134    
135 root 1.11 =item $fh->rbuf
136 root 1.10
137 root 1.13 Returns the current contents of the read buffer (this is an lvalue, so you
138 root 1.11 can change the read buffer if you like).
139    
140 root 1.13 You can use this function to implement your own optimized reader when neither
141 root 1.11 readline nor sysread are viable candidates, like this:
142    
143     # first get the _real_ non-blocking filehandle
144 root 1.15 # and fetch a reference to the read buffer
145 root 1.11 my $nb_fh = $fh->fh;
146 root 1.15 my $buf = \$fh->rbuf;
147 root 1.11
148     for(;;) {
149     # now use buffer contents, modifying
150     # if necessary to reflect the removed data
151    
152 root 1.15 last if $$buf ne ""; # we have leftover data
153 root 1.11
154     # read another buffer full of data
155     $fh->readable or die "end of file";
156 root 1.15 sysread $nb_fh, $$buf, 8192;
157 root 1.11 }
158 root 1.10
159 root 1.4 =cut
160    
161     sub fh {
162 root 1.10 (tied ${$_[0]})->[0];
163     }
164    
165 root 1.11 sub rbuf : lvalue {
166     tied(${$_[0]})->[3];
167 root 1.1 }
168    
169     package Coro::Handle::FH;
170    
171 root 1.10 no warnings qw(uninitialized);
172 root 1.9
173 root 1.1 use Fcntl ();
174     use Errno ();
175     use Carp 'croak';
176    
177     use Coro::Event;
178     use Event::Watcher qw(R W E);
179    
180 root 1.6 # formerly a hash, but we are speed-critical, so try
181     # to be faster even if it hurts.
182     #
183     # 0 FH
184     # 1 desc
185     # 2 timeout
186     # 3 rb
187 root 1.10 # 4 wb # unused
188 root 1.6 # 5 rw
189     # 6 ww
190    
191 root 1.1 sub TIEHANDLE {
192     my $class = shift;
193 root 1.6 my %args = @_;
194 root 1.1
195 root 1.6 my $self = bless [], $class;
196     $self->[0] = $args{fh};
197     $self->[1] = $args{desc};
198     $self->[2] = $args{timeout};
199     $self->[3] = "";
200     $self->[4] = "";
201 root 1.1
202 root 1.6 fcntl $self->[0], &Fcntl::F_SETFL, &Fcntl::O_NONBLOCK
203 root 1.1 or croak "fcntl(O_NONBLOCK): $!";
204    
205     $self;
206     }
207    
208 root 1.6 sub cleanup {
209     $_[0][3] = "";
210 root 1.7 ($_[0][5])->cancel if defined $_[0][5]; $_[0][5] = undef;
211 root 1.6
212     $_[0][4] = "";
213 root 1.7 ($_[0][6])->cancel if defined $_[0][6]; $_[0][6] = undef;
214 root 1.6 }
215    
216 root 1.1 sub OPEN {
217 root 1.6 &cleanup;
218 root 1.1 my $self = shift;
219 root 1.6 my $r = @_ == 2 ? open $self->[0], $_[0], $_[1]
220     : open $self->[0], $_[0], $_[1], $_[2];
221 root 1.1 if ($r) {
222 root 1.6 fcntl $self->[0], &Fcntl::F_SETFL, &Fcntl::O_NONBLOCK
223 root 1.1 or croak "fcntl(O_NONBLOCK): $!";
224     }
225     $r;
226 root 1.9 }
227    
228     sub PRINT {
229 root 1.12 WRITE(shift, join "", @_);
230 root 1.9 }
231    
232     sub PRINTF {
233     WRITE(shift, sprintf(shift,@_));
234     }
235    
236     sub GETC {
237     my $buf;
238     READ($_[0], $buf, 1);
239     $buf;
240     }
241    
242     sub BINMODE {
243     binmode $_[0][0];
244     }
245    
246     sub TELL {
247     use Carp (); Carp::croak("Coro::Handle's don't support tell()");
248     }
249    
250     sub SEEK {
251     use Carp (); Carp::croak("Coro::Handle's don't support seek()");
252     }
253    
254     sub EOF {
255     use Carp (); Carp::croak("Coro::Handle's don't support eof()");
256 root 1.1 }
257    
258     sub CLOSE {
259 root 1.6 &cleanup;
260     close $_[0][0];
261 root 1.1 }
262    
263 root 1.6 sub DESTROY {
264     &cleanup;
265 root 1.1 }
266    
267 root 1.6 sub FILENO {
268     fileno $_[0][0];
269 root 1.1 }
270    
271 root 1.8 # seems to be called for stringification (how weird), at least
272     # when DumpValue::dumpValue is used to print this.
273     sub FETCH {
274     "$_[0]<$_[0][1]>";
275     }
276    
277 root 1.1 sub readable {
278 root 1.6 ($_[0][5] ||= Coro::Event->io(
279     fd => $_[0][0],
280     desc => "$_[0][1] R",
281     timeout => $_[0][2],
282 root 1.1 poll => R+E,
283 root 1.3 ))->next->{Coro::Event}[5] & R;
284 root 1.1 }
285    
286 root 1.6 sub writable {
287     ($_[0][6] ||= Coro::Event->io(
288     fd => $_[0][0],
289     desc => "$_[0][1] W",
290     timeout => $_[0][2],
291     poll => W+E,
292     ))->next->{Coro::Event}[5] & W;
293     }
294    
295 root 1.1 sub WRITE {
296     my $len = defined $_[2] ? $_[2] : length $_[1];
297     my $ofs = $_[3];
298     my $res = 0;
299    
300     while() {
301 root 1.6 my $r = syswrite $_[0][0], $_[1], $len, $ofs;
302 root 1.1 if (defined $r) {
303     $len -= $r;
304     $ofs += $r;
305     $res += $r;
306     last unless $len;
307     } elsif ($! != Errno::EAGAIN) {
308     last;
309     }
310 root 1.6 last unless &writable;
311 root 1.1 }
312    
313     return $res;
314     }
315    
316     sub READ {
317     my $len = $_[2];
318     my $ofs = $_[3];
319     my $res = 0;
320    
321     # first deplete the read buffer
322 root 1.14 if (length $_[0][3]) {
323 root 1.6 my $l = length $_[0][3];
324 root 1.1 if ($l <= $len) {
325 root 1.14 substr($_[1], $ofs) = $_[0][3]; $_[0][3] = "";
326 root 1.1 $len -= $l;
327     $res += $l;
328     return $res unless $len;
329     } else {
330 root 1.6 substr($_[1], $ofs) = substr($_[0][3], 0, $len);
331     substr($_[0][3], 0, $len) = "";
332 root 1.1 return $len;
333     }
334     }
335    
336     while() {
337 root 1.6 my $r = sysread $_[0][0], $_[1], $len, $ofs;
338 root 1.1 if (defined $r) {
339     $len -= $r;
340     $ofs += $r;
341     $res += $r;
342     last unless $len && $r;
343     } elsif ($! != Errno::EAGAIN) {
344     last;
345     }
346 root 1.6 last unless &readable;
347 root 1.1 }
348    
349     return $res;
350     }
351    
352     sub READLINE {
353 root 1.6 my $irs = @_ > 1 ? $_[1] : $/;
354 root 1.1
355     while() {
356 root 1.6 my $pos = index $_[0][3], $irs;
357 root 1.1 if ($pos >= 0) {
358     $pos += length $irs;
359 root 1.6 my $res = substr $_[0][3], 0, $pos;
360     substr ($_[0][3], 0, $pos) = "";
361 root 1.1 return $res;
362     }
363 root 1.6
364     my $r = sysread $_[0][0], $_[0][3], 8192, length $_[0][3];
365 root 1.1 if (defined $r) {
366     return undef unless $r;
367 root 1.6 } elsif ($! != Errno::EAGAIN || !&readable) {
368 root 1.1 return undef;
369     }
370     }
371     }
372    
373     1;
374    
375     =head1 BUGS
376    
377     - Perl's IO-Handle model is THE bug.
378    
379     =head1 AUTHOR
380    
381     Marc Lehmann <pcg@goof.com>
382     http://www.goof.com/pcg/marc/
383    
384     =cut
385