struct once_flag { private: typedef __gthread_once_t __native_type; __native_type _M_once = __GTHREAD_ONCE_INIT; public: /// Constructor constexpr once_flag() noexcept = default; /// Deleted copy constructor once_flag(const once_flag&) = delete; /// Deleted assignment operator once_flag& operator=(const once_flag&) = delete; template<typename _Callable, typename... _Args> friend void call_once(once_flag& __once, _Callable&& __f, _Args&&... __args); };
template<typename _Callable, typename... _Args> void call_once(once_flag& __once, _Callable&& __f, _Args&&... __args) { // _GLIBCXX_RESOLVE_LIB_DEFECTS // 2442. call_once() shouldn't DECAY_COPY() auto __callable = [&] { std::__invoke(std::forward<_Callable>(__f), std::forward<_Args>(__args)...); }; __once_callable = std::__addressof(__callable); __once_call = []{ (*(decltype(__callable)*)__once_callable)(); }; int __e = __gthread_once(&__once._M_once, &__once_proxy); if (__e) __throw_system_error(__e); }
#include <iostream> #include <mutex> #include <memory> #include <thread> using namespace std; struct some_res { some_res() { cout << std::this_thread::get_id() << " : " << __func__ << " : " << "start init" << endl; } private: // big-data }; std::shared_ptr<some_res> res_ptr; std::once_flag res_flag; void foo() { std::call_once(res_flag, [](){ cout << std::this_thread::get_id() << " : " << "start init" << endl; res_ptr = make_shared<some_res>(); cout << std::this_thread::get_id() << " : " << "end init" << endl; }); } void test_static_init() { static some_res res; } int main(int argc, char const *argv[]) { std::thread t1(foo); std::thread t2(foo); t1.join(); t2.join(); // C++11 内存模型 保证初始化只能在一个线程中执行 std::thread t3(test_static_init); std::thread t4(test_static_init); t3.join(); t4.join(); return 0; }
执行结果:
0x800083f90 : start init 0x800083f90 : some_res : start init 0x800083f90 : end init 0x8000841e0 : some_res : start init