Logo ROOT  
Reference Guide
 
Loading...
Searching...
No Matches
TCollection.h
Go to the documentation of this file.
1// @(#)root/cont:$Id$
2// Author: Fons Rademakers 13/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#ifndef ROOT_TCollection
13#define ROOT_TCollection
14
15
16//////////////////////////////////////////////////////////////////////////
17// //
18// TCollection //
19// //
20// Collection abstract base class. This class inherits from TObject //
21// because we want to be able to have collections of collections. //
22// //
23//////////////////////////////////////////////////////////////////////////
24
25#include "TObject.h"
26
27#include "TIterator.h"
28
29#include "TString.h"
30
31#include "TVirtualRWMutex.h"
32
33#include "ROOT/RRangeCast.hxx"
34
35#include <cassert>
36
37class TClass;
38class TObjectTable;
39class TVirtualMutex;
40class TIter;
41
44
46
47// #define R__CHECK_COLLECTION_MULTI_ACCESS
48
49// When R__CHECK_COLLECTION_MULTI_ACCESS is turned on (defined),
50// the normal (not locked) ROOT TCollections are instrumented with a
51// pseudo read-write lock which does not halt the execution but detects
52// and report concurrent access to the same collections.
53// Multiple readers are allowed.
54// Multiple concurrent writer is reported as a Conflict
55// Readers access while a write is running is reported as Conflict
56// Re-entrant writing call by the same Writer thread are allowed.
57// Entering a writing section by a single Reader thread is allowed.
58
59#ifdef R__CHECK_COLLECTION_MULTI_ACCESS
60#include <atomic>
61#include <thread>
62#include <unordered_multiset>
63#endif
64
65class TCollection : public TObject {
66
67#ifdef R__CHECK_COLLECTION_MULTI_ACCESS
68public:
69 class TErrorLock {
70 // Warn when multiple thread try to acquire the same 'lock'
71 std::atomic<std::thread::id> fWriteCurrent;
72 std::atomic<size_t> fWriteCurrentRecurse;
73 std::atomic<size_t> fReadCurrentRecurse;
74 std::unordered_multiset<std::thread::id> fReadSet;
75 std::atomic_flag fSpinLockFlag;
76
77 void Lock(const TCollection *collection, const char *function);
78
79 void Unlock();
80
81 void ReadLock(const TCollection *collection, const char *function);
82
83 void ReadUnlock();
84
85 void ConflictReport(std::thread::id holder, const char *accesstype, const TCollection *collection,
86 const char *function);
87
88 public:
89 TErrorLock() : fWriteCurrent(), fWriteCurrentRecurse(0), fReadCurrentRecurse(0)
90 {
91 std::atomic_flag_clear(&fSpinLockFlag);
92 }
93
94 class WriteGuard {
95 TErrorLock *fLock;
96
97 public:
98 WriteGuard(TErrorLock &lock, const TCollection *collection, const char *function) : fLock(&lock)
99 {
100 fLock->Lock(collection, function);
101 }
102 ~WriteGuard() { fLock->Unlock(); }
103 };
104
105 class ReadGuard {
106 TErrorLock *fLock;
107
108 public:
109 ReadGuard(TErrorLock &lock, const TCollection *collection, const char *function) : fLock(&lock)
110 {
111 fLock->ReadLock(collection, function);
112 }
113 ~ReadGuard() { fLock->ReadUnlock(); }
114 };
115 };
116
117 mutable TErrorLock fLock; //! Special 'lock' to detect multiple access to a collection.
118
119#define R__COLLECTION_WRITE_GUARD() TCollection::TErrorLock::WriteGuard wg(fLock, this, __PRETTY_FUNCTION__)
120#define R__COLLECTION_READ_GUARD() TCollection::TErrorLock::ReadGuard rg(fLock, this, __PRETTY_FUNCTION__)
121
122#define R__COLLECTION_ITER_GUARD(collection) \
123 TCollection::TErrorLock::ReadGuard rg(collection->fLock, collection, __PRETTY_FUNCTION__)
124
125#else
126
127#define R__COLLECTION_WRITE_GUARD()
128#define R__COLLECTION_READ_GUARD()
129#define R__COLLECTION_ITER_GUARD(collection)
130
131#endif
132
133private:
134 static TCollection *fgCurrentCollection; //used by macro R__FOR_EACH
135 static TObjectTable *fgGarbageCollection; //used by garbage collector
136 static Bool_t fgEmptyingGarbage; //used by garbage collector
137 static Int_t fgGarbageStack; //used by garbage collector
138
139 TCollection(const TCollection &) = delete; //private and not-implemented, collections
140 void operator=(const TCollection &) = delete; //are too complex to be automatically copied
141
142protected:
145 // BIT(15) is used by TClonesArray and TMap
146 kUseRWLock = BIT(16)
147 };
148
149 TString fName; //name of the collection
150 Int_t fSize; //number of elements in collection
151
152 TCollection() : fName(), fSize(0) { }
153
154 virtual void PrintCollectionHeader(Option_t* option) const;
155 virtual const char* GetCollectionEntryName(TObject* entry) const;
156 virtual void PrintCollectionEntry(TObject* entry, Option_t* option, Int_t recurse) const;
157
158public:
160
161 virtual ~TCollection();
162 virtual void Add(TObject *obj) = 0;
163 void AddVector(TObject *obj1, ...);
164 virtual void AddAll(const TCollection *col);
165 Bool_t AssertClass(TClass *cl) const;
166 void Browse(TBrowser *b) override;
167 Int_t Capacity() const { return fSize; }
168 void Clear(Option_t *option="") override = 0;
169 TObject *Clone(const char *newname="") const override;
170 Int_t Compare(const TObject *obj) const override;
171 Bool_t Contains(const char *name) const { return FindObject(name) != nullptr; }
172 Bool_t Contains(const TObject *obj) const { return FindObject(obj) != nullptr; }
173 void Delete(Option_t *option="") override = 0;
174 void Draw(Option_t *option="") override;
175 void Dump() const override;
176 TObject *FindObject(const char *name) const override;
177 TObject *operator()(const char *name) const;
178 TObject *FindObject(const TObject *obj) const override;
179 virtual Int_t GetEntries() const { return GetSize(); }
180 const char *GetName() const override;
181 virtual TObject **GetObjectRef(const TObject *obj) const = 0;
182 /// Return the *capacity* of the collection, i.e. the current total amount of space that has been allocated so far.
183 /// Same as `Capacity`. Use `GetEntries` to get the number of elements currently in the collection.
184 virtual Int_t GetSize() const { return fSize; }
185 virtual Int_t GrowBy(Int_t delta) const;
186 ULong_t Hash() const override { return fName.Hash(); }
187 Bool_t IsArgNull(const char *where, const TObject *obj) const;
188 virtual Bool_t IsEmpty() const { return GetSize() <= 0; }
189 Bool_t IsFolder() const override { return kTRUE; }
190 Bool_t IsOwner() const { return TestBit(kIsOwner); }
191 Bool_t IsSortable() const override { return kTRUE; }
192 void ls(Option_t *option="") const override;
193 Bool_t Notify() override;
194 virtual TIterator *MakeIterator(Bool_t dir = kIterForward) const = 0;
196 void Paint(Option_t *option="") override;
197 void Print(Option_t *option="") const override;
198 virtual void Print(Option_t *option, Int_t recurse) const;
199 virtual void Print(Option_t *option, const char* wildcard, Int_t recurse=1) const;
200 virtual void Print(Option_t *option, TPRegexp& regexp, Int_t recurse=1) const;
201 void RecursiveRemove(TObject *obj) override;
202 virtual TObject *Remove(TObject *obj) = 0;
203 virtual void RemoveAll(TCollection *col);
204 void RemoveAll() { Clear(); }
206 void SetName(const char *name) { fName = name; }
207 virtual void SetOwner(Bool_t enable = kTRUE);
208 virtual bool UseRWLock(Bool_t enable = true);
209 Int_t Write(const char *name = nullptr, Int_t option = 0, Int_t bufsize = 0) override;
210 Int_t Write(const char *name = nullptr, Int_t option = 0, Int_t bufsize = 0) const override;
211
213
215 static void StartGarbageCollection();
216 static void GarbageCollect(TObject *obj);
217 static void EmptyGarbageCollection();
218
219 TIter begin() const;
220 TIter end() const;
221
222 ClassDefOverride(TCollection,3) //Collection abstract base class
223};
224
225
226//////////////////////////////////////////////////////////////////////////
227// //
228// TIter //
229// //
230// Iterator wrapper. Type of iterator used depends on type of //
231// collection. //
232// //
233//////////////////////////////////////////////////////////////////////////
234
235class TIter {
236
237private:
238 TIterator *fIterator{nullptr}; //collection iterator
239
240protected:
241 TIter() : fIterator(nullptr) { }
242
243public:
245 : fIterator(col ? col->MakeIterator(dir) : nullptr) { }
246 TIter(TIterator *it) : fIterator(it) { }
247 TIter(const TIter &iter);
248 TIter &operator=(const TIter &rhs);
250 TObject *operator()() { return Next(); }
251 TObject *Next() { return fIterator ? fIterator->Next() : nullptr; }
252 const TCollection *GetCollection() const { return fIterator ? fIterator->GetCollection() : nullptr; }
253 Option_t *GetOption() const { return fIterator ? fIterator->GetOption() : ""; }
254 void Reset() { if (fIterator) fIterator->Reset(); }
255 TIter &operator++() { Next(); return *this; }
256 Bool_t operator==(const TIter &aIter) const {
257 if (fIterator == nullptr)
258 return aIter.fIterator == nullptr || **aIter.fIterator == nullptr;
259 if (aIter.fIterator == nullptr)
260 return fIterator == nullptr || **fIterator == nullptr;
261 return *fIterator == *aIter.fIterator;
262 }
263 Bool_t operator!=(const TIter &aIter) const {
264 return !(*this == aIter);
265 }
267 {
268 if (fIterator)
269 delete fIterator;
270 fIterator = iter;
271 return *this;
272 }
273 TObject *operator*() const { return fIterator ? *(*fIterator): nullptr; }
274 TIter &Begin();
275 static TIter End();
276
277 ClassDef(TIter,0) //Iterator wrapper
278};
279
280template <class T>
281class TIterCategory: public TIter, public std::iterator_traits<typename T::Iterator_t> {
282
283public:
284 TIterCategory(const TCollection *col, Bool_t dir = kIterForward) : TIter(col, dir) { }
286 virtual ~TIterCategory() { }
287 TIterCategory &Begin() { TIter::Begin(); return *this; }
288 static TIterCategory End() { return TIterCategory(static_cast<TIterator*>(nullptr)); }
289};
290
291
292inline TIter TCollection::begin() const { return ++(TIter(this)); }
293inline TIter TCollection::end() const { return TIter::End(); }
294
295namespace ROOT {
296namespace Internal {
297
299bool ContaineeInheritsFrom(TClass *cl, TClass *base);
300
301} // namespace Internal
302
303/// Special implementation of ROOT::RRangeCast for TCollection, including a
304/// check that the cast target type inherits from TObject and a new constructor
305/// that takes the TCollection by pointer.
306/// \tparam T The new type to convert to.
307/// \tparam isDynamic If `true`, `dynamic_cast` is used, otherwise `static_cast` is used.
308namespace Detail {
309
310template <typename T, bool isDynamic>
311class TRangeCast : public ROOT::RRangeCast<T*, isDynamic, TCollection const&> {
312public:
313 TRangeCast(TCollection const& col) : ROOT::RRangeCast<T*, isDynamic, TCollection const&>{col} {
314 static_assert(std::is_base_of<TObject, T>::value, "Containee type must inherit from TObject");
315 }
316 TRangeCast(TCollection const* col) : TRangeCast{col != nullptr ? *col : ROOT::Internal::EmptyCollection()} {}
317};
318
319/// @brief TRangeStaticCast is an adapter class that allows the typed iteration
320/// through a TCollection. This requires the collection to contain elements
321/// of the type requested (or a derived class). Any deviation from this expectation
322/// will only be caught/reported by an assert in debug builds.
323///
324/// This is best used with a TClonesArray, for other cases prefered TRangeDynCast.
325///
326/// The typical use is:
327/// ```{.cpp}
328/// for(auto bcl : TRangeStaticCast<TBaseClass>( *tbaseClassClonesArrayPtr )) {
329/// ... use bcl as a TBaseClass*
330/// }
331/// for(auto bcl : TRangeStaticCast<TBaseClass>( tbaseClassClonesArrayPtr )) {
332/// ... use bcl as a TBaseClass*
333/// }
334/// ```
335/// \tparam T The new type to convert to.
336template <typename T>
338
339} // namespace Detail
340} // namespace ROOT
341
342/// @brief TRangeDynCast is an adapter class that allows the typed iteration
343/// through a TCollection.
344///
345/// The typical use is:
346/// ```{.cpp}
347/// for(auto bcl : TRangeDynCast<TBaseClass>( *cl->GetListOfBases() )) {
348/// if (!bcl) continue;
349/// ... use bcl as a TBaseClass*
350/// }
351/// for(auto bcl : TRangeDynCast<TBaseClass>( cl->GetListOfBases() )) {
352/// if (!bcl) continue;
353/// ... use bcl as a TBaseClass*
354/// }
355/// ```
356/// \tparam T The new type to convert to.
357template <typename T>
359
360#define R__COLL_COND_MUTEX(mutex) this->IsUsingRWLock() ? mutex : nullptr
361
362#define R__COLLECTION_READ_LOCKGUARD(mutex) ::ROOT::TReadLockGuard _R__UNIQUE_(R__readguard)(R__COLL_COND_MUTEX(mutex))
363#define R__COLLECTION_READ_LOCKGUARD_NAMED(name,mutex) ::ROOT::TReadLockGuard _NAME2_(R__readguard,name)(R__COLL_COND_MUTEX(mutex))
364
365#define R__COLLECTION_WRITE_LOCKGUARD(mutex) ::ROOT::TWriteLockGuard _R__UNIQUE_(R__readguard)(R__COLL_COND_MUTEX(mutex))
366#define R__COLLECTION_WRITE_LOCKGUARD_NAMED(name,mutex) ::ROOT::TWriteLockGuard _NAME2_(R__readguard,name)(R__COLL_COND_MUTEX(mutex))
367
368//---- R__FOR_EACH macro -------------------------------------------------------
369
370// Macro to loop over all elements of a list of type "type" while executing
371// procedure "proc" on each element
372
373#define R__FOR_EACH(type,proc) \
374 SetCurrentCollection(); \
375 TIter _NAME3_(nxt_,type,proc)(TCollection::GetCurrentCollection()); \
376 type *_NAME3_(obj_,type,proc); \
377 while ((_NAME3_(obj_,type,proc) = (type*) _NAME3_(nxt_,type,proc)())) \
378 _NAME3_(obj_,type,proc)->proc
379
380#endif
#define R__EXTERN
Definition DllImport.h:26
#define R__ALWAYS_INLINE
Definition RConfig.hxx:552
#define SafeDelete(p)
Definition RConfig.hxx:525
#define b(i)
Definition RSha256.hxx:100
bool Bool_t
Definition RtypesCore.h:63
int Int_t
Definition RtypesCore.h:45
unsigned long ULong_t
Definition RtypesCore.h:55
constexpr Bool_t kTRUE
Definition RtypesCore.h:93
const char Option_t
Definition RtypesCore.h:66
#define ClassDef(name, id)
Definition Rtypes.h:342
#define BIT(n)
Definition Rtypes.h:90
#define ClassDefOverride(name, id)
Definition Rtypes.h:346
const Bool_t kIterBackward
Definition TCollection.h:43
R__EXTERN TVirtualMutex * gCollectionMutex
Definition TCollection.h:45
const Bool_t kIterForward
Definition TCollection.h:42
Option_t Option_t option
char name[80]
Definition TGX11.cxx:110
TRangeCast(TCollection const &col)
TRangeCast(TCollection const *col)
Wraps any collection that can be used in range-based loops and applies static_cast<T> or dynamic_cast...
Using a TBrowser one can browse all ROOT objects.
Definition TBrowser.h:37
TClass instances represent classes, structs and namespaces in the ROOT type system.
Definition TClass.h:81
Collection abstract base class.
Definition TCollection.h:65
virtual TObject ** GetObjectRef(const TObject *obj) const =0
virtual TObject * Remove(TObject *obj)=0
virtual TIterator * MakeIterator(Bool_t dir=kIterForward) const =0
void operator=(const TCollection &)=delete
Bool_t IsFolder() const override
Returns kTRUE in case object contains browsable objects (like containers or lists of other objects).
virtual void PrintCollectionEntry(TObject *entry, Option_t *option, Int_t recurse) const
Print the collection entry.
Bool_t IsArgNull(const char *where, const TObject *obj) const
Returns true if object is a null pointer.
Bool_t Notify() override
'Notify' all objects in this collection.
@ kInitHashTableCapacity
ULong_t Hash() const override
Return hash value for this object.
void SetCurrentCollection()
Set this collection to be the globally accessible collection.
static TCollection * GetCurrentCollection()
Return the globally accessible collection.
void RecursiveRemove(TObject *obj) override
Remove object from this collection and recursively remove the object from all other objects (and coll...
Int_t Capacity() const
void RemoveAll()
virtual bool UseRWLock(Bool_t enable=true)
Set this collection to use a RW lock upon access, making it thread safe.
static Bool_t fgEmptyingGarbage
Bool_t AssertClass(TClass *cl) const
Make sure all objects in this collection inherit from class cl.
static Int_t fgGarbageStack
TIter end() const
void ls(Option_t *option="") const override
List (ls) all objects in this collection.
virtual Int_t GrowBy(Int_t delta) const
Increase the collection's capacity by delta slots.
void SetName(const char *name)
TIter begin() const
virtual void AddAll(const TCollection *col)
Add all objects from collection col to this collection.
const char * GetName() const override
Return name of this collection.
virtual TIterator * MakeReverseIterator() const
void Dump() const override
Dump all objects in this collection.
virtual Int_t GetEntries() const
Int_t Compare(const TObject *obj) const override
Compare two TCollection objects.
virtual const char * GetCollectionEntryName(TObject *entry) const
For given collection entry return the string that is used to identify the object and,...
static void EmptyGarbageCollection()
Do the garbage collection.
virtual void PrintCollectionHeader(Option_t *option) const
Print the collection header.
TCollection(const TCollection &)=delete
Int_t Write(const char *name=nullptr, Int_t option=0, Int_t bufsize=0) override
Write all objects in this collection.
virtual void SetOwner(Bool_t enable=kTRUE)
Set whether this collection is the owner (enable==true) of its content.
static TCollection * fgCurrentCollection
TString fName
void Browse(TBrowser *b) override
Browse this collection (called by TBrowser).
virtual void Add(TObject *obj)=0
Bool_t IsOwner() const
void Print(Option_t *option="") const override
Default print for collections, calls Print(option, 1).
TObject * FindObject(const char *name) const override
Find an object in this collection using its name.
virtual Bool_t IsEmpty() const
R__ALWAYS_INLINE Bool_t IsUsingRWLock() const
static TObjectTable * fgGarbageCollection
TObject * Clone(const char *newname="") const override
Make a clone of an collection using the Streamer facility.
void AddVector(TObject *obj1,...)
Add all arguments to the collection.
void Delete(Option_t *option="") override=0
Delete this object.
void Clear(Option_t *option="") override=0
virtual ~TCollection()
TNamed destructor.
static void StartGarbageCollection()
Set up for garbage collection.
static void GarbageCollect(TObject *obj)
Add to the list of things to be cleaned up.
Bool_t IsSortable() const override
TObject * operator()(const char *name) const
Find an object in this collection by name.
Bool_t Contains(const char *name) const
virtual Int_t GetSize() const
Return the capacity of the collection, i.e.
Bool_t Contains(const TObject *obj) const
void Paint(Option_t *option="") override
Paint all objects in this collection.
TIterCategory(TIterator *it)
TIterCategory(const TCollection *col, Bool_t dir=kIterForward)
TIterCategory & Begin()
virtual ~TIterCategory()
static TIterCategory End()
TIter & Begin()
Pointing to the first element of the container.
virtual ~TIter()
const TCollection * GetCollection() const
Bool_t operator!=(const TIter &aIter) const
Bool_t operator==(const TIter &aIter) const
TIter & operator=(TIterator *iter)
TObject * operator()()
Option_t * GetOption() const
static TIter End()
Pointing to the element after the last - to a nullptr value in our case.
TObject * operator*() const
TObject * Next()
void Reset()
TIter & operator++()
TIter(TIterator *it)
TIter & operator=(const TIter &rhs)
Assigning an TIter to another.
TIter(const TCollection *col, Bool_t dir=kIterForward)
TIterator * fIterator
Iterator abstract base class.
Definition TIterator.h:30
virtual void Reset()=0
virtual TObject * Next()=0
virtual Option_t * GetOption() const
Definition TIterator.h:40
virtual const TCollection * GetCollection() const =0
This class registers all instances of TObject and its derived classes in a hash table.
Mother of all ROOT objects.
Definition TObject.h:41
R__ALWAYS_INLINE Bool_t TestBit(UInt_t f) const
Definition TObject.h:199
Basic string class.
Definition TString.h:139
UInt_t Hash(ECaseCompare cmp=kExact) const
Return hash value.
Definition TString.cxx:677
This class implements a mutex interface.
bool ContaineeInheritsFrom(TClass *cl, TClass *base)
Return true if 'cl' inherits from 'base'.
const TCollection & EmptyCollection()
Return an empty collection for use with nullptr TRangeCast.
tbb::task_arena is an alias of tbb::interface7::task_arena, which doesn't allow to forward declare tb...
th1 Draw()