From a0691f92471f0d34052d2adea8491774cccc360f Mon Sep 17 00:00:00 2001 From: Justin King Date: Wed, 14 Feb 2024 13:55:39 -0800 Subject: [PATCH] Add aliasing constructor to `Shared` PiperOrigin-RevId: 607096421 --- common/memory.h | 25 +++++++++++++++++++++ common/memory_test.cc | 52 +++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 77 insertions(+) diff --git a/common/memory.h b/common/memory.h index 994ca2477..367048448 100644 --- a/common/memory.h +++ b/common/memory.h @@ -119,6 +119,27 @@ class ABSL_ATTRIBUTE_TRIVIAL_ABI Shared final { // NOLINTNEXTLINE(google-explicit-constructor) explicit Shared(SharedView other); + // An aliasing constructor. The resulting `Shared` shares ownership + // information with `alias`, but holds an unmanaged pointer to `T`. + // + // Usage: + // Shared object; + // Shared member = Shared(object, &object->member); + template + Shared(const Shared& alias, T* ptr) + : value_(ptr), refcount_(alias.refcount_) { + common_internal::StrongRef(refcount_); + } + + // An aliasing constructor. The resulting `Shared` shares ownership + // information with `alias`, but holds an unmanaged pointer to `T`. + template + Shared(Shared&& alias, T* ptr) noexcept + : value_(ptr), refcount_(alias.refcount_) { + alias.value_ = nullptr; + alias.refcount_ = nullptr; + } + ~Shared() { common_internal::StrongUnref(refcount_); } Shared& operator=(const Shared& other) { @@ -245,6 +266,10 @@ class ABSL_ATTRIBUTE_TRIVIAL_ABI SharedView final { SharedView(const Shared& other ABSL_ATTRIBUTE_LIFETIME_BOUND) noexcept : value_(other.value_), refcount_(other.refcount_) {} + template + SharedView(SharedView alias, T* ptr) + : value_(ptr), refcount_(alias.refcount_) {} + template < typename U, typename = std::enable_if_t(deleted); + EXPECT_TRUE(object); + EXPECT_FALSE(deleted); + { + auto member = Shared(object, &object->member); + EXPECT_TRUE(object); + EXPECT_FALSE(deleted); + EXPECT_TRUE(member); + } + EXPECT_TRUE(object); + EXPECT_FALSE(deleted); + } + switch (memory_management()) { + case MemoryManagement::kPooling: + EXPECT_FALSE(deleted); + break; + case MemoryManagement::kReferenceCounting: + EXPECT_TRUE(deleted); + break; + } + Finish(); +} + +TEST_P(MemoryManagerTest, SharedAliasMove) { + bool deleted = false; + { + auto object = memory_manager().MakeShared(deleted); + EXPECT_TRUE(object); + EXPECT_FALSE(deleted); + { + auto member = Shared(std::move(object), &object->member); + EXPECT_FALSE(object); + EXPECT_FALSE(deleted); + EXPECT_TRUE(member); + } + switch (memory_management()) { + case MemoryManagement::kPooling: + EXPECT_FALSE(deleted); + break; + case MemoryManagement::kReferenceCounting: + EXPECT_TRUE(deleted); + break; + } + } + Finish(); +} + TEST_P(MemoryManagerTest, SharedCopyConstruct) { bool deleted = false; {