Как я могу сохранить состояние каждого потока между вызовами в Perl? - PullRequest
2 голосов
/ 23 февраля 2010

Теперь из того, что я понимаю под Perl, он считывает, что все данные являются частными, если они не переданы явно.

Я хочу написать функцию, которая будет хранить данные о состоянии потока между вызовами. Я предполагаю, что побочный эффект всех данных, являющихся частными по умолчанию, позволил бы мне использовать замыкание, подобное этому:

#!/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();

Когда я запускаю его, это выглядит так, как будто он работает так, как я ожидал, но я просто хочу быть уверен, потому что я не смог найти документацию, в которой явно говорится, что-то подобное.

Может ли кто-нибудь указать мне на что-то официальное?

Редактировать

Еще одна вещь, которая кажется странной, это то, что потоки всегда работают в порядке создания и по какой-то причине не чередуются. Например, если я бегу:

./tsd.pl 100

Все распечатывается идеально по порядку. Я нахожусь на Ubuntu 9.04, если это имеет значение.

Ответы [ 2 ]

2 голосов
/ 23 февраля 2010

Если вы используете Perl 5.9.4+, это кажется хорошим кандидатом на использование ключевого слова state Если state включен, только ваша подпрограмма foo() сможет изменить значение $per_thread_state.

Вот как:

use feature 'state';

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

Не забудьте включить state, хотя (из perlsub ):

Начиная с perl 5.9.4, вы можете объявлять переменные с ключевым словом state вместо my. Однако, чтобы это работало, вы должны предварительно включить эту функцию, используя прагму функции, или -E на однострочниках.

В

perlsub также есть раздел Персистентная частная переменная с замыканиями . То, что вы сделали, похоже, хорошо.

1 голос
/ 24 февраля 2010

Ваш подход к созданию состояния потока корректен.

Часто помогает думать о потоках Perl как о более удобном способе работы с IPC и разветвленными процессами. Каждый вызов threads->create(...) клонирует текущий интерпретатор вместе со всем в нем, поэтому каждый поток получит свою собственную независимую копию foo() и $per_thread_state. Когда вы присоединяетесь к потоку, вы можете передать значение назад, но все остальное в состоянии интерпретатора потока будет уничтожено.

Ваши потоки работают в порядке создания, в основном из-за деталей реализации в Perl и операционной системе (главным образом потому, что их индивидуальное время выполнения ниже самого короткого интервала времени выполнения операционной системы). Чтобы чередовать потоки, вы можете использовать sleep вместо yield (или заставить потоки выполнять какую-то реальную работу).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...