アクティブな source_node は、エッジが接続されるとすぐにメッセージの送信を開始します。適切に管理されていないと、メッセージが廃棄されることがあります。デフォルトでは、インアクティブ状態で構築されない限り、source_node はアクティブです。
template< typename Body > source_node( graph &g, Body body, bool is_active=true )
インアクティブな source_node をアクティブにするには、ノードの activate 関数を呼び出します。
source_node< int > src( g, src_body(10), false );
// make_edge への呼び出しで使用 ...
src.activate();
この管理を行うには、source_node をすべてインアクティブ状態で構築してフローグラフ全体が構築された後にアクティブにするか、グラフを構築するときにメッセージが廃棄されないように注意しなければなりません。
例えば、データフロー・グラフのコードを使用できます。この実装では、source_node はインアクティブ状態で構築され、ほかのエッジがすべて作成された後にアクティブにされています。
make_edge( squarer, summer );
make_edge( cuber, summer );
source_node< int > src( g, src_body(10), false );
make_edge( src, squarer );
make_edge( src, cuber );
src.activate();
g.wait_for_all();
この例で、source_node がアクティブ状態で構築された場合、エッジが squarer に接続された後、直ちに squarer にメッセージを送ります。次に、エッジが cuber に接続されると、cuber は接続以降のメッセージをすべて受け取りますが、接続前の一部のメッセージを受け取っていない可能性があります。
一般に、source_node をインアクティブ状態で構築し、グラフ全体が構築された後にアクティブ状態にすることが最も安全です。しかし、このアプローチではグラフの構築とグラフの実行がシリアル化されます。
一部のグラフでは、構築と実行のオーバーラップを許可することで、source_node をアクティブ状態で安全に構築できます。グラフが有向非巡回グラフ (DAG) で、各 source_node に 1 つのサクセサーのみ含まれる場合、逆トポロジカル順にエッジを構築すれば、アクティブ状態で source_node を構築できます。つまり、最初にツリーの最も深いエッジを作成した後、最も浅いエッジに戻ります。例えば、src が source_node で func1 と func2 がどちらも関数ノードの場合、次のグラフは src がアクティブ状態で構築された場合でもメッセージは廃棄されません。
const int limit = 10;
int count = 0;
graph g;
source_node<int> src( g, [&]( int &v ) -> bool {
if ( count < limit ) {
++count;
v = count;
return true;
} else {
return false;
}
} );
function_node<int,int> func1( g, 1, []( int i ) -> int {
cout << i << "\n";
return i;
} );
function_node<int,int> func2( g, 1, []( int i ) -> int {
cout << i << "\n";
return i;
} );
make_edge( func1, func2 );
make_edge( src, func1 );
g.wait_for_all();
func1 から func2 のエッジが、src から func1 のエッジの前に作成されるため、上記のコードは安全です。src から func1 のエッジが最初に作成された場合、func2 がアタッチされる前に func1 がメッセージを生成すると、そのメッセージは廃棄されます。また、src には 1 つのサクセサーのみ含まれます。src に 2 つ以上のサクセサーが含まれる場合、最初にアタッチされたサクセサーが、後からアタッチされたサクセサーが受け取らないメッセージを受け取る場合があります。