# 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

- collaborative_once_flag

## 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;
        }
    };