about summary refs log tree commit diff
path: root/absl/base
diff options
context:
space:
mode:
Diffstat (limited to 'absl/base')
-rw-r--r--absl/base/attributes.h14
-rw-r--r--absl/base/config.h19
-rw-r--r--absl/base/internal/raw_logging.cc5
-rw-r--r--absl/base/internal/raw_logging.h5
-rw-r--r--absl/base/internal/sysinfo.cc28
-rw-r--r--absl/base/internal/thread_identity.cc12
-rw-r--r--absl/base/internal/thread_identity.h9
-rw-r--r--absl/base/options.h9
8 files changed, 82 insertions, 19 deletions
diff --git a/absl/base/attributes.h b/absl/base/attributes.h
index acd1c5269829..8f77db77d23a 100644
--- a/absl/base/attributes.h
+++ b/absl/base/attributes.h
@@ -563,7 +563,19 @@
 
 // ABSL_ATTRIBUTE_PACKED
 //
-// Prevents the compiler from padding a structure to natural alignment
+// Instructs the compiler not to use natural alignment for a tagged data
+// structure, but instead to reduce its alignment to 1. This attribute can
+// either be applied to members of a structure or to a structure in its
+// entirety. Applying this attribute (judiciously) to a structure in its
+// entirety to optimize the memory footprint of very commonly-used structs is
+// fine. Do not apply this attribute to a structure in its entirety if the
+// purpose is to control the offsets of the members in the structure. Instead,
+// apply this attribute only to structure members that need it.
+//
+// When applying ABSL_ATTRIBUTE_PACKED only to specific structure members the
+// natural alignment of structure members not annotated is preserved. Aligned
+// member accesses are faster than non-aligned member accesses even if the
+// targeted microprosessor supports non-aligned accesses.
 #if ABSL_HAVE_ATTRIBUTE(packed) || (defined(__GNUC__) && !defined(__clang__))
 #define ABSL_ATTRIBUTE_PACKED __attribute__((__packed__))
 #else
diff --git a/absl/base/config.h b/absl/base/config.h
index c4e8dce403bb..eac5d268e10a 100644
--- a/absl/base/config.h
+++ b/absl/base/config.h
@@ -643,4 +643,23 @@ static_assert(ABSL_INTERNAL_INLINE_NAMESPACE_STR[0] != 'h' ||
 
 #undef ABSL_INTERNAL_HAS_KEYWORD
 
+// ABSL_DLL
+//
+// When building Abseil as a DLL, this macro expands to `__declspec(dllexport)`
+// so we can annotate symbols appropriately as being exported. When used in
+// headers consuming a DLL, this macro expands to `__declspec(dllimport)` so
+// that consumers know the symbol is defined inside the DLL. In all other cases,
+// the macro expands to nothing.
+#if defined(_MSC_VER)
+#if defined(ABSL_BUILD_DLL)
+#define ABSL_DLL __declspec(dllexport)
+#elif defined(ABSL_CONSUME_DLL)
+#define ABSL_DLL __declspec(dllimport)
+#else
+#define ABSL_DLL
+#endif
+#else
+#define ABSL_DLL
+#endif  // defined(_MSC_VER)
+
 #endif  // ABSL_BASE_CONFIG_H_
diff --git a/absl/base/internal/raw_logging.cc b/absl/base/internal/raw_logging.cc
index d79c5486658e..e36eb29abf97 100644
--- a/absl/base/internal/raw_logging.cc
+++ b/absl/base/internal/raw_logging.cc
@@ -225,8 +225,9 @@ bool RawLoggingFullySupported() {
 #endif  // !ABSL_LOW_LEVEL_WRITE_SUPPORTED
 }
 
-ABSL_CONST_INIT absl::base_internal::AtomicHook<InternalLogFunction>
-    internal_log_function(DefaultInternalLog);
+ABSL_CONST_INIT ABSL_DLL
+    absl::base_internal::AtomicHook<InternalLogFunction>
+        internal_log_function(DefaultInternalLog);
 
 void RegisterInternalLogFunction(InternalLogFunction func) {
   internal_log_function.Store(func);
diff --git a/absl/base/internal/raw_logging.h b/absl/base/internal/raw_logging.h
index cff45058b3d5..ac74f97dc3ae 100644
--- a/absl/base/internal/raw_logging.h
+++ b/absl/base/internal/raw_logging.h
@@ -22,9 +22,11 @@
 #include <string>
 
 #include "absl/base/attributes.h"
+#include "absl/base/config.h"
 #include "absl/base/internal/atomic_hook.h"
 #include "absl/base/log_severity.h"
 #include "absl/base/macros.h"
+#include "absl/base/optimization.h"
 #include "absl/base/port.h"
 
 // This is similar to LOG(severity) << format..., but
@@ -168,7 +170,8 @@ using InternalLogFunction = void (*)(absl::LogSeverity severity,
                                      const char* file, int line,
                                      const std::string& message);
 
-extern base_internal::AtomicHook<InternalLogFunction> internal_log_function;
+ABSL_DLL extern base_internal::AtomicHook<InternalLogFunction>
+    internal_log_function;
 
 void RegisterInternalLogFunction(InternalLogFunction func);
 
diff --git a/absl/base/internal/sysinfo.cc b/absl/base/internal/sysinfo.cc
index 7945322f582e..a0930e978183 100644
--- a/absl/base/internal/sysinfo.cc
+++ b/absl/base/internal/sysinfo.cc
@@ -58,10 +58,6 @@ namespace absl {
 ABSL_NAMESPACE_BEGIN
 namespace base_internal {
 
-static once_flag init_system_info_once;
-static int num_cpus = 0;
-static double nominal_cpu_frequency = 1.0;  // 0.0 might be dangerous.
-
 static int GetNumCPUs() {
 #if defined(__myriad2__)
   return 1;
@@ -265,21 +261,27 @@ static double GetNominalCPUFrequency() {
 
 #endif
 
-// InitializeSystemInfo() may be called before main() and before
-// malloc is properly initialized, therefore this must not allocate
-// memory.
-static void InitializeSystemInfo() {
-  num_cpus = GetNumCPUs();
-  nominal_cpu_frequency = GetNominalCPUFrequency();
-}
+ABSL_CONST_INIT static once_flag init_num_cpus_once;
+ABSL_CONST_INIT static int num_cpus = 0;
 
+// NumCPUs() may be called before main() and before malloc is properly
+// initialized, therefore this must not allocate memory.
 int NumCPUs() {
-  base_internal::LowLevelCallOnce(&init_system_info_once, InitializeSystemInfo);
+  base_internal::LowLevelCallOnce(
+      &init_num_cpus_once, []() { num_cpus = GetNumCPUs(); });
   return num_cpus;
 }
 
+// A default frequency of 0.0 might be dangerous if it is used in division.
+ABSL_CONST_INIT static once_flag init_nominal_cpu_frequency_once;
+ABSL_CONST_INIT static double nominal_cpu_frequency = 1.0;
+
+// NominalCPUFrequency() may be called before main() and before malloc is
+// properly initialized, therefore this must not allocate memory.
 double NominalCPUFrequency() {
-  base_internal::LowLevelCallOnce(&init_system_info_once, InitializeSystemInfo);
+  base_internal::LowLevelCallOnce(
+      &init_nominal_cpu_frequency_once,
+      []() { nominal_cpu_frequency = GetNominalCPUFrequency(); });
   return nominal_cpu_frequency;
 }
 
diff --git a/absl/base/internal/thread_identity.cc b/absl/base/internal/thread_identity.cc
index 6a28f246dbdb..d63a04ae91d5 100644
--- a/absl/base/internal/thread_identity.cc
+++ b/absl/base/internal/thread_identity.cc
@@ -113,6 +113,18 @@ void SetCurrentThreadIdentity(
 #endif
 }
 
+#if ABSL_THREAD_IDENTITY_MODE == ABSL_THREAD_IDENTITY_MODE_USE_TLS || \
+    ABSL_THREAD_IDENTITY_MODE == ABSL_THREAD_IDENTITY_MODE_USE_CPP11
+
+// Please see the comment on `CurrentThreadIdentityIfPresent` in
+// thread_identity.h. Because DLLs cannot expose thread_local variables in
+// headers, we opt for the correct-but-slower option of placing the definition
+// of this function only in a translation unit inside DLL.
+#if defined(ABSL_BUILD_DLL) || defined(ABSL_CONSUME_DLL)
+ThreadIdentity* CurrentThreadIdentityIfPresent() { return thread_identity_ptr; }
+#endif
+#endif
+
 void ClearCurrentThreadIdentity() {
 #if ABSL_THREAD_IDENTITY_MODE == ABSL_THREAD_IDENTITY_MODE_USE_TLS || \
     ABSL_THREAD_IDENTITY_MODE == ABSL_THREAD_IDENTITY_MODE_USE_CPP11
diff --git a/absl/base/internal/thread_identity.h b/absl/base/internal/thread_identity.h
index 5dfd0715dc5d..ceb109b41c6a 100644
--- a/absl/base/internal/thread_identity.h
+++ b/absl/base/internal/thread_identity.h
@@ -30,6 +30,7 @@
 #include <atomic>
 #include <cstdint>
 
+#include "absl/base/config.h"
 #include "absl/base/internal/per_thread_tls.h"
 
 namespace absl {
@@ -234,9 +235,17 @@ ABSL_CONST_INIT extern thread_local ThreadIdentity* thread_identity_ptr;
 #error Thread-local storage not detected on this platform
 #endif
 
+// thread_local variables cannot be in headers exposed by DLLs. However, it is
+// important for performance reasons in general that
+// `CurrentThreadIdentityIfPresent` be inlined. This is not possible across a
+// DLL boundary so, with DLLs, we opt to have the function not be inlined. Note
+// that `CurrentThreadIdentityIfPresent` is declared above so we can exclude
+// this entire inline definition when compiling as a DLL.
+#if !defined(ABSL_BUILD_DLL) && !defined(ABSL_CONSUME_DLL)
 inline ThreadIdentity* CurrentThreadIdentityIfPresent() {
   return thread_identity_ptr;
 }
+#endif
 
 #elif ABSL_THREAD_IDENTITY_MODE != \
     ABSL_THREAD_IDENTITY_MODE_USE_POSIX_SETSPECIFIC
diff --git a/absl/base/options.h b/absl/base/options.h
index 592b33b734d7..6868c77b103a 100644
--- a/absl/base/options.h
+++ b/absl/base/options.h
@@ -66,7 +66,13 @@
 // NOTE: the defaults within this file all assume that Abseil can select the
 // proper Abseil implementation at compile-time, which will not be sufficient
 // to guarantee ABI stability to package managers.
-//
+
+// Include a standard library header to allow configuration based on the
+// standard library in use.
+#ifdef __cplusplus
+#include <ciso646>
+#endif
+
 // -----------------------------------------------------------------------------
 // Type Compatibility Options
 // -----------------------------------------------------------------------------
@@ -158,7 +164,6 @@
 
 #define ABSL_OPTION_USE_STD_STRING_VIEW 2
 
-
 // ABSL_OPTION_USE_STD_VARIANT
 //
 // This option controls whether absl::variant is implemented as an alias to