| POE documentation | Contained in the POE distribution. |
POE::Pipe::OneWay - a portable API for one-way pipes
my ($read, $write) = POE::Pipe::OneWay->new(); die "couldn't create a pipe: $!" unless defined $read;
The right way to create an anonymous pipe varies from one operating
system to the next. Some operating systems support pipe(). Others
require socketpair(). And a few operating systems support neither,
so a plain old socket must be created.
POE::Pipe::OneWay will attempt to create a unidirectional pipe using
pipe(), socketpair(), and IO::Socket::INET, in that order.
Exceptions are hardcoded for operating systems with broken or
nonstandard behaviors.
The upshot of all this is that an application can portably create a one-way pipe by instantiating POE::Pipe::OneWay. The work of deciding how to create the pipe and opening the handles will be taken care of internally.
POE::Pipe::OneWay may be used outside of POE, as it doesn't use POE internally.
Create a new one-way pipe, optionally constraining it to a particular TYPE of pipe. One-way pipes have two ends: a "read" end and a "write" end. On success, new() returns two handles: one for the "read" end and one for the "write" end. Returns nothing on failure, and sets $! to explain why the constructor failed.
my ($read, $write) = POE::Pipe::OneWay->new(); die $! unless defined $read;
TYPE may be one of "pipe", "socketpair", or "inet". When set,
POE::Pipe::OneWay will constrain its search to either pipe(), a
UNIX-domain socketpair(), or plain old sockets, respectively.
Otherwise new() will try each method in order, or a particular method
predetermined to be the best one for the current operating
environment.
POE::Pipe::OneWay may block up to one second on some systems if failure occurs while trying to create "inet" sockets.
POE::Pipe::OneWay is copyright 2000-2008 by Rocco Caputo. All rights reserved. POE::Pipe::OneWay is free software; you may redistribute it and/or modify it under the same terms as Perl itself.
| POE documentation | Contained in the POE distribution. |
# Portable one-way pipe creation, trying as many different methods as # we can. package POE::Pipe::OneWay; use strict; use vars qw($VERSION); $VERSION = '1.311'; # NOTE - Should be #.### (three decimal places) use Symbol qw(gensym); use IO::Socket qw( AF_UNIX SOCK_STREAM PF_UNSPEC ); use POE::Pipe; @POE::Pipe::OneWay::ISA = qw( POE::Pipe ); sub DEBUG () { 0 } sub new { my $type = shift; my $conduit_type = shift; # Dummy object used to inherit the base POE::Pipe class. my $self = bless [], $type; # Generate symbols to be used as filehandles for the pipe's ends. my $a_read = gensym(); my $b_write = gensym(); if (defined $conduit_type) { return ($a_read, $b_write) if $self->_try_type($conduit_type, \$a_read, \$b_write); } while (my $try_type = $self->_get_next_preference()) { return ($a_read, $b_write) if $self->_try_type($try_type, \$a_read, \$b_write); $self->_shift_preference(); } # There's nothing left to try. DEBUG and warn "nothing worked"; return; } # Try a pipe by type. sub _try_type { my ($self, $type, $a_read, $b_write) = @_; # Try a pipe(). if ($type eq "pipe") { eval { pipe($$a_read, $$b_write) or die "pipe failed: $!"; }; # Pipe failed. if (length $@) { warn "pipe failed: $@" if DEBUG; return; } DEBUG and do { warn "using a pipe"; warn "ar($$a_read) bw($$b_write)\n"; }; # Turn off buffering. POE::Kernel does this for us, but # someone might want to use the pipe class elsewhere. select((select($$b_write), $| = 1)[0]); return 1; } # Try a UNIX-domain socketpair. if ($type eq "socketpair") { eval { socketpair($$a_read, $$b_write, AF_UNIX, SOCK_STREAM, PF_UNSPEC) or die "socketpair failed: $!"; }; if (length $@) { warn "socketpair failed: $@" if DEBUG; return; } DEBUG and do { warn "using a UNIX domain socketpair"; warn "ar($$a_read) bw($$b_write)\n"; }; # It's one-way, so shut down the unused directions. shutdown($$a_read, 1); shutdown($$b_write, 0); # Turn off buffering. POE::Kernel does this for us, but someone # might want to use the pipe class elsewhere. select((select($$b_write), $| = 1)[0]); return 1; } # Try a pair of plain INET sockets. if ($type eq "inet") { eval { ($$a_read, $$b_write) = $self->_make_socket(); }; if (length $@) { warn "make_socket failed: $@" if DEBUG; return; } DEBUG and do { warn "using a plain INET socket"; warn "ar($$a_read) bw($$b_write)\n"; }; # It's one-way, so shut down the unused directions. shutdown($$a_read, 1); shutdown($$b_write, 0); # Turn off buffering. POE::Kernel does this for us, but someone # might want to use the pipe class elsewhere. select((select($$b_write), $| = 1)[0]); return 1; } # There's nothing left to try. DEBUG and warn "unknown OneWay socket type ``$type''"; return; } 1; __END__
# rocco // vim: ts=2 sw=2 expandtab # TODO - Edit.