Question

How boost::call_once is implemented ?

Does this one use the double checked locking pattern ?

Is there any equivalent implementation in Qt or POCO library ?

Was it helpful?

Solution

I stumbled upon this older question.. After 4 years, it is probably no longer interesting for your case but I believe a sample implementation may still have some value.

contrary to the claim in the comments section that DCLP is broken, this is no longer true in C++11 since it provides the necessary atomic types, operations and memory barriers.

This is is a minimal implementation, not necessarily the boost implementation. Exception behavior is ignored.
The argument function of my_call_once is guaranteed to be called no more than once and shared data is properly synchronized between threads.. just like the real thing std::call_once

#include <iostream>
#include <thread>
#include <mutex>
#include <atomic>

class my_once_flag {
    std::mutex mtx;
    std::atomic<bool> flg{false};

    template<typename Func, typename... Args>
    friend void my_call_once(my_once_flag&, Func&&, Args&&...);
};

template<typename Func, typename... Args>
void my_call_once(my_once_flag& flag, Func&& f, Args&&... args)
{
    if (flag.flg.load(std::memory_order_acquire) == false)
    {
        std::lock_guard<std::mutex> lck{flag.mtx};

        if (flag.flg.load(std::memory_order_relaxed) == true)
            return;

        std::forward<Func>(f)(std::forward<Args>(args)...);

        flag.flg.store(true, std::memory_order_release);
    }
}

void just_once(int i) { std::cout << "once " << i << std::endl; }

int main()
{
    my_once_flag of;

    std::thread {[&]{ my_call_once(of, just_once, 1); }}.join();
    std::thread {[&]{ my_call_once(of, just_once, 2); }}.join();
}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top