collaborative_call_once

collaborative_call_once

[algorithms.collaborative_call_once]

Function template that executes function exactly once.

// Defined in header <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

Requirements:

  • Func type must meet the Function Objects requirements described in the [function.objects] section of the ISO C++ standard.

Executes the Func object only once, even if it is called concurrently. It allows other threads blocked on the same collaborative_once_flag to join oneTBB parallel construction called within the Func object.

In case of the exception thrown from the Func object, the thread calling the Func object receives this exception. One of the threads blocked on the same collaborative_once_flag calls the Func object again.

collaborative_once_flag Class

Example

The following example shows a class in which the “Lazy initialization” pattern is implemented on the “cachedProperty” field.

#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, [&] {
            // serial part
            double result{};

            // parallel part where threads can collaborate
            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>{}
            );

            // continue serial part
            cachedProperty = result;
        });

        return cachedProperty;
    }
};