Как реализовать семафорное взаимодействие потоков в Perl?

Мой Perl-скрипт должен запускать несколько потоков одновременно...

use threads ('yield', 'exit' => 'threads_only');
use threads::shared;
use strict;
use warnings;
 no warnings 'threads';
use LWP::UserAgent;
use HTTP::Request;
use HTTP::Async;
use...

...и такие потоки должны получать некоторую информацию из Интернета, поэтому используется HTTP::Async.

my $request = HTTP::Request->new;
   $request->protocol('HTTP/1.1');
   $request->method('GET');
   $request->header('User-Agent' => '...');

my $async = HTTP::Async->new( slots            => 100,
                              timeout          => REQUEST_TIMEOUT,
                              max_request_time => REQUEST_TIMEOUT );

Но некоторым потокам требуется доступ к сети только тогда, когда другой поток (s )говорит об этом.

my $start = [Time::HiRes::gettimeofday()];
my @threads = ();
foreach... {
  $thread = threads->create(
    sub {
           local $SIG{KILL} = sub { threads->exit };
           my $url = shift;
           if ($url... ) {
             # wait for "go" signal from other threads
           }
           my ($response, $data);
           $request->url($url);
           $data = '';
           $async->add($request);
           while ($response = $async->wait_for_next_response) {
             threads->yield();
             $data.= $response->as_string;
           }
           if ($data... ) {
             # send "go" signal to waiting threads
           }
         }
       }, $_);

  if (defined $thread) {
    $thread->detach;
    push (@threads, $thread);
  }
}

Может быть один или несколько потоков, ожидающих сигнала «вперед», и может быть один или несколько потоков, которые такой сигнал «вперед» может отправить . В начале статус семафора «ожидание », и как только он изменится на «go », он останется таким.

Наконец, приложение проверяет максимальное время работы. Если потоки выполняются слишком долго, отправляется сигнал завершения self -.

my $running;
do {
  $running = 0;
  foreach my $thread (@threads) {
    $running++ if $thread->is_running();
  }
  threads->yield();
} until (($running == 0) || 
         (Time::HiRes::tv_interval($start) > MAX_RUN_TIME));
$running = 0;
foreach my $thread (@threads) {
  if ($thread->is_running()) {
    $thread->kill('KILL');
    $running++;
  }
}
threads->yield();

Теперь к делу. Мои вопросы::

  1. Как мне наиболее эффективно запрограммировать ожидающий «семафор» в скрипте (см. комментарии к скрипту выше ). Должен ли я просто использовать только общую переменную с некоторым фиктивным циклом sleep?

  2. Нужно ли добавлять циклsleepв конец приложения, чтобы дать потокам время для самоуничтожения -?

6
задан Ωmega 7 May 2012 в 20:39
поделиться

0 ответов

Другие вопросы по тегам:

Похожие вопросы: