wait_for_all() を常に使用する

フローグラフのプログラミングでよくあるミスの 1 つは、wait_for_all の呼び出しを忘れることです。graph::wait_for_all 関数は、グラフでスポーンされたすべてのタスクが完了するまでブロックします。wait_for_all は、計算が完了するまで待つときに便利なだけでなく、グラフやそのノードを破棄する前には呼び出す必要があります。例えば、次の関数を実行するとプログラムは失敗します。

void no_wait_for_all() {
	graph g;
	function_node< int, int > f( g, 1, []( int i ) -> int {
		return spin_for(i);
	} );
	f.try_put(1);

	// f のボディーは完了していないため、f と g がスコープの
	// 最後で破棄されるとプログラムは失敗する
}

上記の関数で、グラフ g とそのノード f は関数のスコープの最後で破棄されます。しかし、f のボディーを実行するためにスポーンされたタスクはまだ実行中です。タスクが完了すると、タスクはノードに接続されているサクセサーを探しますが、その前にグラフとノードはどちらも削除されています。関数の最後に g.wait_for_all() を置くことで、グラフとノードが先に破棄されなくなります。

フローグラフを使用していて動作がおかしい場合は、wait_for_all を呼び出しているかどうかを最初に確認してください。

関連情報