15 #ifndef ABSL_BASE_INTERNAL_ATOMIC_HOOK_H_
16 #define ABSL_BASE_INTERNAL_ATOMIC_HOOK_H_
23 #include "absl/base/attributes.h"
24 #include "absl/base/config.h"
26 #if defined(_MSC_VER) && !defined(__clang__)
27 #define ABSL_HAVE_WORKING_CONSTEXPR_STATIC_INIT 0
29 #define ABSL_HAVE_WORKING_CONSTEXPR_STATIC_INIT 1
33 #define ABSL_HAVE_WORKING_ATOMIC_POINTER 0
35 #define ABSL_HAVE_WORKING_ATOMIC_POINTER 1
40 namespace base_internal {
48 #if ABSL_HAVE_WORKING_CONSTEXPR_STATIC_INIT
49 #define ABSL_INTERNAL_ATOMIC_HOOK_ATTRIBUTES ABSL_CONST_INIT
51 #define ABSL_INTERNAL_ATOMIC_HOOK_ATTRIBUTES
71 template <
typename ReturnType,
typename...
Args>
82 #if ABSL_HAVE_WORKING_ATOMIC_POINTER && ABSL_HAVE_WORKING_CONSTEXPR_STATIC_INIT
83 explicit constexpr
AtomicHook(FnPtr default_fn)
84 : hook_(default_fn), default_fn_(default_fn) {}
85 #elif ABSL_HAVE_WORKING_CONSTEXPR_STATIC_INIT
87 : hook_(kUninitialized), default_fn_(default_fn) {}
95 explicit constexpr
AtomicHook(FnPtr default_fn)
96 : default_fn_(default_fn) {
97 static_assert(kUninitialized == 0,
"here we rely on zero-initialization");
108 bool success = DoStore(
fn);
109 static_cast<void>(success);
115 template <
typename... CallArgs>
117 return DoLoad()(std::forward<CallArgs>(
args)...);
131 return (
ptr == DummyFunction) ? nullptr :
ptr;
146 #if ABSL_HAVE_WORKING_ATOMIC_POINTER
148 FnPtr DoLoad()
const {
return hook_.load(std::memory_order_acquire); }
154 FnPtr expected = default_fn_;
155 const bool store_succeeded = hook_.compare_exchange_strong(
156 expected,
fn, std::memory_order_acq_rel, std::memory_order_acquire);
157 const bool same_value_already_stored = (expected ==
fn);
158 return store_succeeded || same_value_already_stored;
162 #else // !ABSL_HAVE_WORKING_ATOMIC_POINTER
164 static constexpr
intptr_t kUninitialized = 0;
167 "intptr_t can't contain a function pointer");
169 FnPtr DoLoad()
const {
170 const intptr_t value = hook_.load(std::memory_order_acquire);
171 if (
value == kUninitialized) {
174 return reinterpret_cast<FnPtr
>(
value);
177 bool DoStore(FnPtr
fn) {
181 const bool store_succeeded = hook_.compare_exchange_strong(
182 expected,
value, std::memory_order_acq_rel, std::memory_order_acquire);
183 const bool same_value_already_stored = (expected ==
value);
184 return store_succeeded || same_value_already_stored;
187 std::atomic<intptr_t> hook_;
193 #undef ABSL_HAVE_WORKING_ATOMIC_POINTER
194 #undef ABSL_HAVE_WORKING_CONSTEXPR_STATIC_INIT
200 #endif // ABSL_BASE_INTERNAL_ATOMIC_HOOK_H_