ATLAS Offline Software
|
A variant of TBranchElement
that can call converters when reading objects in split mode.
More...
#include <TConvertingBranchElement.h>
Public Member Functions | |
TConvertingBranchElement () | |
Constructor. More... | |
virtual | ~TConvertingBranchElement () |
Destructor. More... | |
virtual Int_t | GetEntry (Long64_t entry, Int_t getall) |
Read all branches into the previously-declared object. More... | |
virtual void | Streamer (TBuffer &R__b) |
Read or write this object. More... | |
virtual void | SetAddress (void *add) |
Set the address of the object to use for I/O. More... | |
virtual void | ResetAddress () |
Reset branch addresses and maybe delete the object. More... | |
Static Public Member Functions | |
static void | Initialize () |
Set up to allow for conversions in split mode. More... | |
static void | SetDoDel (bool flag) |
Set the deletion flag. More... | |
Protected Member Functions | |
virtual void | InitInfo () |
Initialize the TStreamerInfo pointer. More... | |
virtual void | InitializeOffsets () |
Initialize data member offsets. More... | |
void | ReadLeavesCollectionConverting (TBuffer &b) |
Read leaves into I/O buffers for this branch. More... | |
void | ReadLeavesMemberBranchCountConverting (TBuffer &b) |
Private Types | |
enum | { kIsDummy = BIT(20) } |
Flag used to mark dummy nodes created by BuildConvertedElisions . More... | |
Private Member Functions | |
void | BuildConvertedElisions () |
Add dummy nodes if needed to recover the correct tree structure. More... | |
void | CheckForConversion () |
Check to see if we need to worry about conversions for this branch. More... | |
void | ConvResetType () |
Recursively reset the type field of containers in conversions. More... | |
Int_t | ReadSubBranches (Long64_t entry, Int_t getall, bool dont_reset) |
@branch Read in the subbranches of this branch. More... | |
TConvertingBranchElement & | operator= (const TConvertingBranchElement &) |
If true, try to delete the. More... | |
TConvertingBranchElement (const TConvertingBranchElement &) | |
Static Private Member Functions | |
static void * | new_TConvertingBranchElement (void *p) |
new() method for this object. More... | |
Private Attributes | |
TVirtualConverter * | fConv |
TClass * | fConvClass |
Conversion for this branch. More... | |
char * | fConvObject |
Class for conversion. More... | |
TObjArray * | fConvOrigBranches |
Pointer to tmp obj used for conversion. More... | |
Int_t | fConvOrigType |
Saved branch list. If we change. More... | |
bool | fConvContainerFlag |
Saved branch type. The original. More... | |
bool | fConvDontReset |
True if we're doing a container. More... | |
Static Private Attributes | |
static std::atomic< bool > | fgDoDel = false |
Flag that the next read should. More... | |
A variant of TBranchElement
that can call converters when reading objects in split mode.
Definition at line 64 of file TConvertingBranchElement.h.
|
private |
Flag used to mark dummy nodes created by BuildConvertedElisions
.
Enumerator | |
---|---|
kIsDummy |
Definition at line 155 of file TConvertingBranchElement.h.
TConvertingBranchElement::TConvertingBranchElement | ( | ) |
|
virtual |
Destructor.
Constructor.
Get rid of any temporary objects which we made.
Definition at line 304 of file TConvertingBranchElement.cxx.
|
private |
|
private |
Add dummy nodes if needed to recover the correct tree structure.
Given a TBranchElement
tree structure, Root will elide some of the intermediate tree nodes. For example, given:
a a.b a.b.c a.b.c.d1 a.b.c.d2
Root will elide the ‘c’ node — so one has node ‘a’, with child ‘a.b’, with children ‘a.b.c.d1’ and ‘a.b.c.d2’.
This greatly complicates the process of running conversions, if ‘c’ has a conversion. So, what we do is if we determine that a conversion is needed, we modify the tree to reinsert the elided nodes. These nodes will have the kIsDummy flag set. Further, if we do that, we remember the original branch list from the parent node (‘a.b’ in the above example), so that if the structure is written, we can write the original, elided structure.
Definition at line 397 of file TConvertingBranchElement.cxx.
|
private |
Check to see if we need to worry about conversions for this branch.
Set up member variables if so.
Definition at line 611 of file TConvertingBranchElement.cxx.
|
private |
Recursively reset the type field of containers in conversions.
Recursively reset the type field of container elts in conversions.
Walk recursively through all children of this node. Any of them that have a fType
corresponding to a member field within a container (31 or 41) are reset to 2 (normal member).
Definition at line 753 of file TConvertingBranchElement.cxx.
|
virtual |
Read all branches into the previously-declared object.
entry | The ntuple row to read. |
getall | If true, force reading all branches, even those previously deactivated. |
If entry = 0, then use current entry number + 1. If entry < 0, then reset entry number to 0.
Returns the number of bytes read from the input buffer. If entry does not exist, then returns 0. If an I/O error occurs, then returns -1.
entry | The ntuple row to read. |
getall | If true, force reading all branches, even those previously deactivated. |
If entry = 0, then use current entry number + 1. If entry < 0, then reset entry number to 0.
Returns the number of bytes read from the input buffer. If entry does not exist, then returns 0. If an I/O error occurs, then returns -1.
Some notes about conversions. If this branch has a conversion, then rather than reading directly into the target address, we instead read into a temporary object of the persistent type (fConvObject
), and then call the converter to copy from the persistent to the transient object. We override SetAddress
so that this will get set correctly for children of converted classes.
Note that the need to call the converter from the branch node corresponding to the class with the conversion is why we have problems with elided tree nodes — and the reason for BuildConvertedElisions
.
Containers are more complicated. Suppose we have something like:
struct A { int a1; int a2; }; struct B { int b1; A b2; }; struct C { std::vector<B> c1; };
and we're working on the vector.
The way Root handles this is that we have three branches: c1.b1, c1.b1.a1, c1.b1.a2 holding the container data. In addition, the container branch c1 will hold the count of the number of elements in the container. What Root does is:
TBranchElement
. Its children point to it to get the number of elements.TBranchInfo::ReadBufferSTL
. We get the number of elements by looking in the parent container branch. Note that for the children of the container, the address set via SetAddress
is not the address of the object itself, but rather the address of a collection proxy. The proxy is then associated with the actual container being read.Now, when we try to do this with conversions, we run into the problem that we need the complete object in order to run the conversion. One way of doing this would be to buffer the complete collection of persistent objects, then loop over them calling the converter. I wanted to avoid having to do that for large collections, so what's done here is somewhat more complicated. The idea is to change the order of the loop over the branches and the loop over the elements, so that we make one complete object at a time. In a little more detail:
GetEntry
. But first, we call SetAddress
to pass in the address of the temporary persistent object (if a conversion is being done for the object directly contained by the container) or the address of the object in the container (if the conversion is further down).GetEntry
is called for a member in a container, it (via ReadLeaves
) resets the TBuffer
to point at the first element in the collection. Because of how we've rearranged the loops, we want this to happen only on the first time. To accomplish this, a ‘dont_reset’ flag is introduced, to tell GetEntry
not to call ReadLeaves
. It would be most natural to do this by adding a parameter to GetEntry
. However, at this point, we do not want to change the GetEntry
interface. So, instead of passing this as an argument, it's passed in a member variable, fConvDontReset
.All of this is handled by the following methods: GetEntry
ReadLeaves
ReadSubBranches
Definition at line 858 of file TConvertingBranchElement.cxx.
|
static |
Set up to allow for conversions in split mode.
Definition at line 335 of file TConvertingBranchElement.cxx.
|
protectedvirtual |
Initialize data member offsets.
(Overridden internal method.)
Definition at line 1301 of file TConvertingBranchElement.cxx.
|
protectedvirtual |
Initialize the TStreamerInfo pointer.
(Overridden internal method.)
(Overridden internal method.)
This gets called by GetInfo
if the fInfo
pointer is null. It should initialize that pointer.
Here is where we check for a conversion.
Definition at line 721 of file TConvertingBranchElement.cxx.
|
staticprivate |
new() method for this object.
p | Address for placement new, or 0. |
This is installed as the New
method in TBranchElement's
TClass
. Thus, when we read from a file a TBranchElement
, we actually make an instance of this class.
Definition at line 366 of file TConvertingBranchElement.cxx.
|
private |
If true, try to delete the.
|
protected |
Read leaves into I/O buffers for this branch.
b | Root I/O buffer. |
Definition at line 977 of file TConvertingBranchElement.cxx.
|
protected |
Definition at line 1069 of file TConvertingBranchElement.cxx.
|
private |
@branch Read in the subbranches of this branch.
entry | The entry number to read. |
getall | If true, read all branches, even if disabled. |
dont_reset | If true, don't reset the TBuffer read pointer. |
entry | The entry number to read. |
getall | If true, read all branches, even if disabled. |
dont_reset | If true, don't reset the TBuffer read pointer. |
This is used to factor out the handling of conversions in containers.
Definition at line 1125 of file TConvertingBranchElement.cxx.
|
virtual |
Reset branch addresses and maybe delete the object.
We have this here because the functionality of getting the object is disabled in standard root, for reasons which aren't entirely clear. We want to add the option to turn it on again, to prevent leaks.
Definition at line 1388 of file TConvertingBranchElement.cxx.
|
virtual |
Set the address of the object to use for I/O.
add | Object address. |
add | Object address. |
Overridden from the base class: if we have a temporary persistent object for conversions, then we pass down the address of that object rather than what we were given.
Definition at line 1358 of file TConvertingBranchElement.cxx.
|
static |
Set the deletion flag.
flag | If true, try to delete the branch object on branch deletion. |
Definition at line 1464 of file TConvertingBranchElement.cxx.
|
virtual |
Read or write this object.
We wrap around the base class streamer. If we made any alterations to the persistent data members, we undo those changes here before calling the base streamer. This way the conversion handling won't change the persistent representation of the object.
Definition at line 1268 of file TConvertingBranchElement.cxx.
|
private |
Definition at line 197 of file TConvertingBranchElement.h.
|
private |
Conversion for this branch.
Definition at line 198 of file TConvertingBranchElement.h.
|
private |
Saved branch type. The original.
Definition at line 210 of file TConvertingBranchElement.h.
|
private |
True if we're doing a container.
Definition at line 212 of file TConvertingBranchElement.h.
|
private |
Class for conversion.
Definition at line 199 of file TConvertingBranchElement.h.
|
private |
Pointer to tmp obj used for conversion.
Definition at line 200 of file TConvertingBranchElement.h.
|
private |
Saved branch list. If we change.
Definition at line 205 of file TConvertingBranchElement.h.
|
staticprivate |
Flag that the next read should.
Definition at line 215 of file TConvertingBranchElement.h.