brintos

brintos / llvm-project-archived public Read only

0
0
Text · 4.6 KiB · 808b1ea Raw
166 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___MUTEX_ONCE_FLAG_H10#define _LIBCPP___MUTEX_ONCE_FLAG_H11 12#include <__config>13#include <__memory/addressof.h>14#include <__tuple/tuple_size.h>15#include <__type_traits/invoke.h>16#include <__utility/forward.h>17#include <__utility/integer_sequence.h>18#include <__utility/move.h>19#include <cstdint>20#ifndef _LIBCPP_CXX03_LANG21#  include <tuple>22#endif23 24#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)25#  pragma GCC system_header26#endif27 28_LIBCPP_PUSH_MACROS29#include <__undef_macros>30 31_LIBCPP_BEGIN_NAMESPACE_STD32 33struct once_flag;34 35#ifndef _LIBCPP_CXX03_LANG36 37template <class _Callable, class... _Args>38_LIBCPP_HIDE_FROM_ABI void call_once(once_flag&, _Callable&&, _Args&&...);39 40#else // _LIBCPP_CXX03_LANG41 42template <class _Callable>43_LIBCPP_HIDE_FROM_ABI void call_once(once_flag&, _Callable&);44 45template <class _Callable>46_LIBCPP_HIDE_FROM_ABI void call_once(once_flag&, const _Callable&);47 48#endif // _LIBCPP_CXX03_LANG49 50struct once_flag {51  _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR once_flag() _NOEXCEPT : __state_(_Unset) {}52  once_flag(const once_flag&)            = delete;53  once_flag& operator=(const once_flag&) = delete;54 55#if defined(_LIBCPP_ABI_MICROSOFT)56  typedef uintptr_t _State_type;57#else58  typedef unsigned long _State_type;59#endif60 61  static const _State_type _Unset    = 0;62  static const _State_type _Pending  = 1;63  static const _State_type _Complete = ~_State_type(0);64 65private:66  _State_type __state_;67 68#ifndef _LIBCPP_CXX03_LANG69  template <class _Callable, class... _Args>70  friend void call_once(once_flag&, _Callable&&, _Args&&...);71#else  // _LIBCPP_CXX03_LANG72  template <class _Callable>73  friend void call_once(once_flag&, _Callable&);74 75  template <class _Callable>76  friend void call_once(once_flag&, const _Callable&);77#endif // _LIBCPP_CXX03_LANG78};79 80#ifndef _LIBCPP_CXX03_LANG81 82template <class _Fp>83class __call_once_param {84  _Fp& __f_;85 86public:87  _LIBCPP_HIDE_FROM_ABI explicit __call_once_param(_Fp& __f) : __f_(__f) {}88 89  _LIBCPP_HIDE_FROM_ABI void operator()() { __execute(__make_index_sequence<tuple_size<_Fp>::value>()); }90 91private:92  template <size_t... _Indices>93  _LIBCPP_HIDE_FROM_ABI void __execute(__index_sequence<_Indices...>) {94    std::__invoke(std::get<_Indices>(std::move(__f_))...);95  }96};97 98#else99 100template <class _Fp>101class __call_once_param {102  _Fp& __f_;103 104public:105  _LIBCPP_HIDE_FROM_ABI explicit __call_once_param(_Fp& __f) : __f_(__f) {}106 107  _LIBCPP_HIDE_FROM_ABI void operator()() { __f_(); }108};109 110#endif111 112template <class _Fp>113void _LIBCPP_HIDE_FROM_ABI __call_once_proxy(void* __vp) {114  __call_once_param<_Fp>* __p = static_cast<__call_once_param<_Fp>*>(__vp);115  (*__p)();116}117 118_LIBCPP_EXPORTED_FROM_ABI void __call_once(volatile once_flag::_State_type&, void*, void (*)(void*));119 120template <class _ValueType>121inline _LIBCPP_HIDE_FROM_ABI _ValueType __libcpp_acquire_load(_ValueType const* __value) {122#if _LIBCPP_HAS_THREADS123  return __atomic_load_n(__value, __ATOMIC_ACQUIRE);124#else125  return *__value;126#endif127}128 129#ifndef _LIBCPP_CXX03_LANG130 131template <class _Callable, class... _Args>132inline _LIBCPP_HIDE_FROM_ABI void call_once(once_flag& __flag, _Callable&& __func, _Args&&... __args) {133  if (__libcpp_acquire_load(&__flag.__state_) != once_flag::_Complete) {134    typedef tuple<_Callable&&, _Args&&...> _Gp;135    _Gp __f(std::forward<_Callable>(__func), std::forward<_Args>(__args)...);136    __call_once_param<_Gp> __p(__f);137    std::__call_once(__flag.__state_, std::addressof(__p), std::addressof(__call_once_proxy<_Gp>));138  }139}140 141#else // _LIBCPP_CXX03_LANG142 143template <class _Callable>144inline _LIBCPP_HIDE_FROM_ABI void call_once(once_flag& __flag, _Callable& __func) {145  if (__libcpp_acquire_load(&__flag.__state_) != once_flag::_Complete) {146    __call_once_param<_Callable> __p(__func);147    std::__call_once(__flag.__state_, std::addressof(__p), std::addressof(__call_once_proxy<_Callable>));148  }149}150 151template <class _Callable>152inline _LIBCPP_HIDE_FROM_ABI void call_once(once_flag& __flag, const _Callable& __func) {153  if (__libcpp_acquire_load(&__flag.__state_) != once_flag::_Complete) {154    __call_once_param<const _Callable> __p(__func);155    std::__call_once(__flag.__state_, std::addressof(__p), std::addressof(__call_once_proxy<const _Callable>));156  }157}158 159#endif // _LIBCPP_CXX03_LANG160 161_LIBCPP_END_NAMESPACE_STD162 163_LIBCPP_POP_MACROS164 165#endif // _LIBCPP___MUTEX_ONCE_FLAG_H166