12 #ifndef ROOT_TCollection
13 #define ROOT_TCollection
40 const Bool_t kIterForward = kTRUE;
41 const Bool_t kIterBackward = !kIterForward;
43 R__EXTERN TVirtualMutex *gCollectionMutex;
57 #ifdef R__CHECK_COLLECTION_MULTI_ACCESS
60 #include <unordered_set>
63 class TCollection :
public TObject {
65 #ifdef R__CHECK_COLLECTION_MULTI_ACCESS
69 std::atomic<std::thread::id> fWriteCurrent;
70 std::atomic<size_t> fWriteCurrentRecurse;
71 std::atomic<size_t> fReadCurrentRecurse;
72 std::unordered_multiset<std::thread::id> fReadSet;
73 std::atomic_flag fSpinLockFlag;
75 void Lock(
const TCollection *collection,
const char *
function);
79 void ReadLock(
const TCollection *collection,
const char *
function);
83 void ConflictReport(std::thread::id holder,
const char *accesstype,
const TCollection *collection,
84 const char *
function);
87 TErrorLock() : fWriteCurrent(), fWriteCurrentRecurse(0), fReadCurrentRecurse(0)
89 std::atomic_flag_clear(&fSpinLockFlag);
96 WriteGuard(TErrorLock &lock,
const TCollection *collection,
const char *
function) : fLock(&lock)
98 fLock->Lock(collection,
function);
100 ~WriteGuard() { fLock->Unlock(); }
107 ReadGuard(TErrorLock &lock,
const TCollection *collection,
const char *
function) : fLock(&lock)
109 fLock->ReadLock(collection,
function);
111 ~ReadGuard() { fLock->ReadUnlock(); }
115 mutable TErrorLock fLock;
117 #define R__COLLECTION_WRITE_GUARD() TCollection::TErrorLock::WriteGuard wg(fLock, this, __PRETTY_FUNCTION__)
118 #define R__COLLECTION_READ_GUARD() TCollection::TErrorLock::ReadGuard rg(fLock, this, __PRETTY_FUNCTION__)
120 #define R__COLLECTION_ITER_GUARD(collection) \
121 TCollection::TErrorLock::ReadGuard rg(collection->fLock, collection, __PRETTY_FUNCTION__)
125 #define R__COLLECTION_WRITE_GUARD()
126 #define R__COLLECTION_READ_GUARD()
127 #define R__COLLECTION_ITER_GUARD(collection)
132 static TCollection *fgCurrentCollection;
133 static TObjectTable *fgGarbageCollection;
134 static Bool_t fgEmptyingGarbage;
135 static Int_t fgGarbageStack;
137 TCollection(
const TCollection &);
138 void operator=(
const TCollection &);
150 TCollection() : fName(), fSize(0) { }
152 virtual void PrintCollectionHeader(Option_t* option)
const;
153 virtual const char* GetCollectionEntryName(TObject* entry)
const;
154 virtual void PrintCollectionEntry(TObject* entry, Option_t* option, Int_t recurse)
const;
157 enum { kInitCapacity = 16, kInitHashTableCapacity = 17 };
159 virtual ~TCollection();
160 virtual void Add(TObject *obj) = 0;
161 void AddVector(TObject *obj1, ...);
162 virtual void AddAll(
const TCollection *col);
163 Bool_t AssertClass(TClass *cl)
const;
164 void Browse(TBrowser *b);
165 Int_t Capacity()
const {
return fSize; }
166 virtual void Clear(Option_t *option=
"") = 0;
167 virtual TObject *Clone(
const char *newname=
"")
const;
168 Int_t Compare(
const TObject *obj)
const;
169 Bool_t Contains(
const char *name)
const {
return FindObject(name) != 0; }
170 Bool_t Contains(
const TObject *obj)
const {
return FindObject(obj) != 0; }
171 virtual void Delete(Option_t *option=
"") = 0;
172 virtual void Draw(Option_t *option=
"");
173 virtual void Dump()
const ;
174 virtual TObject *FindObject(
const char *name)
const;
175 TObject *operator()(
const char *name)
const;
176 virtual TObject *FindObject(
const TObject *obj)
const;
177 virtual Int_t GetEntries()
const {
return GetSize(); }
178 virtual const char *GetName()
const;
179 virtual TObject **GetObjectRef(
const TObject *obj)
const = 0;
182 virtual Int_t GetSize()
const {
return fSize; }
183 virtual Int_t GrowBy(Int_t delta)
const;
184 ULong_t Hash()
const {
return fName.Hash(); }
185 Bool_t IsArgNull(
const char *where,
const TObject *obj)
const;
186 virtual Bool_t IsEmpty()
const {
return GetSize() <= 0; }
187 virtual Bool_t IsFolder()
const {
return kTRUE; }
188 Bool_t IsOwner()
const {
return TestBit(kIsOwner); }
189 Bool_t IsSortable()
const {
return kTRUE; }
190 virtual void ls(Option_t *option=
"")
const ;
191 virtual Bool_t Notify();
192 virtual TIterator *MakeIterator(Bool_t dir = kIterForward)
const = 0;
193 virtual TIterator *MakeReverseIterator()
const {
return MakeIterator(kIterBackward); }
194 virtual void Paint(Option_t *option=
"");
195 virtual void Print(Option_t *option=
"")
const;
196 virtual void Print(Option_t *option, Int_t recurse)
const;
197 virtual void Print(Option_t *option,
const char* wildcard, Int_t recurse=1)
const;
198 virtual void Print(Option_t *option, TPRegexp& regexp, Int_t recurse=1)
const;
199 virtual void RecursiveRemove(TObject *obj);
200 virtual TObject *Remove(TObject *obj) = 0;
201 virtual void RemoveAll(TCollection *col);
202 void RemoveAll() { Clear(); }
203 void SetCurrentCollection();
204 void SetName(
const char *name) { fName = name; }
205 virtual void SetOwner(Bool_t enable = kTRUE);
206 virtual bool UseRWLock();
207 virtual Int_t Write(
const char *name=0, Int_t option=0, Int_t bufsize=0);
208 virtual Int_t Write(
const char *name=0, Int_t option=0, Int_t bufsize=0)
const;
210 R__ALWAYS_INLINE Bool_t IsUsingRWLock()
const {
return TestBit(TCollection::kUseRWLock); }
212 static TCollection *GetCurrentCollection();
213 static void StartGarbageCollection();
214 static void GarbageCollect(TObject *obj);
215 static void EmptyGarbageCollection();
220 ClassDef(TCollection,3)
236 TIterator *fIterator;
239 TIter() : fIterator(nullptr) { }
242 TIter(
const TCollection *col, Bool_t dir = kIterForward)
243 : fIterator(col ? col->MakeIterator(dir) : 0) { }
244 TIter(TIterator *it) : fIterator(it) { }
245 TIter(
const TIter &iter);
246 TIter &operator=(
const TIter &rhs);
247 virtual ~TIter() { SafeDelete(fIterator); }
248 TObject *operator()() {
return Next(); }
249 TObject *Next() {
return fIterator ? fIterator->Next() :
nullptr; }
250 const TCollection *GetCollection()
const {
return fIterator ? fIterator->GetCollection() :
nullptr; }
251 Option_t *GetOption()
const {
return fIterator ? fIterator->GetOption() :
""; }
252 void Reset() {
if (fIterator) fIterator->Reset(); }
253 TIter &operator++() { Next();
return *
this; }
254 Bool_t operator==(
const TIter &aIter)
const {
255 if (fIterator ==
nullptr)
256 return aIter.fIterator ==
nullptr || **aIter.fIterator ==
nullptr;
257 if (aIter.fIterator ==
nullptr)
258 return fIterator ==
nullptr || **fIterator ==
nullptr;
259 return *fIterator == *aIter.fIterator;
261 Bool_t operator!=(
const TIter &aIter)
const {
262 return !(*
this == aIter);
264 TObject *operator*()
const {
return fIterator ? *(*fIterator):
nullptr; }
272 class TIterCategory:
public TIter,
public std::iterator_traits<typename T::Iterator_t> {
275 TIterCategory(
const TCollection *col, Bool_t dir = kIterForward) : TIter(col, dir) { }
276 TIterCategory(TIterator *it) : TIter(it) { }
277 virtual ~TIterCategory() { }
278 TIterCategory &Begin() { TIter::Begin();
return *
this; }
279 static TIterCategory End() {
return TIterCategory(static_cast<TIterator*>(
nullptr)); }
283 inline TIter TCollection::begin()
const {
return ++(TIter(
this)); }
284 inline TIter TCollection::end()
const {
return TIter::End(); }
289 const TCollection &EmptyCollection();
290 bool ContaineeInheritsFrom(TClass *cl, TClass *base);
293 template <
class Containee>
294 class TRangeDynCastIterator :
public TIter {
295 static_assert(std::is_base_of<TObject, Containee>::value,
"Containee type must inherit from TObject");
300 friend class ROOT::Internal::ClassDefGenerateInitInstanceLocalInjector;
302 TRangeDynCastIterator() =
default;
306 TRangeDynCastIterator(
const TIter &iter) : TIter(iter) {}
308 Containee *operator()() =
delete;
310 Containee *Next() {
return dynamic_cast<Containee *
>(TIter::Next()); }
311 Containee *operator*()
const {
return dynamic_cast<Containee *
>(TIter::operator*()); }
313 ClassDefInline(TRangeDynCastIterator, 0);
335 template <
class Containee>
336 class TTypedIter :
public TIter {
337 static_assert(std::is_base_of<TObject, Containee>::value,
"Containee type must inherit from TObject");
342 friend class ROOT::Internal::ClassDefGenerateInitInstanceLocalInjector;
344 TTypedIter() =
default;
346 static Containee *StaticCast(TObject *obj)
348 assert(!obj || ROOT::Internal::ContaineeInheritsFrom(obj->IsA(), Containee::Class()));
349 return static_cast<Containee *
>(obj);
354 TTypedIter(
const TIter &iter) : TIter(iter) {}
356 Containee *operator()() {
return StaticCast(TIter::Next()); }
357 Containee *Next() {
return StaticCast(TIter::Next()); }
358 Containee *operator*()
const {
return StaticCast(TIter::operator*()); }
360 ClassDefInline(TTypedIter, 0);
382 class TRangeStaticCast {
383 const TCollection &fCollection;
386 TRangeStaticCast(
const TCollection &col) : fCollection(col) {}
387 TRangeStaticCast(
const TCollection *col) : fCollection(col != nullptr ? *col : ROOT::Internal::EmptyCollection()) {}
389 TTypedIter<T> begin()
const {
return fCollection.begin(); }
390 TTypedIter<T> end()
const {
return fCollection.end(); }
411 class TRangeDynCast {
412 const TCollection &fCollection;
415 TRangeDynCast(
const TCollection &col) : fCollection(col) {}
416 TRangeDynCast(
const TCollection *col) : fCollection(col != nullptr ? *col : ROOT::Internal::EmptyCollection()) {}
418 ROOT::Internal::TRangeDynCastIterator<T> begin()
const {
return fCollection.begin(); }
419 ROOT::Internal::TRangeDynCastIterator<T> end()
const {
return fCollection.end(); }
423 #if defined (_REENTRANT) || defined (WIN32)
425 #define R__COLL_COND_MUTEX(mutex) this->IsUsingRWLock() ? mutex : nullptr
427 #define R__COLLECTION_READ_LOCKGUARD(mutex) ::ROOT::TReadLockGuard _R__UNIQUE_(R__readguard)(R__COLL_COND_MUTEX(mutex))
428 #define R__COLLECTION_READ_LOCKGUARD_NAMED(name,mutex) ::ROOT::TReadLockGuard _NAME2_(R__readguard,name)(R__COLL_COND_MUTEX(mutex))
430 #define R__COLLECTION_WRITE_LOCKGUARD(mutex) ::ROOT::TWriteLockGuard _R__UNIQUE_(R__readguard)(R__COLL_COND_MUTEX(mutex))
431 #define R__COLLECTION_WRITE_LOCKGUARD_NAMED(name,mutex) ::ROOT::TWriteLockGuard _NAME2_(R__readguard,name)(R__COLL_COND_MUTEX(mutex))
435 #define R__COLLECTION_READ_LOCKGUARD(mutex) (void)mutex
436 #define R__COLLECTION_COLLECTION_READ_LOCKGUARD_NAMED(name,mutex) (void)mutex
438 #define R__COLLECTION_WRITE_LOCKGUARD(mutex) (void)mutex
439 #define R__COLLECTION_WRITE_LOCKGUARD_NAMED(name,mutex) (void)mutex
448 #define R__FOR_EACH(type,proc) \
449 SetCurrentCollection(); \
450 TIter _NAME3_(nxt_,type,proc)(TCollection::GetCurrentCollection()); \
451 type *_NAME3_(obj_,type,proc); \
452 while ((_NAME3_(obj_,type,proc) = (type*) _NAME3_(nxt_,type,proc)())) \
453 _NAME3_(obj_,type,proc)->proc