43 THashTable::THashTable(Int_t capacity, Int_t rehashlevel)
46 Warning(
"THashTable",
"capacity (%d) < 0", capacity);
47 capacity = TCollection::kInitHashTableCapacity;
48 }
else if (capacity == 0)
49 capacity = TCollection::kInitHashTableCapacity;
51 fSize = (Int_t)TMath::NextPrime(TMath::Max(capacity,(
int)TCollection::kInitHashTableCapacity));
52 fCont =
new TList* [fSize];
53 memset(fCont, 0, fSize*
sizeof(TList*));
57 if (rehashlevel < 2) rehashlevel = 0;
58 fRehashLevel = rehashlevel;
65 THashTable::~THashTable()
78 void THashTable::AddImpl(Int_t slot, TObject *obj)
81 fCont[slot] =
new TList;
84 fCont[slot]->Add(obj);
92 void THashTable::Add(TObject *obj)
94 if (IsArgNull(
"Add", obj))
return;
96 Int_t slot = GetCheckedHashValue(obj);
98 R__COLLECTION_WRITE_LOCKGUARD(ROOT::gCoreMutex);
102 if (fRehashLevel && AverageCollisions() > fRehashLevel)
112 void THashTable::AddBefore(
const TObject *before, TObject *obj)
114 if (IsArgNull(
"Add", obj))
return;
116 Int_t slot = GetCheckedHashValue(obj);
118 R__COLLECTION_WRITE_LOCKGUARD(ROOT::gCoreMutex);
120 fCont[slot] =
new TList;
123 if (before && GetHashValue(before) == slot) {
124 fCont[slot]->AddBefore(before,obj);
126 fCont[slot]->Add(obj);
130 if (fRehashLevel && AverageCollisions() > fRehashLevel)
138 void THashTable::AddAll(
const TCollection *col)
140 R__COLLECTION_WRITE_LOCKGUARD(ROOT::gCoreMutex);
145 Int_t sumEntries=fEntries+col->GetEntries();
146 Bool_t rehashBefore=fRehashLevel && (sumEntries > fSize*fRehashLevel);
151 Int_t saveRehashLevel=fRehashLevel;
154 TCollection::AddAll(col);
156 fRehashLevel=saveRehashLevel;
159 if (!rehashBefore && fRehashLevel && AverageCollisions() > fRehashLevel)
167 void THashTable::Clear(Option_t *option)
169 R__COLLECTION_WRITE_LOCKGUARD(ROOT::gCoreMutex);
171 for (
int i = 0; i < fSize; i++) {
176 fCont[i]->SetOwner();
177 fCont[i]->Clear(option);
179 SafeDelete(fCont[i]);
191 Int_t THashTable::Collisions(
const char *name)
const
193 Int_t slot = GetHashValue(name);
195 R__COLLECTION_READ_LOCKGUARD(ROOT::gCoreMutex);
197 if (fCont[slot])
return fCont[slot]->GetSize();
205 Int_t THashTable::Collisions(TObject *obj)
const
207 if (IsArgNull(
"Collisions", obj))
return 0;
209 Int_t slot = GetHashValue(obj);
211 R__COLLECTION_READ_LOCKGUARD(ROOT::gCoreMutex);
213 if (fCont[slot])
return fCont[slot]->GetSize();
220 void THashTable::Delete(Option_t *)
222 R__COLLECTION_WRITE_LOCKGUARD(ROOT::gCoreMutex);
224 for (
int i = 0; i < fSize; i++)
227 SafeDelete(fCont[i]);
238 TObject *THashTable::FindObject(
const char *name)
const
240 Int_t slot = GetHashValue(name);
242 R__COLLECTION_READ_LOCKGUARD(ROOT::gCoreMutex);
244 if (fCont[slot])
return fCont[slot]->FindObject(name);
251 TObject *THashTable::FindObject(
const TObject *obj)
const
253 if (IsArgNull(
"FindObject", obj))
return 0;
255 Int_t slot = GetHashValue(obj);
256 if (fCont[slot])
return fCont[slot]->FindObject(obj);
265 const TList *THashTable::GetListForObject(
const char *name)
const
267 Int_t slot = GetHashValue(name);
269 R__COLLECTION_READ_LOCKGUARD(ROOT::gCoreMutex);
279 const TList *THashTable::GetListForObject(
const TObject *obj)
const
281 if (IsArgNull(
"GetListForObject", obj))
return 0;
283 Int_t slot = GetHashValue(obj);
285 R__COLLECTION_READ_LOCKGUARD(ROOT::gCoreMutex);
293 TObject **THashTable::GetObjectRef(
const TObject *obj)
const
295 if (IsArgNull(
"GetObjectRef", obj))
return 0;
297 Int_t slot = GetHashValue(obj);
299 R__COLLECTION_READ_LOCKGUARD(ROOT::gCoreMutex);
301 if (fCont[slot])
return fCont[slot]->GetObjectRef(obj);
308 TIterator *THashTable::MakeIterator(Bool_t dir)
const
310 return new THashTableIter(
this, dir);
325 void THashTable::Print(Option_t *option, Int_t recurse)
const
327 if (strstr(option,
"details")==
nullptr) {
328 TCollection::Print(option,recurse);
332 PrintCollectionHeader(option);
336 TROOT::IncreaseDirLevel();
337 for (Int_t cursor = 0; cursor < Capacity();
339 printf(
"Slot #%d:\n",cursor);
341 fCont[cursor]->Print();
343 TROOT::IndentLevel();
348 TROOT::DecreaseDirLevel();
362 void THashTable::Rehash(Int_t newCapacity, Bool_t checkObjValidity)
364 THashTable *ht =
new THashTable(newCapacity);
366 R__COLLECTION_WRITE_LOCKGUARD(ROOT::gCoreMutex);
371 auto initialSize = GetEntries();
373 if (checkObjValidity && TObject::GetObjectStat() && gObjectTable) {
374 while ((obj = next()))
375 if (gObjectTable->PtrIsValid(obj))
376 ht->AddImpl(ht->GetHashValue(obj),obj);
378 while ((obj = next()))
379 ht->AddImpl(ht->GetHashValue(obj),obj);
382 if (initialSize != GetEntries()) {
389 "During the rehash of %p one or more element was added or removed. The initalize size was %d and now it is %d",
390 this, initialSize, GetEntries());
400 fEntries = ht->fEntries;
401 fUsedSlots = ht->fUsedSlots;
405 if (fRehashLevel && AverageCollisions() > fRehashLevel)
406 fRehashLevel = (int)AverageCollisions() + 1;
414 TObject *THashTable::Remove(TObject *obj)
416 Int_t slot = GetHashValue(obj);
418 R__COLLECTION_READ_LOCKGUARD(ROOT::gCoreMutex);
421 R__COLLECTION_WRITE_LOCKGUARD(ROOT::gCoreMutex);
423 TObject *ob = fCont[slot]->Remove(obj);
426 if (fCont[slot]->GetSize() == 0) {
427 SafeDelete(fCont[slot]);
439 TObject *THashTable::RemoveSlow(TObject *obj)
442 R__COLLECTION_WRITE_LOCKGUARD(ROOT::gCoreMutex);
444 for (
int i = 0; i < fSize; i++) {
446 TObject *ob = fCont[i]->Remove(obj);
449 if (fCont[i]->GetSize() == 0) {
450 SafeDelete(fCont[i]);
464 ClassImp(THashTableIter);
470 THashTableIter::THashTableIter(
const THashTable *ht, Bool_t dir)
481 THashTableIter::THashTableIter(
const THashTableIter &iter) : TIterator(iter)
483 fTable = iter.fTable;
484 fDirection = iter.fDirection;
485 fCursor = iter.fCursor;
487 if (iter.fListCursor) {
488 fListCursor = (TListIter *)iter.fListCursor->GetCollection()->MakeIterator();
490 fListCursor->operator=(*iter.fListCursor);
497 TIterator &THashTableIter::operator=(
const TIterator &rhs)
499 if (
this != &rhs && rhs.IsA() == THashTableIter::Class()) {
500 const THashTableIter &rhs1 = (
const THashTableIter &)rhs;
501 fTable = rhs1.fTable;
502 fDirection = rhs1.fDirection;
503 fCursor = rhs1.fCursor;
504 if (rhs1.fListCursor) {
507 fListCursor = (TListIter *)rhs1.fListCursor->GetCollection()->MakeIterator();
509 fListCursor->operator=(*rhs1.fListCursor);
518 THashTableIter &THashTableIter::operator=(
const THashTableIter &rhs)
522 fDirection = rhs.fDirection;
523 fCursor = rhs.fCursor;
524 if (rhs.fListCursor) {
527 fListCursor = (TListIter *)rhs.fListCursor->GetCollection()->MakeIterator();
529 fListCursor->operator=(*rhs.fListCursor);
538 THashTableIter::~THashTableIter()
546 TObject *THashTableIter::Next()
552 int slot = NextSlot();
553 if (slot == -1)
return 0;
554 fListCursor =
new TListIter(fTable->fCont[slot], fDirection);
557 TObject *obj = fListCursor->Next();
560 SafeDelete(fListCursor);
567 Int_t THashTableIter::NextSlot()
571 if (fDirection == kIterForward) {
572 for ( ; fCursor < fTable->Capacity() && fTable->fCont[fCursor] == 0;
575 if (fCursor < fTable->Capacity())
579 for ( ; fCursor >= 0 && fTable->fCont[fCursor] == 0;
592 void THashTableIter::Reset()
594 if (fDirection == kIterForward)
597 fCursor = fTable->Capacity() - 1;
598 SafeDelete(fListCursor);
604 Bool_t THashTableIter::operator!=(
const TIterator &aIter)
const
606 if (aIter.IsA() == THashTableIter::Class()) {
607 const THashTableIter &iter(dynamic_cast<const THashTableIter &>(aIter));
608 return (fListCursor != iter.fListCursor);
616 Bool_t THashTableIter::operator!=(
const THashTableIter &aIter)
const
618 return (fListCursor != aIter.fListCursor);
624 TObject *THashTableIter::operator*()
const
626 return (fListCursor ? fListCursor->operator*() :
nullptr);