Logo ROOT  
Reference Guide
Loading...
Searching...
No Matches
THashList.cxx
Go to the documentation of this file.
1// @(#)root/cont:$Id$
2// Author: Fons Rademakers 10/08/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 THashList
13\ingroup Containers
14THashList implements a hybrid collection class consisting of a
15hash table and a list to store TObject's. The hash table is used for
16quick access and lookup of objects while the list allows the objects
17to be ordered. The hash value is calculated using the value returned
18by the TObject's Hash() function. Each class inheriting from TObject
19can override Hash() as it sees fit.
20*/
21
22#include "THashList.h"
23#include "THashTable.h"
24#include "TClass.h"
25
26
27
28////////////////////////////////////////////////////////////////////////////////
29/// Create a THashList object. Capacity is the initial hashtable capacity
30/// (i.e. number of slots), by default kInitHashTableCapacity = 17, and
31/// rehash is the value at which a rehash will be triggered. I.e. when the
32/// average size of the linked lists at a slot becomes longer than rehash
33/// then the hashtable will be resized and refilled to reduce the collision
34/// rate to about 1. The higher the collision rate, i.e. the longer the
35/// linked lists, the longer lookup will take. If rehash=0 the table will
36/// NOT automatically be rehashed. Use Rehash() for manual rehashing.
37///
38/// WARNING !!!
39/// If the name of an object in the HashList is modified, The hashlist
40/// must be Rehashed
41
43{
44 fTable = new THashTable(capacity, rehash);
45}
46
47////////////////////////////////////////////////////////////////////////////////
48/// For backward compatibility only. Use other ctor.
49
51{
52 fTable = new THashTable(capacity, rehash);
53}
54
55////////////////////////////////////////////////////////////////////////////////
56/// Delete a hashlist. Objects are not deleted unless the THashList is the
57/// owner (set via SetOwner()).
58
64
65////////////////////////////////////////////////////////////////////////////////
66/// Add object at the beginning of the list.
67
75
76////////////////////////////////////////////////////////////////////////////////
77/// Add object at the beginning of the list and also store option.
78/// Storing an option is useful when one wants to change the behaviour
79/// of an object a little without having to create a complete new
80/// copy of the object. This feature is used, for example, by the Draw()
81/// method. It allows the same object to be drawn in different ways.
82
90
91////////////////////////////////////////////////////////////////////////////////
92/// Add object at the end of the list.
93
101
102////////////////////////////////////////////////////////////////////////////////
103/// Add object at the end of the list and also store option.
104/// Storing an option is useful when one wants to change the behaviour
105/// of an object a little without having to create a complete new
106/// copy of the object. This feature is used, for example, by the Draw()
107/// method. It allows the same object to be drawn in different ways.
108
110{
112
113 TList::AddLast(obj, opt);
114 fTable->Add(obj);
115}
116
117////////////////////////////////////////////////////////////////////////////////
118/// Insert object before object before in the list.
119
120void THashList::AddBefore(const TObject *before, TObject *obj)
121{
123
124 TList::AddBefore(before, obj);
125 fTable->AddBefore(before, obj);
126}
127
128////////////////////////////////////////////////////////////////////////////////
129/// Insert object before object before in the list.
130
132{
134
135 TList::AddBefore(before, obj);
136 fTable->AddBefore(before->GetObject(), obj);
137}
138
139////////////////////////////////////////////////////////////////////////////////
140/// Insert object before object before in the list, with options.
141
142void THashList::AddBefore(const TObject *before, TObject *obj, Option_t *opt)
143{
145
146 TList::AddBefore(before, obj, opt);
147 fTable->AddBefore(before, obj);
148}
149
150////////////////////////////////////////////////////////////////////////////////
151/// Insert object before object before in the list, with options.
152
154{
156
157 TList::AddBefore(before, obj, opt);
158 fTable->AddBefore(before->GetObject(), obj);
159}
160
161////////////////////////////////////////////////////////////////////////////////
162/// Insert object after object after in the list.
163
164void THashList::AddAfter(const TObject *after, TObject *obj)
165{
167
168 TList::AddAfter(after, obj);
169 fTable->Add(obj);
170}
171
172////////////////////////////////////////////////////////////////////////////////
173/// Insert object after object after in the list.
174
176{
178
179 TList::AddAfter(after, obj);
180 fTable->Add(obj);
181}
182////////////////////////////////////////////////////////////////////////////////
183/// Insert object after object after in the list, with options.
184
185void THashList::AddAfter(const TObject *after, TObject *obj, Option_t *opt)
186{
188
189 TList::AddAfter(after, obj, opt);
190 fTable->Add(obj);
191}
192
193////////////////////////////////////////////////////////////////////////////////
194/// Insert object after object after in the list, with options.
195
197{
199
200 TList::AddAfter(after, obj, opt);
201 fTable->Add(obj);
202}
203
204////////////////////////////////////////////////////////////////////////////////
205/// Insert object at location idx in the list.
206
208{
210
211 TList::AddAt(obj, idx);
212 fTable->Add(obj);
213}
214
215////////////////////////////////////////////////////////////////////////////////
216/// Insert object at location idx in the list, with options.
217
219{
221
222 TList::AddAt(obj, idx, opt);
223 fTable->Add(obj);
224}
225
226////////////////////////////////////////////////////////////////////////////////
227/// Return the average collision rate. The higher the number the longer
228/// the linked lists in the hashtable, the slower the lookup. If the number
229/// is high, or lookup noticeably too slow, perform a Rehash().
230
232{
234
235 return fTable->AverageCollisions();
236}
237
238////////////////////////////////////////////////////////////////////////////////
239/// Remove all objects from the list. Does not delete the objects unless
240/// the THashList is the owner (set via SetOwner()).
241
243{
245
246 fTable->Clear("nodelete"); // clear table so not more lookups
247 if (IsOwner())
248 TList::Delete(option);
249 else
250 TList::Clear(option);
251}
252
253////////////////////////////////////////////////////////////////////////////////
254/// Remove all objects from the list AND delete all heap based objects.
255/// If option="slow" then keep list consistent during delete. This allows
256/// recursive list operations during the delete (e.g. during the dtor
257/// of an object in this list one can still access the list to search for
258/// other not yet deleted objects).
259
261{
263
264 Bool_t slow = option ? (!strcmp(option, "slow") ? kTRUE : kFALSE) : kFALSE;
265
266 if (!slow) {
267 fTable->Clear("nodelete"); // clear table so no more lookups
268 TList::Delete(option); // this deletes the objects
269 } else {
270 TList removeDirectory; // need to deregister these from their directory
271
272 while (fFirst) {
273 auto tlk = fFirst;
274 fFirst = fFirst->NextSP();
275 fSize--;
276 // remove object from table
277 fTable->Remove(tlk->GetObject());
278
279 // delete only heap objects
280 auto obj = tlk->GetObject();
281 // In case somebody else access it.
282 tlk->SetObject(nullptr);
283 if (obj && ROOT::Detail::HasBeenDeleted(obj))
284 Error("Delete", "A list is accessing an object (%p) already deleted (list name = %s)",
285 obj, GetName());
286 else if (obj && obj->IsOnHeap())
288 else if (obj && obj->IsA()->GetDirectoryAutoAdd())
289 removeDirectory.Add(obj);
290
291 // tlk reference count goes down 1.
292 }
293 fFirst.reset();
294 fLast.reset();
295 fCache.reset();
296 fSize = 0;
297
298 // These objects cannot expect to have a valid TDirectory anymore;
299 // e.g. because *this is the TDirectory's list of objects. Even if
300 // not, they are supposed to be deleted, so we can as well unregister
301 // them from their directory, even if they are stack-based:
302 TIter iRemDir(&removeDirectory);
303 TObject* dirRem = nullptr;
304 while ((dirRem = iRemDir())) {
305 (*dirRem->IsA()->GetDirectoryAutoAdd())(dirRem, nullptr);
306 }
307 Changed();
308 }
309}
310
311////////////////////////////////////////////////////////////////////////////////
312/// Find object using its name. Uses the hash value returned by the
313/// TString::Hash() after converting name to a TString.
314
316{
318
319 return fTable->FindObject(name);
320}
321
322////////////////////////////////////////////////////////////////////////////////
323/// Find object using its hash value (returned by its Hash() member).
324
326{
328
329 return fTable->FindObject(obj);
330}
331
332////////////////////////////////////////////////////////////////////////////////
333/// Return the THashTable's list (bucket) in which obj can be found based on
334/// its hash; see THashTable::GetListForObject().
335
336const TList *THashList::GetListForObject(const char *name) const
337{
339
340 return fTable->GetListForObject(name);
341}
342
343////////////////////////////////////////////////////////////////////////////////
344/// Return the THashTable's list (bucket) in which obj can be found based on
345/// its hash; see THashTable::GetListForObject().
346
348{
350
351 return fTable->GetListForObject(obj);
352}
353
354////////////////////////////////////////////////////////////////////////////////
355/// Remove object from this collection and recursively remove the object
356/// from all other objects (and collections).
357/// This function overrides TCollection::RecursiveRemove that calls
358/// the Remove function. THashList::Remove cannot be called because
359/// it uses the hash value of the hash table. This hash value
360/// is not available anymore when RecursiveRemove is called from
361/// the TObject destructor.
362
364{
365 if (!obj || fSize == 0)
366 return;
367
368 // It might not be safe to rely on TROOT::RecursiveRemove to take the readlock in case user code
369 // is calling directly gROOT->GetListOfCleanups()->RecursiveRemove(...)
370 // However this can become a significant bottleneck if there are a very large number of
371 // TDirectory object.
372 // If we need to enabling this read lock, we need to move the fSize check afterwards.
373 // TList::RecursiveRemove has the same pattern.
374 // R__COLLECTION_READ_LOCKGUARD(ROOT::gCoreMutex);
375
376 if (obj->HasInconsistentHash()) {
378
379 // Remove obj in the list itself
380 TObject *object = TList::Remove(obj);
381 if (object)
382 fTable->RemoveSlow(object);
383
384 } else if (fTable->FindObject(obj)) {
386
387 // Remove obj in the list itself
388 TObject *object = TList::Remove(obj);
389 if (object)
390 fTable->Remove(object);
391 }
392
393 // Scan again the list and invoke RecursiveRemove for all objects
394 // We need to make sure to go through all the node even those
395 // marked as empty by another thread (Eventhough we hold the
396 // read lock if one of the call to RecursiveRemove request
397 // the write lock then the read lock will be suspended and
398 // another thread can modify the list; thanks to the shared_pointer
399 // forward-and-backward links, our view of the list is still intact
400 // but might contains node will nullptr payload)
401 auto lnk = fFirst;
402 decltype(lnk) next;
403 while (lnk.get()) {
404 next = lnk->NextSP();
405 TObject *ob = lnk->GetObject();
406 if (ob && !ROOT::Detail::HasBeenDeleted(ob)) {
407 ob->RecursiveRemove(obj);
408 }
409 lnk = next;
410 }
411}
412
413////////////////////////////////////////////////////////////////////////////////
414/// Rehash the hashlist. If the collision rate becomes too high (i.e.
415/// the average size of the linked lists become too long) then lookup
416/// efficiency decreases since relatively long lists have to be searched
417/// every time. To improve performance rehash the hashtable. This resizes
418/// the table to newCapacity slots and refills the table. Use
419/// AverageCollisions() to check if you need to rehash.
420
421void THashList::Rehash(Int_t newCapacity)
422{
424
425 fTable->Rehash(newCapacity);
426}
427
428////////////////////////////////////////////////////////////////////////////////
429/// Remove object from the list.
430
432{
434 if (!obj || !fTable->FindObject(obj)) return nullptr;
435
437 TList::Remove(obj);
438 return fTable->Remove(obj);
439}
440
441////////////////////////////////////////////////////////////////////////////////
442/// Remove object via its objlink from the list.
443
445{
446 if (!lnk) return nullptr;
447
449 TObject *obj = lnk->GetObject();
450
451 TList::Remove(lnk);
452 return fTable->Remove(obj);
453}
454
455////////////////////////////////////////////////////////////////////////////////
456/// Set this collection to use a RW lock upon access, making it thread safe.
457/// Return the previous state.
458///
459/// Note: To test whether the usage is enabled do:
460/// collection->TestBit(TCollection::kUseRWLock);
461
463{
464 fTable->UseRWLock(enable);
465 return TCollection::UseRWLock(enable);
466}
#define SafeDelete(p)
Definition RConfig.hxx:525
int Int_t
Signed integer 4 bytes (int).
Definition RtypesCore.h:59
bool Bool_t
Boolean (0=false, 1=true) (bool).
Definition RtypesCore.h:77
constexpr Bool_t kFALSE
Definition RtypesCore.h:108
float Float_t
Float 4 bytes (float).
Definition RtypesCore.h:71
constexpr Bool_t kTRUE
Definition RtypesCore.h:107
const char Option_t
Option string (const char).
Definition RtypesCore.h:80
#define R__COLLECTION_READ_LOCKGUARD(mutex)
#define R__COLLECTION_WRITE_LOCKGUARD(mutex)
char name[80]
Definition TGX11.cxx:148
virtual bool UseRWLock(Bool_t enable=true)
Set this collection to use a RW lock upon access, making it thread safe.
const char * GetName() const override
Return name of this collection.
Bool_t IsOwner() const
static void GarbageCollect(TObject *obj)
Add to the list of things to be cleaned up.
void Delete(Option_t *option="") override
Remove all objects from the list AND delete all heap based objects.
void AddBefore(const TObject *before, TObject *obj) override
Insert object before object before in the list.
void Clear(Option_t *option="") override
Remove all objects from the list.
void AddFirst(TObject *obj) override
Add object at the beginning of the list.
Definition THashList.cxx:68
void Rehash(Int_t newCapacity)
Rehash the hashlist.
virtual ~THashList()
Delete a hashlist.
Definition THashList.cxx:59
void AddAfter(const TObject *after, TObject *obj) override
Insert object after object after in the list.
THashTable * fTable
Definition THashList.h:37
void RecursiveRemove(TObject *obj) override
Remove object from this collection and recursively remove the object from all other objects (and coll...
void AddAt(TObject *obj, Int_t idx) override
Insert object at location idx in the list.
THashList(const THashList &)=delete
const TList * GetListForObject(const char *name) const
Return the THashTable's list (bucket) in which obj can be found based on its hash; see THashTable::Ge...
bool UseRWLock(Bool_t enable=true) override
Set this collection to use a RW lock upon access, making it thread safe.
Float_t AverageCollisions() const
Return the average collision rate.
TObject * Remove(TObject *obj) override
Remove object from the list.
TObject * FindObject(const char *name) const override
Find object using its name.
void AddLast(TObject *obj) override
Add object at the end of the list.
Definition THashList.cxx:94
THashTable implements a hash table to store TObject's.
Definition THashTable.h:35
void AddAfter(const TObject *after, TObject *obj) override
Insert object after object after in the list.
Definition TList.cxx:247
void Clear(Option_t *option="") override
Remove all objects from the list.
Definition TList.cxx:532
TList(const TList &)=delete
void AddAt(TObject *obj, Int_t idx) override
Insert object at position idx in the list.
Definition TList.cxx:413
void Add(TObject *obj) override
Definition TList.h:81
TObject * Remove(TObject *obj) override
Remove object from the list.
Definition TList.cxx:952
void AddLast(TObject *obj) override
Add object at the end of the list.
Definition TList.cxx:149
TObjLinkPtr_t fLast
! pointer to last entry in linked list
Definition TList.h:47
void AddBefore(const TObject *before, TObject *obj) override
Insert object before object before in the list.
Definition TList.cxx:193
TObjLinkPtr_t fFirst
! pointer to first entry in linked list
Definition TList.h:46
void Delete(Option_t *option="") override
Remove all objects from the list AND delete all heap based objects.
Definition TList.cxx:600
TObjLinkWeakPtr_t fCache
! cache to speedup sequential calling of Before() and After() functions
Definition TList.h:48
void AddFirst(TObject *obj) override
Add object at the beginning of the list.
Definition TList.cxx:97
Mother of all ROOT objects.
Definition TObject.h:42
Bool_t HasInconsistentHash() const
Return true is the type of this object is known to have an inconsistent setup for Hash and RecursiveR...
Definition TObject.h:366
virtual void RecursiveRemove(TObject *obj)
Recursively remove this object from a list.
Definition TObject.cxx:684
virtual void Error(const char *method, const char *msgfmt,...) const
Issue error message.
Definition TObject.cxx:1098
virtual TClass * IsA() const
Definition TObject.h:248
virtual void Changed()
bool HasBeenDeleted(const TObject *obj)
Check if the TObject's memory has been deleted.
Definition TObject.h:409
externTVirtualRWMutex * gCoreMutex