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

I am trying to figure out issue with thread application.Basically i want a thread which sends data to pipeline and other thread gets data from pipeline and consume it. Issue is below code works fine :
use Thread::Queue; use threads; my $q = Thread::Queue->new(); # A new empty queue print "$q\n"; my $command = "ls -la"; print ("sending command...\n"); $q->enqueue($command); #sleep(60); $command = "pwd"; print ("sending command...\n"); $q->enqueue($command); #sleep(60); $q->end(); # Worker threads my $thr = threads->create(sub { print "running thread : $q\n"; while ((my $item = $q->dequeue())) { print "Running Command : $item \n"; my $result = `$item 2>&1`; print "Result of $item : $result \n"; } } ) ; # terminate. $thr->join();
The below code is similar to above one excepts use a function to send data and call that function in another thread but it doesn't work:
#!/usr/bin/perl use Thread::Queue; use threads; use threads::shared; my $q ; share($q); $q = Thread::Queue->new(); my $thr1 = threads->create(sub { my ($q) = @_; print "Running Thread1 : $q\n"; my $command = "ls -la"; print ("sending command...\n"); $q->enqueue($command); #sleep(60); $command = "pwd"; print ("sending command...\n"); $q->enqueue($command); #sleep(60); $q->end(); } , $q) ; # Worker threads my $thr2 = threads->create(sub { my ($q) = @_; print "running thread2 : $q\n"; while ((my $item = $q->dequeue())) { print "Running Command : $item \n"; my $result = `$item 2>&1`; print "Result of $item : $result \n"; } } ,$q) ; $thr1->join(); $thr2->join(); print "Done\n";

Replies are listed 'Best First'.
Re: Perl thread issue
by huck (Prior) on Dec 29, 2016 at 00:05 UTC

    hmm

    Warning, threads::shared has already been loaded. To enable shared variables, 'use threads' must be called before threads::shared or any module that uses it.
    so
    use threads; use threads::shared; use Thread::Queue;
    ah
    Running Thread1 : Thread::Queue=HASH(0xb7d8c4) sending command... sending command... running thread2 : Thread::Queue=HASH(0xbef644) Running Command : ls -la Result of ls -la : 'ls' is not recognized as an internal or external c +ommand, operable program or batch file. Running Command : pwd Result of pwd : 'pwd' is not recognized as an internal or external com +mand, operable program or batch file. Done

      thanks man. I just loaded threads first and it solved. weird as load order shouldn't matter unless all those perl modules are loaded

        Hi gurjit,

        load order shouldn't matter

        That's true in many cases, but with certain modules, load order can matter. Note that use is equivalent to BEGIN { require Module; Module->import( LIST ); }, and the module's import method can be arbitrary Perl code, and require will essentially eval the file once, also allowing for arbitrary code to be executed. For many modules, they just contain sub definitions and don't execute any code that affects other things in your program, and their import is just Exporter's import and all it does is export certain names, or OO modules may not define an import at all. But a few modules out there can do some pretty complex things upon being used, and in that case, order of loading can make a difference.

        Regards,
        -- Hauke D

        Update: Previously, in the above I just talked about the effects of the import method; I've now updated the text to talk about the eval of the code as well.

Re: Perl thread issue
by BrowserUk (Patriarch) on Dec 29, 2016 at 04:21 UTC

    Why, in your second example, did you decide to share the Thread::Queue object, despite that it is not required, (nor even mentioned) in the POD; when it had worked perfectly without sharing in your first example?


    With the rise and rise of 'Social' network sites: 'Computers are making people easier to use everyday'
    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". The enemy of (IT) success is complexity.
    In the absence of evidence, opinion is indistinguishable from prejudice.
Re: Perl thread issue
by gurjit (Initiate) on Dec 28, 2016 at 23:54 UTC
    I have figured out issue since every data element we pass to thread is copied down so queue enqueue and dequeue are not working on same queue due to which second program is not working. But i am not sure how to solve this problem ?

      I have figured out issue since every data element we pass to thread is copied down so queue enqueue and dequeue are not working on same queue due to which second program is not working. But i am not sure how to solve this problem ?

      How did you figure that out?

      See https://metacpan.org/pod/Thread::Queue#end

      Use a different way to signal the end, like

      $q->enqueue( [ 'capture' => 'ls -la' ] ); ... $q->enqueue( [ 'exit' ] ); ... while ((my $jackson = $q->dequeue())) my( $action, @args ) = @$jackson; last if $action eq 'exit'; if( $action eq 'capture' ){ my $result ... @args ...
        read perl thread documentation here : http://perldoc.perl.org/perlthrtut.html Section shared and unshared data. It mentions below The biggest difference between Perl ithreads and the old 5.005 style threading, or for that matter, to most other threading systems out there, is that by default, no data is shared. When a new Perl thread is created, all the data associated with the current thread is copied to the new thread, and is subsequently private to that new thread! This is similar in feel to what happens when a Unix process forks, except that in this case, the data is just copied to a different part of memory within the same process rather than a real fork taking place.