From 86273bd5ec58b2d4fa0b5278f70873e387da94ec Mon Sep 17 00:00:00 2001 From: Axel Huebl Date: Sun, 16 Oct 2022 18:03:23 -0700 Subject: [PATCH] `amrex::Finalize()` w/ `gc.collect()` (#83) When calling `amrex.finalize()`, first call the Python garbage collector. This is purely a bandage to make usage like this easy: ```py import amrex amrex.initialize([]) mfab = amrex.MultiFab( ... ) del mfab amrex.finalize() ``` Respect the Python standard guarantees without furhter headache, by running an explicit call to the garbage collector. Previously, this was only working with CPython, but alternative implementations like PyPy might delay the true free due to time based memory collection approaches. --- src/Base/AMReX.cpp | 22 ++++++++++++++++++++-- 1 file changed, 20 insertions(+), 2 deletions(-) diff --git a/src/Base/AMReX.cpp b/src/Base/AMReX.cpp index dfccda07..c1107682 100644 --- a/src/Base/AMReX.cpp +++ b/src/Base/AMReX.cpp @@ -103,7 +103,25 @@ void init_AMReX(py::module& m) }, py::return_value_policy::reference, "Initialize AMReX library"); + constexpr auto run_gc = []() { + // explicitly run the garbage collector, so deleted objects + // get freed. + // This is a convenience helper/bandage for making work with Python + // garbage collectors in various implementations more easy. + // https://github.com/AMReX-Codes/pyamrex/issues/81 + auto m_gc = py::module::import("gc"); + auto collect = m_gc.attr("collect"); + collect(); + }; + + m.def("finalize", + [run_gc]() { + run_gc(); + amrex::Finalize(); + }); m.def("finalize", - py::overload_cast<>(&Finalize)); - m.def("finalize", py::overload_cast(&Finalize)); + [run_gc](AMReX* pamrex) { + run_gc(); + amrex::Finalize(pamrex); + }); }