-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
* [c++] Add a non-destructed type * Automated change: Fix sanity tests * Automated change: Fix sanity tests * comment Co-authored-by: ctiller <[email protected]>
- Loading branch information
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,88 @@ | ||
// Copyright 2022 gRPC 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 | ||
// | ||
// http://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 GRPC_CORE_LIB_GPRPP_NO_DESTRUCT_H | ||
#define GRPC_CORE_LIB_GPRPP_NO_DESTRUCT_H | ||
|
||
#include <grpc/support/port_platform.h> | ||
|
||
#include <utility> | ||
|
||
#include "src/core/lib/gprpp/construct_destruct.h" | ||
|
||
namespace grpc_core { | ||
|
||
// NoDestruct<T> is a wrapper around an object of type T that: | ||
// - stores the value inline - no heap allocation | ||
// - is non-copyable | ||
// - is eagerly constructed (i.e. the constructor is called when NoDestruct is | ||
// constructed) | ||
// - *NEVER* calls ~T() | ||
// It's useful in cases where no ordering can be assumed between destructors of | ||
// objects that need to refer to each other - such as at program destruction | ||
// time. | ||
// Examples: | ||
// // globally available object: | ||
// static NoDestruct<Foo> g_foo(1, "foo", 2.0); | ||
// // used as: | ||
// g_foo->DoSomething(); | ||
// // singleton function: | ||
// Bar* BarSingleton() { | ||
// static NoDestruct<Bar> bar(1, "bar", 2.0); | ||
// return &*bar; | ||
// } | ||
// The globally available version is constructed at program startup, and the | ||
// singleton version is constructed at the first call to BarSingleton(). | ||
// Neither Foo nor Bar instance will be destructed. | ||
template <typename T> | ||
class NoDestruct { | ||
public: | ||
template <typename... Args> | ||
explicit NoDestruct(Args&&... args) { | ||
static_assert(std::is_trivially_destructible<NoDestruct<T>>::value, | ||
"NoDestruct must be trivially destructible"); | ||
Construct(reinterpret_cast<T*>(&space_), std::forward<Args>(args)...); | ||
} | ||
NoDestruct(const NoDestruct&) = delete; | ||
NoDestruct& operator=(const NoDestruct&) = delete; | ||
~NoDestruct() = default; | ||
|
||
T* operator->() { return reinterpret_cast<T*>(&space_); } | ||
const T* operator->() const { return *reinterpret_cast<const T*>(&space_); } | ||
T& operator*() { return *reinterpret_cast<T*>(&space_); } | ||
const T& operator*() const { return *reinterpret_cast<const T*>(&space_); } | ||
|
||
private: | ||
typename std::aligned_storage<sizeof(T), alignof(T)>::type space_; | ||
}; | ||
|
||
// Helper for when a program desires a single instance of a default constructed | ||
// T to be always available. | ||
// T is constructed eagerly at program startup, so it's essentially free to load | ||
// the pointer to the instance. | ||
template <typename T> | ||
class NoDestructSingleton { | ||
public: | ||
static T* Get() { return &*value_; } | ||
|
||
private: | ||
static NoDestruct<T> value_; | ||
}; | ||
|
||
template <typename T> | ||
NoDestruct<T> NoDestructSingleton<T>::value_; | ||
|
||
} // namespace grpc_core | ||
|
||
#endif // GRPC_CORE_LIB_GPRPP_NO_DESTRUCT_H |