#!/usr/bin/env perl use strict; use warnings; use feature 'say'; use IPC::SysV qw/IPC_PRIVATE S_IRUSR S_IWUSR IPC_NOWAIT/; use IPC::Msg; $|++; use constant MSG_BYTES => 1024; my $q = IPC::Msg->new(IPC_PRIVATE,S_IRUSR|S_IWUSR); sub quit { $q->remove; } $SIG{INT} = \&quit; sub enqueue { my $msg = shift; my $msg_type = shift // 1; # Used for message selection, see msgsnd(2) $q->snd($msg_type,$msg,IPC_NOWAIT) || die $!; } sub dequeue { my $type = shift // 1; # See msgop(2) my $msg; $q->rcv($msg,MSG_BYTES,$type,IPC_NOWAIT); #if ($!) { warn "$$ - $!" } return $msg // undef; } sub dequeue_block { my $msg; my $type = shift // 1; # See msgop(2) $q->rcv($msg,MSG_BYTES,$type); #if ($!) { warn "$$ - $!" } return $msg // undef; } sub isEmpty { my $stat = $q->stat; return $stat->qnum == 0; } sub isPrime { my $num = shift; return 1 if ($num < 4); return 0 if ($num %2 == 0); for (my $i=3; $i <= sqrt($num); $i+=2) { return 0 if $num % $i == 0; } return 1; } my $n_workers = shift // die ; enqueue($_) for (1..2_000_000); my $parent = $$; for (my $i=1; $i<$n_workers && $$ == $parent; $i++) { fork // die; } while (my $data = dequeue()) { if (isPrime($data)) { print "Prime: $data\n"; } } END { if ($$ == $parent) { 1 until wait == -1; quit; } }