Re 常識を覆すソートアルゴリズム!その名も"sleep sort"!

常識を覆すソートアルゴリズム!その名も"sleep sort"! - Islands in the byte streamを読んで、自分が書くとしたらこんな感じかなーと思った。多重化して select 使う必要ないよねということで。

use Time::HiRes qw(sleep);

sub sleep_sort {
    # create pipe
    pipe(my $rfh, my $wfh)
        or die "pipe failed: $!";
    # spawn the processes
    my @pids;
    while (@_) {
        my $value = shift;
        my $pid = fork;
        die "fork failed: $!"
            unless defined $pid;
        if ($pid == 0) {
            # child process
            $| = 1;
            sleep $value / 10;
            print $wfh "$value\n";
            exit 0;
        }
        push @pids, $pid;
    }
    # close write handle and swallow all input
    close $wfh;
    my @values = <$rfh>;
    # get rid of the zombie processes
    for my $pid (@pids) {
        while (waitpid($pid, 0) != $pid) {
            if ($! == Errno::EINTR) {
                # continue
            } elsif ($! == Errno::ECHILD) {
                # somehow got reaped (maybe $SIG{CHLD} is 'IGNORE')
                last;
            } else {
                die "unexpected response from waitpid: $!";
            }
        }
    }
    # remove \n and return the result
    chomp @values;
    @values;
}

まあ、wait するくらいなら print する必要もないと思うけどw

sub sleep_sort {
    my %pid_value = map {
        +(fork || do {
            sleep $_ / 10;
            exit;
        }) => $_
    } @_;
    my @values;
    while (%pid_value) {
        if ((my $pid = wait) != -1) {
            push @values, delete $pid_value{$pid};
        }
    }
    @values;
}