1*9356374aSAndroid Build Coastguard Worker //
2*9356374aSAndroid Build Coastguard Worker // Copyright 2019 The Abseil Authors.
3*9356374aSAndroid Build Coastguard Worker //
4*9356374aSAndroid Build Coastguard Worker // Licensed under the Apache License, Version 2.0 (the "License");
5*9356374aSAndroid Build Coastguard Worker // you may not use this file except in compliance with the License.
6*9356374aSAndroid Build Coastguard Worker // You may obtain a copy of the License at
7*9356374aSAndroid Build Coastguard Worker //
8*9356374aSAndroid Build Coastguard Worker // https://www.apache.org/licenses/LICENSE-2.0
9*9356374aSAndroid Build Coastguard Worker //
10*9356374aSAndroid Build Coastguard Worker // Unless required by applicable law or agreed to in writing, software
11*9356374aSAndroid Build Coastguard Worker // distributed under the License is distributed on an "AS IS" BASIS,
12*9356374aSAndroid Build Coastguard Worker // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*9356374aSAndroid Build Coastguard Worker // See the License for the specific language governing permissions and
14*9356374aSAndroid Build Coastguard Worker // limitations under the License.
15*9356374aSAndroid Build Coastguard Worker
16*9356374aSAndroid Build Coastguard Worker #include "absl/flags/internal/flag.h"
17*9356374aSAndroid Build Coastguard Worker
18*9356374aSAndroid Build Coastguard Worker #include <assert.h>
19*9356374aSAndroid Build Coastguard Worker #include <stddef.h>
20*9356374aSAndroid Build Coastguard Worker #include <stdint.h>
21*9356374aSAndroid Build Coastguard Worker #include <string.h>
22*9356374aSAndroid Build Coastguard Worker
23*9356374aSAndroid Build Coastguard Worker #include <array>
24*9356374aSAndroid Build Coastguard Worker #include <atomic>
25*9356374aSAndroid Build Coastguard Worker #include <cstring>
26*9356374aSAndroid Build Coastguard Worker #include <memory>
27*9356374aSAndroid Build Coastguard Worker #include <string>
28*9356374aSAndroid Build Coastguard Worker #include <typeinfo>
29*9356374aSAndroid Build Coastguard Worker #include <vector>
30*9356374aSAndroid Build Coastguard Worker
31*9356374aSAndroid Build Coastguard Worker #include "absl/base/attributes.h"
32*9356374aSAndroid Build Coastguard Worker #include "absl/base/call_once.h"
33*9356374aSAndroid Build Coastguard Worker #include "absl/base/casts.h"
34*9356374aSAndroid Build Coastguard Worker #include "absl/base/config.h"
35*9356374aSAndroid Build Coastguard Worker #include "absl/base/const_init.h"
36*9356374aSAndroid Build Coastguard Worker #include "absl/base/dynamic_annotations.h"
37*9356374aSAndroid Build Coastguard Worker #include "absl/base/optimization.h"
38*9356374aSAndroid Build Coastguard Worker #include "absl/flags/config.h"
39*9356374aSAndroid Build Coastguard Worker #include "absl/flags/internal/commandlineflag.h"
40*9356374aSAndroid Build Coastguard Worker #include "absl/flags/usage_config.h"
41*9356374aSAndroid Build Coastguard Worker #include "absl/memory/memory.h"
42*9356374aSAndroid Build Coastguard Worker #include "absl/strings/str_cat.h"
43*9356374aSAndroid Build Coastguard Worker #include "absl/strings/string_view.h"
44*9356374aSAndroid Build Coastguard Worker #include "absl/synchronization/mutex.h"
45*9356374aSAndroid Build Coastguard Worker
46*9356374aSAndroid Build Coastguard Worker namespace absl {
47*9356374aSAndroid Build Coastguard Worker ABSL_NAMESPACE_BEGIN
48*9356374aSAndroid Build Coastguard Worker namespace flags_internal {
49*9356374aSAndroid Build Coastguard Worker
50*9356374aSAndroid Build Coastguard Worker // The help message indicating that the commandline flag has been stripped. It
51*9356374aSAndroid Build Coastguard Worker // will not show up when doing "-help" and its variants. The flag is stripped
52*9356374aSAndroid Build Coastguard Worker // if ABSL_FLAGS_STRIP_HELP is set to 1 before including absl/flags/flag.h
53*9356374aSAndroid Build Coastguard Worker const char kStrippedFlagHelp[] = "\001\002\003\004 (unknown) \004\003\002\001";
54*9356374aSAndroid Build Coastguard Worker
55*9356374aSAndroid Build Coastguard Worker namespace {
56*9356374aSAndroid Build Coastguard Worker
57*9356374aSAndroid Build Coastguard Worker // Currently we only validate flag values for user-defined flag types.
ShouldValidateFlagValue(FlagFastTypeId flag_type_id)58*9356374aSAndroid Build Coastguard Worker bool ShouldValidateFlagValue(FlagFastTypeId flag_type_id) {
59*9356374aSAndroid Build Coastguard Worker #define DONT_VALIDATE(T, _) \
60*9356374aSAndroid Build Coastguard Worker if (flag_type_id == base_internal::FastTypeId<T>()) return false;
61*9356374aSAndroid Build Coastguard Worker ABSL_FLAGS_INTERNAL_SUPPORTED_TYPES(DONT_VALIDATE)
62*9356374aSAndroid Build Coastguard Worker #undef DONT_VALIDATE
63*9356374aSAndroid Build Coastguard Worker
64*9356374aSAndroid Build Coastguard Worker return true;
65*9356374aSAndroid Build Coastguard Worker }
66*9356374aSAndroid Build Coastguard Worker
67*9356374aSAndroid Build Coastguard Worker // RAII helper used to temporarily unlock and relock `absl::Mutex`.
68*9356374aSAndroid Build Coastguard Worker // This is used when we need to ensure that locks are released while
69*9356374aSAndroid Build Coastguard Worker // invoking user supplied callbacks and then reacquired, since callbacks may
70*9356374aSAndroid Build Coastguard Worker // need to acquire these locks themselves.
71*9356374aSAndroid Build Coastguard Worker class MutexRelock {
72*9356374aSAndroid Build Coastguard Worker public:
MutexRelock(absl::Mutex & mu)73*9356374aSAndroid Build Coastguard Worker explicit MutexRelock(absl::Mutex& mu) : mu_(mu) { mu_.Unlock(); }
~MutexRelock()74*9356374aSAndroid Build Coastguard Worker ~MutexRelock() { mu_.Lock(); }
75*9356374aSAndroid Build Coastguard Worker
76*9356374aSAndroid Build Coastguard Worker MutexRelock(const MutexRelock&) = delete;
77*9356374aSAndroid Build Coastguard Worker MutexRelock& operator=(const MutexRelock&) = delete;
78*9356374aSAndroid Build Coastguard Worker
79*9356374aSAndroid Build Coastguard Worker private:
80*9356374aSAndroid Build Coastguard Worker absl::Mutex& mu_;
81*9356374aSAndroid Build Coastguard Worker };
82*9356374aSAndroid Build Coastguard Worker
83*9356374aSAndroid Build Coastguard Worker // This is a freelist of leaked flag values and guard for its access.
84*9356374aSAndroid Build Coastguard Worker // When we can't guarantee it is safe to reuse the memory for flag values,
85*9356374aSAndroid Build Coastguard Worker // we move the memory to the freelist where it lives indefinitely, so it can
86*9356374aSAndroid Build Coastguard Worker // still be safely accessed. This also prevents leak checkers from complaining
87*9356374aSAndroid Build Coastguard Worker // about the leaked memory that can no longer be accessed through any pointer.
88*9356374aSAndroid Build Coastguard Worker ABSL_CONST_INIT absl::Mutex s_freelist_guard(absl::kConstInit);
89*9356374aSAndroid Build Coastguard Worker ABSL_CONST_INIT std::vector<void*>* s_freelist = nullptr;
90*9356374aSAndroid Build Coastguard Worker
AddToFreelist(void * p)91*9356374aSAndroid Build Coastguard Worker void AddToFreelist(void* p) {
92*9356374aSAndroid Build Coastguard Worker absl::MutexLock l(&s_freelist_guard);
93*9356374aSAndroid Build Coastguard Worker if (!s_freelist) {
94*9356374aSAndroid Build Coastguard Worker s_freelist = new std::vector<void*>;
95*9356374aSAndroid Build Coastguard Worker }
96*9356374aSAndroid Build Coastguard Worker s_freelist->push_back(p);
97*9356374aSAndroid Build Coastguard Worker }
98*9356374aSAndroid Build Coastguard Worker
99*9356374aSAndroid Build Coastguard Worker } // namespace
100*9356374aSAndroid Build Coastguard Worker
101*9356374aSAndroid Build Coastguard Worker ///////////////////////////////////////////////////////////////////////////////
102*9356374aSAndroid Build Coastguard Worker
NumLeakedFlagValues()103*9356374aSAndroid Build Coastguard Worker uint64_t NumLeakedFlagValues() {
104*9356374aSAndroid Build Coastguard Worker absl::MutexLock l(&s_freelist_guard);
105*9356374aSAndroid Build Coastguard Worker return s_freelist == nullptr ? 0u : s_freelist->size();
106*9356374aSAndroid Build Coastguard Worker }
107*9356374aSAndroid Build Coastguard Worker
108*9356374aSAndroid Build Coastguard Worker ///////////////////////////////////////////////////////////////////////////////
109*9356374aSAndroid Build Coastguard Worker // Persistent state of the flag data.
110*9356374aSAndroid Build Coastguard Worker
111*9356374aSAndroid Build Coastguard Worker class FlagImpl;
112*9356374aSAndroid Build Coastguard Worker
113*9356374aSAndroid Build Coastguard Worker class FlagState : public flags_internal::FlagStateInterface {
114*9356374aSAndroid Build Coastguard Worker public:
115*9356374aSAndroid Build Coastguard Worker template <typename V>
FlagState(FlagImpl & flag_impl,const V & v,bool modified,bool on_command_line,int64_t counter)116*9356374aSAndroid Build Coastguard Worker FlagState(FlagImpl& flag_impl, const V& v, bool modified,
117*9356374aSAndroid Build Coastguard Worker bool on_command_line, int64_t counter)
118*9356374aSAndroid Build Coastguard Worker : flag_impl_(flag_impl),
119*9356374aSAndroid Build Coastguard Worker value_(v),
120*9356374aSAndroid Build Coastguard Worker modified_(modified),
121*9356374aSAndroid Build Coastguard Worker on_command_line_(on_command_line),
122*9356374aSAndroid Build Coastguard Worker counter_(counter) {}
123*9356374aSAndroid Build Coastguard Worker
~FlagState()124*9356374aSAndroid Build Coastguard Worker ~FlagState() override {
125*9356374aSAndroid Build Coastguard Worker if (flag_impl_.ValueStorageKind() != FlagValueStorageKind::kHeapAllocated &&
126*9356374aSAndroid Build Coastguard Worker flag_impl_.ValueStorageKind() != FlagValueStorageKind::kSequenceLocked)
127*9356374aSAndroid Build Coastguard Worker return;
128*9356374aSAndroid Build Coastguard Worker flags_internal::Delete(flag_impl_.op_, value_.heap_allocated);
129*9356374aSAndroid Build Coastguard Worker }
130*9356374aSAndroid Build Coastguard Worker
131*9356374aSAndroid Build Coastguard Worker private:
132*9356374aSAndroid Build Coastguard Worker friend class FlagImpl;
133*9356374aSAndroid Build Coastguard Worker
134*9356374aSAndroid Build Coastguard Worker // Restores the flag to the saved state.
Restore() const135*9356374aSAndroid Build Coastguard Worker void Restore() const override {
136*9356374aSAndroid Build Coastguard Worker if (!flag_impl_.RestoreState(*this)) return;
137*9356374aSAndroid Build Coastguard Worker
138*9356374aSAndroid Build Coastguard Worker ABSL_INTERNAL_LOG(INFO,
139*9356374aSAndroid Build Coastguard Worker absl::StrCat("Restore saved value of ", flag_impl_.Name(),
140*9356374aSAndroid Build Coastguard Worker " to: ", flag_impl_.CurrentValue()));
141*9356374aSAndroid Build Coastguard Worker }
142*9356374aSAndroid Build Coastguard Worker
143*9356374aSAndroid Build Coastguard Worker // Flag and saved flag data.
144*9356374aSAndroid Build Coastguard Worker FlagImpl& flag_impl_;
145*9356374aSAndroid Build Coastguard Worker union SavedValue {
SavedValue(void * v)146*9356374aSAndroid Build Coastguard Worker explicit SavedValue(void* v) : heap_allocated(v) {}
SavedValue(int64_t v)147*9356374aSAndroid Build Coastguard Worker explicit SavedValue(int64_t v) : one_word(v) {}
148*9356374aSAndroid Build Coastguard Worker
149*9356374aSAndroid Build Coastguard Worker void* heap_allocated;
150*9356374aSAndroid Build Coastguard Worker int64_t one_word;
151*9356374aSAndroid Build Coastguard Worker } value_;
152*9356374aSAndroid Build Coastguard Worker bool modified_;
153*9356374aSAndroid Build Coastguard Worker bool on_command_line_;
154*9356374aSAndroid Build Coastguard Worker int64_t counter_;
155*9356374aSAndroid Build Coastguard Worker };
156*9356374aSAndroid Build Coastguard Worker
157*9356374aSAndroid Build Coastguard Worker ///////////////////////////////////////////////////////////////////////////////
158*9356374aSAndroid Build Coastguard Worker // Flag implementation, which does not depend on flag value type.
159*9356374aSAndroid Build Coastguard Worker
DynValueDeleter(FlagOpFn op_arg)160*9356374aSAndroid Build Coastguard Worker DynValueDeleter::DynValueDeleter(FlagOpFn op_arg) : op(op_arg) {}
161*9356374aSAndroid Build Coastguard Worker
operator ()(void * ptr) const162*9356374aSAndroid Build Coastguard Worker void DynValueDeleter::operator()(void* ptr) const {
163*9356374aSAndroid Build Coastguard Worker if (op == nullptr) return;
164*9356374aSAndroid Build Coastguard Worker
165*9356374aSAndroid Build Coastguard Worker Delete(op, ptr);
166*9356374aSAndroid Build Coastguard Worker }
167*9356374aSAndroid Build Coastguard Worker
MaskedPointer(ptr_t rhs,bool is_candidate)168*9356374aSAndroid Build Coastguard Worker MaskedPointer::MaskedPointer(ptr_t rhs, bool is_candidate) : ptr_(rhs) {
169*9356374aSAndroid Build Coastguard Worker if (is_candidate) {
170*9356374aSAndroid Build Coastguard Worker ApplyMask(kUnprotectedReadCandidate);
171*9356374aSAndroid Build Coastguard Worker }
172*9356374aSAndroid Build Coastguard Worker }
173*9356374aSAndroid Build Coastguard Worker
IsUnprotectedReadCandidate() const174*9356374aSAndroid Build Coastguard Worker bool MaskedPointer::IsUnprotectedReadCandidate() const {
175*9356374aSAndroid Build Coastguard Worker return CheckMask(kUnprotectedReadCandidate);
176*9356374aSAndroid Build Coastguard Worker }
177*9356374aSAndroid Build Coastguard Worker
HasBeenRead() const178*9356374aSAndroid Build Coastguard Worker bool MaskedPointer::HasBeenRead() const { return CheckMask(kHasBeenRead); }
179*9356374aSAndroid Build Coastguard Worker
Set(FlagOpFn op,const void * src,bool is_candidate)180*9356374aSAndroid Build Coastguard Worker void MaskedPointer::Set(FlagOpFn op, const void* src, bool is_candidate) {
181*9356374aSAndroid Build Coastguard Worker flags_internal::Copy(op, src, Ptr());
182*9356374aSAndroid Build Coastguard Worker if (is_candidate) {
183*9356374aSAndroid Build Coastguard Worker ApplyMask(kUnprotectedReadCandidate);
184*9356374aSAndroid Build Coastguard Worker }
185*9356374aSAndroid Build Coastguard Worker }
MarkAsRead()186*9356374aSAndroid Build Coastguard Worker void MaskedPointer::MarkAsRead() { ApplyMask(kHasBeenRead); }
187*9356374aSAndroid Build Coastguard Worker
ApplyMask(mask_t mask)188*9356374aSAndroid Build Coastguard Worker void MaskedPointer::ApplyMask(mask_t mask) {
189*9356374aSAndroid Build Coastguard Worker ptr_ = reinterpret_cast<ptr_t>(reinterpret_cast<mask_t>(ptr_) | mask);
190*9356374aSAndroid Build Coastguard Worker }
CheckMask(mask_t mask) const191*9356374aSAndroid Build Coastguard Worker bool MaskedPointer::CheckMask(mask_t mask) const {
192*9356374aSAndroid Build Coastguard Worker return (reinterpret_cast<mask_t>(ptr_) & mask) != 0;
193*9356374aSAndroid Build Coastguard Worker }
194*9356374aSAndroid Build Coastguard Worker
Init()195*9356374aSAndroid Build Coastguard Worker void FlagImpl::Init() {
196*9356374aSAndroid Build Coastguard Worker new (&data_guard_) absl::Mutex;
197*9356374aSAndroid Build Coastguard Worker
198*9356374aSAndroid Build Coastguard Worker auto def_kind = static_cast<FlagDefaultKind>(def_kind_);
199*9356374aSAndroid Build Coastguard Worker
200*9356374aSAndroid Build Coastguard Worker switch (ValueStorageKind()) {
201*9356374aSAndroid Build Coastguard Worker case FlagValueStorageKind::kValueAndInitBit:
202*9356374aSAndroid Build Coastguard Worker case FlagValueStorageKind::kOneWordAtomic: {
203*9356374aSAndroid Build Coastguard Worker alignas(int64_t) std::array<char, sizeof(int64_t)> buf{};
204*9356374aSAndroid Build Coastguard Worker if (def_kind == FlagDefaultKind::kGenFunc) {
205*9356374aSAndroid Build Coastguard Worker (*default_value_.gen_func)(buf.data());
206*9356374aSAndroid Build Coastguard Worker } else {
207*9356374aSAndroid Build Coastguard Worker assert(def_kind != FlagDefaultKind::kDynamicValue);
208*9356374aSAndroid Build Coastguard Worker std::memcpy(buf.data(), &default_value_, Sizeof(op_));
209*9356374aSAndroid Build Coastguard Worker }
210*9356374aSAndroid Build Coastguard Worker if (ValueStorageKind() == FlagValueStorageKind::kValueAndInitBit) {
211*9356374aSAndroid Build Coastguard Worker // We presume here the memory layout of FlagValueAndInitBit struct.
212*9356374aSAndroid Build Coastguard Worker uint8_t initialized = 1;
213*9356374aSAndroid Build Coastguard Worker std::memcpy(buf.data() + Sizeof(op_), &initialized,
214*9356374aSAndroid Build Coastguard Worker sizeof(initialized));
215*9356374aSAndroid Build Coastguard Worker }
216*9356374aSAndroid Build Coastguard Worker // Type can contain valid uninitialized bits, e.g. padding.
217*9356374aSAndroid Build Coastguard Worker ABSL_ANNOTATE_MEMORY_IS_INITIALIZED(buf.data(), buf.size());
218*9356374aSAndroid Build Coastguard Worker OneWordValue().store(absl::bit_cast<int64_t>(buf),
219*9356374aSAndroid Build Coastguard Worker std::memory_order_release);
220*9356374aSAndroid Build Coastguard Worker break;
221*9356374aSAndroid Build Coastguard Worker }
222*9356374aSAndroid Build Coastguard Worker case FlagValueStorageKind::kSequenceLocked: {
223*9356374aSAndroid Build Coastguard Worker // For this storage kind the default_value_ always points to gen_func
224*9356374aSAndroid Build Coastguard Worker // during initialization.
225*9356374aSAndroid Build Coastguard Worker assert(def_kind == FlagDefaultKind::kGenFunc);
226*9356374aSAndroid Build Coastguard Worker (*default_value_.gen_func)(AtomicBufferValue());
227*9356374aSAndroid Build Coastguard Worker break;
228*9356374aSAndroid Build Coastguard Worker }
229*9356374aSAndroid Build Coastguard Worker case FlagValueStorageKind::kHeapAllocated:
230*9356374aSAndroid Build Coastguard Worker // For this storage kind the default_value_ always points to gen_func
231*9356374aSAndroid Build Coastguard Worker // during initialization.
232*9356374aSAndroid Build Coastguard Worker assert(def_kind == FlagDefaultKind::kGenFunc);
233*9356374aSAndroid Build Coastguard Worker // Flag value initially points to the internal buffer.
234*9356374aSAndroid Build Coastguard Worker MaskedPointer ptr_value = PtrStorage().load(std::memory_order_acquire);
235*9356374aSAndroid Build Coastguard Worker (*default_value_.gen_func)(ptr_value.Ptr());
236*9356374aSAndroid Build Coastguard Worker // Default value is a candidate for an unprotected read.
237*9356374aSAndroid Build Coastguard Worker PtrStorage().store(MaskedPointer(ptr_value.Ptr(), true),
238*9356374aSAndroid Build Coastguard Worker std::memory_order_release);
239*9356374aSAndroid Build Coastguard Worker break;
240*9356374aSAndroid Build Coastguard Worker }
241*9356374aSAndroid Build Coastguard Worker seq_lock_.MarkInitialized();
242*9356374aSAndroid Build Coastguard Worker }
243*9356374aSAndroid Build Coastguard Worker
DataGuard() const244*9356374aSAndroid Build Coastguard Worker absl::Mutex* FlagImpl::DataGuard() const {
245*9356374aSAndroid Build Coastguard Worker absl::call_once(const_cast<FlagImpl*>(this)->init_control_, &FlagImpl::Init,
246*9356374aSAndroid Build Coastguard Worker const_cast<FlagImpl*>(this));
247*9356374aSAndroid Build Coastguard Worker
248*9356374aSAndroid Build Coastguard Worker // data_guard_ is initialized inside Init.
249*9356374aSAndroid Build Coastguard Worker return reinterpret_cast<absl::Mutex*>(&data_guard_);
250*9356374aSAndroid Build Coastguard Worker }
251*9356374aSAndroid Build Coastguard Worker
AssertValidType(FlagFastTypeId rhs_type_id,const std::type_info * (* gen_rtti)()) const252*9356374aSAndroid Build Coastguard Worker void FlagImpl::AssertValidType(FlagFastTypeId rhs_type_id,
253*9356374aSAndroid Build Coastguard Worker const std::type_info* (*gen_rtti)()) const {
254*9356374aSAndroid Build Coastguard Worker FlagFastTypeId lhs_type_id = flags_internal::FastTypeId(op_);
255*9356374aSAndroid Build Coastguard Worker
256*9356374aSAndroid Build Coastguard Worker // `rhs_type_id` is the fast type id corresponding to the declaration
257*9356374aSAndroid Build Coastguard Worker // visible at the call site. `lhs_type_id` is the fast type id
258*9356374aSAndroid Build Coastguard Worker // corresponding to the type specified in flag definition. They must match
259*9356374aSAndroid Build Coastguard Worker // for this operation to be well-defined.
260*9356374aSAndroid Build Coastguard Worker if (ABSL_PREDICT_TRUE(lhs_type_id == rhs_type_id)) return;
261*9356374aSAndroid Build Coastguard Worker
262*9356374aSAndroid Build Coastguard Worker const std::type_info* lhs_runtime_type_id =
263*9356374aSAndroid Build Coastguard Worker flags_internal::RuntimeTypeId(op_);
264*9356374aSAndroid Build Coastguard Worker const std::type_info* rhs_runtime_type_id = (*gen_rtti)();
265*9356374aSAndroid Build Coastguard Worker
266*9356374aSAndroid Build Coastguard Worker if (lhs_runtime_type_id == rhs_runtime_type_id) return;
267*9356374aSAndroid Build Coastguard Worker
268*9356374aSAndroid Build Coastguard Worker #ifdef ABSL_INTERNAL_HAS_RTTI
269*9356374aSAndroid Build Coastguard Worker if (*lhs_runtime_type_id == *rhs_runtime_type_id) return;
270*9356374aSAndroid Build Coastguard Worker #endif
271*9356374aSAndroid Build Coastguard Worker
272*9356374aSAndroid Build Coastguard Worker ABSL_INTERNAL_LOG(
273*9356374aSAndroid Build Coastguard Worker FATAL, absl::StrCat("Flag '", Name(),
274*9356374aSAndroid Build Coastguard Worker "' is defined as one type and declared as another"));
275*9356374aSAndroid Build Coastguard Worker }
276*9356374aSAndroid Build Coastguard Worker
MakeInitValue() const277*9356374aSAndroid Build Coastguard Worker std::unique_ptr<void, DynValueDeleter> FlagImpl::MakeInitValue() const {
278*9356374aSAndroid Build Coastguard Worker void* res = nullptr;
279*9356374aSAndroid Build Coastguard Worker switch (DefaultKind()) {
280*9356374aSAndroid Build Coastguard Worker case FlagDefaultKind::kDynamicValue:
281*9356374aSAndroid Build Coastguard Worker res = flags_internal::Clone(op_, default_value_.dynamic_value);
282*9356374aSAndroid Build Coastguard Worker break;
283*9356374aSAndroid Build Coastguard Worker case FlagDefaultKind::kGenFunc:
284*9356374aSAndroid Build Coastguard Worker res = flags_internal::Alloc(op_);
285*9356374aSAndroid Build Coastguard Worker (*default_value_.gen_func)(res);
286*9356374aSAndroid Build Coastguard Worker break;
287*9356374aSAndroid Build Coastguard Worker default:
288*9356374aSAndroid Build Coastguard Worker res = flags_internal::Clone(op_, &default_value_);
289*9356374aSAndroid Build Coastguard Worker break;
290*9356374aSAndroid Build Coastguard Worker }
291*9356374aSAndroid Build Coastguard Worker return {res, DynValueDeleter{op_}};
292*9356374aSAndroid Build Coastguard Worker }
293*9356374aSAndroid Build Coastguard Worker
StoreValue(const void * src,ValueSource source)294*9356374aSAndroid Build Coastguard Worker void FlagImpl::StoreValue(const void* src, ValueSource source) {
295*9356374aSAndroid Build Coastguard Worker switch (ValueStorageKind()) {
296*9356374aSAndroid Build Coastguard Worker case FlagValueStorageKind::kValueAndInitBit:
297*9356374aSAndroid Build Coastguard Worker case FlagValueStorageKind::kOneWordAtomic: {
298*9356374aSAndroid Build Coastguard Worker // Load the current value to avoid setting 'init' bit manually.
299*9356374aSAndroid Build Coastguard Worker int64_t one_word_val = OneWordValue().load(std::memory_order_acquire);
300*9356374aSAndroid Build Coastguard Worker std::memcpy(&one_word_val, src, Sizeof(op_));
301*9356374aSAndroid Build Coastguard Worker OneWordValue().store(one_word_val, std::memory_order_release);
302*9356374aSAndroid Build Coastguard Worker seq_lock_.IncrementModificationCount();
303*9356374aSAndroid Build Coastguard Worker break;
304*9356374aSAndroid Build Coastguard Worker }
305*9356374aSAndroid Build Coastguard Worker case FlagValueStorageKind::kSequenceLocked: {
306*9356374aSAndroid Build Coastguard Worker seq_lock_.Write(AtomicBufferValue(), src, Sizeof(op_));
307*9356374aSAndroid Build Coastguard Worker break;
308*9356374aSAndroid Build Coastguard Worker }
309*9356374aSAndroid Build Coastguard Worker case FlagValueStorageKind::kHeapAllocated:
310*9356374aSAndroid Build Coastguard Worker MaskedPointer ptr_value = PtrStorage().load(std::memory_order_acquire);
311*9356374aSAndroid Build Coastguard Worker
312*9356374aSAndroid Build Coastguard Worker if (ptr_value.IsUnprotectedReadCandidate() && ptr_value.HasBeenRead()) {
313*9356374aSAndroid Build Coastguard Worker // If current value is a candidate for an unprotected read and if it was
314*9356374aSAndroid Build Coastguard Worker // already read at least once, follow up reads (if any) are done without
315*9356374aSAndroid Build Coastguard Worker // mutex protection. We can't guarantee it is safe to reuse this memory
316*9356374aSAndroid Build Coastguard Worker // since it may have been accessed by another thread concurrently, so
317*9356374aSAndroid Build Coastguard Worker // instead we move the memory to a freelist so it can still be safely
318*9356374aSAndroid Build Coastguard Worker // accessed, and allocate a new one for the new value.
319*9356374aSAndroid Build Coastguard Worker AddToFreelist(ptr_value.Ptr());
320*9356374aSAndroid Build Coastguard Worker ptr_value = MaskedPointer(Clone(op_, src), source == kCommandLine);
321*9356374aSAndroid Build Coastguard Worker } else {
322*9356374aSAndroid Build Coastguard Worker // Current value either was set programmatically or was never read.
323*9356374aSAndroid Build Coastguard Worker // We can reuse the memory since all accesses to this value (if any)
324*9356374aSAndroid Build Coastguard Worker // were protected by mutex. That said, if a new value comes from command
325*9356374aSAndroid Build Coastguard Worker // line it now becomes a candidate for an unprotected read.
326*9356374aSAndroid Build Coastguard Worker ptr_value.Set(op_, src, source == kCommandLine);
327*9356374aSAndroid Build Coastguard Worker }
328*9356374aSAndroid Build Coastguard Worker
329*9356374aSAndroid Build Coastguard Worker PtrStorage().store(ptr_value, std::memory_order_release);
330*9356374aSAndroid Build Coastguard Worker seq_lock_.IncrementModificationCount();
331*9356374aSAndroid Build Coastguard Worker break;
332*9356374aSAndroid Build Coastguard Worker }
333*9356374aSAndroid Build Coastguard Worker modified_ = true;
334*9356374aSAndroid Build Coastguard Worker InvokeCallback();
335*9356374aSAndroid Build Coastguard Worker }
336*9356374aSAndroid Build Coastguard Worker
Name() const337*9356374aSAndroid Build Coastguard Worker absl::string_view FlagImpl::Name() const { return name_; }
338*9356374aSAndroid Build Coastguard Worker
Filename() const339*9356374aSAndroid Build Coastguard Worker std::string FlagImpl::Filename() const {
340*9356374aSAndroid Build Coastguard Worker return flags_internal::GetUsageConfig().normalize_filename(filename_);
341*9356374aSAndroid Build Coastguard Worker }
342*9356374aSAndroid Build Coastguard Worker
Help() const343*9356374aSAndroid Build Coastguard Worker std::string FlagImpl::Help() const {
344*9356374aSAndroid Build Coastguard Worker return HelpSourceKind() == FlagHelpKind::kLiteral ? help_.literal
345*9356374aSAndroid Build Coastguard Worker : help_.gen_func();
346*9356374aSAndroid Build Coastguard Worker }
347*9356374aSAndroid Build Coastguard Worker
TypeId() const348*9356374aSAndroid Build Coastguard Worker FlagFastTypeId FlagImpl::TypeId() const {
349*9356374aSAndroid Build Coastguard Worker return flags_internal::FastTypeId(op_);
350*9356374aSAndroid Build Coastguard Worker }
351*9356374aSAndroid Build Coastguard Worker
ModificationCount() const352*9356374aSAndroid Build Coastguard Worker int64_t FlagImpl::ModificationCount() const {
353*9356374aSAndroid Build Coastguard Worker return seq_lock_.ModificationCount();
354*9356374aSAndroid Build Coastguard Worker }
355*9356374aSAndroid Build Coastguard Worker
IsSpecifiedOnCommandLine() const356*9356374aSAndroid Build Coastguard Worker bool FlagImpl::IsSpecifiedOnCommandLine() const {
357*9356374aSAndroid Build Coastguard Worker absl::MutexLock l(DataGuard());
358*9356374aSAndroid Build Coastguard Worker return on_command_line_;
359*9356374aSAndroid Build Coastguard Worker }
360*9356374aSAndroid Build Coastguard Worker
DefaultValue() const361*9356374aSAndroid Build Coastguard Worker std::string FlagImpl::DefaultValue() const {
362*9356374aSAndroid Build Coastguard Worker absl::MutexLock l(DataGuard());
363*9356374aSAndroid Build Coastguard Worker
364*9356374aSAndroid Build Coastguard Worker auto obj = MakeInitValue();
365*9356374aSAndroid Build Coastguard Worker return flags_internal::Unparse(op_, obj.get());
366*9356374aSAndroid Build Coastguard Worker }
367*9356374aSAndroid Build Coastguard Worker
CurrentValue() const368*9356374aSAndroid Build Coastguard Worker std::string FlagImpl::CurrentValue() const {
369*9356374aSAndroid Build Coastguard Worker auto* guard = DataGuard(); // Make sure flag initialized
370*9356374aSAndroid Build Coastguard Worker switch (ValueStorageKind()) {
371*9356374aSAndroid Build Coastguard Worker case FlagValueStorageKind::kValueAndInitBit:
372*9356374aSAndroid Build Coastguard Worker case FlagValueStorageKind::kOneWordAtomic: {
373*9356374aSAndroid Build Coastguard Worker const auto one_word_val =
374*9356374aSAndroid Build Coastguard Worker absl::bit_cast<std::array<char, sizeof(int64_t)>>(
375*9356374aSAndroid Build Coastguard Worker OneWordValue().load(std::memory_order_acquire));
376*9356374aSAndroid Build Coastguard Worker return flags_internal::Unparse(op_, one_word_val.data());
377*9356374aSAndroid Build Coastguard Worker }
378*9356374aSAndroid Build Coastguard Worker case FlagValueStorageKind::kSequenceLocked: {
379*9356374aSAndroid Build Coastguard Worker std::unique_ptr<void, DynValueDeleter> cloned(flags_internal::Alloc(op_),
380*9356374aSAndroid Build Coastguard Worker DynValueDeleter{op_});
381*9356374aSAndroid Build Coastguard Worker ReadSequenceLockedData(cloned.get());
382*9356374aSAndroid Build Coastguard Worker return flags_internal::Unparse(op_, cloned.get());
383*9356374aSAndroid Build Coastguard Worker }
384*9356374aSAndroid Build Coastguard Worker case FlagValueStorageKind::kHeapAllocated: {
385*9356374aSAndroid Build Coastguard Worker absl::MutexLock l(guard);
386*9356374aSAndroid Build Coastguard Worker return flags_internal::Unparse(
387*9356374aSAndroid Build Coastguard Worker op_, PtrStorage().load(std::memory_order_acquire).Ptr());
388*9356374aSAndroid Build Coastguard Worker }
389*9356374aSAndroid Build Coastguard Worker }
390*9356374aSAndroid Build Coastguard Worker
391*9356374aSAndroid Build Coastguard Worker return "";
392*9356374aSAndroid Build Coastguard Worker }
393*9356374aSAndroid Build Coastguard Worker
SetCallback(const FlagCallbackFunc mutation_callback)394*9356374aSAndroid Build Coastguard Worker void FlagImpl::SetCallback(const FlagCallbackFunc mutation_callback) {
395*9356374aSAndroid Build Coastguard Worker absl::MutexLock l(DataGuard());
396*9356374aSAndroid Build Coastguard Worker
397*9356374aSAndroid Build Coastguard Worker if (callback_ == nullptr) {
398*9356374aSAndroid Build Coastguard Worker callback_ = new FlagCallback;
399*9356374aSAndroid Build Coastguard Worker }
400*9356374aSAndroid Build Coastguard Worker callback_->func = mutation_callback;
401*9356374aSAndroid Build Coastguard Worker
402*9356374aSAndroid Build Coastguard Worker InvokeCallback();
403*9356374aSAndroid Build Coastguard Worker }
404*9356374aSAndroid Build Coastguard Worker
InvokeCallback() const405*9356374aSAndroid Build Coastguard Worker void FlagImpl::InvokeCallback() const {
406*9356374aSAndroid Build Coastguard Worker if (!callback_) return;
407*9356374aSAndroid Build Coastguard Worker
408*9356374aSAndroid Build Coastguard Worker // Make a copy of the C-style function pointer that we are about to invoke
409*9356374aSAndroid Build Coastguard Worker // before we release the lock guarding it.
410*9356374aSAndroid Build Coastguard Worker FlagCallbackFunc cb = callback_->func;
411*9356374aSAndroid Build Coastguard Worker
412*9356374aSAndroid Build Coastguard Worker // If the flag has a mutation callback this function invokes it. While the
413*9356374aSAndroid Build Coastguard Worker // callback is being invoked the primary flag's mutex is unlocked and it is
414*9356374aSAndroid Build Coastguard Worker // re-locked back after call to callback is completed. Callback invocation is
415*9356374aSAndroid Build Coastguard Worker // guarded by flag's secondary mutex instead which prevents concurrent
416*9356374aSAndroid Build Coastguard Worker // callback invocation. Note that it is possible for other thread to grab the
417*9356374aSAndroid Build Coastguard Worker // primary lock and update flag's value at any time during the callback
418*9356374aSAndroid Build Coastguard Worker // invocation. This is by design. Callback can get a value of the flag if
419*9356374aSAndroid Build Coastguard Worker // necessary, but it might be different from the value initiated the callback
420*9356374aSAndroid Build Coastguard Worker // and it also can be different by the time the callback invocation is
421*9356374aSAndroid Build Coastguard Worker // completed. Requires that *primary_lock be held in exclusive mode; it may be
422*9356374aSAndroid Build Coastguard Worker // released and reacquired by the implementation.
423*9356374aSAndroid Build Coastguard Worker MutexRelock relock(*DataGuard());
424*9356374aSAndroid Build Coastguard Worker absl::MutexLock lock(&callback_->guard);
425*9356374aSAndroid Build Coastguard Worker cb();
426*9356374aSAndroid Build Coastguard Worker }
427*9356374aSAndroid Build Coastguard Worker
SaveState()428*9356374aSAndroid Build Coastguard Worker std::unique_ptr<FlagStateInterface> FlagImpl::SaveState() {
429*9356374aSAndroid Build Coastguard Worker absl::MutexLock l(DataGuard());
430*9356374aSAndroid Build Coastguard Worker
431*9356374aSAndroid Build Coastguard Worker bool modified = modified_;
432*9356374aSAndroid Build Coastguard Worker bool on_command_line = on_command_line_;
433*9356374aSAndroid Build Coastguard Worker switch (ValueStorageKind()) {
434*9356374aSAndroid Build Coastguard Worker case FlagValueStorageKind::kValueAndInitBit:
435*9356374aSAndroid Build Coastguard Worker case FlagValueStorageKind::kOneWordAtomic: {
436*9356374aSAndroid Build Coastguard Worker return absl::make_unique<FlagState>(
437*9356374aSAndroid Build Coastguard Worker *this, OneWordValue().load(std::memory_order_acquire), modified,
438*9356374aSAndroid Build Coastguard Worker on_command_line, ModificationCount());
439*9356374aSAndroid Build Coastguard Worker }
440*9356374aSAndroid Build Coastguard Worker case FlagValueStorageKind::kSequenceLocked: {
441*9356374aSAndroid Build Coastguard Worker void* cloned = flags_internal::Alloc(op_);
442*9356374aSAndroid Build Coastguard Worker // Read is guaranteed to be successful because we hold the lock.
443*9356374aSAndroid Build Coastguard Worker bool success =
444*9356374aSAndroid Build Coastguard Worker seq_lock_.TryRead(cloned, AtomicBufferValue(), Sizeof(op_));
445*9356374aSAndroid Build Coastguard Worker assert(success);
446*9356374aSAndroid Build Coastguard Worker static_cast<void>(success);
447*9356374aSAndroid Build Coastguard Worker return absl::make_unique<FlagState>(*this, cloned, modified,
448*9356374aSAndroid Build Coastguard Worker on_command_line, ModificationCount());
449*9356374aSAndroid Build Coastguard Worker }
450*9356374aSAndroid Build Coastguard Worker case FlagValueStorageKind::kHeapAllocated: {
451*9356374aSAndroid Build Coastguard Worker return absl::make_unique<FlagState>(
452*9356374aSAndroid Build Coastguard Worker *this,
453*9356374aSAndroid Build Coastguard Worker flags_internal::Clone(
454*9356374aSAndroid Build Coastguard Worker op_, PtrStorage().load(std::memory_order_acquire).Ptr()),
455*9356374aSAndroid Build Coastguard Worker modified, on_command_line, ModificationCount());
456*9356374aSAndroid Build Coastguard Worker }
457*9356374aSAndroid Build Coastguard Worker }
458*9356374aSAndroid Build Coastguard Worker return nullptr;
459*9356374aSAndroid Build Coastguard Worker }
460*9356374aSAndroid Build Coastguard Worker
RestoreState(const FlagState & flag_state)461*9356374aSAndroid Build Coastguard Worker bool FlagImpl::RestoreState(const FlagState& flag_state) {
462*9356374aSAndroid Build Coastguard Worker absl::MutexLock l(DataGuard());
463*9356374aSAndroid Build Coastguard Worker if (flag_state.counter_ == ModificationCount()) {
464*9356374aSAndroid Build Coastguard Worker return false;
465*9356374aSAndroid Build Coastguard Worker }
466*9356374aSAndroid Build Coastguard Worker
467*9356374aSAndroid Build Coastguard Worker switch (ValueStorageKind()) {
468*9356374aSAndroid Build Coastguard Worker case FlagValueStorageKind::kValueAndInitBit:
469*9356374aSAndroid Build Coastguard Worker case FlagValueStorageKind::kOneWordAtomic:
470*9356374aSAndroid Build Coastguard Worker StoreValue(&flag_state.value_.one_word, kProgrammaticChange);
471*9356374aSAndroid Build Coastguard Worker break;
472*9356374aSAndroid Build Coastguard Worker case FlagValueStorageKind::kSequenceLocked:
473*9356374aSAndroid Build Coastguard Worker case FlagValueStorageKind::kHeapAllocated:
474*9356374aSAndroid Build Coastguard Worker StoreValue(flag_state.value_.heap_allocated, kProgrammaticChange);
475*9356374aSAndroid Build Coastguard Worker break;
476*9356374aSAndroid Build Coastguard Worker }
477*9356374aSAndroid Build Coastguard Worker
478*9356374aSAndroid Build Coastguard Worker modified_ = flag_state.modified_;
479*9356374aSAndroid Build Coastguard Worker on_command_line_ = flag_state.on_command_line_;
480*9356374aSAndroid Build Coastguard Worker
481*9356374aSAndroid Build Coastguard Worker return true;
482*9356374aSAndroid Build Coastguard Worker }
483*9356374aSAndroid Build Coastguard Worker
484*9356374aSAndroid Build Coastguard Worker template <typename StorageT>
OffsetValue() const485*9356374aSAndroid Build Coastguard Worker StorageT* FlagImpl::OffsetValue() const {
486*9356374aSAndroid Build Coastguard Worker char* p = reinterpret_cast<char*>(const_cast<FlagImpl*>(this));
487*9356374aSAndroid Build Coastguard Worker // The offset is deduced via Flag value type specific op_.
488*9356374aSAndroid Build Coastguard Worker ptrdiff_t offset = flags_internal::ValueOffset(op_);
489*9356374aSAndroid Build Coastguard Worker
490*9356374aSAndroid Build Coastguard Worker return reinterpret_cast<StorageT*>(p + offset);
491*9356374aSAndroid Build Coastguard Worker }
492*9356374aSAndroid Build Coastguard Worker
AtomicBufferValue() const493*9356374aSAndroid Build Coastguard Worker std::atomic<uint64_t>* FlagImpl::AtomicBufferValue() const {
494*9356374aSAndroid Build Coastguard Worker assert(ValueStorageKind() == FlagValueStorageKind::kSequenceLocked);
495*9356374aSAndroid Build Coastguard Worker return OffsetValue<std::atomic<uint64_t>>();
496*9356374aSAndroid Build Coastguard Worker }
497*9356374aSAndroid Build Coastguard Worker
OneWordValue() const498*9356374aSAndroid Build Coastguard Worker std::atomic<int64_t>& FlagImpl::OneWordValue() const {
499*9356374aSAndroid Build Coastguard Worker assert(ValueStorageKind() == FlagValueStorageKind::kOneWordAtomic ||
500*9356374aSAndroid Build Coastguard Worker ValueStorageKind() == FlagValueStorageKind::kValueAndInitBit);
501*9356374aSAndroid Build Coastguard Worker return OffsetValue<FlagOneWordValue>()->value;
502*9356374aSAndroid Build Coastguard Worker }
503*9356374aSAndroid Build Coastguard Worker
PtrStorage() const504*9356374aSAndroid Build Coastguard Worker std::atomic<MaskedPointer>& FlagImpl::PtrStorage() const {
505*9356374aSAndroid Build Coastguard Worker assert(ValueStorageKind() == FlagValueStorageKind::kHeapAllocated);
506*9356374aSAndroid Build Coastguard Worker return OffsetValue<FlagMaskedPointerValue>()->value;
507*9356374aSAndroid Build Coastguard Worker }
508*9356374aSAndroid Build Coastguard Worker
509*9356374aSAndroid Build Coastguard Worker // Attempts to parse supplied `value` string using parsing routine in the `flag`
510*9356374aSAndroid Build Coastguard Worker // argument. If parsing successful, this function replaces the dst with newly
511*9356374aSAndroid Build Coastguard Worker // parsed value. In case if any error is encountered in either step, the error
512*9356374aSAndroid Build Coastguard Worker // message is stored in 'err'
TryParse(absl::string_view value,std::string & err) const513*9356374aSAndroid Build Coastguard Worker std::unique_ptr<void, DynValueDeleter> FlagImpl::TryParse(
514*9356374aSAndroid Build Coastguard Worker absl::string_view value, std::string& err) const {
515*9356374aSAndroid Build Coastguard Worker std::unique_ptr<void, DynValueDeleter> tentative_value = MakeInitValue();
516*9356374aSAndroid Build Coastguard Worker
517*9356374aSAndroid Build Coastguard Worker std::string parse_err;
518*9356374aSAndroid Build Coastguard Worker if (!flags_internal::Parse(op_, value, tentative_value.get(), &parse_err)) {
519*9356374aSAndroid Build Coastguard Worker absl::string_view err_sep = parse_err.empty() ? "" : "; ";
520*9356374aSAndroid Build Coastguard Worker err = absl::StrCat("Illegal value '", value, "' specified for flag '",
521*9356374aSAndroid Build Coastguard Worker Name(), "'", err_sep, parse_err);
522*9356374aSAndroid Build Coastguard Worker return nullptr;
523*9356374aSAndroid Build Coastguard Worker }
524*9356374aSAndroid Build Coastguard Worker
525*9356374aSAndroid Build Coastguard Worker return tentative_value;
526*9356374aSAndroid Build Coastguard Worker }
527*9356374aSAndroid Build Coastguard Worker
Read(void * dst) const528*9356374aSAndroid Build Coastguard Worker void FlagImpl::Read(void* dst) const {
529*9356374aSAndroid Build Coastguard Worker auto* guard = DataGuard(); // Make sure flag initialized
530*9356374aSAndroid Build Coastguard Worker switch (ValueStorageKind()) {
531*9356374aSAndroid Build Coastguard Worker case FlagValueStorageKind::kValueAndInitBit:
532*9356374aSAndroid Build Coastguard Worker case FlagValueStorageKind::kOneWordAtomic: {
533*9356374aSAndroid Build Coastguard Worker const int64_t one_word_val =
534*9356374aSAndroid Build Coastguard Worker OneWordValue().load(std::memory_order_acquire);
535*9356374aSAndroid Build Coastguard Worker std::memcpy(dst, &one_word_val, Sizeof(op_));
536*9356374aSAndroid Build Coastguard Worker break;
537*9356374aSAndroid Build Coastguard Worker }
538*9356374aSAndroid Build Coastguard Worker case FlagValueStorageKind::kSequenceLocked: {
539*9356374aSAndroid Build Coastguard Worker ReadSequenceLockedData(dst);
540*9356374aSAndroid Build Coastguard Worker break;
541*9356374aSAndroid Build Coastguard Worker }
542*9356374aSAndroid Build Coastguard Worker case FlagValueStorageKind::kHeapAllocated: {
543*9356374aSAndroid Build Coastguard Worker absl::MutexLock l(guard);
544*9356374aSAndroid Build Coastguard Worker MaskedPointer ptr_value = PtrStorage().load(std::memory_order_acquire);
545*9356374aSAndroid Build Coastguard Worker
546*9356374aSAndroid Build Coastguard Worker flags_internal::CopyConstruct(op_, ptr_value.Ptr(), dst);
547*9356374aSAndroid Build Coastguard Worker
548*9356374aSAndroid Build Coastguard Worker // For unprotected read candidates, mark that the value as has been read.
549*9356374aSAndroid Build Coastguard Worker if (ptr_value.IsUnprotectedReadCandidate() && !ptr_value.HasBeenRead()) {
550*9356374aSAndroid Build Coastguard Worker ptr_value.MarkAsRead();
551*9356374aSAndroid Build Coastguard Worker PtrStorage().store(ptr_value, std::memory_order_release);
552*9356374aSAndroid Build Coastguard Worker }
553*9356374aSAndroid Build Coastguard Worker break;
554*9356374aSAndroid Build Coastguard Worker }
555*9356374aSAndroid Build Coastguard Worker }
556*9356374aSAndroid Build Coastguard Worker }
557*9356374aSAndroid Build Coastguard Worker
ReadOneWord() const558*9356374aSAndroid Build Coastguard Worker int64_t FlagImpl::ReadOneWord() const {
559*9356374aSAndroid Build Coastguard Worker assert(ValueStorageKind() == FlagValueStorageKind::kOneWordAtomic ||
560*9356374aSAndroid Build Coastguard Worker ValueStorageKind() == FlagValueStorageKind::kValueAndInitBit);
561*9356374aSAndroid Build Coastguard Worker auto* guard = DataGuard(); // Make sure flag initialized
562*9356374aSAndroid Build Coastguard Worker (void)guard;
563*9356374aSAndroid Build Coastguard Worker return OneWordValue().load(std::memory_order_acquire);
564*9356374aSAndroid Build Coastguard Worker }
565*9356374aSAndroid Build Coastguard Worker
ReadOneBool() const566*9356374aSAndroid Build Coastguard Worker bool FlagImpl::ReadOneBool() const {
567*9356374aSAndroid Build Coastguard Worker assert(ValueStorageKind() == FlagValueStorageKind::kValueAndInitBit);
568*9356374aSAndroid Build Coastguard Worker auto* guard = DataGuard(); // Make sure flag initialized
569*9356374aSAndroid Build Coastguard Worker (void)guard;
570*9356374aSAndroid Build Coastguard Worker return absl::bit_cast<FlagValueAndInitBit<bool>>(
571*9356374aSAndroid Build Coastguard Worker OneWordValue().load(std::memory_order_acquire))
572*9356374aSAndroid Build Coastguard Worker .value;
573*9356374aSAndroid Build Coastguard Worker }
574*9356374aSAndroid Build Coastguard Worker
ReadSequenceLockedData(void * dst) const575*9356374aSAndroid Build Coastguard Worker void FlagImpl::ReadSequenceLockedData(void* dst) const {
576*9356374aSAndroid Build Coastguard Worker size_t size = Sizeof(op_);
577*9356374aSAndroid Build Coastguard Worker // Attempt to read using the sequence lock.
578*9356374aSAndroid Build Coastguard Worker if (ABSL_PREDICT_TRUE(seq_lock_.TryRead(dst, AtomicBufferValue(), size))) {
579*9356374aSAndroid Build Coastguard Worker return;
580*9356374aSAndroid Build Coastguard Worker }
581*9356374aSAndroid Build Coastguard Worker // We failed due to contention. Acquire the lock to prevent contention
582*9356374aSAndroid Build Coastguard Worker // and try again.
583*9356374aSAndroid Build Coastguard Worker absl::ReaderMutexLock l(DataGuard());
584*9356374aSAndroid Build Coastguard Worker bool success = seq_lock_.TryRead(dst, AtomicBufferValue(), size);
585*9356374aSAndroid Build Coastguard Worker assert(success);
586*9356374aSAndroid Build Coastguard Worker static_cast<void>(success);
587*9356374aSAndroid Build Coastguard Worker }
588*9356374aSAndroid Build Coastguard Worker
Write(const void * src)589*9356374aSAndroid Build Coastguard Worker void FlagImpl::Write(const void* src) {
590*9356374aSAndroid Build Coastguard Worker absl::MutexLock l(DataGuard());
591*9356374aSAndroid Build Coastguard Worker
592*9356374aSAndroid Build Coastguard Worker if (ShouldValidateFlagValue(flags_internal::FastTypeId(op_))) {
593*9356374aSAndroid Build Coastguard Worker std::unique_ptr<void, DynValueDeleter> obj{flags_internal::Clone(op_, src),
594*9356374aSAndroid Build Coastguard Worker DynValueDeleter{op_}};
595*9356374aSAndroid Build Coastguard Worker std::string ignored_error;
596*9356374aSAndroid Build Coastguard Worker std::string src_as_str = flags_internal::Unparse(op_, src);
597*9356374aSAndroid Build Coastguard Worker if (!flags_internal::Parse(op_, src_as_str, obj.get(), &ignored_error)) {
598*9356374aSAndroid Build Coastguard Worker ABSL_INTERNAL_LOG(ERROR, absl::StrCat("Attempt to set flag '", Name(),
599*9356374aSAndroid Build Coastguard Worker "' to invalid value ", src_as_str));
600*9356374aSAndroid Build Coastguard Worker }
601*9356374aSAndroid Build Coastguard Worker }
602*9356374aSAndroid Build Coastguard Worker
603*9356374aSAndroid Build Coastguard Worker StoreValue(src, kProgrammaticChange);
604*9356374aSAndroid Build Coastguard Worker }
605*9356374aSAndroid Build Coastguard Worker
606*9356374aSAndroid Build Coastguard Worker // Sets the value of the flag based on specified string `value`. If the flag
607*9356374aSAndroid Build Coastguard Worker // was successfully set to new value, it returns true. Otherwise, sets `err`
608*9356374aSAndroid Build Coastguard Worker // to indicate the error, leaves the flag unchanged, and returns false. There
609*9356374aSAndroid Build Coastguard Worker // are three ways to set the flag's value:
610*9356374aSAndroid Build Coastguard Worker // * Update the current flag value
611*9356374aSAndroid Build Coastguard Worker // * Update the flag's default value
612*9356374aSAndroid Build Coastguard Worker // * Update the current flag value if it was never set before
613*9356374aSAndroid Build Coastguard Worker // The mode is selected based on 'set_mode' parameter.
ParseFrom(absl::string_view value,FlagSettingMode set_mode,ValueSource source,std::string & err)614*9356374aSAndroid Build Coastguard Worker bool FlagImpl::ParseFrom(absl::string_view value, FlagSettingMode set_mode,
615*9356374aSAndroid Build Coastguard Worker ValueSource source, std::string& err) {
616*9356374aSAndroid Build Coastguard Worker absl::MutexLock l(DataGuard());
617*9356374aSAndroid Build Coastguard Worker
618*9356374aSAndroid Build Coastguard Worker switch (set_mode) {
619*9356374aSAndroid Build Coastguard Worker case SET_FLAGS_VALUE: {
620*9356374aSAndroid Build Coastguard Worker // set or modify the flag's value
621*9356374aSAndroid Build Coastguard Worker auto tentative_value = TryParse(value, err);
622*9356374aSAndroid Build Coastguard Worker if (!tentative_value) return false;
623*9356374aSAndroid Build Coastguard Worker
624*9356374aSAndroid Build Coastguard Worker StoreValue(tentative_value.get(), source);
625*9356374aSAndroid Build Coastguard Worker
626*9356374aSAndroid Build Coastguard Worker if (source == kCommandLine) {
627*9356374aSAndroid Build Coastguard Worker on_command_line_ = true;
628*9356374aSAndroid Build Coastguard Worker }
629*9356374aSAndroid Build Coastguard Worker break;
630*9356374aSAndroid Build Coastguard Worker }
631*9356374aSAndroid Build Coastguard Worker case SET_FLAG_IF_DEFAULT: {
632*9356374aSAndroid Build Coastguard Worker // set the flag's value, but only if it hasn't been set by someone else
633*9356374aSAndroid Build Coastguard Worker if (modified_) {
634*9356374aSAndroid Build Coastguard Worker // TODO(rogeeff): review and fix this semantic. Currently we do not fail
635*9356374aSAndroid Build Coastguard Worker // in this case if flag is modified. This is misleading since the flag's
636*9356374aSAndroid Build Coastguard Worker // value is not updated even though we return true.
637*9356374aSAndroid Build Coastguard Worker // *err = absl::StrCat(Name(), " is already set to ",
638*9356374aSAndroid Build Coastguard Worker // CurrentValue(), "\n");
639*9356374aSAndroid Build Coastguard Worker // return false;
640*9356374aSAndroid Build Coastguard Worker return true;
641*9356374aSAndroid Build Coastguard Worker }
642*9356374aSAndroid Build Coastguard Worker auto tentative_value = TryParse(value, err);
643*9356374aSAndroid Build Coastguard Worker if (!tentative_value) return false;
644*9356374aSAndroid Build Coastguard Worker
645*9356374aSAndroid Build Coastguard Worker StoreValue(tentative_value.get(), source);
646*9356374aSAndroid Build Coastguard Worker break;
647*9356374aSAndroid Build Coastguard Worker }
648*9356374aSAndroid Build Coastguard Worker case SET_FLAGS_DEFAULT: {
649*9356374aSAndroid Build Coastguard Worker auto tentative_value = TryParse(value, err);
650*9356374aSAndroid Build Coastguard Worker if (!tentative_value) return false;
651*9356374aSAndroid Build Coastguard Worker
652*9356374aSAndroid Build Coastguard Worker if (DefaultKind() == FlagDefaultKind::kDynamicValue) {
653*9356374aSAndroid Build Coastguard Worker void* old_value = default_value_.dynamic_value;
654*9356374aSAndroid Build Coastguard Worker default_value_.dynamic_value = tentative_value.release();
655*9356374aSAndroid Build Coastguard Worker tentative_value.reset(old_value);
656*9356374aSAndroid Build Coastguard Worker } else {
657*9356374aSAndroid Build Coastguard Worker default_value_.dynamic_value = tentative_value.release();
658*9356374aSAndroid Build Coastguard Worker def_kind_ = static_cast<uint8_t>(FlagDefaultKind::kDynamicValue);
659*9356374aSAndroid Build Coastguard Worker }
660*9356374aSAndroid Build Coastguard Worker
661*9356374aSAndroid Build Coastguard Worker if (!modified_) {
662*9356374aSAndroid Build Coastguard Worker // Need to set both default value *and* current, in this case.
663*9356374aSAndroid Build Coastguard Worker StoreValue(default_value_.dynamic_value, source);
664*9356374aSAndroid Build Coastguard Worker modified_ = false;
665*9356374aSAndroid Build Coastguard Worker }
666*9356374aSAndroid Build Coastguard Worker break;
667*9356374aSAndroid Build Coastguard Worker }
668*9356374aSAndroid Build Coastguard Worker }
669*9356374aSAndroid Build Coastguard Worker
670*9356374aSAndroid Build Coastguard Worker return true;
671*9356374aSAndroid Build Coastguard Worker }
672*9356374aSAndroid Build Coastguard Worker
CheckDefaultValueParsingRoundtrip() const673*9356374aSAndroid Build Coastguard Worker void FlagImpl::CheckDefaultValueParsingRoundtrip() const {
674*9356374aSAndroid Build Coastguard Worker std::string v = DefaultValue();
675*9356374aSAndroid Build Coastguard Worker
676*9356374aSAndroid Build Coastguard Worker absl::MutexLock lock(DataGuard());
677*9356374aSAndroid Build Coastguard Worker
678*9356374aSAndroid Build Coastguard Worker auto dst = MakeInitValue();
679*9356374aSAndroid Build Coastguard Worker std::string error;
680*9356374aSAndroid Build Coastguard Worker if (!flags_internal::Parse(op_, v, dst.get(), &error)) {
681*9356374aSAndroid Build Coastguard Worker ABSL_INTERNAL_LOG(
682*9356374aSAndroid Build Coastguard Worker FATAL,
683*9356374aSAndroid Build Coastguard Worker absl::StrCat("Flag ", Name(), " (from ", Filename(),
684*9356374aSAndroid Build Coastguard Worker "): string form of default value '", v,
685*9356374aSAndroid Build Coastguard Worker "' could not be parsed; error=", error));
686*9356374aSAndroid Build Coastguard Worker }
687*9356374aSAndroid Build Coastguard Worker
688*9356374aSAndroid Build Coastguard Worker // We do not compare dst to def since parsing/unparsing may make
689*9356374aSAndroid Build Coastguard Worker // small changes, e.g., precision loss for floating point types.
690*9356374aSAndroid Build Coastguard Worker }
691*9356374aSAndroid Build Coastguard Worker
ValidateInputValue(absl::string_view value) const692*9356374aSAndroid Build Coastguard Worker bool FlagImpl::ValidateInputValue(absl::string_view value) const {
693*9356374aSAndroid Build Coastguard Worker absl::MutexLock l(DataGuard());
694*9356374aSAndroid Build Coastguard Worker
695*9356374aSAndroid Build Coastguard Worker auto obj = MakeInitValue();
696*9356374aSAndroid Build Coastguard Worker std::string ignored_error;
697*9356374aSAndroid Build Coastguard Worker return flags_internal::Parse(op_, value, obj.get(), &ignored_error);
698*9356374aSAndroid Build Coastguard Worker }
699*9356374aSAndroid Build Coastguard Worker
700*9356374aSAndroid Build Coastguard Worker } // namespace flags_internal
701*9356374aSAndroid Build Coastguard Worker ABSL_NAMESPACE_END
702*9356374aSAndroid Build Coastguard Worker } // namespace absl
703