Logo ROOT  
Reference Guide
 
Loading...
Searching...
No Matches
TMemoryRegulator.cxx
Go to the documentation of this file.
1
2// Author: Enric Tejedor CERN 08/2019
3// Author: Vincenzo Eduardo Padulano CERN 05/2024
4
5/*************************************************************************
6 * Copyright (C) 1995-2019, Rene Brun and Fons Rademakers. *
7 * All rights reserved. *
8 * *
9 * For the licensing terms see $ROOTSYS/LICENSE. *
10 * For the list of contributors see $ROOTSYS/README/CREDITS. *
11 *************************************************************************/
12
13#include "TMemoryRegulator.h"
14
15#include "../../cppyy/CPyCppyy/src/ProxyWrappers.h"
16#include "../../cppyy/CPyCppyy/src/CPPInstance.h"
17
18////////////////////////////////////////////////////////////////////////////
19/// \brief Constructor. Registers the hooks to run on Cppyy's object
20/// construction and destruction
22{
24 [this](Cppyy::TCppObject_t cppobj, Cppyy::TCppType_t klass) { return this->RegisterHook(cppobj, klass); });
26 [this](Cppyy::TCppObject_t cppobj, Cppyy::TCppType_t klass) { return this->UnregisterHook(cppobj, klass); });
27}
28
29////////////////////////////////////////////////////////////////////////////
30/// \brief Register a hook that Cppyy runs when constructing an object.
31/// \param[in] cppobj Address of the object.
32/// \param[in] klass Class id of the object.
33/// \return Pair of two booleans. First indicates success, second tells
34/// Cppyy if we want to continue running RegisterPyObject
36{
37 static Cppyy::TCppType_t tobjectTypeID = (Cppyy::TCppType_t)Cppyy::GetScope("TObject");
38
39 if (Cppyy::IsSubtype(klass, tobjectTypeID)) {
40 fObjectMap.insert({cppobj, klass});
41 }
42
43 return {true, true};
44}
45
46////////////////////////////////////////////////////////////////////////////
47/// \brief Register a hook that Cppyy runs when deleting an object.
48/// \param[in] cppobj Address of the object.
49/// \param[in] klass Class id of the object.
50/// \return Pair of two booleans. First indicates success, second tells
51/// Cppyy if we want to continue running UnRegisterPyObject
53{
54
55 static Cppyy::TCppType_t tobjectTypeID = (Cppyy::TCppType_t)Cppyy::GetScope("TObject");
56
57 if (Cppyy::IsSubtype(klass, tobjectTypeID)) {
58 if (auto it = fObjectMap.find(cppobj); it != fObjectMap.end())
59 fObjectMap.erase(it);
60 }
61
62 return {true, true};
63}
64
65////////////////////////////////////////////////////////////////////////////
66/// \brief Get the class id of the TObject being deleted and run Cppyy's
67/// RecursiveRemove.
68/// \param[in] object Object being destructed.
70{
71 auto cppobj = reinterpret_cast<Cppyy::TCppObject_t>(object);
72
73 if (auto it = fObjectMap.find(cppobj); it != fObjectMap.end()) {
75 fObjectMap.erase(it);
76 }
77}
78
79////////////////////////////////////////////////////////////////////////////
80/// \brief Clean up all tracked objects.
82{
83 while (!fObjectMap.empty()) {
84 auto elem = fObjectMap.begin();
85 auto cppobj = elem->first;
86 auto klassid = elem->second;
87 auto pyclass = CPyCppyy::CreateScopeProxy(klassid);
89
90 if (pyobj && (pyobj->fFlags & CPyCppyy::CPPInstance::kIsOwner)) {
91 // Only delete the C++ object if the Python proxy owns it.
92 // If it is a value, cppyy deletes it in RecursiveRemove as part of
93 // the proxy cleanup.
94 auto o = static_cast<TObject *>(cppobj);
95 bool isValue = pyobj->fFlags & CPyCppyy::CPPInstance::kIsValue;
96 CallCppyyRecursiveRemove(o);
97 if (!isValue)
98 delete o;
99 } else {
100 // Non-owning proxy, just unregister to clean tables.
101 // The proxy deletion by Python will have no effect on C++, so all good
102 bool ret = CPyCppyy::MemoryRegulator::UnregisterPyObject(pyobj, pyclass);
103 if (!ret) {
104 fObjectMap.erase(elem);
105 }
106 }
107 }
108}
static bool RecursiveRemove(Cppyy::TCppObject_t cppobj, Cppyy::TCppType_t klass)
static PyObject * RetrievePyObject(Cppyy::TCppObject_t cppobj, PyObject *pyclass)
static void SetUnregisterHook(MemHook_t h)
static void SetRegisterHook(MemHook_t h)
static bool UnregisterPyObject(CPPInstance *pyobj, PyObject *pyclass)
std::pair< bool, bool > RegisterHook(Cppyy::TCppObject_t, Cppyy::TCppType_t)
Register a hook that Cppyy runs when constructing an object.
void CallCppyyRecursiveRemove(TObject *object)
Get the class id of the TObject being deleted and run Cppyy's RecursiveRemove.
void ClearProxiedObjects()
Clean up all tracked objects.
std::pair< bool, bool > UnregisterHook(Cppyy::TCppObject_t, Cppyy::TCppType_t)
Register a hook that Cppyy runs when deleting an object.
Mother of all ROOT objects.
Definition TObject.h:41
PyObject * CreateScopeProxy(Cppyy::TCppScope_t, const unsigned flags=0)
RPY_EXPORTED bool IsSubtype(TCppType_t derived, TCppType_t base)
void * TCppObject_t
Definition cpp_cppyy.h:21
TCppScope_t TCppType_t
Definition cpp_cppyy.h:19
RPY_EXPORTED TCppScope_t GetScope(const std::string &scope_name)