Repo created
This commit is contained in:
parent
81b91f4139
commit
f8c34fa5ee
22732 changed files with 4815320 additions and 2 deletions
212
TMessagesProj/jni/voip/webrtc/absl/base/no_destructor.h
Normal file
212
TMessagesProj/jni/voip/webrtc/absl/base/no_destructor.h
Normal file
|
|
@ -0,0 +1,212 @@
|
|||
// Copyright 2023 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.
|
||||
//
|
||||
// -----------------------------------------------------------------------------
|
||||
// File: no_destructor.h
|
||||
// -----------------------------------------------------------------------------
|
||||
//
|
||||
// This header file defines the absl::NoDestructor<T> wrapper for defining a
|
||||
// static type that does not need to be destructed upon program exit. Instead,
|
||||
// such an object survives during program exit (and can be safely accessed at
|
||||
// any time).
|
||||
//
|
||||
// absl::NoDestructor<T> is useful when when a variable has static storage
|
||||
// duration but its type has a non-trivial destructor. Global constructors are
|
||||
// not recommended because of the C++'s static initialization order fiasco (See
|
||||
// https://en.cppreference.com/w/cpp/language/siof). Global destructors are not
|
||||
// allowed due to similar concerns about destruction ordering. Using
|
||||
// absl::NoDestructor<T> as a function-local static prevents both of these
|
||||
// issues.
|
||||
//
|
||||
// See below for complete details.
|
||||
|
||||
|
||||
#ifndef ABSL_BASE_NO_DESTRUCTOR_H_
|
||||
#define ABSL_BASE_NO_DESTRUCTOR_H_
|
||||
|
||||
#include <new>
|
||||
#include <type_traits>
|
||||
#include <utility>
|
||||
|
||||
#include "absl/base/config.h"
|
||||
#include "absl/base/nullability.h"
|
||||
|
||||
namespace absl {
|
||||
ABSL_NAMESPACE_BEGIN
|
||||
|
||||
// absl::NoDestructor<T>
|
||||
//
|
||||
// NoDestructor<T> is a wrapper around an object of type T that behaves as an
|
||||
// object of type T but never calls T's destructor. NoDestructor<T> makes it
|
||||
// safer and/or more efficient to use such objects in static storage contexts,
|
||||
// ideally as function scope static variables.
|
||||
//
|
||||
// An instance of absl::NoDestructor<T> has similar type semantics to an
|
||||
// instance of T:
|
||||
//
|
||||
// * Constructs in the same manner as an object of type T through perfect
|
||||
// forwarding.
|
||||
// * Provides pointer/reference semantic access to the object of type T via
|
||||
// `->`, `*`, and `get()`.
|
||||
// (Note that `const NoDestructor<T>` works like a pointer to const `T`.)
|
||||
//
|
||||
// Additionally, NoDestructor<T> provides the following benefits:
|
||||
//
|
||||
// * Never calls T's destructor for the object
|
||||
// * If the object is a function-local static variable, the type can be
|
||||
// lazily constructed.
|
||||
//
|
||||
// An object of type NoDestructor<T> is "trivially destructible" in the notion
|
||||
// that its destructor is never run.
|
||||
//
|
||||
// Usage as Function Scope Static Variables
|
||||
//
|
||||
// Function static objects will be lazily initialized within static storage:
|
||||
//
|
||||
// // Function scope.
|
||||
// const std::string& MyString() {
|
||||
// static const absl::NoDestructor<std::string> x("foo");
|
||||
// return *x;
|
||||
// }
|
||||
//
|
||||
// For function static variables, NoDestructor avoids heap allocation and can be
|
||||
// inlined in static storage, resulting in exactly-once, thread-safe
|
||||
// construction of an object, and very fast access thereafter (the cost is a few
|
||||
// extra cycles).
|
||||
//
|
||||
// Using NoDestructor<T> in this manner is generally better than other patterns
|
||||
// which require pointer chasing:
|
||||
//
|
||||
// // Prefer using absl::NoDestructor<T> instead for the static variable.
|
||||
// const std::string& MyString() {
|
||||
// static const std::string* x = new std::string("foo");
|
||||
// return *x;
|
||||
// }
|
||||
//
|
||||
// Usage as Global Static Variables
|
||||
//
|
||||
// NoDestructor<T> allows declaration of a global object of type T that has a
|
||||
// non-trivial destructor since its destructor is never run. However, such
|
||||
// objects still need to worry about initialization order, so such use is not
|
||||
// recommended, strongly discouraged by the Google C++ Style Guide, and outright
|
||||
// banned in Chromium.
|
||||
// See https://google.github.io/styleguide/cppguide.html#Static_and_Global_Variables
|
||||
//
|
||||
// // Global or namespace scope.
|
||||
// absl::NoDestructor<MyRegistry> reg{"foo", "bar", 8008};
|
||||
//
|
||||
// Note that if your object already has a trivial destructor, you don't need to
|
||||
// use NoDestructor<T>.
|
||||
//
|
||||
template <typename T>
|
||||
class NoDestructor {
|
||||
public:
|
||||
// Forwards arguments to the T's constructor: calls T(args...).
|
||||
template <typename... Ts,
|
||||
// Disable this overload when it might collide with copy/move.
|
||||
typename std::enable_if<!std::is_same<void(std::decay_t<Ts>&...),
|
||||
void(NoDestructor&)>::value,
|
||||
int>::type = 0>
|
||||
explicit constexpr NoDestructor(Ts&&... args)
|
||||
: impl_(std::forward<Ts>(args)...) {}
|
||||
|
||||
// Forwards copy and move construction for T. Enables usage like this:
|
||||
// static NoDestructor<std::array<string, 3>> x{{{"1", "2", "3"}}};
|
||||
// static NoDestructor<std::vector<int>> x{{1, 2, 3}};
|
||||
explicit constexpr NoDestructor(const T& x) : impl_(x) {}
|
||||
explicit constexpr NoDestructor(T&& x)
|
||||
: impl_(std::move(x)) {}
|
||||
|
||||
// No copying.
|
||||
NoDestructor(const NoDestructor&) = delete;
|
||||
NoDestructor& operator=(const NoDestructor&) = delete;
|
||||
|
||||
// Pretend to be a smart pointer to T with deep constness.
|
||||
// Never returns a null pointer.
|
||||
T& operator*() { return *get(); }
|
||||
absl::Nonnull<T*> operator->() { return get(); }
|
||||
absl::Nonnull<T*> get() { return impl_.get(); }
|
||||
const T& operator*() const { return *get(); }
|
||||
absl::Nonnull<const T*> operator->() const { return get(); }
|
||||
absl::Nonnull<const T*> get() const { return impl_.get(); }
|
||||
|
||||
private:
|
||||
class DirectImpl {
|
||||
public:
|
||||
template <typename... Args>
|
||||
explicit constexpr DirectImpl(Args&&... args)
|
||||
: value_(std::forward<Args>(args)...) {}
|
||||
absl::Nonnull<const T*> get() const { return &value_; }
|
||||
absl::Nonnull<T*> get() { return &value_; }
|
||||
|
||||
private:
|
||||
T value_;
|
||||
};
|
||||
|
||||
class PlacementImpl {
|
||||
public:
|
||||
template <typename... Args>
|
||||
explicit PlacementImpl(Args&&... args) {
|
||||
new (&space_) T(std::forward<Args>(args)...);
|
||||
}
|
||||
absl::Nonnull<const T*> get() const {
|
||||
return Launder(reinterpret_cast<const T*>(&space_));
|
||||
}
|
||||
absl::Nonnull<T*> get() { return Launder(reinterpret_cast<T*>(&space_)); }
|
||||
|
||||
private:
|
||||
template <typename P>
|
||||
static absl::Nonnull<P*> Launder(absl::Nonnull<P*> p) {
|
||||
#if defined(__cpp_lib_launder) && __cpp_lib_launder >= 201606L
|
||||
return std::launder(p);
|
||||
#elif ABSL_HAVE_BUILTIN(__builtin_launder)
|
||||
return __builtin_launder(p);
|
||||
#else
|
||||
// When `std::launder` or equivalent are not available, we rely on
|
||||
// undefined behavior, which works as intended on Abseil's officially
|
||||
// supported platforms as of Q3 2023.
|
||||
#if defined(__GNUC__) && !defined(__clang__)
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wstrict-aliasing"
|
||||
#endif
|
||||
return p;
|
||||
#if defined(__GNUC__) && !defined(__clang__)
|
||||
#pragma GCC diagnostic pop
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
alignas(T) unsigned char space_[sizeof(T)];
|
||||
};
|
||||
|
||||
// If the object is trivially destructible we use a member directly to avoid
|
||||
// potential once-init runtime initialization. It somewhat defeats the
|
||||
// purpose of NoDestructor in this case, but this makes the class more
|
||||
// friendly to generic code.
|
||||
std::conditional_t<std::is_trivially_destructible<T>::value, DirectImpl,
|
||||
PlacementImpl>
|
||||
impl_;
|
||||
};
|
||||
|
||||
#ifdef ABSL_HAVE_CLASS_TEMPLATE_ARGUMENT_DEDUCTION
|
||||
// Provide 'Class Template Argument Deduction': the type of NoDestructor's T
|
||||
// will be the same type as the argument passed to NoDestructor's constructor.
|
||||
template <typename T>
|
||||
NoDestructor(T) -> NoDestructor<T>;
|
||||
#endif // ABSL_HAVE_CLASS_TEMPLATE_ARGUMENT_DEDUCTION
|
||||
|
||||
ABSL_NAMESPACE_END
|
||||
} // namespace absl
|
||||
|
||||
#endif // ABSL_BASE_NO_DESTRUCTOR_H_
|
||||
Loading…
Add table
Add a link
Reference in a new issue