[no_destruct] Improve ergonomics (#30564)

* [no_destruct] Improve ergonomics

* comment

* fix

* Automated change: Fix sanity tests

Co-authored-by: ctiller <ctiller@users.noreply.github.com>
pull/30566/head
Craig Tiller 2 years ago committed by GitHub
parent 543b290203
commit 0f9e12f861
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 22
      src/core/lib/gprpp/no_destruct.h
  2. 23
      test/core/gprpp/no_destruct_test.cc

@ -58,25 +58,31 @@ class NoDestruct {
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_); }
T* operator->() { return get(); }
const T* operator->() const { return get(); }
T& operator*() { return *get(); }
const T& operator*() const { return *get(); }
T* get() { return reinterpret_cast<T*>(&space_); }
const T* get() 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.
// Helper for when a program desires a single *process wide* instance of a
// default constructed T to be always available.
// The instance 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:
NoDestructSingleton() = delete;
~NoDestructSingleton() = delete;
static NoDestruct<T> value_;
};

@ -41,6 +41,29 @@ TEST(NoDestruct, CrashOnDestructionIsAccessible) {
g_test_crash_on_destruction->Exists();
}
bool g_thing_constructed = false;
class Thing {
public:
Thing() {
EXPECT_FALSE(g_thing_constructed);
g_thing_constructed = true;
}
int Add(int i, int j) { return i + j; }
private:
~Thing() = delete;
};
TEST(GlobalSingleton, Works) {
// Thing should be eagerly constructed, so we should not observe it being not
// constructed.
EXPECT_TRUE(g_thing_constructed);
// We should be able to fetch the global Thing and use it.
EXPECT_EQ(NoDestructSingleton<Thing>::Get()->Add(1, 2), 3);
}
} // namespace
} // namespace testing
} // namespace grpc_core

Loading…
Cancel
Save