in reply to multi-threaded questions

So I came up with a proof of concept based on the suggestions here. Please let me know if i am doing anything wrong. Thanks to all who posted:

#!/usr/bin/perl use threads; use Thread::Queue; use threads::shared; our $queue = Thread::Queue->new; my $test = "0"; my $stop_var : shared = 0; for (1..30){ $thr = threads->new(\&thread_sub1); } for (1..30){ $thr1 = threads->new(\&thread_sub); } foreach $thr ( threads->list ) { $thr->join; } foreach $thr1 ( threads->list ) { $thr1->join; } sub thread_sub { my $tid = threads->self->tid(); my $sec=1; until ($sec == 0) { ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) += localtime(time); # print "$sec\n"; } lock($stop_var); if ($stop_var ==0) { $stop_var = 1; for (1..30){ $queue->enqueue($tid); } } } sub thread_sub1 { my $tid = threads->self->tid(); print "Order thread number $tid spawned\n"; $action1 = $queue->dequeue; print "I have gotten through the queue my lord: $action1\n"; }

Replies are listed 'Best First'.
Re^2: multi-threaded questions
by zentara (Cardinal) on Dec 09, 2006 at 12:31 UTC
    You don't need 2 join subs. As you can see, all threads are in main's thread->list. You probably should 'use warnings' and 'use strict' too, it will help you keep from confusing variables.
    my @list = threads->list; print scalar(@list),"\n"; foreach my $thr ( threads->list ) { $thr->join; }

    I'm not really a human, but I play one on earth. Cogito ergo sum a bum
Re^2: multi-threaded questions
by renodino (Curate) on Dec 09, 2006 at 21:20 UTC
    Again, as your intentions are less than clear, I'm "assuming" intent.

    1. The "self->" in "threads->self->tid()" isn't needed (its an unfortunate meme many of us inherited from older threads docs).

    2. If your intent is to kill the worker threads whenever any master thread detects an event, then you're fine.

    However, I suspect you ultimately intend to keep those worker threads around to field queued events until the daemon is terminated. If my assumption is correct, then you've got a problem: queueing 30 msgs does not guarantee that all 30 threads will get a copy of the msg. It's entirely possible (indeed, quite probable) that the first few threads may get back to dequeueing before the last waiting threads get a chance to dequeue().

    Which means you either have to

    • use 30 individual queues, one per worker, and enqueue() to all 30 queues when dispatching an event
    • (as previously mentioned) use Thread::Queue::Multiplex aka TQM.

    TQM provides a publish/subscribe capability, so that your master (as publisher) need only post a single msg to a single queue, and all worker threads (as subscribers) will get their own copy of the msg.


    Perl Contrarian & SQL fanboy