Shades has asked for the wisdom of the Perl Monks concerning the following question:

I have a threaded program with queue implemented as an array of arrays (I need the possibility to insert commands in the middle of the queue sometimes, so the Thread::Queue doesn't fit.) However, when I add to the queue, it doesn't stick. Here's where I insert the things in the queue:
sub queuecommand { my ($mcvpservers, $cmd, $priority, $server, $file, $time) = @_; my @tmp : shared; @tmp = ($cmd, $priority, $server, $file, $time); my @queue = $mcvpservers->{$server}->[2]; print $#queue+1; if ($#{$queue[0]}+1 == 0) { push @queue, \[@tmp]; } else { for(my $i = 0; $i < $#queue+1; $i++) { if ($priority > $queue[$i][1]) { splice @queue, $i, 0, \[@tmp]; last; } } } print $#queue+1; }
The $mcvpservers is a hash_ref with a queue at the 2 index. I have created the queue as a shared: our @queue : shared = (); Everytime I enter the queuecommand, my queue is empty. What have I done wrong?

Replies are listed 'Best First'.
Re: Shared variable not changing?
by weismat (Friar) on Mar 17, 2009 at 10:40 UTC
    You are hiding the shared queue, because you have a my @queue in your code.
    Additionally there is no lock statement anywhere, thus this will never ever be thread-safe. If you want to extent Thread::Queue, you should first read the thread tutorial and look at the implementation of Thread::Queue in the lib directory.
    I would suggest that you copy the enqueue code into a new function and change it to work inside the queue. The implementation of the Thread::Queue shows you the difficulty of working with threads in a safe way...
Re: Shared variable not changing?
by BrowserUk (Pope) on Mar 17, 2009 at 11:15 UTC
    (I need the possibility to insert commands in the middle of the queue sometimes, so the Thread::Queue doesn't fit.)

    The you do not want a 'queue'. A queue is fed from one end and read from the other. How can you ever know what is "the middle of the queue"?


    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.
Re: Shared variable not changing?
by zentara (Archbishop) on Mar 17, 2009 at 13:12 UTC
    I'm not bothering to work my way thru all that ref based code, but from your node title, I will tell you that other threads will NOT automatically update the value they have for the shared variable..... it needs to be updated manually in a whille loop or an event-system. Threads do NOT export the value they set in their own thread, to ALL other threads. They don't even NOTIFY other threads that there has been a change.

    If you want real sharing of actual memory space, used Shared Memory Segments. But pardon me, if you already realize this.


    I'm not really a human, but I play one on earth My Petition to the Great Cosmic Conciousness
Re: Shared variable not changing?
by Anonymous Monk on Mar 17, 2009 at 10:20 UTC
    Are you using hreads::shared? What variable are you expecting to be shared (@tmp/@queue have short lifespans)?
      Yes, I'm using threads::shared. I want to add to the queue that resides in $mcvpservers->{$server}->2. Do I have to push to that reference somehow?
        ...the queue that resides in $mcvpservers->{$server}->[2]. Do I have to push to that reference somehow?

        If that's an array reference, you probably don't want

        my @queue = $mcvpservers->{$server}->[2];

        but rather

        my $queue = $mcvpservers->{$server}->[2]; ... push @$queue, ...

        Update: as you have it, your array ref (queue) will be assigned to the first element of @queue, but whatever you push onto @queue will be added outside of what is pointed to by the array ref. Consider

        use Data::Dumper; our @queue = (qw(stuff in queue)); my $server = "name"; $mcvpservers->{$server}->[2] = \@queue; # ... my @queue = $mcvpservers->{$server}->[2]; push @queue, "morestuff"; print Dumper \@queue; __END__ $VAR1 = [ [ 'stuff', 'in', 'queue' ], 'morestuff' ];
Re: Shared variable not changing?
by Shades (Initiate) on Mar 17, 2009 at 14:50 UTC
    Than you all for the answers. I read a bit more and I realized I could use Thread::Queue, since it has insert and peek, which I needed. My queue was a priority based queue, so if a command had a higher priority, it would go ahead of a lower priority command. Thread::Queue worked fine, and now my program works.