23 PyMethodDef gObjectEraseMethodDef = {
24 const_cast< char*
>(
"TMemoryRegulator_internal_ObjectEraseCallback" ),
31 PyTypeObject PyROOT_NoneType;
42 PyMappingMethods PyROOT_NoneType_mapping = {
49#if defined(__GNUC__) && (__GNUC__ >= 5 || (__GNUC__ >= 4 && ((__GNUC_MINOR__ == 2 && __GNUC_PATCHLEVEL__ >= 1) || (__GNUC_MINOR__ >= 3)))) && !__INTEL_COMPILER
50#pragma GCC diagnostic ignored "-Wstrict-aliasing"
55 struct InitPyROOT_NoneType_t {
56 InitPyROOT_NoneType_t()
59 memset( &PyROOT_NoneType, 0,
sizeof( PyROOT_NoneType ) );
61 ((
PyObject&)PyROOT_NoneType).ob_type = &PyType_Type;
62 ((
PyObject&)PyROOT_NoneType).ob_refcnt = 1;
63 ((PyVarObject&)PyROOT_NoneType).ob_size = 0;
65 PyROOT_NoneType.tp_name =
const_cast< char*
>(
"PyROOT_NoneType" );
66 PyROOT_NoneType.tp_flags = Py_TPFLAGS_HAVE_RICHCOMPARE | Py_TPFLAGS_HAVE_GC;
68 PyROOT_NoneType.tp_traverse = (traverseproc) 0;
69 PyROOT_NoneType.tp_clear = (inquiry) 0;
70 PyROOT_NoneType.tp_dealloc = (destructor) &InitPyROOT_NoneType_t::DeAlloc;
71 PyROOT_NoneType.tp_repr =
Py_TYPE(Py_None)->tp_repr;
72 PyROOT_NoneType.tp_richcompare = (richcmpfunc) &InitPyROOT_NoneType_t::RichCompare;
73#if PY_VERSION_HEX < 0x03000000
77 PyROOT_NoneType.tp_hash = (hashfunc) &InitPyROOT_NoneType_t::PtrHash;
79 PyROOT_NoneType.tp_as_mapping = &PyROOT_NoneType_mapping;
81 PyType_Ready( &PyROOT_NoneType );
89 return PyObject_RichCompare( other, Py_None, opid );
94#if PY_VERSION_HEX < 0x03000000
95 return PyObject_Compare( other, Py_None );
98 return ! PyObject_RichCompareBool( other, Py_None, Py_EQ );
110 static InitPyROOT_NoneType_t initPyROOT_NoneType;
124 delete fgWeakRefTable;
127 delete fgObjectTable;
136 if ( !
object || ! fgObjectTable )
140 ObjectMap_t::iterator ppo = fgObjectTable->find(
object );
142 if ( ppo != fgObjectTable->end() ) {
143 fgWeakRefTable->erase( fgWeakRefTable->find( ppo->second ) );
148 fgObjectTable->erase( ppo );
153 Py_DECREF( ppo->second );
157 if ( ! PyROOT_NoneType.tp_traverse ) {
162 PyROOT_NoneType.tp_traverse =
Py_TYPE(pyobj)->tp_traverse;
163 PyROOT_NoneType.tp_clear =
Py_TYPE(pyobj)->tp_clear;
164 PyROOT_NoneType.tp_free =
Py_TYPE(pyobj)->tp_free;
165 }
else if ( PyROOT_NoneType.tp_traverse !=
Py_TYPE(pyobj)->tp_traverse ) {
166 std::cerr <<
"in PyROOT::TMemoryRegulater, unexpected object of type: "
167 <<
Py_TYPE(pyobj)->tp_name << std::endl;
174 int refcnt = ((
PyObject*)pyobj)->ob_refcnt;
176 PyObject_ClearWeakRefs( (
PyObject*)pyobj );
177 ((
PyObject*)pyobj)->ob_refcnt = refcnt;
184 Py_INCREF( (
PyObject*)(
void*)&PyROOT_NoneType );
186 ((
PyObject*)pyobj)->ob_type = &PyROOT_NoneType;
190 fgObjectTable->erase( ppo );
199 while (!fgObjectTable->empty()) {
200 auto elem = fgObjectTable->begin();
201 auto cppobj = elem->first;
202 auto pyobj = (
ObjectProxy*)PyWeakref_GetObject(elem->second);
212 UnregisterObject(cppobj);
222 static PyObject* objectEraseCallback = PyCFunction_New(&gObjectEraseMethodDef,
nullptr);
224 if ( ! ( pyobj &&
object ) )
227 ObjectMap_t::iterator ppo = fgObjectTable->find(
object );
228 if ( ppo == fgObjectTable->end() ) {
230 PyObject* pyref = PyWeakref_NewRef( (
PyObject*)pyobj, objectEraseCallback );
231 ObjectMap_t::iterator newppo = fgObjectTable->insert( std::make_pair(
object, pyref ) ).first;
232 (*fgWeakRefTable)[ pyref ] = newppo;
244 ObjectMap_t::iterator ppo = fgObjectTable->find(
object );
246 if ( ppo != fgObjectTable->end() ) {
247 fgWeakRefTable->erase( fgWeakRefTable->find( ppo->second ) );
248 fgObjectTable->erase( ppo );
263 ObjectMap_t::iterator ppo = fgObjectTable->find(
object );
264 if ( ppo != fgObjectTable->end() ) {
265 PyObject* pyobj = PyWeakref_GetObject( ppo->second );
267 if ( pyobj && ((
ObjectProxy*)pyobj)->ObjectIsA() != klass ) {
294 ObjectMap_t::iterator ppo = fgObjectTable->find(
object );
295 if ( ppo != fgObjectTable->end() ) {
297 fgWeakRefTable->erase( fgWeakRefTable->find( ppo->second ) );
298 Py_DECREF( ppo->second );
299 fgObjectTable->erase( ppo );
304 WeakRefMap_t::iterator wri = fgWeakRefTable->find( pyref );
305 if ( wri != fgWeakRefTable->end() ) {
306 fgObjectTable->erase( wri->second );
307 fgWeakRefTable->erase( wri );
312 Py_INCREF( Py_None );
Int_t Compare(const void *item1, const void *item2)
Cppyy::TCppType_t ObjectIsA() const
static Bool_t UnregisterObject(TObject *object)
stop tracking <object>, without notification
static Bool_t RegisterObject(ObjectProxy *pyobj, TObject *object)
start tracking <object> proxied by <pyobj>
virtual void RecursiveRemove(TObject *object)
Recursively remove this object from a list.
~TMemoryRegulator()
cleanup weakref cache
std::unordered_map< TObject *, PyObject * > ObjectMap_t
static ObjectMap_t * fgObjectTable
static PyObject * ObjectEraseCallback(PyObject *, PyObject *pyref)
void ClearProxiedObjects()
clean up all tracked objects
std::unordered_map< PyObject *, ObjectMap_t::iterator > WeakRefMap_t
static PyObject * RetrieveObject(TObject *object, Cppyy::TCppType_t klass)
lookup <object>, return old proxy if tracked
static WeakRefMap_t * fgWeakRefTable
Mother of all ROOT objects.
@ kMustCleanup
if object destructor must call RecursiveRemove()
ptrdiff_t GetBaseOffset(TCppType_t derived, TCppType_t base, TCppObject_t address, int direction, bool rerror=false)
TCppScope_t GetScope(const std::string &scope_name)
Bool_t IsSubtype(TCppType_t derived, TCppType_t base)
Bool_t ObjectProxy_Check(T *object)
void op_dealloc_nofree(ObjectProxy *)
Destroy the held C++ object, if owned; does not deallocate the proxy.