in reply to Re^2: threads on Windows
in thread threads on Windows
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
|
|---|
| Replies are listed 'Best First'. | |
|---|---|
|
Re^4: threads on Windows
by kennethk (Abbot) on Feb 13, 2009 at 17:48 UTC | |
by BrowserUk (Patriarch) on Feb 13, 2009 at 20:37 UTC | |
by kennethk (Abbot) on Feb 17, 2009 at 22:45 UTC | |
by BrowserUk (Patriarch) on Feb 18, 2009 at 15:22 UTC | |
by kennethk (Abbot) on Feb 18, 2009 at 16:38 UTC | |
|