From 633ba775d36f1b0859bc535bfce113867d8af652 Mon Sep 17 00:00:00 2001 From: Michael Sandstedt Date: Mon, 20 Dec 2021 11:02:43 -0600 Subject: [PATCH] Add Platform::SharedPtr, similar to Platform::UniquePtr This commit adds a Platform::SharedPtr wrapper for std::shared_ptr, but using the chip platform allocator, in the pattern of Platform::UniquePtr. --- src/lib/support/CHIPMem.h | 9 ++++++ src/lib/support/tests/TestCHIPMem.cpp | 46 ++++++++++++++++++++++++++- 2 files changed, 54 insertions(+), 1 deletion(-) diff --git a/src/lib/support/CHIPMem.h b/src/lib/support/CHIPMem.h index 14164f1e310c6f..3bd852210de5a4 100644 --- a/src/lib/support/CHIPMem.h +++ b/src/lib/support/CHIPMem.h @@ -179,6 +179,15 @@ inline UniquePtr MakeUnique(Args &&... args) return UniquePtr(New(std::forward(args)...)); } +template +using SharedPtr = std::shared_ptr; + +template +inline SharedPtr MakeShared(Args &&... args) +{ + return SharedPtr(New(std::forward(args)...), Deleter()); +} + // See MemoryDebugCheckPointer(). extern bool MemoryInternalCheckPointer(const void * p, size_t min_size); diff --git a/src/lib/support/tests/TestCHIPMem.cpp b/src/lib/support/tests/TestCHIPMem.cpp index 55aa60c2285d29..2473a211e2f0ff 100644 --- a/src/lib/support/tests/TestCHIPMem.cpp +++ b/src/lib/support/tests/TestCHIPMem.cpp @@ -121,13 +121,57 @@ static void TestMemAlloc_UniquePtr(nlTestSuite * inSuite, void * inContext) NL_TEST_ASSERT(inSuite, destructorCalled == 1); } +static void TestMemAlloc_SharedPtr(nlTestSuite * inSuite, void * inContext) +{ + // SharedPtr is a wrapper of std::shared_ptr for platform allocators. + int instanceConstructorCalled = 0; + int instanceDestructorCalled = 0; + int otherInstanceConstructorCalled = 0; + int otherInstanceDestructorCalled = 0; + + class Cls + { + public: + Cls(int * constructCtr, int * desctructorCtr) : mpDestructorCtr(desctructorCtr) { (*constructCtr)++; } + ~Cls() { (*mpDestructorCtr)++; } + + private: + int * mpDestructorCtr; + }; + + // Check constructor call for a block-scoped variable and share our + // reference to a function-scoped variable. + SharedPtr otherReference; + { + auto ptr = MakeShared(&instanceConstructorCalled, &instanceDestructorCalled); + NL_TEST_ASSERT(inSuite, instanceConstructorCalled == 1); + // Capture a shared reference so we aren't destructed when we leave this scope. + otherReference = ptr; + } + + // Verify that by sharing to otherReference, we weren't destructed. + NL_TEST_ASSERT(inSuite, instanceDestructorCalled == 0); + + // Now drop our reference. + otherReference = MakeShared(&otherInstanceConstructorCalled, &otherInstanceDestructorCalled); + + // Verify that the new instance was constructed and the first instance was + // destructed, and that we retain a reference to the new instance. + NL_TEST_ASSERT(inSuite, instanceConstructorCalled == 1); + NL_TEST_ASSERT(inSuite, instanceDestructorCalled == 1); + NL_TEST_ASSERT(inSuite, otherInstanceConstructorCalled == 1); + NL_TEST_ASSERT(inSuite, otherInstanceDestructorCalled == 0); +} + /** * Test Suite. It lists all the test functions. */ static const nlTest sTests[] = { NL_TEST_DEF("Test MemAlloc::Malloc", TestMemAlloc_Malloc), NL_TEST_DEF("Test MemAlloc::Calloc", TestMemAlloc_Calloc), NL_TEST_DEF("Test MemAlloc::Realloc", TestMemAlloc_Realloc), - NL_TEST_DEF("Test MemAlloc::UniquePtr", TestMemAlloc_UniquePtr), NL_TEST_SENTINEL() }; + NL_TEST_DEF("Test MemAlloc::UniquePtr", TestMemAlloc_UniquePtr), + NL_TEST_DEF("Test MemAlloc::SharedPtr", TestMemAlloc_SharedPtr), + NL_TEST_SENTINEL() }; /** * Set up the test suite.