On Thu, May 23, 2002 at 09:16:44PM -0400, Peter Chen wrote:
> I am working on a tutorial explaining how to poeize a procedural
> program, in the hope of making it easier for my coworkers to pick up
> POE.
>
> Since I have not worked with POE for that long, I am wondering whether
> there is an easier and more elegant way of doing this.  This is what I
> have so far, starting with the most basic.  I would appreciate your
> feedback.
>
>
> Given the following function foo:
>
>   sub foo {
>     &step1() or return (undef, 'step1 failed');
>     &step2() or return (undef, 'step2 failed');
>     &step3() or return (undef, 'step3 failed');
>     &step4();
>   }
>
> What's the easiest way to poeize this into the following form:
>
>   $kernel->post($session, 'foo', $response_postback);
>
> Assume event foo, step1, ... step4 map to state poe_foo, poe_step1, ...
> poe_step4.

Depending on the application, I might do something like this.

sub poe_foo {
  my ($kernel, $sender, $response, $cookie) = @_[KERNEL, SENDER, ARG0, ARG1];

  my @steps  = (\&step1, \&step2, \&step3, \&step4);
  my @errors = ("step1 failed", "second step failed", "oops three",
                "four was bad"
               );

  # The caller does not provide a cookie.  Instead, one is generated
  # from the first call.  The cookie consists of two fields: the step
  # number to execute, and a copy of the sender so an event can be
  # posted back.

  unless (defined $cookie) {
    $kernel->refcount_increment($sender, "doing foo");
    $cookie = [ 0, $sender ];
  }

  my ($step, $reply_to) = @$cookie;

  # Execute the step.  If it succeeds, and there are more steps, then
  # post another "foo" with an updated cookie.

  if ($steps[$step]->()) {
    $step++;
    if (defined $steps[$step]) {
      $cookie->[0] = $step;
      $kernel->yield("foo", $response, $cookie);
      return;
    }

    # There are no more steps.  Send back a positive response event.
    $kernel->post($reply_to, $response, "success");
    $kernel->refcount_decrement($reply_to, "doing foo");
    return;
  }

  # The step failed.  Send back an appropriate failure message.
  $kernel->post($cookie->[1], $response, $errors[$step]);
  $kernel->refcount_decrement($cookie->[1], "doing foo");
}

I think after writing about two of those, I'd go slightly mad and
create a function that built these for me.  If it turned out that I
was doing this a lot, I would probably assume it's a generic pattern
and write a new type of Session to do it.

Here are a couple articles that discuss other porting issues,
specifically blocking syscalls like sleep(), and porting large loops
so they don't block POE as they run.

  http://poe.perl.org/?POE_Cookbook/Waiting
  http://poe.perl.org/?POE_Cookbook/Looping

-- Rocco Caputo / [EMAIL PROTECTED] / poe.perl.org / poe.sf.net

Reply via email to