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