From 0f9e12f86181c05d6e33b3c22bbebab24e358233 Mon Sep 17 00:00:00 2001 From: Craig Tiller Date: Thu, 11 Aug 2022 17:08:15 -0700 Subject: [PATCH] [no_destruct] Improve ergonomics (#30564) * [no_destruct] Improve ergonomics * comment * fix * Automated change: Fix sanity tests Co-authored-by: ctiller --- src/core/lib/gprpp/no_destruct.h | 22 ++++++++++++++-------- test/core/gprpp/no_destruct_test.cc | 23 +++++++++++++++++++++++ 2 files changed, 37 insertions(+), 8 deletions(-) diff --git a/src/core/lib/gprpp/no_destruct.h b/src/core/lib/gprpp/no_destruct.h index a7d2188ef4b..0e839e3ca73 100644 --- a/src/core/lib/gprpp/no_destruct.h +++ b/src/core/lib/gprpp/no_destruct.h @@ -58,25 +58,31 @@ class NoDestruct { NoDestruct& operator=(const NoDestruct&) = delete; ~NoDestruct() = default; - T* operator->() { return reinterpret_cast(&space_); } - const T* operator->() const { return *reinterpret_cast(&space_); } - T& operator*() { return *reinterpret_cast(&space_); } - const T& operator*() const { return *reinterpret_cast(&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(&space_); } + const T* get() const { return reinterpret_cast(&space_); } private: typename std::aligned_storage::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 class NoDestructSingleton { public: static T* Get() { return &*value_; } private: + NoDestructSingleton() = delete; + ~NoDestructSingleton() = delete; + static NoDestruct value_; }; diff --git a/test/core/gprpp/no_destruct_test.cc b/test/core/gprpp/no_destruct_test.cc index 954e5a84c32..1cda14a44f3 100644 --- a/test/core/gprpp/no_destruct_test.cc +++ b/test/core/gprpp/no_destruct_test.cc @@ -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::Get()->Add(1, 2), 3); +} + } // namespace } // namespace testing } // namespace grpc_core