collaborative_call_once
[algorithms.collaborative_call_once]
関数を 1 度だけ実行する関数テンプレート。
// <oneapi/tbb/collaborative_call_once.h> ヘッダーで定義
namespace oneapi {
namespace tbb {
template<typename Func, typename...Args>
void collaborative_call_once(collaborative_once_flag& flag, Func&& func, Args&&... args);
} // namespace tbb
} // namespace oneapi
要件:
Func
タイプは、[function.objects] ISO C++ 標準の関数オブジェクトの要件を満たしている必要があります。
Func
オブジェクトは、同時に呼び出されても 1 度だけ実行されます。これにより、同じ collaborative_once_flag
でブロックされた他のスレッドが Func
オブジェクト内で呼び出される oneTBB 並列構造にジョインできるようになります。
Func
オブジェクトから例外がスローされると、Func
オブジェクトを呼び出したスレッドが例外を受け取ります。同じ collaborative_once_flag
でブロックされたスレッドの 1 つが Func
オブジェクトを呼び出します。
collaborative_once_flag クラス
例
次の例は、cachedProperty
フィールドに “遅延初期化” パターンが実装されているクラスを示しています。
#include "oneapi/tbb/collaborative_call_once.h"
#include "oneapi/tbb/parallel_reduce.h"
#include "oneapi/tbb/blocked_range.h"
extern double foo(int i);
class LazyData {
oneapi::tbb::collaborative_once_flag flag;
double cachedProperty;
public:
double getProperty() {
oneapi::tbb::collaborative_call_once(flag, [&] {
// シリアル部分
double result{};
// スレッドが連携する並列部分
result = oneapi::tbb::parallel_reduce(oneapi::tbb::blocked_range<int>(0, 1000), 0.,
[] (auto r, double val) {
for(int i = r.begin(); i != r.end(); ++i) {
val += foo(i);
}
return val;
},
std::plus<double>{}
);
// シリアル部分を継続
cachedProperty = result;
});
return cachedProperty;
}
};