1 つまたは複数のサクセサーへの送信

事前定義ノードの重要な特性は、出力を 1 つのサクセサーに push するか、すべてのサクセサーにブロードキャストするかどうかです。次の事前定義ノードは 1 つのサクセサーにメッセージを push します。

ほかのノードは、メッセージを受け付けるすべてのサクセサーに push します。

1 つのサクセサーのみに push するノードはすべてバッファーノードです。その目的は、ダウンストリームに消費されるまで、メッセージを一時的に保持することです。次の例について考えてみます。

void use_buffer_and_two_nodes() {
  graph g;

  function_node< int, int, rejecting > f1( g, 1, []( int i ) -> int {
    spin_for(0.1);
    cout << "f1 consuming " << i << "\n";
    return i; 
  } );

  function_node< int, int, rejecting > f2( g, 1, []( int i ) -> int {
    spin_for(0.2);
    cout << "f2 consuming " << i << "\n";
    return i; 
  } );

  priority_queue_node< int > q(g);

  make_edge( q, f1 );
  make_edge( q, f2 );
  for ( int i = 10; i > 0; --i ) {
    q.try_put( i );
  }
  g.wait_for_all();
}

まず、function_node は入力で受け取ったメッセージをデフォルトでキューに入れます。priority_queue_nodefunction_node で適切に動作するように、上記の例では function_node と拒否するバッファー・ポリシー・セットを構築しています。このため、f1f2 は着信メッセージを内部にバッファーしないで、代わりに priority_queue_node のアップストリーム・バッファーに依存します。

上記の例で、priority_queue_node にバッファーされたメッセージは、f1 または f2 のいずれかに送られます。両方には送られません。

別の動作を行った場合、例えば、priority_queue_node がすべてのサクセサーにブロードキャストした場合を考えてみましょう。全ノードではなく、一部のノードがメッセージを受け付ける場合はどうすれば良いでしょうか。すべてのノードがメッセージを受け付けるまでメッセージをバッファーすべきでしょうか。それとも、メッセージを受け付けるバッファーのみにメッセージを送信すべきでしょうか。ノードがメッセージをバッファーし続ける場合、ノードが次のメッセージを受け付けるときに、すべてのノードに同じ順でメッセージを送信すべきでしょうか。それとも現在の優先順でメッセージを送信すべきでしょうか。例えば、priority_queue_node が "9" のメッセージのみを含み、サクセサーノード f1 が "9" を受け付け、別のサクセサーノード f2 が "9" を拒否したとします。次に、"100" のメッセージが到着し、f2 はこのメッセージを受け付けることができるとします。この場合、f2 は "9" と "100" のどちらを受け取るべきでしょうか。どちらの優先度が高いでしょうか。どのような状況でも、すべてのサクセサーがメッセージを受信できることを保証しようとすると、ガベージ・コレクション問題が起こり、問題の原因が複雑になります。このため、これらのバッファーノードは 1 つのサクセサーのみにメッセージを push します。また、この特性を活かして、上記のグラフで示されているような、各メッセージが f1 または f2 のいずれかで優先順に処理されるグラフ構造を作成することができます。

では、f1f2 の両方ですべての値を優先順に受信したい場合はどうすればいいでしょうか。この場合は、次に示すように、function_node ごとに 1 つの priority_queue_node を作成し、broadcast_node を使用して値を両方のキューに push します。

  graph g;

  function_node< int, int, rejecting > f1( g, 1, []( int i ) -> int {
    spin_for(0.1);
    cout << "f1 consuming " << i << "\n";
    return i; 
  } );

  function_node< int, int, rejecting > f2( g, 1, []( int i ) -> int {
    spin_for(0.2);
    cout << "f2 consuming " << i << "\n";
    return i; 
  } );

  priority_queue_node< int > q1(g);
  priority_queue_node< int > q2(g);
  broadcast_node< int > b(g);

  make_edge( b, q1 );
  make_edge( b, q2 );
  make_edge( q1, f1 );
  make_edge( q2, f2 );
  for ( int i = 10; i > 0; --i ) {
    b.try_put( i );
  }
  g.wait_for_all();

このため、複数のサクセサーにグラフのノードを接続する場合は、出力がすべてのサクセサーにブロードキャストされるのか、1 つのサクセサーにのみ送信されるのかを必ず理解するようにしてください。

関連情報