about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--absl/base/config.h22
-rw-r--r--absl/flags/flag.h21
-rw-r--r--absl/flags/internal/registry.cc80
-rw-r--r--absl/flags/internal/registry.h3
-rw-r--r--absl/random/internal/salted_seed_seq.h63
5 files changed, 67 insertions, 122 deletions
diff --git a/absl/base/config.h b/absl/base/config.h
index 406a931f4858..692738e31e25 100644
--- a/absl/base/config.h
+++ b/absl/base/config.h
@@ -370,16 +370,20 @@
 #error "absl endian detection needs to be set up for your compiler"
 #endif
 
-// MacOS 10.13 doesn't let you use <any>, <optional>, or <variant> even though
-// the headers exist and are publicly noted to work.  See
+// MacOS 10.13 and iOS 10.11 don't let you use <any>, <optional>, or <variant>
+// even though the headers exist and are publicly noted to work.  See
 // https://github.com/abseil/abseil-cpp/issues/207 and
 // https://developer.apple.com/documentation/xcode_release_notes/xcode_10_release_notes
+// libc++ spells out the availability requirements in the file
+// llvm-project/libcxx/include/__config.
 #if defined(__APPLE__) && defined(_LIBCPP_VERSION) && \
-    defined(__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__) && \
-    __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ < 101400
-#define ABSL_INTERNAL_MACOS_CXX17_TYPES_UNAVAILABLE 1
+  ((defined(__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__) && \
+   __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ < 101400) || \
+  (defined(__ENVIRONMENT_IPHONE_OS_VERSION_MIN_REQUIRED__) && \
+   __ENVIRONMENT_IPHONE_OS_VERSION_MIN_REQUIRED__ < 101200))
+#define ABSL_INTERNAL_APPLE_CXX17_TYPES_UNAVAILABLE 1
 #else
-#define ABSL_INTERNAL_MACOS_CXX17_TYPES_UNAVAILABLE 0
+#define ABSL_INTERNAL_APPLE_CXX17_TYPES_UNAVAILABLE 0
 #endif
 
 // ABSL_HAVE_STD_ANY
@@ -391,7 +395,7 @@
 
 #ifdef __has_include
 #if __has_include(<any>) && __cplusplus >= 201703L && \
-    !ABSL_INTERNAL_MACOS_CXX17_TYPES_UNAVAILABLE
+    !ABSL_INTERNAL_APPLE_CXX17_TYPES_UNAVAILABLE
 #define ABSL_HAVE_STD_ANY 1
 #endif
 #endif
@@ -405,7 +409,7 @@
 
 #ifdef __has_include
 #if __has_include(<optional>) && __cplusplus >= 201703L && \
-    !ABSL_INTERNAL_MACOS_CXX17_TYPES_UNAVAILABLE
+    !ABSL_INTERNAL_APPLE_CXX17_TYPES_UNAVAILABLE
 #define ABSL_HAVE_STD_OPTIONAL 1
 #endif
 #endif
@@ -419,7 +423,7 @@
 
 #ifdef __has_include
 #if __has_include(<variant>) && __cplusplus >= 201703L && \
-    !ABSL_INTERNAL_MACOS_CXX17_TYPES_UNAVAILABLE
+    !ABSL_INTERNAL_APPLE_CXX17_TYPES_UNAVAILABLE
 #define ABSL_HAVE_STD_VARIANT 1
 #endif
 #endif
diff --git a/absl/flags/flag.h b/absl/flags/flag.h
index c70023aba8c7..6c9f48765cfa 100644
--- a/absl/flags/flag.h
+++ b/absl/flags/flag.h
@@ -216,17 +216,16 @@ void SetFlag(absl::Flag<T>* flag, const V& v) {
 // Note: Name of registrar object is not arbitrary. It is used to "grab"
 // global name for FLAGS_no<flag_name> symbol, thus preventing the possibility
 // of defining two flags with names foo and nofoo.
-#define ABSL_FLAG_IMPL(Type, name, default_value, help)              \
-  namespace absl {}                                                  \
-  ABSL_FLAG_IMPL_DECLARE_DEF_VAL_WRAPPER(name, Type, default_value)  \
-  ABSL_FLAG_IMPL_DECLARE_HELP_WRAPPER(name, help)                    \
-  absl::Flag<Type> FLAGS_##name(                                     \
-      ABSL_FLAG_IMPL_FLAGNAME(#name),                                \
-      &AbslFlagsWrapHelp##name,                                      \
-      ABSL_FLAG_IMPL_FILENAME(),                                     \
-      &absl::flags_internal::FlagMarshallingOps<Type>,               \
-      &AbslFlagsInitFlag##name);                                     \
-  extern bool FLAGS_no##name;                                        \
+#define ABSL_FLAG_IMPL(Type, name, default_value, help)             \
+  namespace absl {}                                                 \
+  ABSL_FLAG_IMPL_DECLARE_DEF_VAL_WRAPPER(name, Type, default_value) \
+  ABSL_FLAG_IMPL_DECLARE_HELP_WRAPPER(name, help)                   \
+  ABSL_CONST_INIT absl::Flag<Type> FLAGS_##name(                    \
+      ABSL_FLAG_IMPL_FLAGNAME(#name), &AbslFlagsWrapHelp##name,     \
+      ABSL_FLAG_IMPL_FILENAME(),                                    \
+      &absl::flags_internal::FlagMarshallingOps<Type>,              \
+      &AbslFlagsInitFlag##name);                                    \
+  extern bool FLAGS_no##name;                                       \
   bool FLAGS_no##name = ABSL_FLAG_IMPL_REGISTRAR(Type, FLAGS_##name)
 
 // ABSL_RETIRED_FLAG
diff --git a/absl/flags/internal/registry.cc b/absl/flags/internal/registry.cc
index f37871c9d40f..4e5d1106b93c 100644
--- a/absl/flags/internal/registry.cc
+++ b/absl/flags/internal/registry.cc
@@ -54,53 +54,6 @@ void DestroyFlag(CommandLineFlag* flag) NO_THREAD_SAFETY_ANALYSIS {
 //    the function will acquire it itself if needed.
 // --------------------------------------------------------------------
 
-// A map from flag pointer to CommandLineFlag*. Used when registering
-// validators.
-class FlagPtrMap {
- public:
-  void Register(CommandLineFlag* flag) {
-    auto& vec = buckets_[BucketForFlag(flag->cur)];
-    if (vec.size() == vec.capacity()) {
-      // Bypass default 2x growth factor with 1.25 so we have fuller vectors.
-      // This saves 4% memory compared to default growth.
-      vec.reserve(vec.size() * 1.25 + 0.5);
-    }
-    vec.push_back(flag);
-  }
-
-  CommandLineFlag* FindByPtr(const void* flag_ptr) {
-    const auto& flag_vector = buckets_[BucketForFlag(flag_ptr)];
-    for (CommandLineFlag* entry : flag_vector) {
-      if (entry->cur == flag_ptr) {
-        return entry;
-      }
-    }
-    return nullptr;
-  }
-
- private:
-  // Instead of std::map, we use a custom hash table where each bucket stores
-  // flags in a vector. This reduces memory usage 40% of the memory that would
-  // have been used by std::map.
-  //
-  // kNumBuckets was picked as a large enough prime. As of writing this code, a
-  // typical large binary has ~8k (old-style) flags, and this would gives
-  // buckets with roughly 50 elements each.
-  //
-  // Note that reads to this hash table are rare: exactly as many as we have
-  // flags with validators. As of writing, a typical binary only registers 52
-  // validated flags.
-  static constexpr size_t kNumBuckets = 163;
-  std::vector<CommandLineFlag*> buckets_[kNumBuckets];
-
-  static int BucketForFlag(const void* ptr) {
-    // Modulo a prime is good enough here. On a real program, bucket size stddev
-    // after registering 8k flags is ~5 (mean size at 51).
-    return reinterpret_cast<uintptr_t>(ptr) % kNumBuckets;
-  }
-};
-constexpr size_t FlagPtrMap::kNumBuckets;
-
 class FlagRegistry {
  public:
   FlagRegistry() = default;
@@ -111,9 +64,7 @@ class FlagRegistry {
   }
 
   // Store a flag in this registry.  Takes ownership of *flag.
-  // If ptr is non-null, the flag can later be found by calling
-  // FindFlagViaPtrLocked(ptr).
-  void RegisterFlag(CommandLineFlag* flag, const void* ptr);
+  void RegisterFlag(CommandLineFlag* flag);
 
   void Lock() EXCLUSIVE_LOCK_FUNCTION(lock_) { lock_.Lock(); }
   void Unlock() UNLOCK_FUNCTION(lock_) { lock_.Unlock(); }
@@ -126,9 +77,6 @@ class FlagRegistry {
   // found or not retired.  Does not emit a warning.
   CommandLineFlag* FindRetiredFlagLocked(absl::string_view name);
 
-  // Returns the flag object whose current-value is stored at flag_ptr.
-  CommandLineFlag* FindFlagViaPtrLocked(const void* flag_ptr);
-
   static FlagRegistry* GlobalRegistry();  // returns a singleton registry
 
  private:
@@ -142,8 +90,6 @@ class FlagRegistry {
   using FlagConstIterator = FlagMap::const_iterator;
   FlagMap flags_;
 
-  FlagPtrMap flag_ptr_map_;
-
   absl::Mutex lock_;
 
   // Disallow
@@ -169,7 +115,7 @@ class FlagRegistryLock {
 
 }  // namespace
 
-void FlagRegistry::RegisterFlag(CommandLineFlag* flag, const void* ptr) {
+void FlagRegistry::RegisterFlag(CommandLineFlag* flag) {
   FlagRegistryLock registry_lock(this);
   std::pair<FlagIterator, bool> ins =
       flags_.insert(FlagMap::value_type(flag->Name(), flag));
@@ -217,11 +163,6 @@ void FlagRegistry::RegisterFlag(CommandLineFlag* flag, const void* ptr) {
     // All cases above are fatal, except for the retired flags.
     std::exit(1);
   }
-
-  if (ptr != nullptr) {
-    // This must be the first time we're seeing this flag.
-    flag_ptr_map_.Register(flag);
-  }
 }
 
 CommandLineFlag* FlagRegistry::FindFlagLocked(absl::string_view name) {
@@ -247,10 +188,6 @@ CommandLineFlag* FlagRegistry::FindRetiredFlagLocked(absl::string_view name) {
   return i->second;
 }
 
-CommandLineFlag* FlagRegistry::FindFlagViaPtrLocked(const void* flag_ptr) {
-  return flag_ptr_map_.FindByPtr(flag_ptr);
-}
-
 // --------------------------------------------------------------------
 // FlagSaver
 // FlagSaverImpl
@@ -430,13 +367,6 @@ CommandLineFlag* FindCommandLineFlag(absl::string_view name) {
   return registry->FindFlagLocked(name);
 }
 
-CommandLineFlag* FindCommandLineV1Flag(const void* flag_ptr) {
-  FlagRegistry* const registry = FlagRegistry::GlobalRegistry();
-  FlagRegistryLock frl(registry);
-
-  return registry->FindFlagViaPtrLocked(flag_ptr);
-}
-
 CommandLineFlag* FindRetiredFlag(absl::string_view name) {
   FlagRegistry* const registry = FlagRegistry::GlobalRegistry();
   FlagRegistryLock frl(registry);
@@ -477,8 +407,8 @@ void GetAllFlags(std::vector<CommandLineFlagInfo>* OUTPUT) {
 
 // --------------------------------------------------------------------
 
-bool RegisterCommandLineFlag(CommandLineFlag* flag, const void* ptr) {
-  FlagRegistry::GlobalRegistry()->RegisterFlag(flag, ptr);
+bool RegisterCommandLineFlag(CommandLineFlag* flag) {
+  FlagRegistry::GlobalRegistry()->RegisterFlag(flag);
   return true;
 }
 
@@ -492,7 +422,7 @@ bool Retire(FlagOpFn ops, FlagMarshallingOpFn marshalling_ops,
       /*filename_arg=*/"RETIRED", ops, marshalling_ops,
       /*initial_value_gen=*/nullptr,
       /*retired_arg=*/true, nullptr, nullptr);
-  FlagRegistry::GlobalRegistry()->RegisterFlag(flag, nullptr);
+  FlagRegistry::GlobalRegistry()->RegisterFlag(flag);
   return true;
 }
 
diff --git a/absl/flags/internal/registry.h b/absl/flags/internal/registry.h
index bd141e1e23d2..27566fbf4ab7 100644
--- a/absl/flags/internal/registry.h
+++ b/absl/flags/internal/registry.h
@@ -57,7 +57,6 @@ void FillCommandLineFlagInfo(CommandLineFlag* flag,
 //-----------------------------------------------------------------------------
 
 CommandLineFlag* FindCommandLineFlag(absl::string_view name);
-CommandLineFlag* FindCommandLineV1Flag(const void* flag_ptr);
 CommandLineFlag* FindRetiredFlag(absl::string_view name);
 
 // Executes specified visitor for each non-retired flag in the registry.
@@ -74,7 +73,7 @@ void GetAllFlags(std::vector<CommandLineFlagInfo>* OUTPUT);
 
 //-----------------------------------------------------------------------------
 
-bool RegisterCommandLineFlag(CommandLineFlag*, const void* ptr = nullptr);
+bool RegisterCommandLineFlag(CommandLineFlag*);
 
 //-----------------------------------------------------------------------------
 // Retired registrations:
diff --git a/absl/random/internal/salted_seed_seq.h b/absl/random/internal/salted_seed_seq.h
index 3d16cf97d3d7..e160f79e1f5b 100644
--- a/absl/random/internal/salted_seed_seq.h
+++ b/absl/random/internal/salted_seed_seq.h
@@ -64,10 +64,15 @@ class SaltedSeedSeq {
 
   template <typename RandomAccessIterator>
   void generate(RandomAccessIterator begin, RandomAccessIterator end) {
+    // The common case is that generate is called with ContiguousIterators
+    // to uint arrays. Such contiguous memory regions may be optimized,
+    // which we detect here.
+    using tag = absl::conditional_t<
+        (std::is_pointer<RandomAccessIterator>::value &&
+         std::is_same<absl::decay_t<decltype(*begin)>, uint32_t>::value),
+        ContiguousAndUint32Tag, DefaultTag>;
     if (begin != end) {
-      generate_impl(
-          std::integral_constant<bool, sizeof(*begin) == sizeof(uint32_t)>{},
-          begin, end);
+      generate_impl(begin, end, tag{});
     }
   }
 
@@ -79,19 +84,12 @@ class SaltedSeedSeq {
   size_t size() const { return seq_->size(); }
 
  private:
-  // The common case for generate is that it is called with iterators over a
-  // 32-bit value buffer. These can be reinterpreted to a uint32_t and we can
-  // operate on them as such.
-  template <typename RandomAccessIterator>
-  void generate_impl(std::integral_constant<bool, true> /*is_32bit*/,
-                     RandomAccessIterator begin, RandomAccessIterator end) {
-    seq_->generate(begin, end);
-    const uint32_t salt = absl::random_internal::GetSaltMaterial().value_or(0);
-    auto buffer = absl::MakeSpan(begin, end);
-    MixIntoSeedMaterial(
-        absl::MakeConstSpan(&salt, 1),
-        absl::MakeSpan(reinterpret_cast<uint32_t*>(buffer.data()),
-                       buffer.size()));
+  struct ContiguousAndUint32Tag {};
+  struct DefaultTag {};
+
+  // Generate which requires the iterators are contiguous pointers to uint32_t.
+  void generate_impl(uint32_t* begin, uint32_t* end, ContiguousAndUint32Tag) {
+    generate_contiguous(absl::MakeSpan(begin, end));
   }
 
   // The uncommon case for generate is that it is called with iterators over
@@ -99,17 +97,32 @@ class SaltedSeedSeq {
   // case we allocate a temporary 32-bit buffer and then copy-assign back
   // to the initial inputs.
   template <typename RandomAccessIterator>
-  void generate_impl(std::integral_constant<bool, false> /*is_32bit*/,
-                     RandomAccessIterator begin, RandomAccessIterator end) {
-    // Allocate a temporary buffer, seed, and then copy.
-    absl::InlinedVector<uint32_t, 8> data(std::distance(begin, end), 0);
-    generate_impl(std::integral_constant<bool, true>{}, data.begin(),
-                  data.end());
-    std::copy(data.begin(), data.end(), begin);
+  void generate_impl(RandomAccessIterator begin, RandomAccessIterator end,
+                     DefaultTag) {
+    return generate_and_copy(std::distance(begin, end), begin);
+  }
+
+  // Fills the initial seed buffer the underlying SSeq::generate() call,
+  // mixing in the salt material.
+  void generate_contiguous(absl::Span<uint32_t> buffer) {
+    seq_->generate(buffer.begin(), buffer.end());
+    const uint32_t salt = absl::random_internal::GetSaltMaterial().value_or(0);
+    MixIntoSeedMaterial(absl::MakeConstSpan(&salt, 1), buffer);
+  }
+
+  // Allocates a seed buffer of `n` elements, generates the seed, then
+  // copies the result into the `out` iterator.
+  template <typename Iterator>
+  void generate_and_copy(size_t n, Iterator out) {
+    // Allocate a temporary buffer, generate, and then copy.
+    absl::InlinedVector<uint32_t, 8> data(n, 0);
+    generate_contiguous(absl::MakeSpan(data.data(), data.size()));
+    std::copy(data.begin(), data.end(), out);
   }
 
-  // Because [rand.req.seedseq] is not copy-constructible, copy-assignable nor
-  // movable so we wrap it with unique pointer to be able to move SaltedSeedSeq.
+  // Because [rand.req.seedseq] is not required to be copy-constructible,
+  // copy-assignable nor movable, we wrap it with unique pointer to be able
+  // to move SaltedSeedSeq.
   std::unique_ptr<SSeq> seq_;
 };