TRef
class description - source file - inheritance tree
private:
public:
TRef TRef()
TRef TRef(TObject* obj)
TRef TRef(const TRef& ref)
virtual void ~TRef()
static Int_t AddExec(const char* name)
static TClass* Class()
static TObjArray* GetListOfExecs()
TObject* GetObject() const
virtual TClass* IsA() const
void operator=(TObject* obj)
TRef& operator=(const TRef& ref)
virtual void SetAction(const char* name)
virtual void SetAction(TObject* parent)
static void SetObject(TObject* obj)
virtual void ShowMembers(TMemberInspector& insp, char* parent)
virtual void Streamer(TBuffer& b)
void StreamerNVirtual(TBuffer& b)
private:
protected:
TProcessID* fPID !Pointer to ProcessID when TRef was written
static TObjArray* fgExecs List of execs
static TObject* fgObject Pointer to object (set in Action on Demand)
public:
static const enum TObject:: kNotComputed
TRef
Persistent Reference link to a TObject
A TRef is a lightweight object pointing to any TObject.
This object can be used instead of normal C++ pointers in case
- the referenced object R and the pointer P are not written to the same file
- P is read before R
- R and P are written to different Tree branches
When a top level object (eg Event *event) is a tree/graph of many objects,
the normal ROOT Streaming mechanism ensures that only one copy of each object
in the tree/graph is written to the output buffer to avoid circular
dependencies.
However if the object event is split into several files or into several
branches of one or more Trees, normal C++ pointers cannot be used because
each I/O operation will write the referenced objects.
When a TRef is used to point to a TObject *robj.
For example in a class with
TRef fRef;
one can do:
fRef = robj; //to set the pointer
this TRef and robj can be written with two different I/O calls
in the same or different files, in the same or different branches of a Tree.
If the TRef is read and the referenced object has not yet been read,
the TRef will return a null pointer. As soon as the referenced object
will be read, the TRef will point to it.
TRef also supports the complex situation where a TFile is updated
multiple times on the same machine or a different machine.
How does it work
----------------
A TRef is itself a TObject with an additional transient pointer fPID.
When the statement fRef = robj is executed, the following actions happen:
- The pointer fPID is set to the current TProcessID.
- The current ObjectNumber (see below) is incremented by one.
- robj::fUniqueID is set to ObjectNumber.
- In the fPID object, the element fObjects[ObjectNumber] is set to robj
- ref::fUniqueID is also set to ObjectNumber.
After having set fRef, one can immediatly return the value of robj
using fRef.GetObject(). This function returns directly fObjects[fUniqueID]
from the fPID object.
When the TRef is written, the process id number pidf of fPID is written
in addition to the TObject part of TRef (fBits,fUniqueID).
When the TRef is read, its pointer fPID is set to the value
stored in the TObjArray of TFile::fProcessIDs (fProcessIDs[pidf]).
When a referenced object robj is written, TObject::Streamer writes
in addition to the standard (fBits,fUniqueID) the pidf.
When this robj is read by TObject::Streamer, the pidf is read.
At this point, robj is entered into the table of objects of the TProcessID
corresponding to pidf.
WARNING: If MyClass is the class of the referenced object, The TObject
part of MyClass must be Streamed. One should not
call MyClass::Class()->IgnoreTObjectStreamer()
ObjectNumber
------------
When an object is referenced (see TRef assignement operator or TRefArray::Add)
a unique identifier is computed and stored in both the fUniqueID of the
referenced and referencing object. This uniqueID is computed by incrementing
by one the static global in TProcessID::fgNumber. fUniqueID is some sort of
serial object number in the current session. One can retrieve at any time
the current value of fgNumber by calling the static function TProcessID::GetObjectCount
or set this number via TProcessID::SetObjectCount.
To avoid a growing table of fObjects in TProcessID, in case, for example,
one processes many events in a loop, it might be necessary to reset the
ObjectNumber at the end of processing of one event. See an example
in $ROOTSYS/test/Event.cxx (look at function Build).
The value of ObjectNumber (say saveNumber=TProcessID::GetObjectCount()) may be
saved at the beginning of one event and reset to this original value
at the end of the event via TProcessID::SetObjectCount(saveNumber). These
actions may be stacked.
Action on Demand
----------------
The normal behaviour of a TRef has been described above. In addition,
TRef supports also "Actions on Demand". It may happen that the object
referenced is not yet in memory, on a separate file or not yet computed.
In this case TRef is able to automatically execute an action:
- call to a compiled function (static function of member function)
- call to an interpreted function
- execution of a CINT script
How to select this option?
In the definition of the TRef data member in the original class, do:
TRef fRef; //EXEC:execName. points to something
When the special keyword "EXEC:" is found in the comment field of the member,
the next string is assumed to be the name of a TExec object.
When a file is connected, the dictionary of the classes on the file
is read in memory (see TFile::ReadStreamerInfo). When the TStreamerElement
object is read, a TExec object is automatically created with the name
specified after the keywork "EXEC:" in case a TExec with a same name does
not already exist.
The action to be executed via this TExec can be specified with:
- a call to the TExec constructor, if the constructor is called before
opening the file.
- a call to TExec::SetAction at any time.
One can compute a pointer to an existing TExec with a name with:
TExec *myExec = gROOT->GetExec(execName);
myExec->SetAction(actionCommand); where
- actionCommand is a string containing a CINT instruction. Examples:
myExec->SetAction("LoadHits()");
myExec->SetAction(".x script.C");
When a TRef is dereferenced via TRef::GetObject, its TExec will be
automatically executed. In the function/script being executed, one or more
of the following actions can be executed:
- load a file containing the referenced object. This function typically
looks in the file catalog (GRID).
- compute a pointer to the referenced object and communicate this pointer
back to the calling function TRef::GetObject via:
TRef::SetObject(object).
As soon as an object is returned to GetObject, the fUniqueID of the TRef is set
to the fUniqueID of the referenced object. At the next call to GetObject,
the pointer stored in fPid:fObjects[fUniqueID] will be returned directly.
An example of action on demand is shown in $ROOTSYS/test/Event.h with
the member:
TRef fWebHistogram; //EXEC:GetWebHistogram
When calling fWebHistogram.GetObject(), the function GetObject
will automatically invoke a script GetWebHistogram.C via the interpreter.
An example of a GetWebHistogram.C script is shown below
void GetWebHistogram() {
TFile *f= TFile::Open("http://root.cern.ch/files/pippa.root");
f->cd("DM/CJ");
TH1 *h6 = (TH1*)gDirectory->Get("h6");
h6->SetDirectory(0);
delete f;
TRef::SetObject(h6);
}
In the above example, a call to fWebHistogram.GetObject() executes the
script with the function GetWebHistogram. This script connects a file
with histograms: pippa.root on the ROOT Web site and returns the object h6
to TRef::GetObject.
Note that if the definition of the TRef fWebHistogram had been:
TRef fWebHistogram; //EXEC:GetWebHistogram()
then, the compiled or interpreted function GetWebHistogram() would have
been called instead of the CINT script GetWebHistogram.C
Array of TRef
-------------
The special class TRefArray should be used to store multiple references.
A TRefArray has one single pointer fPID for all objects in the array.
It has a dynamic compact table of fUniqueIDs. Use a TRefArray rather
then a collection of TRefs.
Example:
Suppose a TObjArray *mytracks containing a list of Track objects
Suppose a TRefArray *pions containing pointers to the pion tracks in mytracks.
This list is created with statements like: pions->Add(track);
Suppose a TRefArray *muons containing pointers to the muon tracks in mytracks.
The 3 arrays mytracks,pions and muons may be written separately.
TRef(TObject *obj)
TRef copy ctor.
TRef(const TRef &ref)
Int_t AddExec(const char *name)
if Exec with name does not exist in the list of Execs, it is created.
returns the index of the Exec in the list
TObjArray* GetListOfExecs()
Return a pointer to the static TObjArray holding the list of Execs
TObject* GetObject() const
Return a pointer to the referenced object.
void SetAction(const char *name)
Store the exec number (in the ROOT list of Execs)
into the fBits of this TRef
void SetAction(TObject *parent)
Find the action to be executed in the dictionary of the parent class
and store the corresponding exec number into fBits
This function searches a data member in the class of parent with an offset
corresponding to this.
If a comment "TEXEC:" is found in the comment field of the data member,
the function stores the exec identifier of the exec statement
following this keyword.
void SetObject(TObject *obj)
static function to set the object found on the Action on Demand function.
This function may be called by the user in the function called
when a "EXEC:" keyword is specified in the data member field of the TRef.
void Streamer(TBuffer &R__b)
Stream an object of class TRef.
Inline Functions
TRef TRef(const TRef& ref)
void operator=(TObject* obj)
TRef& operator=(const TRef& ref)
TClass* Class()
TClass* IsA() const
void ShowMembers(TMemberInspector& insp, char* parent)
void StreamerNVirtual(TBuffer& b)
void ~TRef()
Author: Rene Brun 28/09/2001
Last update: root/cont:$Name: $:$Id: TRef.cxx,v 1.10 2002/01/08 11:50:24 brun Exp $
Copyright (C) 1995-2000, Rene Brun and Fons Rademakers. *
ROOT page - Class index - Top of the page
This page has been automatically generated. If you have any comments or suggestions about the page layout send a mail to ROOT support, or contact the developers with any questions or problems regarding ROOT.