diff --git a/clif/pybind11/classes.py b/clif/pybind11/classes.py index e7e92dd8..b53f5a64 100644 --- a/clif/pybind11/classes.py +++ b/clif/pybind11/classes.py @@ -100,6 +100,7 @@ def generate_from( base.cpp_canonical_type in codegen_info.dynamic_attr_types): enable_instance_dict = True break + definition += ', py::release_gil_before_calling_cpp_dtor()' if mi_bases: definition += ', py::multiple_inheritance()' if enable_instance_dict: diff --git a/clif/testing/class_release_gil_before_calling_cpp_dtor.h b/clif/testing/class_release_gil_before_calling_cpp_dtor.h new file mode 100644 index 00000000..ca172c03 --- /dev/null +++ b/clif/testing/class_release_gil_before_calling_cpp_dtor.h @@ -0,0 +1,62 @@ +/* + * Copyright 2024 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// Similar to pybind11/tests/test_class_release_gil_before_calling_cpp_dtor.cpp + +#ifndef CLIF_TESTING_CLASS_RELEASE_GIL_BEFORE_CALLING_CPP_DTOR_H_ +#define CLIF_TESTING_CLASS_RELEASE_GIL_BEFORE_CALLING_CPP_DTOR_H_ + +#include + +#include +#include + +namespace clif_testing::class_release_gil_before_calling_cpp_dtor { + +using RegistryType = std::unordered_map; + +inline RegistryType &PyGILState_Check_Results() { + static auto *singleton = new RegistryType(); + return *singleton; +} + +struct ProbeType { + private: + std::string unique_key; + + public: + explicit ProbeType(const std::string &unique_key) : unique_key{unique_key} {} + + ~ProbeType() { + RegistryType ® = PyGILState_Check_Results(); + assert(reg.count(unique_key) == 0); + reg[unique_key] = PyGILState_Check(); + } +}; + +std::string PopPyGILState_Check_Result(const std::string &unique_key) { + RegistryType ® = PyGILState_Check_Results(); + if (reg.count(unique_key) == 0) { + return "MISSING"; + } + int res = reg[unique_key]; + reg.erase(unique_key); + return std::to_string(res); +} + +} // namespace clif_testing::class_release_gil_before_calling_cpp_dtor + +#endif // CLIF_TESTING_CLASS_RELEASE_GIL_BEFORE_CALLING_CPP_DTOR_H_ diff --git a/clif/testing/python/CMakeLists.txt b/clif/testing/python/CMakeLists.txt index c001315a..753fe372 100644 --- a/clif/testing/python/CMakeLists.txt +++ b/clif/testing/python/CMakeLists.txt @@ -247,4 +247,6 @@ add_pyclif_library_for_test(std_containers_copy_move std_containers_copy_move.cl CLIF_DEPS clif_testing_python_copy_move_types_library ) +add_pyclif_library_for_test(class_release_gil_before_calling_cpp_dtor class_release_gil_before_calling_cpp_dtor.clif) + # OMITTED: instrumentation_for_testing_test (pytype currently not supported on GitHub) diff --git a/clif/testing/python/class_release_gil_before_calling_cpp_dtor.clif b/clif/testing/python/class_release_gil_before_calling_cpp_dtor.clif new file mode 100644 index 00000000..f3cb98a4 --- /dev/null +++ b/clif/testing/python/class_release_gil_before_calling_cpp_dtor.clif @@ -0,0 +1,20 @@ +# Copyright 2024 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +from "clif/testing/class_release_gil_before_calling_cpp_dtor.h": + namespace `clif_testing::class_release_gil_before_calling_cpp_dtor`: + class ProbeType: + def __init__(self, unique_key: str) + + def PopPyGILState_Check_Result(unique_key: str) -> str diff --git a/clif/testing/python/class_release_gil_before_calling_cpp_dtor_test.py b/clif/testing/python/class_release_gil_before_calling_cpp_dtor_test.py new file mode 100644 index 00000000..99465dbb --- /dev/null +++ b/clif/testing/python/class_release_gil_before_calling_cpp_dtor_test.py @@ -0,0 +1,32 @@ +# Copyright 2024 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import gc + +from absl.testing import absltest + +from clif.testing.python import class_release_gil_before_calling_cpp_dtor as tm + + +class ReleaseGilBeforeCallingCppDtorTest(absltest.TestCase): + + def test_with_probe_type(self): + unique_key = "release_gil_before_calling_cpp_dtor" + tm.ProbeType(unique_key) + gc.collect() + self.assertEqual(tm.PopPyGILState_Check_Result(unique_key), "0") + + +if __name__ == "__main__": + absltest.main()