入力ポートで受け取ったメッセージのセットから tuple<T0,T1, ... > を作成して、タプルをすべての後続 (successor) にブロードキャストするノード。 join_node クラスは、入力ポートで 3 つのバッファーポリシー (reserving、queueing、tag_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, ... >> です。 OutputTuple の T0 .. TN に対応する receiver<Ti> である入力ポートのタプルが含まれます。 異なる型の複数の入力レシーバーをサポートしており、受け取ったメッセージのタプルをすべての後続にブロードキャストします。 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 オブジェクトが作成されます。f1 は int i に 2 を掛けて、f2 は float f を 2 で割って、f3 は std::tuple<int,float> t を受け取り、要素を互いに追加して結果を出力します。 join_node j は、f1 と f2 の出力を組み合わせて、生成されたタプルを 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_node の tag_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 番目の入力ポート。 |