81 namespace std {}
using namespace std;
97 void TList::AddFirst(TObject *obj)
99 R__COLLECTION_WRITE_GUARD();
101 if (IsArgNull(
"AddFirst", obj))
return;
103 R__COLLECTION_WRITE_LOCKGUARD(ROOT::gCoreMutex);
106 fFirst = NewLink(obj);
109 auto t = NewLink(obj);
125 void TList::AddFirst(TObject *obj, Option_t *opt)
127 R__COLLECTION_WRITE_GUARD();
129 if (IsArgNull(
"AddFirst", obj))
return;
131 R__COLLECTION_WRITE_LOCKGUARD(ROOT::gCoreMutex);
134 fFirst = NewOptLink(obj, opt);
137 auto t = NewOptLink(obj, opt);
149 void TList::AddLast(TObject *obj)
151 R__COLLECTION_WRITE_GUARD();
153 if (IsArgNull(
"AddLast", obj))
return;
155 R__COLLECTION_WRITE_LOCKGUARD(ROOT::gCoreMutex);
158 fFirst = NewLink(obj);
161 fLast = NewLink(obj, fLast);
173 void TList::AddLast(TObject *obj, Option_t *opt)
175 R__COLLECTION_WRITE_GUARD();
177 if (IsArgNull(
"AddLast", obj))
return;
179 R__COLLECTION_WRITE_LOCKGUARD(ROOT::gCoreMutex);
182 fFirst = NewOptLink(obj, opt);
185 fLast = NewOptLink(obj, opt, fLast);
193 void TList::AddBefore(
const TObject *before, TObject *obj)
195 R__COLLECTION_WRITE_GUARD();
197 if (IsArgNull(
"AddBefore", obj))
return;
199 R__COLLECTION_WRITE_LOCKGUARD(ROOT::gCoreMutex);
202 TList::AddFirst(obj);
205 TObjLink *t = FindLink(before, idx);
207 Error(
"AddBefore",
"before not found, object not added");
210 if (t == fFirst.get())
211 TList::AddFirst(obj);
213 NewLink(obj, t->fPrev.lock());
225 void TList::AddBefore(TObjLink *before, TObject *obj)
227 R__COLLECTION_WRITE_GUARD();
229 if (IsArgNull(
"AddBefore", obj))
return;
232 TList::AddFirst(obj);
234 if (before == fFirst.get())
235 TList::AddFirst(obj);
237 NewLink(obj, before->fPrev.lock());
247 void TList::AddAfter(
const TObject *after, TObject *obj)
249 R__COLLECTION_WRITE_GUARD();
251 if (IsArgNull(
"AddAfter", obj))
return;
253 R__COLLECTION_WRITE_LOCKGUARD(ROOT::gCoreMutex);
259 TObjLink *t = FindLink(after, idx);
261 Error(
"AddAfter",
"after not found, object not added");
264 if (t == fLast.get())
267 NewLink(obj, t->shared_from_this());
279 void TList::AddAfter(TObjLink *after, TObject *obj)
281 R__COLLECTION_WRITE_GUARD();
283 if (IsArgNull(
"AddAfter", obj))
return;
285 R__COLLECTION_WRITE_LOCKGUARD(ROOT::gCoreMutex);
290 if (after == fLast.get())
293 NewLink(obj, after->shared_from_this());
303 void TList::AddAt(TObject *obj, Int_t idx)
305 R__COLLECTION_WRITE_GUARD();
307 if (IsArgNull(
"AddAt", obj))
return;
309 R__COLLECTION_WRITE_LOCKGUARD(ROOT::gCoreMutex);
311 TObjLink *lnk = LinkAt(idx);
314 else if (lnk == fFirst.get())
315 TList::AddFirst(obj);
317 NewLink(obj, lnk->fPrev.lock());
327 TObject *TList::After(
const TObject *obj)
const
329 R__COLLECTION_WRITE_GUARD();
333 R__COLLECTION_WRITE_LOCKGUARD(ROOT::gCoreMutex);
335 auto cached = fCache.lock();
336 if (cached.get() && cached->GetObject() && cached->GetObject()->IsEqual(obj)) {
338 ((TList*)
this)->fCache = cached->fNext;
341 t = FindLink(obj, idx);
342 if (t) ((TList*)
this)->fCache = t->fNext;
346 return t->Next()->GetObject();
354 TObject *TList::At(Int_t idx)
const
356 R__COLLECTION_WRITE_LOCKGUARD(ROOT::gCoreMutex);
357 R__COLLECTION_WRITE_GUARD();
359 TObjLink *lnk = LinkAt(idx);
360 if (lnk)
return lnk->GetObject();
368 TObject *TList::Before(
const TObject *obj)
const
370 R__COLLECTION_WRITE_LOCKGUARD(ROOT::gCoreMutex);
371 R__COLLECTION_WRITE_GUARD();
375 auto cached = fCache.lock();
376 if (cached.get() && cached->GetObject() && cached->GetObject()->IsEqual(obj)) {
378 ((TList*)
this)->fCache = cached->fPrev;
381 t = FindLink(obj, idx);
382 if (t) ((TList*)
this)->fCache = t->fPrev;
386 return t->Prev()->GetObject();
399 void TList::Clear(Option_t *option)
401 R__COLLECTION_WRITE_LOCKGUARD(ROOT::gCoreMutex);
402 R__COLLECTION_WRITE_GUARD();
404 Bool_t nodel = option ? (!strcmp(option,
"nodelete") ? kTRUE : kFALSE) : kFALSE;
406 if (!nodel && IsOwner()) {
428 fFirst = fFirst->fNext;
438 auto obj = tlk->GetObject();
440 if (!obj->TestBit(kNotDeleted)) {
441 Error(
"Clear",
"A list is accessing an object (%p) already deleted (list name = %s)",
443 }
else if (obj->IsOnHeap()) {
444 if (obj->TestBit(kCanDelete)) {
445 if (obj->TestBit(kNotDeleted)) {
446 TCollection::GarbageCollect(obj);
467 void TList::Delete(Option_t *option)
469 R__COLLECTION_WRITE_LOCKGUARD(ROOT::gCoreMutex);
470 R__COLLECTION_WRITE_GUARD();
472 Bool_t slow = option ? (!strcmp(option,
"slow") ? kTRUE : kFALSE) : kFALSE;
474 TList removeDirectory;
491 fFirst = fFirst->fNext;
500 auto obj = tlk->GetObject();
501 if (obj && !obj->TestBit(kNotDeleted))
502 Error(
"Delete",
"A list is accessing an object (%p) already deleted (list name = %s)",
504 else if (obj && obj->IsOnHeap())
505 TCollection::GarbageCollect(obj);
506 else if (obj && obj->IsA()->GetDirectoryAutoAdd())
507 removeDirectory.Add(obj);
526 first = first->fNext;
528 auto obj = tlk->GetObject();
529 tlk->SetObject(
nullptr);
530 if (obj && !obj->TestBit(kNotDeleted))
531 Error(
"Delete",
"A list is accessing an object (%p) already deleted (list name = %s)",
533 else if (obj && obj->IsOnHeap())
534 TCollection::GarbageCollect(obj);
535 else if (obj && obj->IsA()->GetDirectoryAutoAdd())
536 removeDirectory.Add(obj);
547 TIter iRemDir(&removeDirectory);
549 while ((dirRem = iRemDir())) {
550 (*dirRem->IsA()->GetDirectoryAutoAdd())(dirRem, 0);
559 void TList::DeleteLink(TObjLink *lnk)
561 R__COLLECTION_WRITE_GUARD();
563 lnk->fNext = lnk->fPrev = 0;
575 TObject *TList::FindObject(
const char *name)
const
577 R__COLLECTION_READ_GUARD();
582 R__COLLECTION_READ_LOCKGUARD(ROOT::gCoreMutex);
584 for (TObjLink *lnk = FirstLink(); lnk !=
nullptr; lnk = lnk->Next()) {
585 if (TObject *obj = lnk->GetObject()) {
586 const char *objname = obj->GetName();
587 if (objname && strcmp(name, objname) == 0)
602 TObject *TList::FindObject(
const TObject *obj)
const
604 R__COLLECTION_READ_GUARD();
609 R__COLLECTION_READ_LOCKGUARD(ROOT::gCoreMutex);
611 TObjLink *lnk = FirstLink();
614 TObject *ob = lnk->GetObject();
615 if (ob->IsEqual(obj))
return ob;
625 TObjLink *TList::FindLink(
const TObject *obj, Int_t &idx)
const
627 R__COLLECTION_READ_GUARD();
632 R__COLLECTION_READ_LOCKGUARD(ROOT::gCoreMutex);
634 if (!fFirst)
return 0;
637 TObjLink *lnk = fFirst.get();
641 object = lnk->GetObject();
643 if (object->TestBit(kNotDeleted)) {
644 if (object->IsEqual(obj))
return lnk;
656 TObject *TList::First()
const
658 R__COLLECTION_READ_LOCKGUARD(ROOT::gCoreMutex);
659 R__COLLECTION_READ_GUARD();
661 if (fFirst)
return fFirst->GetObject();
668 TObject **TList::GetObjectRef(
const TObject *obj)
const
670 R__COLLECTION_READ_GUARD();
675 R__COLLECTION_READ_LOCKGUARD(ROOT::gCoreMutex);
677 TObjLink *lnk = FirstLink();
680 TObject *ob = lnk->GetObject();
681 if (ob->IsEqual(obj))
return lnk->GetObjectRef();
690 TObject *TList::Last()
const
692 R__COLLECTION_READ_LOCKGUARD(ROOT::gCoreMutex);
693 R__COLLECTION_READ_GUARD();
695 if (fLast)
return fLast->GetObject();
702 TObjLink *TList::LinkAt(Int_t idx)
const
704 R__COLLECTION_READ_LOCKGUARD(ROOT::gCoreMutex);
705 R__COLLECTION_READ_GUARD();
708 TObjLink *lnk = fFirst.get();
709 while (i < idx && lnk) {
719 TIterator *TList::MakeIterator(Bool_t dir)
const
721 R__COLLECTION_READ_LOCKGUARD(ROOT::gCoreMutex);
722 R__COLLECTION_READ_GUARD();
724 return new TListIter(
this, dir);
730 TList::TObjLinkPtr_t TList::NewLink(TObject *obj,
const TObjLinkPtr_t &prev)
732 R__COLLECTION_WRITE_LOCKGUARD(ROOT::gCoreMutex);
733 R__COLLECTION_WRITE_GUARD();
735 auto newlink = std::make_shared<TObjLink>(obj);
737 InsertAfter(newlink, prev);
745 TList::TObjLinkPtr_t TList::NewOptLink(TObject *obj, Option_t *opt,
const TObjLinkPtr_t &prev)
747 R__COLLECTION_WRITE_LOCKGUARD(ROOT::gCoreMutex);
748 R__COLLECTION_WRITE_GUARD();
750 auto newlink = std::make_shared<TObjOptLink>(obj, opt);
752 InsertAfter(newlink, prev);
761 void TList::RecursiveRemove(TObject *obj)
763 R__COLLECTION_WRITE_GUARD();
770 auto cached = fCache.lock();
771 if (cached && cached->fNext.get() ==
nullptr && cached->fPrev.lock().get() ==
nullptr) {
772 TObject *ob = cached->GetObject();
773 if (ob && ob->TestBit(kNotDeleted)) {
774 ob->RecursiveRemove(obj);
786 TObject *ob = lnk->GetObject();
787 if (ob && ob->TestBit(kNotDeleted)) {
788 if (ob->IsEqual(obj)) {
789 lnk->SetObject(
nullptr);
795 fFirst->fPrev.reset();
797 }
else if (lnk == fLast) {
798 fLast = lnk->fPrev.lock();
799 fLast->fNext.reset();
802 lnk->Prev()->fNext = next;
803 lnk->Next()->fPrev = lnk->fPrev;
810 ob->RecursiveRemove(obj);
819 TObject *TList::Remove(TObject *obj)
821 R__COLLECTION_WRITE_GUARD();
826 TObjLink *lnk = FindLink(obj, idx);
833 R__COLLECTION_WRITE_LOCKGUARD(ROOT::gCoreMutex);
835 TObject *ob = lnk->GetObject();
836 lnk->SetObject(
nullptr);
837 if (lnk == fFirst.get()) {
841 if (lnk == fLast.get()) {
845 fFirst->fPrev.reset();
847 }
else if (lnk == fLast.get()) {
848 fLast = lnk->fPrev.lock();
849 fLast->fNext.reset();
852 lnk->Next()->fPrev = lnk->fPrev;
853 lnk->Prev()->fNext = lnk->fNext;
867 TObject *TList::Remove(TObjLink *lnk)
869 R__COLLECTION_WRITE_GUARD();
873 R__COLLECTION_WRITE_LOCKGUARD(ROOT::gCoreMutex);
875 TObject *obj = lnk->GetObject();
876 lnk->SetObject(
nullptr);
877 if (lnk == fFirst.get()) {
881 if (lnk == fLast.get()) {
885 fFirst->fPrev.reset();
887 }
else if (lnk == fLast.get()) {
888 fLast = lnk->fPrev.lock();
889 fLast->fNext.reset();
892 lnk->Next()->fPrev = lnk->fPrev;
893 lnk->Prev()->fNext = lnk->fNext;
906 void TList::RemoveLast()
908 R__COLLECTION_WRITE_LOCKGUARD(ROOT::gCoreMutex);
909 R__COLLECTION_WRITE_GUARD();
911 TObjLink *lnk = fLast.get();
914 lnk->SetObject(
nullptr);
915 if (lnk == fFirst.get()) {
919 fLast = lnk->fPrev.lock();
920 fLast->fNext.reset();
934 void TList::Sort(Bool_t order)
936 R__COLLECTION_WRITE_LOCKGUARD(ROOT::gCoreMutex);
937 R__COLLECTION_WRITE_GUARD();
943 if (!fFirst->GetObject()->IsSortable()) {
944 Error(
"Sort",
"objects in list are not sortable");
948 DoSort(&fFirst, fSize);
951 std::shared_ptr<TObjLink> ol, lnk = fFirst;
953 if (lnk.get()) lnk->fPrev.reset();
969 Bool_t TList::LnkCompare(
const TObjLinkPtr_t &l1,
const TObjLinkPtr_t &l2)
971 Int_t cmp = l1->GetObject()->Compare(l2->GetObject());
973 if ((IsAscending() && cmp <=0) || (!IsAscending() && cmp > 0))
981 std::shared_ptr<TObjLink> *TList::DoSort(std::shared_ptr<TObjLink> *head, Int_t n)
983 R__COLLECTION_WRITE_LOCKGUARD(ROOT::gCoreMutex);
984 R__COLLECTION_WRITE_GUARD();
986 std::shared_ptr<TObjLink> p1, p2, *h2, *t2;
993 return &((*head)->fNext);
996 p2 = (p1 = *head)->fNext;
997 if (LnkCompare(p1, p2))
return &(p2->fNext);
998 p1->fNext = (*head = p2)->fNext;
999 return &((p2->fNext = p1)->fNext);
1005 t2 = DoSort(h2 = DoSort(head, n), m);
1007 if (LnkCompare((p1 = *head), (p2 = *h2))) {
1009 if (!--n)
return *h2 = p2, t2;
1010 }
while (LnkCompare((p1 = *(head = &(p1->fNext))), p2));
1016 if (!--m)
return *h2 = *t2, *t2 = p1, h2;
1017 }
while (!LnkCompare(p1, (p2 = *(head = &(p2->fNext)))));
1020 if (!--n)
return *h2 = p2, t2;
1021 }
while (LnkCompare((p1 = *(head = &(p1->fNext))), p2));
1032 void TList::InsertAfter(
const TObjLinkPtr_t &newlink,
const TObjLinkPtr_t &prev)
1034 newlink->fNext = prev->fNext;
1035 newlink->fPrev = prev;
1036 prev->fNext = newlink;
1038 newlink->fNext->fPrev = newlink;
1045 ClassImp(TListIter);
1051 TListIter::TListIter(
const TList *l, Bool_t dir)
1052 : fList(l), fCurCursor(0), fCursor(0), fDirection(dir), fStarted(kFALSE)
1054 R__COLLECTION_ITER_GUARD(fList);
1060 TListIter::TListIter(
const TListIter &iter) : TIterator(iter)
1062 R__COLLECTION_ITER_GUARD(iter.fList);
1065 fCurCursor = iter.fCurCursor;
1066 fCursor = iter.fCursor;
1067 fDirection = iter.fDirection;
1068 fStarted = iter.fStarted;
1074 TIterator &TListIter::operator=(
const TIterator &rhs)
1077 const TListIter *rhs1 =
dynamic_cast<const TListIter *
>(&rhs);
1078 if (
this != &rhs && rhs1) {
1079 R__COLLECTION_ITER_GUARD(rhs1->fList);
1080 TIterator::operator=(rhs);
1081 fList = rhs1->fList;
1082 fCurCursor = rhs1->fCurCursor;
1083 fCursor = rhs1->fCursor;
1084 fDirection = rhs1->fDirection;
1085 fStarted = rhs1->fStarted;
1093 TListIter &TListIter::operator=(
const TListIter &rhs)
1096 R__COLLECTION_ITER_GUARD(rhs.fList);
1097 TIterator::operator=(rhs);
1099 fCurCursor = rhs.fCurCursor;
1100 fCursor = rhs.fCursor;
1101 fDirection = rhs.fDirection;
1102 fStarted = rhs.fStarted;
1110 TObject *TListIter::Next()
1112 if (!fList)
return 0;
1114 R__COLLECTION_ITER_GUARD(fList);
1116 if (fDirection == kIterForward) {
1118 fCursor = fList->fFirst;
1121 fCurCursor = fCursor;
1123 auto next = fCursor = fCursor->NextSP();
1127 fCursor = fList->fLast;
1130 fCurCursor = fCursor;
1131 if (fCursor) fCursor = fCursor->PrevSP();
1134 if (fCurCursor)
return fCurCursor->GetObject();
1141 Option_t *TListIter::GetOption()
const
1143 if (fCurCursor)
return fCurCursor->GetOption();
1150 void TListIter::SetOption(Option_t *option)
1152 if (fCurCursor) fCurCursor->SetOption(option);
1158 void TListIter::Reset()
1160 R__COLLECTION_ITER_GUARD(fList);
1167 Bool_t TListIter::operator!=(
const TIterator &aIter)
const
1169 if (IsA() == aIter.IsA()) {
1173 const TListIter &iter(dynamic_cast<const TListIter &>(aIter));
1174 return (fCurCursor != iter.fCurCursor);
1182 Bool_t TListIter::operator!=(
const TListIter &aIter)
const
1184 return (fCurCursor != aIter.fCurCursor);
1190 void TList::Streamer(TBuffer &b)
1192 R__COLLECTION_WRITE_GUARD();
1200 if (b.IsReading()) {
1202 Version_t v = b.ReadVersion(&R__s, &R__c);
1204 TObject::Streamer(b);
1208 for (Int_t i = 0; i < nobjects; i++) {
1211 if (v > 4 && nch == 255) {
1216 readOption.resize(nbig,
'\0');
1217 b.ReadFastArray((
char*) readOption.data(),nbig);
1220 Add(obj,readOption.c_str());
1226 b.CheckByteCount(R__s, R__c,TList::IsA());
1232 TObject::Streamer(b);
1236 for (Int_t i = 0; i < nobjects; i++) {
1240 b.CheckByteCount(R__s, R__c,TList::IsA());
1243 R__COLLECTION_READ_LOCKGUARD(ROOT::gCoreMutex);
1245 R__c = b.WriteVersion(TList::IsA(), kTRUE);
1246 TObject::Streamer(b);
1248 nobjects = GetSize();
1251 TObjLink *lnk = fFirst.get();
1253 obj = lnk->GetObject();
1256 nbig = strlen(lnk->GetAddOption());
1262 nch = UChar_t(nbig);
1265 b.WriteFastArray(lnk->GetAddOption(),nbig);
1269 b.SetByteCount(R__c, kTRUE);