开发者

How can I store per-thread state between calls in Perl?

开发者 https://www.devze.com 2022-12-20 19:54 出处:网络
Now from what I understand under Perl ithreads all data is private unless explicitly shared. I want to write a function which stores per thread state between calls.I assume that a side effect of all

Now from what I understand under Perl ithreads all data is private unless explicitly shared.

I want to write a function which stores per thread state between calls. I assume that a side effect of all data being thread private by default would allow me to use a closure like this:

#!/usr/bin/perl -w

use strict;
use threads;

{ # closure to create local static variable
    my $per_thread_state = 0;

    sub foo {
        my $inc = shift;
        $per_thread_开发者_开发百科state += $inc;

        return $per_thread_state;
    }
}

my $inc = 0;

threads->create(
    sub { 
        my $inc = shift;
        my $i = $inc; 
        while (--$i) { 
            threads->yield(); 
            print threads->tid().":".foo($inc)."\n";
        }
    }, $inc
) while (++$inc < $ARGV[0]);

$_->join() foreach threads->list();

When I run it this looks like it works the way I expect, but I just want to be sure because I couldn't find any documentation which explicitly discusses doing something like this.

Could anyone point me to something official looking?

Edit

One other thing that seems strange is that the threads always seem to run in order of creation and don't interleave for some reason. For instance if I run:

./tsd.pl 100

Everything prints out perfectly in order. I'm on Ubuntu 9.04 if it matters.


Provided you're running Perl 5.9.4+, this seems like a good candidate for use of the state keyword. If state is enabled, only your foo() subroutine will be able to modify the value of $per_thread_state.

Here's how:

use feature 'state';

sub foo {
    state $per_thread_state;
    my $inc = shift;
    $per_thread_state += $inc;
    return $per_thread_state;
}

Remember to enable state though (from perlsub):

Beginning with perl 5.9.4, you can declare variables with the state keyword in place of my. For that to work, though, you must have enabled that feature beforehand, either by using the feature pragma, or by using -E on one-liners.

perlsub also has a section on Persistent Private Variable with Closures. What you've done appears to be fine.


Your approach to creating per thread state is correct.

It often helps to think of Perl's threads as a more convenient way to deal with IPC and forked processes. Each call to threads->create(...) clones the current interpreter, along with everything in it, so each thread will get their own independent copy of foo() and $per_thread_state. When you join a thread, you can pass back a value, but everything else in the state of the thread's interpreter will be destroyed.

Your threads are running in creation order largely due to implementation details in Perl and the operating system (mainly because their individual execution time is below the operating system's shortest execution-time slice). To interleave the threads, you can use sleep rather than yield (or make the threads do some real work).

0

精彩评论

暂无评论...
验证码 换一张
取 消