Subject: | Convert to using Object States |
I suppose this isn't really a bug, but it definitely hinders modules (or at least my module!) that subclass PoCo::Child.
The patch I've included converts PoCo::Child from using package states to using object states. All existing code that uses PoCo::Child should work exactly the same. The two big differences with the change are that you no longer have to pass $self around in the heap and it gives greater flexibility for subclassed modules.
For instance, I just discovered a bug in my PoCo::Player::Musicus module where an event that I wanted to be handled by the session that PoCo::Child started was actually being handled by whatever session called ->new. To fix this, I need to register my object state handler from within PoCo::Child's session. I talked with Rocco on IRC about ways to fix this and he suggested that PoCo::Child either have an init callback of some sort, or convert to using object states and override the _start method in the subclass (and thought that going to object states was the best way to go out of the two).
To give a concrete example, this is what I would like to be able to do from within my module:
sub _start {
my $self = shift;
my @args = @_;
$poe_kernel->state('queue_check', $self);
$self->{session} = $poe_kernel->get_active_session;
$self->SUPER::_start(@args);
}
Since the _start method is guaranteed to be within PoCo::Child's session and I catch it before PoCo::Child does, I can modify it however I want, including adding object state handlers, then pass control along to PoCo::Child like it would normally go.
I can't really fix the (fairly major) bug in my module until there's a way to do this or something like it, so it would be great if you could release a new version soon.
Let me know if you have any questions, objections, differences of opinion, etc. If there's a different way you'd like things to be done, I'd be happy to rewrite the patch if it would save you time.
Thanks!
--- POE-Component-Child-1.33/Child.pm 2004-06-02 23:16:35.000000000 -0500
+++ ../Child.pm 2005-07-06 20:49:19.000000000 -0500
@@ -56,8 +56,7 @@
/;
POE::Session->create(
- package_states => [ $PKG => \@sh ],
- heap => { self => $self }
+ object_states => [ $self => \@sh ],
);
return $self;
@@ -65,7 +64,7 @@
sub run {
my $self = shift;
- POE::Kernel->call($self->{$PKG}{session}, got_run => $self, \@_);
+ POE::Kernel->call($self->{$PKG}{session}, got_run => \@_);
}
sub write {
@@ -119,8 +118,7 @@
# --- session handlers --------------------------------------------------------
sub _start {
- my ($kernel, $heap, $session) = @_[KERNEL, HEAP, SESSION];
- my $self = $heap->{self};
+ my ($self, $kernel, $session) = @_[OBJECT, KERNEL, SESSION];
$self->{$PKG}{session} = $session->ID;
$self->debug("session-id: $self->{$PKG}{session}");
@@ -134,8 +132,7 @@
}
sub _stop {
- my ($heap, $session) = @_[HEAP, SESSION];
- my $self = $heap->{self};
+ my ($self, $session) = @_[OBJECT, SESSION];
# clean remaining wheels
@@ -157,13 +154,12 @@
# to propagate
sub _default {
- my $heap = $_[HEAP];
- my $self = $heap->{self};
+ my ($self) = $_[OBJECT];
$self->debug(qq/_default: "$_[ARG0]", args: @{$_[ARG1]}/);
}
sub got_run {
- my ($kernel, $session, $self, $cmd) = @_[KERNEL, SESSION, ARG0, ARG1];
+ my ($self, $kernel, $session, $cmd) = @_[OBJECT, KERNEL, SESSION, ARG0];
# init stuff
@@ -206,10 +202,9 @@
}
sub stdio {
- my ($kernel, $heap, $event) = @_[KERNEL, HEAP, STATE];
+ my ($self, $kernel, $event) = @_[OBJECT, KERNEL, STATE];
return unless $_[ARG0];
- my $self = $heap->{self};
$self->callback($event, { out => $_[ARG0], wheel => $_[ARG1] });
$self->debug(qq/$event(): "$_[ARG0]"/, 2);
@@ -218,8 +213,7 @@
*stdout = *stderr = *stdio;
sub sig_child {
- my ($kernel, $heap, $pid, $rc) = @_[KERNEL, HEAP, ARG1, ARG2];
- my $self = $heap->{self};
+ my ($self, $kernel, $pid, $rc) = @_[OBJECT, KERNEL, ARG1, ARG2];
my $id = $self->{$PKG}{pids}{$pid} || "";
@@ -241,8 +235,7 @@
# the child has closed its output pipes
sub close {
- my $self = $_[HEAP]->{self};
- my $id = $_[ARG0];
+ my ($self, $id) = @_[OBJECT, ARG0];
my $sigchld = $self->{$PKG}{SIGCHLD}{$id};
return done(%$sigchld) if $sigchld;
@@ -271,7 +264,7 @@
}
sub error {
- my ($kernel, $heap, $event) = @_[KERNEL, HEAP, STATE];
+ my ($self, $kernel, $event) = @_[OBJECT, KERNEL, STATE];
my $args = {
syscall => $_[ARG0],
err => $_[ARG1],
@@ -282,7 +275,6 @@
return if $args->{syscall} eq "read" && $args->{err} == 0;
- my $self = $heap->{self};
$self->callback($event, $args);
$self->debug("$event() [$args->{err}]: $args->{error}");
}