Thread - Boss Worker updated

It is a fundamental law of ... blogging that updates come in spurts? I hacked (just a little teensy weensy tiny bit) and we're back in business with the 5.8 threading. Apparently, the distinction between joinable and still waiting has been removed with the recent threads upgrades. I don't have enough free brain cells to grok this, but the punch line is ... well, look at the finished version of 'threadbossworker.pl' for yourself, and compare it to http://www.radkeland.org/boss-worker-threaded-model-implemented-perl if you're masochistic, and ... grin, and hope it works for you. The short bit is that arguments to thread->list() are now completely irrelevant.

#!/usr/bin/perl -w
#
# threadbossworker.pl
#
# Copyright 2008 Joshua Radke (josh at radkeland dot org)
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License (version 2) as
# published by the Free Software Foundation.
#
# This program is a demonstration (simple scaffold) for a boss/worker
# threaded program.  It uses semaphores to control the number of worker
# threads allowed.  It uses a general cleanthreads() routine to gather
# the results from finished threads.  The cleanthreads routine takes a
# reference to a function to determine what to do with the harvested
# threads.
#
# These are the minimum needed to implement a semaphore managed
# threading program.
use strict;
use threads;
use Thread::Semaphore;

# Cleanthreads harvests and dispatches the return values of the worker
# threads (detail with the actual function).  Idleworker hangs out
# awhile, and returns its original value untouched.  Note that
# idleworker needs to be thread aware (increment and decrement the
# semaphore).  Printreturn prints the value of whatever is passed to
# it, with a newline appended.
sub cleanthreads($$@);
sub idleworker($);
sub printreturn($);

my $maxthreads = 5;
my $sem = new Thread::Semaphore($maxthreads);

for my $i (1 .. 10) {
  threads->create(\&idleworker, $i) or die "Unable to create thread";
  cleanthreads(0, \&printreturn, "foo");
}

cleanthreads(1, \&printreturn, "foo");
exit(0);

# Cleanthreads is the interesting workhorse of the threading model.  It is
# called like this:
# cleanthreads(<mode>, <action function>, <list of other arguments
#                                          for action function> )
# Mode = 0 or 1.  The meanings are:
#  0:  Find all joinable threads , and join/process the return value.
#      Do not return unless there is at least one semaphore available.
#  1:  Clean all threads but the parent before returning.
sub cleanthreads($$@) {
  my $mode = shift @_;
  my $func = shift @_;
  my @othervals = (defined($_[0])) ? (@_) : (undef);
  my @thrlist;

  # Get our list of threads to join.
  @thrlist = threads->list();

  # And do the deed.  I had previous reservations, but had no idea what
  # I was concerned about.  Progress sometimes (regretably) hides the true
  # reality that should have been uncovered, but remains buried to the
  # author's incompetence.
  foreach my $thr (@thrlist) {
    &$func($thr->join(), @othervals);
  }
  return;
}

sub idleworker($) {
  $sem->down;
  my $retval = shift @_;
  sleep 2;
  $sem->up;
  return $retval;
}

sub printreturn($) {
  print "$_[0]\n";
  return;
}