2013-04-05 6 views
10

1つのアプリケーションに複数のタスクがあり、いずれの順序で終了してもよいとします。すべてのタスクが完了したら、コードを実行する必要があります。その場合、アプリケーションはAnyEventではなくCoroなしで実行されています。多重化コールバック

ある程度、AnyEvent$cv->begin/$cv->endは、私が望むことを許しています。しかし、もっと細かい制御が必要です。例えば、私は仕事を2回「完了」することができないようにしたいと思います。すべてのタスクからデータを収集する能力も良いでしょう。

もちろん、これを行うことができます。ハッシュを共有するたくさんのコールバックを設定します。タスクが終了するたびにそのハッシュからキーを削除する。ハッシュが空のときにmegacallbackを呼び出します。私はそれを行うより文明的な方法、多分いくつかのCPANモジュールがあるのだろうか?

たとえば、私の必要性を満たす想像上のAPIがあります。

#!/usr/bin/perl -w 
use strict; 

use Some::Module; 

# Set goals 
my $cb = Some::Module->new(sub { say 'BOOM!' }); 
$cb->begin(qw(foo bar)); 

# Much later, as tasks start getting done 
$cb->end(foo => 42);  # "return" value from task 'foo' 
$cb->begin('baz');   # can add more tasks, why not 
$cb->end('bar');   # just finish task 'bar' 
# still waiting for 'baz' to finish at this point 

# Finally, last hanging task is done 
$cb->end(baz => 137);  # BOOM! 
# at this point, sub {}->({ foo=>42, bar=>undef, baz=>137 }) 
#  has been called 

も私のperlmonks questionを参照してください。

このようなものがありますか?

答えて

3

Futureとするとよいでしょう。

具体的には、完了するまでに多くのことを待っているために、あなたはFuture->needs_allまたは類似を使用することができます。

my @things = ... # generate Futures to represent each thing 

Future->needs_all(@things) 
    ->on_done(sub { 
    # some code here when all the things are done 
    }); 

また、あなたはまた、あなたが考えていたものに非常に近いAPIを与えるAsync::MergePointを試みることができる:

my $mp = Async::MergePoint->new(needs => [qw(foo bar)]); 
$mp->close(on_done => sub { 
    # some code here when all the things are done 
}); 

$mp->done(foo => $value); 
$mp->done(bar =>); 
+0

MergePointは*頼んだものです。ありがとうございます。 – Dallaylaen

+0

未来も有望そうです。再度、感謝します。私は2倍upvoteすることができたらいいと思う。 – Dallaylaen

2

私は確かに非同期のものは専門家ではありませんが、私はMojo::IOLoop::DelayMojoliciousスイートの一部)も同様のインターフェイスを持っていると思います。 Mojo :: IOLoopはEV and thus AnyEventと一緒に使用できます。ここ

the cookbookの例である:

use Mojo::UserAgent; 
use Mojo::IOLoop; 

# Synchronize non-blocking requests portably 
my $ua = Mojo::UserAgent->new; 
my $delay = Mojo::IOLoop->delay(sub { 
    my ($delay, $tx, $tx2) = @_; 
    ... 
}); 
$ua->get('http://mojolicio.us'   => $delay->begin); 
$ua->get('http://mojolicio.us/perldoc' => $delay->begin); 
$delay->wait unless Mojo::IOLoop->is_running; 

また、$delay->beginは本質的end方法であって、コールバックを返すことに注意してください。

クールな「ステップ」コンセプトのような他の例は、::遅延ドキュメントに示されています。ここで

EDIT

は簡単な例です。わずかな構文変更が遅延クラスで発生したことに注意してください。これはMojolicious 3.93+でのみ有効です。これは以前は不可能ではありませんでしたが、構文が少し異なりました。

#!/usr/bin/env perl 

use strict; 
use warnings; 
use v5.10; 

use Mojo::IOLoop; 

my $delay = Mojo::IOLoop->delay(sub{shift; say for @_}); 

my $end_foo = $delay->begin(0); 
Mojo::IOLoop->timer(0 => sub { $end_foo->('hi') }); 

my $end_bar = $delay->begin(0); 
Mojo::IOLoop->timer(0 => sub { $end_bar->('bye') }); 

$delay->wait unless $delay->ioloop->is_running; #start loop if necessary 

ここでは遅延オブジェクトを作成します。引数はfinishイベントコールバックです。各非同期アクションに対して、私はbeginを呼び出し、endコールバックを返します。デフォルトでは、これらのコールバックは最初の引数を取り除いて余分な呼び出し元を削除します(上記の例を参照)。しかし、それらは持っていません。したがって、そうしないことを示すために0を渡します。それぞれのアクションについて、私は単純にゼロ待機タイマを延期します。エンドコールバックへの引数は、endイベントに対して順番にキューに入れられます。タダ!

関連する問題