Re: Reading objects in TObjectBranch without new/delete?

From: stefan kluth (skluth@mh1.lbl.gov)
Date: Thu Oct 28 1999 - 20:40:21 MEST


On Thu, 28 Oct 1999, Rene Brun wrote:

> > As far as I understand, the normal procedure for ROOT when reading objects
> > e.g. of type A in a TObjectBranch of a TTree is to delete the previous
> > object pointed to by the pointer contained in TObjectBranch::fAddress and
> > creating a new object using its default ctor A::A(). Then it is filled
> > using the Streamer member function of the object A::Streamer(...).
> 
> This will work if users make sure to delete all objects and basic types
> allocated via new in the Streamer function itself. I cannot introduce
> this functionality by default, too many people will complain.
> However, I could introduce an option (at the branch or tree ? level)
> to tell Root that it should not delete the object before invoking
> Streamer.
>  What about TTree:SetAutoDelete(Bool_t mode=kTRUE) ?
That sounds good, but I think it should also be possible to set this per
branch. So TTree::SetAutoDelete(Bool_t mode=kTRUE) could be used to set
the default behaviour for all branches of a tree, but one could also use
TBranch::SetAutoDelete(Bool_t mode=kTRUE) to switch branches individually.
One could also think of a scheme, where it depends on the value of the
pointer in TBranch::fAddress, e.g. if it is 0, ROOT creates and deletes
for every event, and if it is != 0, ROOT doesn't does not delete and
create it. However, I do not like this implicit method, and I prefer
explicit setting of this important behaviour in the way you proposed. 

> Note that in case of split mode, this is already the case. The top level
> object is never deleted.
Oops, I didn't realise this. This is another example of behaviour
differences between branches in split-mode and non-split-mode, I guess.
(The other one was that the pointer to the read object was not available
via the pointer in TBranch::fAddress, and has been fixed in 2.23/04). It
seems these two behaviour differences are connected, since in split-mode
ROOT does not delete the object it was presumed not neccessay to provide
the pointer through TBranch::fAddress. 

It would be preferable to have the same behaviour of branches in split- or
non-split-mode, i.e. setting the split mode should not have side-effects
(other than creating lots of branches of course!). I assume that
some existing code might be broken, if ROOT changes its default behaviour
for split-mode branches from not deleting objects to deleting them. I
personally would prefer to have consistent default behaviour for all
branches, at least after TTree::SetAutoDelete(true/false) has been called.
Perhaps the general default should be, that objects are not deleted, but
this could introduce new memory leaks in existing user code. 


> > Is it possible to arrange it so that ROOT does not delete the existing
> > object, and just calls the Streamer A::Streamer again to overwrite the
> > contents?
> > 
> > This should work ok for objects with "constant memory footprint", i.e.
> > those which don't allocate memory from the heap themselves.
> > 
> > One interesting application would be that one could have several
> > TObjectBranch'es holding the *same* type of objects, which in turn contain
> > non-static pointers to TClonesArrays holding identical types of objects.
> 
> I am not sure I understand what you mean precisely without giving an
> example.
Your suggestion above answers my question. 
 

> > Currently, one can only have one TObjectBranch containig objects with
> > a static pointer to one TClonesArray to reuse memory. If one would have
> > several branches, reading the next branch would overwrite the data from a
> > previously read branch in the one shared TClonesArray.
> 
> > 
> > For example, one could read several TObjectBranches of the Event
> > class containig different events. Of course, one would not do this with an
> > "event", but one could imagine storing and retrieving several objects of
> > the same type containg lists of e.g. tracks reconstructed in different
> > ways.
> \
> You can already do this by either swapping pointers or calling
> tree->SetBranchAddress.
I think you suggest ways to reuse one object in several branches. But what
about the case, when I need the data of both branches simultaneously, i.e.
I really need two objects including two TClonesArrays in memory? If I was
guaranteed that the top level object does not get deleted, it could hold a
non-static pointer to a TClonesArray, which would be reused for just this 
branch. Your nice suggestion above would allow exactly this solution, and
decouple it from using split-mode. 

I would have another suggestion for a convenience to users of objects,
which don't get deleted. These must be "cleared" after every event, if
they allocate memory or contain a pointer to a TClonesAyrray. Adding a new
virtual member function to TObject might make this easier:

class TObject {

...

public:

virtual Clear() {}

...

}

A user could implement Clear() to do the cleaning up if neccessary and
TBranch would call it always just before actually reading a new entry (if
it is in the state that it does not delete/create objects for every
entry, a default or from calling TTree::SetAutoDelete(false) or
TBranch::SetAutoDelete(false)). 

cheers, Stefan

---Stefan Kluth---------------Lynen Fellow----------------|\--|\-------
-  LBNL, MS 50A 2160       -  phone:  +1 510 495 2376  -  |/  |/      -
-  1 Cyclotron Rd.         -  fax:    +1 510 495 2957  -  |\/\|\/\|'  -
---Berkeley, CA94720, USA-----e-mail: SKluth@lbl.gov------|/\/|/\/|----



This archive was generated by hypermail 2b29 : Tue Jan 04 2000 - 00:43:41 MET