diff --git a/include/pybind11/smart_holder_poc.h b/include/pybind11/smart_holder_poc.h index 6ea0aa24d..8216eaeab 100644 --- a/include/pybind11/smart_holder_poc.h +++ b/include/pybind11/smart_holder_poc.h @@ -3,12 +3,14 @@ #include #include -PYBIND11_NAMESPACE_BEGIN(PYBIND11_NAMESPACE) +namespace pybindit { +namespace memory { template struct guarded_builtin_delete { bool* flag_ptr; - explicit guarded_builtin_delete(bool* flag_ptr_) : flag_ptr{flag_ptr_} {} + explicit guarded_builtin_delete(bool* guard_flag_ptr) + : flag_ptr{guard_flag_ptr} {} void operator()(T* raw_ptr) { if (*flag_ptr) delete raw_ptr; } @@ -17,27 +19,30 @@ struct guarded_builtin_delete { template struct guarded_custom_deleter { bool* flag_ptr; - explicit guarded_custom_deleter(bool* flag_ptr_) : flag_ptr{flag_ptr_} {} + explicit guarded_custom_deleter(bool* guard_flag_ptr) + : flag_ptr{guard_flag_ptr} {} void operator()(T* raw_ptr) { if (*flag_ptr) D()(raw_ptr); } }; struct smart_holder { - std::shared_ptr vptr; const std::type_info* rtti_held; const std::type_info* rtti_uqp_del; - bool vptr_deleter_flag; + std::shared_ptr vptr; + bool vptr_deleter_guard_flag; void clear() { vptr.reset(); - vptr_deleter_flag = false; + vptr_deleter_guard_flag = false; rtti_held = nullptr; rtti_uqp_del = nullptr; } smart_holder() - : rtti_held{nullptr}, rtti_uqp_del{nullptr}, vptr_deleter_flag{false} {} + : rtti_held{nullptr}, + rtti_uqp_del{nullptr}, + vptr_deleter_guard_flag{false} {} template void ensure_compatible_rtti_held(const char* context) { @@ -57,7 +62,7 @@ struct smart_holder { } } - void ensure_vptr_deleter_flag_true(const char* context) { + void ensure_vptr_deleter_guard_flag_true(const char* context) { if (rtti_uqp_del != nullptr) { throw std::runtime_error(std::string("Cannot disown this shared_ptr (") + context + ")."); @@ -71,36 +76,29 @@ struct smart_holder { } } - template - std::shared_ptr as_shared_ptr() { - static const char* context = "as_shared_ptr"; - ensure_compatible_rtti_held(context); - return std::static_pointer_cast(vptr); - } - template void from_raw_ptr_owned(T* raw_ptr) { clear(); rtti_held = &typeid(T); - vptr_deleter_flag = true; - vptr.reset(raw_ptr, guarded_builtin_delete(&vptr_deleter_flag)); + vptr_deleter_guard_flag = true; + vptr.reset(raw_ptr, guarded_builtin_delete(&vptr_deleter_guard_flag)); } template void from_raw_ptr_unowned(T* raw_ptr) { clear(); rtti_held = &typeid(T); - vptr_deleter_flag = false; - vptr.reset(raw_ptr, guarded_builtin_delete(&vptr_deleter_flag)); + vptr_deleter_guard_flag = false; + vptr.reset(raw_ptr, guarded_builtin_delete(&vptr_deleter_guard_flag)); } template T* as_raw_ptr_owned(const char* context = "as_raw_ptr_owned") { ensure_compatible_rtti_held(context); - ensure_vptr_deleter_flag_true(context); + ensure_vptr_deleter_guard_flag_true(context); ensure_use_count_1(context); T* raw_ptr = static_cast(vptr.get()); - vptr_deleter_flag = false; + vptr_deleter_guard_flag = false; vptr.reset(); return raw_ptr; } @@ -116,8 +114,9 @@ struct smart_holder { void from_unique_ptr(std::unique_ptr&& unq_ptr) { clear(); rtti_held = &typeid(T); - vptr_deleter_flag = true; - vptr.reset(unq_ptr.get(), guarded_builtin_delete(&vptr_deleter_flag)); + vptr_deleter_guard_flag = true; + vptr.reset(unq_ptr.get(), + guarded_builtin_delete(&vptr_deleter_guard_flag)); unq_ptr.release(); } @@ -131,8 +130,9 @@ struct smart_holder { clear(); rtti_held = &typeid(T); rtti_uqp_del = &typeid(D); - vptr_deleter_flag = true; - vptr.reset(unq_ptr.get(), guarded_custom_deleter(&vptr_deleter_flag)); + vptr_deleter_guard_flag = true; + vptr.reset(unq_ptr.get(), + guarded_custom_deleter(&vptr_deleter_guard_flag)); unq_ptr.release(); } @@ -143,10 +143,25 @@ struct smart_holder { ensure_compatible_rtti_uqp_del(context); ensure_use_count_1(context); T* raw_ptr = static_cast(vptr.get()); - vptr_deleter_flag = false; + vptr_deleter_guard_flag = false; vptr.reset(); return std::unique_ptr(raw_ptr); } + + template + void from_shared_ptr(std::shared_ptr shd_ptr) { + clear(); + rtti_held = &typeid(T); + vptr = std::static_pointer_cast(shd_ptr); + } + + template + std::shared_ptr as_shared_ptr() { + static const char* context = "as_shared_ptr"; + ensure_compatible_rtti_held(context); + return std::static_pointer_cast(vptr); + } }; -PYBIND11_NAMESPACE_END(PYBIND11_NAMESPACE) +} // namespace memory +} // namespace pybindit diff --git a/tests/test_smart_holder_poc.cpp b/tests/test_smart_holder_poc.cpp index b26363b37..8a750c444 100644 --- a/tests/test_smart_holder_poc.cpp +++ b/tests/test_smart_holder_poc.cpp @@ -17,9 +17,9 @@ struct functor_builtin_delete { inline void exercise() { to_cout(""); - namespace py = pybind11; + using pybindit::memory::smart_holder; { - py::smart_holder hld; + smart_holder hld; hld.from_raw_ptr_owned(new int(13)); to_cout(hld.rtti_held->name()); { @@ -33,24 +33,24 @@ inline void exercise() { } // namespace ; { std::unique_ptr val(new int(13)); - py::smart_holder hld; + smart_holder hld; hld.from_raw_ptr_unowned(val.get()); to_cout(std::to_string(*hld.as_raw_ptr_unowned())); } { std::unique_ptr val(new int(13)); - py::smart_holder hld; + smart_holder hld; hld.from_unique_ptr(std::move(val)); to_cout(std::to_string(*hld.as_raw_ptr_unowned())); } { - py::smart_holder hld; + smart_holder hld; hld.from_raw_ptr_owned(new int(13)); to_cout(std::to_string(*hld.as_unique_ptr())); } { std::unique_ptr> unq_ptr(new int(13)); - py::smart_holder hld; + smart_holder hld; hld.from_unique_ptr_with_deleter(std::move(unq_ptr)); to_cout(std::to_string(unq_ptr.get() == nullptr)); to_cout(std::to_string(*hld.as_raw_ptr_unowned())); @@ -59,6 +59,12 @@ inline void exercise() { to_cout(std::to_string(hld.vptr.get() == nullptr)); to_cout(std::to_string(*unq_ptr_retrieved)); } + { + std::shared_ptr val(new int(13)); + smart_holder hld; + hld.from_shared_ptr(val); + to_cout(std::to_string(*hld.as_raw_ptr_unowned())); + } } TEST_SUBMODULE(smart_holder_poc, m) { m.def("exercise", exercise); }