00001 // @(#)root/cont:$Id: TProcessID.cxx 35949 2010-09-30 16:11:21Z brun $ 00002 // Author: Rene Brun 28/09/2001 00003 00004 /************************************************************************* 00005 * Copyright (C) 1995-2000, Rene Brun and Fons Rademakers. * 00006 * All rights reserved. * 00007 * * 00008 * For the licensing terms see $ROOTSYS/LICENSE. * 00009 * For the list of contributors see $ROOTSYS/README/CREDITS. * 00010 *************************************************************************/ 00011 00012 ////////////////////////////////////////////////////////////////////////// 00013 // 00014 // TProcessID 00015 // 00016 // A TProcessID identifies a ROOT job in a unique way in time and space. 00017 // The TProcessID title consists of a TUUID object which provides a globally 00018 // unique identifier (for more see TUUID.h). 00019 // 00020 // A TProcessID is automatically created by the TROOT constructor. 00021 // When a TFile contains referenced objects (see TRef), the TProcessID 00022 // object is written to the file. 00023 // If a file has been written in multiple sessions (same machine or not), 00024 // a TProcessID is written for each session. 00025 // These objects are used by the class TRef to uniquely identified 00026 // any TObject pointed by a TRef. 00027 // 00028 // When a referenced object is read from a file (its bit kIsReferenced is set), 00029 // this object is entered into the objects table of the corresponding TProcessID. 00030 // Each TFile has a list of TProcessIDs (see TFile::fProcessIDs) also 00031 // accessible via TProcessID::fgPIDs (for all files). 00032 // When this object is deleted, it is removed from the table via the cleanup 00033 // mechanism invoked by the TObject destructor. 00034 // 00035 // Each TProcessID has a table (TObjArray *fObjects) that keeps track 00036 // of all referenced objects. If a referenced object has a fUniqueID set, 00037 // a pointer to this unique object may be found via fObjects->At(fUniqueID). 00038 // In the same way, when a TRef::GetObject is called, GetObject uses 00039 // its own fUniqueID to find the pointer to the referenced object. 00040 // See TProcessID::GetObjectWithID and PutObjectWithID. 00041 // 00042 // When a referenced object is deleted, its slot in fObjects is set to null. 00043 // 00044 // See also TProcessUUID: a specialized TProcessID to manage the single list 00045 // of TUUIDs. 00046 // 00047 ////////////////////////////////////////////////////////////////////////// 00048 00049 #include "TProcessID.h" 00050 #include "TROOT.h" 00051 #include "TObjArray.h" 00052 #include "TExMap.h" 00053 #include "TVirtualMutex.h" 00054 00055 TObjArray *TProcessID::fgPIDs = 0; //pointer to the list of TProcessID 00056 TProcessID *TProcessID::fgPID = 0; //pointer to the TProcessID of the current session 00057 UInt_t TProcessID::fgNumber = 0; //Current referenced object instance count 00058 TExMap *TProcessID::fgObjPIDs= 0; //Table (pointer,pids) 00059 ClassImp(TProcessID) 00060 00061 //______________________________________________________________________________ 00062 static inline ULong_t Void_Hash(const void *ptr) 00063 { 00064 // Return hash value for this object. 00065 00066 return TString::Hash(&ptr, sizeof(void*)); 00067 } 00068 00069 //______________________________________________________________________________ 00070 TProcessID::TProcessID() 00071 { 00072 // Default constructor. 00073 00074 fCount = 0; 00075 fObjects = 0; 00076 } 00077 00078 //______________________________________________________________________________ 00079 TProcessID::~TProcessID() 00080 { 00081 // Destructor. 00082 00083 delete fObjects; 00084 fObjects = 0; 00085 R__LOCKGUARD2(gROOTMutex); 00086 fgPIDs->Remove(this); 00087 } 00088 00089 //______________________________________________________________________________ 00090 TProcessID *TProcessID::AddProcessID() 00091 { 00092 // Static function to add a new TProcessID to the list of PIDs. 00093 00094 R__LOCKGUARD2(gROOTMutex); 00095 00096 TProcessID *pid = new TProcessID(); 00097 00098 if (!fgPIDs) { 00099 fgPID = pid; 00100 fgPIDs = new TObjArray(10); 00101 gROOT->GetListOfCleanups()->Add(fgPIDs); 00102 } 00103 UShort_t apid = fgPIDs->GetEntriesFast(); 00104 pid->IncrementCount(); 00105 00106 fgPIDs->Add(pid); 00107 char name[20]; 00108 snprintf(name,20,"ProcessID%d",apid); 00109 pid->SetName(name); 00110 TUUID u; 00111 apid = fgPIDs->GetEntriesFast(); 00112 pid->SetTitle(u.AsString()); 00113 return pid; 00114 } 00115 00116 //______________________________________________________________________________ 00117 UInt_t TProcessID::AssignID(TObject *obj) 00118 { 00119 // static function returning the ID assigned to obj 00120 // If the object is not yet referenced, its kIsReferenced bit is set 00121 // and its fUniqueID set to the current number of referenced objects so far. 00122 00123 R__LOCKGUARD2(gROOTMutex); 00124 00125 UInt_t uid = obj->GetUniqueID() & 0xffffff; 00126 if (obj == fgPID->GetObjectWithID(uid)) return uid; 00127 if (obj->TestBit(kIsReferenced)) { 00128 fgPID->PutObjectWithID(obj,uid); 00129 return uid; 00130 } 00131 fgNumber++; 00132 obj->SetBit(kIsReferenced); 00133 uid = fgNumber; 00134 obj->SetUniqueID(uid); 00135 fgPID->PutObjectWithID(obj,uid); 00136 return uid; 00137 } 00138 00139 //______________________________________________________________________________ 00140 void TProcessID::CheckInit() 00141 { 00142 // Initialize fObjects. 00143 if (!fObjects) fObjects = new TObjArray(100); 00144 } 00145 00146 //______________________________________________________________________________ 00147 void TProcessID::Cleanup() 00148 { 00149 // static function (called by TROOT destructor) to delete all TProcessIDs 00150 00151 R__LOCKGUARD2(gROOTMutex); 00152 00153 fgPIDs->Delete(); 00154 gROOT->GetListOfCleanups()->Remove(fgPIDs); 00155 delete fgPIDs; 00156 } 00157 00158 //______________________________________________________________________________ 00159 void TProcessID::Clear(Option_t *) 00160 { 00161 // delete the TObjArray pointing to referenced objects 00162 // this function is called by TFile::Close("R") 00163 00164 delete fObjects; fObjects = 0; 00165 } 00166 00167 //______________________________________________________________________________ 00168 Int_t TProcessID::DecrementCount() 00169 { 00170 00171 // the reference fCount is used to delete the TProcessID 00172 // in the TFile destructor when fCount = 0 00173 00174 fCount--; 00175 if (fCount < 0) fCount = 0; 00176 return fCount; 00177 } 00178 00179 //______________________________________________________________________________ 00180 TProcessID *TProcessID::GetProcessID(UShort_t pid) 00181 { 00182 // static function returning a pointer to TProcessID number pid in fgPIDs 00183 00184 return (TProcessID*)fgPIDs->At(pid); 00185 } 00186 00187 //______________________________________________________________________________ 00188 UInt_t TProcessID::GetNProcessIDs() 00189 { 00190 // Return the (static) number of process IDs. 00191 return fgPIDs ? fgPIDs->GetLast()+1 : 0; 00192 } 00193 00194 //______________________________________________________________________________ 00195 TProcessID *TProcessID::GetProcessWithUID(UInt_t uid, const void *obj) 00196 { 00197 // static function returning a pointer to TProcessID with its pid 00198 // encoded in the highest byte of uid 00199 00200 R__LOCKGUARD2(gROOTMutex); 00201 00202 Int_t pid = (uid>>24)&0xff; 00203 if (pid==0xff) { 00204 // Look up the pid in the table (pointer,pid) 00205 if (fgObjPIDs==0) return 0; 00206 ULong_t hash = Void_Hash(obj); 00207 pid = fgObjPIDs->GetValue(hash,(Long_t)obj); 00208 } 00209 return (TProcessID*)fgPIDs->At(pid); 00210 } 00211 00212 //______________________________________________________________________________ 00213 TProcessID *TProcessID::GetProcessWithUID(const TObject *obj) 00214 { 00215 // static function returning a pointer to TProcessID with its pid 00216 // encoded in the highest byte of obj->GetUniqueID() 00217 00218 return GetProcessWithUID(obj->GetUniqueID(),obj); 00219 } 00220 00221 //______________________________________________________________________________ 00222 TProcessID *TProcessID::GetSessionProcessID() 00223 { 00224 // static function returning the pointer to the session TProcessID 00225 00226 return fgPID; 00227 } 00228 00229 //______________________________________________________________________________ 00230 Int_t TProcessID::IncrementCount() 00231 { 00232 // Increase the reference count to this object. 00233 00234 if (!fObjects) fObjects = new TObjArray(100); 00235 fCount++; 00236 return fCount; 00237 } 00238 00239 //______________________________________________________________________________ 00240 UInt_t TProcessID::GetObjectCount() 00241 { 00242 // Return the current referenced object count 00243 // fgNumber is incremented everytime a new object is referenced 00244 00245 return fgNumber; 00246 } 00247 00248 //______________________________________________________________________________ 00249 TObject *TProcessID::GetObjectWithID(UInt_t uidd) 00250 { 00251 //returns the TObject with unique identifier uid in the table of objects 00252 00253 Int_t uid = uidd & 0xffffff; //take only the 24 lower bits 00254 00255 if (fObjects==0 || uid >= fObjects->GetSize()) return 0; 00256 return fObjects->UncheckedAt(uid); 00257 } 00258 00259 //______________________________________________________________________________ 00260 TProcessID *TProcessID::GetPID() 00261 { 00262 //static: returns pointer to current TProcessID 00263 00264 return fgPID; 00265 } 00266 00267 //______________________________________________________________________________ 00268 TObjArray *TProcessID::GetPIDs() 00269 { 00270 //static: returns array of TProcessIDs 00271 00272 return fgPIDs; 00273 } 00274 00275 00276 //______________________________________________________________________________ 00277 Bool_t TProcessID::IsValid(TProcessID *pid) 00278 { 00279 // static function. return kTRUE if pid is a valid TProcessID 00280 00281 R__LOCKGUARD2(gROOTMutex); 00282 00283 if (fgPIDs->IndexOf(pid) >= 0) return kTRUE; 00284 if (pid == (TProcessID*)gROOT->GetUUIDs()) return kTRUE; 00285 return kFALSE; 00286 } 00287 00288 //______________________________________________________________________________ 00289 void TProcessID::PutObjectWithID(TObject *obj, UInt_t uid) 00290 { 00291 //stores the object at the uid th slot in the table of objects 00292 //The object uniqueid is set as well as its kMustCleanup bit 00293 00294 if (uid == 0) uid = obj->GetUniqueID() & 0xffffff; 00295 00296 if (!fObjects) fObjects = new TObjArray(100); 00297 fObjects->AddAtAndExpand(obj,uid); 00298 00299 obj->SetBit(kMustCleanup); 00300 if ( (obj->GetUniqueID()&0xff000000)==0xff000000 ) { 00301 // We have more than 255 pids we need to store this 00302 // pointer in the table(pointer,pid) since there is no 00303 // more space in fUniqueID 00304 if (fgObjPIDs==0) fgObjPIDs = new TExMap; 00305 ULong_t hash = Void_Hash(obj); 00306 00307 // We use operator() rather than Add() because 00308 // if the address has already been registered, we want to 00309 // update it's uniqueID (this can easily happen when the 00310 // referenced object have been stored in a TClonesArray. 00311 (*fgObjPIDs)(hash, (Long_t)obj) = GetUniqueID(); 00312 } 00313 } 00314 00315 //______________________________________________________________________________ 00316 void TProcessID::RecursiveRemove(TObject *obj) 00317 { 00318 // called by the object destructor 00319 // remove reference to obj from the current table if it is referenced 00320 00321 if (!fObjects) return; 00322 if (!obj->TestBit(kIsReferenced)) return; 00323 UInt_t uid = obj->GetUniqueID() & 0xffffff; 00324 if (obj == GetObjectWithID(uid)) fObjects->RemoveAt(uid); 00325 } 00326 00327 00328 //______________________________________________________________________________ 00329 void TProcessID::SetObjectCount(UInt_t number) 00330 { 00331 // static function to set the current referenced object count 00332 // fgNumber is incremented everytime a new object is referenced 00333 00334 fgNumber = number; 00335 }