zev.kronenberg
zev.kronenberg

Reputation: 75

Perl threads not printing correctly

If there are explicit examples in another post please let me know. I am having problems with interleaved printing from my threads. I am trying to control my threads by using a shared variable across all threads. The pseudo code below highlights the pieces of my code giving me problems. I have tried everything to make the threads wait their turns to print. Right now only a few output lines are being destroyed.

#!/usr/bin/perl                                                                                                                                
use threads;
use threads::shared;

my $PRINTFLAG :shared = 1;

Run_Threads();

sub Do_stuff{

    lock($PRINTFLAG);
    cond_wait($PRINTFLAG) until $PRINTFLAG == 1;
    $PRINTFLAG = 0;
    print "$working\n";
    $PRINTFLAG =1;
}

Sub to spawn threads.

sub Run_Threads{

    my @threads;

    for (my $i = 1; $i <= 5; $i++){
        push @threads, threads->create(\&Do_stuff);
    }

    foreach (@threads){
        $_->join;
    }
}

Upvotes: 3

Views: 2027

Answers (2)

ikegami
ikegami

Reputation: 385916

It would seem that each thread has its own handle, and thus its own output buffer. Considering that Perl file handles can't be shared using the mechanisms in threads::shared, that's not very surprising.

That means you need to flush the handle's buffer before releasing the lock. You can do that explicitly:

select->flush();       # Flush handle currently default for print.

Or you can have perl flush automatically after every print to that handle:

select->autoflush(1);  # Autoflush handle currently default for print.
$| = 1;                # Autoflush handle currently default for print.

Note: To use the ->flush and ->autoflush methods (but not for $|=1;) before Perl 5.14, you'll need to also load IO::Handle.


By the way,

my $PRINTFLAG :shared = 1;
lock($PRINTFLAG);
cond_wait($PRINTFLAG) until $PRINTFLAG == 1;
$PRINTFLAG = 0;
print "$d\n";
$PRINTFLAG =1;

can be simplified to

my $PRINTMUTEX :shared;
lock($PRINTMUTEX);
print "$d\n";

Upvotes: 5

gangabass
gangabass

Reputation: 10666

From my experience with threads it's much better/simple to use Threads::Queue.

I have two queues: one for the tasks for running threads and another for the results from threads.

So in my master thread I just check the result's queue and print from it. So no any conflicts accessing result file etc.

Upvotes: 3

Related Questions