Given an arbitrary TObject, is there a way to find out who owns it?
The context of this question is as follows. In my Perl-ROOT wrapper, so far, I always assume the objects are owned by the user and Perl garbage collection will free the underlying TObjects when a variable goes out of scope. I know that’s wrong, thus the question.
Specifically, I’m trying to get this to do the right thing:
[code]my $canvas = TCanvas->new;
my $ar = TArrow->new(0.1,0.1,0.1,0.7);
$ar (aka the TArrow) owned by the canvas, right?
} # $ar freed here, need to know that the TArrow is not ours to free
If I manually keep the $ar and thus the TArrow around, this works just fine, of course.
I’m quite certain that people saw this one coming when I announced my early Perl-ROOT wrapper.
there’s a related thread at http://root.cern.ch/phpBB2/viewtopic.php?t=9284&highlight=object+ownership about the PyROOT memory management. Now, PyROOT’s code - specifically the TObject wrapping and associated memory management - is significantly more elaborate than what I have and will have in the near future. Regardless, in the above thread, Wim notes that he isn’t aware of a solution to the problem I posed:
This seems a little odd. ROOT does have to keep track somehow. My hunch is that with some extra work, it should be possible to find out whether a given TObject is the user’s responsibility or not. We have:
I’ve read up on kCanDelete and kMustCleanup in the object ownership chapter of the user manual, but I don’t think they get me there. kObjInCanvas and kIsReferenced do sound helpful, but I haven’t had the time to track down their meaning properly yet.
I’d like to get some input as to whether I’m barking up a completely wrong tree or whether it’d be possible to get programmatic access to what the Object Ownership chapter of the user manual describes.
If anything, the most common cases of TFile’s and TCanvases owning objects should be testable with some tree-walking of the special collections, right? I’m a little reluctant to try to do that without a sanity check from those who actually know ROOT. Sounds like it’d be very slow, doesn’t it.
Object Ownership is a tricky thing. I am writing this message via a very slow link, so I will not give you a long and complete answer.
ROOT takes care of bookkeeping some special objects, see TROOT
eg, files, sockets, geometries, canvases, threads, etc
When you create objects like TH1, TTree, they are added by default to the list of objects in the current directory (a TFile may have a TDirectoryFile tree). You can take out these objects from this list via object->SetDirectory(0). When a TFile is closed, all objects that are in the managed list are destroyed.
With TCanvas/TPad, things may be more complex because you can draw the same object in several canvases.
By default when adding an object to a TPad/TCanvas, its kMustCleanup bit is set. When you Delete/Close a TPad, the system loops on all the pad hierarchy objects and calling the object RecursiveRemove function,
removing the object from the pad lists and making sure that the object is deleted only ONCE if its kCanDelete bit is set. This way, the pad destructor makes sure that the same object is also removed from other pads containing it.
As this was supposed to be a short mail, I recommend to look at the TFile/TDirectoryFile, TCanvas/TPad destructors.
One additional difficulty is the cleanup at the end of the job.
In case your applications has objects in the stack, the destruction order is not specified. ROOT is protecting this problem by testing if an object has already been deleted (this assumes that the storage area for the object
has not been allocated to another object meanwhile).
Do not hesitate to ask more precise questions if you need. Most members of the ROOT team are in India this week, so the answer may be slower than usual.