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 <rcap...@pobox.com>