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