call_once通过双重检查锁定模式实现

时间:2013-08-22 19:18:29

标签: c++ qt boost poco-libraries

如何实现boost :: call_once?

这个是否使用双重检查锁定模式?

Qt或POCO库中是否有相应的实现?

1 个答案:

答案 0 :(得分:1)

我偶然发现了这个老问题。 4年后,它可能不再适用于您的情况,但我相信示例实现可能仍然具有一定的价值。

与评论部分中声称DCLP被破坏的情况相反,在C ++ 11中不再如此,因为它提供了必要的原子类型,操作和内存障碍。

这是一个最小的实现,不一定是boost实现。忽略异常行为 保证my_call_once的参数函数不会被调用一次,并且共享数据在线程之间正确同步......就像真实的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();
}