Export of internal Abseil changes
-- 00f5301405423005d9129935c05f20155536cc1a by CJ Johnson <johnsoncj@google.com>: Removes usage of std::aligned_storage from Abseil implementation details PiperOrigin-RevId: 296492301 -- fc11d15f91764612fba080669d2381dc181df52b by Abseil Team <absl-team@google.com>: Fix absl::bind_front documentation. PiperOrigin-RevId: 296482945 -- 0164c595c129c46bf21ae74eba5399a1da5f140b by Gennadiy Rozental <rogeeff@google.com>: Automated g4 rollback of changelist 296320700. PiperOrigin-RevId: 296439968 -- 1eb295700758ca0894d872b2de7c675b4ad679af by Abseil Team <absl-team@google.com>: Removes duplicate comments. PiperOrigin-RevId: 296433214 -- c30c01caae02d2fa4ef783d988de6bebb9757c39 by Derek Mauro <dmauro@google.com>: Merge GitHub #621: Add RISCV support to GetProgramCounter() Fixes #621 PiperOrigin-RevId: 296351174 -- 95d4498167596fd7543e025bdfe9a8da9e2ca3c8 by Abseil Team <absl-team@google.com>: Automated g4 rollback of changelist 296320700. PiperOrigin-RevId: 296348701 -- b193f0543e0cec54dddb2ed51f45dc489c8d06d5 by Gennadiy Rozental <rogeeff@google.com>: Change TryParse interface to return managed value. In addition introduce companion StoreValue routine which consumes pointer to source value and stores the value inside of FlagImpl. In a follow up CL we will change StoreValue implementation to behave differently depending on "value storage kind". We also rename default_src_ to default_value_. PiperOrigin-RevId: 296320700 -- 57e942b485d12912a0a8d0d0b35fa2a62847020f by Derek Mauro <dmauro@google.com>: Merge GitHub #622 * Add missing #ifdef conditionals for ABSL_HAVE_VDSO_SUPPORT PiperOrigin-RevId: 296272830 GitOrigin-RevId: 00f5301405423005d9129935c05f20155536cc1a Change-Id: I1b05eeaf1280f95fb0a2c5f3654995a87c792893
This commit is contained in:
		
							parent
							
								
									2a5633fc07
								
							
						
					
					
						commit
						b69c7d880c
					
				
					 16 changed files with 131 additions and 135 deletions
				
			
		|  | @ -328,17 +328,15 @@ TEST(ThrowingValueTest, NonThrowingDelete) { | ||||||
|   UnsetCountdown(); |   UnsetCountdown(); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| using Storage = |  | ||||||
|     absl::aligned_storage_t<sizeof(ThrowingValue<>), alignof(ThrowingValue<>)>; |  | ||||||
| 
 |  | ||||||
| TEST(ThrowingValueTest, NonThrowingPlacementDelete) { | TEST(ThrowingValueTest, NonThrowingPlacementDelete) { | ||||||
|   constexpr int kArrayLen = 2; |   constexpr int kArrayLen = 2; | ||||||
|   // We intentionally create extra space to store the tag allocated by placement
 |   // We intentionally create extra space to store the tag allocated by placement
 | ||||||
|   // new[].
 |   // new[].
 | ||||||
|   constexpr int kStorageLen = 4; |   constexpr int kStorageLen = 4; | ||||||
| 
 | 
 | ||||||
|   Storage buf; |   alignas(ThrowingValue<>) unsigned char buf[sizeof(ThrowingValue<>)]; | ||||||
|   Storage array_buf[kStorageLen]; |   alignas(ThrowingValue<>) unsigned char | ||||||
|  |       array_buf[sizeof(ThrowingValue<>[kStorageLen])]; | ||||||
|   auto* placed = new (&buf) ThrowingValue<>(1); |   auto* placed = new (&buf) ThrowingValue<>(1); | ||||||
|   auto placed_array = new (&array_buf) ThrowingValue<>[kArrayLen]; |   auto placed_array = new (&array_buf) ThrowingValue<>[kArrayLen]; | ||||||
| 
 | 
 | ||||||
|  | @ -902,12 +900,12 @@ TEST(ConstructorTrackerTest, CreatedAfter) { | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| TEST(ConstructorTrackerTest, NotDestroyedAfter) { | TEST(ConstructorTrackerTest, NotDestroyedAfter) { | ||||||
|   absl::aligned_storage_t<sizeof(Tracked), alignof(Tracked)> storage; |   alignas(Tracked) unsigned char storage[sizeof(Tracked)]; | ||||||
|   EXPECT_NONFATAL_FAILURE( |   EXPECT_NONFATAL_FAILURE( | ||||||
|       { |       { | ||||||
|         exceptions_internal::ConstructorTracker ct( |         exceptions_internal::ConstructorTracker ct( | ||||||
|             exceptions_internal::countdown); |             exceptions_internal::countdown); | ||||||
|         new (&storage) Tracked; |         new (&storage) Tracked(); | ||||||
|       }, |       }, | ||||||
|       "not destroyed"); |       "not destroyed"); | ||||||
| } | } | ||||||
|  | @ -924,11 +922,11 @@ TEST(ConstructorTrackerTest, DestroyedTwice) { | ||||||
| 
 | 
 | ||||||
| TEST(ConstructorTrackerTest, ConstructedTwice) { | TEST(ConstructorTrackerTest, ConstructedTwice) { | ||||||
|   exceptions_internal::ConstructorTracker ct(exceptions_internal::countdown); |   exceptions_internal::ConstructorTracker ct(exceptions_internal::countdown); | ||||||
|   absl::aligned_storage_t<sizeof(Tracked), alignof(Tracked)> storage; |   alignas(Tracked) unsigned char storage[sizeof(Tracked)]; | ||||||
|   EXPECT_NONFATAL_FAILURE( |   EXPECT_NONFATAL_FAILURE( | ||||||
|       { |       { | ||||||
|         new (&storage) Tracked; |         new (&storage) Tracked(); | ||||||
|         new (&storage) Tracked; |         new (&storage) Tracked(); | ||||||
|         reinterpret_cast<Tracked*>(&storage)->~Tracked(); |         reinterpret_cast<Tracked*>(&storage)->~Tracked(); | ||||||
|       }, |       }, | ||||||
|       "re-constructed"); |       "re-constructed"); | ||||||
|  |  | ||||||
|  | @ -220,16 +220,17 @@ struct LowLevelAlloc::Arena { | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| namespace { | namespace { | ||||||
| using ArenaStorage = std::aligned_storage<sizeof(LowLevelAlloc::Arena), |  | ||||||
|                                           alignof(LowLevelAlloc::Arena)>::type; |  | ||||||
| 
 |  | ||||||
| // Static storage space for the lazily-constructed, default global arena
 | // Static storage space for the lazily-constructed, default global arena
 | ||||||
| // instances.  We require this space because the whole point of LowLevelAlloc
 | // instances.  We require this space because the whole point of LowLevelAlloc
 | ||||||
| // is to avoid relying on malloc/new.
 | // is to avoid relying on malloc/new.
 | ||||||
| ArenaStorage default_arena_storage; | alignas(LowLevelAlloc::Arena) unsigned char default_arena_storage[sizeof( | ||||||
| ArenaStorage unhooked_arena_storage; |     LowLevelAlloc::Arena)]; | ||||||
|  | alignas(LowLevelAlloc::Arena) unsigned char unhooked_arena_storage[sizeof( | ||||||
|  |     LowLevelAlloc::Arena)]; | ||||||
| #ifndef ABSL_LOW_LEVEL_ALLOC_ASYNC_SIGNAL_SAFE_MISSING | #ifndef ABSL_LOW_LEVEL_ALLOC_ASYNC_SIGNAL_SAFE_MISSING | ||||||
| ArenaStorage unhooked_async_sig_safe_arena_storage; | alignas( | ||||||
|  |     LowLevelAlloc::Arena) unsigned char unhooked_async_sig_safe_arena_storage | ||||||
|  |     [sizeof(LowLevelAlloc::Arena)]; | ||||||
| #endif | #endif | ||||||
| 
 | 
 | ||||||
| // We must use LowLevelCallOnce here to construct the global arenas, rather than
 | // We must use LowLevelCallOnce here to construct the global arenas, rather than
 | ||||||
|  |  | ||||||
|  | @ -123,14 +123,6 @@ | ||||||
| // compiler flags passed by the end user.  For more info, see
 | // compiler flags passed by the end user.  For more info, see
 | ||||||
| // https://abseil.io/about/design/dropin-types.
 | // https://abseil.io/about/design/dropin-types.
 | ||||||
| 
 | 
 | ||||||
| // A value of 2 means to detect the C++ version being used to compile Abseil,
 |  | ||||||
| // and use an alias only if a working std::optional is available.  This option
 |  | ||||||
| // should not be used when your program is not built from source -- for example,
 |  | ||||||
| // if you are distributing Abseil in a binary package manager -- since in mode
 |  | ||||||
| // 2, absl::optional will name a different template class, with a different
 |  | ||||||
| // mangled name and binary layout, depending on the compiler flags passed by the
 |  | ||||||
| // end user.
 |  | ||||||
| //
 |  | ||||||
| // User code should not inspect this macro.  To check in the preprocessor if
 | // User code should not inspect this macro.  To check in the preprocessor if
 | ||||||
| // absl::optional is a typedef of std::optional, use the feature macro
 | // absl::optional is a typedef of std::optional, use the feature macro
 | ||||||
| // ABSL_USES_STD_OPTIONAL.
 | // ABSL_USES_STD_OPTIONAL.
 | ||||||
|  |  | ||||||
|  | @ -604,19 +604,16 @@ TEST(FixedArrayTest, Fill) { | ||||||
|   empty.fill(fill_val); |   empty.fill(fill_val); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| // TODO(johnsoncj): Investigate InlinedStorage default initialization in GCC 4.x
 |  | ||||||
| #ifndef __GNUC__ | #ifndef __GNUC__ | ||||||
| TEST(FixedArrayTest, DefaultCtorDoesNotValueInit) { | TEST(FixedArrayTest, DefaultCtorDoesNotValueInit) { | ||||||
|   using T = char; |   using T = char; | ||||||
|   constexpr auto capacity = 10; |   constexpr auto capacity = 10; | ||||||
|   using FixedArrType = absl::FixedArray<T, capacity>; |   using FixedArrType = absl::FixedArray<T, capacity>; | ||||||
|   using FixedArrBuffType = |  | ||||||
|       absl::aligned_storage_t<sizeof(FixedArrType), alignof(FixedArrType)>; |  | ||||||
|   constexpr auto scrubbed_bits = 0x95; |   constexpr auto scrubbed_bits = 0x95; | ||||||
|   constexpr auto length = capacity / 2; |   constexpr auto length = capacity / 2; | ||||||
| 
 | 
 | ||||||
|   FixedArrBuffType buff; |   alignas(FixedArrType) unsigned char buff[sizeof(FixedArrType)]; | ||||||
|   std::memset(std::addressof(buff), scrubbed_bits, sizeof(FixedArrBuffType)); |   std::memset(std::addressof(buff), scrubbed_bits, sizeof(FixedArrType)); | ||||||
| 
 | 
 | ||||||
|   FixedArrType* arr = |   FixedArrType* arr = | ||||||
|       ::new (static_cast<void*>(std::addressof(buff))) FixedArrType(length); |       ::new (static_cast<void*>(std::addressof(buff))) FixedArrType(length); | ||||||
|  |  | ||||||
|  | @ -56,7 +56,7 @@ class node_handle_base { | ||||||
|  public: |  public: | ||||||
|   using allocator_type = Alloc; |   using allocator_type = Alloc; | ||||||
| 
 | 
 | ||||||
|   constexpr node_handle_base() {} |   constexpr node_handle_base() = default; | ||||||
|   node_handle_base(node_handle_base&& other) noexcept { |   node_handle_base(node_handle_base&& other) noexcept { | ||||||
|     *this = std::move(other); |     *this = std::move(other); | ||||||
|   } |   } | ||||||
|  | @ -109,9 +109,8 @@ class node_handle_base { | ||||||
|   allocator_type* alloc() { return std::addressof(*alloc_); } |   allocator_type* alloc() { return std::addressof(*alloc_); } | ||||||
| 
 | 
 | ||||||
|  private: |  private: | ||||||
|   absl::optional<allocator_type> alloc_; |   absl::optional<allocator_type> alloc_ = {}; | ||||||
|   mutable absl::aligned_storage_t<sizeof(slot_type), alignof(slot_type)> |   alignas(slot_type) mutable unsigned char slot_space_[sizeof(slot_type)] = {}; | ||||||
|       slot_space_; |  | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| // For sets.
 | // For sets.
 | ||||||
|  |  | ||||||
|  | @ -1067,8 +1067,7 @@ class raw_hash_set { | ||||||
|   template <class... Args, typename std::enable_if< |   template <class... Args, typename std::enable_if< | ||||||
|                                !IsDecomposable<Args...>::value, int>::type = 0> |                                !IsDecomposable<Args...>::value, int>::type = 0> | ||||||
|   std::pair<iterator, bool> emplace(Args&&... args) { |   std::pair<iterator, bool> emplace(Args&&... args) { | ||||||
|     typename std::aligned_storage<sizeof(slot_type), alignof(slot_type)>::type |     alignas(slot_type) unsigned char raw[sizeof(slot_type)]; | ||||||
|         raw; |  | ||||||
|     slot_type* slot = reinterpret_cast<slot_type*>(&raw); |     slot_type* slot = reinterpret_cast<slot_type*>(&raw); | ||||||
| 
 | 
 | ||||||
|     PolicyTraits::construct(&alloc_ref(), slot, std::forward<Args>(args)...); |     PolicyTraits::construct(&alloc_ref(), slot, std::forward<Args>(args)...); | ||||||
|  | @ -1556,8 +1555,7 @@ class raw_hash_set { | ||||||
|     //       mark target as FULL
 |     //       mark target as FULL
 | ||||||
|     //       repeat procedure for current slot with moved from element (target)
 |     //       repeat procedure for current slot with moved from element (target)
 | ||||||
|     ConvertDeletedToEmptyAndFullToDeleted(ctrl_, capacity_); |     ConvertDeletedToEmptyAndFullToDeleted(ctrl_, capacity_); | ||||||
|     typename std::aligned_storage<sizeof(slot_type), alignof(slot_type)>::type |     alignas(slot_type) unsigned char raw[sizeof(slot_type)]; | ||||||
|         raw; |  | ||||||
|     size_t total_probe_length = 0; |     size_t total_probe_length = 0; | ||||||
|     slot_type* slot = reinterpret_cast<slot_type*>(&raw); |     slot_type* slot = reinterpret_cast<slot_type*>(&raw); | ||||||
|     for (size_t i = 0; i != capacity_; ++i) { |     for (size_t i = 0; i != capacity_; ++i) { | ||||||
|  |  | ||||||
|  | @ -202,9 +202,9 @@ static void **NextStackFrame(void **old_fp, const void *uc) { | ||||||
|       } else { |       } else { | ||||||
|         num_push_instructions = 0; |         num_push_instructions = 0; | ||||||
|       } |       } | ||||||
| #else
 | #else  // ABSL_HAVE_VDSO_SUPPORT
 | ||||||
|       num_push_instructions = 0; |       num_push_instructions = 0; | ||||||
| #endif
 | #endif  // ABSL_HAVE_VDSO_SUPPORT
 | ||||||
|     } |     } | ||||||
|     if (num_push_instructions != 0 && kernel_rt_sigreturn_address != nullptr && |     if (num_push_instructions != 0 && kernel_rt_sigreturn_address != nullptr && | ||||||
|         old_fp[1] == kernel_rt_sigreturn_address) { |         old_fp[1] == kernel_rt_sigreturn_address) { | ||||||
|  |  | ||||||
|  | @ -121,13 +121,21 @@ void FlagImpl::AssertValidType(FlagStaticTypeId type_id) const { | ||||||
| std::unique_ptr<void, DynValueDeleter> FlagImpl::MakeInitValue() const { | std::unique_ptr<void, DynValueDeleter> FlagImpl::MakeInitValue() const { | ||||||
|   void* res = nullptr; |   void* res = nullptr; | ||||||
|   if (DefaultKind() == FlagDefaultKind::kDynamicValue) { |   if (DefaultKind() == FlagDefaultKind::kDynamicValue) { | ||||||
|     res = flags_internal::Clone(op_, default_src_.dynamic_value); |     res = flags_internal::Clone(op_, default_value_.dynamic_value); | ||||||
|   } else { |   } else { | ||||||
|     res = (*default_src_.gen_func)(); |     res = (*default_value_.gen_func)(); | ||||||
|   } |   } | ||||||
|   return {res, DynValueDeleter{op_}}; |   return {res, DynValueDeleter{op_}}; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | void FlagImpl::StoreValue(const void* src) { | ||||||
|  |   flags_internal::Copy(op_, src, value_.dynamic); | ||||||
|  |   StoreAtomic(); | ||||||
|  |   modified_ = true; | ||||||
|  |   ++counter_; | ||||||
|  |   InvokeCallback(); | ||||||
|  | } | ||||||
|  | 
 | ||||||
| absl::string_view FlagImpl::Name() const { return name_; } | absl::string_view FlagImpl::Name() const { return name_; } | ||||||
| 
 | 
 | ||||||
| std::string FlagImpl::Filename() const { | std::string FlagImpl::Filename() const { | ||||||
|  | @ -220,23 +228,19 @@ bool FlagImpl::RestoreState(const void* value, bool modified, | ||||||
| // argument. If parsing successful, this function replaces the dst with newly
 | // argument. If parsing successful, this function replaces the dst with newly
 | ||||||
| // parsed value. In case if any error is encountered in either step, the error
 | // parsed value. In case if any error is encountered in either step, the error
 | ||||||
| // message is stored in 'err'
 | // message is stored in 'err'
 | ||||||
| bool FlagImpl::TryParse(void** dst, absl::string_view value, | std::unique_ptr<void, DynValueDeleter> FlagImpl::TryParse( | ||||||
|                         std::string* err) const { |     absl::string_view value, std::string* err) const { | ||||||
|   auto tentative_value = MakeInitValue(); |   std::unique_ptr<void, DynValueDeleter> tentative_value = MakeInitValue(); | ||||||
| 
 | 
 | ||||||
|   std::string parse_err; |   std::string parse_err; | ||||||
|   if (!flags_internal::Parse(op_, value, tentative_value.get(), &parse_err)) { |   if (!flags_internal::Parse(op_, value, tentative_value.get(), &parse_err)) { | ||||||
|     absl::string_view err_sep = parse_err.empty() ? "" : "; "; |     absl::string_view err_sep = parse_err.empty() ? "" : "; "; | ||||||
|     *err = absl::StrCat("Illegal value '", value, "' specified for flag '", |     *err = absl::StrCat("Illegal value '", value, "' specified for flag '", | ||||||
|                         Name(), "'", err_sep, parse_err); |                         Name(), "'", err_sep, parse_err); | ||||||
|     return false; |     return nullptr; | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|   void* old_val = *dst; |   return tentative_value; | ||||||
|   *dst = tentative_value.release(); |  | ||||||
|   tentative_value.reset(old_val); |  | ||||||
| 
 |  | ||||||
|   return true; |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void FlagImpl::Read(void* dst) const { | void FlagImpl::Read(void* dst) const { | ||||||
|  | @ -266,22 +270,17 @@ void FlagImpl::Write(const void* src) { | ||||||
|   absl::MutexLock l(DataGuard()); |   absl::MutexLock l(DataGuard()); | ||||||
| 
 | 
 | ||||||
|   if (ShouldValidateFlagValue(flags_internal::StaticTypeId(op_))) { |   if (ShouldValidateFlagValue(flags_internal::StaticTypeId(op_))) { | ||||||
|     void* obj = flags_internal::Clone(op_, src); |     std::unique_ptr<void, DynValueDeleter> obj{flags_internal::Clone(op_, src), | ||||||
|  |                                                DynValueDeleter{op_}}; | ||||||
|     std::string ignored_error; |     std::string ignored_error; | ||||||
|     std::string src_as_str = flags_internal::Unparse(op_, src); |     std::string src_as_str = flags_internal::Unparse(op_, src); | ||||||
|     if (!flags_internal::Parse(op_, src_as_str, obj, &ignored_error)) { |     if (!flags_internal::Parse(op_, src_as_str, obj.get(), &ignored_error)) { | ||||||
|       ABSL_INTERNAL_LOG(ERROR, absl::StrCat("Attempt to set flag '", Name(), |       ABSL_INTERNAL_LOG(ERROR, absl::StrCat("Attempt to set flag '", Name(), | ||||||
|                                             "' to invalid value ", src_as_str)); |                                             "' to invalid value ", src_as_str)); | ||||||
|     } |     } | ||||||
|     flags_internal::Delete(op_, obj); |  | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|   modified_ = true; |   StoreValue(src); | ||||||
|   counter_++; |  | ||||||
|   flags_internal::Copy(op_, src, value_.dynamic); |  | ||||||
| 
 |  | ||||||
|   StoreAtomic(); |  | ||||||
|   InvokeCallback(); |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| // Sets the value of the flag based on specified string `value`. If the flag
 | // Sets the value of the flag based on specified string `value`. If the flag
 | ||||||
|  | @ -299,11 +298,10 @@ bool FlagImpl::SetFromString(absl::string_view value, FlagSettingMode set_mode, | ||||||
|   switch (set_mode) { |   switch (set_mode) { | ||||||
|     case SET_FLAGS_VALUE: { |     case SET_FLAGS_VALUE: { | ||||||
|       // set or modify the flag's value
 |       // set or modify the flag's value
 | ||||||
|       if (!TryParse(&value_.dynamic, value, err)) return false; |       auto tentative_value = TryParse(value, err); | ||||||
|       modified_ = true; |       if (!tentative_value) return false; | ||||||
|       counter_++; | 
 | ||||||
|       StoreAtomic(); |       StoreValue(tentative_value.get()); | ||||||
|       InvokeCallback(); |  | ||||||
| 
 | 
 | ||||||
|       if (source == kCommandLine) { |       if (source == kCommandLine) { | ||||||
|         on_command_line_ = true; |         on_command_line_ = true; | ||||||
|  | @ -312,13 +310,7 @@ bool FlagImpl::SetFromString(absl::string_view value, FlagSettingMode set_mode, | ||||||
|     } |     } | ||||||
|     case SET_FLAG_IF_DEFAULT: { |     case SET_FLAG_IF_DEFAULT: { | ||||||
|       // set the flag's value, but only if it hasn't been set by someone else
 |       // set the flag's value, but only if it hasn't been set by someone else
 | ||||||
|       if (!modified_) { |       if (modified_) { | ||||||
|         if (!TryParse(&value_.dynamic, value, err)) return false; |  | ||||||
|         modified_ = true; |  | ||||||
|         counter_++; |  | ||||||
|         StoreAtomic(); |  | ||||||
|         InvokeCallback(); |  | ||||||
|       } else { |  | ||||||
|         // TODO(rogeeff): review and fix this semantic. Currently we do not fail
 |         // TODO(rogeeff): review and fix this semantic. Currently we do not fail
 | ||||||
|         // in this case if flag is modified. This is misleading since the flag's
 |         // in this case if flag is modified. This is misleading since the flag's
 | ||||||
|         // value is not updated even though we return true.
 |         // value is not updated even though we return true.
 | ||||||
|  | @ -327,28 +319,29 @@ bool FlagImpl::SetFromString(absl::string_view value, FlagSettingMode set_mode, | ||||||
|         // return false;
 |         // return false;
 | ||||||
|         return true; |         return true; | ||||||
|       } |       } | ||||||
|  |       auto tentative_value = TryParse(value, err); | ||||||
|  |       if (!tentative_value) return false; | ||||||
|  | 
 | ||||||
|  |       StoreValue(tentative_value.get()); | ||||||
|       break; |       break; | ||||||
|     } |     } | ||||||
|     case SET_FLAGS_DEFAULT: { |     case SET_FLAGS_DEFAULT: { | ||||||
|       if (DefaultKind() == FlagDefaultKind::kDynamicValue) { |       auto tentative_value = TryParse(value, err); | ||||||
|         if (!TryParse(&default_src_.dynamic_value, value, err)) { |       if (!tentative_value) return false; | ||||||
|           return false; |  | ||||||
|         } |  | ||||||
|       } else { |  | ||||||
|         void* new_default_val = nullptr; |  | ||||||
|         if (!TryParse(&new_default_val, value, err)) { |  | ||||||
|           return false; |  | ||||||
|         } |  | ||||||
| 
 | 
 | ||||||
|         default_src_.dynamic_value = new_default_val; |       if (DefaultKind() == FlagDefaultKind::kDynamicValue) { | ||||||
|  |         void* old_value = default_value_.dynamic_value; | ||||||
|  |         default_value_.dynamic_value = tentative_value.release(); | ||||||
|  |         tentative_value.reset(old_value); | ||||||
|  |       } else { | ||||||
|  |         default_value_.dynamic_value = tentative_value.release(); | ||||||
|         def_kind_ = static_cast<uint8_t>(FlagDefaultKind::kDynamicValue); |         def_kind_ = static_cast<uint8_t>(FlagDefaultKind::kDynamicValue); | ||||||
|       } |       } | ||||||
| 
 | 
 | ||||||
|       if (!modified_) { |       if (!modified_) { | ||||||
|         // Need to set both default value *and* current, in this case
 |         // Need to set both default value *and* current, in this case
 | ||||||
|         flags_internal::Copy(op_, default_src_.dynamic_value, value_.dynamic); |         StoreValue(default_value_.dynamic_value); | ||||||
|         StoreAtomic(); |         modified_ = false; | ||||||
|         InvokeCallback(); |  | ||||||
|       } |       } | ||||||
|       break; |       break; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  | @ -363,7 +363,7 @@ struct DynValueDeleter { | ||||||
|     if (op != nullptr) Delete(op, ptr); |     if (op != nullptr) Delete(op, ptr); | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|   const FlagOpFn op; |   FlagOpFn op; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| class FlagImpl { | class FlagImpl { | ||||||
|  | @ -380,7 +380,7 @@ class FlagImpl { | ||||||
|         on_command_line_(false), |         on_command_line_(false), | ||||||
|         counter_(0), |         counter_(0), | ||||||
|         callback_(nullptr), |         callback_(nullptr), | ||||||
|         default_src_(default_value_gen), |         default_value_(default_value_gen), | ||||||
|         data_guard_{} {} |         data_guard_{} {} | ||||||
| 
 | 
 | ||||||
|   // Constant access methods
 |   // Constant access methods
 | ||||||
|  | @ -392,10 +392,6 @@ class FlagImpl { | ||||||
|   std::string DefaultValue() const ABSL_LOCKS_EXCLUDED(*DataGuard()); |   std::string DefaultValue() const ABSL_LOCKS_EXCLUDED(*DataGuard()); | ||||||
|   std::string CurrentValue() const ABSL_LOCKS_EXCLUDED(*DataGuard()); |   std::string CurrentValue() const ABSL_LOCKS_EXCLUDED(*DataGuard()); | ||||||
|   void Read(void* dst) const ABSL_LOCKS_EXCLUDED(*DataGuard()); |   void Read(void* dst) const ABSL_LOCKS_EXCLUDED(*DataGuard()); | ||||||
|   // Attempts to parse supplied `value` std::string. If parsing is successful, then
 |  | ||||||
|   // it replaces `dst` with the new value.
 |  | ||||||
|   bool TryParse(void** dst, absl::string_view value, std::string* err) const |  | ||||||
|       ABSL_EXCLUSIVE_LOCKS_REQUIRED(*DataGuard()); |  | ||||||
| 
 | 
 | ||||||
|   template <typename T, typename std::enable_if< |   template <typename T, typename std::enable_if< | ||||||
|                             !IsAtomicFlagTypeTrait<T>::value, int>::type = 0> |                             !IsAtomicFlagTypeTrait<T>::value, int>::type = 0> | ||||||
|  | @ -466,8 +462,15 @@ class FlagImpl { | ||||||
|   // Returns heap allocated value of type T initialized with default value.
 |   // Returns heap allocated value of type T initialized with default value.
 | ||||||
|   std::unique_ptr<void, DynValueDeleter> MakeInitValue() const |   std::unique_ptr<void, DynValueDeleter> MakeInitValue() const | ||||||
|       ABSL_EXCLUSIVE_LOCKS_REQUIRED(*DataGuard()); |       ABSL_EXCLUSIVE_LOCKS_REQUIRED(*DataGuard()); | ||||||
|   // Lazy initialization of the Flag's data.
 |   // Flag initialization called via absl::call_once.
 | ||||||
|   void Init(); |   void Init(); | ||||||
|  |   // Attempts to parse supplied `value` std::string. If parsing is successful,
 | ||||||
|  |   // returns new value. Otherwsie returns nullptr.
 | ||||||
|  |   std::unique_ptr<void, DynValueDeleter> TryParse(absl::string_view value, | ||||||
|  |                                                   std::string* err) const | ||||||
|  |       ABSL_EXCLUSIVE_LOCKS_REQUIRED(*DataGuard()); | ||||||
|  |   // Stores the flag value based on the pointer to the source.
 | ||||||
|  |   void StoreValue(const void* src) ABSL_EXCLUSIVE_LOCKS_REQUIRED(*DataGuard()); | ||||||
| 
 | 
 | ||||||
|   FlagHelpKind HelpSourceKind() const { |   FlagHelpKind HelpSourceKind() const { | ||||||
|     return static_cast<FlagHelpKind>(help_source_kind_); |     return static_cast<FlagHelpKind>(help_source_kind_); | ||||||
|  | @ -511,7 +514,7 @@ class FlagImpl { | ||||||
| 
 | 
 | ||||||
|   // Mutable flag's state (guarded by `data_guard_`).
 |   // Mutable flag's state (guarded by `data_guard_`).
 | ||||||
| 
 | 
 | ||||||
|   // If def_kind_ == kDynamicValue, default_src_ holds a dynamically allocated
 |   // If def_kind_ == kDynamicValue, default_value_ holds a dynamically allocated
 | ||||||
|   // value.
 |   // value.
 | ||||||
|   uint8_t def_kind_ : 1 ABSL_GUARDED_BY(*DataGuard()); |   uint8_t def_kind_ : 1 ABSL_GUARDED_BY(*DataGuard()); | ||||||
|   // Has this flag's value been modified?
 |   // Has this flag's value been modified?
 | ||||||
|  | @ -527,7 +530,7 @@ class FlagImpl { | ||||||
|   // value specified in ABSL_FLAG or pointer to the dynamically set default
 |   // value specified in ABSL_FLAG or pointer to the dynamically set default
 | ||||||
|   // value via SetCommandLineOptionWithMode. def_kind_ is used to distinguish
 |   // value via SetCommandLineOptionWithMode. def_kind_ is used to distinguish
 | ||||||
|   // these two cases.
 |   // these two cases.
 | ||||||
|   FlagDefaultSrc default_src_ ABSL_GUARDED_BY(*DataGuard()); |   FlagDefaultSrc default_value_ ABSL_GUARDED_BY(*DataGuard()); | ||||||
|   // Current Flag Value
 |   // Current Flag Value
 | ||||||
|   FlagValue value_; |   FlagValue value_; | ||||||
| 
 | 
 | ||||||
|  | @ -542,8 +545,8 @@ class FlagImpl { | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| ///////////////////////////////////////////////////////////////////////////////
 | ///////////////////////////////////////////////////////////////////////////////
 | ||||||
| // The "unspecified" implementation of Flag object parameterized by the
 | // The Flag object parameterized by the flag's value type. This class implements
 | ||||||
| // flag's value type.
 | // flag reflection handle interface.
 | ||||||
| 
 | 
 | ||||||
| template <typename T> | template <typename T> | ||||||
| class Flag final : public flags_internal::CommandLineFlag { | class Flag final : public flags_internal::CommandLineFlag { | ||||||
|  |  | ||||||
|  | @ -119,6 +119,13 @@ TEST_F(TypeErasedTest, TestSetCommandLineOptionWithMode_SET_FLAGS_DEFAULT) { | ||||||
|   EXPECT_TRUE(flags::SetCommandLineOptionWithMode("int_flag", "101", |   EXPECT_TRUE(flags::SetCommandLineOptionWithMode("int_flag", "101", | ||||||
|                                                   flags::SET_FLAGS_DEFAULT)); |                                                   flags::SET_FLAGS_DEFAULT)); | ||||||
| 
 | 
 | ||||||
|  |   // Set it again to ensure that resetting logic is covered.
 | ||||||
|  |   EXPECT_TRUE(flags::SetCommandLineOptionWithMode("int_flag", "102", | ||||||
|  |                                                   flags::SET_FLAGS_DEFAULT)); | ||||||
|  | 
 | ||||||
|  |   EXPECT_TRUE(flags::SetCommandLineOptionWithMode("int_flag", "103", | ||||||
|  |                                                   flags::SET_FLAGS_DEFAULT)); | ||||||
|  | 
 | ||||||
|   EXPECT_TRUE(flags::SetCommandLineOptionWithMode("string_flag", "asdfgh", |   EXPECT_TRUE(flags::SetCommandLineOptionWithMode("string_flag", "asdfgh", | ||||||
|                                                   flags::SET_FLAGS_DEFAULT)); |                                                   flags::SET_FLAGS_DEFAULT)); | ||||||
|   EXPECT_EQ(absl::GetFlag(FLAGS_string_flag), "asdfgh"); |   EXPECT_EQ(absl::GetFlag(FLAGS_string_flag), "asdfgh"); | ||||||
|  |  | ||||||
|  | @ -38,9 +38,7 @@ ABSL_NAMESPACE_BEGIN | ||||||
| 
 | 
 | ||||||
| // bind_front()
 | // bind_front()
 | ||||||
| //
 | //
 | ||||||
| // Binds the first N arguments of an invocable object and stores them by value,
 | // Binds the first N arguments of an invocable object and stores them by value.
 | ||||||
| // except types of `std::reference_wrapper` which are 'unwound' and stored by
 |  | ||||||
| // reference.
 |  | ||||||
| //
 | //
 | ||||||
| // Like `std::bind()`, `absl::bind_front()` is implicitly convertible to
 | // Like `std::bind()`, `absl::bind_front()` is implicitly convertible to
 | ||||||
| // `std::function`.  In particular, it may be used as a simpler replacement for
 | // `std::function`.  In particular, it may be used as a simpler replacement for
 | ||||||
|  | @ -140,7 +138,9 @@ ABSL_NAMESPACE_BEGIN | ||||||
| //
 | //
 | ||||||
| // Example: Storing bound arguments by reference.
 | // Example: Storing bound arguments by reference.
 | ||||||
| //
 | //
 | ||||||
| //   void Print(const string& a, const string& b) { LOG(INFO) << a << b; }
 | //   void Print(const std::string& a, const std::string& b) {
 | ||||||
|  | //     std::cerr << a << b;
 | ||||||
|  | //   }
 | ||||||
| //
 | //
 | ||||||
| //   std::string hi = "Hello, ";
 | //   std::string hi = "Hello, ";
 | ||||||
| //   std::vector<std::string> names = {"Chuk", "Gek"};
 | //   std::vector<std::string> names = {"Chuk", "Gek"};
 | ||||||
|  | @ -152,6 +152,24 @@ ABSL_NAMESPACE_BEGIN | ||||||
| //   // dangling references.
 | //   // dangling references.
 | ||||||
| //   foo->DoInFuture(absl::bind_front(Print, std::ref(hi), "Guest"));  // BAD!
 | //   foo->DoInFuture(absl::bind_front(Print, std::ref(hi), "Guest"));  // BAD!
 | ||||||
| //   auto f = absl::bind_front(Print, std::ref(hi), "Guest"); // BAD!
 | //   auto f = absl::bind_front(Print, std::ref(hi), "Guest"); // BAD!
 | ||||||
|  | //
 | ||||||
|  | // Example: Storing reference-like types.
 | ||||||
|  | //
 | ||||||
|  | //   void Print(absl::string_view a, const std::string& b) {
 | ||||||
|  | //     std::cerr << a << b;
 | ||||||
|  | //   }
 | ||||||
|  | //
 | ||||||
|  | //   std::string hi = "Hello, ";
 | ||||||
|  | //   // Copies "hi".
 | ||||||
|  | //   absl::bind_front(Print, hi)("Chuk");
 | ||||||
|  | //
 | ||||||
|  | //   // Compile error: std::reference_wrapper<const string> is not implicitly
 | ||||||
|  | //   // convertible to string_view.
 | ||||||
|  | //   // absl::bind_front(Print, std::cref(hi))("Chuk");
 | ||||||
|  | //
 | ||||||
|  | //   // Doesn't copy "hi".
 | ||||||
|  | //   absl::bind_front(Print, absl::string_view(hi))("Chuk");
 | ||||||
|  | //
 | ||||||
| template <class F, class... BoundArgs> | template <class F, class... BoundArgs> | ||||||
| constexpr functional_internal::bind_front_t<F, BoundArgs...> bind_front( | constexpr functional_internal::bind_front_t<F, BoundArgs...> bind_front( | ||||||
|     F&& func, BoundArgs&&... args) { |     F&& func, BoundArgs&&... args) { | ||||||
|  |  | ||||||
|  | @ -27,9 +27,6 @@ namespace { | ||||||
| 
 | 
 | ||||||
| constexpr int kLength = 50; | constexpr int kLength = 50; | ||||||
| using Thrower = testing::ThrowingValue<testing::TypeSpec::kEverythingThrows>; | using Thrower = testing::ThrowingValue<testing::TypeSpec::kEverythingThrows>; | ||||||
| using ThrowerStorage = |  | ||||||
|     absl::aligned_storage_t<sizeof(Thrower), alignof(Thrower)>; |  | ||||||
| using ThrowerList = std::array<ThrowerStorage, kLength>; |  | ||||||
| 
 | 
 | ||||||
| TEST(MakeUnique, CheckForLeaks) { | TEST(MakeUnique, CheckForLeaks) { | ||||||
|   constexpr int kValue = 321; |   constexpr int kValue = 321; | ||||||
|  |  | ||||||
|  | @ -63,16 +63,16 @@ namespace { | ||||||
| // Type used with std::allocator for allocating and deallocating
 | // Type used with std::allocator for allocating and deallocating
 | ||||||
| // `CordRepExternal`. std::allocator is used because it opaquely handles the
 | // `CordRepExternal`. std::allocator is used because it opaquely handles the
 | ||||||
| // different new / delete overloads available on a given platform.
 | // different new / delete overloads available on a given platform.
 | ||||||
| using ExternalAllocType = | struct alignas(absl::cord_internal::ExternalRepAlignment()) ExternalAllocType { | ||||||
|     absl::aligned_storage_t<absl::cord_internal::ExternalRepAlignment(), |   unsigned char value[absl::cord_internal::ExternalRepAlignment()]; | ||||||
|                             absl::cord_internal::ExternalRepAlignment()>; | }; | ||||||
| 
 | 
 | ||||||
| // Returns the number of objects to pass in to std::allocator<ExternalAllocType>
 | // Returns the number of objects to pass in to std::allocator<ExternalAllocType>
 | ||||||
| // allocate() and deallocate() to create enough room for `CordRepExternal` with
 | // allocate() and deallocate() to create enough room for `CordRepExternal` with
 | ||||||
| // `releaser_size` bytes on the end.
 | // `releaser_size` bytes on the end.
 | ||||||
| constexpr size_t GetExternalAllocNumObjects(size_t releaser_size) { | constexpr size_t GetExternalAllocNumObjects(size_t releaser_size) { | ||||||
|   // Be sure to round up since `releaser_size` could be smaller than
 |   // Be sure to round up since `releaser_size` could be smaller than
 | ||||||
|   // sizeof(ExternalAllocType)`.
 |   // `sizeof(ExternalAllocType)`.
 | ||||||
|   return (sizeof(CordRepExternal) + releaser_size + sizeof(ExternalAllocType) - |   return (sizeof(CordRepExternal) + releaser_size + sizeof(ExternalAllocType) - | ||||||
|           1) / |           1) / | ||||||
|          sizeof(ExternalAllocType); |          sizeof(ExternalAllocType); | ||||||
|  |  | ||||||
|  | @ -252,8 +252,8 @@ class SynchronizationStorage { | ||||||
| 
 | 
 | ||||||
|   absl::once_flag once_; |   absl::once_flag once_; | ||||||
| 
 | 
 | ||||||
|   // An aligned space for T.
 |   // An aligned space for the T.
 | ||||||
|   typename std::aligned_storage<sizeof(T), alignof(T)>::type space_; |   alignas(T) unsigned char space_[sizeof(T)]; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| }  // namespace synchronization_internal
 | }  // namespace synchronization_internal
 | ||||||
|  |  | ||||||
|  | @ -368,31 +368,29 @@ class Waiter::WinHelper { | ||||||
|     return reinterpret_cast<CONDITION_VARIABLE *>(&w->cv_storage_); |     return reinterpret_cast<CONDITION_VARIABLE *>(&w->cv_storage_); | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|   static_assert(sizeof(SRWLOCK) == sizeof(Waiter::SRWLockStorage), |   static_assert(sizeof(SRWLOCK) == sizeof(void *), | ||||||
|                 "SRWLockStorage does not have the same size as SRWLOCK"); |                 "`mu_storage_` does not have the same size as SRWLOCK"); | ||||||
|   static_assert( |   static_assert(alignof(SRWLOCK) == alignof(void *), | ||||||
|       alignof(SRWLOCK) == alignof(Waiter::SRWLockStorage), |                 "`mu_storage_` does not have the same alignment as SRWLOCK"); | ||||||
|       "SRWLockStorage does not have the same alignment as SRWLOCK"); |  | ||||||
| 
 | 
 | ||||||
|   static_assert(sizeof(CONDITION_VARIABLE) == |   static_assert(sizeof(CONDITION_VARIABLE) == sizeof(void *), | ||||||
|                     sizeof(Waiter::ConditionVariableStorage), |                 "`ABSL_CONDITION_VARIABLE_STORAGE` does not have the same size " | ||||||
|                 "ABSL_CONDITION_VARIABLE_STORAGE does not have the same size " |                 "as `CONDITION_VARIABLE`"); | ||||||
|                 "as CONDITION_VARIABLE"); |   static_assert( | ||||||
|   static_assert(alignof(CONDITION_VARIABLE) == |       alignof(CONDITION_VARIABLE) == alignof(void *), | ||||||
|                     alignof(Waiter::ConditionVariableStorage), |       "`cv_storage_` does not have the same alignment as `CONDITION_VARIABLE`"); | ||||||
|                 "ConditionVariableStorage does not have the same " |  | ||||||
|                 "alignment as CONDITION_VARIABLE"); |  | ||||||
| 
 | 
 | ||||||
|   // The SRWLOCK and CONDITION_VARIABLE types must be trivially constructible
 |   // The SRWLOCK and CONDITION_VARIABLE types must be trivially constructible
 | ||||||
|   // and destructible because we never call their constructors or destructors.
 |   // and destructible because we never call their constructors or destructors.
 | ||||||
|   static_assert(std::is_trivially_constructible<SRWLOCK>::value, |   static_assert(std::is_trivially_constructible<SRWLOCK>::value, | ||||||
|                 "The SRWLOCK type must be trivially constructible"); |                 "The `SRWLOCK` type must be trivially constructible"); | ||||||
|   static_assert(std::is_trivially_constructible<CONDITION_VARIABLE>::value, |   static_assert( | ||||||
|                 "The CONDITION_VARIABLE type must be trivially constructible"); |       std::is_trivially_constructible<CONDITION_VARIABLE>::value, | ||||||
|  |       "The `CONDITION_VARIABLE` type must be trivially constructible"); | ||||||
|   static_assert(std::is_trivially_destructible<SRWLOCK>::value, |   static_assert(std::is_trivially_destructible<SRWLOCK>::value, | ||||||
|                 "The SRWLOCK type must be trivially destructible"); |                 "The `SRWLOCK` type must be trivially destructible"); | ||||||
|   static_assert(std::is_trivially_destructible<CONDITION_VARIABLE>::value, |   static_assert(std::is_trivially_destructible<CONDITION_VARIABLE>::value, | ||||||
|                 "The CONDITION_VARIABLE type must be trivially destructible"); |                 "The `CONDITION_VARIABLE` type must be trivially destructible"); | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| class LockHolder { | class LockHolder { | ||||||
|  |  | ||||||
|  | @ -133,13 +133,6 @@ class Waiter { | ||||||
|   std::atomic<int> wakeups_; |   std::atomic<int> wakeups_; | ||||||
| 
 | 
 | ||||||
| #elif ABSL_WAITER_MODE == ABSL_WAITER_MODE_WIN32 | #elif ABSL_WAITER_MODE == ABSL_WAITER_MODE_WIN32 | ||||||
|   // We can't include Windows.h in our headers, so we use aligned storage
 |  | ||||||
|   // buffers to define the storage of SRWLOCK and CONDITION_VARIABLE.
 |  | ||||||
|   using SRWLockStorage = |  | ||||||
|       typename std::aligned_storage<sizeof(void*), alignof(void*)>::type; |  | ||||||
|   using ConditionVariableStorage = |  | ||||||
|       typename std::aligned_storage<sizeof(void*), alignof(void*)>::type; |  | ||||||
| 
 |  | ||||||
|   // WinHelper - Used to define utilities for accessing the lock and
 |   // WinHelper - Used to define utilities for accessing the lock and
 | ||||||
|   // condition variable storage once the types are complete.
 |   // condition variable storage once the types are complete.
 | ||||||
|   class WinHelper; |   class WinHelper; | ||||||
|  | @ -147,8 +140,10 @@ class Waiter { | ||||||
|   // REQUIRES: WinHelper::GetLock(this) must be held.
 |   // REQUIRES: WinHelper::GetLock(this) must be held.
 | ||||||
|   void InternalCondVarPoke(); |   void InternalCondVarPoke(); | ||||||
| 
 | 
 | ||||||
|   SRWLockStorage mu_storage_; |   // We can't include Windows.h in our headers, so we use aligned charachter
 | ||||||
|   ConditionVariableStorage cv_storage_; |   // buffers to define the storage of SRWLOCK and CONDITION_VARIABLE.
 | ||||||
|  |   alignas(void*) unsigned char mu_storage_[sizeof(void*)]; | ||||||
|  |   alignas(void*) unsigned char cv_storage_[sizeof(void*)]; | ||||||
|   int waiter_count_; |   int waiter_count_; | ||||||
|   int wakeup_count_; |   int wakeup_count_; | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue