about summary refs log tree commit diff
path: root/absl/base/internal
diff options
context:
space:
mode:
Diffstat (limited to 'absl/base/internal')
-rw-r--r--absl/base/internal/atomic_hook.h39
-rw-r--r--absl/base/internal/atomic_hook_test.cc9
-rw-r--r--absl/base/internal/atomic_hook_test_helper.cc3
-rw-r--r--absl/base/internal/raw_logging.cc12
-rw-r--r--absl/base/internal/raw_logging.h3
-rw-r--r--absl/base/internal/spinlock.cc4
6 files changed, 49 insertions, 21 deletions
diff --git a/absl/base/internal/atomic_hook.h b/absl/base/internal/atomic_hook.h
index d885bc059e2f..ae21cd7fe50a 100644
--- a/absl/base/internal/atomic_hook.h
+++ b/absl/base/internal/atomic_hook.h
@@ -20,16 +20,21 @@
 #include <cstdint>
 #include <utility>
 
+#include "absl/base/attributes.h"
 #include "absl/base/config.h"
 
-#ifdef _MSC_FULL_VER
-#define ABSL_HAVE_WORKING_ATOMIC_POINTER 0
+#if defined(_MSC_VER) && !defined(__clang__)
 #define ABSL_HAVE_WORKING_CONSTEXPR_STATIC_INIT 0
 #else
-#define ABSL_HAVE_WORKING_ATOMIC_POINTER 1
 #define ABSL_HAVE_WORKING_CONSTEXPR_STATIC_INIT 1
 #endif
 
+#if defined(_MSC_VER)
+#define ABSL_HAVE_WORKING_ATOMIC_POINTER 0
+#else
+#define ABSL_HAVE_WORKING_ATOMIC_POINTER 1
+#endif
+
 namespace absl {
 ABSL_NAMESPACE_BEGIN
 namespace base_internal {
@@ -37,6 +42,15 @@ namespace base_internal {
 template <typename T>
 class AtomicHook;
 
+// To workaround AtomicHook not being constant-initializable on some platforms,
+// prefer to annotate instances with `ABSL_INTERNAL_ATOMIC_HOOK_ATTRIBUTES`
+// instead of `ABSL_CONST_INIT`.
+#if ABSL_HAVE_WORKING_CONSTEXPR_STATIC_INIT
+#define ABSL_INTERNAL_ATOMIC_HOOK_ATTRIBUTES ABSL_CONST_INIT
+#else
+#define ABSL_INTERNAL_ATOMIC_HOOK_ATTRIBUTES
+#endif
+
 // `AtomicHook` is a helper class, templatized on a raw function pointer type,
 // for implementing Abseil customization hooks.  It is a callable object that
 // dispatches to the registered hook.  Objects of type `AtomicHook` must have
@@ -45,8 +59,11 @@ class AtomicHook;
 // A default constructed object performs a no-op (and returns a default
 // constructed object) if no hook has been registered.
 //
-// Hooks can be pre-registered via constant initialization, for example,
-// `ABSL_CONST_INIT static AtomicHook<void(*)()> my_hook(DefaultAction);`
+// Hooks can be pre-registered via constant initialization, for example:
+//
+// ABSL_INTERNAL_ATOMIC_HOOK_ATTRIBUTES static AtomicHook<void(*)()>
+//     my_hook(DefaultAction);
+//
 // and then changed at runtime via a call to `Store()`.
 //
 // Reads and writes guarantee memory_order_acquire/memory_order_release
@@ -65,11 +82,15 @@ class AtomicHook<ReturnType (*)(Args...)> {
 #if ABSL_HAVE_WORKING_ATOMIC_POINTER && ABSL_HAVE_WORKING_CONSTEXPR_STATIC_INIT
   explicit constexpr AtomicHook(FnPtr default_fn)
       : hook_(default_fn), default_fn_(default_fn) {}
+#elif ABSL_HAVE_WORKING_CONSTEXPR_STATIC_INIT
+  explicit constexpr AtomicHook(FnPtr default_fn)
+      : hook_(kUninitialized), default_fn_(default_fn) {}
 #else
-  // On MSVC, this function sometimes executes after dynamic initialization =(.
-  // If a non-zero `hook_` has been installed by a dynamic initializer, we want
-  // to preserve it.  If not, `hook_` will be zero initialized and we have no
-  // need to set it to `kUninitialized`.
+  // As of January 2020, on all known versions of MSVC this constructor runs in
+  // the global constructor sequence.  If `Store()` is called by a dynamic
+  // initializer, we want to preserve the value, even if this constructor runs
+  // after the call to `Store()`.  If not, `hook_` will be
+  // zero-initialized by the linker and we have no need to set it.
   // https://developercommunity.visualstudio.com/content/problem/336946/class-with-constexpr-constructor-not-using-static.html
   explicit constexpr AtomicHook(FnPtr default_fn)
       : /* hook_(deliberately omitted), */ default_fn_(default_fn) {
diff --git a/absl/base/internal/atomic_hook_test.cc b/absl/base/internal/atomic_hook_test.cc
index 794072ee2fc2..e577a8fd930b 100644
--- a/absl/base/internal/atomic_hook_test.cc
+++ b/absl/base/internal/atomic_hook_test.cc
@@ -27,7 +27,9 @@ int value = 0;
 void TestHook(int x) { value = x; }
 
 TEST(AtomicHookTest, NoDefaultFunction) {
-  ABSL_CONST_INIT static absl::base_internal::AtomicHook<void(*)(int)> hook;
+  ABSL_INTERNAL_ATOMIC_HOOK_ATTRIBUTES static absl::base_internal::AtomicHook<
+      void (*)(int)>
+      hook;
   value = 0;
 
   // Test the default DummyFunction.
@@ -53,8 +55,9 @@ TEST(AtomicHookTest, NoDefaultFunction) {
 
 TEST(AtomicHookTest, WithDefaultFunction) {
   // Set the default value to TestHook at compile-time.
-  ABSL_CONST_INIT static absl::base_internal::AtomicHook<void (*)(int)> hook(
-      TestHook);
+  ABSL_INTERNAL_ATOMIC_HOOK_ATTRIBUTES static absl::base_internal::AtomicHook<
+      void (*)(int)>
+      hook(TestHook);
   value = 0;
 
   // Test the default value is TestHook.
diff --git a/absl/base/internal/atomic_hook_test_helper.cc b/absl/base/internal/atomic_hook_test_helper.cc
index f95d962b343f..537d47cd2d2f 100644
--- a/absl/base/internal/atomic_hook_test_helper.cc
+++ b/absl/base/internal/atomic_hook_test_helper.cc
@@ -21,7 +21,8 @@ namespace absl {
 ABSL_NAMESPACE_BEGIN
 namespace atomic_hook_internal {
 
-ABSL_CONST_INIT absl::base_internal::AtomicHook<VoidF> func(DefaultFunc);
+ABSL_INTERNAL_ATOMIC_HOOK_ATTRIBUTES absl::base_internal::AtomicHook<VoidF>
+    func(DefaultFunc);
 ABSL_CONST_INIT int default_func_calls = 0;
 void DefaultFunc() { default_func_calls++; }
 void RegisterFunc(VoidF f) { func.Store(f); }
diff --git a/absl/base/internal/raw_logging.cc b/absl/base/internal/raw_logging.cc
index e36eb29abf97..40cea5506172 100644
--- a/absl/base/internal/raw_logging.cc
+++ b/absl/base/internal/raw_logging.cc
@@ -71,10 +71,12 @@
 // Explicitly #error out when not ABSL_LOW_LEVEL_WRITE_SUPPORTED, except for a
 // whitelisted set of platforms for which we expect not to be able to raw log.
 
-ABSL_CONST_INIT static absl::base_internal::AtomicHook<
-    absl::raw_logging_internal::LogPrefixHook> log_prefix_hook;
-ABSL_CONST_INIT static absl::base_internal::AtomicHook<
-    absl::raw_logging_internal::AbortHook> abort_hook;
+ABSL_INTERNAL_ATOMIC_HOOK_ATTRIBUTES static absl::base_internal::AtomicHook<
+    absl::raw_logging_internal::LogPrefixHook>
+    log_prefix_hook;
+ABSL_INTERNAL_ATOMIC_HOOK_ATTRIBUTES static absl::base_internal::AtomicHook<
+    absl::raw_logging_internal::AbortHook>
+    abort_hook;
 
 #ifdef ABSL_LOW_LEVEL_WRITE_SUPPORTED
 static const char kTruncated[] = " ... (message truncated)\n";
@@ -225,7 +227,7 @@ bool RawLoggingFullySupported() {
 #endif  // !ABSL_LOW_LEVEL_WRITE_SUPPORTED
 }
 
-ABSL_CONST_INIT ABSL_DLL
+ABSL_DLL ABSL_INTERNAL_ATOMIC_HOOK_ATTRIBUTES
     absl::base_internal::AtomicHook<InternalLogFunction>
         internal_log_function(DefaultInternalLog);
 
diff --git a/absl/base/internal/raw_logging.h b/absl/base/internal/raw_logging.h
index ac74f97dc3ae..418d6c856feb 100644
--- a/absl/base/internal/raw_logging.h
+++ b/absl/base/internal/raw_logging.h
@@ -170,7 +170,8 @@ using InternalLogFunction = void (*)(absl::LogSeverity severity,
                                      const char* file, int line,
                                      const std::string& message);
 
-ABSL_DLL extern base_internal::AtomicHook<InternalLogFunction>
+ABSL_DLL ABSL_INTERNAL_ATOMIC_HOOK_ATTRIBUTES extern base_internal::AtomicHook<
+    InternalLogFunction>
     internal_log_function;
 
 void RegisterInternalLogFunction(InternalLogFunction func);
diff --git a/absl/base/internal/spinlock.cc b/absl/base/internal/spinlock.cc
index 8dd8dab9e20c..830d4729af3b 100644
--- a/absl/base/internal/spinlock.cc
+++ b/absl/base/internal/spinlock.cc
@@ -57,8 +57,8 @@ namespace absl {
 ABSL_NAMESPACE_BEGIN
 namespace base_internal {
 
-ABSL_CONST_INIT static base_internal::AtomicHook<void (*)(const void *lock,
-                                                          int64_t wait_cycles)>
+ABSL_INTERNAL_ATOMIC_HOOK_ATTRIBUTES static base_internal::AtomicHook<void (*)(
+    const void *lock, int64_t wait_cycles)>
     submit_profile_data;
 
 void RegisterSpinLockProfiler(void (*fn)(const void *contendedlock,