mirror of
https://github.com/pybind/pybind11.git
synced 2024-11-22 21:25:13 +00:00
Adding tests involving stashing shared_ptr
s. WIP.
This commit is contained in:
parent
4218213f29
commit
553054b26b
@ -10,27 +10,81 @@
|
||||
|
||||
namespace {
|
||||
|
||||
struct WithSft : std::enable_shared_from_this<WithSft> {
|
||||
virtual ~WithSft() = default;
|
||||
struct Sft : std::enable_shared_from_this<Sft> {
|
||||
std::string history;
|
||||
explicit Sft(const std::string &history) : history{history} {}
|
||||
long use_count() const { return this->shared_from_this().use_count(); }
|
||||
virtual ~Sft() = default;
|
||||
|
||||
// "Group of 4" begin.
|
||||
// This group is not meant to be used, but will leave a trace in the
|
||||
// history in case something goes wrong.
|
||||
Sft(const Sft &other) { history = other.history + "_CpCtor"; }
|
||||
|
||||
Sft(Sft &&other) { history = other.history + "_MvCtor"; }
|
||||
|
||||
Sft &operator=(const Sft &other) {
|
||||
history = other.history + "_OpEqLv";
|
||||
return *this;
|
||||
}
|
||||
|
||||
Sft &operator=(Sft &&other) {
|
||||
history = other.history + "_OpEqRv";
|
||||
return *this;
|
||||
}
|
||||
// "Group of 4" end.
|
||||
};
|
||||
|
||||
struct WithSftTrampoline : WithSft {
|
||||
using WithSft::WithSft;
|
||||
struct SftSharedPtrStash {
|
||||
int ser_no;
|
||||
std::vector<std::shared_ptr<Sft>> stash;
|
||||
explicit SftSharedPtrStash(int ser_no) : ser_no{ser_no} {}
|
||||
void Add(const std::shared_ptr<Sft> &obj) {
|
||||
obj->history += "_Stash" + std::to_string(ser_no) + "Add";
|
||||
stash.push_back(obj);
|
||||
}
|
||||
void AddSharedFromThis(Sft *obj) {
|
||||
auto sft = obj->shared_from_this();
|
||||
sft->history += "_Stash" + std::to_string(ser_no) + "AddSharedFromThis";
|
||||
stash.push_back(sft);
|
||||
}
|
||||
std::string history(unsigned i) {
|
||||
if (i < stash.size())
|
||||
return stash[i]->history;
|
||||
return "OutOfRange";
|
||||
}
|
||||
long use_count(unsigned i) {
|
||||
if (i < stash.size())
|
||||
return stash[i].use_count();
|
||||
return -1;
|
||||
}
|
||||
};
|
||||
|
||||
void pass_shared_ptr(const std::shared_ptr<WithSft> &obj) {
|
||||
to_cout("LOOOK pass_shared_ptr entry");
|
||||
to_cout("LOOOK obj->shared_from_this();");
|
||||
(void) obj->shared_from_this();
|
||||
to_cout("LOOOK pass_shared_ptr return");
|
||||
struct SftTrampoline : Sft {
|
||||
using Sft::Sft;
|
||||
};
|
||||
|
||||
void pass_shared_ptr(const std::shared_ptr<Sft> &obj) {
|
||||
obj->shared_from_this()->history += "_PassSharedPtr";
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
PYBIND11_SMART_HOLDER_TYPE_CASTERS(WithSft)
|
||||
PYBIND11_SMART_HOLDER_TYPE_CASTERS(Sft)
|
||||
PYBIND11_SMART_HOLDER_TYPE_CASTERS(SftSharedPtrStash)
|
||||
|
||||
TEST_SUBMODULE(class_sh_trampoline_shared_from_this, m) {
|
||||
py::classh<WithSft, WithSftTrampoline>(m, "WithSft").def(py::init<>());
|
||||
py::classh<Sft, SftTrampoline>(m, "Sft")
|
||||
.def(py::init<std::string>())
|
||||
.def_readonly("history", &Sft::history)
|
||||
.def("use_count", &Sft::use_count);
|
||||
|
||||
py::classh<SftSharedPtrStash>(m, "SftSharedPtrStash")
|
||||
.def(py::init<int>())
|
||||
.def("Add", &SftSharedPtrStash::Add)
|
||||
.def("AddSharedFromThis", &SftSharedPtrStash::AddSharedFromThis)
|
||||
.def("history", &SftSharedPtrStash::history)
|
||||
.def("use_count", &SftSharedPtrStash::use_count);
|
||||
|
||||
m.def("pass_shared_ptr", pass_shared_ptr);
|
||||
m.def("to_cout", to_cout);
|
||||
}
|
||||
|
@ -2,18 +2,77 @@
|
||||
|
||||
import pybind11_tests.class_sh_trampoline_shared_from_this as m
|
||||
|
||||
import gc
|
||||
import weakref
|
||||
|
||||
class PyWithSft(m.WithSft):
|
||||
|
||||
class PySft(m.Sft):
|
||||
pass
|
||||
|
||||
|
||||
def test_pass_shared_ptr():
|
||||
m.to_cout("")
|
||||
m.to_cout(">>> obj = PyWithSft()")
|
||||
obj = PyWithSft()
|
||||
m.to_cout(">>> m.pass_shared_ptr(obj) #1")
|
||||
obj = PySft("PySft")
|
||||
assert obj.history == "PySft"
|
||||
assert obj.use_count() == 2
|
||||
m.pass_shared_ptr(obj)
|
||||
m.to_cout(">>> m.pass_shared_ptr(obj) #2")
|
||||
assert obj.history == "PySft_PassSharedPtr"
|
||||
assert obj.use_count() == 2
|
||||
m.pass_shared_ptr(obj)
|
||||
m.to_cout(">>> del obj")
|
||||
assert obj.history == "PySft_PassSharedPtr_PassSharedPtr"
|
||||
assert obj.use_count() == 2
|
||||
|
||||
|
||||
def test_pass_shared_ptr_while_stashed():
|
||||
obj = PySft("PySft")
|
||||
obj_wr = weakref.ref(obj)
|
||||
stash1 = m.SftSharedPtrStash(1)
|
||||
stash1.Add(obj)
|
||||
assert obj.history == "PySft_Stash1Add"
|
||||
assert obj.use_count() == 2
|
||||
m.pass_shared_ptr(obj)
|
||||
assert obj.history == "PySft_Stash1Add_PassSharedPtr"
|
||||
assert obj.use_count() == 2
|
||||
stash2 = m.SftSharedPtrStash(2)
|
||||
stash2.Add(obj)
|
||||
assert obj.history == "PySft_Stash1Add_PassSharedPtr_Stash2Add"
|
||||
assert obj.use_count() == 2
|
||||
assert stash2.history(0) == "PySft_Stash1Add_PassSharedPtr_Stash2Add"
|
||||
assert stash2.use_count(0) == 1 # TODO: this is not great.
|
||||
stash2.Add(obj)
|
||||
assert obj.history == "PySft_Stash1Add_PassSharedPtr_Stash2Add_Stash2Add"
|
||||
assert obj.use_count() == 2
|
||||
assert stash1.use_count(0) == 1
|
||||
assert stash1.history(0) == "PySft_Stash1Add_PassSharedPtr_Stash2Add_Stash2Add"
|
||||
assert stash2.use_count(0) == 1
|
||||
assert stash2.history(0) == "PySft_Stash1Add_PassSharedPtr_Stash2Add_Stash2Add"
|
||||
assert stash2.use_count(1) == 1
|
||||
assert stash2.history(1) == "PySft_Stash1Add_PassSharedPtr_Stash2Add_Stash2Add"
|
||||
del obj
|
||||
assert stash2.use_count(0) == 1
|
||||
assert stash2.history(0) == "PySft_Stash1Add_PassSharedPtr_Stash2Add_Stash2Add"
|
||||
assert stash2.use_count(1) == 1
|
||||
assert stash2.history(1) == "PySft_Stash1Add_PassSharedPtr_Stash2Add_Stash2Add"
|
||||
del stash2
|
||||
gc.collect()
|
||||
assert obj_wr() is not None
|
||||
assert stash1.history(0) == "PySft_Stash1Add_PassSharedPtr_Stash2Add_Stash2Add"
|
||||
del stash1
|
||||
gc.collect()
|
||||
assert obj_wr() is None
|
||||
|
||||
|
||||
def test_pass_shared_ptr_while_stashed_with_shared_from_this():
|
||||
obj = PySft("PySft")
|
||||
obj_wr = weakref.ref(obj)
|
||||
stash1 = m.SftSharedPtrStash(1)
|
||||
stash1.AddSharedFromThis(obj)
|
||||
assert obj.history == "PySft_Stash1AddSharedFromThis"
|
||||
assert stash1.use_count(0) == 2
|
||||
stash1.AddSharedFromThis(obj)
|
||||
assert obj.history == "PySft_Stash1AddSharedFromThis_Stash1AddSharedFromThis"
|
||||
assert stash1.use_count(0) == 3
|
||||
assert stash1.use_count(1) == 3
|
||||
del obj
|
||||
del stash1
|
||||
gc.collect()
|
||||
assert obj_wr() is None
|
||||
|
Loading…
Reference in New Issue
Block a user