Loading [MathJax]/extensions/tex2jax.js
ROOT  6.06/09
Reference Guide
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Modules Pages
THashTable.cxx
Go to the documentation of this file.
1 // @(#)root/cont:$Id$
2 // Author: Fons Rademakers 27/09/95
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 THashTable
13 THashTable implements a hash table to store TObject's. The hash
14 value is calculated using the value returned by the TObject's
15 Hash() function. Each class inheriting from TObject can override
16 Hash() as it sees fit.
17 
18 THashTable does not preserve the insertion order of the objects.
19 If the insertion order is important AND fast retrieval is needed
20 use THashList instead.
21 */
22 
23 #include "THashTable.h"
24 #include "TObjectTable.h"
25 #include "TList.h"
26 #include "TError.h"
27 
29 
30 ////////////////////////////////////////////////////////////////////////////////
31 /// Create a THashTable object. Capacity is the initial hashtable capacity
32 /// (i.e. number of slots), by default kInitHashTableCapacity = 17, and
33 /// rehashlevel is the value at which a rehash will be triggered. I.e. when
34 /// the average size of the linked lists at a slot becomes longer than
35 /// rehashlevel then the hashtable will be resized and refilled to reduce
36 /// the collision rate to about 1. The higher the collision rate, i.e. the
37 /// longer the linked lists, the longer lookup will take. If rehashlevel=0
38 /// the table will NOT automatically be rehashed. Use Rehash() for manual
39 /// rehashing.
40 
41 THashTable::THashTable(Int_t capacity, Int_t rehashlevel)
42 {
43  if (capacity < 0) {
44  Warning("THashTable", "capacity (%d) < 0", capacity);
46  } else if (capacity == 0)
48 
50  fCont = new TList* [fSize];
51  memset(fCont, 0, fSize*sizeof(TList*));
52 
53  fEntries = 0;
54  fUsedSlots = 0;
55  if (rehashlevel < 2) rehashlevel = 0;
56  fRehashLevel = rehashlevel;
57 }
58 
59 ////////////////////////////////////////////////////////////////////////////////
60 /// Delete a hashtable. Objects are not deleted unless the THashTable is the
61 /// owner (set via SetOwner()).
62 
64 {
65  if (fCont) Clear();
66  delete [] fCont;
67  fCont = 0;
68  fSize = 0;
69 }
70 
71 ////////////////////////////////////////////////////////////////////////////////
72 /// Add object to the hash table. Its position in the table will be
73 /// determined by the value returned by its Hash() function.
74 
76 {
77  if (IsArgNull("Add", obj)) return;
78 
79  Int_t slot = GetHashValue(obj);
80  if (!fCont[slot]) {
81  fCont[slot] = new TList;
82  fUsedSlots++;
83  }
84  fCont[slot]->Add(obj);
85  fEntries++;
86 
89 }
90 
91 ////////////////////////////////////////////////////////////////////////////////
92 /// Add object to the hash table. Its position in the table will be
93 /// determined by the value returned by its Hash() function.
94 /// If and only if 'before' is in the same bucket as obj, obj is added
95 /// in front of 'before' within the bucket's list.
96 
98 {
99  if (IsArgNull("Add", obj)) return;
100 
101  Int_t slot = GetHashValue(obj);
102  if (!fCont[slot]) {
103  fCont[slot] = new TList;
104  fUsedSlots++;
105  }
106  if (before && GetHashValue(before) == slot) {
107  fCont[slot]->AddBefore(before,obj);
108  } else {
109  fCont[slot]->Add(obj);
110  }
111  fEntries++;
112 
114  Rehash(fEntries);
115 }
116 
117 ////////////////////////////////////////////////////////////////////////////////
118 /// Add all objects from collection col to this collection.
119 /// Implemented for more efficient rehashing.
120 
122 {
123  // Hashing after AddAll can be much more expensive than
124  // hashing before, as we need to add more elements.
125  // We assume an ideal hash, i.e. fUsedSlots==fSize.
126  Int_t sumEntries=fEntries+col->GetEntries();
127  Bool_t rehashBefore=fRehashLevel && (sumEntries > fSize*fRehashLevel);
128  if (rehashBefore)
129  Rehash(sumEntries);
130 
131  // prevent Add from Rehashing
132  Int_t saveRehashLevel=fRehashLevel;
133  fRehashLevel=0;
134 
135  TCollection::AddAll(col);
136 
137  fRehashLevel=saveRehashLevel;
138  // If we didn't Rehash before, we might have to do it
139  // now, due to a non-perfect hash function.
140  if (!rehashBefore && fRehashLevel && AverageCollisions() > fRehashLevel)
141  Rehash(fEntries);
142 }
143 
144 ////////////////////////////////////////////////////////////////////////////////
145 /// Remove all objects from the table. Does not delete the objects
146 /// unless the THashTable is the owner (set via SetOwner()).
147 
149 {
150  for (int i = 0; i < fSize; i++) {
151  // option "nodelete" is passed when Clear is called from
152  // THashList::Clear() or THashList::Delete() or Rehash().
153  if (fCont[i]) {
154  if (IsOwner())
155  fCont[i]->SetOwner();
156  fCont[i]->Clear(option);
157  }
158  SafeDelete(fCont[i]);
159  }
160 
161  fEntries = 0;
162  fUsedSlots = 0;
163 }
164 
165 ////////////////////////////////////////////////////////////////////////////////
166 /// Returns the number of collisions for an object with a certain name
167 /// (i.e. number of objects in same slot in the hash table, i.e. length
168 /// of linked list).
169 
171 {
172  Int_t slot = GetHashValue(name);
173  if (fCont[slot]) return fCont[slot]->GetSize();
174  return 0;
175 }
176 
177 ////////////////////////////////////////////////////////////////////////////////
178 /// Returns the number of collisions for an object (i.e. number of objects
179 /// in same slot in the hash table, i.e. length of linked list).
180 
182 {
183  if (IsArgNull("Collisions", obj)) return 0;
184 
185  Int_t slot = GetHashValue(obj);
186  if (fCont[slot]) return fCont[slot]->GetSize();
187  return 0;
188 }
189 
190 ////////////////////////////////////////////////////////////////////////////////
191 /// Remove all objects from the table AND delete all heap based objects.
192 
194 {
195  for (int i = 0; i < fSize; i++)
196  if (fCont[i]) {
197  fCont[i]->Delete();
198  SafeDelete(fCont[i]);
199  }
200 
201  fEntries = 0;
202  fUsedSlots = 0;
203 }
204 
205 ////////////////////////////////////////////////////////////////////////////////
206 /// Find object using its name. Uses the hash value returned by the
207 /// TString::Hash() after converting name to a TString.
208 
210 {
211  Int_t slot = GetHashValue(name);
212  if (fCont[slot]) return fCont[slot]->FindObject(name);
213  return 0;
214 }
215 
216 ////////////////////////////////////////////////////////////////////////////////
217 /// Find object using its hash value (returned by its Hash() member).
218 
220 {
221  if (IsArgNull("FindObject", obj)) return 0;
222 
223  Int_t slot = GetHashValue(obj);
224  if (fCont[slot]) return fCont[slot]->FindObject(obj);
225  return 0;
226 }
227 
228 ////////////////////////////////////////////////////////////////////////////////
229 /// Return the TList corresponding to object's name based hash value.
230 /// One can iterate this list "manually" to find, e.g. objects with
231 /// the same name.
232 
233 const TList *THashTable::GetListForObject(const char *name) const
234 {
235  return fCont[GetHashValue(name)];
236 }
237 
238 ////////////////////////////////////////////////////////////////////////////////
239 /// Return the TList corresponding to object's hash value.
240 /// One can iterate this list "manually" to find, e.g. identical
241 /// objects.
242 
244 {
245  if (IsArgNull("GetListForObject", obj)) return 0;
246  return fCont[GetHashValue(obj)];
247 }
248 
249 ////////////////////////////////////////////////////////////////////////////////
250 /// Return address of pointer to obj
251 
253 {
254  if (IsArgNull("GetObjectRef", obj)) return 0;
255 
256  Int_t slot = GetHashValue(obj);
257  if (fCont[slot]) return fCont[slot]->GetObjectRef(obj);
258  return 0;
259 }
260 
261 ////////////////////////////////////////////////////////////////////////////////
262 /// Returns a hash table iterator.
263 
265 {
266  return new THashTableIter(this, dir);
267 }
268 
269 ////////////////////////////////////////////////////////////////////////////////
270 /// Rehash the hashtable. If the collision rate becomes too high (i.e.
271 /// the average size of the linked lists become too long) then lookup
272 /// efficiency decreases since relatively long lists have to be searched
273 /// every time. To improve performance rehash the hashtable. This resizes
274 /// the table to newCapacity slots and refills the table. Use
275 /// AverageCollisions() to check if you need to rehash. Set checkObjValidity
276 /// to kFALSE if you know that all objects in the table are still valid
277 /// (i.e. have not been deleted from the system in the meanwhile).
278 
279 void THashTable::Rehash(Int_t newCapacity, Bool_t checkObjValidity)
280 {
281  THashTable *ht = new THashTable(newCapacity);
282 
283  TIter next(this);
284  TObject *obj;
285 
286  if (checkObjValidity && TObject::GetObjectStat() && gObjectTable) {
287  while ((obj = next()))
288  if (gObjectTable->PtrIsValid(obj)) ht->Add(obj);
289  } else {
290  while ((obj = next()))
291  ht->Add(obj);
292  }
293 
294  Clear("nodelete");
295  delete [] fCont;
296  fCont = ht->fCont;
297  ht->fCont = 0;
298 
299  fSize = ht->fSize; // idem
300  fEntries = ht->fEntries;
301  fUsedSlots = ht->fUsedSlots;
302 
303  // this should not happen, but it will prevent an endless loop
304  // in case of a very bad hash function
306  fRehashLevel = (int)AverageCollisions() + 1;
307 
308  delete ht;
309 }
310 
311 ////////////////////////////////////////////////////////////////////////////////
312 /// Remove object from the hashtable.
313 
315 {
316  Int_t slot = GetHashValue(obj);
317  if (fCont[slot]) {
318  TObject *ob = fCont[slot]->Remove(obj);
319  if (ob) {
320  fEntries--;
321  if (fCont[slot]->GetSize() == 0) {
322  SafeDelete(fCont[slot]);
323  fUsedSlots--;
324  }
325  return ob;
326  }
327  }
328  return 0;
329 }
330 
331 ////////////////////////////////////////////////////////////////////////////////
332 /// Remove object from the hashtable without using the hash value.
333 
335 {
336  for (int i = 0; i < fSize; i++) {
337  if (fCont[i]) {
338  TObject *ob = fCont[i]->Remove(obj);
339  if (ob) {
340  fEntries--;
341  if (fCont[i]->GetSize() == 0) {
342  SafeDelete(fCont[i]);
343  fUsedSlots--;
344  }
345  return ob;
346  }
347  }
348  }
349  return 0;
350 }
351 
352 /** \class THashTableIter
353 Iterator of hash table.
354 */
355 
357 
358 ////////////////////////////////////////////////////////////////////////////////
359 /// Create a hashtable iterator. By default the iteration direction
360 /// is kIterForward. To go backward use kIterBackward.
361 
363 {
364  fTable = ht;
365  fDirection = dir;
366  fListCursor = 0;
367  Reset();
368 }
369 
370 ////////////////////////////////////////////////////////////////////////////////
371 /// Copy ctor.
372 
374 {
375  fTable = iter.fTable;
376  fDirection = iter.fDirection;
377  fCursor = iter.fCursor;
378  fListCursor = 0;
379  if (iter.fListCursor) {
381  if (fListCursor)
382  fListCursor->operator=(*iter.fListCursor);
383  }
384 }
385 
386 ////////////////////////////////////////////////////////////////////////////////
387 /// Overridden assignment operator.
388 
390 {
391  if (this != &rhs && rhs.IsA() == THashTableIter::Class()) {
392  const THashTableIter &rhs1 = (const THashTableIter &)rhs;
393  fTable = rhs1.fTable;
394  fDirection = rhs1.fDirection;
395  fCursor = rhs1.fCursor;
396  if (rhs1.fListCursor) {
398  if (fListCursor)
399  fListCursor->operator=(*rhs1.fListCursor);
400  }
401  }
402  return *this;
403 }
404 
405 ////////////////////////////////////////////////////////////////////////////////
406 /// Overloaded assignment operator.
407 
409 {
410  if (this != &rhs) {
411  fTable = rhs.fTable;
412  fDirection = rhs.fDirection;
413  fCursor = rhs.fCursor;
414  if (rhs.fListCursor) {
416  if (fListCursor)
417  fListCursor->operator=(*rhs.fListCursor);
418  }
419  }
420  return *this;
421 }
422 
423 ////////////////////////////////////////////////////////////////////////////////
424 /// Delete hashtable iterator.
425 
427 {
428  delete fListCursor;
429 }
430 
431 ////////////////////////////////////////////////////////////////////////////////
432 /// Return next object in hashtable. Returns 0 when no more objects in table.
433 
435 {
436  while (kTRUE) {
437  if (!fListCursor) {
438  int slot = NextSlot();
439  if (slot == -1) return 0;
441  }
442 
443  TObject *obj = fListCursor->Next();
444  if (obj) return obj;
445 
447  }
448 }
449 
450 ////////////////////////////////////////////////////////////////////////////////
451 /// Returns index of next slot in table containing list to be iterated.
452 
454 {
455  if (fDirection == kIterForward) {
456  for ( ; fCursor < fTable->Capacity() && fTable->fCont[fCursor] == 0;
457  fCursor++) { }
458 
459  if (fCursor < fTable->Capacity())
460  return fCursor++;
461 
462  } else {
463  for ( ; fCursor >= 0 && fTable->fCont[fCursor] == 0;
464  fCursor--) { }
465 
466  if (fCursor >= 0)
467  return fCursor--;
468  }
469  return -1;
470 }
471 
472 ////////////////////////////////////////////////////////////////////////////////
473 /// Reset the hashtable iterator. Either to beginning or end, depending on
474 /// the initial iteration direction.
475 
477 {
478  if (fDirection == kIterForward)
479  fCursor = 0;
480  else
481  fCursor = fTable->Capacity() - 1;
483 }
484 
485 ////////////////////////////////////////////////////////////////////////////////
486 /// This operator compares two TIterator objects.
487 
489 {
490  if (aIter.IsA() == THashTableIter::Class()) {
491  const THashTableIter &iter(dynamic_cast<const THashTableIter &>(aIter));
492  return (fListCursor != iter.fListCursor);
493  }
494  return false; // for base class we don't implement a comparison
495 }
496 
497 ////////////////////////////////////////////////////////////////////////////////
498 /// This operator compares two THashTableIter objects.
499 
501 {
502  return (fListCursor != aIter.fListCursor);
503 }
504 
505 ////////////////////////////////////////////////////////////////////////////////
506 /// Return pointer to current object or nullptr.
507 
509 {
510  return (fListCursor ? fListCursor->operator*() : nullptr);
511 }
virtual Int_t GetEntries() const
Definition: TCollection.h:92
Int_t Collisions(const char *name) const
Returns the number of collisions for an object with a certain name (i.e.
Definition: THashTable.cxx:170
virtual void Delete(Option_t *option="")
Remove all objects from the list AND delete all heap based objects.
Definition: TList.cxx:404
virtual void AddAll(const TCollection *col)
Add all objects from collection col to this collection.
Definition: THashTable.cxx:121
void AddBefore(const TObject *before, TObject *obj)
Add object to the hash table.
Definition: THashTable.cxx:97
ClassImp(TSeqCollection) Int_t TSeqCollection TIter next(this)
Return index of object in collection.
Int_t Capacity() const
Definition: TCollection.h:80
void Reset()
Reset the hashtable iterator.
Definition: THashTable.cxx:476
const TList * GetListForObject(const char *name) const
Return the TList corresponding to object's name based hash value.
Definition: THashTable.cxx:233
TList ** fCont
Definition: THashTable.h:44
const char Option_t
Definition: RtypesCore.h:62
virtual void SetOwner(Bool_t enable=kTRUE)
Set whether this collection is the owner (enable==true) of its content.
TObject * operator*() const
Return pointer to current object or nullptr.
Definition: THashTable.cxx:508
void Rehash(Int_t newCapacity, Bool_t checkObjValidity=kTRUE)
Rehash the hashtable.
Definition: THashTable.cxx:279
TObject * ob
Int_t fUsedSlots
Definition: THashTable.h:46
int Int_t
Definition: RtypesCore.h:41
bool Bool_t
Definition: RtypesCore.h:59
TIterator * MakeIterator(Bool_t dir=kIterForward) const
Returns a hash table iterator.
Definition: THashTable.cxx:264
TObject * RemoveSlow(TObject *obj)
Remove object from the hashtable without using the hash value.
Definition: THashTable.cxx:334
virtual TObject * FindObject(const char *name) const
Find an object in this list using its name.
Definition: TList.cxx:496
TObject * Next()
Return next object in the list. Returns 0 when no more objects in list.
Definition: TList.cxx:932
TListIter * fListCursor
Definition: THashTable.h:111
Int_t GetHashValue(const TObject *obj) const
Definition: THashTable.h:91
const THashTable * fTable
Definition: THashTable.h:109
Iterator abstract base class.
Definition: TIterator.h:32
Iterator of linked list.
Definition: TList.h:187
Bool_t operator!=(const TIterator &aIter) const
This operator compares two TIterator objects.
Definition: THashTable.cxx:488
THashTable(const THashTable &)
Bool_t IsArgNull(const char *where, const TObject *obj) const
Returns true if object is a null pointer.
friend class THashTableIter
Definition: THashTable.h:41
#define SafeDelete(p)
Definition: RConfig.h:436
Iterator of hash table.
Definition: THashTable.h:106
THashTable implements a hash table to store TObject's.
Definition: THashTable.h:39
void Class()
Definition: Class.C:29
void Clear(Option_t *option="")
Remove all objects from the table.
Definition: THashTable.cxx:148
std::map< std::string, std::string >::const_iterator iter
Definition: TAlienJob.cxx:54
virtual void AddAll(const TCollection *col)
Int_t GetSize() const
Definition: THashTable.h:73
const Bool_t kIterForward
Definition: TCollection.h:43
Int_t NextSlot()
Returns index of next slot in table containing list to be iterated.
Definition: THashTable.cxx:453
const TCollection * GetCollection() const
Definition: TList.h:209
~THashTableIter()
Delete hashtable iterator.
Definition: THashTable.cxx:426
Bool_t fDirection
Definition: THashTable.h:112
A doubly linked list.
Definition: TList.h:47
Int_t fEntries
Definition: THashTable.h:45
Bool_t IsOwner() const
Definition: TCollection.h:101
virtual TIterator * MakeIterator(Bool_t dir=kIterForward) const =0
virtual TObject * Remove(TObject *obj)
Remove object from the list.
Definition: TList.cxx:674
Collection abstract base class.
Definition: TCollection.h:48
virtual ~THashTable()
Delete a hashtable.
Definition: THashTable.cxx:63
Bool_t PtrIsValid(TObject *obj)
Definition: TObjectTable.h:80
Int_t fSize
Definition: TCollection.h:63
void Reset(Detail::TBranchProxy *x)
void Warning(const char *location, const char *msgfmt,...)
static Bool_t GetObjectStat()
Get status of object stat flag.
Definition: TObject.cxx:992
virtual void AddBefore(const TObject *before, TObject *obj)
Insert object before object before in the list.
Definition: TList.cxx:172
Float_t AverageCollisions() const
Definition: THashTable.h:83
R__EXTERN TObjectTable * gObjectTable
Definition: TObjectTable.h:84
Long_t NextPrime(Long_t x)
TMath Base functions.
Definition: TMathBase.cxx:29
TIterator & operator=(const TIterator &rhs)
Overridden assignment operator.
Definition: THashTable.cxx:389
virtual Int_t GetSize() const
Definition: TCollection.h:95
TObject ** GetObjectRef(const TObject *obj) const
Return address of pointer to obj.
Definition: THashTable.cxx:252
void Add(TObject *obj)
Add object to the hash table.
Definition: THashTable.cxx:75
virtual void Clear(Option_t *option="")
Remove all objects from the list.
Definition: TList.cxx:348
#define name(a, b)
Definition: linkTestLib0.cpp:5
Mother of all ROOT objects.
Definition: TObject.h:58
void Delete(Option_t *option="")
Remove all objects from the table AND delete all heap based objects.
Definition: THashTable.cxx:193
Int_t fRehashLevel
Definition: THashTable.h:47
virtual void Add(TObject *obj)
Definition: TList.h:81
Short_t Max(Short_t a, Short_t b)
Definition: TMathBase.h:202
TObject * FindObject(const char *name) const
Find object using its name.
Definition: THashTable.cxx:209
TObject * Next()
Return next object in hashtable. Returns 0 when no more objects in table.
Definition: THashTable.cxx:434
virtual TObject ** GetObjectRef(const TObject *obj) const
Return address of pointer to obj.
Definition: TList.cxx:565
ClassImp(THashTable) THashTable
Create a THashTable object.
Definition: THashTable.cxx:28
const Bool_t kTRUE
Definition: Rtypes.h:91
TObject * obj
TObject * Remove(TObject *obj)
Remove object from the hashtable.
Definition: THashTable.cxx:314