Export of internal Abseil changes
-- 972333fe1e43427849b8a634aa35061e81be3642 by Abseil Team <absl-team@google.com>: Replace deprecated thread annotations macros. PiperOrigin-RevId: 267332619 -- 7039c6dc499a31c372b4872eda0772455931c360 by Gennadiy Rozental <rogeeff@google.com>: Internal change PiperOrigin-RevId: 267220271 -- a3f524d2afc2535686f206a7ce06961016349d7a by Abseil Team <absl-team@google.com>: Factor kernel_timeout out of synchronization. PiperOrigin-RevId: 267217304 -- 90287de4114ef9a06cafe50256a2d03349772c21 by Abseil Team <absl-team@google.com>: Fixed comment typo. PiperOrigin-RevId: 267198532 -- d312c1a1e52aeca1871ff0deead416d09a7f237e by Gennadiy Rozental <rogeeff@google.com>: Internal change PiperOrigin-RevId: 267185804 GitOrigin-RevId: 972333fe1e43427849b8a634aa35061e81be3642 Change-Id: Ia8a2f877c57cef9854aad48f1753af872fc04dc8
This commit is contained in:
parent
eb6b7bd23b
commit
83c1d65c90
27 changed files with 282 additions and 377 deletions
|
@ -30,11 +30,11 @@ absl::once_flag once;
|
||||||
|
|
||||||
ABSL_CONST_INIT Mutex counters_mu(absl::kConstInit);
|
ABSL_CONST_INIT Mutex counters_mu(absl::kConstInit);
|
||||||
|
|
||||||
int running_thread_count GUARDED_BY(counters_mu) = 0;
|
int running_thread_count ABSL_GUARDED_BY(counters_mu) = 0;
|
||||||
int call_once_invoke_count GUARDED_BY(counters_mu) = 0;
|
int call_once_invoke_count ABSL_GUARDED_BY(counters_mu) = 0;
|
||||||
int call_once_finished_count GUARDED_BY(counters_mu) = 0;
|
int call_once_finished_count ABSL_GUARDED_BY(counters_mu) = 0;
|
||||||
int call_once_return_count GUARDED_BY(counters_mu) = 0;
|
int call_once_return_count ABSL_GUARDED_BY(counters_mu) = 0;
|
||||||
bool done_blocking GUARDED_BY(counters_mu) = false;
|
bool done_blocking ABSL_GUARDED_BY(counters_mu) = false;
|
||||||
|
|
||||||
// Function to be called from absl::call_once. Waits for a notification.
|
// Function to be called from absl::call_once. Waits for a notification.
|
||||||
void WaitAndIncrement() {
|
void WaitAndIncrement() {
|
||||||
|
@ -60,7 +60,7 @@ void ThreadBody() {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Returns true if all threads are set up for the test.
|
// Returns true if all threads are set up for the test.
|
||||||
bool ThreadsAreSetup(void*) EXCLUSIVE_LOCKS_REQUIRED(counters_mu) {
|
bool ThreadsAreSetup(void*) ABSL_EXCLUSIVE_LOCKS_REQUIRED(counters_mu) {
|
||||||
// All ten threads must be running, and WaitAndIncrement should be blocked.
|
// All ten threads must be running, and WaitAndIncrement should be blocked.
|
||||||
return running_thread_count == 10 && call_once_invoke_count == 1;
|
return running_thread_count == 10 && call_once_invoke_count == 1;
|
||||||
}
|
}
|
||||||
|
|
|
@ -203,9 +203,9 @@ struct LowLevelAlloc::Arena {
|
||||||
|
|
||||||
base_internal::SpinLock mu;
|
base_internal::SpinLock mu;
|
||||||
// Head of free list, sorted by address
|
// Head of free list, sorted by address
|
||||||
AllocList freelist GUARDED_BY(mu);
|
AllocList freelist ABSL_GUARDED_BY(mu);
|
||||||
// Count of allocated blocks
|
// Count of allocated blocks
|
||||||
int32_t allocation_count GUARDED_BY(mu);
|
int32_t allocation_count ABSL_GUARDED_BY(mu);
|
||||||
// flags passed to NewArena
|
// flags passed to NewArena
|
||||||
const uint32_t flags;
|
const uint32_t flags;
|
||||||
// Result of sysconf(_SC_PAGESIZE)
|
// Result of sysconf(_SC_PAGESIZE)
|
||||||
|
@ -215,7 +215,7 @@ struct LowLevelAlloc::Arena {
|
||||||
// Smallest allocation block size
|
// Smallest allocation block size
|
||||||
const size_t min_size;
|
const size_t min_size;
|
||||||
// PRNG state
|
// PRNG state
|
||||||
uint32_t random GUARDED_BY(mu);
|
uint32_t random ABSL_GUARDED_BY(mu);
|
||||||
};
|
};
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
@ -275,10 +275,10 @@ static const uintptr_t kMagicAllocated = 0x4c833e95U;
|
||||||
static const uintptr_t kMagicUnallocated = ~kMagicAllocated;
|
static const uintptr_t kMagicUnallocated = ~kMagicAllocated;
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
class SCOPED_LOCKABLE ArenaLock {
|
class ABSL_SCOPED_LOCKABLE ArenaLock {
|
||||||
public:
|
public:
|
||||||
explicit ArenaLock(LowLevelAlloc::Arena *arena)
|
explicit ArenaLock(LowLevelAlloc::Arena *arena)
|
||||||
EXCLUSIVE_LOCK_FUNCTION(arena->mu)
|
ABSL_EXCLUSIVE_LOCK_FUNCTION(arena->mu)
|
||||||
: arena_(arena) {
|
: arena_(arena) {
|
||||||
#ifndef ABSL_LOW_LEVEL_ALLOC_ASYNC_SIGNAL_SAFE_MISSING
|
#ifndef ABSL_LOW_LEVEL_ALLOC_ASYNC_SIGNAL_SAFE_MISSING
|
||||||
if ((arena->flags & LowLevelAlloc::kAsyncSignalSafe) != 0) {
|
if ((arena->flags & LowLevelAlloc::kAsyncSignalSafe) != 0) {
|
||||||
|
@ -290,7 +290,7 @@ class SCOPED_LOCKABLE ArenaLock {
|
||||||
arena_->mu.Lock();
|
arena_->mu.Lock();
|
||||||
}
|
}
|
||||||
~ArenaLock() { ABSL_RAW_CHECK(left_, "haven't left Arena region"); }
|
~ArenaLock() { ABSL_RAW_CHECK(left_, "haven't left Arena region"); }
|
||||||
void Leave() UNLOCK_FUNCTION() {
|
void Leave() ABSL_UNLOCK_FUNCTION() {
|
||||||
arena_->mu.Unlock();
|
arena_->mu.Unlock();
|
||||||
#ifndef ABSL_LOW_LEVEL_ALLOC_ASYNC_SIGNAL_SAFE_MISSING
|
#ifndef ABSL_LOW_LEVEL_ALLOC_ASYNC_SIGNAL_SAFE_MISSING
|
||||||
if (mask_valid_) {
|
if (mask_valid_) {
|
||||||
|
|
|
@ -48,7 +48,7 @@
|
||||||
namespace absl {
|
namespace absl {
|
||||||
namespace base_internal {
|
namespace base_internal {
|
||||||
|
|
||||||
class LOCKABLE SpinLock {
|
class ABSL_LOCKABLE SpinLock {
|
||||||
public:
|
public:
|
||||||
SpinLock() : lockword_(kSpinLockCooperative) {
|
SpinLock() : lockword_(kSpinLockCooperative) {
|
||||||
ABSL_TSAN_MUTEX_CREATE(this, __tsan_mutex_not_static);
|
ABSL_TSAN_MUTEX_CREATE(this, __tsan_mutex_not_static);
|
||||||
|
@ -79,7 +79,7 @@ class LOCKABLE SpinLock {
|
||||||
~SpinLock() { ABSL_TSAN_MUTEX_DESTROY(this, __tsan_mutex_not_static); }
|
~SpinLock() { ABSL_TSAN_MUTEX_DESTROY(this, __tsan_mutex_not_static); }
|
||||||
|
|
||||||
// Acquire this SpinLock.
|
// Acquire this SpinLock.
|
||||||
inline void Lock() EXCLUSIVE_LOCK_FUNCTION() {
|
inline void Lock() ABSL_EXCLUSIVE_LOCK_FUNCTION() {
|
||||||
ABSL_TSAN_MUTEX_PRE_LOCK(this, 0);
|
ABSL_TSAN_MUTEX_PRE_LOCK(this, 0);
|
||||||
if (!TryLockImpl()) {
|
if (!TryLockImpl()) {
|
||||||
SlowLock();
|
SlowLock();
|
||||||
|
@ -91,7 +91,7 @@ class LOCKABLE SpinLock {
|
||||||
// acquisition was successful. If the lock was not acquired, false is
|
// acquisition was successful. If the lock was not acquired, false is
|
||||||
// returned. If this SpinLock is free at the time of the call, TryLock
|
// returned. If this SpinLock is free at the time of the call, TryLock
|
||||||
// will return true with high probability.
|
// will return true with high probability.
|
||||||
inline bool TryLock() EXCLUSIVE_TRYLOCK_FUNCTION(true) {
|
inline bool TryLock() ABSL_EXCLUSIVE_TRYLOCK_FUNCTION(true) {
|
||||||
ABSL_TSAN_MUTEX_PRE_LOCK(this, __tsan_mutex_try_lock);
|
ABSL_TSAN_MUTEX_PRE_LOCK(this, __tsan_mutex_try_lock);
|
||||||
bool res = TryLockImpl();
|
bool res = TryLockImpl();
|
||||||
ABSL_TSAN_MUTEX_POST_LOCK(
|
ABSL_TSAN_MUTEX_POST_LOCK(
|
||||||
|
@ -101,7 +101,7 @@ class LOCKABLE SpinLock {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Release this SpinLock, which must be held by the calling thread.
|
// Release this SpinLock, which must be held by the calling thread.
|
||||||
inline void Unlock() UNLOCK_FUNCTION() {
|
inline void Unlock() ABSL_UNLOCK_FUNCTION() {
|
||||||
ABSL_TSAN_MUTEX_PRE_UNLOCK(this, 0);
|
ABSL_TSAN_MUTEX_PRE_UNLOCK(this, 0);
|
||||||
uint32_t lock_value = lockword_.load(std::memory_order_relaxed);
|
uint32_t lock_value = lockword_.load(std::memory_order_relaxed);
|
||||||
lock_value = lockword_.exchange(lock_value & kSpinLockCooperative,
|
lock_value = lockword_.exchange(lock_value & kSpinLockCooperative,
|
||||||
|
@ -179,13 +179,13 @@ class LOCKABLE SpinLock {
|
||||||
|
|
||||||
// Corresponding locker object that arranges to acquire a spinlock for
|
// Corresponding locker object that arranges to acquire a spinlock for
|
||||||
// the duration of a C++ scope.
|
// the duration of a C++ scope.
|
||||||
class SCOPED_LOCKABLE SpinLockHolder {
|
class ABSL_SCOPED_LOCKABLE SpinLockHolder {
|
||||||
public:
|
public:
|
||||||
inline explicit SpinLockHolder(SpinLock* l) EXCLUSIVE_LOCK_FUNCTION(l)
|
inline explicit SpinLockHolder(SpinLock* l) ABSL_EXCLUSIVE_LOCK_FUNCTION(l)
|
||||||
: lock_(l) {
|
: lock_(l) {
|
||||||
l->Lock();
|
l->Lock();
|
||||||
}
|
}
|
||||||
inline ~SpinLockHolder() UNLOCK_FUNCTION() { lock_->Unlock(); }
|
inline ~SpinLockHolder() ABSL_UNLOCK_FUNCTION() { lock_->Unlock(); }
|
||||||
|
|
||||||
SpinLockHolder(const SpinLockHolder&) = delete;
|
SpinLockHolder(const SpinLockHolder&) = delete;
|
||||||
SpinLockHolder& operator=(const SpinLockHolder&) = delete;
|
SpinLockHolder& operator=(const SpinLockHolder&) = delete;
|
||||||
|
|
|
@ -65,7 +65,7 @@ struct HashtablezInfo {
|
||||||
|
|
||||||
// Puts the object into a clean state, fills in the logically `const` members,
|
// Puts the object into a clean state, fills in the logically `const` members,
|
||||||
// blocking for any readers that are currently sampling the object.
|
// blocking for any readers that are currently sampling the object.
|
||||||
void PrepareForSampling() EXCLUSIVE_LOCKS_REQUIRED(init_mu);
|
void PrepareForSampling() ABSL_EXCLUSIVE_LOCKS_REQUIRED(init_mu);
|
||||||
|
|
||||||
// These fields are mutated by the various Record* APIs and need to be
|
// These fields are mutated by the various Record* APIs and need to be
|
||||||
// thread-safe.
|
// thread-safe.
|
||||||
|
@ -83,7 +83,7 @@ struct HashtablezInfo {
|
||||||
// prevents races with sampling and resurrecting an object.
|
// prevents races with sampling and resurrecting an object.
|
||||||
absl::Mutex init_mu;
|
absl::Mutex init_mu;
|
||||||
HashtablezInfo* next;
|
HashtablezInfo* next;
|
||||||
HashtablezInfo* dead GUARDED_BY(init_mu);
|
HashtablezInfo* dead ABSL_GUARDED_BY(init_mu);
|
||||||
|
|
||||||
// All of the fields below are set by `PrepareForSampling`, they must not be
|
// All of the fields below are set by `PrepareForSampling`, they must not be
|
||||||
// mutated in `Record*` functions. They are logically `const` in that sense.
|
// mutated in `Record*` functions. They are logically `const` in that sense.
|
||||||
|
|
|
@ -58,55 +58,55 @@ absl::Mutex* InitFlag(CommandLineFlag* flag) {
|
||||||
{
|
{
|
||||||
absl::MutexLock lock(&init_lock);
|
absl::MutexLock lock(&init_lock);
|
||||||
|
|
||||||
if (flag->locks == nullptr) { // Must initialize Mutexes for this flag.
|
if (flag->locks_ == nullptr) { // Must initialize Mutexes for this flag.
|
||||||
flag->locks = new flags_internal::CommandLineFlagLocks;
|
flag->locks_ = new flags_internal::CommandLineFlagLocks;
|
||||||
}
|
}
|
||||||
|
|
||||||
mu = &flag->locks->primary_mu;
|
mu = &flag->locks_->primary_mu;
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
absl::MutexLock lock(mu);
|
absl::MutexLock lock(mu);
|
||||||
|
|
||||||
if (!flag->IsRetired() && flag->def == nullptr) {
|
if (!flag->IsRetired() && flag->def_ == nullptr) {
|
||||||
// Need to initialize def and cur fields.
|
// Need to initialize def and cur fields.
|
||||||
flag->def = (*flag->make_init_value)();
|
flag->def_ = (*flag->make_init_value_)();
|
||||||
flag->cur = Clone(flag->op, flag->def);
|
flag->cur_ = Clone(flag->op_, flag->def_);
|
||||||
UpdateCopy(flag);
|
UpdateCopy(flag);
|
||||||
flag->inited.store(true, std::memory_order_release);
|
flag->inited_.store(true, std::memory_order_release);
|
||||||
flag->InvokeCallback();
|
flag->InvokeCallback();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
flag->inited.store(true, std::memory_order_release);
|
flag->inited_.store(true, std::memory_order_release);
|
||||||
return mu;
|
return mu;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Ensure that the lazily initialized fields of *flag have been initialized,
|
// Ensure that the lazily initialized fields of *flag have been initialized,
|
||||||
// and return &flag->locks->primary_mu.
|
// and return &flag->locks_->primary_mu.
|
||||||
absl::Mutex* CommandLineFlag::InitFlagIfNecessary() const
|
absl::Mutex* CommandLineFlag::InitFlagIfNecessary() const
|
||||||
LOCK_RETURNED(locks->primary_mu) {
|
ABSL_LOCK_RETURNED(locks_->primary_mu) {
|
||||||
if (!this->inited.load(std::memory_order_acquire)) {
|
if (!inited_.load(std::memory_order_acquire)) {
|
||||||
return InitFlag(const_cast<CommandLineFlag*>(this));
|
return InitFlag(const_cast<CommandLineFlag*>(this));
|
||||||
}
|
}
|
||||||
|
|
||||||
// All fields initialized; this->locks is therefore safe to read.
|
// All fields initialized; locks_ is therefore safe to read.
|
||||||
return &this->locks->primary_mu;
|
return &locks_->primary_mu;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CommandLineFlag::IsModified() const {
|
bool CommandLineFlag::IsModified() const {
|
||||||
absl::MutexLock l(InitFlagIfNecessary());
|
absl::MutexLock l(InitFlagIfNecessary());
|
||||||
return modified;
|
return modified_;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CommandLineFlag::SetModified(bool is_modified) {
|
void CommandLineFlag::SetModified(bool is_modified) {
|
||||||
absl::MutexLock l(InitFlagIfNecessary());
|
absl::MutexLock l(InitFlagIfNecessary());
|
||||||
modified = is_modified;
|
modified_ = is_modified;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CommandLineFlag::IsSpecifiedOnCommandLine() const {
|
bool CommandLineFlag::IsSpecifiedOnCommandLine() const {
|
||||||
absl::MutexLock l(InitFlagIfNecessary());
|
absl::MutexLock l(InitFlagIfNecessary());
|
||||||
return on_command_line;
|
return on_command_line_;
|
||||||
}
|
}
|
||||||
|
|
||||||
absl::string_view CommandLineFlag::Typename() const {
|
absl::string_view CommandLineFlag::Typename() const {
|
||||||
|
@ -134,19 +134,19 @@ absl::string_view CommandLineFlag::Typename() const {
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string CommandLineFlag::Filename() const {
|
std::string CommandLineFlag::Filename() const {
|
||||||
return flags_internal::GetUsageConfig().normalize_filename(this->filename);
|
return flags_internal::GetUsageConfig().normalize_filename(filename_);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string CommandLineFlag::DefaultValue() const {
|
std::string CommandLineFlag::DefaultValue() const {
|
||||||
absl::MutexLock l(InitFlagIfNecessary());
|
absl::MutexLock l(InitFlagIfNecessary());
|
||||||
|
|
||||||
return Unparse(this->marshalling_op, this->def);
|
return Unparse(marshalling_op_, def_);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string CommandLineFlag::CurrentValue() const {
|
std::string CommandLineFlag::CurrentValue() const {
|
||||||
absl::MutexLock l(InitFlagIfNecessary());
|
absl::MutexLock l(InitFlagIfNecessary());
|
||||||
|
|
||||||
return Unparse(this->marshalling_op, this->cur);
|
return Unparse(marshalling_op_, cur_);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Attempts to parse supplied `value` string using parsing routine in the `flag`
|
// Attempts to parse supplied `value` string using parsing routine in the `flag`
|
||||||
|
@ -157,31 +157,31 @@ std::string CommandLineFlag::CurrentValue() const {
|
||||||
// in 'err'
|
// in 'err'
|
||||||
bool TryParseLocked(CommandLineFlag* flag, void* dst, absl::string_view value,
|
bool TryParseLocked(CommandLineFlag* flag, void* dst, absl::string_view value,
|
||||||
std::string* err)
|
std::string* err)
|
||||||
EXCLUSIVE_LOCKS_REQUIRED(flag->locks->primary_mu) {
|
ABSL_EXCLUSIVE_LOCKS_REQUIRED(flag->locks_->primary_mu) {
|
||||||
void* tentative_value = Clone(flag->op, flag->def);
|
void* tentative_value = Clone(flag->op_, flag->def_);
|
||||||
std::string parse_err;
|
std::string parse_err;
|
||||||
if (!Parse(flag->marshalling_op, value, tentative_value, &parse_err)) {
|
if (!Parse(flag->marshalling_op_, value, tentative_value, &parse_err)) {
|
||||||
auto type_name = flag->Typename();
|
auto type_name = flag->Typename();
|
||||||
absl::string_view err_sep = parse_err.empty() ? "" : "; ";
|
absl::string_view err_sep = parse_err.empty() ? "" : "; ";
|
||||||
absl::string_view typename_sep = type_name.empty() ? "" : " ";
|
absl::string_view typename_sep = type_name.empty() ? "" : " ";
|
||||||
*err = absl::StrCat("Illegal value '", value, "' specified for",
|
*err = absl::StrCat("Illegal value '", value, "' specified for",
|
||||||
typename_sep, type_name, " flag '", flag->Name(), "'",
|
typename_sep, type_name, " flag '", flag->Name(), "'",
|
||||||
err_sep, parse_err);
|
err_sep, parse_err);
|
||||||
Delete(flag->op, tentative_value);
|
Delete(flag->op_, tentative_value);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!flag->InvokeValidator(tentative_value)) {
|
if (!flag->InvokeValidator(tentative_value)) {
|
||||||
*err = absl::StrCat("Failed validation of new value '",
|
*err = absl::StrCat("Failed validation of new value '",
|
||||||
Unparse(flag->marshalling_op, tentative_value),
|
Unparse(flag->marshalling_op_, tentative_value),
|
||||||
"' for flag '", flag->Name(), "'");
|
"' for flag '", flag->Name(), "'");
|
||||||
Delete(flag->op, tentative_value);
|
Delete(flag->op_, tentative_value);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
flag->counter++;
|
flag->counter_++;
|
||||||
Copy(flag->op, tentative_value, dst);
|
Copy(flag->op_, tentative_value, dst);
|
||||||
Delete(flag->op, tentative_value);
|
Delete(flag->op_, tentative_value);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -201,38 +201,38 @@ bool CommandLineFlag::SetFromString(absl::string_view value,
|
||||||
absl::MutexLock l(InitFlagIfNecessary());
|
absl::MutexLock l(InitFlagIfNecessary());
|
||||||
|
|
||||||
// Direct-access flags can be modified without going through the
|
// Direct-access flags can be modified without going through the
|
||||||
// flag API. Detect such changes and update the flag->modified bit.
|
// flag API. Detect such changes and update the flag->modified_ bit.
|
||||||
if (!IsAbseilFlag()) {
|
if (!IsAbseilFlag()) {
|
||||||
if (!this->modified && ChangedDirectly(this, this->cur, this->def)) {
|
if (!modified_ && ChangedDirectly(this, cur_, def_)) {
|
||||||
this->modified = true;
|
modified_ = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
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 (!TryParseLocked(this, this->cur, value, err)) return false;
|
if (!TryParseLocked(this, cur_, value, err)) return false;
|
||||||
this->modified = true;
|
modified_ = true;
|
||||||
UpdateCopy(this);
|
UpdateCopy(this);
|
||||||
InvokeCallback();
|
InvokeCallback();
|
||||||
|
|
||||||
if (source == kCommandLine) {
|
if (source == kCommandLine) {
|
||||||
this->on_command_line = true;
|
on_command_line_ = true;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
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 (!this->modified) {
|
if (!modified_) {
|
||||||
if (!TryParseLocked(this, this->cur, value, err)) return false;
|
if (!TryParseLocked(this, cur_, value, err)) return false;
|
||||||
this->modified = true;
|
modified_ = true;
|
||||||
UpdateCopy(this);
|
UpdateCopy(this);
|
||||||
InvokeCallback();
|
InvokeCallback();
|
||||||
} else {
|
} 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.
|
||||||
// *err = absl::StrCat(this->Name(), " is already set to ",
|
// *err = absl::StrCat(Name(), " is already set to ",
|
||||||
// CurrentValue(), "\n");
|
// CurrentValue(), "\n");
|
||||||
// return false;
|
// return false;
|
||||||
return true;
|
return true;
|
||||||
|
@ -241,11 +241,11 @@ bool CommandLineFlag::SetFromString(absl::string_view value,
|
||||||
}
|
}
|
||||||
case SET_FLAGS_DEFAULT: {
|
case SET_FLAGS_DEFAULT: {
|
||||||
// modify the flag's default-value
|
// modify the flag's default-value
|
||||||
if (!TryParseLocked(this, this->def, value, err)) return false;
|
if (!TryParseLocked(this, def_, value, err)) return false;
|
||||||
|
|
||||||
if (!this->modified) {
|
if (!modified_) {
|
||||||
// Need to set both defvalue *and* current, in this case
|
// Need to set both defvalue *and* current, in this case
|
||||||
Copy(this->op, this->def, this->cur);
|
Copy(op_, def_, cur_);
|
||||||
UpdateCopy(this);
|
UpdateCopy(this);
|
||||||
InvokeCallback();
|
InvokeCallback();
|
||||||
}
|
}
|
||||||
|
@ -264,8 +264,8 @@ bool CommandLineFlag::SetFromString(absl::string_view value,
|
||||||
void CommandLineFlag::StoreAtomic(size_t size) {
|
void CommandLineFlag::StoreAtomic(size_t size) {
|
||||||
int64_t t = 0;
|
int64_t t = 0;
|
||||||
assert(size <= sizeof(int64_t));
|
assert(size <= sizeof(int64_t));
|
||||||
memcpy(&t, this->cur, size);
|
memcpy(&t, cur_, size);
|
||||||
this->atomic.store(t, std::memory_order_release);
|
atomic_.store(t, std::memory_order_release);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CommandLineFlag::CheckDefaultValueParsingRoundtrip() const {
|
void CommandLineFlag::CheckDefaultValueParsingRoundtrip() const {
|
||||||
|
@ -273,9 +273,9 @@ void CommandLineFlag::CheckDefaultValueParsingRoundtrip() const {
|
||||||
|
|
||||||
absl::MutexLock lock(InitFlagIfNecessary());
|
absl::MutexLock lock(InitFlagIfNecessary());
|
||||||
|
|
||||||
void* dst = Clone(this->op, this->def);
|
void* dst = Clone(op_, def_);
|
||||||
std::string error;
|
std::string error;
|
||||||
if (!flags_internal::Parse(this->marshalling_op, v, dst, &error)) {
|
if (!flags_internal::Parse(marshalling_op_, v, dst, &error)) {
|
||||||
ABSL_INTERNAL_LOG(
|
ABSL_INTERNAL_LOG(
|
||||||
FATAL,
|
FATAL,
|
||||||
absl::StrCat("Flag ", Name(), " (from ", Filename(),
|
absl::StrCat("Flag ", Name(), " (from ", Filename(),
|
||||||
|
@ -285,23 +285,23 @@ void CommandLineFlag::CheckDefaultValueParsingRoundtrip() const {
|
||||||
|
|
||||||
// We do not compare dst to def since parsing/unparsing may make
|
// We do not compare dst to def since parsing/unparsing may make
|
||||||
// small changes, e.g., precision loss for floating point types.
|
// small changes, e.g., precision loss for floating point types.
|
||||||
Delete(this->op, dst);
|
Delete(op_, dst);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CommandLineFlag::ValidateDefaultValue() const {
|
bool CommandLineFlag::ValidateDefaultValue() const {
|
||||||
absl::MutexLock lock(InitFlagIfNecessary());
|
absl::MutexLock lock(InitFlagIfNecessary());
|
||||||
return InvokeValidator(this->def);
|
return InvokeValidator(def_);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CommandLineFlag::ValidateInputValue(absl::string_view value) const {
|
bool CommandLineFlag::ValidateInputValue(absl::string_view value) const {
|
||||||
absl::MutexLock l(InitFlagIfNecessary()); // protect default value access
|
absl::MutexLock l(InitFlagIfNecessary()); // protect default value access
|
||||||
|
|
||||||
void* obj = Clone(this->op, this->def);
|
void* obj = Clone(op_, def_);
|
||||||
std::string ignored_error;
|
std::string ignored_error;
|
||||||
const bool result =
|
const bool result =
|
||||||
flags_internal::Parse(this->marshalling_op, value, obj, &ignored_error) &&
|
flags_internal::Parse(marshalling_op_, value, obj, &ignored_error) &&
|
||||||
InvokeValidator(obj);
|
InvokeValidator(obj);
|
||||||
Delete(this->op, obj);
|
Delete(op_, obj);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -314,13 +314,13 @@ void CommandLineFlag::Read(void* dst,
|
||||||
// `dst_op` is the unmarshaling operation corresponding to the declaration
|
// `dst_op` is the unmarshaling operation corresponding to the declaration
|
||||||
// visibile at the call site. `op` is the Flag's defined unmarshalling
|
// visibile at the call site. `op` is the Flag's defined unmarshalling
|
||||||
// operation. They must match for this operation to be well-defined.
|
// operation. They must match for this operation to be well-defined.
|
||||||
if (ABSL_PREDICT_FALSE(dst_op != op)) {
|
if (ABSL_PREDICT_FALSE(dst_op != op_)) {
|
||||||
ABSL_INTERNAL_LOG(
|
ABSL_INTERNAL_LOG(
|
||||||
ERROR,
|
ERROR,
|
||||||
absl::StrCat("Flag '", name,
|
absl::StrCat("Flag '", Name(),
|
||||||
"' is defined as one type and declared as another"));
|
"' is defined as one type and declared as another"));
|
||||||
}
|
}
|
||||||
CopyConstruct(op, cur, dst);
|
CopyConstruct(op_, cur_, dst);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CommandLineFlag::Write(const void* src,
|
void CommandLineFlag::Write(const void* src,
|
||||||
|
@ -330,28 +330,28 @@ void CommandLineFlag::Write(const void* src,
|
||||||
// `src_op` is the marshalling operation corresponding to the declaration
|
// `src_op` is the marshalling operation corresponding to the declaration
|
||||||
// visible at the call site. `op` is the Flag's defined marshalling operation.
|
// visible at the call site. `op` is the Flag's defined marshalling operation.
|
||||||
// They must match for this operation to be well-defined.
|
// They must match for this operation to be well-defined.
|
||||||
if (ABSL_PREDICT_FALSE(src_op != op)) {
|
if (ABSL_PREDICT_FALSE(src_op != op_)) {
|
||||||
ABSL_INTERNAL_LOG(
|
ABSL_INTERNAL_LOG(
|
||||||
ERROR,
|
ERROR,
|
||||||
absl::StrCat("Flag '", name,
|
absl::StrCat("Flag '", Name(),
|
||||||
"' is defined as one type and declared as another"));
|
"' is defined as one type and declared as another"));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ShouldValidateFlagValue(*this)) {
|
if (ShouldValidateFlagValue(*this)) {
|
||||||
void* obj = Clone(op, src);
|
void* obj = Clone(op_, src);
|
||||||
std::string ignored_error;
|
std::string ignored_error;
|
||||||
std::string src_as_str = Unparse(marshalling_op, src);
|
std::string src_as_str = Unparse(marshalling_op_, src);
|
||||||
if (!Parse(marshalling_op, src_as_str, obj, &ignored_error) ||
|
if (!Parse(marshalling_op_, src_as_str, obj, &ignored_error) ||
|
||||||
!InvokeValidator(obj)) {
|
!InvokeValidator(obj)) {
|
||||||
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));
|
||||||
}
|
}
|
||||||
Delete(op, obj);
|
Delete(op_, obj);
|
||||||
}
|
}
|
||||||
|
|
||||||
modified = true;
|
modified_ = true;
|
||||||
counter++;
|
counter_++;
|
||||||
Copy(op, src, cur);
|
Copy(op_, src, cur_);
|
||||||
|
|
||||||
UpdateCopy(this);
|
UpdateCopy(this);
|
||||||
InvokeCallback();
|
InvokeCallback();
|
||||||
|
|
|
@ -69,8 +69,6 @@ using HelpGenFunc = std::string (*)();
|
||||||
// based on default value supplied in flag's definition)
|
// based on default value supplied in flag's definition)
|
||||||
using InitialValGenFunc = void* (*)();
|
using InitialValGenFunc = void* (*)();
|
||||||
|
|
||||||
struct CommandLineFlagInfo;
|
|
||||||
|
|
||||||
extern const char kStrippedFlagHelp[];
|
extern const char kStrippedFlagHelp[];
|
||||||
|
|
||||||
// The per-type function
|
// The per-type function
|
||||||
|
@ -189,27 +187,28 @@ class HelpText {
|
||||||
};
|
};
|
||||||
|
|
||||||
// Holds all information for a flag.
|
// Holds all information for a flag.
|
||||||
struct CommandLineFlag {
|
class CommandLineFlag {
|
||||||
|
public:
|
||||||
constexpr CommandLineFlag(
|
constexpr CommandLineFlag(
|
||||||
const char* name_arg, HelpText help_text, const char* filename_arg,
|
const char* name, HelpText help_text, const char* filename,
|
||||||
const flags_internal::FlagOpFn op_arg,
|
const flags_internal::FlagOpFn op,
|
||||||
const flags_internal::FlagMarshallingOpFn marshalling_op_arg,
|
const flags_internal::FlagMarshallingOpFn marshalling_op,
|
||||||
const flags_internal::InitialValGenFunc initial_value_gen, void* def_arg,
|
const flags_internal::InitialValGenFunc initial_value_gen, void* def,
|
||||||
void* cur_arg)
|
void* cur)
|
||||||
: name(name_arg),
|
: name_(name),
|
||||||
help(help_text),
|
help_(help_text),
|
||||||
filename(filename_arg),
|
filename_(filename),
|
||||||
op(op_arg),
|
op_(op),
|
||||||
marshalling_op(marshalling_op_arg),
|
marshalling_op_(marshalling_op),
|
||||||
make_init_value(initial_value_gen),
|
make_init_value_(initial_value_gen),
|
||||||
inited(false),
|
inited_(false),
|
||||||
modified(false),
|
modified_(false),
|
||||||
on_command_line(false),
|
on_command_line_(false),
|
||||||
def(def_arg),
|
def_(def),
|
||||||
cur(cur_arg),
|
cur_(cur),
|
||||||
counter(0),
|
counter_(0),
|
||||||
atomic(kAtomicInit),
|
atomic_(kAtomicInit),
|
||||||
locks(nullptr) {}
|
locks_(nullptr) {}
|
||||||
|
|
||||||
// Virtual destructor
|
// Virtual destructor
|
||||||
virtual void Destroy() const = 0;
|
virtual void Destroy() const = 0;
|
||||||
|
@ -225,8 +224,8 @@ struct CommandLineFlag {
|
||||||
// Returns true iff this is a handle to an Abseil Flag.
|
// Returns true iff this is a handle to an Abseil Flag.
|
||||||
virtual bool IsAbseilFlag() const { return true; }
|
virtual bool IsAbseilFlag() const { return true; }
|
||||||
|
|
||||||
absl::string_view Name() const { return name; }
|
absl::string_view Name() const { return name_; }
|
||||||
std::string Help() const { return help.GetHelpText(); }
|
std::string Help() const { return help_.GetHelpText(); }
|
||||||
bool IsModified() const;
|
bool IsModified() const;
|
||||||
void SetModified(bool is_modified);
|
void SetModified(bool is_modified);
|
||||||
bool IsSpecifiedOnCommandLine() const;
|
bool IsSpecifiedOnCommandLine() const;
|
||||||
|
@ -247,15 +246,14 @@ struct CommandLineFlag {
|
||||||
// Return true iff flag has type T.
|
// Return true iff flag has type T.
|
||||||
template <typename T>
|
template <typename T>
|
||||||
inline bool IsOfType() const {
|
inline bool IsOfType() const {
|
||||||
return this->op == &flags_internal::FlagOps<T>;
|
return op_ == &flags_internal::FlagOps<T>;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Attempts to retrieve the flag value. Returns value on success,
|
// Attempts to retrieve the flag value. Returns value on success,
|
||||||
// absl::nullopt otherwise.
|
// absl::nullopt otherwise.
|
||||||
template <typename T>
|
template <typename T>
|
||||||
absl::optional<T> Get() const {
|
absl::optional<T> Get() const {
|
||||||
if (IsRetired() || flags_internal::FlagOps<T> != this->op)
|
if (IsRetired() || flags_internal::FlagOps<T> != op_) return absl::nullopt;
|
||||||
return absl::nullopt;
|
|
||||||
|
|
||||||
T res;
|
T res;
|
||||||
Read(&res, flags_internal::FlagOps<T>);
|
Read(&res, flags_internal::FlagOps<T>);
|
||||||
|
@ -286,36 +284,36 @@ struct CommandLineFlag {
|
||||||
protected:
|
protected:
|
||||||
~CommandLineFlag() = default;
|
~CommandLineFlag() = default;
|
||||||
|
|
||||||
const char* const name;
|
const char* const name_;
|
||||||
const HelpText help;
|
const HelpText help_;
|
||||||
const char* const filename;
|
const char* const filename_;
|
||||||
|
|
||||||
const FlagOpFn op; // Type-specific handler
|
const FlagOpFn op_; // Type-specific handler
|
||||||
const FlagMarshallingOpFn marshalling_op; // Marshalling ops handler
|
const FlagMarshallingOpFn marshalling_op_; // Marshalling ops handler
|
||||||
const InitialValGenFunc make_init_value; // Makes initial value for the flag
|
const InitialValGenFunc make_init_value_; // Makes initial value for the flag
|
||||||
std::atomic<bool> inited; // fields have been lazily initialized
|
std::atomic<bool> inited_; // fields have been lazily initialized
|
||||||
|
|
||||||
// Mutable state (guarded by locks->primary_mu).
|
// Mutable state (guarded by locks_->primary_mu).
|
||||||
bool modified; // Has flag value been modified?
|
bool modified_; // Has flag value been modified?
|
||||||
bool on_command_line; // Specified on command line.
|
bool on_command_line_; // Specified on command line.
|
||||||
void* def; // Lazily initialized pointer to default value
|
void* def_; // Lazily initialized pointer to default value
|
||||||
void* cur; // Lazily initialized pointer to current value
|
void* cur_; // Lazily initialized pointer to current value
|
||||||
int64_t counter; // Mutation counter
|
int64_t counter_; // Mutation counter
|
||||||
|
|
||||||
// For some types, a copy of the current value is kept in an atomically
|
// For some types, a copy of the current value is kept in an atomically
|
||||||
// accessible field.
|
// accessible field.
|
||||||
static const int64_t kAtomicInit = 0xababababababababll;
|
static const int64_t kAtomicInit = 0xababababababababll;
|
||||||
std::atomic<int64_t> atomic;
|
std::atomic<int64_t> atomic_;
|
||||||
|
|
||||||
// Lazily initialized mutexes for this flag value. We cannot inline a
|
// Lazily initialized mutexes for this flag value. We cannot inline a
|
||||||
// SpinLock or Mutex here because those have non-constexpr constructors and
|
// SpinLock or Mutex here because those have non-constexpr constructors and
|
||||||
// so would prevent constant initialization of this type.
|
// so would prevent constant initialization of this type.
|
||||||
// TODO(rogeeff): fix it once Mutex has constexpr constructor
|
// TODO(rogeeff): fix it once Mutex has constexpr constructor
|
||||||
struct CommandLineFlagLocks* locks; // locks, laziliy allocated.
|
struct CommandLineFlagLocks* locks_; // locks, laziliy allocated.
|
||||||
|
|
||||||
// Ensure that the lazily initialized fields of *flag have been initialized,
|
// Ensure that the lazily initialized fields of *flag have been initialized,
|
||||||
// and return the lock which should be locked when flag's state is mutated.
|
// and return the lock which should be locked when flag's state is mutated.
|
||||||
absl::Mutex* InitFlagIfNecessary() const LOCK_RETURNED(locks->primary_mu);
|
absl::Mutex* InitFlagIfNecessary() const ABSL_LOCK_RETURNED(locks_->primary_mu);
|
||||||
|
|
||||||
// copy construct new value of flag's type in a memory referenced by dst
|
// copy construct new value of flag's type in a memory referenced by dst
|
||||||
// based on current flag's value
|
// based on current flag's value
|
||||||
|
@ -326,8 +324,6 @@ struct CommandLineFlag {
|
||||||
friend class FlagRegistry;
|
friend class FlagRegistry;
|
||||||
friend class FlagPtrMap;
|
friend class FlagPtrMap;
|
||||||
friend class FlagSaverImpl;
|
friend class FlagSaverImpl;
|
||||||
friend void FillCommandLineFlagInfo(CommandLineFlag* flag,
|
|
||||||
CommandLineFlagInfo* result);
|
|
||||||
friend bool TryParseLocked(CommandLineFlag* flag, void* dst,
|
friend bool TryParseLocked(CommandLineFlag* flag, void* dst,
|
||||||
absl::string_view value, std::string* err);
|
absl::string_view value, std::string* err);
|
||||||
friend absl::Mutex* InitFlag(CommandLineFlag* flag);
|
friend absl::Mutex* InitFlag(CommandLineFlag* flag);
|
||||||
|
@ -335,7 +331,7 @@ struct CommandLineFlag {
|
||||||
// This is a short term, until we completely rework persistent state
|
// This is a short term, until we completely rework persistent state
|
||||||
// storage API.
|
// storage API.
|
||||||
virtual void* GetValidator() const { return nullptr; }
|
virtual void* GetValidator() const { return nullptr; }
|
||||||
virtual void SetValidator(void*) {}
|
virtual bool SetValidator(void*) { return false; }
|
||||||
};
|
};
|
||||||
|
|
||||||
// Update any copy of the flag value that is stored in an atomic word.
|
// Update any copy of the flag value that is stored in an atomic word.
|
||||||
|
|
|
@ -32,7 +32,7 @@ namespace flags_internal {
|
||||||
// completed. Requires that *primary_lock be held in exclusive mode; it may be
|
// completed. Requires that *primary_lock be held in exclusive mode; it may be
|
||||||
// released and reacquired by the implementation.
|
// released and reacquired by the implementation.
|
||||||
void InvokeCallback(absl::Mutex* primary_mu, absl::Mutex* callback_mu,
|
void InvokeCallback(absl::Mutex* primary_mu, absl::Mutex* callback_mu,
|
||||||
FlagCallback cb) EXCLUSIVE_LOCKS_REQUIRED(primary_mu) {
|
FlagCallback cb) ABSL_EXCLUSIVE_LOCKS_REQUIRED(primary_mu) {
|
||||||
if (!cb) return;
|
if (!cb) return;
|
||||||
|
|
||||||
// When executing the callback we need the primary flag's mutex to be
|
// When executing the callback we need the primary flag's mutex to be
|
||||||
|
|
|
@ -28,23 +28,22 @@ namespace flags_internal {
|
||||||
using FlagCallback = void (*)();
|
using FlagCallback = void (*)();
|
||||||
|
|
||||||
void InvokeCallback(absl::Mutex* primary_mu, absl::Mutex* callback_mu,
|
void InvokeCallback(absl::Mutex* primary_mu, absl::Mutex* callback_mu,
|
||||||
FlagCallback cb) EXCLUSIVE_LOCKS_REQUIRED(primary_mu);
|
FlagCallback cb) ABSL_EXCLUSIVE_LOCKS_REQUIRED(primary_mu);
|
||||||
|
|
||||||
// This is "unspecified" implementation of absl::Flag<T> type.
|
// This is "unspecified" implementation of absl::Flag<T> type.
|
||||||
template <typename T>
|
template <typename T>
|
||||||
class Flag final : public flags_internal::CommandLineFlag {
|
class Flag final : public flags_internal::CommandLineFlag {
|
||||||
public:
|
public:
|
||||||
constexpr Flag(const char* name_arg,
|
constexpr Flag(const char* name, const flags_internal::HelpGenFunc help_gen,
|
||||||
const flags_internal::HelpGenFunc help_gen,
|
const char* filename,
|
||||||
const char* filename_arg,
|
const flags_internal::FlagMarshallingOpFn marshalling_op,
|
||||||
const flags_internal::FlagMarshallingOpFn marshalling_op_arg,
|
|
||||||
const flags_internal::InitialValGenFunc initial_value_gen)
|
const flags_internal::InitialValGenFunc initial_value_gen)
|
||||||
: flags_internal::CommandLineFlag(
|
: flags_internal::CommandLineFlag(
|
||||||
name_arg, flags_internal::HelpText::FromFunctionPointer(help_gen),
|
name, flags_internal::HelpText::FromFunctionPointer(help_gen),
|
||||||
filename_arg, &flags_internal::FlagOps<T>, marshalling_op_arg,
|
filename, &flags_internal::FlagOps<T>, marshalling_op,
|
||||||
initial_value_gen,
|
initial_value_gen,
|
||||||
/*def_arg=*/nullptr,
|
/*def=*/nullptr,
|
||||||
/*cur_arg=*/nullptr),
|
/*cur=*/nullptr),
|
||||||
callback_(nullptr) {}
|
callback_(nullptr) {}
|
||||||
|
|
||||||
T Get() const {
|
T Get() const {
|
||||||
|
@ -71,12 +70,12 @@ class Flag final : public flags_internal::CommandLineFlag {
|
||||||
};
|
};
|
||||||
U u;
|
U u;
|
||||||
|
|
||||||
this->Read(&u.value, &flags_internal::FlagOps<T>);
|
Read(&u.value, &flags_internal::FlagOps<T>);
|
||||||
return std::move(u.value);
|
return std::move(u.value);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool AtomicGet(T* v) const {
|
bool AtomicGet(T* v) const {
|
||||||
const int64_t r = this->atomic.load(std::memory_order_acquire);
|
const int64_t r = atomic_.load(std::memory_order_acquire);
|
||||||
if (r != flags_internal::CommandLineFlag::kAtomicInit) {
|
if (r != flags_internal::CommandLineFlag::kAtomicInit) {
|
||||||
memcpy(v, &r, sizeof(T));
|
memcpy(v, &r, sizeof(T));
|
||||||
return true;
|
return true;
|
||||||
|
@ -85,7 +84,7 @@ class Flag final : public flags_internal::CommandLineFlag {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Set(const T& v) { this->Write(&v, &flags_internal::FlagOps<T>); }
|
void Set(const T& v) { Write(&v, &flags_internal::FlagOps<T>); }
|
||||||
|
|
||||||
void SetCallback(const flags_internal::FlagCallback mutation_callback) {
|
void SetCallback(const flags_internal::FlagCallback mutation_callback) {
|
||||||
absl::MutexLock l(InitFlagIfNecessary());
|
absl::MutexLock l(InitFlagIfNecessary());
|
||||||
|
@ -95,18 +94,18 @@ class Flag final : public flags_internal::CommandLineFlag {
|
||||||
InvokeCallback();
|
InvokeCallback();
|
||||||
}
|
}
|
||||||
void InvokeCallback() override
|
void InvokeCallback() override
|
||||||
EXCLUSIVE_LOCKS_REQUIRED(this->locks->primary_mu) {
|
ABSL_EXCLUSIVE_LOCKS_REQUIRED(locks_->primary_mu) {
|
||||||
flags_internal::InvokeCallback(&this->locks->primary_mu,
|
flags_internal::InvokeCallback(&locks_->primary_mu, &locks_->callback_mu,
|
||||||
&this->locks->callback_mu, callback_);
|
callback_);
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void Destroy() const override {
|
void Destroy() const override {
|
||||||
// Values are heap allocated Abseil Flags.
|
// Values are heap allocated Abseil Flags.
|
||||||
if (this->cur) Delete(this->op, this->cur);
|
if (cur_) Delete(op_, cur_);
|
||||||
if (this->def) Delete(this->op, this->def);
|
if (def_) Delete(op_, def_);
|
||||||
|
|
||||||
delete this->locks;
|
delete locks_;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Flag's data
|
// Flag's data
|
||||||
|
|
|
@ -25,7 +25,7 @@ namespace flags_internal {
|
||||||
|
|
||||||
ABSL_CONST_INIT static absl::Mutex program_name_guard(absl::kConstInit);
|
ABSL_CONST_INIT static absl::Mutex program_name_guard(absl::kConstInit);
|
||||||
ABSL_CONST_INIT static std::string* program_name
|
ABSL_CONST_INIT static std::string* program_name
|
||||||
GUARDED_BY(program_name_guard) = nullptr;
|
ABSL_GUARDED_BY(program_name_guard) = nullptr;
|
||||||
|
|
||||||
std::string ProgramInvocationName() {
|
std::string ProgramInvocationName() {
|
||||||
absl::MutexLock l(&program_name_guard);
|
absl::MutexLock l(&program_name_guard);
|
||||||
|
|
|
@ -54,8 +54,8 @@ class FlagRegistry {
|
||||||
// Store a flag in this registry. Takes ownership of *flag.
|
// Store a flag in this registry. Takes ownership of *flag.
|
||||||
void RegisterFlag(CommandLineFlag* flag);
|
void RegisterFlag(CommandLineFlag* flag);
|
||||||
|
|
||||||
void Lock() EXCLUSIVE_LOCK_FUNCTION(lock_) { lock_.Lock(); }
|
void Lock() ABSL_EXCLUSIVE_LOCK_FUNCTION(lock_) { lock_.Lock(); }
|
||||||
void Unlock() UNLOCK_FUNCTION(lock_) { lock_.Unlock(); }
|
void Unlock() ABSL_UNLOCK_FUNCTION(lock_) { lock_.Unlock(); }
|
||||||
|
|
||||||
// Returns the flag object for the specified name, or nullptr if not found.
|
// Returns the flag object for the specified name, or nullptr if not found.
|
||||||
// Will emit a warning if a 'retired' flag is specified.
|
// Will emit a warning if a 'retired' flag is specified.
|
||||||
|
@ -118,7 +118,7 @@ void FlagRegistry::RegisterFlag(CommandLineFlag* flag) {
|
||||||
(flag->IsRetired() ? old_flag->Filename() : flag->Filename()),
|
(flag->IsRetired() ? old_flag->Filename() : flag->Filename()),
|
||||||
"'."),
|
"'."),
|
||||||
true);
|
true);
|
||||||
} else if (flag->op != old_flag->op) {
|
} else if (flag->op_ != old_flag->op_) {
|
||||||
flags_internal::ReportUsageError(
|
flags_internal::ReportUsageError(
|
||||||
absl::StrCat("Flag '", flag->Name(),
|
absl::StrCat("Flag '", flag->Name(),
|
||||||
"' was defined more than once but with "
|
"' was defined more than once but with "
|
||||||
|
@ -208,16 +208,16 @@ class FlagSaverImpl {
|
||||||
if (flag->IsRetired()) return;
|
if (flag->IsRetired()) return;
|
||||||
|
|
||||||
saved.name = flag->Name();
|
saved.name = flag->Name();
|
||||||
saved.op = flag->op;
|
saved.op = flag->op_;
|
||||||
saved.marshalling_op = flag->marshalling_op;
|
saved.marshalling_op = flag->marshalling_op_;
|
||||||
{
|
{
|
||||||
absl::MutexLock l(flag->InitFlagIfNecessary());
|
absl::MutexLock l(flag->InitFlagIfNecessary());
|
||||||
saved.validator = flag->GetValidator();
|
saved.validator = flag->GetValidator();
|
||||||
saved.modified = flag->modified;
|
saved.modified = flag->modified_;
|
||||||
saved.on_command_line = flag->on_command_line;
|
saved.on_command_line = flag->on_command_line_;
|
||||||
saved.current = Clone(saved.op, flag->cur);
|
saved.current = Clone(saved.op, flag->cur_);
|
||||||
saved.default_value = Clone(saved.op, flag->def);
|
saved.default_value = Clone(saved.op, flag->def_);
|
||||||
saved.counter = flag->counter;
|
saved.counter = flag->counter_;
|
||||||
}
|
}
|
||||||
backup_registry_.push_back(saved);
|
backup_registry_.push_back(saved);
|
||||||
});
|
});
|
||||||
|
@ -237,26 +237,28 @@ class FlagSaverImpl {
|
||||||
|
|
||||||
bool restored = false;
|
bool restored = false;
|
||||||
{
|
{
|
||||||
absl::MutexLock l(flag->InitFlagIfNecessary());
|
// This function encapsulate the lock.
|
||||||
flag->SetValidator(src.validator);
|
flag->SetValidator(src.validator);
|
||||||
flag->modified = src.modified;
|
|
||||||
flag->on_command_line = src.on_command_line;
|
absl::MutexLock l(flag->InitFlagIfNecessary());
|
||||||
if (flag->counter != src.counter ||
|
flag->modified_ = src.modified;
|
||||||
ChangedDirectly(flag, src.default_value, flag->def)) {
|
flag->on_command_line_ = src.on_command_line;
|
||||||
|
if (flag->counter_ != src.counter ||
|
||||||
|
ChangedDirectly(flag, src.default_value, flag->def_)) {
|
||||||
restored = true;
|
restored = true;
|
||||||
Copy(src.op, src.default_value, flag->def);
|
Copy(src.op, src.default_value, flag->def_);
|
||||||
}
|
}
|
||||||
if (flag->counter != src.counter ||
|
if (flag->counter_ != src.counter ||
|
||||||
ChangedDirectly(flag, src.current, flag->cur)) {
|
ChangedDirectly(flag, src.current, flag->cur_)) {
|
||||||
restored = true;
|
restored = true;
|
||||||
Copy(src.op, src.current, flag->cur);
|
Copy(src.op, src.current, flag->cur_);
|
||||||
UpdateCopy(flag);
|
UpdateCopy(flag);
|
||||||
flag->InvokeCallback();
|
flag->InvokeCallback();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (restored) {
|
if (restored) {
|
||||||
flag->counter++;
|
flag->counter_++;
|
||||||
|
|
||||||
// Revalidate the flag because the validator might store state based
|
// Revalidate the flag because the validator might store state based
|
||||||
// on the flag's value, which just changed due to the restore.
|
// on the flag's value, which just changed due to the restore.
|
||||||
|
@ -307,44 +309,6 @@ FlagSaver::~FlagSaver() {
|
||||||
delete impl_;
|
delete impl_;
|
||||||
}
|
}
|
||||||
|
|
||||||
// --------------------------------------------------------------------
|
|
||||||
// GetAllFlags()
|
|
||||||
// The main way the FlagRegistry class exposes its data. This
|
|
||||||
// returns, as strings, all the info about all the flags in
|
|
||||||
// the main registry, sorted first by filename they are defined
|
|
||||||
// in, and then by flagname.
|
|
||||||
// --------------------------------------------------------------------
|
|
||||||
|
|
||||||
struct FilenameFlagnameLess {
|
|
||||||
bool operator()(const CommandLineFlagInfo& a,
|
|
||||||
const CommandLineFlagInfo& b) const {
|
|
||||||
int cmp = absl::string_view(a.filename).compare(b.filename);
|
|
||||||
if (cmp != 0) return cmp < 0;
|
|
||||||
return a.name < b.name;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
void FillCommandLineFlagInfo(CommandLineFlag* flag,
|
|
||||||
CommandLineFlagInfo* result) {
|
|
||||||
result->name = std::string(flag->Name());
|
|
||||||
result->type = std::string(flag->Typename());
|
|
||||||
result->description = flag->Help();
|
|
||||||
result->filename = flag->Filename();
|
|
||||||
|
|
||||||
if (!flag->IsAbseilFlag()) {
|
|
||||||
if (!flag->IsModified() && ChangedDirectly(flag, flag->cur, flag->def)) {
|
|
||||||
flag->modified = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
result->current_value = flag->CurrentValue();
|
|
||||||
result->default_value = flag->DefaultValue();
|
|
||||||
result->is_default = !flag->IsModified();
|
|
||||||
result->has_validator_fn = flag->HasValidatorFn();
|
|
||||||
absl::MutexLock l(flag->InitFlagIfNecessary());
|
|
||||||
result->flag_ptr = flag->IsAbseilFlag() ? nullptr : flag->cur;
|
|
||||||
}
|
|
||||||
|
|
||||||
// --------------------------------------------------------------------
|
// --------------------------------------------------------------------
|
||||||
|
|
||||||
CommandLineFlag* FindCommandLineFlag(absl::string_view name) {
|
CommandLineFlag* FindCommandLineFlag(absl::string_view name) {
|
||||||
|
@ -380,21 +344,6 @@ void ForEachFlag(std::function<void(CommandLineFlag*)> visitor) {
|
||||||
|
|
||||||
// --------------------------------------------------------------------
|
// --------------------------------------------------------------------
|
||||||
|
|
||||||
void GetAllFlags(std::vector<CommandLineFlagInfo>* OUTPUT) {
|
|
||||||
flags_internal::ForEachFlag([&](CommandLineFlag* flag) {
|
|
||||||
if (flag->IsRetired()) return;
|
|
||||||
|
|
||||||
CommandLineFlagInfo fi;
|
|
||||||
FillCommandLineFlagInfo(flag, &fi);
|
|
||||||
OUTPUT->push_back(fi);
|
|
||||||
});
|
|
||||||
|
|
||||||
// Now sort the flags, first by filename they occur in, then alphabetically
|
|
||||||
std::sort(OUTPUT->begin(), OUTPUT->end(), FilenameFlagnameLess());
|
|
||||||
}
|
|
||||||
|
|
||||||
// --------------------------------------------------------------------
|
|
||||||
|
|
||||||
bool RegisterCommandLineFlag(CommandLineFlag* flag) {
|
bool RegisterCommandLineFlag(CommandLineFlag* flag) {
|
||||||
FlagRegistry::GlobalRegistry()->RegisterFlag(flag);
|
FlagRegistry::GlobalRegistry()->RegisterFlag(flag);
|
||||||
return true;
|
return true;
|
||||||
|
@ -406,24 +355,24 @@ namespace {
|
||||||
|
|
||||||
class RetiredFlagObj final : public flags_internal::CommandLineFlag {
|
class RetiredFlagObj final : public flags_internal::CommandLineFlag {
|
||||||
public:
|
public:
|
||||||
constexpr RetiredFlagObj(const char* name_arg, FlagOpFn ops,
|
constexpr RetiredFlagObj(const char* name, FlagOpFn ops,
|
||||||
FlagMarshallingOpFn marshalling_ops)
|
FlagMarshallingOpFn marshalling_ops)
|
||||||
: flags_internal::CommandLineFlag(
|
: flags_internal::CommandLineFlag(
|
||||||
name_arg, flags_internal::HelpText::FromStaticCString(nullptr),
|
name, flags_internal::HelpText::FromStaticCString(nullptr),
|
||||||
/*filename_arg=*/"RETIRED", ops, marshalling_ops,
|
/*filename=*/"RETIRED", ops, marshalling_ops,
|
||||||
/*initial_value_gen=*/nullptr,
|
/*initial_value_gen=*/nullptr,
|
||||||
/*def_arg=*/nullptr,
|
/*def=*/nullptr,
|
||||||
/*cur_arg=*/nullptr) {}
|
/*cur=*/nullptr) {}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool IsRetired() const override { return true; }
|
bool IsRetired() const override { return true; }
|
||||||
|
|
||||||
void Destroy() const override {
|
void Destroy() const override {
|
||||||
// Values are heap allocated for Retired Flags.
|
// Values are heap allocated for Retired Flags.
|
||||||
if (this->cur) Delete(this->op, this->cur);
|
if (cur_) Delete(op_, cur_);
|
||||||
if (this->def) Delete(this->op, this->def);
|
if (def_) Delete(op_, def_);
|
||||||
|
|
||||||
if (this->locks) delete this->locks;
|
if (locks_) delete locks_;
|
||||||
|
|
||||||
delete this;
|
delete this;
|
||||||
}
|
}
|
||||||
|
|
|
@ -29,33 +29,6 @@
|
||||||
namespace absl {
|
namespace absl {
|
||||||
namespace flags_internal {
|
namespace flags_internal {
|
||||||
|
|
||||||
// CommandLineFlagInfo holds all information for a flag.
|
|
||||||
struct CommandLineFlagInfo {
|
|
||||||
std::string name; // the name of the flag
|
|
||||||
std::string type; // DO NOT use. Use flag->IsOfType<T>() instead.
|
|
||||||
std::string description; // the "help text" associated with the flag
|
|
||||||
std::string current_value; // the current value, as a std::string
|
|
||||||
std::string default_value; // the default value, as a std::string
|
|
||||||
std::string filename; // 'cleaned' version of filename holding the flag
|
|
||||||
bool has_validator_fn; // true if RegisterFlagValidator called on this flag
|
|
||||||
|
|
||||||
bool is_default; // true if the flag has the default value and
|
|
||||||
// has not been set explicitly from the cmdline
|
|
||||||
// or via SetCommandLineOption.
|
|
||||||
|
|
||||||
// nullptr for ABSL_FLAG. A pointer to the flag's current value
|
|
||||||
// otherwise. E.g., for DEFINE_int32(foo, ...), flag_ptr will be
|
|
||||||
// &FLAGS_foo.
|
|
||||||
const void* flag_ptr;
|
|
||||||
};
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
|
|
||||||
void FillCommandLineFlagInfo(CommandLineFlag* flag,
|
|
||||||
CommandLineFlagInfo* result);
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
|
|
||||||
CommandLineFlag* FindCommandLineFlag(absl::string_view name);
|
CommandLineFlag* FindCommandLineFlag(absl::string_view name);
|
||||||
CommandLineFlag* FindRetiredFlag(absl::string_view name);
|
CommandLineFlag* FindRetiredFlag(absl::string_view name);
|
||||||
|
|
||||||
|
@ -68,11 +41,6 @@ void ForEachFlag(std::function<void(CommandLineFlag*)> visitor);
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
|
|
||||||
// Store the list of all flags in *OUTPUT, sorted by file.
|
|
||||||
void GetAllFlags(std::vector<CommandLineFlagInfo>* OUTPUT);
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
|
|
||||||
bool RegisterCommandLineFlag(CommandLineFlag*);
|
bool RegisterCommandLineFlag(CommandLineFlag*);
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
|
|
|
@ -36,30 +36,6 @@ bool GetCommandLineOption(absl::string_view name, std::string* value) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool GetCommandLineFlagInfo(absl::string_view name,
|
|
||||||
CommandLineFlagInfo* OUTPUT) {
|
|
||||||
if (name.empty()) return false;
|
|
||||||
|
|
||||||
CommandLineFlag* flag = flags_internal::FindCommandLineFlag(name);
|
|
||||||
if (flag == nullptr || flag->IsRetired()) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
assert(OUTPUT);
|
|
||||||
FillCommandLineFlagInfo(flag, OUTPUT);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
CommandLineFlagInfo GetCommandLineFlagInfoOrDie(absl::string_view name) {
|
|
||||||
CommandLineFlagInfo info;
|
|
||||||
if (!GetCommandLineFlagInfo(name, &info)) {
|
|
||||||
ABSL_INTERNAL_LOG(FATAL, absl::StrCat("Flag '", name, "' does not exist"));
|
|
||||||
}
|
|
||||||
return info;
|
|
||||||
}
|
|
||||||
|
|
||||||
// --------------------------------------------------------------------
|
|
||||||
|
|
||||||
bool SetCommandLineOption(absl::string_view name, absl::string_view value) {
|
bool SetCommandLineOption(absl::string_view name, absl::string_view value) {
|
||||||
return SetCommandLineOptionWithMode(name, value,
|
return SetCommandLineOptionWithMode(name, value,
|
||||||
flags_internal::SET_FLAGS_VALUE);
|
flags_internal::SET_FLAGS_VALUE);
|
||||||
|
|
|
@ -32,17 +32,6 @@ namespace flags_internal {
|
||||||
// Thread-safe.
|
// Thread-safe.
|
||||||
bool GetCommandLineOption(absl::string_view name, std::string* value);
|
bool GetCommandLineOption(absl::string_view name, std::string* value);
|
||||||
|
|
||||||
// If a flag named "name" exists, store its information in *OUTPUT
|
|
||||||
// and return true. Else return false without changing *OUTPUT.
|
|
||||||
// Thread-safe.
|
|
||||||
bool GetCommandLineFlagInfo(absl::string_view name,
|
|
||||||
CommandLineFlagInfo* OUTPUT);
|
|
||||||
|
|
||||||
// Returns the CommandLineFlagInfo of the flagname. exit() with an
|
|
||||||
// error code if name not found.
|
|
||||||
// Thread-safe.
|
|
||||||
CommandLineFlagInfo GetCommandLineFlagInfoOrDie(absl::string_view name);
|
|
||||||
|
|
||||||
// Set the value of the flag named "name" to value. If successful,
|
// Set the value of the flag named "name" to value. If successful,
|
||||||
// returns true. If not successful (e.g., the flag was not found or
|
// returns true. If not successful (e.g., the flag was not found or
|
||||||
// the value is not a valid value), returns false.
|
// the value is not a valid value), returns false.
|
||||||
|
|
|
@ -44,11 +44,11 @@ namespace {
|
||||||
ABSL_CONST_INIT absl::Mutex processing_checks_guard(absl::kConstInit);
|
ABSL_CONST_INIT absl::Mutex processing_checks_guard(absl::kConstInit);
|
||||||
|
|
||||||
ABSL_CONST_INIT bool flagfile_needs_processing
|
ABSL_CONST_INIT bool flagfile_needs_processing
|
||||||
GUARDED_BY(processing_checks_guard) = false;
|
ABSL_GUARDED_BY(processing_checks_guard) = false;
|
||||||
ABSL_CONST_INIT bool fromenv_needs_processing
|
ABSL_CONST_INIT bool fromenv_needs_processing
|
||||||
GUARDED_BY(processing_checks_guard) = false;
|
ABSL_GUARDED_BY(processing_checks_guard) = false;
|
||||||
ABSL_CONST_INIT bool tryfromenv_needs_processing
|
ABSL_CONST_INIT bool tryfromenv_needs_processing
|
||||||
GUARDED_BY(processing_checks_guard) = false;
|
ABSL_GUARDED_BY(processing_checks_guard) = false;
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
} // namespace flags_internal
|
} // namespace flags_internal
|
||||||
|
|
|
@ -24,7 +24,7 @@ namespace flags_internal {
|
||||||
namespace {
|
namespace {
|
||||||
ABSL_CONST_INIT absl::Mutex usage_message_guard(absl::kConstInit);
|
ABSL_CONST_INIT absl::Mutex usage_message_guard(absl::kConstInit);
|
||||||
ABSL_CONST_INIT std::string* program_usage_message
|
ABSL_CONST_INIT std::string* program_usage_message
|
||||||
GUARDED_BY(usage_message_guard) = nullptr;
|
ABSL_GUARDED_BY(usage_message_guard) = nullptr;
|
||||||
} // namespace
|
} // namespace
|
||||||
} // namespace flags_internal
|
} // namespace flags_internal
|
||||||
|
|
||||||
|
|
|
@ -94,7 +94,7 @@ std::string NormalizeFilename(absl::string_view filename) {
|
||||||
|
|
||||||
ABSL_CONST_INIT absl::Mutex custom_usage_config_guard(absl::kConstInit);
|
ABSL_CONST_INIT absl::Mutex custom_usage_config_guard(absl::kConstInit);
|
||||||
ABSL_CONST_INIT FlagsUsageConfig* custom_usage_config
|
ABSL_CONST_INIT FlagsUsageConfig* custom_usage_config
|
||||||
GUARDED_BY(custom_usage_config_guard) = nullptr;
|
ABSL_GUARDED_BY(custom_usage_config_guard) = nullptr;
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
|
|
|
@ -59,13 +59,13 @@ class RandenPoolEntry {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Copy bytes into out.
|
// Copy bytes into out.
|
||||||
void Fill(uint8_t* out, size_t bytes) LOCKS_EXCLUDED(mu_);
|
void Fill(uint8_t* out, size_t bytes) ABSL_LOCKS_EXCLUDED(mu_);
|
||||||
|
|
||||||
// Returns random bits from the buffer in units of T.
|
// Returns random bits from the buffer in units of T.
|
||||||
template <typename T>
|
template <typename T>
|
||||||
inline T Generate() LOCKS_EXCLUDED(mu_);
|
inline T Generate() ABSL_LOCKS_EXCLUDED(mu_);
|
||||||
|
|
||||||
inline void MaybeRefill() EXCLUSIVE_LOCKS_REQUIRED(mu_) {
|
inline void MaybeRefill() ABSL_EXCLUSIVE_LOCKS_REQUIRED(mu_) {
|
||||||
if (next_ >= kState) {
|
if (next_ >= kState) {
|
||||||
next_ = kCapacity;
|
next_ = kCapacity;
|
||||||
impl_.Generate(state_);
|
impl_.Generate(state_);
|
||||||
|
@ -74,10 +74,10 @@ class RandenPoolEntry {
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// Randen URBG state.
|
// Randen URBG state.
|
||||||
uint32_t state_[kState] GUARDED_BY(mu_); // First to satisfy alignment.
|
uint32_t state_[kState] ABSL_GUARDED_BY(mu_); // First to satisfy alignment.
|
||||||
SpinLock mu_;
|
SpinLock mu_;
|
||||||
const Randen impl_;
|
const Randen impl_;
|
||||||
size_t next_ GUARDED_BY(mu_);
|
size_t next_ ABSL_GUARDED_BY(mu_);
|
||||||
};
|
};
|
||||||
|
|
||||||
template <>
|
template <>
|
||||||
|
|
|
@ -49,6 +49,21 @@ cc_library(
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
|
|
||||||
|
cc_library(
|
||||||
|
name = "kernel_timeout_internal",
|
||||||
|
hdrs = ["internal/kernel_timeout.h"],
|
||||||
|
copts = ABSL_DEFAULT_COPTS,
|
||||||
|
linkopts = ABSL_DEFAULT_LINKOPTS,
|
||||||
|
visibility = [
|
||||||
|
"//absl/synchronization:__pkg__",
|
||||||
|
],
|
||||||
|
deps = [
|
||||||
|
"//absl/base:core_headers",
|
||||||
|
"//absl/base:raw_logging_internal",
|
||||||
|
"//absl/time",
|
||||||
|
],
|
||||||
|
)
|
||||||
|
|
||||||
cc_library(
|
cc_library(
|
||||||
name = "synchronization",
|
name = "synchronization",
|
||||||
srcs = [
|
srcs = [
|
||||||
|
@ -65,7 +80,6 @@ cc_library(
|
||||||
"barrier.h",
|
"barrier.h",
|
||||||
"blocking_counter.h",
|
"blocking_counter.h",
|
||||||
"internal/create_thread_identity.h",
|
"internal/create_thread_identity.h",
|
||||||
"internal/kernel_timeout.h",
|
|
||||||
"internal/mutex_nonprod.inc",
|
"internal/mutex_nonprod.inc",
|
||||||
"internal/per_thread_sem.h",
|
"internal/per_thread_sem.h",
|
||||||
"internal/waiter.h",
|
"internal/waiter.h",
|
||||||
|
@ -79,6 +93,7 @@ cc_library(
|
||||||
}) + ABSL_DEFAULT_LINKOPTS,
|
}) + ABSL_DEFAULT_LINKOPTS,
|
||||||
deps = [
|
deps = [
|
||||||
":graphcycles_internal",
|
":graphcycles_internal",
|
||||||
|
":kernel_timeout_internal",
|
||||||
"//absl/base",
|
"//absl/base",
|
||||||
"//absl/base:atomic_hook",
|
"//absl/base:atomic_hook",
|
||||||
"//absl/base:base_internal",
|
"//absl/base:base_internal",
|
||||||
|
|
|
@ -31,6 +31,19 @@ absl_cc_library(
|
||||||
absl::raw_logging_internal
|
absl::raw_logging_internal
|
||||||
)
|
)
|
||||||
|
|
||||||
|
absl_cc_library(
|
||||||
|
NAME
|
||||||
|
kernel_timeout_internal
|
||||||
|
HDRS
|
||||||
|
"internal/kernel_timeout.h"
|
||||||
|
COPTS
|
||||||
|
${ABSL_DEFAULT_COPTS}
|
||||||
|
DEPS
|
||||||
|
absl::core_headers
|
||||||
|
absl::raw_logging_internal
|
||||||
|
absl::time
|
||||||
|
)
|
||||||
|
|
||||||
absl_cc_library(
|
absl_cc_library(
|
||||||
NAME
|
NAME
|
||||||
synchronization
|
synchronization
|
||||||
|
@ -38,7 +51,6 @@ absl_cc_library(
|
||||||
"barrier.h"
|
"barrier.h"
|
||||||
"blocking_counter.h"
|
"blocking_counter.h"
|
||||||
"internal/create_thread_identity.h"
|
"internal/create_thread_identity.h"
|
||||||
"internal/kernel_timeout.h"
|
|
||||||
"internal/mutex_nonprod.inc"
|
"internal/mutex_nonprod.inc"
|
||||||
"internal/per_thread_sem.h"
|
"internal/per_thread_sem.h"
|
||||||
"internal/waiter.h"
|
"internal/waiter.h"
|
||||||
|
@ -56,6 +68,7 @@ absl_cc_library(
|
||||||
${ABSL_DEFAULT_COPTS}
|
${ABSL_DEFAULT_COPTS}
|
||||||
DEPS
|
DEPS
|
||||||
absl::graphcycles_internal
|
absl::graphcycles_internal
|
||||||
|
absl::kernel_timeout_internal
|
||||||
absl::atomic_hook
|
absl::atomic_hook
|
||||||
absl::base
|
absl::base
|
||||||
absl::base_internal
|
absl::base_internal
|
||||||
|
|
|
@ -69,8 +69,8 @@ class Barrier {
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Mutex lock_;
|
Mutex lock_;
|
||||||
int num_to_block_ GUARDED_BY(lock_);
|
int num_to_block_ ABSL_GUARDED_BY(lock_);
|
||||||
int num_to_exit_ GUARDED_BY(lock_);
|
int num_to_exit_ ABSL_GUARDED_BY(lock_);
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace absl
|
} // namespace absl
|
||||||
|
|
|
@ -88,8 +88,8 @@ class BlockingCounter {
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Mutex lock_;
|
Mutex lock_;
|
||||||
int count_ GUARDED_BY(lock_);
|
int count_ ABSL_GUARDED_BY(lock_);
|
||||||
int num_waiting_ GUARDED_BY(lock_);
|
int num_waiting_ ABSL_GUARDED_BY(lock_);
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace absl
|
} // namespace absl
|
||||||
|
|
|
@ -60,7 +60,7 @@ class ThreadPool {
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool WorkAvailable() const EXCLUSIVE_LOCKS_REQUIRED(mu_) {
|
bool WorkAvailable() const ABSL_EXCLUSIVE_LOCKS_REQUIRED(mu_) {
|
||||||
return !queue_.empty();
|
return !queue_.empty();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -81,7 +81,7 @@ class ThreadPool {
|
||||||
}
|
}
|
||||||
|
|
||||||
absl::Mutex mu_;
|
absl::Mutex mu_;
|
||||||
std::queue<std::function<void()>> queue_ GUARDED_BY(mu_);
|
std::queue<std::function<void()>> queue_ ABSL_GUARDED_BY(mu_);
|
||||||
std::vector<std::thread> threads_;
|
std::vector<std::thread> threads_;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -143,11 +143,11 @@ ABSL_CONST_INIT absl::Mutex early_const_init_mutex(absl::kConstInit);
|
||||||
// constructors of globals "happen at link time"; memory is pre-initialized,
|
// constructors of globals "happen at link time"; memory is pre-initialized,
|
||||||
// before the constructors of either grab_lock or check_still_locked are run.)
|
// before the constructors of either grab_lock or check_still_locked are run.)
|
||||||
extern absl::Mutex const_init_sanity_mutex;
|
extern absl::Mutex const_init_sanity_mutex;
|
||||||
OnConstruction grab_lock([]() NO_THREAD_SAFETY_ANALYSIS {
|
OnConstruction grab_lock([]() ABSL_NO_THREAD_SAFETY_ANALYSIS {
|
||||||
const_init_sanity_mutex.Lock();
|
const_init_sanity_mutex.Lock();
|
||||||
});
|
});
|
||||||
ABSL_CONST_INIT absl::Mutex const_init_sanity_mutex(absl::kConstInit);
|
ABSL_CONST_INIT absl::Mutex const_init_sanity_mutex(absl::kConstInit);
|
||||||
OnConstruction check_still_locked([]() NO_THREAD_SAFETY_ANALYSIS {
|
OnConstruction check_still_locked([]() ABSL_NO_THREAD_SAFETY_ANALYSIS {
|
||||||
const_init_sanity_mutex.AssertHeld();
|
const_init_sanity_mutex.AssertHeld();
|
||||||
const_init_sanity_mutex.Unlock();
|
const_init_sanity_mutex.Unlock();
|
||||||
});
|
});
|
||||||
|
|
|
@ -207,8 +207,8 @@ static absl::base_internal::SpinLock deadlock_graph_mu(
|
||||||
absl::base_internal::kLinkerInitialized);
|
absl::base_internal::kLinkerInitialized);
|
||||||
|
|
||||||
// graph used to detect deadlocks.
|
// graph used to detect deadlocks.
|
||||||
static GraphCycles *deadlock_graph GUARDED_BY(deadlock_graph_mu)
|
static GraphCycles *deadlock_graph ABSL_GUARDED_BY(deadlock_graph_mu)
|
||||||
PT_GUARDED_BY(deadlock_graph_mu);
|
ABSL_PT_GUARDED_BY(deadlock_graph_mu);
|
||||||
|
|
||||||
//------------------------------------------------------------------
|
//------------------------------------------------------------------
|
||||||
// An event mechanism for debugging mutex use.
|
// An event mechanism for debugging mutex use.
|
||||||
|
@ -279,10 +279,10 @@ static const uint32_t kNSynchEvent = 1031;
|
||||||
|
|
||||||
static struct SynchEvent { // this is a trivial hash table for the events
|
static struct SynchEvent { // this is a trivial hash table for the events
|
||||||
// struct is freed when refcount reaches 0
|
// struct is freed when refcount reaches 0
|
||||||
int refcount GUARDED_BY(synch_event_mu);
|
int refcount ABSL_GUARDED_BY(synch_event_mu);
|
||||||
|
|
||||||
// buckets have linear, 0-terminated chains
|
// buckets have linear, 0-terminated chains
|
||||||
SynchEvent *next GUARDED_BY(synch_event_mu);
|
SynchEvent *next ABSL_GUARDED_BY(synch_event_mu);
|
||||||
|
|
||||||
// Constant after initialization
|
// Constant after initialization
|
||||||
uintptr_t masked_addr; // object at this address is called "name"
|
uintptr_t masked_addr; // object at this address is called "name"
|
||||||
|
@ -296,7 +296,7 @@ static struct SynchEvent { // this is a trivial hash table for the events
|
||||||
|
|
||||||
// Constant after initialization
|
// Constant after initialization
|
||||||
char name[1]; // actually longer---null-terminated std::string
|
char name[1]; // actually longer---null-terminated std::string
|
||||||
} *synch_event[kNSynchEvent] GUARDED_BY(synch_event_mu);
|
} * synch_event[kNSynchEvent] ABSL_GUARDED_BY(synch_event_mu);
|
||||||
|
|
||||||
// Ensure that the object at "addr" has a SynchEvent struct associated with it,
|
// Ensure that the object at "addr" has a SynchEvent struct associated with it,
|
||||||
// set "bits" in the word there (waiting until lockbit is clear before doing
|
// set "bits" in the word there (waiting until lockbit is clear before doing
|
||||||
|
@ -1143,7 +1143,7 @@ PerThreadSynch *Mutex::Wakeup(PerThreadSynch *w) {
|
||||||
}
|
}
|
||||||
|
|
||||||
static GraphId GetGraphIdLocked(Mutex *mu)
|
static GraphId GetGraphIdLocked(Mutex *mu)
|
||||||
EXCLUSIVE_LOCKS_REQUIRED(deadlock_graph_mu) {
|
ABSL_EXCLUSIVE_LOCKS_REQUIRED(deadlock_graph_mu) {
|
||||||
if (!deadlock_graph) { // (re)create the deadlock graph.
|
if (!deadlock_graph) { // (re)create the deadlock graph.
|
||||||
deadlock_graph =
|
deadlock_graph =
|
||||||
new (base_internal::LowLevelAlloc::Alloc(sizeof(*deadlock_graph)))
|
new (base_internal::LowLevelAlloc::Alloc(sizeof(*deadlock_graph)))
|
||||||
|
@ -1152,7 +1152,7 @@ static GraphId GetGraphIdLocked(Mutex *mu)
|
||||||
return deadlock_graph->GetId(mu);
|
return deadlock_graph->GetId(mu);
|
||||||
}
|
}
|
||||||
|
|
||||||
static GraphId GetGraphId(Mutex *mu) LOCKS_EXCLUDED(deadlock_graph_mu) {
|
static GraphId GetGraphId(Mutex *mu) ABSL_LOCKS_EXCLUDED(deadlock_graph_mu) {
|
||||||
deadlock_graph_mu.Lock();
|
deadlock_graph_mu.Lock();
|
||||||
GraphId id = GetGraphIdLocked(mu);
|
GraphId id = GetGraphIdLocked(mu);
|
||||||
deadlock_graph_mu.Unlock();
|
deadlock_graph_mu.Unlock();
|
||||||
|
|
|
@ -135,7 +135,7 @@ struct SynchWaitParams;
|
||||||
//
|
//
|
||||||
// See also `MutexLock`, below, for scoped `Mutex` acquisition.
|
// See also `MutexLock`, below, for scoped `Mutex` acquisition.
|
||||||
|
|
||||||
class LOCKABLE Mutex {
|
class ABSL_LOCKABLE Mutex {
|
||||||
public:
|
public:
|
||||||
// Creates a `Mutex` that is not held by anyone. This constructor is
|
// Creates a `Mutex` that is not held by anyone. This constructor is
|
||||||
// typically used for Mutexes allocated on the heap or the stack.
|
// typically used for Mutexes allocated on the heap or the stack.
|
||||||
|
@ -164,27 +164,27 @@ class LOCKABLE Mutex {
|
||||||
//
|
//
|
||||||
// Blocks the calling thread, if necessary, until this `Mutex` is free, and
|
// Blocks the calling thread, if necessary, until this `Mutex` is free, and
|
||||||
// then acquires it exclusively. (This lock is also known as a "write lock.")
|
// then acquires it exclusively. (This lock is also known as a "write lock.")
|
||||||
void Lock() EXCLUSIVE_LOCK_FUNCTION();
|
void Lock() ABSL_EXCLUSIVE_LOCK_FUNCTION();
|
||||||
|
|
||||||
// Mutex::Unlock()
|
// Mutex::Unlock()
|
||||||
//
|
//
|
||||||
// Releases this `Mutex` and returns it from the exclusive/write state to the
|
// Releases this `Mutex` and returns it from the exclusive/write state to the
|
||||||
// free state. Caller must hold the `Mutex` exclusively.
|
// free state. Caller must hold the `Mutex` exclusively.
|
||||||
void Unlock() UNLOCK_FUNCTION();
|
void Unlock() ABSL_UNLOCK_FUNCTION();
|
||||||
|
|
||||||
// Mutex::TryLock()
|
// Mutex::TryLock()
|
||||||
//
|
//
|
||||||
// If the mutex can be acquired without blocking, does so exclusively and
|
// If the mutex can be acquired without blocking, does so exclusively and
|
||||||
// returns `true`. Otherwise, returns `false`. Returns `true` with high
|
// returns `true`. Otherwise, returns `false`. Returns `true` with high
|
||||||
// probability if the `Mutex` was free.
|
// probability if the `Mutex` was free.
|
||||||
bool TryLock() EXCLUSIVE_TRYLOCK_FUNCTION(true);
|
bool TryLock() ABSL_EXCLUSIVE_TRYLOCK_FUNCTION(true);
|
||||||
|
|
||||||
// Mutex::AssertHeld()
|
// Mutex::AssertHeld()
|
||||||
//
|
//
|
||||||
// Return immediately if this thread holds the `Mutex` exclusively (in write
|
// Return immediately if this thread holds the `Mutex` exclusively (in write
|
||||||
// mode). Otherwise, may report an error (typically by crashing with a
|
// mode). Otherwise, may report an error (typically by crashing with a
|
||||||
// diagnostic), or may return immediately.
|
// diagnostic), or may return immediately.
|
||||||
void AssertHeld() const ASSERT_EXCLUSIVE_LOCK();
|
void AssertHeld() const ABSL_ASSERT_EXCLUSIVE_LOCK();
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
||||||
// Reader-Writer Locking
|
// Reader-Writer Locking
|
||||||
|
@ -225,28 +225,28 @@ class LOCKABLE Mutex {
|
||||||
// `ReaderLock()` will block if some other thread has an exclusive/writer lock
|
// `ReaderLock()` will block if some other thread has an exclusive/writer lock
|
||||||
// on the mutex.
|
// on the mutex.
|
||||||
|
|
||||||
void ReaderLock() SHARED_LOCK_FUNCTION();
|
void ReaderLock() ABSL_SHARED_LOCK_FUNCTION();
|
||||||
|
|
||||||
// Mutex::ReaderUnlock()
|
// Mutex::ReaderUnlock()
|
||||||
//
|
//
|
||||||
// Releases a read share of this `Mutex`. `ReaderUnlock` may return a mutex to
|
// Releases a read share of this `Mutex`. `ReaderUnlock` may return a mutex to
|
||||||
// the free state if this thread holds the last reader lock on the mutex. Note
|
// the free state if this thread holds the last reader lock on the mutex. Note
|
||||||
// that you cannot call `ReaderUnlock()` on a mutex held in write mode.
|
// that you cannot call `ReaderUnlock()` on a mutex held in write mode.
|
||||||
void ReaderUnlock() UNLOCK_FUNCTION();
|
void ReaderUnlock() ABSL_UNLOCK_FUNCTION();
|
||||||
|
|
||||||
// Mutex::ReaderTryLock()
|
// Mutex::ReaderTryLock()
|
||||||
//
|
//
|
||||||
// If the mutex can be acquired without blocking, acquires this mutex for
|
// If the mutex can be acquired without blocking, acquires this mutex for
|
||||||
// shared access and returns `true`. Otherwise, returns `false`. Returns
|
// shared access and returns `true`. Otherwise, returns `false`. Returns
|
||||||
// `true` with high probability if the `Mutex` was free or shared.
|
// `true` with high probability if the `Mutex` was free or shared.
|
||||||
bool ReaderTryLock() SHARED_TRYLOCK_FUNCTION(true);
|
bool ReaderTryLock() ABSL_SHARED_TRYLOCK_FUNCTION(true);
|
||||||
|
|
||||||
// Mutex::AssertReaderHeld()
|
// Mutex::AssertReaderHeld()
|
||||||
//
|
//
|
||||||
// Returns immediately if this thread holds the `Mutex` in at least shared
|
// Returns immediately if this thread holds the `Mutex` in at least shared
|
||||||
// mode (read mode). Otherwise, may report an error (typically by
|
// mode (read mode). Otherwise, may report an error (typically by
|
||||||
// crashing with a diagnostic), or may return immediately.
|
// crashing with a diagnostic), or may return immediately.
|
||||||
void AssertReaderHeld() const ASSERT_SHARED_LOCK();
|
void AssertReaderHeld() const ABSL_ASSERT_SHARED_LOCK();
|
||||||
|
|
||||||
// Mutex::WriterLock()
|
// Mutex::WriterLock()
|
||||||
// Mutex::WriterUnlock()
|
// Mutex::WriterUnlock()
|
||||||
|
@ -257,11 +257,11 @@ class LOCKABLE Mutex {
|
||||||
// These methods may be used (along with the complementary `Reader*()`
|
// These methods may be used (along with the complementary `Reader*()`
|
||||||
// methods) to distingish simple exclusive `Mutex` usage (`Lock()`,
|
// methods) to distingish simple exclusive `Mutex` usage (`Lock()`,
|
||||||
// etc.) from reader/writer lock usage.
|
// etc.) from reader/writer lock usage.
|
||||||
void WriterLock() EXCLUSIVE_LOCK_FUNCTION() { this->Lock(); }
|
void WriterLock() ABSL_EXCLUSIVE_LOCK_FUNCTION() { this->Lock(); }
|
||||||
|
|
||||||
void WriterUnlock() UNLOCK_FUNCTION() { this->Unlock(); }
|
void WriterUnlock() ABSL_UNLOCK_FUNCTION() { this->Unlock(); }
|
||||||
|
|
||||||
bool WriterTryLock() EXCLUSIVE_TRYLOCK_FUNCTION(true) {
|
bool WriterTryLock() ABSL_EXCLUSIVE_TRYLOCK_FUNCTION(true) {
|
||||||
return this->TryLock();
|
return this->TryLock();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -315,11 +315,11 @@ class LOCKABLE Mutex {
|
||||||
// be acquired, then atomically acquires this `Mutex`. `LockWhen()` is
|
// be acquired, then atomically acquires this `Mutex`. `LockWhen()` is
|
||||||
// logically equivalent to `*Lock(); Await();` though they may have different
|
// logically equivalent to `*Lock(); Await();` though they may have different
|
||||||
// performance characteristics.
|
// performance characteristics.
|
||||||
void LockWhen(const Condition &cond) EXCLUSIVE_LOCK_FUNCTION();
|
void LockWhen(const Condition &cond) ABSL_EXCLUSIVE_LOCK_FUNCTION();
|
||||||
|
|
||||||
void ReaderLockWhen(const Condition &cond) SHARED_LOCK_FUNCTION();
|
void ReaderLockWhen(const Condition &cond) ABSL_SHARED_LOCK_FUNCTION();
|
||||||
|
|
||||||
void WriterLockWhen(const Condition &cond) EXCLUSIVE_LOCK_FUNCTION() {
|
void WriterLockWhen(const Condition &cond) ABSL_EXCLUSIVE_LOCK_FUNCTION() {
|
||||||
this->LockWhen(cond);
|
this->LockWhen(cond);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -361,11 +361,11 @@ class LOCKABLE Mutex {
|
||||||
//
|
//
|
||||||
// Negative timeouts are equivalent to a zero timeout.
|
// Negative timeouts are equivalent to a zero timeout.
|
||||||
bool LockWhenWithTimeout(const Condition &cond, absl::Duration timeout)
|
bool LockWhenWithTimeout(const Condition &cond, absl::Duration timeout)
|
||||||
EXCLUSIVE_LOCK_FUNCTION();
|
ABSL_EXCLUSIVE_LOCK_FUNCTION();
|
||||||
bool ReaderLockWhenWithTimeout(const Condition &cond, absl::Duration timeout)
|
bool ReaderLockWhenWithTimeout(const Condition &cond, absl::Duration timeout)
|
||||||
SHARED_LOCK_FUNCTION();
|
ABSL_SHARED_LOCK_FUNCTION();
|
||||||
bool WriterLockWhenWithTimeout(const Condition &cond, absl::Duration timeout)
|
bool WriterLockWhenWithTimeout(const Condition &cond, absl::Duration timeout)
|
||||||
EXCLUSIVE_LOCK_FUNCTION() {
|
ABSL_EXCLUSIVE_LOCK_FUNCTION() {
|
||||||
return this->LockWhenWithTimeout(cond, timeout);
|
return this->LockWhenWithTimeout(cond, timeout);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -381,11 +381,11 @@ class LOCKABLE Mutex {
|
||||||
//
|
//
|
||||||
// Deadlines in the past are equivalent to an immediate deadline.
|
// Deadlines in the past are equivalent to an immediate deadline.
|
||||||
bool LockWhenWithDeadline(const Condition &cond, absl::Time deadline)
|
bool LockWhenWithDeadline(const Condition &cond, absl::Time deadline)
|
||||||
EXCLUSIVE_LOCK_FUNCTION();
|
ABSL_EXCLUSIVE_LOCK_FUNCTION();
|
||||||
bool ReaderLockWhenWithDeadline(const Condition &cond, absl::Time deadline)
|
bool ReaderLockWhenWithDeadline(const Condition &cond, absl::Time deadline)
|
||||||
SHARED_LOCK_FUNCTION();
|
ABSL_SHARED_LOCK_FUNCTION();
|
||||||
bool WriterLockWhenWithDeadline(const Condition &cond, absl::Time deadline)
|
bool WriterLockWhenWithDeadline(const Condition &cond, absl::Time deadline)
|
||||||
EXCLUSIVE_LOCK_FUNCTION() {
|
ABSL_EXCLUSIVE_LOCK_FUNCTION() {
|
||||||
return this->LockWhenWithDeadline(cond, deadline);
|
return this->LockWhenWithDeadline(cond, deadline);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -535,9 +535,9 @@ class LOCKABLE Mutex {
|
||||||
// private:
|
// private:
|
||||||
// Mutex lock_;
|
// Mutex lock_;
|
||||||
// };
|
// };
|
||||||
class SCOPED_LOCKABLE MutexLock {
|
class ABSL_SCOPED_LOCKABLE MutexLock {
|
||||||
public:
|
public:
|
||||||
explicit MutexLock(Mutex *mu) EXCLUSIVE_LOCK_FUNCTION(mu) : mu_(mu) {
|
explicit MutexLock(Mutex *mu) ABSL_EXCLUSIVE_LOCK_FUNCTION(mu) : mu_(mu) {
|
||||||
this->mu_->Lock();
|
this->mu_->Lock();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -546,7 +546,7 @@ class SCOPED_LOCKABLE MutexLock {
|
||||||
MutexLock& operator=(const MutexLock&) = delete;
|
MutexLock& operator=(const MutexLock&) = delete;
|
||||||
MutexLock& operator=(MutexLock&&) = delete;
|
MutexLock& operator=(MutexLock&&) = delete;
|
||||||
|
|
||||||
~MutexLock() UNLOCK_FUNCTION() { this->mu_->Unlock(); }
|
~MutexLock() ABSL_UNLOCK_FUNCTION() { this->mu_->Unlock(); }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Mutex *const mu_;
|
Mutex *const mu_;
|
||||||
|
@ -556,10 +556,9 @@ class SCOPED_LOCKABLE MutexLock {
|
||||||
//
|
//
|
||||||
// The `ReaderMutexLock` is a helper class, like `MutexLock`, which acquires and
|
// The `ReaderMutexLock` is a helper class, like `MutexLock`, which acquires and
|
||||||
// releases a shared lock on a `Mutex` via RAII.
|
// releases a shared lock on a `Mutex` via RAII.
|
||||||
class SCOPED_LOCKABLE ReaderMutexLock {
|
class ABSL_SCOPED_LOCKABLE ReaderMutexLock {
|
||||||
public:
|
public:
|
||||||
explicit ReaderMutexLock(Mutex *mu) SHARED_LOCK_FUNCTION(mu)
|
explicit ReaderMutexLock(Mutex *mu) ABSL_SHARED_LOCK_FUNCTION(mu) : mu_(mu) {
|
||||||
: mu_(mu) {
|
|
||||||
mu->ReaderLock();
|
mu->ReaderLock();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -568,9 +567,7 @@ class SCOPED_LOCKABLE ReaderMutexLock {
|
||||||
ReaderMutexLock& operator=(const ReaderMutexLock&) = delete;
|
ReaderMutexLock& operator=(const ReaderMutexLock&) = delete;
|
||||||
ReaderMutexLock& operator=(ReaderMutexLock&&) = delete;
|
ReaderMutexLock& operator=(ReaderMutexLock&&) = delete;
|
||||||
|
|
||||||
~ReaderMutexLock() UNLOCK_FUNCTION() {
|
~ReaderMutexLock() ABSL_UNLOCK_FUNCTION() { this->mu_->ReaderUnlock(); }
|
||||||
this->mu_->ReaderUnlock();
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Mutex *const mu_;
|
Mutex *const mu_;
|
||||||
|
@ -580,9 +577,9 @@ class SCOPED_LOCKABLE ReaderMutexLock {
|
||||||
//
|
//
|
||||||
// The `WriterMutexLock` is a helper class, like `MutexLock`, which acquires and
|
// The `WriterMutexLock` is a helper class, like `MutexLock`, which acquires and
|
||||||
// releases a write (exclusive) lock on a `Mutex` via RAII.
|
// releases a write (exclusive) lock on a `Mutex` via RAII.
|
||||||
class SCOPED_LOCKABLE WriterMutexLock {
|
class ABSL_SCOPED_LOCKABLE WriterMutexLock {
|
||||||
public:
|
public:
|
||||||
explicit WriterMutexLock(Mutex *mu) EXCLUSIVE_LOCK_FUNCTION(mu)
|
explicit WriterMutexLock(Mutex *mu) ABSL_EXCLUSIVE_LOCK_FUNCTION(mu)
|
||||||
: mu_(mu) {
|
: mu_(mu) {
|
||||||
mu->WriterLock();
|
mu->WriterLock();
|
||||||
}
|
}
|
||||||
|
@ -592,9 +589,7 @@ class SCOPED_LOCKABLE WriterMutexLock {
|
||||||
WriterMutexLock& operator=(const WriterMutexLock&) = delete;
|
WriterMutexLock& operator=(const WriterMutexLock&) = delete;
|
||||||
WriterMutexLock& operator=(WriterMutexLock&&) = delete;
|
WriterMutexLock& operator=(WriterMutexLock&&) = delete;
|
||||||
|
|
||||||
~WriterMutexLock() UNLOCK_FUNCTION() {
|
~WriterMutexLock() ABSL_UNLOCK_FUNCTION() { this->mu_->WriterUnlock(); }
|
||||||
this->mu_->WriterUnlock();
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Mutex *const mu_;
|
Mutex *const mu_;
|
||||||
|
@ -860,13 +855,18 @@ class CondVar {
|
||||||
// MutexLockMaybe
|
// MutexLockMaybe
|
||||||
//
|
//
|
||||||
// MutexLockMaybe is like MutexLock, but is a no-op when mu is null.
|
// MutexLockMaybe is like MutexLock, but is a no-op when mu is null.
|
||||||
class SCOPED_LOCKABLE MutexLockMaybe {
|
class ABSL_SCOPED_LOCKABLE MutexLockMaybe {
|
||||||
public:
|
public:
|
||||||
explicit MutexLockMaybe(Mutex *mu) EXCLUSIVE_LOCK_FUNCTION(mu)
|
explicit MutexLockMaybe(Mutex *mu) ABSL_EXCLUSIVE_LOCK_FUNCTION(mu)
|
||||||
: mu_(mu) { if (this->mu_ != nullptr) { this->mu_->Lock(); } }
|
: mu_(mu) {
|
||||||
~MutexLockMaybe() UNLOCK_FUNCTION() {
|
if (this->mu_ != nullptr) {
|
||||||
|
this->mu_->Lock();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
~MutexLockMaybe() ABSL_UNLOCK_FUNCTION() {
|
||||||
if (this->mu_ != nullptr) { this->mu_->Unlock(); }
|
if (this->mu_ != nullptr) { this->mu_->Unlock(); }
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Mutex *const mu_;
|
Mutex *const mu_;
|
||||||
MutexLockMaybe(const MutexLockMaybe&) = delete;
|
MutexLockMaybe(const MutexLockMaybe&) = delete;
|
||||||
|
@ -879,17 +879,17 @@ class SCOPED_LOCKABLE MutexLockMaybe {
|
||||||
//
|
//
|
||||||
// ReleasableMutexLock is like MutexLock, but permits `Release()` of its
|
// ReleasableMutexLock is like MutexLock, but permits `Release()` of its
|
||||||
// mutex before destruction. `Release()` may be called at most once.
|
// mutex before destruction. `Release()` may be called at most once.
|
||||||
class SCOPED_LOCKABLE ReleasableMutexLock {
|
class ABSL_SCOPED_LOCKABLE ReleasableMutexLock {
|
||||||
public:
|
public:
|
||||||
explicit ReleasableMutexLock(Mutex *mu) EXCLUSIVE_LOCK_FUNCTION(mu)
|
explicit ReleasableMutexLock(Mutex *mu) ABSL_EXCLUSIVE_LOCK_FUNCTION(mu)
|
||||||
: mu_(mu) {
|
: mu_(mu) {
|
||||||
this->mu_->Lock();
|
this->mu_->Lock();
|
||||||
}
|
}
|
||||||
~ReleasableMutexLock() UNLOCK_FUNCTION() {
|
~ReleasableMutexLock() ABSL_UNLOCK_FUNCTION() {
|
||||||
if (this->mu_ != nullptr) { this->mu_->Unlock(); }
|
if (this->mu_ != nullptr) { this->mu_->Unlock(); }
|
||||||
}
|
}
|
||||||
|
|
||||||
void Release() UNLOCK_FUNCTION();
|
void Release() ABSL_UNLOCK_FUNCTION();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Mutex *mu_;
|
Mutex *mu_;
|
||||||
|
|
|
@ -425,10 +425,10 @@ TEST(Mutex, CondVarWaitSignalsAwait) {
|
||||||
// Use a struct so the lock annotations apply.
|
// Use a struct so the lock annotations apply.
|
||||||
struct {
|
struct {
|
||||||
absl::Mutex barrier_mu;
|
absl::Mutex barrier_mu;
|
||||||
bool barrier GUARDED_BY(barrier_mu) = false;
|
bool barrier ABSL_GUARDED_BY(barrier_mu) = false;
|
||||||
|
|
||||||
absl::Mutex release_mu;
|
absl::Mutex release_mu;
|
||||||
bool release GUARDED_BY(release_mu) = false;
|
bool release ABSL_GUARDED_BY(release_mu) = false;
|
||||||
absl::CondVar released_cv;
|
absl::CondVar released_cv;
|
||||||
} state;
|
} state;
|
||||||
|
|
||||||
|
@ -466,10 +466,10 @@ TEST(Mutex, CondVarWaitWithTimeoutSignalsAwait) {
|
||||||
// Use a struct so the lock annotations apply.
|
// Use a struct so the lock annotations apply.
|
||||||
struct {
|
struct {
|
||||||
absl::Mutex barrier_mu;
|
absl::Mutex barrier_mu;
|
||||||
bool barrier GUARDED_BY(barrier_mu) = false;
|
bool barrier ABSL_GUARDED_BY(barrier_mu) = false;
|
||||||
|
|
||||||
absl::Mutex release_mu;
|
absl::Mutex release_mu;
|
||||||
bool release GUARDED_BY(release_mu) = false;
|
bool release ABSL_GUARDED_BY(release_mu) = false;
|
||||||
absl::CondVar released_cv;
|
absl::CondVar released_cv;
|
||||||
} state;
|
} state;
|
||||||
|
|
||||||
|
@ -770,7 +770,7 @@ static void GetReadLock(ReaderDecrementBugStruct *x) {
|
||||||
|
|
||||||
// Test for reader counter being decremented incorrectly by waiter
|
// Test for reader counter being decremented incorrectly by waiter
|
||||||
// with false condition.
|
// with false condition.
|
||||||
TEST(Mutex, MutexReaderDecrementBug) NO_THREAD_SAFETY_ANALYSIS {
|
TEST(Mutex, MutexReaderDecrementBug) ABSL_NO_THREAD_SAFETY_ANALYSIS {
|
||||||
ReaderDecrementBugStruct x;
|
ReaderDecrementBugStruct x;
|
||||||
x.cond = false;
|
x.cond = false;
|
||||||
x.waiting_on_cond = false;
|
x.waiting_on_cond = false;
|
||||||
|
@ -819,7 +819,7 @@ TEST(Mutex, MutexReaderDecrementBug) NO_THREAD_SAFETY_ANALYSIS {
|
||||||
// TSAN reports errors when locked Mutexes are destroyed.
|
// TSAN reports errors when locked Mutexes are destroyed.
|
||||||
TEST(Mutex, DISABLED_LockedMutexDestructionBug) NO_THREAD_SAFETY_ANALYSIS {
|
TEST(Mutex, DISABLED_LockedMutexDestructionBug) NO_THREAD_SAFETY_ANALYSIS {
|
||||||
#else
|
#else
|
||||||
TEST(Mutex, LockedMutexDestructionBug) NO_THREAD_SAFETY_ANALYSIS {
|
TEST(Mutex, LockedMutexDestructionBug) ABSL_NO_THREAD_SAFETY_ANALYSIS {
|
||||||
#endif
|
#endif
|
||||||
for (int i = 0; i != 10; i++) {
|
for (int i = 0; i != 10; i++) {
|
||||||
// Create, lock and destroy 10 locks.
|
// Create, lock and destroy 10 locks.
|
||||||
|
@ -1101,7 +1101,7 @@ TEST(Mutex, DeadlockDetectorBazelWarning) {
|
||||||
// annotation-based static thread-safety analysis is not currently
|
// annotation-based static thread-safety analysis is not currently
|
||||||
// predicate-aware and cannot tell if the two for-loops that acquire and
|
// predicate-aware and cannot tell if the two for-loops that acquire and
|
||||||
// release the locks have the same predicates.
|
// release the locks have the same predicates.
|
||||||
TEST(Mutex, DeadlockDetectorStessTest) NO_THREAD_SAFETY_ANALYSIS {
|
TEST(Mutex, DeadlockDetectorStessTest) ABSL_NO_THREAD_SAFETY_ANALYSIS {
|
||||||
// Stress test: Here we create a large number of locks and use all of them.
|
// Stress test: Here we create a large number of locks and use all of them.
|
||||||
// If a deadlock detector keeps a full graph of lock acquisition order,
|
// If a deadlock detector keeps a full graph of lock acquisition order,
|
||||||
// it will likely be too slow for this test to pass.
|
// it will likely be too slow for this test to pass.
|
||||||
|
@ -1123,7 +1123,7 @@ TEST(Mutex, DeadlockDetectorStessTest) NO_THREAD_SAFETY_ANALYSIS {
|
||||||
// TSAN reports errors when locked Mutexes are destroyed.
|
// TSAN reports errors when locked Mutexes are destroyed.
|
||||||
TEST(Mutex, DISABLED_DeadlockIdBug) NO_THREAD_SAFETY_ANALYSIS {
|
TEST(Mutex, DISABLED_DeadlockIdBug) NO_THREAD_SAFETY_ANALYSIS {
|
||||||
#else
|
#else
|
||||||
TEST(Mutex, DeadlockIdBug) NO_THREAD_SAFETY_ANALYSIS {
|
TEST(Mutex, DeadlockIdBug) ABSL_NO_THREAD_SAFETY_ANALYSIS {
|
||||||
#endif
|
#endif
|
||||||
// Test a scenario where a cached deadlock graph node id in the
|
// Test a scenario where a cached deadlock graph node id in the
|
||||||
// list of held locks is not invalidated when the corresponding
|
// list of held locks is not invalidated when the corresponding
|
||||||
|
|
|
@ -1103,7 +1103,7 @@ inline Time FromCivil(CivilSecond ct, TimeZone tz) {
|
||||||
// An `absl::TimeConversion` represents the conversion of year, month, day,
|
// An `absl::TimeConversion` represents the conversion of year, month, day,
|
||||||
// hour, minute, and second values (i.e., a civil time), in a particular
|
// hour, minute, and second values (i.e., a civil time), in a particular
|
||||||
// `absl::TimeZone`, to a time instant (an absolute time), as returned by
|
// `absl::TimeZone`, to a time instant (an absolute time), as returned by
|
||||||
// `absl::ConvertDateTime()`. Lecacy version of `absl::TimeZone::TimeInfo`.
|
// `absl::ConvertDateTime()`. Legacy version of `absl::TimeZone::TimeInfo`.
|
||||||
//
|
//
|
||||||
// Deprecated. Use `absl::TimeZone::TimeInfo`.
|
// Deprecated. Use `absl::TimeZone::TimeInfo`.
|
||||||
struct
|
struct
|
||||||
|
|
Loading…
Reference in a new issue