103 lines · c
1//===----------------------------------------------------------------------===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8 9#ifndef _LIBCPP___CXX03___MUTEX_ONCE_FLAG_H10#define _LIBCPP___CXX03___MUTEX_ONCE_FLAG_H11 12#include <__cxx03/__config>13#include <__cxx03/__memory/addressof.h>14#include <__cxx03/__memory/shared_ptr.h> // __libcpp_acquire_load15#include <__cxx03/__tuple/tuple_indices.h>16#include <__cxx03/__tuple/tuple_size.h>17#include <__cxx03/__type_traits/invoke.h>18#include <__cxx03/__utility/forward.h>19#include <__cxx03/__utility/move.h>20#include <__cxx03/cstdint>21 22#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)23# pragma GCC system_header24#endif25 26_LIBCPP_PUSH_MACROS27#include <__cxx03/__undef_macros>28 29_LIBCPP_BEGIN_NAMESPACE_STD30 31struct _LIBCPP_TEMPLATE_VIS once_flag;32 33template <class _Callable>34_LIBCPP_HIDE_FROM_ABI void call_once(once_flag&, _Callable&);35 36template <class _Callable>37_LIBCPP_HIDE_FROM_ABI void call_once(once_flag&, const _Callable&);38 39struct _LIBCPP_TEMPLATE_VIS once_flag {40 _LIBCPP_HIDE_FROM_ABI once_flag() _NOEXCEPT : __state_(_Unset) {}41 once_flag(const once_flag&) = delete;42 once_flag& operator=(const once_flag&) = delete;43 44#if defined(_LIBCPP_ABI_MICROSOFT)45 typedef uintptr_t _State_type;46#else47 typedef unsigned long _State_type;48#endif49 50 static const _State_type _Unset = 0;51 static const _State_type _Pending = 1;52 static const _State_type _Complete = ~_State_type(0);53 54private:55 _State_type __state_;56 57 template <class _Callable>58 friend void call_once(once_flag&, _Callable&);59 60 template <class _Callable>61 friend void call_once(once_flag&, const _Callable&);62};63 64template <class _Fp>65class __call_once_param {66 _Fp& __f_;67 68public:69 _LIBCPP_HIDE_FROM_ABI explicit __call_once_param(_Fp& __f) : __f_(__f) {}70 71 _LIBCPP_HIDE_FROM_ABI void operator()() { __f_(); }72};73 74template <class _Fp>75void _LIBCPP_HIDE_FROM_ABI __call_once_proxy(void* __vp) {76 __call_once_param<_Fp>* __p = static_cast<__call_once_param<_Fp>*>(__vp);77 (*__p)();78}79 80_LIBCPP_EXPORTED_FROM_ABI void __call_once(volatile once_flag::_State_type&, void*, void (*)(void*));81 82template <class _Callable>83inline _LIBCPP_HIDE_FROM_ABI void call_once(once_flag& __flag, _Callable& __func) {84 if (__libcpp_acquire_load(&__flag.__state_) != once_flag::_Complete) {85 __call_once_param<_Callable> __p(__func);86 std::__call_once(__flag.__state_, std::addressof(__p), std::addressof(__call_once_proxy<_Callable>));87 }88}89 90template <class _Callable>91inline _LIBCPP_HIDE_FROM_ABI void call_once(once_flag& __flag, const _Callable& __func) {92 if (__libcpp_acquire_load(&__flag.__state_) != once_flag::_Complete) {93 __call_once_param<const _Callable> __p(__func);94 std::__call_once(__flag.__state_, std::addressof(__p), std::addressof(__call_once_proxy<const _Callable>));95 }96}97 98_LIBCPP_END_NAMESPACE_STD99 100_LIBCPP_POP_MACROS101 102#endif // _LIBCPP___CXX03___MUTEX_ONCE_FLAG_H103