File indexing completed on 2025-01-18 10:17:52
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010 #include "pybind11_tests.h"
0011
0012 struct CustomGuard {
0013 static bool enabled;
0014
0015 CustomGuard() { enabled = true; }
0016 ~CustomGuard() { enabled = false; }
0017
0018 static const char *report_status() { return enabled ? "guarded" : "unguarded"; }
0019 };
0020 bool CustomGuard::enabled = false;
0021
0022 struct DependentGuard {
0023 static bool enabled;
0024
0025 DependentGuard() { enabled = CustomGuard::enabled; }
0026 ~DependentGuard() { enabled = false; }
0027
0028 static const char *report_status() { return enabled ? "guarded" : "unguarded"; }
0029 };
0030 bool DependentGuard::enabled = false;
0031
0032 TEST_SUBMODULE(call_policies, m) {
0033
0034
0035
0036 class Child {
0037 public:
0038 Child() { py::print("Allocating child."); }
0039 Child(const Child &) = default;
0040 Child(Child &&) = default;
0041 ~Child() { py::print("Releasing child."); }
0042 };
0043 py::class_<Child>(m, "Child").def(py::init<>());
0044
0045 class Parent {
0046 public:
0047 Parent() { py::print("Allocating parent."); }
0048 Parent(const Parent &parent) = default;
0049 ~Parent() { py::print("Releasing parent."); }
0050 void addChild(Child *) {}
0051 Child *returnChild() { return new Child(); }
0052 Child *returnNullChild() { return nullptr; }
0053 static Child *staticFunction(Parent *) { return new Child(); }
0054 };
0055 py::class_<Parent>(m, "Parent")
0056 .def(py::init<>())
0057 .def(py::init([](Child *) { return new Parent(); }), py::keep_alive<1, 2>())
0058 .def("addChild", &Parent::addChild)
0059 .def("addChildKeepAlive", &Parent::addChild, py::keep_alive<1, 2>())
0060 .def("returnChild", &Parent::returnChild)
0061 .def("returnChildKeepAlive", &Parent::returnChild, py::keep_alive<1, 0>())
0062 .def("returnNullChildKeepAliveChild", &Parent::returnNullChild, py::keep_alive<1, 0>())
0063 .def("returnNullChildKeepAliveParent", &Parent::returnNullChild, py::keep_alive<0, 1>())
0064 .def_static("staticFunction", &Parent::staticFunction, py::keep_alive<1, 0>());
0065
0066 m.def(
0067 "free_function", [](Parent *, Child *) {}, py::keep_alive<1, 2>());
0068 m.def(
0069 "invalid_arg_index", [] {}, py::keep_alive<0, 1>());
0070
0071 #if !defined(PYPY_VERSION)
0072
0073 class ParentGC : public Parent {
0074 public:
0075 using Parent::Parent;
0076 };
0077 py::class_<ParentGC, Parent>(m, "ParentGC", py::dynamic_attr()).def(py::init<>());
0078 #endif
0079
0080
0081 m.def("unguarded_call", &CustomGuard::report_status);
0082 m.def("guarded_call", &CustomGuard::report_status, py::call_guard<CustomGuard>());
0083
0084 m.def(
0085 "multiple_guards_correct_order",
0086 []() {
0087 return CustomGuard::report_status() + std::string(" & ")
0088 + DependentGuard::report_status();
0089 },
0090 py::call_guard<CustomGuard, DependentGuard>());
0091
0092 m.def(
0093 "multiple_guards_wrong_order",
0094 []() {
0095 return DependentGuard::report_status() + std::string(" & ")
0096 + CustomGuard::report_status();
0097 },
0098 py::call_guard<DependentGuard, CustomGuard>());
0099
0100 #if defined(WITH_THREAD) && !defined(PYPY_VERSION)
0101
0102
0103 auto report_gil_status = []() {
0104 auto is_gil_held = false;
0105 if (auto *tstate = py::detail::get_thread_state_unchecked()) {
0106 is_gil_held = (tstate == PyGILState_GetThisThreadState());
0107 }
0108
0109 return is_gil_held ? "GIL held" : "GIL released";
0110 };
0111
0112 m.def("with_gil", report_gil_status);
0113 m.def("without_gil", report_gil_status, py::call_guard<py::gil_scoped_release>());
0114 #endif
0115 }