join_node テンプレート・クラス

概要

入力ポートで受け取ったメッセージのセットから tuple<T0,T1, ... > を作成して、タプルをすべての後続 (successor) にブロードキャストするノード。 join_node クラスは、入力ポートで 3 つのバッファーポリシー (reservingqueueingtag_matching) をサポートします。 デフォルトでは、join_node の入力ポートは queueing ポリシーを使用します。

構文

template<typename OutputTuple, graph_buffer_policy JP = queueing>
class join_node;

ヘッダー

#include "tbb/flow_graph.h"

説明

join_node は、graph_node および sender< std::tuple< T0, T1, ... >> です。 OutputTupleT0 .. TN に対応する receiver<Ti> である入力ポートのタプルが含まれます。 異なる型の複数の入力レシーバーをサポートしており、受け取ったメッセージのタプルをすべての後続にブロードキャストします。 join_node の入力ポートはすべて、同じバッファーポリシーを使用しなければなりません。 バッファーポリシーに基づく join_node の動作は、下記の表に示されています。

入力ポートのバッファーポリシーに基づく join_node の動作

バッファーポリシー

動作

queueing

各入力ポートで、受け取ったメッセージがポートの無制限の FIFO (先入れ先出し) キューに追加されます。 各入力ポートに少なくとも 1 つのメッセージがある場合、join_node は各キューの先頭を含むタプルをすべての後続にブロードキャストします。 少なくとも 1 つの後続がタプルを受け付けた場合、各入力ポートのキューの先頭は削除されます。その他の場合、メッセージは各入力ポートのキューに残されます。

reserving

各入力ポートで、join_node は入力がそのポートで利用可能であるとマークして false を返します。 すべてのポートがおそらく利用可能であるとマークされている場合、join_node は既知の先行 (predecessor) から各ポートのメッセージを予約しようとします。 あるポートでメッセージを予約できない場合、そのポートのマークを解除して、以前取得した予約をすべて解除します。 すべてのポートでメッセージを予約できる場合、これらのメッセージを含むタプルをすべての後続にブロードキャストします。 少なくとも 1 つの後続がタプルを受け付けた場合、予約は消費されます。その他の場合、予約は解除されます。

tag_matching

各入力ポートで、ユーザー定義関数オブジェクトがタグを取得するメッセージに適用されます。 次に、キーをタグとして使用して、メッセージが各入力ポートのハッシュテーブルに追加されます。 指定されたタグの各入力ポートにメッセージがある場合、join_node は一致するメッセージを含むタプルをすべての後続にブロードキャストします。 少なくとも 1 つの後続がタプルを受け付けた場合、メッセージは各入力ポートのハッシュテーブルから削除されます。その他の場合、メッセージは各入力ポートに残されます。

join_node の後続がメッセージを拒否した場合、および入力ポートの先行からのメッセージの取得に失敗した場合、メッセージ・パッシング・プロトコルを使用して処理されます (詳細は、以下のリンクを参照)。

input_port テンプレート関数は、特定の入力ポートへの参照を取得するための構文を単純化します。

OutputTuple は、各要素がコピー構築および代入可能な std::tuple<T0,T1, ... > でなければなりません。

#include<cstdio>
#include "tbb/flow_graph.h"
 
using namespace tbb::flow;
 
int main() {
   graph g;
   function_node<int,int>
       f1( g, unlimited, [](const int &i) { return 2*i; } );
   function_node<float,float>
       f2( g, unlimited, [](const float &f) { return f/2; } );
 
   join_node< std::tuple<int,float> > j(g);
 
   function_node< std::tuple<int,float> >
       f3( g, unlimited,
           []( const std::tuple<int,float> &t ) {
               printf( "結果は %f\n",
                       std::get<0>(t) + std::get<1>(t));
           } );
 
   make_edge( f1, input_port<0>( j ) );
   make_edge( f2, input_port<1>( j ) );
   make_edge( j, f3 );
 
   f1.try_put( 3 );
   f2.try_put( 3 );
   g.wait_for_all( );
   return 0;
}

上記の例では、3 つの function_node オブジェクトが作成されます。f1int i に 2 を掛けて、f2float f を 2 で割って、f3std::tuple<int,float> t を受け取り、要素を互いに追加して結果を出力します。 join_node j は、f1f2 の出力を組み合わせて、生成されたタプルを f3 に送ります。 この例は構文を示すことを目的としているため、ノードでほとんど作業を行っていません。

メンバー

namespace tbb {
namespace flow {
 
enum graph_buffer_policy {
    rejecting, reserving, queueing, tag_matching };
 
template<typename OutputTuple, graph_buffer_policy JP = queueing>
class join_node :
    public graph_node, public sender< OutputTuple > {
 
public:
    typedef OutputTuple output_type;
    typedef receiver<output_type> successor_type;
    typedef implementation-dependent-tuple input_ports_tuple_type;
 
    join_node( graph &g );
    join_node( const join_node &src );
    input_ports_tuple_type &inputs( );
    bool register_successor( successor_type &r );
    bool remove_successor( successor_type &r );
    bool try_get( output_type &v );
    bool try_reserve( output_type &v );
    bool try_release( );
    bool try_consume( );
 
};
 
//
// tag_matching 用に特殊化
//
 
template<typename OutputTuple>
class join_node<OutputTuple, tag_matching> :
    public graph_node, public sender< OutputTuple > {
 
public:
 
    // 前の join_node と同じメソッドのほかに
    // tag_matching 関数オブジェクトを指定する
    // コンストラクターがある
 
    template<typename B0, typename B1>
    join_node( graph &g, B0 b0, B1 b1 );
   
    // 3 から 10 の要素でコンストラクターを
    // 同様に定義 ...
};
 
}
}
次の表は、このテンプレート・クラスのメンバーの詳細な情報を提供します。
メンバー 説明
join_node( graph &g ) g のルートタスクを使用してタスクをキューに入れる join_node を構築します。
template < typename B0, typename B1, ... > join_node( graph &g, B0 b0, B1 b1, ... )

join_nodetag_matching の特殊化でのみ利用できるコンストラクター。

関数オブジェクト b0, b1, ... , bN を使用して入力ポート 0 から N のタグを決定する join_node を作成します。 g のルートタスクを使用してタスクをキューに入れます。

警告

join に渡す関数オブジェクトは例外をスローしてはなりません。

join_node( const join_node &src )

src の構築時の状態と同じ初期状態で join_node を構築します。 先行のリスト、入力ポートにあるメッセージ、後続はコピーされません。

input_ports_tuple_type &inputs( )

戻り値: レシーバーの std::tuple。 各要素は tbb::receiver<T> から継承されます。T はその入力で想定されるメッセージの型です。 各タプル要素は、flow::receiver<T> と同じように使用できます。 選択した join_node ポリシーに基づくポートの動作は上記の表に示されています。

bool register_successor( successor_type &r )

後続のセットに r を追加します。

戻り値: true

bool remove_successor( successor_type &r )

後続のセットから r を削除します。

戻り値: true

bool try_get( output_type &v )

join_node のバッファーポリシーに基づいてタプルを生成しようとします。

戻り値: タプルの生成に成功した場合、生成したタプルを v にコピーして true を返します。 その他の場合は false を返します。

bool try_reserve( output_type &v )

予約をサポートしません。

戻り値: false

bool try_release( )

予約をサポートしません。

戻り値: false

bool try_consume( )

予約をサポートしません。

戻り値: false

template<size_t N, typename JNT> typename std::tuple_element<N, typename JNT::input_ports_tuple_type>::type &input_port( JNT &jn )

input_port <N>( jn ) の呼び出しは std::get<N>( jn.inputs() ) の呼び出しと等価です。

戻り値: join_node jn の N 番目の入力ポート。

関連情報