From cb548bb3ccb9c437706daceaf8bdfa1b29553aae Mon Sep 17 00:00:00 2001 From: "Ralf W. Grosse-Kunstleve" Date: Fri, 25 Jun 2021 13:25:19 -0700 Subject: [PATCH] This change fixes the 6 unit tests in https://github.com/deepmind/open_spiel/tree/bbfb0259b5d26c1e3f05000f1f4a05b7ad60393e/open_spiel/python/mfg/algorithms best_response_value_test distribution_test fictitious_play_test greedy_policy_test nash_conv_test policy_value_test CAVEAT: The fix is NOT covered by pybind11 unit tests. --- include/pybind11/detail/smart_holder_poc.h | 7 ++++++ .../detail/smart_holder_type_casters.h | 23 ++++++++++++++++--- 2 files changed, 27 insertions(+), 3 deletions(-) diff --git a/include/pybind11/detail/smart_holder_poc.h b/include/pybind11/detail/smart_holder_poc.h index 5c4f565fc..953852e27 100644 --- a/include/pybind11/detail/smart_holder_poc.h +++ b/include/pybind11/detail/smart_holder_poc.h @@ -60,6 +60,13 @@ Details: namespace pybindit { namespace memory { +static constexpr bool type_has_shared_from_this(...) { return false; } + +template +static constexpr bool type_has_shared_from_this(const std::enable_shared_from_this *) { + return true; +} + struct guarded_delete { std::weak_ptr released_ptr; // Trick to keep the smart_holder memory footprint small. void (*del_ptr)(void *); diff --git a/include/pybind11/detail/smart_holder_type_casters.h b/include/pybind11/detail/smart_holder_type_casters.h index bbbf6e8e2..eddf96d63 100644 --- a/include/pybind11/detail/smart_holder_type_casters.h +++ b/include/pybind11/detail/smart_holder_type_casters.h @@ -393,6 +393,9 @@ struct smart_holder_type_caster_load { throw_if_uninitialized_or_disowned_holder(); holder_type &hld = holder(); hld.ensure_is_not_disowned("loaded_as_shared_ptr"); + if (hld.vptr_is_using_noop_deleter) { + throw std::runtime_error("Non-owning holder (loaded_as_shared_ptr)."); + } auto void_raw_ptr = hld.template as_raw_ptr_unowned(); auto type_raw_ptr = convert_type(void_raw_ptr); if (hld.pointee_depends_on_holder_owner) { @@ -407,12 +410,26 @@ struct smart_holder_type_caster_load { vptr_gd_ptr->released_ptr = to_be_released; return to_be_released; } + if (std::get_deleter(hld.vptr) != nullptr) { + // SMART_HOLDER_WIP: unit test coverage. + std::shared_ptr void_shd_ptr = hld.template as_shared_ptr(); + return std::shared_ptr(void_shd_ptr, type_raw_ptr); + } + if (!pybindit::memory::type_has_shared_from_this(type_raw_ptr)) { + // SMART_HOLDER_WIP: unit test coverage. + // SMART_HOLDER_WIP: keep weak_ref? + auto self = reinterpret_cast(load_impl.loaded_v_h.inst); + Py_INCREF(self); + return std::shared_ptr(type_raw_ptr, shared_ptr_dec_ref_deleter{self}); + } + if (hld.vptr_is_external_shared_ptr) { + // SMART_HOLDER_WIP: unit test coverage. + pybind11_fail("smart_holder_type_casters loaded_as_shared_ptr failure: external " + "shared_ptr for type with shared_from_this."); + } pybind11_fail("smart_holder_type_casters: loaded_as_shared_ptr failure: internal " "inconsistency."); } - if (hld.vptr_is_using_noop_deleter) { - throw std::runtime_error("Non-owning holder (loaded_as_shared_ptr)."); - } std::shared_ptr void_shd_ptr = hld.template as_shared_ptr(); return std::shared_ptr(void_shd_ptr, type_raw_ptr); }