Skip to content

Instantly share code, notes, and snippets.



Last active Jan 11, 2020
What would you like to do?
// This macro is the "source of truth" for the list of supported flag types we
// expect to perform lock free operations on. Specifically it generates code,
// a one argument macro operating on a type, supplied as a macro argument, for
// each type in the list.
A(bool) \
A(short) \
A(unsigned short) \
A(int) \
A(unsigned int) \
A(long) \
A(unsigned long) \
A(long long) \
A(unsigned long long) \
A(double) \
constexpr int64_t AtomicInit() { return 0xababababababababll; }
class FlagImpl {
// Init this atomic with some garbage where
// the collisions are negligible.
std::atomic<int64_t> atomic_{AtomicInit()};
void FlagImpl::StoreAtomic() {
// Get the size of a type.
size_t data_size = Sizeof(op_);
// If it fits into the word on 64 bit systems.
if (data_size <= sizeof(int64_t)) {
int64_t t = 0;
// Copy it inside this atomic.
std::memcpy(&t, cur_, data_size);, std::memory_order_release);
template <typename T>
bool AtomicGet(T* v) const {
// Load the byte representation.
const int64_t r = atomic_.load(std::memory_order_acquire);
// If it is not atomic init which means that the atomic
// value was initialized with something but not a garbage.
if (r != flags_internal::AtomicInit()) {
// Copy it inside the value.
// Compilers are very smart enough to generate
// couple of cmov, mov instructions when the memcpy size is known.
std::memcpy(v, &r, sizeof(T));
// Return that we successfully returned a true value depending
// on a "garbage heuristic".
return true;
// In that case we do believe that the flag was not yet initialized.
return false;
T GetFlag(const absl::Flag<T>& flag) { \
T result; \
/* Try to get the heuristic */ \
if (flag.AtomicGet(&result)) { \
/* If it was initialized, return*/ \
return result; \
} \
/* Use slow mutex holding impl */ \
return flag.Get(); \
// For other types use mutex holding implementation.
template <typename T>
ABSL_MUST_USE_RESULT T GetFlag(const absl::Flag<T>& flag) {
return flag.Get();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment