From e01550bbb6520f00c0826e17e13360f127dfddf6 Mon Sep 17 00:00:00 2001 From: John Reck Date: Fri, 10 Nov 2023 15:05:35 -0500 Subject: [PATCH] Add StrongPointer::release() Useful when dealing with raw pointers in unavoidable places. Avoids an awkward (and "slow") dance of mySp->incStrong(0); mySp->get(); ~mySp; Test: make && atest --host libutils_binder_test Change-Id: Ib8d46150592725cc256779bccfed19a16dce78b2 --- libutils/binder/StrongPointer_test.cpp | 14 ++++++++++++++ libutils/binder/include/utils/StrongPointer.h | 9 +++++++++ 2 files changed, 23 insertions(+) diff --git a/libutils/binder/StrongPointer_test.cpp b/libutils/binder/StrongPointer_test.cpp index f27c1f1cc..aa993c3f8 100644 --- a/libutils/binder/StrongPointer_test.cpp +++ b/libutils/binder/StrongPointer_test.cpp @@ -106,3 +106,17 @@ TYPED_TEST(StrongPointer, AssertStrongRefExists) { EXPECT_DEATH(sp::fromExisting(foo), ""); delete foo; } + +TYPED_TEST(StrongPointer, release) { + bool isDeleted = false; + TypeParam* foo = nullptr; + { + sp sp1 = sp::make(&isDeleted); + ASSERT_EQ(1, sp1->getStrongCount()); + foo = sp1.release(); + } + ASSERT_FALSE(isDeleted) << "release failed, deleted anyway when sp left scope"; + ASSERT_EQ(1, foo->getStrongCount()) << "release mismanaged refcount"; + foo->decStrong(nullptr); + ASSERT_TRUE(isDeleted) << "foo was leaked!"; +} diff --git a/libutils/binder/include/utils/StrongPointer.h b/libutils/binder/include/utils/StrongPointer.h index 54aa691e0..43c00c95a 100644 --- a/libutils/binder/include/utils/StrongPointer.h +++ b/libutils/binder/include/utils/StrongPointer.h @@ -98,6 +98,15 @@ public: void clear(); + // Releases the ownership of the object managed by this instance of sp, if any. + // The caller is now responsible for managing it. That is, the caller must ensure + // decStrong() is called when the pointer is no longer used. + [[nodiscard]] inline T* release() noexcept { + auto ret = m_ptr; + m_ptr = nullptr; + return ret; + } + // Accessors inline T& operator* () const { return *m_ptr; }