From 6ffecfbcec2c4b641a6130d40bdcda2e63445d5b Mon Sep 17 00:00:00 2001 From: "Nicolas \"Pixel\" Noble" Date: Thu, 3 Oct 2019 00:34:20 +0200 Subject: [PATCH] Adding multiple inheritence delete. --- src/core/lib/gprpp/memory.h | 24 +++++++++++++++++++----- test/core/gprpp/memory_test.cc | 21 +++++++++++++++++++++ 2 files changed, 40 insertions(+), 5 deletions(-) diff --git a/src/core/lib/gprpp/memory.h b/src/core/lib/gprpp/memory.h index 53b89507c6f..d3d9b9eb035 100644 --- a/src/core/lib/gprpp/memory.h +++ b/src/core/lib/gprpp/memory.h @@ -48,19 +48,32 @@ namespace grpc_core { -// Alternative to new, since we cannot use it (for fear of libstdc++) +// Alternative to new, to ensure memory allocation being wrapped to gpr_malloc template inline T* New(Args&&... args) { void* p = gpr_malloc(sizeof(T)); return new (p) T(std::forward(args)...); } -// Alternative to delete, since we cannot use it (for fear of libstdc++) +// Gets the base pointer of any class, in case of multiple inheritence. +// Used by Delete and friends. +template +struct BasePointerGetter { + static void* get(T* p) { return p; } +}; + +template +struct BasePointerGetter { + static void* get(T* p) { return dynamic_cast(p); } +}; + +// Alternative to delete, to ensure memory allocation being wrapped to gpr_free template inline void Delete(T* p) { if (p == nullptr) return; + void* basePtr = BasePointerGetter::value>::get(p); p->~T(); - gpr_free(p); + gpr_free(basePtr); } class DefaultDelete { @@ -68,12 +81,13 @@ class DefaultDelete { template void operator()(T* p) { // Delete() checks whether the value is null, but std::unique_ptr<> is - // gauranteed not to call the deleter if the pointer is nullptr + // guaranteed not to call the deleter if the pointer is nullptr // (i.e., it already does this check for us), and we don't want to // do the check twice. So, instead of calling Delete() here, we // manually call the object's dtor and free it. + void* basePtr = BasePointerGetter::value>::get(p); p->~T(); - gpr_free(p); + gpr_free(basePtr); } }; diff --git a/test/core/gprpp/memory_test.cc b/test/core/gprpp/memory_test.cc index bb6a219a848..b148d7dfccb 100644 --- a/test/core/gprpp/memory_test.cc +++ b/test/core/gprpp/memory_test.cc @@ -29,6 +29,21 @@ struct Foo { int b; }; +struct Base1 { + int a; + virtual ~Base1() {} +}; + +struct Base2 { + int b; + virtual ~Base2() {} +}; + +struct Compound : public Base1, Base2 { + int c; + virtual ~Compound() {} +}; + TEST(MemoryTest, NewDeleteTest) { Delete(New()); } TEST(MemoryTest, NewDeleteWithArgTest) { @@ -64,6 +79,12 @@ TEST(MemoryTest, UniquePtrWithCustomDeleter) { EXPECT_EQ(1, n); } +TEST(MemoryTest, MultipleInheritence) { + Base2* p = New(); + EXPECT_NE(p, dynamic_cast(p)); + Delete(p); +} + } // namespace testing } // namespace grpc_core