package IO::Event::Callback;
use strict;
use warnings;
use IO::Event;
our @handlers;
BEGIN {
@handlers = qw(input connection read_ready werror eof output
outputdone connected connect_failed died timer exception
outputoverflow);
}
sub new
{
my ($pkg, $filehandle, %h) = @_;
my $ro = $h{read_only};
my $wo = $h{write_only};
delete $h{read_only};
delete $h{write_only};
my $self = handler($pkg, %h);
return IO::Event->new($filehandle, $self, read_only => $ro, write_only => $wo);
}
sub ie_input { $_[0]->{'ie_input'}->(@_) };
sub ie_connection { $_[0]->{'ie_connection'}->(@_) };
sub ie_read_ready { $_[0]->{'ie_read_ready'}->(@_) };
sub ie_werror { $_[0]->{'ie_werror'}->(@_) };
sub ie_eof { $_[0]->{'ie_eof'}->(@_) };
sub ie_output { $_[0]->{'ie_output'}->(@_) };
sub ie_outputdone { $_[0]->{'ie_outputdone'}->(@_) };
sub ie_connected { $_[0]->{'ie_connected'}->(@_) };
sub ie_connect_failed { $_[0]->{'ie_connect_failed'}->(@_) };
sub ie_died { $_[0]->{'ie_died'}->(@_) };
sub ie_timer { $_[0]->{'ie_timer'}->(@_) };
sub ie_exception { $_[0]->{'ie_exception'}->(@_) };
sub ie_outputoverflow { $_[0]->{'ie_outputoverflow'}->(@_) };
sub handler
{
my ($pkg, %h) = @_;
my $self = bless {}, $pkg;
for my $h (@handlers) {
my $key =
exists($h{$h}) ? $h :
exists($h{"ie_$h"}) ? "ie_$h" : undef;
if ($key) {
$self->{"ie_$h"} = $h{$key};
delete $h{$key};
} else {
$self->{"ie_$h"} = sub {};
}
}
my @k = keys %h;
die "unexpected parameters: @k" if @k;
return $self;
}
sub sock2handler
{
my ($pkg, $sref) = @_;
my %h;
for my $h (@handlers) {
next unless exists $sref->{$h};
my $key =
exists($sref->{$h}) ? $h :
exists($sref->{"ie_$h"}) ? "ie_$h" : next;
$h{$h} = $sref->{$key};
delete $sref->{$key};
}
my $handler = handler($pkg,%h);
}
package IO::Event::INET::Callback;
use strict;
use warnings;
sub new
{
my ($pkg, %sock) = @_;
my $handler = IO::Event::Callback->sock2handler(\%sock);
return IO::Event::INET->new(%sock, Handler => $handler);
}
package IO::Event::UNIX::Callback;
use strict;
use warnings;
sub new
{
my ($pkg, %sock) = @_;
my $handler = IO::Event::Callback->sock2handler(\%sock);
return IO::Event::UNIX->new(%sock, Handler => $handler);
}
1;
__END__
=head1 NAME
IO::Event::Callback - A closure based API for IO::Event
=head1 SYNOPSIS
use IO::Event::Callback;
IO::Event::Callback->new($filehanle, %callbacks);
use IO::Event::INET::Callback;
IO::Event::INET::Callback->new(%socket_info, %callbacks);
use IO::Event::UNIX::Callback;
IO::Event::UNIX::Callback->new(%socket_info, %callbacks);
=head1 DESCRIPTION
IO::Event::Callback is a wrapper around L<IO::Event>. It
provides an alternative interface to using L<IO::Event>.
Instead of defining a class with methods like "ie_input", you
provide the callbacks as code references when you create
the object.
The keys for the callbacks are the same as the callbacks
for L<IO::Event> with the C<ie_> prefix removed.
=head1 EXAMPLE
use IO::Event::Callback;
my $remote = IO::Event::Callback::INET->new(
peeraddr => '10.20.10.3',
peerport => '23',
input => sub {
# handle input
},
werror => sub {
# handdle error
},
eof => sub {
# handle end-of-file
},
);
=head1 SEE ALSO
See the source for L<RPC::ToWorker> for an exmaple use of IO::Event::Callback.