Logo ROOT   6.16/01
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
15A TProcessID identifies a ROOT job in a unique way in time and space.
16The TProcessID title consists of a TUUID object which provides a globally
17unique identifier (for more see TUUID.h).
18
19A TProcessID is automatically created by the TROOT constructor.
20When a TFile contains referenced objects (see TRef), the TProcessID
21object is written to the file.
22If a file has been written in multiple sessions (same machine or not),
23a TProcessID is written for each session.
24These objects are used by the class TRef to uniquely identified
25any TObject pointed by a TRef.
26
27When a referenced object is read from a file (its bit kIsReferenced is set),
28this object is entered into the objects table of the corresponding TProcessID.
29Each TFile has a list of TProcessIDs (see TFile::fProcessIDs) also
30accessible via TProcessID::fgPIDs (for all files).
31When this object is deleted, it is removed from the table via the cleanup
32mechanism invoked by the TObject destructor.
33
34Each TProcessID has a table (TObjArray *fObjects) that keeps track
35of all referenced objects. If a referenced object has a fUniqueID set,
36a pointer to this unique object may be found via fObjects->At(fUniqueID).
37In the same way, when a TRef::GetObject is called, GetObject uses
38its own fUniqueID to find the pointer to the referenced object.
39See TProcessID::GetObjectWithID and PutObjectWithID.
40
41When a referenced object is deleted, its slot in fObjects is set to null.
42//
43See also TProcessUUID: a specialized TProcessID to manage the single list
44of 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
54TObjArray *TProcessID::fgPIDs = 0; //pointer to the list of TProcessID
55TProcessID *TProcessID::fgPID = 0; //pointer to the TProcessID of the current session
56std::atomic_uint TProcessID::fgNumber(0); //Current referenced object instance count
57TExMap *TProcessID::fgObjPIDs= 0; //Table (pointer,pids)
59
60static std::atomic<TProcessID *> gIsValidCache;
61using PIDCacheContent_t = std::pair<Int_t, TProcessID*>;
62static std::atomic<PIDCacheContent_t *> gGetProcessWithUIDCache;
63
64////////////////////////////////////////////////////////////////////////////////
65/// Return hash value for this object.
66
67static 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 }
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.
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}
unsigned short UShort_t
Definition: RtypesCore.h:36
int Int_t
Definition: RtypesCore.h:41
unsigned int UInt_t
Definition: RtypesCore.h:42
const Bool_t kFALSE
Definition: RtypesCore.h:88
unsigned long ULong_t
Definition: RtypesCore.h:51
long Long_t
Definition: RtypesCore.h:50
bool Bool_t
Definition: RtypesCore.h:59
long long Long64_t
Definition: RtypesCore.h:69
unsigned long long ULong64_t
Definition: RtypesCore.h:70
const Bool_t kTRUE
Definition: RtypesCore.h:87
const char Option_t
Definition: RtypesCore.h:62
#define ClassImp(name)
Definition: Rtypes.h:363
static std::atomic< PIDCacheContent_t * > gGetProcessWithUIDCache
Definition: TProcessID.cxx:62
static std::atomic< TProcessID * > gIsValidCache
Definition: TProcessID.cxx:60
static ULong_t Void_Hash(const void *ptr)
Return hash value for this object.
Definition: TProcessID.cxx:67
std::pair< Int_t, TProcessID * > PIDCacheContent_t
Definition: TProcessID.cxx:61
R__EXTERN TVirtualMutex * gROOTMutex
Definition: TROOT.h:57
#define gROOT
Definition: TROOT.h:410
#define R__LOCKGUARD_IMT(mutex)
#define R__WRITE_LOCKGUARD(mutex)
#define R__READ_LOCKGUARD(mutex)
#define snprintf
Definition: civetweb.c:1540
This class stores a (key,value) pair using an external hash.
Definition: TExMap.h:33
void Remove(ULong64_t hash, Long64_t key)
Remove entry with specified key from the TExMap.
Definition: TExMap.cxx:216
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 SetTitle(const char *title="")
Set the title of the TNamed.
Definition: TNamed.cxx:164
virtual void SetName(const char *name)
Set the name of the TNamed.
Definition: TNamed.cxx:140
An array of TObjects.
Definition: TObjArray.h:37
Int_t IndexOf(const TObject *obj) const
Definition: TObjArray.cxx:589
Int_t GetEntriesFast() const
Definition: TObjArray.h:64
void Add(TObject *obj)
Definition: TObjArray.h:73
virtual void Delete(Option_t *option="")
Remove all objects from the array AND delete all heap based objects.
Definition: TObjArray.cxx:355
Int_t GetLast() const
Return index of last object in array.
Definition: TObjArray.cxx:561
virtual TObject * Remove(TObject *obj)
Remove object from array.
Definition: TObjArray.cxx:703
TObject * At(Int_t idx) const
Definition: TObjArray.h:165
Mother of all ROOT objects.
Definition: TObject.h:37
R__ALWAYS_INLINE Bool_t TestBit(UInt_t f) const
Definition: TObject.h:172
virtual UInt_t GetUniqueID() const
Return the unique object id.
Definition: TObject.cxx:375
virtual void Warning(const char *method, const char *msgfmt,...) const
Issue warning message.
Definition: TObject.cxx:866
void SetBit(UInt_t f, Bool_t set)
Set or unset the user status bits as specified in f.
Definition: TObject.cxx:694
virtual void Fatal(const char *method, const char *msgfmt,...) const
Issue fatal error message.
Definition: TObject.cxx:908
virtual void SetUniqueID(UInt_t uid)
Set the unique object id.
Definition: TObject.cxx:705
@ kIsReferenced
if object is referenced by a TRef or TRefArray
Definition: TObject.h:61
@ kMustCleanup
if object destructor must call RecursiveRemove()
Definition: TObject.h:60
A TProcessID identifies a ROOT job in a unique way in time and space.
Definition: TProcessID.h:69
Int_t IncrementCount()
Increase the reference count to this object.
Definition: TProcessID.cxx:311
void CheckInit()
Initialize fObjects.
Definition: TProcessID.cxx:190
static void Cleanup()
static function (called by TROOT destructor) to delete all TProcessIDs
Definition: TProcessID.cxx:202
static Bool_t IsValid(TProcessID *pid)
static function. return kTRUE if pid is a valid TProcessID
Definition: TProcessID.cxx:358
static UInt_t GetNProcessIDs()
Return the (static) number of process IDs.
Definition: TProcessID.cxx:254
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
static TObjArray * fgPIDs
Definition: TProcessID.h:81
static TObjArray * GetPIDs()
static: returns array of TProcessIDs
Definition: TProcessID.cxx:349
static UInt_t AssignID(TObject *obj)
static function returning the ID assigned to obj If the object is not yet referenced,...
Definition: TProcessID.cxx:153
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
static TProcessID * GetSessionProcessID()
static function returning the pointer to the session TProcessID
Definition: TProcessID.cxx:303
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
virtual ~TProcessID()
Destructor.
Definition: TProcessID.cxx:93
static TExMap * fgObjPIDs
Definition: TProcessID.h:82
std::atomic_int fCount
Definition: TProcessID.h:76
static TProcessID * AddProcessID()
Static function to add a new TProcessID to the list of PIDs.
Definition: TProcessID.cxx:114
std::atomic_flag fLock
Array pointing to the referenced objects.
Definition: TProcessID.h:78
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
static TProcessID * GetProcessID(UShort_t pid)
static function returning a pointer to TProcessID number pid in fgPIDs
Definition: TProcessID.cxx:246
Int_t DecrementCount()
The reference fCount is used to delete the TProcessID in the TFile destructor when fCount = 0.
Definition: TProcessID.cxx:236
TObject * GetObjectWithID(UInt_t uid)
returns the TObject with unique identifier uid in the table of objects
Definition: TProcessID.cxx:330
static std::atomic_uint fgNumber
Definition: TProcessID.h:84
ROOT::Internal::TAtomicPointer< TObjArray * > fObjects
Reference count to this object (from TFile)
Definition: TProcessID.h:77
static TProcessID * fgPID
Spin lock for initialization of fObjects.
Definition: TProcessID.h:80
TProcessID()
Default constructor.
Definition: TProcessID.cxx:75
static UInt_t GetObjectCount()
Return the current referenced object count fgNumber is incremented every time a new object is referen...
Definition: TProcessID.cxx:322
static TProcessID * GetPID()
static: returns pointer to current TProcessID
Definition: TProcessID.cxx:341
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
UInt_t Hash(ECaseCompare cmp=kExact) const
Return hash value.
Definition: TString.cxx:626
This class defines a UUID (Universally Unique IDentifier), also known as GUIDs (Globally Unique IDent...
Definition: TUUID.h:42
const char * AsString() const
Return UUID as string. Copy string immediately since it will be reused.
Definition: TUUID.cxx:560
R__EXTERN TVirtualRWMutex * gCoreMutex