A forking version:
use POSIX qw( _exit );
my $num_drives = 3;
my $num_discs = 12;
my @idle; # Idle drives
my %busy; # Busy drives, keyed by the pid using them
sub wait_for_a_kid {
my $pid = wait();
if ($pid == -1) {
warn("Can't wait: $!\n");
return 0;
}
... check the child's exit code if desired ...
push @idle, delete($busy{$pid});
return 1;
}
for my $drive (1..$num_drives) {
... eject disc ...
push @idle, $drive;
}
my @queue = 1..$num_discs;
while (@queue) {
if (!@idle) {
last if !wait_for_a_kid();
}
my $disc = shift(@queue);
my $drive = shift(@idle);
my $pid = fork();
if (!defined($pid)) {
warn("Can't fork: $!\n");
last;
}
if ($pid) {
$busy{$pid} = $drive;
next;
}
if (!eval {
print("Please insert disc $disc in drive $drive\n");
... wait for disc to be present ...
... read disc ...
... eject disc ...
1;
}) {
warn($@);
_exit(1);
}
_exit(0);
}
while (keys(%busy)) {
last if !wait_for_a_kid();
}
Update: Added some error checking. Fixed a bug exit wait loop.