home *** CD-ROM | disk | FTP | other *** search
/ PC Professionell 2004 December / PCpro_2004_12.ISO / files / webserver / tsw / TSW_3.4.0.exe / Apache2 / perl / Trap.pm < prev    next >
Encoding:
Perl POD Document  |  2002-04-15  |  5.4 KB  |  243 lines

  1. package IO::Select::Trap;
  2.  
  3. use strict;
  4. use IO::Select;
  5.  
  6. use vars qw/$VERSION/;
  7. $VERSION = '0.03';
  8.  
  9. sub new {
  10.     my $pkg = shift;
  11.     my $opts = (ref $_[0] eq 'HASH') ? shift : {};
  12.     my $self = bless {
  13.         ioselect => new IO::Select(),
  14.         handles => {},
  15.         traps => ($opts->{traps} or 'String|Scalar'),
  16.         debug => (exists $opts->{debug} ? $opts->{debug} : 1),
  17.     }, (ref $pkg || $pkg);
  18.  
  19.     $self->add(@_) if @_;
  20.     $self;
  21. }
  22.  
  23. sub _update {
  24.     my ($self) = shift;
  25.     my $add = shift eq 'add';
  26.     
  27.     my @pthru;
  28.     foreach my $h (@_) {
  29.         next unless defined $h;
  30.         unless ($self->_trapped($h)) {
  31.             push @pthru, $h;
  32.             next;
  33.         }
  34.                 
  35.         if ($add) {
  36.                 $self->{handles}->{\*{$h}} = $h;
  37.         } else {
  38.                 delete $_[0]->{handles}->{\*{$h}};
  39.         }
  40.     }
  41.     return \@pthru;
  42. }
  43.  
  44. sub _trapped { 
  45.     my ($self, $h) = @_;
  46.     (ref $h) =~ /$self->{traps}/i;
  47. }
  48.  
  49. sub _count {
  50.     my $self = shift;
  51.     return scalar keys %{$self->{handles}};
  52. }
  53.  
  54. sub _can_read {
  55.     my $self = shift;
  56.     return unless $self->_count;
  57.     my @result;
  58.     while (my ($k, $h) = each %{$self->{handles}}) {
  59.         push @result, $h if (length ${$h->sref});
  60.     } 
  61.     return wantarray ? @result : \@result;
  62. }
  63.  
  64. sub _can_write {
  65.     my $self = shift;
  66.     return unless $self->_count;
  67.     my @result;
  68.     while (my ($k, $h) = each %{$self->{handles}}) {
  69.         push @result, $h if ($h->opened);
  70.     } 
  71.     return wantarray ? @result : \@result;
  72. }
  73.  
  74. sub _has_exception {}
  75.  
  76. sub add {
  77.     my $self = shift;
  78.     my $pthru = $self->_update('add', @_);
  79.     $self->{ioselect}->add(@$pthru) if @$pthru;
  80. }
  81.  
  82. sub remove {
  83.     my $self = shift;
  84.     my $pthru = $self->_update('remove', @_);
  85.     $self->{ioselect}->remove(@$pthru) if @$pthru;
  86. }
  87.  
  88. sub select {
  89.     shift if defined $_[0] && !ref($_[0]);
  90.     my ($r, $w, $e, $t) = @_;
  91.     my (@RR, @WR, @ER);
  92.     
  93.     my $rready = defined $r ? $r->_can_read : undef;
  94.     my $wready = defined $w ? $w->_can_write : undef;
  95.     my $eready = defined $e ? $e->_has_exception : undef;
  96.  
  97.     push @RR, @$rready if defined $rready;
  98.     push @WR, @$wready if defined $wready;
  99.     push @ER, @$eready if defined $eready;
  100.  
  101.     my ($ir) = defined $r ? $r->{ioselect} : undef;
  102.     my ($iw) = defined $w ? $w->{ioselect} : undef;
  103.     my ($ie) = defined $e ? $e->{ioselect} : undef;
  104.     
  105.     if (@RR || @WR || @ER) {
  106.         $t = 0 unless (defined $t); # Force non-blocking select()
  107.     }
  108.     
  109.     ($rready, $wready, $eready) = IO::Select->select($ir, $iw, $ie, $t);
  110.     push @RR, @$rready if defined $rready;
  111.     push @WR, @$wready if defined $wready;
  112.     push @ER, @$eready if defined $eready;
  113.  
  114.  
  115.     return (\@RR, \@WR, \@ER);
  116. }
  117.  
  118. sub exists {
  119.     return unless defined $_[1];
  120.     exists $_[0]->{handles}->{\*{$_[1]}};
  121. }
  122.  
  123. sub can_read {
  124.     my ($self, $t) = @_;
  125.     my @hready = $self->_can_read();
  126.     $t = 0 if (! defined $t && @hready);
  127.     my @iready = $self->{ioselect}->can_read($t);
  128.     return 
  129.         @iready ? 
  130.             @hready ? (@iready, @hready) : @iready
  131.                 : @hready;
  132. }
  133.  
  134. sub can_write {
  135.     my ($self, $t) = @_;
  136.     my @hready = $self->_can_write();
  137.     $t = 0 if (! defined $t && @hready);
  138.     my @iready = $self->{ioselect}->can_write($t);
  139.     return 
  140.         @iready ? 
  141.             @hready ? (@iready, @hready) : @iready
  142.                 : @hready;
  143. }
  144.  
  145. sub has_exception {
  146.     my ($self, $t) = @_;
  147.     my @hready = $self->_has_exception();
  148.     $t = 0 if (! defined $t && @hready);
  149.     my @iready = $self->{ioselect}->has_exception($t);
  150.     return 
  151.         @iready ? 
  152.             @hready ? (@iready, @hready) : @iready
  153.                 : @hready;
  154. }
  155.  
  156. sub count {
  157.     my $self = shift;
  158.     return $self->{ioselect}->count
  159.         + scalar keys %{$self->{handles}};
  160. }
  161.  
  162. sub _debug {
  163.     my $self = shift;
  164.     print STDERR "$self: ", @_ if $self->{debug};
  165. }
  166.  
  167.  
  168. 1;
  169. __END__
  170.  
  171. =head1 NAME
  172.  
  173. IO::Select::Trap - IO::Select() functionality on Scalar-based Filehandles
  174.  
  175. =head1 SYNOPSIS
  176.  
  177.  use IO::Select::Trap;
  178.  use IO::String;
  179.  
  180.  my $ios = new IO::String();
  181.  my $sock = new IO::Socket();
  182.  my $rb = new IO::Select::Trap(<{ trap=>'Scalar|String' }>, $ios, $sock);
  183.  my $wb = new IO::Select::Trap(<{ trap=>'Scalar|String' }>, $ios, $sock);
  184.  my ($rready, $wready) = IO::Select::Trap->select($rb, $wb);
  185.  
  186. =head1 DESCRIPTION
  187.  
  188. IO::Select::Trap is a wrapper for C<IO::Select> which enables use of the 
  189. C<IO::Select-E<gt>select()> method on IO::Scalar or IO::String
  190. object/filehandles. Other filehandle object types (ie IO::Socket) are passed
  191. through to IO::Select for processing.  Most of the IO::Select interface is 
  192. supported.
  193.  
  194. An IO::String/Scalar object/filehandle is ready for reading when it contains 
  195. some amount of data.  It will always be ready for writing.  Also, IO::String/Scalar
  196. objects will *never* block.
  197.  
  198. When calling select(), the trapped objects are evaluated first.  If any
  199. are found to be ready, the IO::Select->select() is called with a timeout of
  200. '0'.  Otherwise it is called with the supplied timeout (or undef).
  201.  
  202. =head1 OPTIONS
  203.  
  204. =over 4
  205.  
  206. =item trap I<experimental>
  207.  
  208. REGEX that specifies the IO objects to trap.
  209.  
  210. =back
  211.  
  212. =head1 LIMITATIONS
  213.  
  214. Currently, the select(), can_read(), etc. methods only support
  215. trapped IO::Scalar or IO::String objects.  Other trapped objects will 
  216. probably break the tests that the methods use to determine read/write ability.
  217.  
  218. The is a bug when using IO::Scalar objects, in that two IO::Scalars can't be
  219. compared.  Eg:
  220.  
  221.   $ios = new IO::Scalar;
  222.   $ios2 = $ios;
  223.   
  224.   if ($ios == $ios2) { #...
  225.   
  226. .. causes a runtime error.  A fix has been sent to to the author, and should be
  227. included in a future version.
  228.  
  229. =head1 AUTHOR & COPYRIGHT
  230.  
  231. Scott Scecina, E<lt>scotts@inmind.comE<gt>
  232.  
  233. Except where otherwise noted, IO::Select::Trap is 
  234. Copyright 2001 Scott Scecina. All rights reserved. 
  235. IO::Select::Trap is free software; you may redistribute 
  236. it and/or modify it under the same terms as Perl itself.
  237.  
  238. =head1 SEE ALSO
  239.  
  240. L<IO::Select>.
  241.  
  242. =cut
  243.