mirror of
https://github.com/pybind/pybind11.git
synced 2025-01-31 15:20:34 +00:00
Copying in shared_from_this_custom_deleters.cpp from github.com/rwgk, with adjustments.
Base version: e5318faa6a/shared_from_this_custom_deleters.cpp
This commit is contained in:
parent
28ed5ecce8
commit
4f00ffdc69
@ -1,10 +1,98 @@
|
||||
#include "pybind11_tests.h"
|
||||
|
||||
#include "object.h"
|
||||
|
||||
#include <pybind11/smart_holder.h>
|
||||
|
||||
#include <iostream>
|
||||
#include <stdexcept>
|
||||
|
||||
namespace shared_from_this_custom_deleters {
|
||||
|
||||
template <typename T>
|
||||
struct labeled_delete {
|
||||
std::string label;
|
||||
explicit labeled_delete(const std::string &label) : label{label} {}
|
||||
void operator()(T *raw_ptr) {
|
||||
std::cout << "labeled_delete::operator() " << label << std::endl;
|
||||
if (label != "SkipDelete") {
|
||||
delete raw_ptr;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
struct Atype : std::enable_shared_from_this<Atype> {};
|
||||
|
||||
#define SHOW_USE_COUNTS \
|
||||
std::cout << "obj1, obj2 use_counts: " << obj1.use_count() << ", " << obj2.use_count() \
|
||||
<< std::endl;
|
||||
|
||||
void obj1_owns() {
|
||||
std::cout << "\nobj1_owns()" << std::endl;
|
||||
std::shared_ptr<Atype> obj1(new Atype, labeled_delete<Atype>("1st"));
|
||||
std::shared_ptr<Atype> obj2(obj1.get(), labeled_delete<Atype>("SkipDelete"));
|
||||
SHOW_USE_COUNTS
|
||||
auto sft1 = obj1->shared_from_this();
|
||||
SHOW_USE_COUNTS
|
||||
auto sft2 = obj2->shared_from_this();
|
||||
SHOW_USE_COUNTS
|
||||
}
|
||||
|
||||
void obj2_owns() {
|
||||
std::cout << "\nobj2_owns()" << std::endl;
|
||||
std::shared_ptr<Atype> obj1(new Atype, labeled_delete<Atype>("SkipDelete"));
|
||||
std::shared_ptr<Atype> obj2(obj1.get(), labeled_delete<Atype>("2nd"));
|
||||
SHOW_USE_COUNTS
|
||||
auto sft1 = obj1->shared_from_this();
|
||||
SHOW_USE_COUNTS
|
||||
auto sft2 = obj2->shared_from_this();
|
||||
SHOW_USE_COUNTS
|
||||
}
|
||||
|
||||
void obj_sft_reset() {
|
||||
std::cout << "\nobj_sft_reset()" << std::endl;
|
||||
std::shared_ptr<Atype> obj1(new Atype, labeled_delete<Atype>("SkipDelete"));
|
||||
std::shared_ptr<Atype> obj2(obj1.get(), labeled_delete<Atype>("ThisDeletes"));
|
||||
std::shared_ptr<Atype> *obj_sft = nullptr;
|
||||
std::shared_ptr<Atype> *obj_ign = nullptr;
|
||||
{
|
||||
auto sft1 = obj1->shared_from_this();
|
||||
auto sft2 = obj2->shared_from_this();
|
||||
long uc1 = obj1.use_count();
|
||||
long uc2 = obj2.use_count();
|
||||
if (uc1 == 3 && uc2 == 1) {
|
||||
std::cout << "SHARED_FROM_THIS_REFERENT: 1" << std::endl;
|
||||
obj_sft = &obj1;
|
||||
obj_ign = &obj2;
|
||||
} else if (uc1 == 1 && uc2 == 3) {
|
||||
std::cout << "SHARED_FROM_THIS_REFERENT: 2" << std::endl;
|
||||
obj_sft = &obj2;
|
||||
obj_ign = &obj1;
|
||||
} else {
|
||||
std::cout << "SHARED_FROM_THIS_REFERENT: UNKNOWN" << std::endl;
|
||||
}
|
||||
}
|
||||
if (obj_sft == nullptr)
|
||||
throw std::runtime_error("Unexpected `use_count`s.");
|
||||
(*obj_sft).reset();
|
||||
bool got_bad_weak_ptr = false;
|
||||
try {
|
||||
(*obj_ign)->shared_from_this();
|
||||
} catch (const std::bad_weak_ptr &) {
|
||||
got_bad_weak_ptr = true;
|
||||
}
|
||||
std::cout << "got_bad_weak_ptr: " << got_bad_weak_ptr << std::endl;
|
||||
std::shared_ptr<Atype> obj3(obj2.get(), labeled_delete<Atype>("SkipDelete"));
|
||||
// Working again based on the shared_ptr that was created after obj_sft was reset:
|
||||
(*obj_ign)->shared_from_this();
|
||||
}
|
||||
|
||||
} // namespace shared_from_this_custom_deleters
|
||||
|
||||
namespace test_class_sh_shared_from_this {
|
||||
|
||||
// clang-format off
|
||||
|
||||
class MyObject3 : public std::enable_shared_from_this<MyObject3> {
|
||||
public:
|
||||
MyObject3(const MyObject3 &) = default;
|
||||
@ -35,6 +123,8 @@ struct SharedFromThisVBase : std::enable_shared_from_this<SharedFromThisVBase> {
|
||||
|
||||
struct SharedFromThisVirt : virtual SharedFromThisVBase {};
|
||||
|
||||
// clang-format on
|
||||
|
||||
} // namespace test_class_sh_shared_from_this
|
||||
|
||||
using namespace test_class_sh_shared_from_this;
|
||||
@ -45,6 +135,8 @@ PYBIND11_SMART_HOLDER_TYPE_CASTERS(SharedFromThisRef)
|
||||
PYBIND11_SMART_HOLDER_TYPE_CASTERS(SharedFromThisVirt)
|
||||
|
||||
TEST_SUBMODULE(class_sh_shared_from_this, m) {
|
||||
// clang-format off
|
||||
|
||||
py::classh<MyObject3>(m, "MyObject3")
|
||||
.def(py::init<int>());
|
||||
m.def("make_myobject3_1", []() { return new MyObject3(8); });
|
||||
@ -71,4 +163,10 @@ TEST_SUBMODULE(class_sh_shared_from_this, m) {
|
||||
static std::shared_ptr<SharedFromThisVirt> sft(new SharedFromThisVirt());
|
||||
py::classh<SharedFromThisVirt>(m, "SharedFromThisVirt")
|
||||
.def_static("get", []() { return sft.get(); }, py::return_value_policy::reference);
|
||||
|
||||
// clang-format on
|
||||
|
||||
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);
|
||||
}
|
||||
|
@ -109,3 +109,15 @@ def test_shared_from_this_virt():
|
||||
z = m.SharedFromThisVirt.get()
|
||||
y = m.SharedFromThisVirt.get()
|
||||
assert y is z
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"test_func",
|
||||
[
|
||||
m.obj1_owns,
|
||||
m.obj2_owns,
|
||||
m.obj_sft_reset,
|
||||
],
|
||||
)
|
||||
def test_shared_from_this_custom_deleters(test_func):
|
||||
test_func()
|
||||
|
Loading…
Reference in New Issue
Block a user