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