Coro で Guarded-Suspension パターン (Coro::Channel使用)

増補改訂版 Java言語で学ぶデザインパターン入門 マルチスレッド編 の Guarded-Suspension パターンを Coro で実装。Guarded-Suspension パターンは要するにメッセージ送受信。Coro::Channel を使ったが、 Coro::Channel を使うと厳密には、Producer-Consumer パターンになるっぽい。


use strict;
use warnings;

package Client;
use Coro;
use Coro::Timer;

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

sub run {
    my $self = shift;
    my $coro = async {
        do {
            my $ch = $self->{channel};

            my $msg;
            $msg = "message1";
            print "Client: put $msg\n";
            $ch->put($msg);

            $msg = "message2";
            print "Client: put $msg\n";
            $ch->put($msg);

            print "Client: sleep...\n";
            Coro::Timer::sleep(1);

            $msg = "end";
            print "Client: put $msg\n";
            $ch->put($msg);
        };
    };
    return $coro;
}

package Server;
use Coro;

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

sub run {
    my $self = shift;
    my $coro = async {
        do {
            my $ch = $self->{channel};
            while (1) {
                my $msg = $ch->get;
                print "Server: get $msg\n";
                last if $msg =~ m/^end$/;
            }
        };
    };

    return $coro;
}

package main;
use Coro;
use Coro::Channel;

my $channel = Coro::Channel->new;
my $server  = Server->new( channel => $channel );
my $client  = Client->new( channel => $channel );

my $client_coro = $client->run();
my $server_coro = $server->run();

$client_coro->join();
$server_coro->join();

結果出力

Client: put message1
Client: put message2
Client: sleep...
Server: get message1
Server: get message2
Client: put end
Server: get end

pic ファイル

.PS

copy "sequence.pic";

boxwid = 1.3;

# Define the objects
object(CL,":client");
object(CH,":channel");
object(S,":server");
step();

# Message sequences
active(CL);
active(S);

message(CL,CH,"put");
active(CH);
rmessage(CH,CL,"");
inactive(CH);

message(CL,CH,"put");
active(CH);
rmessage(CH,CL,"");
inactive(CH);

message(S,CH,"get");
active(CH);
rmessage(CH,S,"");
inactive(CH);

message(S,CH,"get");
active(CH);
rmessage(CH,S,"");
inactive(CH);

message(S,CH,"get");
active(CH);
comment(CH,T2,up 0.5 left 0.5,wid 1 ht 0.5 "waiting for" "put");

message(CL,CH,"put");
active(CH);
rmessage(CH,CL,"");
inactive(CH);
rmessage(CH,S,"");
inactive(CH);

complete(CL);
complete(CH);
complete(S);

.PE