サンタクロース問題(マルチスレッドのお勉強)

初出はちょっと前だが、時期的には丁度いいのかなと。
http://karetta.jp/article/blog/oneline/030756
問題文には、どんなタイミングでトナカイや小人が戻ってくるかは明記されていない。ので、そこはランダム間隔なんだろう。(他の言語のを見てもそうなってた)。
要するに、マルチスレッドの練習問題な訳だ。
まあ、CGI作る分にはマルチスレッドはあんまり関係ない訳だが、できないよりはできる方がいいのでやってみた。

santa.pl

use strict;
use threads;
use threads::shared;

# トナカイの名前
my @rangifer_name = qw (
	Dasher
	Dancer
	Prancer
	Vixen
	Donder
	Blitzen
	Cupid
	Comet
	Rudolph
);

# 小人の名前
my @gnome_name = qw (
	Bashfun
	Grumpy
	Happy
	Sleepy
	Dopey
	Sneezy
	Doc

	eight
	nine
	ten
);

# 準備
my @returned_rangifer : shared = ();
my @returned_gnome : shared = ();
my $count : shared = 0;

# 開始
my $santa = threads->new(\&santa);
$santa->join;
exit;

# サンタ
sub santa {
	my %rangifer = map { $_=>threads->new(\&rangifer, $_) } @rangifer_name;
	my %gnome = map { $_=>threads->new(\&gnome, $_) } @gnome_name;
	my $mode = -1;
	while ( $count < 100000 ) {
		my $r = scalar @returned_rangifer;
		my $d = scalar @returned_gnome;
		if ( 2 < $d ) {
			print "$count : Santa and $d gnomes are Talking.\n";
			foreach ( 1..$d ) {
				my $name = shift @returned_gnome;
				$gnome{$name}->join;
				$gnome{$name} = threads->new(\&gnome, $name);
			}
			$mode = 2;
		} elsif ( 8 < $r ) {
			print "$count : Santa and $r rangifers are Flying.\n";
			foreach ( 1..$r ) {
				my $name = shift @returned_rangifer;
				$rangifer{$name}->join;
				$rangifer{$name} = threads->new(\&rangifer, $name);
			}
			$mode = 1;
		} else {
			$mode == 0 or print "$count : Santa is Sleeping.\n";
			$mode = 0;
		}
		++ $count;
	}
}
# トナカイ
sub rangifer {
	my $name = shift;
	select undef, undef, undef, rand();
	print "$count : rangifer - $name Return\n";
	++ $count;
	push @returned_rangifer, $name;
}
# 小人
sub gnome {
	my $name = shift;
	select undef, undef, undef, rand();
	print "$count : gnome - $name Return\n";
	++ $count;
	push @returned_gnome, $name;
}

実行結果

0 : rangifer - Rudolph Return
1 : Santa is Sleeping.
1306 : gnome - nine Return
3360 : gnome - Happy Return
7701 : gnome - ten Return
7703 : Santa and 3 gnomes are Talking.
7703 : gnome - Grumpy Return
7705 : Santa is Sleeping.
16128 : gnome - Dopey Return
18262 : rangifer - Blitzen Return
27867 : gnome - Bashfun Return
27868 : Santa and 3 gnomes are Talking.
27868 : rangifer - Cupid Return
27869 : rangifer - Prancer Return
27871 : Santa is Sleeping.
28457 : rangifer - Dancer Return
35750 : rangifer - Donder Return
47049 : gnome - Happy Return
62917 : gnome - Sneezy Return
66219 : rangifer - Comet Return
66378 : rangifer - Vixen Return
70658 : gnome - eight Return
78392 : rangifer - Dasher Return
79805 : Santa and 3 gnomes are Talking.
79806 : Santa and 9 rangifers are Flying.
79806 : gnome - Dopey Return
79807 : gnome - Sleepy Return
79808 : gnome - Bashfun Return
79809 : gnome - ten Return
79810 : gnome - Doc Return
79812 : Santa and 5 gnomes are Talking.
79813 : Santa is Sleeping.
94181 : gnome - nine Return
98901 : gnome - Sleepy Return
A thread exited while 18 threads were running.

最後に警告メッセージが出ててまあ、お行儀の悪いこと。
つうか、これどうやっても出たりしない?