16 #ifndef ABSL_BASE_INTERNAL_ATOMIC_HOOK_H_ 17 #define ABSL_BASE_INTERNAL_ATOMIC_HOOK_H_ 25 #define ABSL_HAVE_WORKING_ATOMIC_POINTER 0 27 #define ABSL_HAVE_WORKING_ATOMIC_POINTER 1 31 namespace base_internal {
49 template <
typename ReturnType,
typename... Args>
52 using FnPtr = ReturnType (*)(Args...);
60 #if ABSL_HAVE_WORKING_ATOMIC_POINTER 62 : hook_(default_fn), default_fn_(default_fn) {}
65 : hook_(kUninitialized), default_fn_(default_fn) {}
75 bool success = DoStore(fn);
76 static_cast<void>(success);
82 template <
typename... CallArgs>
84 return DoLoad()(std::forward<CallArgs>(args)...);
98 return (ptr == DummyFunction) ?
nullptr :
ptr;
113 #if ABSL_HAVE_WORKING_ATOMIC_POINTER 115 FnPtr DoLoad()
const {
return hook_.load(std::memory_order_acquire); }
121 FnPtr expected = default_fn_;
122 const bool store_succeeded = hook_.compare_exchange_strong(
123 expected, fn, std::memory_order_acq_rel, std::memory_order_acquire);
124 const bool same_value_already_stored = (expected == fn);
125 return store_succeeded || same_value_already_stored;
129 #else // !ABSL_HAVE_WORKING_ATOMIC_POINTER 131 static constexpr intptr_t kUninitialized = 0;
133 static_assert(
sizeof(intptr_t) >=
sizeof(
FnPtr),
134 "intptr_t can't contain a function pointer");
136 FnPtr DoLoad()
const {
137 const intptr_t
value = hook_.load(std::memory_order_acquire);
138 if (value == kUninitialized) {
144 bool DoStore(
FnPtr fn) {
146 const auto value =
reinterpret_cast<intptr_t
>(fn);
147 intptr_t expected = kUninitialized;
148 const bool store_succeeded = hook_.compare_exchange_strong(
149 expected, value, std::memory_order_acq_rel, std::memory_order_acquire);
150 const bool same_value_already_stored = (expected ==
value);
151 return store_succeeded || same_value_already_stored;
154 std::atomic<intptr_t> hook_;
160 #undef ABSL_HAVE_WORKING_ATOMIC_POINTER 165 #endif // ABSL_BASE_INTERNAL_ATOMIC_HOOK_H_ constexpr AtomicHook(FnPtr default_fn)
static ReturnType DummyFunction(Args...)
ReturnType(*)(Args...) FnPtr
std::atomic< FnPtr > hook_
ReturnType operator()(CallArgs &&...args) const