home *** CD-ROM | disk | FTP | other *** search
/ PC Professionell 2004 December / PCpro_2004_12.ISO / files / webserver / xampp / xampp-perl-addon-1.4.9-installer.exe / TwoWay.pm < prev    next >
Encoding:
Perl POD Document  |  2003-11-21  |  5.6 KB  |  208 lines

  1. # $Id: TwoWay.pm,v 1.16 2003/11/21 05:08:26 rcaputo Exp $
  2.  
  3. # Portable two-way pipe creation, trying as many different methods as
  4. # we can.
  5.  
  6. package POE::Pipe::TwoWay;
  7.  
  8. use strict;
  9.  
  10. use vars qw($VERSION);
  11. $VERSION = do {my@r=(q$Revision: 1.16 $=~/\d+/g);sprintf"%d."."%04d"x$#r,@r};
  12.  
  13. use Symbol qw(gensym);
  14. use IO::Socket;
  15. use POE::Pipe;
  16.  
  17. @POE::Pipe::TwoWay::ISA = qw( POE::Pipe );
  18.  
  19. sub DEBUG () { 0 }
  20.  
  21. sub new {
  22.   my $type         = shift;
  23.   my $conduit_type = shift;
  24.  
  25.   # Dummy object used to inherit the base POE::Pipe class.
  26.   my $self = bless [], $type;
  27.  
  28.   # Generate symbols to be used as filehandles for the pipe's ends.
  29.   my $a_read  = gensym();
  30.   my $a_write = gensym();
  31.   my $b_read  = gensym();
  32.   my $b_write = gensym();
  33.  
  34.   if (defined $conduit_type) {
  35.     return ($a_read, $a_write, $b_read, $b_write) if
  36.       $self->_try_type(
  37.         $conduit_type,
  38.         \$a_read, \$a_write,
  39.         \$b_read, \$b_write
  40.       );
  41.   }
  42.  
  43.   while (my $try_type = $self->get_next_preference()) {
  44.     return ($a_read, $a_write, $b_read, $b_write) if
  45.       $self->_try_type(
  46.         $try_type,
  47.         \$a_read, \$a_write,
  48.         \$b_read, \$b_write
  49.       );
  50.     $self->shift_preference();
  51.   }
  52.  
  53.   # There's nothing left to try.
  54.   DEBUG and warn "nothing worked";
  55.   return;
  56. }
  57.  
  58. # Try a pipe by type.
  59.  
  60. sub _try_type {
  61.   my ($self, $type, $a_read, $a_write, $b_read, $b_write) = @_;
  62.  
  63.   # Try a socketpair().
  64.   if ($type eq "socketpair") {
  65.     eval {
  66.       socketpair($$a_read, $$b_read, AF_UNIX, SOCK_STREAM, PF_UNSPEC)
  67.         or die "socketpair 1 failed: $!";
  68.     };
  69.  
  70.     # Socketpair failed.
  71.     if (length $@) {
  72.       warn "socketpair failed: $@" if DEBUG;
  73.       return;
  74.     }
  75.  
  76.     DEBUG and do {
  77.       warn "using UNIX domain socketpairs";
  78.       warn "ar($$a_read) aw($$a_write) br($$b_read) bw($$b_write)\n";
  79.     };
  80.  
  81.     # It's two-way, so each reader is also a writer.
  82.     $$a_write = $$a_read;
  83.     $$b_write = $$b_read;
  84.  
  85.     # Turn off buffering.  POE::Kernel does this for us, but someone
  86.     # might want to use the pipe class elsewhere.
  87.     select((select($$a_write), $| = 1)[0]);
  88.     select((select($$b_write), $| = 1)[0]);
  89.     return 1;
  90.   }
  91.  
  92.   # Try a couple pipe() calls.
  93.   if ($type eq "pipe") {
  94.     eval {
  95.       pipe($$a_read, $$b_write) or die "pipe 1 failed: $!";
  96.       pipe($$b_read, $$a_write) or die "pipe 2 failed: $!";
  97.     };
  98.  
  99.     # Pipe failed.
  100.     if (length $@) {
  101.       warn "pipe failed: $@" if DEBUG;
  102.       return;
  103.     }
  104.  
  105.     DEBUG and do {
  106.       warn "using a pipe";
  107.       warn "ar($$a_read) aw($$a_write) br($$b_read) bw($$b_write)\n";
  108.     };
  109.  
  110.     # Turn off buffering.  POE::Kernel does this for us, but someone
  111.     # might want to use the pipe class elsewhere.
  112.     select((select($$a_write), $| = 1)[0]);
  113.     select((select($$b_write), $| = 1)[0]);
  114.     return 1;
  115.   }
  116.  
  117.   # Try a pair of plain INET sockets.
  118.   if ($type eq "inet") {
  119.     eval {
  120.       ($$a_read, $$b_read) = $self->make_socket();
  121.     };
  122.  
  123.     # Sockets failed.
  124.     if (length $@) {
  125.       warn "make_socket failed: $@" if DEBUG;
  126.       return;
  127.     }
  128.  
  129.     DEBUG and do {
  130.       warn "using a plain INET socket";
  131.       warn "ar($$a_read) aw($$a_write) br($$b_read) bw($$b_write)\n";
  132.     };
  133.  
  134.     $$a_write = $$a_read;
  135.     $$b_write = $$b_read;
  136.  
  137.     # Turn off buffering.  POE::Kernel does this for us, but someone
  138.     # might want to use the pipe class elsewhere.
  139.     select((select($$a_write), $| = 1)[0]);
  140.     select((select($$b_write), $| = 1)[0]);
  141.     return 1;
  142.   }
  143.  
  144.   DEBUG and warn "unknown OneWay socket type ``$type''";
  145.   return;
  146. }
  147.  
  148. ###############################################################################
  149. 1;
  150.  
  151. __END__
  152.  
  153. =head1 NAME
  154.  
  155. POE::Pipe::TwoWay - portable two-way pipe creation (works without POE)
  156.  
  157. =head1 SYNOPSIS
  158.  
  159.   my ($a_read, $a_write, $b_read, $b_write) = POE::Pipe::TwoWay->new();
  160.   die "couldn't create a pipe: $!" unless defined $a_read;
  161.  
  162. =head1 DESCRIPTION
  163.  
  164. POE::Pipe::TwoWay makes unbuffered two-way pipes or it dies trying.
  165. It can be more frugal with filehandles than two OneWay pipes when
  166. socketpair() is available.
  167.  
  168. Pipes are troublesome beasts because the different pipe creation
  169. methods have spotty support from one system to another.  Some systems
  170. have C<pipe()>, others have C<socketfactory()>, and still others have
  171. neither.
  172.  
  173. POE::Pipe::TwoWay tries different ways to make a pipe in the hope that
  174. one of them will succeed on any given platform.  It tries them in
  175. socketpair() -> pipe() -> IO::Socket::INET order.  If socketpair() is
  176. available, the two-way pipe will use half as many filehandles as two
  177. one-way pipes.
  178.  
  179. So anyway, the syntax is pretty easy:
  180.  
  181.   my ($a_read, $a_write, $b_read, $b_write) = POE::Pipe::TwoWay->new();
  182.   die "couldn't create a pipe: $!" unless defined $a_read;
  183.  
  184. And now you have an unbuffered pipe with two read/write sides, A and
  185. B.  Writing to C<$a_write> passes data to C<$b_read>, and writing to
  186. C<$b_write> passes data to C<$a_read>.
  187.  
  188. =head1 DEBUGGING
  189.  
  190. It's possible to force POE::Pipe::TwoWay to use one of its underlying
  191. pipe methods.  This was implemented for exercising each method in
  192. tests, but it's possibly useful for others.
  193.  
  194. However, forcing TwoWay's pipe method isn't documented because it's
  195. cheezy and likely to change.  Use it at your own risk.
  196.  
  197. =head1 BUGS
  198.  
  199. The INET domain socket method may block for up to 1s if it fails.
  200.  
  201. =head1 AUTHOR & COPYRIGHT
  202.  
  203. POE::Pipe::TwoWay is copyright 2000 by Rocco Caputo.  All rights
  204. reserved.  POE::Pipe::TwoWay is free software; you may redistribute it
  205. and/or modify it under the same terms as Perl itself.
  206.  
  207. =cut
  208.