Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Begin exploring parameterized Moose roles for static composition.
Should be faster and more Moose-friendly than Reflex dynamic roles, although dynamic roles may still be useful for managing collections. Pure Moose roles should also be cleaner for people who like that sort of thing.
- Loading branch information
Showing
4 changed files
with
225 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,76 @@ | ||
package Proxy; | ||
use Moose; | ||
extends 'Reflex::Object'; | ||
|
||
has handle_a => ( is => 'rw', isa => 'FileHandle', required => 1 ); | ||
has handle_b => ( is => 'rw', isa => 'FileHandle', required => 1 ); | ||
|
||
with 'Readable' => { | ||
handle => 'handle_a', | ||
active => 1, | ||
}; | ||
|
||
with 'Readable' => { | ||
handle => 'handle_b', | ||
active => 1, | ||
}; | ||
|
||
# TODO - Next two roles should be Writable, but I haven't figured out | ||
# the syntax for subclassing parameterized roles and overriding their | ||
# default parameters. "knob_suffix", "select_method" and "event" | ||
# ought to be hidden in the defaults for a Writable role. | ||
|
||
with 'Readable' => { | ||
handle => 'handle_a', | ||
knob_suffix => '_wr', | ||
select_method => 'select_write', | ||
event => 'writable', | ||
}; | ||
|
||
with 'Readable' => { | ||
handle => 'handle_b', | ||
knob_suffix => '_wr', | ||
select_method => 'select_write', | ||
event => 'writable', | ||
}; | ||
|
||
# TODO - put() methods. | ||
# TODO - Write buffering to be provided by a Streamable role. | ||
|
||
sub on_readable_handle_a_readable { | ||
my ($self, $arg) = @_; | ||
my $octet_count = sysread($self->handle_a(), my $buffer = "", 65536); | ||
if ($octet_count) { | ||
$self->emit( | ||
event => "handle_a_data", | ||
args => { | ||
data => $buffer, | ||
handle => $self->handle_a() | ||
}, | ||
); | ||
return; | ||
} | ||
|
||
return if defined $octet_count; | ||
warn $!; | ||
} | ||
|
||
sub on_readable_handle_b_readable { | ||
my ($self, $arg) = @_; | ||
my $octet_count = sysread($self->handle_b(), my $buffer = "", 65536); | ||
if ($octet_count) { | ||
$self->emit( | ||
event => "handle_b_data", | ||
args => { | ||
data => $buffer, | ||
handle => $self->handle_b(), | ||
} | ||
); | ||
return; | ||
} | ||
|
||
return if defined $octet_count; | ||
warn $!; | ||
} | ||
|
||
1; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,103 @@ | ||
package Readable; | ||
use MooseX::Role::Parameterized; | ||
|
||
use Scalar::Util qw(weaken); | ||
|
||
parameter handle => ( | ||
isa => 'Str', | ||
default => 'handle', | ||
); | ||
|
||
parameter knob_suffix => ( | ||
isa => 'Str', | ||
default => '_rd', | ||
); | ||
|
||
parameter knob => ( | ||
isa => 'Str', | ||
default => sub { | ||
my $self = shift; | ||
$self->handle() . $self->knob_suffix(); | ||
}, | ||
lazy => 1, | ||
); | ||
|
||
parameter select_method => ( | ||
isa => 'Str', | ||
default => 'select_read', | ||
); | ||
|
||
parameter event => ( | ||
isa => 'Str', | ||
default => 'readable', | ||
); | ||
|
||
parameter active => ( | ||
isa => 'Bool', | ||
default => 0, | ||
); | ||
|
||
role { | ||
my $p = shift; | ||
|
||
my $h = $p->handle(); | ||
my $k = $p->knob(); | ||
my $m = $p->select_method(); | ||
my $e = $p->event(); | ||
my $active = $p->active(); | ||
my $trigger_name = "_${k}_changed"; | ||
my $emit_name = "${h}_${e}"; | ||
|
||
has $k => ( | ||
is => 'rw', | ||
isa => 'Bool', | ||
default => $active, | ||
trigger => sub { | ||
my $self = shift; | ||
$self->$trigger_name(@_); | ||
}, | ||
initializer => sub { | ||
my $self = shift; | ||
$self->$trigger_name(@_); | ||
}, | ||
); | ||
|
||
method $trigger_name => sub { | ||
my ($self, $value) = @_; | ||
|
||
# Must be run in the right POE session. | ||
return unless $self->call_gate($trigger_name, $value); | ||
|
||
# Turn on watcher. | ||
if ($value) { | ||
my $envelope = [ $self ]; | ||
weaken $envelope->[0]; | ||
$POE::Kernel::poe_kernel->$m( | ||
$self->$h(), 'select_ready', $envelope, $e, $emit_name | ||
); | ||
return; | ||
} | ||
|
||
# Turn off watcher. | ||
$POE::Kernel::poe_kernel->$m($self->$h(), undef); | ||
}; | ||
|
||
# Turn off watcher during destruction. | ||
after DESTROY => sub { | ||
my $self = shift; | ||
$self->$k(0) if $self->$k(); | ||
}; | ||
|
||
# Part of the POE/Reflex contract. | ||
method _deliver => sub { | ||
my ($self, $handle, $mode, $event_name) = @_; | ||
$self->emit( | ||
event => $event_name, | ||
args => { | ||
handle => $handle, | ||
} | ||
); | ||
}; | ||
}; | ||
|
||
1; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
package Writable; | ||
use MooseX::Role::Parameterized; | ||
|
||
die die die "doesn't work, see source"; | ||
|
||
# TODO - Figure out how to subclass parameterized roles and override | ||
# attributes of their parameters. For instance, Writable only differs | ||
# from Readable in the default parameters! | ||
|
||
with 'Readable'; | ||
|
||
parameter '+knob_suffix' => ( default => '_wr' ); | ||
# TODO - Etc. | ||
|
||
# Don't define anything; use what Readable gives us? | ||
role { }; | ||
|
||
1; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
use Moose; | ||
use POE::Pipe::TwoWay; | ||
use Socket qw(AF_UNIX SOCK_STREAM PF_UNSPEC); | ||
use Proxy; | ||
|
||
# Need two sockets to test passing data back and forth. | ||
my ($socket_a, $socket_b); | ||
socketpair($socket_a, $socket_b, AF_UNIX, SOCK_STREAM, PF_UNSPEC) or die $!; | ||
|
||
my $p = Proxy->new( | ||
handle_a => $socket_a, | ||
handle_b => $socket_b, | ||
); | ||
|
||
# Write test data to one end of the proxy. | ||
print $socket_a "test request\n"; | ||
|
||
# Wait for it to arrive at the other end. | ||
# Send something back. | ||
{ | ||
my $e = $p->wait(); | ||
warn $e->{name}, ": ", $e->{arg}{data}; | ||
print {$e->{arg}{handle}} "test response\n"; | ||
} | ||
|
||
# Wait for it to arrive back. | ||
my $e = $p->wait(); | ||
warn $e->{name}, ": ", $e->{arg}{data}; |