Coro で Thread-Per-Message パターン

増補改訂版 Java言語で学ぶデザインパターン入門 マルチスレッド編 を参考に Coro で Thread-Per-Message パターンを実装。

Thread-Per-Message パターン は メッセージを送ると新しく一つのスレッドが割り当てられて、そのスレッドが処理を行なう。


#!/usr/bin/perl
use strict;
use warnings;

package Host;
use Coro;

sub new {
    my ( $class, %args ) = @_;
    $args{helper} = Helper->new();
    $args{coros}  = [];
    bless \%args, $class;
}

sub request {
    my $self    = shift;
    my $content = shift;
    print "request $content\n";
    my $coro = async {
        do {
            $self->{helper}->handle($content);
        };
    };
    push @{ $self->{coros} }, $coro;
}

sub wait_all {
    my $self = shift;
    for my $coro ( @{ $self->{coros} } ) {
        $coro->join();
    }
}

package Helper;
use Coro;
use Coro::Timer;

sub new {
    my ( $class, %args ) = @_;
    bless \%args, $class;
}

sub handle {
    my $self    = shift;
    my $content = shift;

    print "working $content...\n";
    Coro::Timer::sleep(1);
    print "done $content...\n";
}

package main;
use Coro;

print "start main\n";
my $host = Host->new();
$host->request("work1");
$host->request("work2");
print "end main\n";

$host->wait_all();

出力

start main
request work1
request work2
end main
working work1...
working work2...
done work2...
done work1...

pic ファイル

.PS

copy "sequence.pic";

boxwid = 1.3;

# Define the objects
object(M,":main");
placeholder_object(HOST);
placeholder_object(T1);
placeholder_object(T2);
placeholder_object(HELPER);
step();

# Message sequences
active(M);

create_message(M,HOST,":host");
active(HOST);

create_message(HOST,HELPER,":helper");
active(HELPER);


message(M,HOST,"request");
create_message(HOST,T1,":coro1");
begin_frame(T1,F,"On other coro");
rmessage(HOST,M,"");
active(T1);
message(T1,HELPER,"handle");
rmessage(HELPER,T1);
delete(T1);
step();
end_frame(HELPER,F);

message(M,HOST,"request");
create_message(HOST,T2,":coro2");
begin_frame(T2,F,"On other coro");
rmessage(HOST,M,"");
complete(M);
active(T2);
message(T2,HELPER,"handle");
rmessage(HELPER,T2);
delete(T2);
step();
end_frame(HELPER,F);

complete(HOST);
complete(HELPER);

.PE