1# -------------------------------------------------------------------- 2 3cdef extern from * nogil: 4 int printf(char *, ...) 5 6cdef extern from "Python.h": 7 """ 8 #if defined(Py_LIMITED_API) 9 #define _pytype_enable_gc(t, traverse, clear) \ 10 do { (void)(traverse); (void)(clear); } while (0) 11 #else 12 #define _pytype_enable_gc(t, traverse, clear) \ 13 do { (t)->tp_traverse = (traverse); (t)->tp_clear = (clear); } while (0) 14 #endif 15 #if PY_VERSION_HEX < 0x030B0000 && !defined(Py_Version) 16 #define Py_Version __Pyx_get_runtime_version() 17 #endif 18 """ 19 const unsigned long Py_Version 20 enum: Py_TPFLAGS_HEAPTYPE 21 ctypedef struct PyObject 22 ctypedef struct PyTypeObject 23 void Py_VISIT(void*) noexcept 24 PyTypeObject *Py_TYPE(PyObject *) noexcept 25 unsigned long PyType_GetFlags(PyTypeObject *type) noexcept 26 ctypedef int (*visitproc)(PyObject *, void *) noexcept 27 ctypedef int (*traverseproc)(PyObject *, visitproc, void *) noexcept 28 ctypedef int (*inquiry)(PyObject *) noexcept 29 void _pytype_enable_gc(PyTypeObject *, traverseproc, inquiry) 30 31cdef extern from "<petsc/private/garbagecollector.h>" nogil: 32 PetscErrorCode PetscGarbageCleanup(MPI_Comm) 33 PetscErrorCode PetscGarbageView(MPI_Comm, PetscViewer) 34 35cdef int tp_traverse(PyObject *o, visitproc _visit, void *_arg) noexcept: 36 cdef visitproc visit "visit" = _visit 37 cdef void *arg "arg" = _arg 38 <void> visit 39 <void> arg 40 if Py_Version >= 0x03090000: 41 if not (PyType_GetFlags(Py_TYPE(o)) & Py_TPFLAGS_HEAPTYPE): 42 Py_VISIT(Py_TYPE(o)) 43 cdef PetscObject p = (<Object>o).obj[0] 44 if p == NULL: return 0 45 cdef PyObject *d = <PyObject*>p.python_context 46 if d == NULL: return 0 47 Py_VISIT(d) 48 return 0 49 50cdef int tp_clear(PyObject *o) noexcept: 51 cdef PetscObject *p = (<Object>o).obj 52 PetscDEALLOC(p) 53 return 0 54 55cdef inline void TypeEnableGC(PyTypeObject *t) noexcept: 56 _pytype_enable_gc(t, tp_traverse, tp_clear) 57 58 59def garbage_cleanup(comm: Comm | None = None) -> None: 60 """Clean up unused PETSc objects. 61 62 Collective. 63 64 Notes 65 ----- 66 If the communicator ``comm`` if not provided or it is `None`, 67 then `COMM_WORLD` is used. 68 69 """ 70 if not (<int>PetscInitializeCalled): return 71 if (<int>PetscFinalizeCalled): return 72 cdef MPI_Comm ccomm = MPI_COMM_NULL 73 if comm is None: 74 ccomm = GetComm(COMM_WORLD, MPI_COMM_NULL) 75 CHKERR(PetscGarbageCleanup(ccomm)) 76 else: 77 ccomm = GetComm(comm, MPI_COMM_NULL) 78 if ccomm == MPI_COMM_NULL: 79 raise ValueError("null communicator") 80 CHKERR(PetscGarbageCleanup(ccomm)) 81 82 83def garbage_view(comm: Comm | None = None) -> None: 84 """Print summary of the garbage PETSc objects. 85 86 Collective. 87 88 Notes 89 ----- 90 Print out garbage summary on each rank of the communicator ``comm``. 91 If no communicator is provided then `COMM_WORLD` is used. 92 93 """ 94 if not (<int>PetscInitializeCalled): return 95 if (<int>PetscFinalizeCalled): return 96 cdef MPI_Comm ccomm = MPI_COMM_NULL 97 if comm is None: 98 comm = COMM_WORLD 99 ccomm = GetComm(comm, MPI_COMM_NULL) 100 if ccomm == MPI_COMM_NULL: 101 raise ValueError("null communicator") 102 CHKERR(PetscGarbageView(ccomm, NULL)) 103 104# -------------------------------------------------------------------- 105