On Apr 5, 2011, at 12:45, Michael R. Davis wrote:
> POE Folks,
> I've not used POE before but have plans to use a POE capability shortly.
> Last night I added a POE::Session wrapper in my Net::GPSD3 (v0.15) package
> but I'm not entirely sure it's using best practices.
>
> http://search.cpan.org/dist/Net-GPSD3/lib/Net/GPSD3/POE.pm
>
> Specifically, should I use a more specific HEAP key than "wheel".
>
> $heap->{"wheel"}=...
You may call it whatever you like. More specific names are good because they
help make the code more readable.
> I've also not seen any best practices about passing the parent object around
> in HEAP.
>
> $heap->{"gpsd"}=$self;
Using object_states instead of inline_states makes sense in your case. All
your callbacks are essentially object methods. Here's an untested rewrite of
the guts of Net::GPSD3::POE. I'm sure it's not quite functional, but I hope
it's a good example.
### Called as a plain method, not a POE callback.
# @_ is $self and whatever the caller provides.
# In this case, object_states are being used because the callbacks are
# object methods. The $_[OBJECT] parameter will be populated with the
# $self for the callback. This eliminates the need to store $self
# explicitly.
sub start_session {
my $self = shift;#ISA Net::GPSD::POE
# Don't start another one.
return if $self->{sid};
$self->{sid} = POE::Session->create(
object_states => [
$self => {
_start => '_handle_poe_start',
input_event => '_handle_input_event',
shutdown=> '_handle_poe_shutdown',
},
]
)->ID();
}
# POE callback. Start the session's resources. We're skipping
# $_[HEAP] altogether because the original code only shows need for
# one I/O watcher per object. We can use a single name for the
# ReadWrite resource ("io"). If we were managing multiple wheels,
# then we might create a hash of them keyed on wheel ID.
sub _handle_poe_start {
my $self = $_[OBJECT];
$self->{io} = POE::Wheel::ReadWrite->new(
InputEvent => "input_event",
Handle => $self->socket(),
Filter => POE::Filter::Line->new(
InputLiteral => "\r\n",
OutputLiteral => "\n",
),
);
$self->{io}->put(qq(?WATCH={"enable":true,"json":true};));
},
### Called as a plain method, not a POE callback.
# @_ is $self and whatever the caller provides.
#
# This method asks the session to clean up and stop. POE's session
# encapsulation makes it difficult (but not impossible---this is Perl)
# to release another session's resources.
sub stop_session {
my $self = shift;
# Don't re-stop a dead one.
return unless $self->{sid};
$poe_kernel->call($self->{sid}, "shutdown");
$self->{sid} = undef;
}
# POE callback. Deletes the wheel from within the context of the
# session that owns it.
sub _handle_poe_shutdown {
my $self = $_[OBJECT];
delete $self->{io};
}
# POE callback. Handle input.
sub _handle_input_event {
my ($self, $line) = @_[OBJECT, ARG0];
my @handler = $self->handlers();
push @handler, \&Net::GPSD3::default_handler unless @handler;
my $object = $self->constructor($self->decode($line), string => $line);
foreach my $handler (@handler) {
$handler->($object);
}
$self->cache($object);
}
--
Rocco Caputo