in reply to Re: threads on Windows
in thread threads on Windows
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.
|
|---|
| Replies are listed 'Best First'. | |
|---|---|
|
Re^3: threads on Windows
by BrowserUk (Patriarch) on Feb 13, 2009 at 04:09 UTC | |
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 | |
|