54 TObjArray *TProcessID::fgPIDs = 0;
55 TProcessID *TProcessID::fgPID = 0;
56 std::atomic_uint TProcessID::fgNumber(0);
57 TExMap *TProcessID::fgObjPIDs= 0;
60 static std::atomic<TProcessID *> gIsValidCache;
61 using PIDCacheContent_t = std::pair<Int_t, TProcessID*>;
62 static std::atomic<PIDCacheContent_t *> gGetProcessWithUIDCache;
67 static inline ULong_t Void_Hash(
const void *ptr)
69 return TString::Hash(&ptr,
sizeof(
void*));
75 TProcessID::TProcessID()
84 std::atomic_flag_clear( &fLock );
93 TProcessID::~TProcessID()
98 TProcessID *This =
this;
99 gIsValidCache.compare_exchange_strong(This,
nullptr);
101 auto current = gGetProcessWithUIDCache.load();
102 if (current && current->second ==
this) {
103 gGetProcessWithUIDCache.compare_exchange_strong(current,
nullptr);
107 R__WRITE_LOCKGUARD(ROOT::gCoreMutex);
108 fgPIDs->Remove(
this);
114 TProcessID *TProcessID::AddProcessID()
116 R__WRITE_LOCKGUARD(ROOT::gCoreMutex);
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.");
122 ::Fatal(
"TProcessID::AddProcessID",
"Maximum number of TProcessID (65535) has been reached. TRef are not longer functional.");
126 TProcessID *pid =
new TProcessID();
130 fgPIDs =
new TObjArray(10);
131 gROOT->GetListOfCleanups()->Add(fgPIDs);
133 UShort_t apid = fgPIDs->GetEntriesFast();
134 pid->IncrementCount();
139 snprintf(name,20,
"ProcessID%d",apid);
141 pid->SetUniqueID((UInt_t)apid);
144 pid->SetTitle(u.AsString());
153 UInt_t TProcessID::AssignID(TObject *obj)
155 R__WRITE_LOCKGUARD(ROOT::gCoreMutex);
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);
163 if (fgNumber >= 16777215) {
165 fgPID = AddProcessID();
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) {
175 obj->SetBit(kIsReferenced);
178 if ( fgPID->GetUniqueID() < 255 ) {
179 obj->SetUniqueID( (uid & 0xffffff) + (fgPID->GetUniqueID()<<24) );
181 obj->SetUniqueID( (uid & 0xffffff) + 0xff000000 );
183 fgPID->PutObjectWithID(obj,uid);
190 void TProcessID::CheckInit()
193 while (fLock.test_and_set(std::memory_order_acquire));
194 if (!fObjects) fObjects =
new TObjArray(100);
195 fLock.clear(std::memory_order_release);
202 void TProcessID::Cleanup()
204 R__WRITE_LOCKGUARD(ROOT::gCoreMutex);
207 gROOT->GetListOfCleanups()->Remove(fgPIDs);
216 void TProcessID::Clear(Option_t *)
218 if (GetUniqueID()>254 && fObjects && fgObjPIDs) {
220 for(Int_t i = 0; i < fObjects->GetSize(); ++i) {
221 TObject *obj = fObjects->UncheckedAt(i);
223 ULong64_t hash = Void_Hash(obj);
224 fgObjPIDs->Remove(hash,(Long64_t)obj);
229 delete fObjects; fObjects = 0;
236 Int_t TProcessID::DecrementCount()
239 if (fCount < 0) fCount = 0;
246 TProcessID *TProcessID::GetProcessID(UShort_t pid)
248 return (TProcessID*)fgPIDs->At(pid);
254 UInt_t TProcessID::GetNProcessIDs()
256 return fgPIDs ? fgPIDs->GetLast()+1 : 0;
263 TProcessID *TProcessID::GetProcessWithUID(UInt_t uid,
const void *obj)
266 Int_t pid = (uid>>24)&0xff;
269 if (fgObjPIDs==0)
return 0;
270 ULong_t hash = Void_Hash(obj);
272 R__READ_LOCKGUARD(ROOT::gCoreMutex);
273 pid = fgObjPIDs->GetValue(hash,(Long_t)obj);
274 return (TProcessID*)fgPIDs->At(pid);
276 auto current = gGetProcessWithUIDCache.load();
277 if (current && current->first == pid)
278 return current->second;
280 R__READ_LOCKGUARD(ROOT::gCoreMutex);
281 auto res = (TProcessID*)fgPIDs->At(pid);
283 auto next =
new PIDCacheContent_t(pid, res);
284 auto old = gGetProcessWithUIDCache.exchange(next);
295 TProcessID *TProcessID::GetProcessWithUID(
const TObject *obj)
297 return GetProcessWithUID(obj->GetUniqueID(),obj);
303 TProcessID *TProcessID::GetSessionProcessID()
311 Int_t TProcessID::IncrementCount()
322 UInt_t TProcessID::GetObjectCount()
330 TObject *TProcessID::GetObjectWithID(UInt_t uidd)
332 Int_t uid = uidd & 0xffffff;
334 if (fObjects==0 || uid >= fObjects->GetSize())
return 0;
335 return fObjects->UncheckedAt(uid);
341 TProcessID *TProcessID::GetPID()
349 TObjArray *TProcessID::GetPIDs()
358 Bool_t TProcessID::IsValid(TProcessID *pid)
360 if (gIsValidCache == pid)
363 R__READ_LOCKGUARD(ROOT::gCoreMutex);
365 if (fgPIDs==0)
return kFALSE;
366 if (fgPIDs->IndexOf(pid) >= 0) {
370 if (pid == (TProcessID*)gROOT->GetUUIDs()) {
381 void TProcessID::PutObjectWithID(TObject *obj, UInt_t uid)
383 R__LOCKGUARD_IMT(gROOTMutex);
385 if (uid == 0) uid = obj->GetUniqueID() & 0xffffff;
387 if (!fObjects) fObjects =
new TObjArray(100);
388 fObjects->AddAtAndExpand(obj,uid);
390 obj->SetBit(kMustCleanup);
391 if ( (obj->GetUniqueID()&0xff000000)==0xff000000 ) {
395 if (fgObjPIDs==0) fgObjPIDs =
new TExMap;
396 ULong_t hash = Void_Hash(obj);
402 (*fgObjPIDs)(hash, (Long_t)obj) = GetUniqueID();
410 void TProcessID::RecursiveRemove(TObject *obj)
412 if (!fObjects)
return;
413 if (!obj->TestBit(kIsReferenced))
return;
414 UInt_t uid = obj->GetUniqueID() & 0xffffff;
415 if (obj == GetObjectWithID(uid)) {
416 R__WRITE_LOCKGUARD(ROOT::gCoreMutex);
418 ULong64_t hash = Void_Hash(obj);
419 fgObjPIDs->Remove(hash,(Long64_t)obj);
421 (*fObjects)[uid] = 0;
430 void TProcessID::SetObjectCount(UInt_t number)