Logo ROOT   6.14/05
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 std::atomic_uint TProcessID::fgNumber(0); //Current referenced object instance count
57 TExMap *TProcessID::fgObjPIDs= 0; //Table (pointer,pids)
59 
60 static std::atomic<TProcessID *> gIsValidCache;
61 using PIDCacheContent_t = std::pair<Int_t, TProcessID*>;
62 static std::atomic<PIDCacheContent_t *> gGetProcessWithUIDCache;
63 
64 ////////////////////////////////////////////////////////////////////////////////
65 /// Return hash value for this object.
66 
67 static inline ULong_t Void_Hash(const void *ptr)
68 {
69  return TString::Hash(&ptr, sizeof(void*));
70 }
71 
72 ////////////////////////////////////////////////////////////////////////////////
73 /// Default constructor.
74 
76 {
77  // MSVC doesn't support fSpinLock=ATOMIC_FLAG_INIT; in the class definition
78  // and Apple LLVM version 7.3.0 (clang-703.0.31) warns about:
79  // fLock(ATOMIC_FLAG_INIT)
80  // ^~~~~~~~~~~~~~~~
81  // c++/v1/atomic:1779:26: note: expanded from macro 'ATOMIC_FLAG_INIT'
82  // #define ATOMIC_FLAG_INIT {false}
83  // So reset the flag instead.
84  std::atomic_flag_clear( &fLock );
85 
86  fCount = 0;
87  fObjects = 0;
88 }
89 
90 ////////////////////////////////////////////////////////////////////////////////
91 /// Destructor.
92 
94 {
95  delete fObjects;
96  fObjects = 0;
97 
98  TProcessID *This = this; // We need a referencable value for the 1st argument
99  gIsValidCache.compare_exchange_strong(This, nullptr);
100 
101  auto current = gGetProcessWithUIDCache.load();
102  if (current && current->second == this) {
103  gGetProcessWithUIDCache.compare_exchange_strong(current, nullptr);
104  delete current;
105  }
106 
108  fgPIDs->Remove(this);
109 }
110 
111 ////////////////////////////////////////////////////////////////////////////////
112 /// Static function to add a new TProcessID to the list of PIDs.
113 
115 {
117 
118  if (fgPIDs && fgPIDs->GetEntriesFast() >= 65534) {
119  if (fgPIDs->GetEntriesFast() == 65534) {
120  ::Warning("TProcessID::AddProcessID","Maximum number of TProcessID (65535) is almost reached (one left). TRef will stop being functional when the limit is reached.");
121  } else {
122  ::Fatal("TProcessID::AddProcessID","Maximum number of TProcessID (65535) has been reached. TRef are not longer functional.");
123  }
124  }
125 
126  TProcessID *pid = new TProcessID();
127 
128  if (!fgPIDs) {
129  fgPID = pid;
130  fgPIDs = new TObjArray(10);
131  gROOT->GetListOfCleanups()->Add(fgPIDs);
132  }
133  UShort_t apid = fgPIDs->GetEntriesFast();
134  pid->IncrementCount();
135 
136  fgPIDs->Add(pid);
137  // if (apid == 0) for(int incr=0; incr < 65533; ++incr) fgPIDs->Add(0); // NOTE: DEBUGGING ONLY MUST BE REMOVED!
138  char name[20];
139  snprintf(name,20,"ProcessID%d",apid);
140  pid->SetName(name);
141  pid->SetUniqueID((UInt_t)apid);
142  TUUID u;
143  //apid = fgPIDs->GetEntriesFast();
144  pid->SetTitle(u.AsString());
145  return pid;
146 }
147 
148 ////////////////////////////////////////////////////////////////////////////////
149 /// static function returning the ID assigned to obj
150 /// If the object is not yet referenced, its kIsReferenced bit is set
151 /// and its fUniqueID set to the current number of referenced objects so far.
152 
154 {
156 
157  UInt_t uid = obj->GetUniqueID() & 0xffffff;
158  if (obj == fgPID->GetObjectWithID(uid)) return uid;
159  if (obj->TestBit(kIsReferenced)) {
160  fgPID->PutObjectWithID(obj,uid);
161  return uid;
162  }
163  if (fgNumber >= 16777215) {
164  // This process id is 'full', we need to use a new one.
165  fgPID = AddProcessID();
166  fgNumber = 0;
167  for(Int_t i = 0; i < fgPIDs->GetLast()+1; ++i) {
168  TProcessID *pid = (TProcessID*)fgPIDs->At(i);
169  if (pid && pid->fObjects && pid->fObjects->GetEntries() == 0) {
170  pid->Clear();
171  }
172  }
173  }
174  fgNumber++;
175  obj->SetBit(kIsReferenced);
176  uid = fgNumber;
177  // if (fgNumber<10) fgNumber = 16777213; // NOTE: DEBUGGING ONLY MUST BE REMOVED!
178  if ( fgPID->GetUniqueID() < 255 ) {
179  obj->SetUniqueID( (uid & 0xffffff) + (fgPID->GetUniqueID()<<24) );
180  } else {
181  obj->SetUniqueID( (uid & 0xffffff) + 0xff000000 /* 255 << 24 */ );
182  }
183  fgPID->PutObjectWithID(obj,uid);
184  return uid;
185 }
186 
187 ////////////////////////////////////////////////////////////////////////////////
188 /// Initialize fObjects.
189 
191 {
192  if (!fObjects) {
193  while (fLock.test_and_set(std::memory_order_acquire)); // acquire lock
194  if (!fObjects) fObjects = new TObjArray(100);
195  fLock.clear(std::memory_order_release);
196  }
197 }
198 
199 ////////////////////////////////////////////////////////////////////////////////
200 /// static function (called by TROOT destructor) to delete all TProcessIDs
201 
203 {
205 
206  fgPIDs->Delete();
207  gROOT->GetListOfCleanups()->Remove(fgPIDs);
208  delete fgPIDs;
209  fgPIDs = 0;
210 }
211 
212 ////////////////////////////////////////////////////////////////////////////////
213 /// delete the TObjArray pointing to referenced objects
214 /// this function is called by TFile::Close("R")
215 
217 {
218  if (GetUniqueID()>254 && fObjects && fgObjPIDs) {
219  // We might have many references registered in the map
220  for(Int_t i = 0; i < fObjects->GetSize(); ++i) {
221  TObject *obj = fObjects->UncheckedAt(i);
222  if (obj) {
223  ULong64_t hash = Void_Hash(obj);
224  fgObjPIDs->Remove(hash,(Long64_t)obj);
225  (*fObjects)[i] = 0;
226  }
227  }
228  }
229  delete fObjects; fObjects = 0;
230 }
231 
232 ////////////////////////////////////////////////////////////////////////////////
233 /// The reference fCount is used to delete the TProcessID
234 /// in the TFile destructor when fCount = 0
235 
237 {
238  fCount--;
239  if (fCount < 0) fCount = 0;
240  return fCount;
241 }
242 
243 ////////////////////////////////////////////////////////////////////////////////
244 /// static function returning a pointer to TProcessID number pid in fgPIDs
245 
247 {
248  return (TProcessID*)fgPIDs->At(pid);
249 }
250 
251 ////////////////////////////////////////////////////////////////////////////////
252 /// Return the (static) number of process IDs.
253 
255 {
256  return fgPIDs ? fgPIDs->GetLast()+1 : 0;
257 }
258 
259 ////////////////////////////////////////////////////////////////////////////////
260 /// static function returning a pointer to TProcessID with its pid
261 /// encoded in the highest byte of uid
262 
264 {
265 
266  Int_t pid = (uid>>24)&0xff;
267  if (pid==0xff) {
268  // Look up the pid in the table (pointer,pid)
269  if (fgObjPIDs==0) return 0;
270  ULong_t hash = Void_Hash(obj);
271 
273  pid = fgObjPIDs->GetValue(hash,(Long_t)obj);
274  return (TProcessID*)fgPIDs->At(pid);
275  } else {
276  auto current = gGetProcessWithUIDCache.load();
277  if (current && current->first == pid)
278  return current->second;
279 
281  auto res = (TProcessID*)fgPIDs->At(pid);
282 
283  auto next = new PIDCacheContent_t(pid, res);
284  auto old = gGetProcessWithUIDCache.exchange(next);
285  delete old;
286 
287  return res;
288  }
289 }
290 
291 ////////////////////////////////////////////////////////////////////////////////
292 /// static function returning a pointer to TProcessID with its pid
293 /// encoded in the highest byte of obj->GetUniqueID()
294 
296 {
297  return GetProcessWithUID(obj->GetUniqueID(),obj);
298 }
299 
300 ////////////////////////////////////////////////////////////////////////////////
301 /// static function returning the pointer to the session TProcessID
302 
304 {
305  return fgPID;
306 }
307 
308 ////////////////////////////////////////////////////////////////////////////////
309 /// Increase the reference count to this object.
310 
312 {
313  CheckInit();
314  ++fCount;
315  return fCount;
316 }
317 
318 ////////////////////////////////////////////////////////////////////////////////
319 /// Return the current referenced object count
320 /// fgNumber is incremented every time a new object is referenced
321 
323 {
324  return fgNumber;
325 }
326 
327 ////////////////////////////////////////////////////////////////////////////////
328 /// returns the TObject with unique identifier uid in the table of objects
329 
331 {
332  Int_t uid = uidd & 0xffffff; //take only the 24 lower bits
333 
334  if (fObjects==0 || uid >= fObjects->GetSize()) return 0;
335  return fObjects->UncheckedAt(uid);
336 }
337 
338 ////////////////////////////////////////////////////////////////////////////////
339 /// static: returns pointer to current TProcessID
340 
342 {
343  return fgPID;
344 }
345 
346 ////////////////////////////////////////////////////////////////////////////////
347 /// static: returns array of TProcessIDs
348 
350 {
351  return fgPIDs;
352 }
353 
354 
355 ////////////////////////////////////////////////////////////////////////////////
356 /// static function. return kTRUE if pid is a valid TProcessID
357 
359 {
360  if (gIsValidCache == pid)
361  return kTRUE;
362 
364 
365  if (fgPIDs==0) return kFALSE;
366  if (fgPIDs->IndexOf(pid) >= 0) {
367  gIsValidCache = pid;
368  return kTRUE;
369  }
370  if (pid == (TProcessID*)gROOT->GetUUIDs()) {
371  gIsValidCache = pid;
372  return kTRUE;
373  }
374  return kFALSE;
375 }
376 
377 ////////////////////////////////////////////////////////////////////////////////
378 /// stores the object at the uid th slot in the table of objects
379 /// The object uniqued is set as well as its kMustCleanup bit
380 
382 {
383  R__LOCKGUARD_IMT(gROOTMutex); // Lock for parallel TTree I/O
384 
385  if (uid == 0) uid = obj->GetUniqueID() & 0xffffff;
386 
387  if (!fObjects) fObjects = new TObjArray(100);
388  fObjects->AddAtAndExpand(obj,uid);
389 
390  obj->SetBit(kMustCleanup);
391  if ( (obj->GetUniqueID()&0xff000000)==0xff000000 ) {
392  // We have more than 255 pids we need to store this
393  // pointer in the table(pointer,pid) since there is no
394  // more space in fUniqueID
395  if (fgObjPIDs==0) fgObjPIDs = new TExMap;
396  ULong_t hash = Void_Hash(obj);
397 
398  // We use operator() rather than Add() because
399  // if the address has already been registered, we want to
400  // update it's uniqueID (this can easily happen when the
401  // referenced object have been stored in a TClonesArray.
402  (*fgObjPIDs)(hash, (Long_t)obj) = GetUniqueID();
403  }
404 }
405 
406 ////////////////////////////////////////////////////////////////////////////////
407 /// called by the object destructor
408 /// remove reference to obj from the current table if it is referenced
409 
411 {
412  if (!fObjects) return;
413  if (!obj->TestBit(kIsReferenced)) return;
414  UInt_t uid = obj->GetUniqueID() & 0xffffff;
415  if (obj == GetObjectWithID(uid)) {
417  if (fgObjPIDs) {
418  ULong64_t hash = Void_Hash(obj);
419  fgObjPIDs->Remove(hash,(Long64_t)obj);
420  }
421  (*fObjects)[uid] = 0; // Avoid recalculation of fLast (compared to ->RemoveAt(uid))
422  }
423 }
424 
425 
426 ////////////////////////////////////////////////////////////////////////////////
427 /// static function to set the current referenced object count
428 /// fgNumber is incremented every time a new object is referenced
429 
431 {
432  fgNumber = number;
433 }
static TProcessID * GetPID()
static: returns pointer to current TProcessID
Definition: TProcessID.cxx:341
static TProcessID * GetProcessID(UShort_t pid)
static function returning a pointer to TProcessID number pid in fgPIDs
Definition: TProcessID.cxx:246
virtual UInt_t GetUniqueID() const
Return the unique object id.
Definition: TObject.cxx:375
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:410
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:381
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:355
static UInt_t GetNProcessIDs()
Return the (static) number of process IDs.
Definition: TProcessID.cxx:254
unsigned short UShort_t
Definition: RtypesCore.h:36
virtual void SetName(const char *name)
Set the name of the TNamed.
Definition: TNamed.cxx:140
virtual ~TProcessID()
Destructor.
Definition: TProcessID.cxx:93
#define gROOT
Definition: TROOT.h:410
virtual TObject * Remove(TObject *obj)
Remove object from array.
Definition: TObjArray.cxx:703
R__ALWAYS_INLINE Bool_t TestBit(UInt_t f) const
Definition: TObject.h:172
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
static std::atomic< TProcessID * > gIsValidCache
Definition: TProcessID.cxx:60
UInt_t Hash(ECaseCompare cmp=kExact) const
Return hash value.
Definition: TString.cxx:626
void SetBit(UInt_t f, Bool_t set)
Set or unset the user status bits as specified in f.
Definition: TObject.cxx:694
This class defines a UUID (Universally Unique IDentifier), also known as GUIDs (Globally Unique IDent...
Definition: TUUID.h:42
#define R__LOCKGUARD_IMT(mutex)
static TObjArray * GetPIDs()
static: returns array of TProcessIDs
Definition: TProcessID.cxx:349
static TObjArray * fgPIDs
Definition: TProcessID.h:81
static TProcessID * fgPID
Spin lock for initialization of fObjects.
Definition: TProcessID.h:80
std::pair< Int_t, TProcessID * > PIDCacheContent_t
Definition: TProcessID.cxx:61
#define R__WRITE_LOCKGUARD(mutex)
static std::atomic_uint fgNumber
Definition: TProcessID.h:84
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:430
R__EXTERN TVirtualRWMutex * gCoreMutex
static ULong_t Void_Hash(const void *ptr)
Return hash value for this object.
Definition: TProcessID.cxx:67
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:202
virtual void SetUniqueID(UInt_t uid)
Set the unique object id.
Definition: TObject.cxx:705
#define R__READ_LOCKGUARD(mutex)
Int_t GetLast() const
Return index of last object in array.
Definition: TObjArray.cxx:561
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:234
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:295
TProcessID()
Default constructor.
Definition: TProcessID.cxx:75
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:311
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:236
static TProcessID * AddProcessID()
Static function to add a new TProcessID to the list of PIDs.
Definition: TProcessID.cxx:114
if object destructor must call RecursiveRemove()
Definition: TObject.h:60
const Bool_t kFALSE
Definition: RtypesCore.h:88
TObject * GetObjectWithID(UInt_t uid)
returns the TObject with unique identifier uid in the table of objects
Definition: TProcessID.cxx:330
void CheckInit()
Initialize fObjects.
Definition: TProcessID.cxx:190
long Long_t
Definition: RtypesCore.h:50
TObject * UncheckedAt(Int_t i) const
Definition: TObjArray.h:89
#define ClassImp(name)
Definition: Rtypes.h:359
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:216
Int_t IndexOf(const TObject *obj) const
Definition: TObjArray.cxx:589
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:303
const char * AsString() const
Return UUID as string. Copy string immediately since it will be reused.
Definition: TUUID.cxx:533
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:153
if object is referenced by a TRef or TRefArray
Definition: TObject.h:61
#define snprintf
Definition: civetweb.c:1351
static UInt_t GetObjectCount()
Return the current referenced object count fgNumber is incremented every time a new object is referen...
Definition: TProcessID.cxx:322
Int_t GetEntries() const
Return the number of objects in array (i.e.
Definition: TObjArray.cxx:522
void Add(TObject *obj)
Definition: TObjArray.h:73
static Bool_t IsValid(TProcessID *pid)
static function. return kTRUE if pid is a valid TProcessID
Definition: TProcessID.cxx:358
static std::atomic< PIDCacheContent_t * > gGetProcessWithUIDCache
Definition: TProcessID.cxx:62
virtual void Fatal(const char *method, const char *msgfmt,...) const
Issue fatal error message.
Definition: TObject.cxx:908
virtual Int_t GetSize() const
Return the capacity of the collection, i.e.
Definition: TCollection.h:182
virtual void SetTitle(const char *title="")
Set the title of the TNamed.
Definition: TNamed.cxx:164
const Bool_t kTRUE
Definition: RtypesCore.h:87
char name[80]
Definition: TGX11.cxx:109
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:866