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