2013-06-26 12 views
7

私はさまざまなサービス、システム、データベース、ファイルなどのさまざまな「チェック」を実行する「チェッカー」システムを作成しています。「チェック」は本質的に一般的なものであり、何でもかまいません。すべての小切手は、天気予報の天気予報や天気予報などの一般的な形式で報告されます。"any"コードのPerl非同期タスク、それは何ですか?

開発者がフレームワークに従うだけで、1つまたは他のものとは独立してチェックを書くことができるように、モジュラーOO形式で書かれています。各オブジェクトには、共有のレポートオブジェクトが含まれています。共有オブジェクトは、チェックを実行した後、単純に$ self - > {'reporting'} - > report(params)です。 paramsが定義され、開発者が適切に報告すると仮定します。レポートオブジェクトは、これらのレポートのインデックスを作成します。私の主なローダスクリプトは、次のようなエントリがあります。

my $reportingObject = new Checks::Reporting(params); 
my @checks; 

push @checks, new Checks::Check_One($reportingObject, params)); 
push @checks, new Checks::Check_One($reportingObject, params)); 
. 
. 
push @checks, new Checks::Check_N($reportingObject, params)); 

それらが完了したらチェックをキックオフし、レポートを完成するために私がやっている:

foreach my $check (@checks) { 
    $check->run_stuff(); 
} 

$reportingObject->finalize_report(); 

を今すぐこれらのチェックは完全に独立しているので、 (報告オブジェクトについて心配する必要はありません)、それらは並行して実行できます。私が行った改善として:

my @threads; 
foreach my $check (@checks) { 
    push @threads, async { $check->run_stuff(); } 
} 

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

#All threads are complete, and thus all checks are done 
$reportingObject->finalize_report(); 

私が先に述べたように、開発者はお互いに独立して小切手を書くでしょう。いくつかの小切手は単純で、他の小切手はそうではありませ簡単なチェックは、それらに非同期コードを持っていないかもしれませんが、他の人はあなたがスレッドモデルは、私は非常にあいまいな用語で物事を行うことができます見ることができるように、このような

sub do_check { 
    my @threads; 
    my @list = @{$self->{'list'}}; 

    foreach my $item (@list) { 
     push @threads, async { 
        #do_work_on_$item 
        #return 1 or 0 for success or fail 
       }; 
     foreach my $thread (@threads) { 
      my $res = $thread->join; 
      if($res == 1) { 
       $self->{'reporting'}->report(params_here); 
      } 
     } 
    } 
} 

として内部的に非同期で実行する必要がある場合があります。それぞれの "チェック"は、それが自分のスレッドで独立して実行されているかどうかにかかわらず。個々の開発者が非同期のものを持っている場合は、それが何であるかにかかわらず、彼は独自のスレッドでそれを単独で実行します。私はこのようなモデルが欲しい。

残念ながらスレッドは遅く、非効率的です。すべての非同期ライブラリにはIOなどの特定のウォッチャーがあります。私は何も特定したくありません。私はイベントベースのモデルが好きです。これは、非同期タスクが何であっても単に非同期タスクを開始し、すべて完了したときに通知するだけで、私が進めることができます。

うまくいけばそれが説明され、正しい方向に向けることができます。

+2

[間接オブジェクト構文](http://modernperlbooks.com/mt/2009/08/the-problems-with-indirect-object-notation.html)を避けることをお勧めします。 – friedo

+0

AFAIK 「非同期ライブラリ」は常に「特定のIOを実行」し、次に「IO結果を収集する関数を呼び出す」 –

+1

「スレッドは低速で非効率的」という意味はどうですか?また、[builtin threading](http://perldoc.perl.org/threads.html)でこれを行うことができるときに、なぜ非同期ライブラリを使用していますか? –

答えて

6

これはボスワーカーモデルに適してのように思える:

  • スポーン数労働者プログラムの先頭で。すべてのキューにアクセスできることを確認してください。

  • 好きなだけ多くのチェックをエンキューします。作業員は小切手をデキューして実行し、その結果を出力キューにエンキューします。

  • メインスレッドは、出力スレッドの結果を確認し、必要なものを実行します。

  • あなたはおそらくあなたがキューにコードリファレンスを配置する機会がある場合Thread::Queue::Any見たいENDブロックに

を労働者に参加します。ここ

が完全に実行可能な例である:

use strict; use feature 'say'; 
use threads; use threads::shared; use Thread::Queue::Any; 
use constant NUM_THREADS => 5; 
local $Storable::Deparse = 1; local $Storable::Eval = 1; # needed to serialize code 

my $check_q = Thread::Queue::Any->new; 
my $result_q = Thread::Queue::Any->new; 

# start the workers 
{ 
    my $running :shared = NUM_THREADS; 
    my @threads = map threads->new(\&worker, $check_q, $result_q, \$running), 1..NUM_THREADS; 

    END { $_->join for @threads } 
} 

# enqueue the checks 
$check_q->enqueue($_) for sub {1}, sub{2}, sub{"hi"}, sub{ die }; 
$check_q->enqueue(undef) for 1..NUM_THREADS; # end the queue 

while(defined(my $result = $result_q->dequeue)) { 
    report($$result); 
} 

sub report { 
    say shift // "FAILED"; 
} 

sub worker { 
    my ($in, $out, $running_ref) = @_; 
    while (defined(my $check = $in->dequeue)) { 
    my $result = eval { $check->() }; 
    $out->enqueue(\$result); 
    } 

    # last thread closes the door 
    lock $$running_ref; 
    --$$running_ref || $out->enqueue(undef); 
} 

これはわずかにランダムな順序で

1 
2 
hi 
FAILED 

を印刷します。

関連する問題