47 ClassImp(RooLinkedList);
49 namespace RooLinkedListImplDetails {
55 _sz(sz), _free(capacity()),
56 _chunk(new RooLinkedListElem[_free]), _freelist(_chunk)
60 for (Int_t i = 0; i < _free; ++i)
61 _chunk[i]._next = (i + 1 < _free) ? &_chunk[i + 1] : 0;
64 ~Chunk() {
delete[] _chunk; }
66 Int_t capacity()
const
67 {
return (1 << _sz) /
sizeof(RooLinkedListElem); }
69 Int_t free()
const {
return _free; }
71 Int_t size()
const {
return capacity() - free(); }
73 int szclass()
const {
return _sz; }
75 bool full()
const {
return !free(); }
77 bool empty()
const {
return capacity() == free(); }
79 const void* chunkaddr()
const {
return _chunk; }
81 bool contains(RooLinkedListElem* el)
const
82 {
return _chunk <= el && el < &_chunk[capacity()]; }
84 RooLinkedListElem* pop_free_elem()
86 if (!_freelist)
return 0;
87 RooLinkedListElem* retVal = _freelist;
88 _freelist = retVal->_next;
89 retVal->_arg = 0; retVal->_refCount = 0;
90 retVal->_prev = retVal->_next = 0;
95 void push_free_elem(RooLinkedListElem* el)
97 el->_next = _freelist;
104 RooLinkedListElem* _chunk;
105 RooLinkedListElem* _freelist;
110 Chunk& operator=(
const Chunk&);
121 typedef RooLinkedListImplDetails::Chunk Chunk;
122 typedef std::list<Chunk*> ChunkList;
123 typedef std::map<const void*, Chunk*> AddrMap;
130 inline void acquire() { ++_refCount; }
132 inline bool release() {
return 0 == --_refCount; }
134 RooLinkedListElem* pop_free_elem();
136 void push_free_elem(RooLinkedListElem* el);
140 UInt_t _szmap[(maxsz - minsz) / szincr];
145 void updateCurSz(Int_t sz, Int_t incr);
147 Int_t nextChunkSz()
const;
150 Pool::Pool() : _cursz(minsz), _refCount(0)
152 std::fill(_szmap, _szmap + ((maxsz - minsz) / szincr), 0);
158 for (AddrMap::iterator it = _addrmap.begin(); _addrmap.end() != it; ++it)
163 RooLinkedListElem* Pool::pop_free_elem()
165 if (_freelist.empty()) {
167 const Int_t sz = nextChunkSz();
168 Chunk *c =
new Chunk(sz);
169 _addrmap[c->chunkaddr()] = c;
170 _freelist.push_back(c);
174 Chunk* c = _freelist.front();
175 RooLinkedListElem* retVal = c->pop_free_elem();
177 if (c->full()) _freelist.pop_front();
181 void Pool::push_free_elem(RooLinkedListElem* el)
184 AddrMap::iterator ci = _addrmap.end();
185 if (!_addrmap.empty()) {
186 ci = _addrmap.lower_bound(el);
187 if (ci == _addrmap.end()) {
189 ci = (++_addrmap.rbegin()).base();
193 if (_addrmap.begin() != ci && ci->first != el) --ci;
198 if (_addrmap.empty() || !ci->second->contains(el)) {
203 Chunk *c = ci->second;
204 const bool moveToFreelist = c->full();
205 c->push_free_elem(el);
208 ChunkList::iterator it = std::find( _freelist.begin(), _freelist.end(), c);
209 if (_freelist.end() != it) _freelist.erase(it);
210 _addrmap.erase(ci->first);
211 updateCurSz(c->szclass(), -1);
213 }
else if (moveToFreelist) {
214 _freelist.push_back(c);
218 void Pool::updateCurSz(Int_t sz, Int_t incr)
220 _szmap[(sz - minsz) / szincr] += incr;
222 for (
int i = (maxsz - minsz) / szincr; i--; ) {
224 _cursz += i * szincr;
230 Int_t Pool::nextChunkSz()
const
234 if (_addrmap.empty()) {
242 if (1 != _addrmap.size()) {
252 if (sz > maxsz) sz = maxsz;
253 if (sz < minsz) sz = minsz;
258 RooLinkedList::Pool* RooLinkedList::_pool = 0;
262 RooLinkedList::RooLinkedList(Int_t htsize) :
263 _hashThresh(htsize), _size(0), _first(0), _last(0), _htableName(0), _htableLink(0), _useNptr(kTRUE)
265 if (!_pool) _pool =
new Pool;
272 RooLinkedList::RooLinkedList(
const RooLinkedList& other) :
273 TObject(other), _hashThresh(other._hashThresh), _size(0), _first(0), _last(0), _htableName(0), _htableLink(0),
275 _useNptr(other._useNptr)
277 if (!_pool) _pool =
new Pool;
279 if (other._htableName) _htableName =
new RooHashTable(other._htableName->size()) ;
280 if (other._htableLink) _htableLink =
new RooHashTable(other._htableLink->size(),RooHashTable::Pointer) ;
281 for (RooLinkedListElem* elem = other._first; elem; elem = elem->_next) {
282 Add(elem->_arg, elem->_refCount) ;
289 RooLinkedListElem* RooLinkedList::createElement(TObject* obj, RooLinkedListElem* elem)
291 RooLinkedListElem* ret = _pool->pop_free_elem();
292 ret->init(obj, elem);
298 void RooLinkedList::deleteElement(RooLinkedListElem* elem)
301 _pool->push_free_elem(elem);
308 RooLinkedList& RooLinkedList::operator=(
const RooLinkedList& other)
311 if (&other==
this)
return *this ;
316 for (RooLinkedListElem* elem = other._first; elem; elem = elem->_next) {
327 void RooLinkedList::setHashTableSize(Int_t size)
330 coutE(InputArguments) <<
"RooLinkedList::setHashTable() ERROR size must be positive" << endl ;
347 if (_htableName)
delete _htableName ;
348 _htableName =
new RooHashTable(size) ;
350 if (_htableLink)
delete _htableLink ;
351 _htableLink =
new RooHashTable(size,RooHashTable::Pointer) ;
354 RooLinkedListElem* ptr = _first ;
356 _htableName->add(ptr->_arg) ;
357 _htableLink->add((TObject*)ptr,ptr->_arg) ;
366 RooLinkedList::~RooLinkedList()
369 ROOT::CallRecursiveRemoveIfNeeded(*
this);
381 if (_pool->release()) {
390 RooLinkedListElem* RooLinkedList::findLink(
const TObject* arg)
const
393 return _htableLink->findLinkTo(arg) ;
396 RooLinkedListElem* ptr = _first;
398 if (ptr->_arg == arg) {
410 void RooLinkedList::Add(TObject* arg, Int_t refCount)
415 if (!dynamic_cast<RooAbsArg*>(arg)) _useNptr = kFALSE;
421 if (_size > _htableName->size()) {
422 setHashTableSize(_size*2) ;
425 }
else if (_hashThresh>0 && _size>_hashThresh) {
427 setHashTableSize(_hashThresh) ;
432 _last = createElement(arg,_last) ;
435 _last = createElement(arg) ;
441 _htableName->add(arg) ;
442 _htableLink->add((TObject*)_last,arg) ;
446 _last->_refCount = refCount ;
448 _at.push_back(_last);
454 Bool_t RooLinkedList::Remove(TObject* arg)
457 RooLinkedListElem* elem = findLink(arg) ;
458 if (!elem)
return kFALSE ;
462 _htableName->remove(arg) ;
465 _htableLink->remove((TObject*)elem,arg) ;
469 if (elem==_first) _first=elem->_next ;
470 if (elem==_last) _last=elem->_prev ;
473 auto at_elem_it = std::find(_at.begin(), _at.end(), elem);
474 _at.erase(at_elem_it);
478 deleteElement(elem) ;
486 void RooLinkedList::RecursiveRemove(TObject *obj)
495 TObject* RooLinkedList::At(Int_t index)
const
498 if (index<0 || index>=_size)
return 0 ;
500 return _at[index]->_arg;
515 Bool_t RooLinkedList::Replace(
const TObject* oldArg,
const TObject* newArg)
518 RooLinkedListElem* elem = findLink(oldArg) ;
519 if (!elem)
return kFALSE ;
522 _htableName->replace(oldArg,newArg) ;
526 _htableLink->remove((TObject*)elem,(TObject*)oldArg) ;
527 _htableLink->add((TObject*)elem,(TObject*)newArg) ;
530 elem->_arg = (TObject*)newArg ;
538 TObject* RooLinkedList::FindObject(
const char* name)
const
547 TObject* RooLinkedList::FindObject(
const TObject* obj)
const
549 RooLinkedListElem *elem = findLink((TObject*)obj) ;
550 return elem ? elem->_arg : 0 ;
556 void RooLinkedList::Clear(Option_t *)
558 for (RooLinkedListElem *elem = _first, *next; elem; elem = next) {
560 deleteElement(elem) ;
567 Int_t hsize = _htableName->size() ;
569 _htableName =
new RooHashTable(hsize) ;
572 Int_t hsize = _htableLink->size() ;
574 _htableLink =
new RooHashTable(hsize,RooHashTable::Pointer) ;
586 void RooLinkedList::Delete(Option_t *)
588 RooLinkedListElem* elem = _first;
590 RooLinkedListElem* next = elem->_next ;
592 deleteElement(elem) ;
600 Int_t hsize = _htableName->size() ;
602 _htableName =
new RooHashTable(hsize) ;
605 Int_t hsize = _htableLink->size() ;
607 _htableLink =
new RooHashTable(hsize,RooHashTable::Pointer) ;
618 TObject* RooLinkedList::find(
const char* name)
const
622 RooAbsArg* a = (RooAbsArg*) _htableName->find(name) ;
628 const TNamed* nptr= RooNameReg::known(name);
630 if (nptr && nptr->TestBit(RooNameReg::kRenamedArg)) {
631 RooLinkedListElem* ptr = _first ;
633 if ((((RooAbsArg*)ptr->_arg)->namePtr() == nptr)) {
644 RooLinkedListElem* ptr = _first ;
648 if (_useNptr && _size>9) {
649 const TNamed* nptr= RooNameReg::known(name);
653 if ((((RooAbsArg*)ptr->_arg)->namePtr() == nptr)) {
662 if (!strcmp(ptr->_arg->GetName(),name)) {
674 RooAbsArg* RooLinkedList::findArg(
const RooAbsArg* arg)
const
677 RooAbsArg* a = (RooAbsArg*) _htableName->findArg(arg) ;
681 if (!arg->namePtr()->TestBit(RooNameReg::kRenamedArg))
return 0;
684 RooLinkedListElem* ptr = _first ;
685 const TNamed* nptr = arg->namePtr();
687 if (((RooAbsArg*)(ptr->_arg))->namePtr() == nptr) {
688 return (RooAbsArg*) ptr->_arg ;
699 Int_t RooLinkedList::IndexOf(
const TObject* arg)
const
701 RooLinkedListElem* ptr = _first;
704 if (ptr->_arg==arg)
return idx ;
715 Int_t RooLinkedList::IndexOf(
const char* name)
const
717 RooLinkedListElem* ptr = _first;
720 if (strcmp(ptr->_arg->GetName(),name)==0)
return idx ;
731 void RooLinkedList::Print(
const char* opt)
const
733 RooLinkedListElem* elem = _first ;
735 cout << elem->_arg <<
" : " ;
736 elem->_arg->Print(opt) ;
746 TIterator* RooLinkedList::MakeIterator(Bool_t forward)
const {
747 auto iterImpl = std::make_unique<RooLinkedListIterImpl>(
this, forward);
748 return new RooLinkedListIter(std::move(iterImpl));
756 RooLinkedListIter RooLinkedList::iterator(Bool_t forward)
const {
757 auto iterImpl = std::make_unique<RooLinkedListIterImpl>(
this, forward);
758 return RooLinkedListIter(std::move(iterImpl));
765 RooFIter RooLinkedList::fwdIterator()
const {
766 auto iterImpl = std::make_unique<RooFIterForLinkedList>(
this);
767 return RooFIter(std::move(iterImpl));
772 void RooLinkedList::Sort(Bool_t ascend)
774 if (ascend) _first = mergesort_impl<true>(_first, _size, &_last);
775 else _first = mergesort_impl<false>(_first, _size, &_last);
778 RooLinkedListElem* elem = _first;
779 for (
auto it = _at.begin(); it != _at.end(); ++it, elem = elem->_next) {
787 template <
bool ascending>
788 RooLinkedListElem* RooLinkedList::mergesort_impl(
789 RooLinkedListElem* l1,
const unsigned sz, RooLinkedListElem** tail)
793 if (tail) *tail = l1;
798 #if !defined(_WIN32) && !defined(R__SOLARIS_CC50)
799 RooLinkedListElem *arr[sz];
800 #else // _WIN32 && Solaris
804 RooLinkedListElem *arr[16];
806 for (
int i = 0; l1; l1 = l1->_next, ++i) arr[i] = l1;
812 RooLinkedListElem *tmp = arr[i];
814 const bool inOrder = ascending ?
815 (tmp->_arg->Compare(arr[j]->_arg) <= 0) :
816 (arr[j]->_arg->Compare(tmp->_arg) <= 0);
823 }
while (
int(sz) != i);
826 arr[0]->_prev = arr[sz - 1]->_next = 0;
827 for (
int i = 0; i < int(sz - 1); ++i) {
828 arr[i]->_next = arr[i + 1];
829 arr[i + 1]->_prev = arr[i];
831 if (tail) *tail = arr[sz - 1];
835 RooLinkedListElem *l2 = l1;
836 for (RooLinkedListElem *end = l2; end->_next; end = end->_next) {
839 if (!end->_next)
break;
842 l2->_prev->_next = 0;
845 if (l1->_next) l1 = mergesort_impl<ascending>(l1, sz / 2);
846 if (l2->_next) l2 = mergesort_impl<ascending>(l2, sz - sz / 2);
849 RooLinkedListElem *l = (ascending ? (l1->_arg->Compare(l2->_arg) <= 0) :
850 (l2->_arg->Compare(l1->_arg) <= 0)) ? l1 : l2;
851 RooLinkedListElem *t = l;
853 RooLinkedListElem* tmp = l1;
859 const bool inOrder = ascending ? (l1->_arg->Compare(l2->_arg) <= 0) :
860 (l2->_arg->Compare(l1->_arg) <= 0);
864 l1->_prev->_next = l2;
865 l2->_prev = l1->_prev;
868 RooLinkedListElem *tmp = l1;
879 if (t) t->_next = l2;
883 for (l1 = t; l1; l1 = l1->_next) t = l1;
903 void RooLinkedList::Streamer(TBuffer &R__b)
905 if (R__b.IsReading()) {
907 Version_t v = R__b.ReadVersion();
909 TObject::Streamer(R__b);
920 if (v > 1 && v < 4) {
925 R__b.WriteVersion(RooLinkedList::IsA());
926 TObject::Streamer(R__b);
929 RooLinkedListElem* ptr = _first;