Re: Accessors

Rocco Caputo <[email protected]>
Newsgroups gmane.comp.lang.perl.poe
Message-ID <[email protected]>
My favorite method (har) is to wrap the session in an object that acts  
as its interface and also its storage.   
POE::Component::Client::KeepAlive is implemented this way.

In brief, new() creates the object and spawns a hidden POE::Session.   
object_states map events to private methods on the new object.  Public  
methods on the object act as accessors and mutators, and can be used  
to send commands into the hidden session.

sub new {
   my $class = shift;
   my $self = bless { }, $class;
   POE::Session->create(
     object_states => {
       _start => "_poe_start_handler",
       lala_changed => "_poe_lala_changed",
       do_something => "_poe_do_something",
       ...,
     }
   );
   return $self;
}

The session's _start handler sets its alias to be the stringified  
object reference.  More on this later.

sub _poe_start_handler {
   $_[KERNEL]->alias_set("$_[OBJECT]");
}

 From event handlers:

sub _poe_handler {
   my ($self, $heap) = @_[OBJECT, HEAP];
   $self->{lala} = 123;  # visible from $object->accessor()
   $heap->{lala} = "abc";  # not visible from the OO interface
}

 From accessors:

sub accessor {
   my $self = shift;
   return $self->{lala};
}

Mutators can trigger POE events by calling "$self" (stringified object  
reference).  This is the alias set in _poe_start_handler().

sub mutator {
   my ($self, $new_lala) = @_;
   $self->{lala} = $new_lala;
   $poe_kernel->call("$self", lala_changed => $new_lala);
   return $new_lala;
}

sub _poe_lala_changed {
   my $new_lala = $_[ARG0];
   my $other_new_lala = $_[OBJECT]{lala};
   # do something here
}

And "command" methods can call "$self" without setting members.

sub do_something {
   my $self = shift;
   $poe_kernel->call("$self", do_something => @_);
}

sub _poe_do_something {
   # don't just stand there!
   return "result";
}

...

This isn't a best practice, however.  It implies a 1:1 ration of  
sessions to objects, which isn't ideal.  The ideal, best way is to  
implement a dispatcher that lets many objects share a smaller set of  
sessions.  POE::Stage is implemented this way, but it's not ready for  
production yet.

A compromise: Embed POE sessions in I/O objects, and use regular Perl  
objects for everything else.

-- 
Rocco Caputo - [email protected]


On Apr 8, 2008, at 20:04, John R. wrote:
> From the 1.0 documentation (very good by the way):
>
> "call() returns the value returned by the EVENT_NAME handler.  It  
> can do
> this because the handler is invoked before call() returns.  call() can
> therefore be used as an accessor, although there are better ways to
> accomplish simple accessor behavior."
>
> (from POE::Kernel)
>
> I don't see reference to the better ways so they probably are  
> standard perlish ways of doing things that I am having difficulty  
> figuring out. What other ways are there to accomplish accessors that  
> provide access to POE things like the heap?  I am doing calls within  
> a session and between sessions.  Should I pass the heap, kernel, etc  
> as arguments to regular sub calls?
>
> Thanks,
>
> John
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.