NAME
IO::Mux - simplify use of file-event loops
INHERITANCE
IO::Mux is extended by
IO::Mux::Poll
IO::Mux::Select
SYNOPSIS
use IO::Mux;
use IO::Mux::Socket::TCP;
my $mux = IO::Mux->new;
my $server = IO::Mux::Socket::TCP->new(...);
$mux->add($server);
DESCRIPTION
IO::Mux
is designed to take the effort out of managing multiple socket, file or pipe connections within one process. It is essentially a really fancy front end to various kinds of event mechanisms, like select
and poll
. In addition to maintaining the event loop, all input and output of the data stream gets buffered for you which tends to be quite difficult in event driven programs.
On many platforms, the capabilities of various event mechanisms do differ a lot. Be careful which mechanism you pick. Test it! Read the man-pages which contain information about limitations and please contribute information you discover.
See "DETAILS" far below for a long description about
- . event managers
select()
andpoll()
- . managed file handles
- . differences with IO::Multiplex and IO::Async, plus
- . interesting implementation details.
METHODS
Constructors
- IO::Mux->new(OPTIONS)
-
There can only be one of these objects in your program. After instantiating this, you will add() file-handles and sockets. Finally, loop() is called to go into
select
-driven connection handling.There are currently no OPTIONS, but they will probably arrive in the upcoming releases.
Accessors
User interface
- $obj->add(HANDLER|BUNDLE)
-
Add an HANDLER or BUNDLE to the multiplexer. Handlers extend IO::Mux::Handler. Bundles are related sets of handlers and extend IO::Mux::Bundle.
- $obj->endLoop(BOOLEAN)
-
When this flag is set to
true
, the activities will end after having processed all currently flagged handles. All open handles when get closed cleanly.The loop will also be terminated when all the handlers are removed (closed) That is a saver way to close the activities of your program where a call to
endLoop()
in many uses can be seen as tricky side-effect of a single handler. - $obj->loop([HEARTBEAT])
-
Enter the main loop and start processing IO events. The loop will terminate when all handles are closed, serious errors emerge or endLoop() was called.
You may provide a HARTBEAT code reference, which will get called each time the internal
select()
has found a file handle with something to do or a timeout has expired. As arguments, it get the multiplexer object, the number of events and the time left to the next timeout. The validity of that third argument depends on the operating system and the actual muxer type.example: loop
$mux->loop; exit 0;
example: loop with heartbeat
$mux->loop(\&hb); sub hb($$) { my ($mux, $count, $t) = @_; }
- $obj->open(MODE, PARAMS)
-
This
open()
provides a simplified interface to IO::Mux::Open, which on its turn is a simplification on using all kinds of handlers. See the manual of IO::Mux::Open for an extended description of the use.example:
use IO::Mux::Open '-|'; # loads handler code sub print_line($$) { my ($handler, $line) = @_; print "line = $line"; } # the short form my $who = $mux->open('-|', 'who'); $who->readline(\&print_line); # equivalent to the longer my $who = IO::Mux::Open->new('-|', 'who'); $mux->add($who); $who->readline(\&print_line); # or even longer use IO::Mux::Pipe::Read; my $who = IO::Mux::Pipe::Read->new(command => 'who'); $mux->add($who); $who->readline(\&print_line);
For internal use
The following methods are provided, but end-users should avoid calling these methods directly: call them via the IO::Mux::Handler.
- $obj->changeTimeout(FILENO, OLDTIMEOUT, NEWTIMEOUT)
-
One of the connections wants to change its timeouts. A value of zero or undef means not active.
The correct OLDTIMEOUT must be provided to make it fast to detect whether this was the first timeout to expire. Checking the first timeout takes
O(n)
time, so we wish to avoid that.example:
# set timeout $mux->changeTimeout($conn->fileno, undef, 10); # better this way $conn->timeout(10);
- $obj->fdset(FILENO, STATE, READ, WRITE, EXCEPT)
-
Change the select bit STATE for the FILENO. Change the READ, WRITE and/or EXCEPTion state.
example:
# clear read and except, keep write $mux->fdset($conn->fileno, 0, 1, 0, 1); # better this way: $conn->fdset(0, 1, 0, 1);
- $obj->handler(FILENO, [HANDLER])
-
Returns (or sets) the handler which maintains FILENO.
example:
$mux->handler(1); # probably STDOUT
- $obj->handlers
-
Returns a list of all registered handlers (also the sockets).
example:
foreach my $conn ($mux->handlers) { ... }
- $obj->remove(FILENO)
-
Remove a connection from the multiplexer. Better to use the connection close method.
example:
$mux->remove($conn->fileno); # better this way: $conn->close;
DETAILS
Installation
Many components of IO-driven programming are quite platform dependent. Therefore, IO::Mux
does not enforce the installation of these dependencies during installation. However, when you choose to use some of the components, you will discover you need to install additional modules. For instance, when you use IO::Mux::Poll you will need IO::Poll.
Many perl modules (like LWP) use autoloading to get additional code in when it gets used. This is a nice help for users who do not need to load those modules explicitly. It is also a speed-up for the boot-time of scripts. However, IO::Mux
is usually run in a daemon (see examples/ directory) which should load all code before child processes are started. Besides, initialization time does not really matter for daemons.
Event managers
The following event managers are available on the moment:
-
uses a
select
call (see "man 2 select" on UNIX/Linux). The number of file handles it can monitor is limited (but quite large) and the overhead increases with the number of handles. On Windows only usable with sockets, no pipes nor files. -
uses a
poll
call (see "man 2 poll" on UNIX/Linux). Not available on Windows, afaik. More efficient thanselect
when the number of file handles grows, and many more filehandles can be monitored at once.
Other possible mechanisms include epoll
, ppoll
, pselect
, kqueue
, and Glib
, may get added later. Connections to other event frameworks as POE
, IO::Async
, and AnyEvent
may get added as well.
File handles
The event managers looks to one or more file handles for changes: either the write buffer gets empty (the program may send more), requested data has arrived (ready to be read) or (unexpected) error text comes in.
The following handles are supported, although maybe not on your platform.
-
A server for TCP based application, like a web-server. On each incoming connection, a IO::Mux::Net::TCP will be started to handle it.
-
Handle a single TCP connection.
IO::Mux::File::Read and IO::Mux::File::Write
Read and write a file asynchronously.
IO::Mux::Pipe::Read and IO::Mux::Pipe::Write
Read the output from an command, respectively send bytes to and external command.
Alternatives
IO::Multiplex
Difference to IO::Multiplex
The IO::Mux (Mux) implementation is much closer to IO::Multiplex (Plex) than you may expect. Similar enough to write a comparison.
Main differences:
- . Event managers
-
In Plex, all is organized around a
select
loop. In Mux, you have a choice between various mechanisms of which some still need to be implemented. - . Callback objects
-
In Plex, the file-handle may have a callback object associated to it. If not, a default is used. In Mux, the callback has the focus, which has a file-handle associated to it. This use if the multiplexing
select
less visible this way, which should simplify implementations.Mux does not support callbacks to name-spaces, because the object is used for per-handle administration. In Plex, that administration is located inside the multiplex object (and therefore difficult to extend with higher level applications)
- . Callback routines
-
The Mux implementation defines the same
mux_*
methods as Plex, but has organized them. In Plex, the connection acceptingmux_connection
and the input callbackmux_input
are always available, even though the callback object will only support one of both (if your abstraction is correct). In Mux, there is a clear distinction between various kinds of handlers.In Mux, you have a few more locations where you can hook the process, a few more callbacks.
- . Pipes and files
-
Mux added support for file reading and writing, pipes and proxies.
- . Timeouts
-
One should use timeouts on all handlers, because no connection can be trusted even files (which may come from stalled NFS partitions).
This module started as a rework of IO::Multiplex. It follows the same concept, but with major internal and visible improvements. Some core logic of this module has been derived from work by Bruce J Keeler and Rob Brown. Examples, tests and documentation are derived from their work as well.
IO::Async / Net::Async
Paul Evans has developed a large number of modules which is more feature complete than IO::Mux
. It supports far more event loops, is better tested, and has many higher level applications ready to be used.
Certain applications will benefit from IO::Mux (especially my personal development projects), because it is based on the OODoc module for object oriented perl module documentation, and Log::Report for error handling and translations. Besides, the IO::Multiplex interface is much easier to use than the IO::Async concept.
On CPAN, you can find various alternatives for this module.
SEE ALSO
This module is part of IO-Mux distribution version 0.11, built on January 26, 2011. Website: http://perl.overmeer.net/ All modules in this suite: "Any::Daemon", "IO::Mux", and "IO::Mux::HTTP".
Please post questions or ideas to perl@overmeer.net
LICENSE
Copyrights 2011 by Mark Overmeer. For other contributors see ChangeLog.
This program is free software; you can redistribute it and/or modify it under the same terms as Perl itself. See http://www.perl.com/perl/misc/Artistic.html