From 45ec61f419d8c79b8fcb047b20e740c48c4e4478 Mon Sep 17 00:00:00 2001 From: "Ralf W. Grosse-Kunstleve" Date: Mon, 14 Jun 2021 14:32:42 -0700 Subject: [PATCH] Adding shared_ptr_reset_and_rescue_pointee_model_proof_of_concept. --- tests/test_class_sh_shared_from_this.cpp | 59 ++++++++++++++++++++++++ tests/test_class_sh_shared_from_this.py | 9 ++++ 2 files changed, 68 insertions(+) diff --git a/tests/test_class_sh_shared_from_this.cpp b/tests/test_class_sh_shared_from_this.cpp index d7673f0c7..09fdbff12 100644 --- a/tests/test_class_sh_shared_from_this.cpp +++ b/tests/test_class_sh_shared_from_this.cpp @@ -95,6 +95,62 @@ void obj_sft_reset() { } // namespace shared_from_this_custom_deleters +namespace shared_ptr_reset_and_rescue_pointee_model { + +struct ToBeWrapped : std::enable_shared_from_this {}; + +struct RescuingDeleter; + +struct PyWrapper { + std::unique_ptr rdel; + std::shared_ptr wobj; + std::shared_ptr self; +}; + +struct RescuingDeleter { + PyWrapper *pyw; + explicit RescuingDeleter(PyWrapper *pyw) : pyw{pyw} {} + void operator()(ToBeWrapped *raw_ptr) { + if (pyw->self.get() != nullptr) { + assert(raw_ptr->weak_from_this().expired()); // CRITICAL + pyw->wobj = std::shared_ptr(raw_ptr, *this); + pyw->self.reset(); + } else { + delete raw_ptr; + } + } +}; + +std::shared_ptr release_to_cpp(const std::shared_ptr &pyw) { + std::shared_ptr return_value = pyw->wobj; + pyw->wobj.reset(); + pyw->self = pyw; + return return_value; +} + +void proof_of_concept() { + std::shared_ptr pyw(new PyWrapper); + pyw->rdel = std::unique_ptr(new RescuingDeleter(pyw.get())); + pyw->wobj = std::shared_ptr(new ToBeWrapped, *pyw->rdel); + std::shared_ptr cpp_owner = release_to_cpp(pyw); + assert(pyw->wobj.get() == nullptr); + assert(cpp_owner.use_count() == 1); + { + std::shared_ptr sft = cpp_owner->shared_from_this(); + assert(cpp_owner.use_count() == 2); + } + assert(cpp_owner.use_count() == 1); + cpp_owner.reset(); + assert(pyw->wobj.get() != nullptr); + assert(pyw->wobj.use_count() == 1); + { + std::shared_ptr sft = pyw->wobj->shared_from_this(); + assert(pyw->wobj.use_count() == 2); + } +} + +} // namespace shared_ptr_reset_and_rescue_pointee_model + namespace test_class_sh_shared_from_this { // clang-format off @@ -175,4 +231,7 @@ TEST_SUBMODULE(class_sh_shared_from_this, m) { m.def("obj1_owns", shared_from_this_custom_deleters::obj1_owns); m.def("obj2_owns", shared_from_this_custom_deleters::obj2_owns); m.def("obj_sft_reset", shared_from_this_custom_deleters::obj_sft_reset); + + m.def("shared_ptr_reset_and_rescue_pointee_model_proof_of_concept", + shared_ptr_reset_and_rescue_pointee_model::proof_of_concept); } diff --git a/tests/test_class_sh_shared_from_this.py b/tests/test_class_sh_shared_from_this.py index 26501bf68..6319029f7 100644 --- a/tests/test_class_sh_shared_from_this.py +++ b/tests/test_class_sh_shared_from_this.py @@ -121,3 +121,12 @@ def test_shared_from_this_virt(): ) def test_shared_from_this_custom_deleters(test_func): test_func() + + +def test_shared_ptr_reset_and_rescue_pointee_model(loop_count_max=10 ** 6): + loop_count = 0 + while True: + m.shared_ptr_reset_and_rescue_pointee_model_proof_of_concept() + loop_count += 1 + if loop_count == loop_count_max: + break