ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/AnyEvent/lib/AnyEvent/Handle.pm
Revision: 1.1
Committed: Sun Apr 27 16:56:17 2008 UTC (16 years, 1 month ago) by elmex
Branch: MAIN
Log Message:
added IO::AnyEvent as AnyEvent::Handle and AnyEvent::Socket, including tests

File Contents

# User Rev Content
1 elmex 1.1 package AnyEvent::Handle;
2    
3     use warnings;
4     use strict;
5    
6     use AnyEvent;
7     use IO::Handle;
8     use Errno qw/EAGAIN EINTR/;
9    
10     =head1 NAME
11    
12     AnyEvent::Handle - non-blocking I/O on filehandles via AnyEvent
13    
14     =head1 VERSION
15    
16     Version 0.01
17    
18     =cut
19    
20     our $VERSION = '0.01';
21    
22     =head1 SYNOPSIS
23    
24     use AnyEvent;
25     use AnyEvent::Handle;
26    
27     my $cv = AnyEvent->condvar;
28    
29     my $ae_fh = AnyEvent::Handle->new (fh => \*STDIN);
30    
31     $ae_fh->readlines (sub {
32     my ($ae_fh, @lines) = @_;
33     for (@lines) {
34     chomp;
35     print "Line: $_";
36     }
37     $cv->broadcast;
38     });
39    
40     $cv->wait;
41    
42     =head1 DESCRIPTION
43    
44     This module is a helper module to make it easier to do non-blocking I/O
45     on filehandles (and sockets, see L<AnyEvent::Socket>).
46    
47     The event loop is provided by L<AnyEvent>.
48    
49     =head1 METHODS
50    
51     =over 4
52    
53     =item B<new (%args)>
54    
55     The constructor has these arguments:
56    
57     =over 4
58    
59     =item fh => $filehandle
60    
61     The filehandle this L<AnyEvent::Handle> object will operate on.
62    
63     NOTE: The filehandle will be set to non-blocking.
64    
65     =item read_block_size => $size
66    
67     The default read block size use for reads via the C<on_read>
68     method.
69    
70     =back
71    
72     =cut
73    
74     sub new {
75     my $this = shift;
76     my $class = ref($this) || $this;
77     my $self = {
78     read_block_size => 4096,
79     rbuf => '',
80     @_
81     };
82     bless $self, $class;
83    
84     $self->{fh}->blocking (0) if $self->{fh};
85    
86     if ($self->{on_read}) {
87     $self->on_read ($self->{on_read});
88    
89     } elsif ($self->{on_readline}) {
90     $self->readlines ($self->{on_readline});
91     }
92    
93     return $self
94     }
95    
96     =item B<fh>
97    
98     This method returns the filehandle of the L<AnyEvent::Handle> object.
99    
100     =cut
101    
102     sub fh { $_[0]->{fh} }
103    
104     =item B<on_read ($callback)>
105    
106     This method installs a C<$callback> that will be called
107     when new data arrived. You can access the read buffer via the C<rbuf>
108     method (see below).
109    
110     The first argument of the C<$callback> will be the L<AnyEvent::Handle> object.
111    
112     =cut
113    
114     sub on_read {
115     my ($self, $cb) = @_;
116     $self->{on_read} = $cb;
117    
118     unless (defined $self->{on_read}) {
119     delete $self->{on_read_w};
120     return;
121     }
122    
123     $self->{on_read_w} =
124     AnyEvent->io (poll => 'r', fh => $self->{fh}, cb => sub {
125     #d# warn "READ:[$self->{read_size}] $self->{read_block_size} : ".length ($self->{rbuf})."\n";
126     my $rbuf_len = length $self->{rbuf};
127     my $l;
128     if (defined $self->{read_size}) {
129     $l = sysread $self->{fh}, $self->{rbuf},
130     ($self->{read_size} - $rbuf_len), $rbuf_len;
131     } else {
132     $l = sysread $self->{fh}, $self->{rbuf}, $self->{read_block_size}, $rbuf_len;
133     }
134     #d# warn "READL $l [$self->{rbuf}]\n";
135    
136     if (not defined $l) {
137     return if $! == EAGAIN || $! == EINTR;
138     $self->{on_error}->($self, $!) if $self->{on_error};
139     delete $self->{on_read_w};
140    
141     } elsif ($l == 0) {
142     $self->{on_eof}->($self) if $self->{on_eof};
143     delete $self->{on_read_w};
144    
145     } else {
146     $self->{on_read}->($self);
147     }
148     });
149     }
150    
151     =item B<on_error ($callback)>
152    
153     Whenever a read or write operation resulted in an error the C<$callback>
154     will be called.
155    
156     The first argument of C<$callback> will be the L<AnyEvent::Handle> object itself
157     and the second argument will be the value of C<$!>.
158    
159     =cut
160    
161     sub on_error {
162     $_[0]->{on_error} = $_[1];
163     }
164    
165     =item B<on_eof ($callback)>
166    
167     Installs the C<$callback> that will be called when the end of file is
168     encountered in a read operation this C<$callback> will be called. The first
169     argument will be the L<AnyEvent::Handle> object itself.
170    
171     =cut
172    
173     sub on_eof {
174     $_[0]->{on_eof} = $_[1];
175     }
176    
177     =item B<rbuf>
178    
179     Returns a reference to the read buffer.
180    
181     NOTE: The read buffer should only be used or modified if the C<on_read>
182     method is used directly. The C<read> and C<readlines> methods will provide
183     the read data to their callbacks.
184    
185     =cut
186    
187     sub rbuf : lvalue { $_[0]->{rbuf} }
188    
189     =item B<read ($len, $callback)>
190    
191     Will read exactly C<$len> bytes from the filehandle and call the C<$callback>
192     if done so. The first argument to the C<$callback> will be the L<AnyEvent::Handle>
193     object itself and the second argument the read data.
194    
195     NOTE: This method will override any callbacks installed via the C<on_read> method.
196    
197     =cut
198    
199     sub read {
200     my ($self, $len, $cb) = @_;
201    
202     $self->{read_cb} = $cb;
203     my $old_blk_size = $self->{read_block_size};
204     $self->{read_block_size} = $len;
205    
206     $self->on_read (sub {
207     #d# warn "OFOFO $len || ".length($_[0]->{rbuf})."||\n";
208    
209     if ($len == length $_[0]->{rbuf}) {
210     $_[0]->{read_block_size} = $old_blk_size;
211     $_[0]->on_read (undef);
212     $_[0]->{read_cb}->($_[0], (substr $self->{rbuf}, 0, $len, ''));
213     }
214     });
215     }
216    
217     =item B<readlines ($callback)>
218    
219     =item B<readlines ($sep, $callback)>
220    
221     This method will read lines from the filehandle, seperated by C<$sep> or C<"\n">
222     if C<$sep> is not provided. C<$sep> will be used as part of a regex, so it can be
223     a regex itself and won't be quoted!
224    
225     The C<$callback> will be called when at least one
226     line could be read. The first argument to the C<$callback> will be the L<AnyEvent::Handle>
227     object itself and the rest of the arguments will be the read lines.
228    
229     NOTE: This method will override any callbacks installed via the C<on_read> method.
230    
231     =cut
232    
233     sub readlines {
234     my ($self, $NL, $cb) = @_;
235    
236     if (ref $NL) {
237     $cb = $NL;
238     $NL = "\n";
239     }
240    
241     $self->{on_readline} = $cb;
242    
243     $self->on_read (sub {
244     my @lines;
245     push @lines, $1 while $_[0]->{rbuf} =~ s/(.*)$NL//;
246     $self->{on_readline}->($_[0], @lines);
247     });
248     }
249    
250     =item B<write ($data)>
251    
252     =item B<write ($callback)>
253    
254     =item B<write ($data, $callback)>
255    
256     This method will write C<$data> to the filehandle and call the C<$callback>
257     afterwards. If only C<$callback> is provided it will be called when the
258     write buffer becomes empty the next time (or immediately if it already is empty).
259    
260     =cut
261    
262     sub write {
263     my ($self, $data, $cb) = @_;
264     if (ref $data) { $cb = $data; undef $data }
265     push @{$self->{write_bufs}}, [$data, $cb];
266     $self->_check_writer;
267     }
268    
269     sub _check_writer {
270     my ($self) = @_;
271    
272     if ($self->{write_w}) {
273     unless ($self->{write_cb}) {
274     while (@{$self->{write_bufs}} && not defined $self->{write_bufs}->[0]->[1]) {
275     my $wba = shift @{$self->{write_bufs}};
276     $self->{wbuf} .= $wba->[0];
277     }
278     }
279     return;
280     }
281    
282     my $wba = shift @{$self->{write_bufs}}
283     or return;
284    
285     unless (defined $wba->[0]) {
286     $wba->[1]->($self) if $wba->[1];
287     $self->_check_writer;
288     return;
289     }
290    
291     $self->{wbuf} = $wba->[0];
292     $self->{write_cb} = $wba->[1];
293    
294     $self->{write_w} =
295     AnyEvent->io (poll => 'w', fh => $self->{fh}, cb => sub {
296     my $l = syswrite $self->{fh}, $self->{wbuf}, length $self->{wbuf};
297    
298     if (not defined $l) {
299     return if $! == EAGAIN || $! == EINTR;
300     delete $self->{write_w};
301    
302     $self->{on_error}->($self, $!) if $self->{on_error};
303    
304     } else {
305     substr $self->{wbuf}, 0, $l, '';
306    
307     if (length ($self->{wbuf}) == 0) {
308     $self->{write_cb}->($self) if $self->{write_cb};
309    
310     delete $self->{write_w};
311     delete $self->{wbuf};
312     delete $self->{write_cb};
313    
314     $self->_check_writer;
315     }
316     }
317     });
318     }
319    
320     =back
321    
322     =head1 AUTHOR
323    
324     Robin Redeker, C<< <elmex at ta-sa.org> >>
325    
326     =head1 BUGS
327    
328     Please report any bugs or feature requests to
329     C<bug-io-anyevent at rt.cpan.org>, or through the web interface at
330     L<http://rt.cpan.org/NoAuth/ReportBug.html?Queue=IO-AnyEvent>.
331     I will be notified, and then you'll automatically be notified of progress on
332     your bug as I make changes.
333    
334     =head1 SUPPORT
335    
336     You can find documentation for this module with the perldoc command.
337    
338     perldoc AnyEvent::Handle
339    
340     You can also look for information at:
341    
342     =over 4
343    
344     =item * AnnoCPAN: Annotated CPAN documentation
345    
346     L<http://annocpan.org/dist/IO-AnyEvent>
347    
348     =item * CPAN Ratings
349    
350     L<http://cpanratings.perl.org/d/IO-AnyEvent>
351    
352     =item * RT: CPAN's request tracker
353    
354     L<http://rt.cpan.org/NoAuth/Bugs.html?Dist=IO-AnyEvent>
355    
356     =item * Search CPAN
357    
358     L<http://search.cpan.org/dist/IO-AnyEvent>
359    
360     =back
361    
362     =head1 ACKNOWLEDGEMENTS
363    
364     =head1 COPYRIGHT & LICENSE
365    
366     Copyright 2008 Robin Redeker, all rights reserved.
367    
368     This program is free software; you can redistribute it and/or modify it
369     under the same terms as Perl itself.
370    
371     =cut
372    
373     1; # End of AnyEvent::Handle