home *** CD-ROM | disk | FTP | other *** search
/ Netrunner 2004 October / NETRUNNER0410.ISO / regular / ActivePerl-5.8.4.810-MSWin32-x86.msi / _d2da7a50d6c69d7ac042fa8858c9037b < prev    next >
Encoding:
Text File  |  2004-06-01  |  5.0 KB  |  156 lines

  1. # ======================================================================
  2. #
  3. # Copyright (C) 2000 Lincoln D. Stein
  4. #
  5. # ======================================================================
  6.  
  7. package IO::SessionSet;
  8.  
  9. use strict;
  10. use Carp;
  11. use IO::Select;
  12. use IO::Handle;
  13. use IO::SessionData;
  14.  
  15. use vars '$DEBUG';
  16. $DEBUG = 0;
  17.  
  18. # Class method new()
  19. # Create a new Session set.
  20. # If passed a listening socket, use that to
  21. # accept new IO::SessionData objects automatically.
  22. sub new {
  23.   my $pack = shift;
  24.   my $listen = shift;
  25.   my $self = bless { 
  26.                     sessions     => {},
  27.                     readers      => IO::Select->new(),
  28.                     writers      => IO::Select->new(),
  29.                    },$pack;
  30.   # if initialized with an IO::Handle object (or subclass)
  31.   # then we treat it as a listening socket.
  32.   if ( defined($listen) and $listen->can('accept') ) { 
  33.     $self->{listen_socket} = $listen;
  34.     $self->{readers}->add($listen);
  35.   }
  36.   return $self;
  37. }
  38.  
  39. # Object method: sessions()
  40. # Return list of all the sessions currently in the set.
  41. sub sessions { return values %{shift->{sessions}} };
  42.  
  43. # Object method: add()
  44. # Add a handle to the session set.  Will automatically
  45. # create a IO::SessionData wrapper around the handle.
  46. sub add {
  47.   my $self = shift;
  48.   my ($handle,$writeonly) = @_;
  49.   warn "Adding a new session for $handle.\n" if $DEBUG;
  50.   return $self->{sessions}{$handle} = $self->SessionDataClass->new($self,$handle,$writeonly);
  51. }
  52.  
  53. # Object method: delete()
  54. # Remove a session from the session set.  May pass either a handle or
  55. # a corresponding IO::SessionData wrapper.
  56. sub delete {
  57.   my $self = shift;
  58.   my $thing = shift;
  59.   my $handle = $self->to_handle($thing);
  60.   my $sess = $self->to_session($thing);
  61.   warn "Deleting session $sess handle $handle.\n" if $DEBUG;
  62.   delete $self->{sessions}{$handle};
  63.   $self->{readers}->remove($handle);
  64.   $self->{writers}->remove($handle);
  65. }
  66.  
  67. # Object method: to_handle()
  68. # Return a handle, given either a handle or a IO::SessionData object.
  69. sub to_handle {
  70.   my $self = shift;
  71.   my $thing = shift;
  72.   return $thing->handle if $thing->isa('IO::SessionData');
  73.   return $thing if defined (fileno $thing);
  74.   return;  # undefined value
  75. }
  76.  
  77. # Object method: to_session
  78. # Return a IO::SessionData object, given either a handle or the object itself.
  79. sub to_session {
  80.   my $self = shift;
  81.   my $thing = shift;
  82.   return $thing if $thing->isa('IO::SessionData');
  83.   return $self->{sessions}{$thing} if defined (fileno $thing);
  84.   return;  # undefined value
  85. }
  86.  
  87. # Object method: activate()
  88. # Called with parameters ($session,'read'|'write' [,$activate])
  89. # If called without the $activate argument, will return true
  90. # if the indicated handle is on the read or write IO::Select set.
  91. # May use either a session object or a handle as first argument.
  92. sub activate {
  93.   my $self = shift;
  94.   my ($thing,$rw,$act) = @_;
  95.   croak 'Usage $obj->activate($session,"read"|"write" [,$activate])'
  96.     unless @_ >= 2;
  97.   my $handle = $self->to_handle($thing);
  98.   my $select = lc($rw) eq 'read' ? 'readers' : 'writers';
  99.   my $prior = defined $self->{$select}->exists($handle);
  100.   if (defined $act && $act != $prior) {
  101.     $self->{$select}->add($handle)        if $act;
  102.     $self->{$select}->remove($handle) unless $act;
  103.     warn $act ? 'Activating' : 'Inactivating',
  104.            " handle $handle for ",
  105.             $rw eq 'read' ? 'reading':'writing',".\n" if $DEBUG;
  106.   }
  107.   return $prior;
  108. }
  109.  
  110. # Object method: wait()
  111. # Wait for I/O.  Handles writes automatically.  Returns a list of IO::SessionData
  112. # objects ready for reading.  
  113. # If there is a listen socket, then will automatically do an accept() and return
  114. # a new IO::SessionData object for that.
  115. sub wait {
  116.   my $self = shift;
  117.   my $timeout = shift;
  118.  
  119.   # Call select() to get the list of sessions that are ready for reading/writing.
  120.   croak "IO::Select->select() returned error: $!"
  121.     unless my ($read,$write) = 
  122.       IO::Select->select($self->{readers},$self->{writers},undef,$timeout);
  123.  
  124.   # handle queued writes automatically
  125.   foreach (@$write) {
  126.     my $session = $self->to_session($_);
  127.     warn "Writing pending data (",$session->pending+0," bytes) for $_.\n" if $DEBUG;
  128.     my $rc = $session->write;
  129.   }
  130.  
  131.   # Return list of sessions that are ready for reading.
  132.   # If one of the ready handles is the listen socket, then
  133.   # create a new session.
  134.   # Otherwise return the ready handles as a list of IO::SessionData objects.
  135.   my @sessions;
  136.   foreach (@$read) {
  137.     if ($_ eq $self->{listen_socket}) {
  138.       my $newhandle = $_->accept;
  139.       warn "Accepting a new handle $newhandle.\n" if $DEBUG;
  140.       my $newsess = $self->add($newhandle) if $newhandle;
  141.       push @sessions,$newsess;
  142.     } else {
  143.       push @sessions,$self->to_session($_);
  144.     }
  145.   }
  146.   return @sessions;
  147. }
  148.  
  149. # Class method: SessionDataClass
  150. # Return the string containing the name of the session data
  151. # wrapper class.  Subclass and override to use a different
  152. # session data class.
  153. sub SessionDataClass {  return 'IO::SessionData'; }
  154.  
  155. 1;
  156.