boost::call_once 是如何实现的?
这是否使用双重检查锁定模式?
Qt 或 POCO 库中是否有任何等效的实现?
我偶然发现了这个较老的问题。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();
}