Feeds:
Posts
Comments

Posts Tagged ‘poe’

I’m (unfortunately) doing more work on Windows on these days so I’ve installed a mini Windows-dev environment at home. It is impressive what the libre software guys have done – between Emacs, Cygwin and Perl (and a rusty MinGW C compiler) I feel almost at home.

On Windows, there is an embarrassment of Perl options. I could choose from ActiveState Perl, Strawberry Perl, CygPerl or try and build it myself. I haven’t tried Strawberry Perl so I thought I’d give it a whirl. The install process was pleasant enough but after that I had some problems. I tried my usual perl -MCPAN -e shell incantation followed by installing (upgrading) the CPAN package but it didn’t work. Woe is me!

I reached for old reliable cygperl but that didn’t work either. Hmmm… fishy, I’m sure I haven’t had problems previously. Thankfully googling the exact error lead to a solution which unfortunately I didn’t make a note of. I do remember that it involved a rebase from the static shell, ash. Following that, Strawberry Perl worked too.

The next thing to do was to install POE. POE allows you to structure your code in an event-driven way. I’ve experienced some strange behaviour with POE on various Windows Perl implementations in the past so I want to test a few things.

My basic POE script.

use strict;
use warnings;

use POE;

POE::Session->create(
    inline_states => {
        _start => sub { $_[KERNEL]->yield('loop'); },
        loop   => sub {
            print "Normal loop\n";
            $_[KERNEL]->delay(loop => 1);
        },
    }
);

$poe_kernel->run();

That was a cumbersome way to implement a while 1 loop eh?

while (1) {
    print "Normal Loop\n";
    sleep 1;
}

The first thing I want to test is timeouts. I actually like the crufty way that timeouts are implemented in perl with eval / sig alarm. I use sleep here to simulate a long running process despite the warning in the documentation.

It is usually a mistake to intermix alarm and sleep calls. (sleep may be internally implemented in your system with alarm)

use strict;
use warnings;

use POE;

sub timeout_test
{
    eval {
        local $SIG{ALRM} = sub { die "alarm\n" }; # NB: \n required
        alarm 3;
        sleep 5; # This simulates a long-running process
        alarm 0;
    };
    if ($@) {
        die unless $@ eq "alarm\n"; # propagate unexpected errors
        print "Timeout\n";
        # timed out
    }
    else {
        # didn't
    }
}

POE sessions are a bit like co-operative threads. If the session doesn’t yield to the kernel, another session can’t run so if the timeout doesn’t work, we won’t see any output after the timeout loop starts.

POE::Session->create(
    inline_states => {
        _start => sub { $_[KERNEL]->yield('loop'); },
        loop   => sub {
            print "Normal Loop\n";
            $_[KERNEL]->delay(loop => 1);
        },
    }
);

POE::Session->create(
    inline_states => {
        _start => sub { $_[KERNEL]->yield('loop'); },
        loop   => sub {
            print "Timeout loop\n";
            timeout_test();
            $_[KERNEL]->delay(loop => 1);
        },
    }
);

$poe_kernel->run();

Fortunately, it works fine.

$ perl basic-poe.pl
Normal Loop
Timeout loop
Timeout
Normal Loop
Timeout loop
Timeout
Normal Loop
Terminating on signal SIGINT(2)

Read Full Post »

Follow

Get every new post delivered to your Inbox.