I do not understand how you arrived at this architecture.

Why start a thread to accept the commands from STDIN and then post them to a queue, and then have your main thread read that queue and action them?

The only reason I can see for doing this is so that your main thread/loop can make busy work polling two queues, in non-blocking mode, and sleeping.

Ignoring that the second queues only purpose seems to be to print messages from the workers to the console (which could just as easily have been directed there from within the worker threads), the actions essentially consist entirely of sending signals, so why not perform those actions in the STDIN thread?

I spent ages thinking about your statement of intent to move to using a gui, and whether this conflation of loops was some attempt to bring all the interaction, input and output, together into a single thread in preparation for that. But that doesn't make any sense either. You aren't going to use a command line for input and a gui for output (are you!?), and if the interaction is all going to be via the gui, whether button or keyboard based, it's all going to be event driven. So conflating the two now, would just need to be undone when you make the switch.

Anyway, on the basis of what you've posted, here's how I would do what you are attempting. It all works, though using Thread::Sempaphore and those dratted per thread signals together is awfully clumsy, given that a signal won't even awake a sleep, never mind a semaphore wait.

This code is somewhat stylistically challenged, because it was a case of tacking things in here and there to see what works. I might have tried to rewrite it a little, but given the total disparity between our coding styles, you would have just rewritten it yourself anyway--so you might as well expend the effort :)

The sample run at the bottom shows that all the commands: (w)orker; (s)tatus; (p)ause/resume; (k)ill; and (q)uit all work. To some degree at least:

#! perl -slw use strict; use threads; use Thread::Queue; use Thread::Semaphore; my $Q = new Thread::Queue; my $boss = async { my %workers; my %sems; while( <STDIN> ) { ( local( $_ ), my $name ) = m[([a-zA-Z])\s*(\d+)?] or next; warn "Non-integer thread '$name'\n" and next if defined $name and $name =~m[\D]; if( m[^w]i ) { warn "You must give a name for the worker\n" and next unless defined $name; warn "Worker $name already exists\n" and next if exists $workers{ $name }; $sems{ $name } = new Thread::Semaphore; $workers{ $name } = threads->create( \&worker, $name, $Q, $sems{ $name } ); next; } warn "Worker $name does not exist\n" and next unless m[^q] or exists $workers{ $name }; m[^k] and $sems{ $name }->up, ## Ensure the worker can respon +d delete( $workers{ $name } )->kill( 'KILL' )->join and next; if( m[^p] ) { ${ $sems{ $name } } ? $sems{ $name }->down : $sems{ $name }->up; $workers{ $name }->kill( 'STOP' ); next; } m[^s] and $sems{ $name }->up, ## Ensure a paused thread is able to r +espond $workers{ $name }->kill( 'FPE' ), $sems{ $name }->down ## and set it back and next; m[^q] or next; for( keys %workers ) { $sems{ $_ }->up; $workers{ $_ }->kill( 'KILL' )->join; } $Q->enqueue( undef ); ## Terminate main loop last; } }; print ">$_" while defined( $_ = $Q->dequeue ); $boss->join; exit; sub worker { my( $name, $queue, $sem ) = @_; my $cooldown = 0; my $state = 0; $SIG{KILL} = sub { warn "Worker $name dying\n"; threads->exit(); }; $SIG{STOP} = sub { printf STDERR "Worker $name is %s\n", ( $state ^= 1 ) ? 'paused' : 'resumed'; $sem->down(); $sem->up(); }; $SIG{FPE } = sub { $queue->enqueue("Worker $name has cooldown $cooldown."); }; $queue->enqueue("Worker $name starting"); my %nodes = (); while (1) { $queue->enqueue("$name step $cooldown"); sleep 1; $cooldown++; } } __END__ C:\test>743398.pl w1 >Worker 1 starting >1 step 0 >1 step 1 p1>1 step 2 Worker 1 is paused s1 >Worker 1 has cooldown 2. w2 >Worker 2 starting >2 step 0 >2 step 1 >2 step 2 p>2 step 3 2 Worker 2 is paused s2 >Worker 2 has cooldown 3. k1 >1 step 3 Worker 1 dying q >2 step 4 Worker 2 dying

Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
"Science is about questioning the status quo. Questioning authority".
In the absence of evidence, opinion is indistinguishable from prejudice.
"Too many [] have been sedated by an oppressive environment of political correctness and risk aversion."

In reply to Re^3: threads on Windows by BrowserUk
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.