Skip to content

Commit

Permalink
Export of internal Abseil changes
Browse files Browse the repository at this point in the history
--
d6748c733a70cd74ad9b76a0c9cd6b3fe2cecacf by Xiaoyi Zhang <zhangxy@google.com>:

Remove empty block, to address alerts reported in
#368.

PiperOrigin-RevId: 265099887

--
232e2036b5668d6d1296b881f9347756d84541ee by Derek Mauro <dmauro@google.com>:

Make the Linux Bazel CI scripts test with the exception mode explicitly set.

PiperOrigin-RevId: 265092105

--
942a40696c2c9b833be03e92d22a6ede7bccb6d4 by Xiaoyi Zhang <zhangxy@google.com>:

Import #372.
Suppress the unused variable warning on GCC, i.e. "-Wunused-variable".

PiperOrigin-RevId: 265063925

--
7ef90796b52cbdc260afc77cf47206f9356471d0 by Xiaoyi Zhang <zhangxy@google.com>:

Add quotes to `ABSL_COMMON_INCLUDE_DIRS` since it's a list and may contain a
`;`. This addresses #373.

PiperOrigin-RevId: 265059077

--
43f3ae742e00b83672ad6c5bc5b17fdb8f9fe6fe by Gennadiy Rozental <rogeeff@google.com>:

Internal re-organization

PiperOrigin-RevId: 264913945

--
6a2adf9c08ee1d98cc6b2855a676345c6495294a by Andy Soffer <asoffer@google.com>:

Publicly expose type names for uniform interval tags as in, for example, absl::IntervalClosedClosedTag, and add equality comparison operators.

PiperOrigin-RevId: 264861162

--
3c90c6e05fd61d56b419cd2d39dab8f17b8711b8 by Abseil Team <absl-team@google.com>:

Add validity check on returned frame pointer.

PiperOrigin-RevId: 264858823

--
2db87e0cfa0c6bea7ba81684b834cb8a73b7d748 by Gennadiy Rozental <rogeeff@google.com>:

Add MUST_USE_RESULT attribute to absl::GetFlag to prevent accidental misuse.

PiperOrigin-RevId: 264782762
GitOrigin-RevId: d6748c733a70cd74ad9b76a0c9cd6b3fe2cecacf
Change-Id: I169e9c5358e4f63000c1255e806d26b8afecf5ff
  • Loading branch information
Abseil Team authored and Xiaoyi Zhang committed Aug 23, 2019
1 parent 0302d1e commit 2d2d7fb
Show file tree
Hide file tree
Showing 24 changed files with 549 additions and 392 deletions.
4 changes: 2 additions & 2 deletions CMake/AbseilHelpers.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,7 @@ function(absl_cc_library)
target_sources(${_NAME} PRIVATE ${ABSL_CC_LIB_SRCS} ${ABSL_CC_LIB_HDRS})
target_include_directories(${_NAME}
PUBLIC
$<BUILD_INTERFACE:${ABSL_COMMON_INCLUDE_DIRS}>
"$<BUILD_INTERFACE:${ABSL_COMMON_INCLUDE_DIRS}>"
$<INSTALL_INTERFACE:${ABSL_INSTALL_INCLUDEDIR}>
)
target_compile_options(${_NAME}
Expand Down Expand Up @@ -145,7 +145,7 @@ function(absl_cc_library)
add_library(${_NAME} INTERFACE)
target_include_directories(${_NAME}
INTERFACE
$<BUILD_INTERFACE:${ABSL_COMMON_INCLUDE_DIRS}>
"$<BUILD_INTERFACE:${ABSL_COMMON_INCLUDE_DIRS}>"
$<INSTALL_INTERFACE:${ABSL_INSTALL_INCLUDEDIR}>
)
target_link_libraries(${_NAME}
Expand Down
3 changes: 1 addition & 2 deletions absl/base/internal/spinlock.h
Original file line number Diff line number Diff line change
Expand Up @@ -225,11 +225,10 @@ inline uint32_t SpinLock::TryLockInternal(uint32_t lock_value,
}
}

if (lockword_.compare_exchange_strong(
if (!lockword_.compare_exchange_strong(
lock_value,
kSpinLockHeld | lock_value | wait_cycles | sched_disabled_bit,
std::memory_order_acquire, std::memory_order_relaxed)) {
} else {
base_internal::SchedulingGuard::EnableRescheduling(sched_disabled_bit != 0);
}

Expand Down
8 changes: 5 additions & 3 deletions absl/debugging/internal/stacktrace_x86-inl.inc
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,8 @@

#include "absl/base/internal/raw_logging.h"

using absl::debugging_internal::AddressIsReadable;

#if defined(__linux__) && defined(__i386__)
// Count "push %reg" instructions in VDSO __kernel_vsyscall(),
// preceeding "syscall" or "sysenter".
Expand Down Expand Up @@ -81,7 +83,7 @@ static int CountPushInstructions(const unsigned char *const addr) {
// "mov reg,reg"
if (addr[i + 1] == 0xE5) {
// Found "mov %esp,%ebp".
return 0;
return 0;
}
++i; // Skip register encoding byte.
} else if (addr[i] == 0x0F &&
Expand Down Expand Up @@ -222,7 +224,7 @@ static void **NextStackFrame(void **old_fp, const void *uc) {
// "double fault" in case we hit the first fault due to e.g. stack
// corruption.
void *const reg_esp2 = reg_esp[num_push_instructions - 1];
if (absl::debugging_internal::AddressIsReadable(reg_esp2)) {
if (AddressIsReadable(reg_esp2)) {
// Alleged %esp is readable, use it for further unwinding.
new_fp = reinterpret_cast<void **>(reg_esp2);
}
Expand Down Expand Up @@ -274,7 +276,7 @@ static void **NextStackFrame(void **old_fp, const void *uc) {
// Note: NextStackFrame<false>() is only called while the program
// is already on its last leg, so it's ok to be slow here.

if (!absl::debugging_internal::AddressIsReadable(new_fp)) {
if (!AddressIsReadable(new_fp)) {
return nullptr;
}
}
Expand Down
2 changes: 2 additions & 0 deletions absl/flags/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,7 @@ cc_library(
name = "flag",
srcs = [
"flag.cc",
"internal/flag.cc",
],
hdrs = [
"declare.h",
Expand All @@ -152,6 +153,7 @@ cc_library(
"//absl/base",
"//absl/base:core_headers",
"//absl/strings",
"//absl/synchronization",
],
)

Expand Down
2 changes: 2 additions & 0 deletions absl/flags/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,7 @@ absl_cc_library(
flags
SRCS
"flag.cc"
"internal/flag.cc"
HDRS
"declare.h"
"flag.h"
Expand All @@ -136,6 +137,7 @@ absl_cc_library(
absl::base
absl::core_headers
absl::strings
absl::synchronization
)

# Internal-only target, do not depend on directly.
Expand Down
5 changes: 5 additions & 0 deletions absl/flags/declare.h
Original file line number Diff line number Diff line change
Expand Up @@ -39,8 +39,13 @@ class Flag;
// Flag
//
// Forward declaration of the `absl::Flag` type for use in defining the macro.
#if defined(_MSC_VER)
template <typename T>
class Flag;
#else
template <typename T>
using Flag = flags_internal::Flag<T>;
#endif

} // namespace absl

Expand Down
16 changes: 16 additions & 0 deletions absl/flags/flag.cc
Original file line number Diff line number Diff line change
Expand Up @@ -41,4 +41,20 @@ ABSL_FLAGS_INTERNAL_FOR_EACH_LOCK_FREE(ABSL_FLAGS_ATOMIC_GET)

#undef ABSL_FLAGS_ATOMIC_GET

// This global nutex protects on-demand construction of flag objects in MSVC
// builds.
#if defined(_MSC_VER)

namespace flags_internal {

ABSL_CONST_INIT static absl::Mutex construction_guard(absl::kConstInit);

void LockGlobalConstructionGuard() { construction_guard.Lock(); }

void UnlockGlobalConstructionGuard() { construction_guard.Unlock(); }

} // namespace flags_internal

#endif

} // namespace absl
106 changes: 104 additions & 2 deletions absl/flags/flag.h
Original file line number Diff line number Diff line change
Expand Up @@ -63,8 +63,100 @@ namespace absl {
// ABSL_FLAG(int, count, 0, "Count of items to process");
//
// No public methods of `absl::Flag<T>` are part of the Abseil Flags API.
#if !defined(_MSC_VER)
template <typename T>
using Flag = flags_internal::Flag<T>;
#else
// MSVC debug builds do not implement constexpr correctly for classes with
// virtual methods. To work around this we adding level of indirection, so that
// the class `absl::Flag` contains an `internal::Flag*` (instead of being an
// alias to that class) and dynamically allocates an instance when necessary.
// We also forward all calls to internal::Flag methods via trampoline methods.
// In this setup the `absl::Flag` class does not have virtual methods and thus
// MSVC is able to initialize it at link time. To deal with multiple threads
// accessing the flag for the first time concurrently we use an atomic boolean
// indicating if flag object is constructed. We also employ the double-checked
// locking pattern where the second level of protection is a global Mutex, so
// if two threads attempt to construct the flag concurrently only one wins.

namespace flags_internal {
void LockGlobalConstructionGuard();
void UnlockGlobalConstructionGuard();
} // namespace flags_internal

template <typename T>
class Flag {
public:
constexpr Flag(const char* name, const flags_internal::HelpGenFunc help_gen,
const char* filename,
const flags_internal::FlagMarshallingOpFn marshalling_op,
const flags_internal::InitialValGenFunc initial_value_gen)
: name_(name),
help_gen_(help_gen),
filename_(filename),
marshalling_op_(marshalling_op),
initial_value_gen_(initial_value_gen),
inited_(false) {}

flags_internal::Flag<T>* GetImpl() const {
if (!inited_.load(std::memory_order_acquire)) {
flags_internal::LockGlobalConstructionGuard();

if (inited_.load(std::memory_order_acquire)) {
return impl_;
}

impl_ = new flags_internal::Flag<T>(name_, help_gen_, filename_,
marshalling_op_, initial_value_gen_);
inited_.store(true, std::memory_order_release);

flags_internal::UnlockGlobalConstructionGuard();
}

return impl_;
}

// absl::Flag API
bool IsRetired() const { return GetImpl()->IsRetired(); }
bool IsAbseilFlag() const { return GetImpl()->IsAbseilFlag(); }
absl::string_view Name() const { return GetImpl()->Name(); }
std::string Help() const { return GetImpl()->Help(); }
bool IsModified() const { return GetImpl()->IsModified(); }
void SetModified(bool is_modified) { GetImpl()->SetModified(is_modified); }
bool IsSpecifiedOnCommandLine() const {
GetImpl()->IsSpecifiedOnCommandLine();
}
absl::string_view Typename() const { return GetImpl()->Typename(); }
std::string Filename() const { return GetImpl()->Filename(); }
std::string DefaultValue() const { return GetImpl()->DefaultValue(); }
std::string CurrentValue() const { return GetImpl()->CurrentValue(); }
bool HasValidatorFn() const { return GetImpl()->HasValidatorFn(); }
bool InvokeValidator(const void* value) const {
return GetImpl()->InvokeValidator(value);
}
template <typename T>
inline bool IsOfType() const {
return GetImpl()->IsOftype<T>();
}
T Get() const { return GetImpl()->Get(); }
bool AtomicGet(T* v) const { return GetImpl()->AtomicGet(v); }
void Set(const T& v) { GetImpl()->Set(v); }
void SetCallback(const flags_internal::FlagCallback mutation_callback) {
GetImpl()->SetCallback(mutation_callback);
}
void InvokeCallback() { GetImpl()->InvokeCallback(); }

private:
const char* name_;
const flags_internal::HelpGenFunc help_gen_;
const char* filename_;
const flags_internal::FlagMarshallingOpFn marshalling_op_;
const flags_internal::InitialValGenFunc initial_value_gen_;

mutable std::atomic<bool> inited_;
mutable flags_internal::Flag<T>* impl_ = nullptr;
};
#endif

// GetFlag()
//
Expand All @@ -83,7 +175,7 @@ using Flag = flags_internal::Flag<T>;
// // FLAGS_firstname is a Flag of type `std::string`
// std::string first_name = absl::GetFlag(FLAGS_firstname);
template <typename T>
T GetFlag(const absl::Flag<T>& flag) {
ABSL_MUST_USE_RESULT T GetFlag(const absl::Flag<T>& flag) {
#define ABSL_FLAGS_INTERNAL_LOCK_FREE_VALIDATE(BIT) \
static_assert( \
!std::is_same<T, BIT>::value, \
Expand All @@ -96,7 +188,7 @@ T GetFlag(const absl::Flag<T>& flag) {

// Overload for `GetFlag()` for types that support lock-free reads.
#define ABSL_FLAGS_INTERNAL_LOCK_FREE_EXPORT(T) \
extern T GetFlag(const absl::Flag<T>& flag);
ABSL_MUST_USE_RESULT T GetFlag(const absl::Flag<T>& flag);
ABSL_FLAGS_INTERNAL_FOR_EACH_LOCK_FREE(ABSL_FLAGS_INTERNAL_LOCK_FREE_EXPORT)
#undef ABSL_FLAGS_INTERNAL_LOCK_FREE_EXPORT

Expand Down Expand Up @@ -184,13 +276,23 @@ void SetFlag(absl::Flag<T>* flag, const V& v) {
#if ABSL_FLAGS_STRIP_NAMES
#define ABSL_FLAG_IMPL_FLAGNAME(txt) ""
#define ABSL_FLAG_IMPL_FILENAME() ""
#if !defined(_MSC_VER)
#define ABSL_FLAG_IMPL_REGISTRAR(T, flag) \
absl::flags_internal::FlagRegistrar<T, false>(&flag)
#else
#define ABSL_FLAG_IMPL_REGISTRAR(T, flag) \
absl::flags_internal::FlagRegistrar<T, false>(flag.GetImpl())
#endif
#else
#define ABSL_FLAG_IMPL_FLAGNAME(txt) txt
#define ABSL_FLAG_IMPL_FILENAME() __FILE__
#if !defined(_MSC_VER)
#define ABSL_FLAG_IMPL_REGISTRAR(T, flag) \
absl::flags_internal::FlagRegistrar<T, true>(&flag)
#else
#define ABSL_FLAG_IMPL_REGISTRAR(T, flag) \
absl::flags_internal::FlagRegistrar<T, true>(flag.GetImpl())
#endif
#endif

// ABSL_FLAG_IMPL macro definition conditional on ABSL_FLAGS_STRIP_HELP
Expand Down
93 changes: 1 addition & 92 deletions absl/flags/internal/commandlineflag.cc
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ absl::Mutex* InitFlag(CommandLineFlag* flag) {
{
absl::MutexLock lock(mu);

if (!flag->retired && flag->def == nullptr) {
if (!flag->IsRetired() && flag->def == nullptr) {
// Need to initialize def and cur fields.
flag->def = (*flag->make_init_value)();
flag->cur = Clone(flag->op, flag->def);
Expand All @@ -94,16 +94,6 @@ absl::Mutex* CommandLineFlag::InitFlagIfNecessary() const
return &this->locks->primary_mu;
}

void CommandLineFlag::Destroy() const {
// Values are heap allocated for retired and Abseil Flags.
if (IsRetired() || IsAbseilFlag()) {
if (this->cur) Delete(this->op, this->cur);
if (this->def) Delete(this->op, this->def);
}

delete this->locks;
}

bool CommandLineFlag::IsModified() const {
absl::MutexLock l(InitFlagIfNecessary());
return modified;
Expand Down Expand Up @@ -159,87 +149,6 @@ std::string CommandLineFlag::CurrentValue() const {
return Unparse(this->marshalling_op, this->cur);
}

bool CommandLineFlag::HasValidatorFn() const {
absl::MutexLock l(InitFlagIfNecessary());

return this->validator != nullptr;
}

bool CommandLineFlag::SetValidatorFn(FlagValidator fn) {
absl::MutexLock l(InitFlagIfNecessary());

// ok to register the same function over and over again
if (fn == this->validator) return true;

// Can't set validator to a different function, unless reset first.
if (fn != nullptr && this->validator != nullptr) {
ABSL_INTERNAL_LOG(
WARNING, absl::StrCat("Ignoring SetValidatorFn() for flag '", Name(),
"': validate-fn already registered"));

return false;
}

this->validator = fn;
return true;
}

bool CommandLineFlag::InvokeValidator(const void* value) const
EXCLUSIVE_LOCKS_REQUIRED(this->locks->primary_mu) {
if (!this->validator) {
return true;
}

(void)value;

ABSL_INTERNAL_LOG(
FATAL,
absl::StrCat("Flag '", Name(),
"' of encapsulated type should not have a validator"));

return false;
}

void CommandLineFlag::SetCallback(
const flags_internal::FlagCallback mutation_callback) {
absl::MutexLock l(InitFlagIfNecessary());

callback = mutation_callback;

InvokeCallback();
}

// If the flag has a mutation callback this function invokes it. While the
// callback is being invoked the primary flag's mutex is unlocked and it is
// re-locked back after call to callback is completed. Callback invocation is
// guarded by flag's secondary mutex instead which prevents concurrent callback
// invocation. Note that it is possible for other thread to grab the primary
// lock and update flag's value at any time during the callback invocation.
// This is by design. Callback can get a value of the flag if necessary, but it
// might be different from the value initiated the callback and it also can be
// different by the time the callback invocation is completed.
// Requires that *primary_lock be held in exclusive mode; it may be released
// and reacquired by the implementation.
void CommandLineFlag::InvokeCallback()
EXCLUSIVE_LOCKS_REQUIRED(this->locks->primary_mu) {
if (!this->callback) return;

// The callback lock is guaranteed initialized, because *locks->primary_mu
// exists.
absl::Mutex* callback_mu = &this->locks->callback_mu;

// When executing the callback we need the primary flag's mutex to be unlocked
// so that callback can retrieve the flag's value.
this->locks->primary_mu.Unlock();

{
absl::MutexLock lock(callback_mu);
this->callback();
}

this->locks->primary_mu.Lock();
}

// Attempts to parse supplied `value` string using parsing routine in the `flag`
// argument. If parsing is successful, it will try to validate that the parsed
// value is valid for the specified 'flag'. Finally this function stores the
Expand Down
Loading

0 comments on commit 2d2d7fb

Please sign in to comment.