Logo ROOT   6.10/09
Reference Guide
TProcessID.cxx
Go to the documentation of this file.
1 // @(#)root/cont:$Id$
2 // Author: Rene Brun 28/09/2001
3 
4 /*************************************************************************
5  * Copyright (C) 1995-2000, Rene Brun and Fons Rademakers. *
6  * All rights reserved. *
7  * *
8  * For the licensing terms see $ROOTSYS/LICENSE. *
9  * For the list of contributors see $ROOTSYS/README/CREDITS. *
10  *************************************************************************/
11 
12 /** \class TProcessID
13 \ingroup Base
14 
15 A TProcessID identifies a ROOT job in a unique way in time and space.
16 The TProcessID title consists of a TUUID object which provides a globally
17 unique identifier (for more see TUUID.h).
18 
19 A TProcessID is automatically created by the TROOT constructor.
20 When a TFile contains referenced objects (see TRef), the TProcessID
21 object is written to the file.
22 If a file has been written in multiple sessions (same machine or not),
23 a TProcessID is written for each session.
24 These objects are used by the class TRef to uniquely identified
25 any TObject pointed by a TRef.
26 
27 When a referenced object is read from a file (its bit kIsReferenced is set),
28 this object is entered into the objects table of the corresponding TProcessID.
29 Each TFile has a list of TProcessIDs (see TFile::fProcessIDs) also
30 accessible via TProcessID::fgPIDs (for all files).
31 When this object is deleted, it is removed from the table via the cleanup
32 mechanism invoked by the TObject destructor.
33 
34 Each TProcessID has a table (TObjArray *fObjects) that keeps track
35 of all referenced objects. If a referenced object has a fUniqueID set,
36 a pointer to this unique object may be found via fObjects->At(fUniqueID).
37 In the same way, when a TRef::GetObject is called, GetObject uses
38 its own fUniqueID to find the pointer to the referenced object.
39 See TProcessID::GetObjectWithID and PutObjectWithID.
40 
41 When a referenced object is deleted, its slot in fObjects is set to null.
42 //
43 See also TProcessUUID: a specialized TProcessID to manage the single list
44 of TUUIDs.
45 */
46 
47 #include "TProcessID.h"
48 #include "TROOT.h"
49 #include "TObjArray.h"
50 #include "TExMap.h"
51 #include "TVirtualMutex.h"
52 #include "TError.h"
53 
54 TObjArray *TProcessID::fgPIDs = 0; //pointer to the list of TProcessID
55 TProcessID *TProcessID::fgPID = 0; //pointer to the TProcessID of the current session
56 UInt_t TProcessID::fgNumber = 0; //Current referenced object instance count
57 TExMap *TProcessID::fgObjPIDs= 0; //Table (pointer,pids)
59 
60 ////////////////////////////////////////////////////////////////////////////////
61 /// Return hash value for this object.
62 
63 static inline ULong_t Void_Hash(const void *ptr)
64 {
65  return TString::Hash(&ptr, sizeof(void*));
66 }
67 
68 ////////////////////////////////////////////////////////////////////////////////
69 /// Default constructor.
70 
72 {
73  // MSVC doesn't support fSpinLock=ATOMIC_FLAG_INIT; in the class definition
74  // and Apple LLVM version 7.3.0 (clang-703.0.31) warns about:
75  // fLock(ATOMIC_FLAG_INIT)
76  // ^~~~~~~~~~~~~~~~
77  // c++/v1/atomic:1779:26: note: expanded from macro 'ATOMIC_FLAG_INIT'
78  // #define ATOMIC_FLAG_INIT {false}
79  // So reset the flag instead.
80  std::atomic_flag_clear( &fLock );
81 
82  fCount = 0;
83  fObjects = 0;
84 }
85 
86 ////////////////////////////////////////////////////////////////////////////////
87 /// Destructor.
88 
90 {
91  delete fObjects;
92  fObjects = 0;
94  fgPIDs->Remove(this);
95 }
96 
97 ////////////////////////////////////////////////////////////////////////////////
98 /// Static function to add a new TProcessID to the list of PIDs.
99 
101 {
103 
104  if (fgPIDs && fgPIDs->GetEntriesFast() >= 65534) {
105  if (fgPIDs->GetEntriesFast() == 65534) {
106  ::Warning("TProcessID::AddProcessID","Maximum number of TProcessID (65535) is almost reached (one left). TRef will stop being functional when the limit is reached.");
107  } else {
108  ::Fatal("TProcessID::AddProcessID","Maximum number of TProcessID (65535) has been reached. TRef are not longer functional.");
109  }
110  }
111 
112  TProcessID *pid = new TProcessID();
113 
114  if (!fgPIDs) {
115  fgPID = pid;
116  fgPIDs = new TObjArray(10);
117  gROOT->GetListOfCleanups()->Add(fgPIDs);
118  }
119  UShort_t apid = fgPIDs->GetEntriesFast();
120  pid->IncrementCount();
121 
122  fgPIDs->Add(pid);
123  // if (apid == 0) for(int incr=0; incr < 65533; ++incr) fgPIDs->Add(0); // NOTE: DEBUGGING ONLY MUST BE REMOVED!
124  char name[20];
125  snprintf(name,20,"ProcessID%d",apid);
126  pid->SetName(name);
127  pid->SetUniqueID((UInt_t)apid);
128  TUUID u;
129  //apid = fgPIDs->GetEntriesFast();
130  pid->SetTitle(u.AsString());
131  return pid;
132 }
133 
134 ////////////////////////////////////////////////////////////////////////////////
135 /// static function returning the ID assigned to obj
136 /// If the object is not yet referenced, its kIsReferenced bit is set
137 /// and its fUniqueID set to the current number of referenced objects so far.
138 
140 {
142 
143  UInt_t uid = obj->GetUniqueID() & 0xffffff;
144  if (obj == fgPID->GetObjectWithID(uid)) return uid;
145  if (obj->TestBit(kIsReferenced)) {
146  fgPID->PutObjectWithID(obj,uid);
147  return uid;
148  }
149  if (fgNumber >= 16777215) {
150  // This process id is 'full', we need to use a new one.
151  fgPID = AddProcessID();
152  fgNumber = 0;
153  for(Int_t i = 0; i < fgPIDs->GetLast()+1; ++i) {
154  TProcessID *pid = (TProcessID*)fgPIDs->At(i);
155  if (pid && pid->fObjects && pid->fObjects->GetEntries() == 0) {
156  pid->Clear();
157  }
158  }
159  }
160  fgNumber++;
161  obj->SetBit(kIsReferenced);
162  uid = fgNumber;
163  // if (fgNumber<10) fgNumber = 16777213; // NOTE: DEBUGGING ONLY MUST BE REMOVED!
164  if ( fgPID->GetUniqueID() < 255 ) {
165  obj->SetUniqueID( (uid & 0xffffff) + (fgPID->GetUniqueID()<<24) );
166  } else {
167  obj->SetUniqueID( (uid & 0xffffff) + 0xff000000 /* 255 << 24 */ );
168  }
169  fgPID->PutObjectWithID(obj,uid);
170  return uid;
171 }
172 
173 ////////////////////////////////////////////////////////////////////////////////
174 /// Initialize fObjects.
175 
177 {
178  if (!fObjects) {
179  while (fLock.test_and_set(std::memory_order_acquire)); // acquire lock
180  if (!fObjects) fObjects = new TObjArray(100);
181  fLock.clear(std::memory_order_release);
182  }
183 }
184 
185 ////////////////////////////////////////////////////////////////////////////////
186 /// static function (called by TROOT destructor) to delete all TProcessIDs
187 
189 {
191 
192  fgPIDs->Delete();
193  gROOT->GetListOfCleanups()->Remove(fgPIDs);
194  delete fgPIDs;
195  fgPIDs = 0;
196 }
197 
198 ////////////////////////////////////////////////////////////////////////////////
199 /// delete the TObjArray pointing to referenced objects
200 /// this function is called by TFile::Close("R")
201 
203 {
204  if (GetUniqueID()>254 && fObjects && fgObjPIDs) {
205  // We might have many references registered in the map
206  for(Int_t i = 0; i < fObjects->GetSize(); ++i) {
207  TObject *obj = fObjects->UncheckedAt(i);
208  if (obj) {
209  ULong64_t hash = Void_Hash(obj);
210  fgObjPIDs->Remove(hash,(Long64_t)obj);
211  (*fObjects)[i] = 0;
212  }
213  }
214  }
215  delete fObjects; fObjects = 0;
216 }
217 
218 ////////////////////////////////////////////////////////////////////////////////
219 /// The reference fCount is used to delete the TProcessID
220 /// in the TFile destructor when fCount = 0
221 
223 {
224  fCount--;
225  if (fCount < 0) fCount = 0;
226  return fCount;
227 }
228 
229 ////////////////////////////////////////////////////////////////////////////////
230 /// static function returning a pointer to TProcessID number pid in fgPIDs
231 
233 {
234  return (TProcessID*)fgPIDs->At(pid);
235 }
236 
237 ////////////////////////////////////////////////////////////////////////////////
238 /// Return the (static) number of process IDs.
239 
241 {
242  return fgPIDs ? fgPIDs->GetLast()+1 : 0;
243 }
244 
245 ////////////////////////////////////////////////////////////////////////////////
246 /// static function returning a pointer to TProcessID with its pid
247 /// encoded in the highest byte of uid
248 
250 {
252 
253  Int_t pid = (uid>>24)&0xff;
254  if (pid==0xff) {
255  // Look up the pid in the table (pointer,pid)
256  if (fgObjPIDs==0) return 0;
257  ULong_t hash = Void_Hash(obj);
258  pid = fgObjPIDs->GetValue(hash,(Long_t)obj);
259  }
260  return (TProcessID*)fgPIDs->At(pid);
261 }
262 
263 ////////////////////////////////////////////////////////////////////////////////
264 /// static function returning a pointer to TProcessID with its pid
265 /// encoded in the highest byte of obj->GetUniqueID()
266 
268 {
269  return GetProcessWithUID(obj->GetUniqueID(),obj);
270 }
271 
272 ////////////////////////////////////////////////////////////////////////////////
273 /// static function returning the pointer to the session TProcessID
274 
276 {
277  return fgPID;
278 }
279 
280 ////////////////////////////////////////////////////////////////////////////////
281 /// Increase the reference count to this object.
282 
284 {
285  CheckInit();
286  ++fCount;
287  return fCount;
288 }
289 
290 ////////////////////////////////////////////////////////////////////////////////
291 /// Return the current referenced object count
292 /// fgNumber is incremented every time a new object is referenced
293 
295 {
296  return fgNumber;
297 }
298 
299 ////////////////////////////////////////////////////////////////////////////////
300 /// returns the TObject with unique identifier uid in the table of objects
301 
303 {
304  Int_t uid = uidd & 0xffffff; //take only the 24 lower bits
305 
306  if (fObjects==0 || uid >= fObjects->GetSize()) return 0;
307  return fObjects->UncheckedAt(uid);
308 }
309 
310 ////////////////////////////////////////////////////////////////////////////////
311 /// static: returns pointer to current TProcessID
312 
314 {
315  return fgPID;
316 }
317 
318 ////////////////////////////////////////////////////////////////////////////////
319 /// static: returns array of TProcessIDs
320 
322 {
323  return fgPIDs;
324 }
325 
326 
327 ////////////////////////////////////////////////////////////////////////////////
328 /// static function. return kTRUE if pid is a valid TProcessID
329 
331 {
333 
334  if (fgPIDs==0) return kFALSE;
335  if (fgPIDs->IndexOf(pid) >= 0) return kTRUE;
336  if (pid == (TProcessID*)gROOT->GetUUIDs()) return kTRUE;
337  return kFALSE;
338 }
339 
340 ////////////////////////////////////////////////////////////////////////////////
341 /// stores the object at the uid th slot in the table of objects
342 /// The object uniqued is set as well as its kMustCleanup bit
343 
345 {
346  R__LOCKGUARD_IMT2(gROOTMutex); // Lock for parallel TTree I/O
347 
348  if (uid == 0) uid = obj->GetUniqueID() & 0xffffff;
349 
350  if (!fObjects) fObjects = new TObjArray(100);
351  fObjects->AddAtAndExpand(obj,uid);
352 
353  obj->SetBit(kMustCleanup);
354  if ( (obj->GetUniqueID()&0xff000000)==0xff000000 ) {
355  // We have more than 255 pids we need to store this
356  // pointer in the table(pointer,pid) since there is no
357  // more space in fUniqueID
358  if (fgObjPIDs==0) fgObjPIDs = new TExMap;
359  ULong_t hash = Void_Hash(obj);
360 
361  // We use operator() rather than Add() because
362  // if the address has already been registered, we want to
363  // update it's uniqueID (this can easily happen when the
364  // referenced object have been stored in a TClonesArray.
365  (*fgObjPIDs)(hash, (Long_t)obj) = GetUniqueID();
366  }
367 }
368 
369 ////////////////////////////////////////////////////////////////////////////////
370 /// called by the object destructor
371 /// remove reference to obj from the current table if it is referenced
372 
374 {
375  if (!fObjects) return;
376  if (!obj->TestBit(kIsReferenced)) return;
377  UInt_t uid = obj->GetUniqueID() & 0xffffff;
378  if (obj == GetObjectWithID(uid)) {
379  if (fgObjPIDs) {
380  ULong64_t hash = Void_Hash(obj);
381  fgObjPIDs->Remove(hash,(Long64_t)obj);
382  }
383  (*fObjects)[uid] = 0; // Avoid recalculation of fLast (compared to ->RemoveAt(uid))
384  }
385 }
386 
387 
388 ////////////////////////////////////////////////////////////////////////////////
389 /// static function to set the current referenced object count
390 /// fgNumber is incremented every time a new object is referenced
391 
393 {
394  fgNumber = number;
395 }
static TProcessID * GetPID()
static: returns pointer to current TProcessID
Definition: TProcessID.cxx:313
static TProcessID * GetProcessID(UShort_t pid)
static function returning a pointer to TProcessID number pid in fgPIDs
Definition: TProcessID.cxx:232
virtual UInt_t GetUniqueID() const
Return the unique object id.
Definition: TObject.cxx:382
ROOT::Internal::TAtomicPointer< TObjArray * > fObjects
Reference count to this object (from TFile)
Definition: TProcessID.h:77
virtual void RecursiveRemove(TObject *obj)
called by the object destructor remove reference to obj from the current table if it is referenced ...
Definition: TProcessID.cxx:373
void PutObjectWithID(TObject *obj, UInt_t uid=0)
stores the object at the uid th slot in the table of objects The object uniqued is set as well as its...
Definition: TProcessID.cxx:344
void Remove(ULong64_t hash, Long64_t key)
Remove entry with specified key from the TExMap.
Definition: TExMap.cxx:216
An array of TObjects.
Definition: TObjArray.h:37
long long Long64_t
Definition: RtypesCore.h:69
const char Option_t
Definition: RtypesCore.h:62
virtual void Delete(Option_t *option="")
Remove all objects from the array AND delete all heap based objects.
Definition: TObjArray.cxx:329
static UInt_t GetNProcessIDs()
Return the (static) number of process IDs.
Definition: TProcessID.cxx:240
unsigned short UShort_t
Definition: RtypesCore.h:36
Bool_t TestBit(UInt_t f) const
Definition: TObject.h:159
virtual void SetName(const char *name)
Set the name of the TNamed.
Definition: TNamed.cxx:131
virtual ~TProcessID()
Destructor.
Definition: TProcessID.cxx:89
#define gROOT
Definition: TROOT.h:375
virtual TObject * Remove(TObject *obj)
Remove object from array.
Definition: TObjArray.cxx:653
int Int_t
Definition: RtypesCore.h:41
bool Bool_t
Definition: RtypesCore.h:59
R__EXTERN TVirtualMutex * gROOTMutex
Definition: TROOT.h:57
TObject * At(Int_t idx) const
Definition: TObjArray.h:165
UInt_t Hash(ECaseCompare cmp=kExact) const
Return hash value.
Definition: TString.cxx:616
void SetBit(UInt_t f, Bool_t set)
Set or unset the user status bits as specified in f.
Definition: TObject.cxx:687
This class defines a UUID (Universally Unique IDentifier), also known as GUIDs (Globally Unique IDent...
Definition: TUUID.h:42
static TObjArray * GetPIDs()
static: returns array of TProcessIDs
Definition: TProcessID.cxx:321
static TObjArray * fgPIDs
Definition: TProcessID.h:81
static TProcessID * fgPID
Spin lock for initialization of fObjects.
Definition: TProcessID.h:80
static void SetObjectCount(UInt_t number)
static function to set the current referenced object count fgNumber is incremented every time a new o...
Definition: TProcessID.cxx:392
static ULong_t Void_Hash(const void *ptr)
Return hash value for this object.
Definition: TProcessID.cxx:63
A TProcessID identifies a ROOT job in a unique way in time and space.
Definition: TProcessID.h:69
static void Cleanup()
static function (called by TROOT destructor) to delete all TProcessIDs
Definition: TProcessID.cxx:188
virtual void SetUniqueID(UInt_t uid)
Set the unique object id.
Definition: TObject.cxx:698
Int_t GetLast() const
Return index of last object in array.
Definition: TObjArray.cxx:528
Long64_t GetValue(ULong64_t hash, Long64_t key)
Return the value belonging to specified key and hash value.
Definition: TExMap.cxx:173
virtual void AddAtAndExpand(TObject *obj, Int_t idx)
Add object at position idx.
Definition: TObjArray.cxx:222
static TProcessID * GetProcessWithUID(const TObject *obj)
static function returning a pointer to TProcessID with its pid encoded in the highest byte of obj->Ge...
Definition: TProcessID.cxx:267
TProcessID()
Default constructor.
Definition: TProcessID.cxx:71
std::atomic_flag fLock
Array pointing to the referenced objects.
Definition: TProcessID.h:78
Int_t IncrementCount()
Increase the reference count to this object.
Definition: TProcessID.cxx:283
unsigned int UInt_t
Definition: RtypesCore.h:42
Int_t GetEntriesFast() const
Definition: TObjArray.h:64
Int_t DecrementCount()
The reference fCount is used to delete the TProcessID in the TFile destructor when fCount = 0...
Definition: TProcessID.cxx:222
static TProcessID * AddProcessID()
Static function to add a new TProcessID to the list of PIDs.
Definition: TProcessID.cxx:100
if object destructor must call RecursiveRemove()
Definition: TObject.h:59
#define R__LOCKGUARD2(mutex)
const Bool_t kFALSE
Definition: RtypesCore.h:92
TObject * GetObjectWithID(UInt_t uid)
returns the TObject with unique identifier uid in the table of objects
Definition: TProcessID.cxx:302
void CheckInit()
Initialize fObjects.
Definition: TProcessID.cxx:176
long Long_t
Definition: RtypesCore.h:50
static UInt_t fgNumber
Definition: TProcessID.h:83
TObject * UncheckedAt(Int_t i) const
Definition: TObjArray.h:89
#define ClassImp(name)
Definition: Rtypes.h:336
static TExMap * fgObjPIDs
Definition: TProcessID.h:82
virtual void Clear(Option_t *option="")
delete the TObjArray pointing to referenced objects this function is called by TFile::Close("R") ...
Definition: TProcessID.cxx:202
Int_t IndexOf(const TObject *obj) const
Definition: TObjArray.cxx:552
unsigned long long ULong64_t
Definition: RtypesCore.h:70
unsigned long ULong_t
Definition: RtypesCore.h:51
static TProcessID * GetSessionProcessID()
static function returning the pointer to the session TProcessID
Definition: TProcessID.cxx:275
const char * AsString() const
Return UUID as string. Copy string immediately since it will be reused.
Definition: TUUID.cxx:537
std::atomic_int fCount
Definition: TProcessID.h:76
Mother of all ROOT objects.
Definition: TObject.h:37
static UInt_t AssignID(TObject *obj)
static function returning the ID assigned to obj If the object is not yet referenced, its kIsReferenced bit is set and its fUniqueID set to the current number of referenced objects so far.
Definition: TProcessID.cxx:139
if object is referenced by a TRef or TRefArray
Definition: TObject.h:61
#define snprintf
Definition: civetweb.c:822
static UInt_t GetObjectCount()
Return the current referenced object count fgNumber is incremented every time a new object is referen...
Definition: TProcessID.cxx:294
Int_t GetEntries() const
Return the number of objects in array (i.e.
Definition: TObjArray.cxx:494
void Add(TObject *obj)
Definition: TObjArray.h:73
#define R__LOCKGUARD_IMT2(mutex)
static Bool_t IsValid(TProcessID *pid)
static function. return kTRUE if pid is a valid TProcessID
Definition: TProcessID.cxx:330
virtual void Fatal(const char *method, const char *msgfmt,...) const
Issue fatal error message.
Definition: TObject.cxx:901
virtual Int_t GetSize() const
Definition: TCollection.h:89
virtual void SetTitle(const char *title="")
Set the title of the TNamed.
Definition: TNamed.cxx:155
const Bool_t kTRUE
Definition: RtypesCore.h:91
This class stores a (key,value) pair using an external hash.
Definition: TExMap.h:33
virtual void Warning(const char *method, const char *msgfmt,...) const
Issue warning message.
Definition: TObject.cxx:859