tvl-depot/absl/flags/internal/flag.h
Abseil Team 2d2d7fbc28 Export of internal Abseil changes
--
d6748c733a70cd74ad9b76a0c9cd6b3fe2cecacf by Xiaoyi Zhang <zhangxy@google.com>:

Remove empty block, to address alerts reported in
https://github.com/abseil/abseil-cpp/issues/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 https://github.com/abseil/abseil-cpp/pull/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 https://github.com/abseil/abseil-cpp/issues/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
2019-08-23 14:48:13 -04:00

156 lines
5 KiB
C++

//
// Copyright 2019 The Abseil Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef ABSL_FLAGS_INTERNAL_FLAG_H_
#define ABSL_FLAGS_INTERNAL_FLAG_H_
#include "absl/flags/internal/commandlineflag.h"
#include "absl/flags/internal/registry.h"
namespace absl {
namespace flags_internal {
// Signature for the mutation callback used by watched Flags
// The callback is noexcept.
// TODO(rogeeff): add noexcept after C++17 support is added.
using FlagCallback = void (*)();
void InvokeCallback(absl::Mutex* primary_mu, absl::Mutex* callback_mu,
FlagCallback cb) EXCLUSIVE_LOCKS_REQUIRED(primary_mu);
// This is "unspecified" implementation of absl::Flag<T> type.
template <typename T>
class Flag final : public flags_internal::CommandLineFlag {
public:
constexpr Flag(const char* name_arg,
const flags_internal::HelpGenFunc help_gen,
const char* filename_arg,
const flags_internal::FlagMarshallingOpFn marshalling_op_arg,
const flags_internal::InitialValGenFunc initial_value_gen)
: flags_internal::CommandLineFlag(
name_arg, flags_internal::HelpText::FromFunctionPointer(help_gen),
filename_arg, &flags_internal::FlagOps<T>, marshalling_op_arg,
initial_value_gen,
/*def_arg=*/nullptr,
/*cur_arg=*/nullptr),
callback_(nullptr) {}
T Get() const {
// Implementation notes:
//
// We are wrapping a union around the value of `T` to serve three purposes:
//
// 1. `U.value` has correct size and alignment for a value of type `T`
// 2. The `U.value` constructor is not invoked since U's constructor does
// not
// do it explicitly.
// 3. The `U.value` destructor is invoked since U's destructor does it
// explicitly. This makes `U` a kind of RAII wrapper around non default
// constructible value of T, which is destructed when we leave the
// scope. We do need to destroy U.value, which is constructed by
// CommandLineFlag::Read even though we left it in a moved-from state
// after std::move.
//
// All of this serves to avoid requiring `T` being default constructible.
union U {
T value;
U() {}
~U() { value.~T(); }
};
U u;
this->Read(&u.value, &flags_internal::FlagOps<T>);
return std::move(u.value);
}
bool AtomicGet(T* v) const {
const int64_t r = this->atomic.load(std::memory_order_acquire);
if (r != flags_internal::CommandLineFlag::kAtomicInit) {
memcpy(v, &r, sizeof(T));
return true;
}
return false;
}
void Set(const T& v) { this->Write(&v, &flags_internal::FlagOps<T>); }
void SetCallback(const flags_internal::FlagCallback mutation_callback) {
absl::MutexLock l(InitFlagIfNecessary());
callback_ = mutation_callback;
InvokeCallback();
}
void InvokeCallback() override
EXCLUSIVE_LOCKS_REQUIRED(this->locks->primary_mu) {
flags_internal::InvokeCallback(&this->locks->primary_mu,
&this->locks->callback_mu, callback_);
}
private:
void Destroy() const override {
// Values are heap allocated Abseil Flags.
if (this->cur) Delete(this->op, this->cur);
if (this->def) Delete(this->op, this->def);
delete this->locks;
}
// Flag's data
FlagCallback callback_; // Mutation callback
};
// This class facilitates Flag object registration and tail expression-based
// flag definition, for example:
// ABSL_FLAG(int, foo, 42, "Foo help").OnUpdate(NotifyFooWatcher);
template <typename T, bool do_register>
class FlagRegistrar {
public:
explicit FlagRegistrar(Flag<T>* flag) : flag_(flag) {
if (do_register) flags_internal::RegisterCommandLineFlag(flag_);
}
FlagRegistrar& OnUpdate(flags_internal::FlagCallback cb) && {
flag_->SetCallback(cb);
return *this;
}
// Make the registrar "die" gracefully as a bool on a line where registration
// happens. Registrar objects are intended to live only as temporary.
operator bool() const { return true; } // NOLINT
private:
Flag<T>* flag_; // Flag being registered (not owned).
};
// This struct and corresponding overload to MakeDefaultValue are used to
// facilitate usage of {} as default value in ABSL_FLAG macro.
struct EmptyBraces {};
template <typename T>
T* MakeFromDefaultValue(T t) {
return new T(std::move(t));
}
template <typename T>
T* MakeFromDefaultValue(EmptyBraces) {
return new T;
}
} // namespace flags_internal
} // namespace absl
#endif // ABSL_FLAGS_INTERNAL_FLAG_H_