First, thank you for your detailed response.

As you have noted, this code is extremely impractical. It represents the smallest version of a more complex but impractical code that repeated the issue, which is why I posted it. In addition to being a generic learning exercise, my ultimate goal is the design of a main processing engine with worker threads that respond to pause/resume/kill requests. The more complex version follows:

#!/usr/bin/perl use strict; use warnings; use threads; use Thread::Queue; use Thread::Semaphore; # Create terminal watcher print "Create terminal watcher...\n"; my $Q_stdin = Thread::Queue->new; my $T_input = async { $Q_stdin->enqueue( $_ ) while defined( $_ = <S +TDIN> ); }->detach; # Create tracking arrays close STDIN; my $Q_found = Thread::Queue->new; my %workers = (); my %sema = (); my $cmd; #my $i = 0; print "Awaiting commands...\n"; MAIN_LOOP: while (not defined $cmd or $cmd !~ /^q/i) { # Process commands #print ++$i, "\n"; $cmd = $Q_stdin->dequeue_nb; if (defined $cmd) { chomp $cmd; if ($cmd =~ /^q/i) { # Quit print "Resolving open threads\n"; } elsif ($cmd =~ /^w/i) { # Work my (undef, $thread) = split /\s+/, $cmd; if ($thread =~ /\D/) { print "Noninteger thread $thread in $cmd\n"; } elsif (defined ($workers{$thread}) and $workers{$thread} +) { print "Value $thread already a worker\n"; } else { $sema{$thread} = Thread::Semaphore->new(1);; $workers{$thread} = threads->new(\&worker, $thread, $Q_found, $s +ema{$thread} ); } } elsif ($cmd =~ /^p/i) { # Pause my (undef, $thread) = split /\s+/, $cmd; if (defined ($workers{$thread}) and $workers{$thread}) { if (${$sema{$thread}}) { $sema{$thread}->down(); $workers{$thread}->kill('STOP'); print "Thread $thread paused\n"; } else { print "Thread $thread already paused\n"; } } else { print "Unrecognized thread $thread in $cmd\n"; } } elsif ($cmd =~ /^r/i) { #Resume my (undef, $thread) = split /\s+/, $cmd; if (defined ($workers{$thread}) and $workers{$thread}) { if (${$sema{$thread}}) { print "Thread $thread already running\n"; } else { $sema{$thread}->up(); print "Thread $thread resumed\n"; } } else { print "Unrecognized thread $thread in $cmd\n"; } } elsif ($cmd =~ /^s/i) { # Status my (undef, $thread) = split /\s+/, $cmd; if (defined ($workers{$thread}) and $workers{$thread}) { $workers{$thread}->kill('FPE'); } else { print "Unrecognized thread $thread in $cmd\n"; } } elsif ($cmd =~ /^k/i) { # Kill my (undef, $thread) = split /\s+/, $cmd; if (defined ($workers{$thread})) { if ($workers{$thread}) { $workers{$thread}->kill('KILL')->detach; print "Thread $thread killed\n"; $workers{$thread} = 0; } else { print "Thread $thread already dead\n"; } } else { print "Unrecognized thread $thread in $cmd\n"; } } else { print "Unknown/misformatted command $cmd\n"; } } # Print announcements while (defined(my $output = $Q_found->dequeue_nb)) { print $output, "\n"; } sleep(1); # Reduce load } # We're quitting - kill remaining threads for my $thread (grep $workers{$_}, keys %workers) { $workers{$thread}->kill('KILL')->detach; } #--------------------------------------------------------------------- +---------- sub worker { my ($thread, $queue, $semafore) = @_; my $cooldown = 0; # Thread signal handlers $SIG{KILL} = sub { threads->exit(); }; # Kill $SIG{STOP} = sub { $semafore->down(); $semafore->up(); }; # Paus +e $SIG{FPE} = sub { $queue->enqueue("Thread $thread has cooldown $co +oldown."); }; # Report $queue->enqueue("Thread name: $thread"); my %nodes = (); while (1) { $queue->enqueue("$thread step $cooldown"); sleep(5 * int(exp(0.1 * $cooldown++))); } }
.

It mostly comes down to me being unwilling to relinquish control over the scheduling a user interface. Ultimately, I plan on replacing the CLI with a GUI thread, though this is probably all an abuse of queues. I also note I am abusing the FPE signal, which came down to random selection of a signal on both my Linux and Windows boxes that Windows did not treat as fatal.


In reply to Re^2: threads on Windows by kennethk
in thread threads on Windows by kennethk

Title:
Use:  <p> text here (a paragraph) </p>
and:  <code> code here </code>
to format your post, it's "PerlMonks-approved HTML":



  • Posts are HTML formatted. Put <p> </p> tags around your paragraphs. Put <code> </code> tags around your code and data!
  • Titles consisting of a single word are discouraged, and in most cases are disallowed outright.
  • Read Where should I post X? if you're not absolutely sure you're posting in the right place.
  • Please read these before you post! —
  • Posts may use any of the Perl Monks Approved HTML tags:
    a, abbr, b, big, blockquote, br, caption, center, col, colgroup, dd, del, details, div, dl, dt, em, font, h1, h2, h3, h4, h5, h6, hr, i, ins, li, ol, p, pre, readmore, small, span, spoiler, strike, strong, sub, summary, sup, table, tbody, td, tfoot, th, thead, tr, tt, u, ul, wbr
  • You may need to use entities for some characters, as follows. (Exception: Within code tags, you can put the characters literally.)
            For:     Use:
    & &amp;
    < &lt;
    > &gt;
    [ &#91;
    ] &#93;
  • Link using PerlMonks shortcuts! What shortcuts can I use for linking?
  • See Writeup Formatting Tips and other pages linked from there for more info.