Logo ROOT  
Reference Guide
 
Loading...
Searching...
No Matches
RooLinkedList.cxx
Go to the documentation of this file.
1/*****************************************************************************
2 * Project: RooFit *
3 * Package: RooFitCore *
4 * @(#)root/roofitcore:$Id$
5 * Authors: *
6 * WV, Wouter Verkerke, UC Santa Barbara, verkerke@slac.stanford.edu *
7 * DK, David Kirkby, UC Irvine, dkirkby@uci.edu *
8 * *
9 * Copyright (c) 2000-2005, Regents of the University of California *
10 * and Stanford University. All rights reserved. *
11 * *
12 * Redistribution and use in source and binary forms, *
13 * with or without modification, are permitted according to the terms *
14 * listed in LICENSE (http://roofit.sourceforge.net/license.txt) *
15 *****************************************************************************/
16
17/**
18\file RooLinkedList.cxx
19\class RooLinkedList
20\ingroup Roofitcore
21
22RooLinkedList is an collection class for internal use, storing
23a collection of RooAbsArg pointers in a doubly linked list.
24It can optionally add a hash table to speed up random access
25in large collections
26Use RooAbsCollection derived objects for public use
27(e.g. RooArgSet or RooArgList)
28**/
29
30#include "RooLinkedList.h"
31
32#include "RooFit.h"
33#include "RooLinkedListIter.h"
34#include "RooAbsArg.h"
35#include "RooAbsData.h"
36#include "RooMsgService.h"
37
38#include "Riostream.h"
39#include "TBuffer.h"
40#include "TROOT.h"
41
42#include <algorithm>
43#include <list>
44#include <memory>
45#include <vector>
46
47using namespace std;
48
50;
52 /// a chunk of memory in a pool for quick allocation of RooLinkedListElems
53 class Chunk {
54 public:
55 /// constructor
57 _sz(sz), _free(capacity()),
59 {
60 //cout << "RLLID::Chunk ctor(" << this << ") of size " << _free << " list elements" << endl ;
61 // initialise free list
62 for (Int_t i = 0; i < _free; ++i)
63 _chunk[i]._next = (i + 1 < _free) ? &_chunk[i + 1] : 0;
64 }
65 /// destructor
66 ~Chunk() { delete[] _chunk; }
67 /// chunk capacity
69 { return (1 << _sz) / sizeof(RooLinkedListElem); }
70 /// chunk free elements
71 Int_t free() const { return _free; }
72 /// chunk occupied elements
73 Int_t size() const { return capacity() - free(); }
74 /// return size class
75 int szclass() const { return _sz; }
76 /// chunk full?
77 bool full() const { return !free(); }
78 /// chunk empty?
79 bool empty() const { return capacity() == free(); }
80 /// return address of chunk
81 const void* chunkaddr() const { return _chunk; }
82 /// check if el is in this chunk
84 { return _chunk <= el && el < &_chunk[capacity()]; }
85 /// pop a free element off the free list
87 {
88 if (!_freelist) return 0;
90 _freelist = retVal->_next;
91 retVal->_arg = 0; retVal->_refCount = 0;
92 retVal->_prev = retVal->_next = 0;
93 --_free;
94 return retVal;
95 }
96 /// push a free element back onto the freelist
98 {
99 el->_next = _freelist;
100 _freelist = el;
101 ++_free;
102 }
103 private:
104 Int_t _sz; ///< chunk capacity
105 Int_t _free; ///< length of free list
106 RooLinkedListElem* _chunk; ///< chunk from which elements come
107 RooLinkedListElem* _freelist; ///< list of free elements
108
109 /// forbid copying
110 Chunk(const Chunk&);
111 // forbid assignment
113 };
114
115 class Pool {
116 private:
117 enum {
118 minsz = 7, ///< minimum chunk size (just below 1 << minsz bytes)
119 maxsz = 18, ///< maximum chunk size (just below 1 << maxsz bytes)
120 szincr = 1 ///< size class increment (sz = 1 << (minsz + k * szincr))
121 };
122 /// a chunk of memory in the pool
124 typedef std::list<Chunk*> ChunkList;
125 typedef std::map<const void*, Chunk*> AddrMap;
126 public:
127 /// constructor
128 Pool();
129 /// destructor
130 ~Pool();
131 /// acquire the pool
132 inline void acquire() { ++_refCount; }
133 /// release the pool, return true if the pool is unused
134 inline bool release() { return 0 == --_refCount; }
135 /// pop a free element out of the pool
137 /// push a free element back into the pool
139 private:
145
146 /// adjust _cursz to current largest block
147 void updateCurSz(Int_t sz, Int_t incr);
148 /// find size of next chunk to allocate (in a hopefully smart way)
149 Int_t nextChunkSz() const;
150 };
151
152 Pool::Pool() : _cursz(minsz), _refCount(0)
153 {
154 std::fill(_szmap, _szmap + ((maxsz - minsz) / szincr), 0);
155 }
156
158 {
159 _freelist.clear();
160 for (AddrMap::iterator it = _addrmap.begin(); _addrmap.end() != it; ++it)
161 delete it->second;
162 _addrmap.clear();
163 }
164
166 {
167 if (_freelist.empty()) {
168 // allocate and register new chunk and put it on the freelist
169 const Int_t sz = nextChunkSz();
170 Chunk *c = new Chunk(sz);
171 _addrmap[c->chunkaddr()] = c;
172 _freelist.push_back(c);
173 updateCurSz(sz, +1);
174 }
175 // get free element from first chunk on _freelist
176 Chunk* c = _freelist.front();
177 RooLinkedListElem* retVal = c->pop_free_elem();
178 // full chunks are removed from _freelist
179 if (c->full()) _freelist.pop_front();
180 return retVal;
181 }
182
184 {
185 // find from which chunk el came
186 AddrMap::iterator ci = _addrmap.end();
187 if (!_addrmap.empty()) {
188 ci = _addrmap.lower_bound(el);
189 if (ci == _addrmap.end()) {
190 // point beyond last element, so get last one
191 ci = (++_addrmap.rbegin()).base();
192 } else {
193 // valid ci, check if we need to decrement ci because el isn't the
194 // first element in the chunk
195 if (_addrmap.begin() != ci && ci->first != el) --ci;
196 }
197 }
198 // either empty addressmap, or ci should now point to the chunk which might
199 // contain el
200 if (_addrmap.empty() || !ci->second->contains(el)) {
201 // el is not in any chunk we know about, so just delete it
202 delete el;
203 return;
204 }
205 Chunk *c = ci->second;
206 const bool moveToFreelist = c->full();
207 c->push_free_elem(el);
208 if (c->empty()) {
209 // delete chunk if all empty
210 ChunkList::iterator it = std::find( _freelist.begin(), _freelist.end(), c);
211 if (_freelist.end() != it) _freelist.erase(it);
212 _addrmap.erase(ci->first);
213 updateCurSz(c->szclass(), -1);
214 delete c;
215 } else if (moveToFreelist) {
216 _freelist.push_back(c);
217 }
218 }
219
221 {
222 _szmap[(sz - minsz) / szincr] += incr;
223 _cursz = minsz;
224 for (int i = (maxsz - minsz) / szincr; i--; ) {
225 if (_szmap[i]) {
226 _cursz += i * szincr;
227 break;
228 }
229 }
230 }
231
233 {
234 // no chunks with space available, figure out chunk size
235 Int_t sz = _cursz;
236 if (_addrmap.empty()) {
237 // if we start allocating chunks, we start from minsz
238 sz = minsz;
239 } else {
240 if (minsz >= sz) {
241 // minimal sized chunks are always grown
242 sz = minsz + szincr;
243 } else {
244 if (1 != _addrmap.size()) {
245 // if we have more than one completely filled chunk, grow
246 sz += szincr;
247 } else {
248 // just one chunk left, try shrinking chunk size
249 sz -= szincr;
250 }
251 }
252 }
253 // clamp size to allowed range
254 if (sz > maxsz) sz = maxsz;
255 if (sz < minsz) sz = minsz;
256 return sz;
257 }
258}
259
261
262////////////////////////////////////////////////////////////////////////////////
263
265 _hashThresh(htsize), _size(0), _first(0), _last(0), _htableName(nullptr), _htableLink(nullptr), _useNptr(true)
266{
267 if (!_pool) _pool = new Pool;
268 _pool->acquire();
269}
270
271////////////////////////////////////////////////////////////////////////////////
272/// Copy constructor
273
275 TObject(other), _hashThresh(other._hashThresh), _size(0), _first(0), _last(0), _htableName(nullptr), _htableLink(nullptr),
276 _name(other._name),
277 _useNptr(other._useNptr)
278{
279 if (!_pool) _pool = new Pool;
280 _pool->acquire();
281 if (other._htableName) _htableName = std::make_unique<HashTableByName>(other._htableName->size()) ;
282 if (other._htableLink) _htableLink = std::make_unique<HashTableByLink>(other._htableLink->size()) ;
283 for (RooLinkedListElem* elem = other._first; elem; elem = elem->_next) {
284 Add(elem->_arg, elem->_refCount) ;
285 }
286}
287
288////////////////////////////////////////////////////////////////////////////////
289/// cout << "RooLinkedList::createElem(" << this << ") obj = " << obj << " elem = " << elem << endl ;
290
292{
294 ret->init(obj, elem);
295 return ret ;
296}
297
298////////////////////////////////////////////////////////////////////////////////
299
301{
302 elem->release() ;
303 _pool->push_free_elem(elem);
304 //delete elem ;
305}
306
307////////////////////////////////////////////////////////////////////////////////
308/// Assignment operator, copy contents from 'other'
309
311{
312 // Prevent self-assignment
313 if (&other==this) return *this ;
314
315 // remove old elements
316 Clear();
317 // Copy elements
318 for (RooLinkedListElem* elem = other._first; elem; elem = elem->_next) {
319 Add(elem->_arg) ;
320 }
321
322 return *this ;
323}
324
325////////////////////////////////////////////////////////////////////////////////
326/// Change the threshold for hash-table use to given size.
327/// If a hash table exists when this method is called, it is regenerated.
328
330{
331 if (size<0) {
332 coutE(InputArguments) << "RooLinkedList::setHashTable() ERROR size must be positive" << endl ;
333 return ;
334 }
335 if (size==0) {
336 if (!_htableName) {
337 // No hash table present
338 return ;
339 } else {
340 // Remove existing hash table
341 _htableName.reset(nullptr);
342 _htableLink.reset(nullptr);
343 }
344 } else {
345
346 // (Re)create hash tables
347 _htableName = std::make_unique<HashTableByName>(size) ;
348 _htableLink = std::make_unique<HashTableByLink>(size) ;
349
350 // Fill hash table with existing entries
352 while(ptr) {
353 _htableName->insert({ptr->_arg->GetName(), ptr->_arg}) ;
354 _htableLink->insert({ptr->_arg, (TObject*)ptr}) ;
355 ptr = ptr->_next ;
356 }
357 }
358}
359
360////////////////////////////////////////////////////////////////////////////////
361/// Destructor
362
364{
365 // Required since we overload TObject::Hash.
367
368 _htableName.reset(nullptr);
369 _htableLink.reset(nullptr);
370
371 Clear() ;
372 if (_pool->release()) {
373 delete _pool;
374 _pool = 0;
375 }
376}
377
378////////////////////////////////////////////////////////////////////////////////
379/// Find the element link containing the given object
380
382{
383 if (_htableLink) {
384 auto found = _htableLink->find(arg);
385 if (found == _htableLink->end()) return nullptr;
386 return (RooLinkedListElem*)found->second;
387 }
388
390 while(ptr) {
391 if (ptr->_arg == arg) {
392 return ptr ;
393 }
394 ptr = ptr->_next ;
395 }
396 return 0 ;
397
398}
399
400////////////////////////////////////////////////////////////////////////////////
401/// Insert object into collection with given reference count value
402
403void RooLinkedList::Add(TObject* arg, Int_t refCount)
404{
405 if (!arg) return ;
406
407 // Only use RooAbsArg::namePtr() in lookup-by-name if all elements have it
408 if (!dynamic_cast<RooAbsArg*>(arg) && !dynamic_cast<RooAbsData*>(arg)) _useNptr = false;
409
410 // Add to hash table
411 if (_htableName) {
412
413 // Expand capacity of hash table if #entries>#slots
414 if (static_cast<size_t>(_size) > _htableName->size()) {
416 }
417
418 } else if (_hashThresh>0 && _size>_hashThresh) {
419
421 }
422
423 if (_last) {
424 // Append element at end of list
425 _last = createElement(arg,_last) ;
426 } else {
427 // Append first element, set first,last
428 _last = createElement(arg) ;
429 _first=_last ;
430 }
431
432 if (_htableName){
433 //cout << "storing link " << _last << " with hash arg " << arg << endl ;
434 _htableName->insert({arg->GetName(), arg});
435 _htableLink->insert({arg, (TObject*)_last});
436 }
437
438 _size++ ;
439 _last->_refCount = refCount ;
440
441 _at.push_back(_last);
442}
443
444////////////////////////////////////////////////////////////////////////////////
445/// Remove object from collection
446
448{
449 // Find link element
450 RooLinkedListElem* elem = findLink(arg) ;
451 if (!elem) return false ;
452
453 // Remove from hash table
454 if (_htableName) {
455 _htableName->erase(arg->GetName()) ;
456 }
457 if (_htableLink) {
458 _htableLink->erase(arg) ;
459 }
460
461 // Update first,last if necessary
462 if (elem==_first) _first=elem->_next ;
463 if (elem==_last) _last=elem->_prev ;
464
465 // Remove from index array
466 auto at_elem_it = std::find(_at.begin(), _at.end(), elem);
467 _at.erase(at_elem_it);
468
469 // Delete and shrink
470 _size-- ;
471 deleteElement(elem) ;
472 return true ;
473}
474
475////////////////////////////////////////////////////////////////////////////////
476/// If one of the TObject we have a referenced to is deleted, remove the
477/// reference.
478
480{
481 Remove(obj); // This is a nop if the obj is not in the collection.
482}
483
484////////////////////////////////////////////////////////////////////////////////
485/// Return object stored in sequential position given by index.
486/// If index is out of range, a null pointer is returned.
487
489{
490 // Check range
491 if (index<0 || index>=_size) return 0 ;
492
493 return _at[index]->_arg;
494//
495//
496// // Walk list
497// RooLinkedListElem* ptr = _first;
498// while(index--) ptr = ptr->_next ;
499//
500// // Return arg
501// return ptr->_arg ;
502}
503
504////////////////////////////////////////////////////////////////////////////////
505/// Replace object 'oldArg' in collection with new object 'newArg'.
506/// If 'oldArg' is not found in collection false is returned
507
508Bool_t RooLinkedList::Replace(const TObject* oldArg, const TObject* newArg)
509{
510 // Find existing element and replace arg
511 RooLinkedListElem* elem = findLink(oldArg) ;
512 if (!elem) return false ;
513
514 if (_htableName) {
515 _htableName->erase(oldArg->GetName());
516 _htableName->insert({newArg->GetName(), newArg});
517 }
518 if (_htableLink) {
519 // Link is hashed by contents and may change slot in hash table
520 _htableLink->erase(oldArg) ;
521 _htableLink->insert({newArg, (TObject*)elem}) ;
522 }
523
524 elem->_arg = (TObject*)newArg ;
525 return true ;
526}
527
528////////////////////////////////////////////////////////////////////////////////
529/// Return pointer to obejct with given name. If no such object
530/// is found return a null pointer
531
533{
534 return find(name) ;
535}
536
537////////////////////////////////////////////////////////////////////////////////
538/// Find object in list. If list contains object return
539/// (same) pointer to object, otherwise return null pointer
540
542{
543 RooLinkedListElem *elem = findLink((TObject*)obj) ;
544 return elem ? elem->_arg : 0 ;
545}
546
547////////////////////////////////////////////////////////////////////////////////
548/// Remove all elements from collection
549
551{
552 for (RooLinkedListElem *elem = _first, *next; elem; elem = next) {
553 next = elem->_next ;
554 deleteElement(elem) ;
555 }
556 _first = 0 ;
557 _last = 0 ;
558 _size = 0 ;
559
560 if (_htableName) {
561 _htableName = std::make_unique<HashTableByName>(_htableName->size()) ;
562 }
563 if (_htableLink) {
564 _htableLink = std::make_unique<HashTableByLink>(_htableLink->size()) ;
565 }
566
567 // empty index array
568 _at.clear();
569}
570
571////////////////////////////////////////////////////////////////////////////////
572/// Remove all elements in collection and delete all elements
573/// NB: Collection does not own elements, this function should
574/// be used judiciously by caller.
575
577{
579 while(elem) {
580 RooLinkedListElem* next = elem->_next ;
581 delete elem->_arg ;
582 deleteElement(elem) ;
583 elem = next ;
584 }
585 _first = 0 ;
586 _last = 0 ;
587 _size = 0 ;
588
589 if (_htableName) {
590 _htableName = std::make_unique<HashTableByName>(_htableName->size()) ;
591 }
592 if (_htableLink) {
593 _htableLink = std::make_unique<HashTableByLink>(_htableLink->size()) ;
594 }
595
596 // empty index array
597 _at.clear();
598}
599
600////////////////////////////////////////////////////////////////////////////////
601/// Return pointer to object with given name in collection.
602/// If no such object is found, return null pointer.
603
604TObject* RooLinkedList::find(const char* name) const
605{
606
607 if (_htableName) {
608 auto found = _htableName->find(name);
609 TObject *a = found != _htableName->end() ? const_cast<TObject*>(found->second) : nullptr;
610 // RooHashTable::find could return false negative if element was renamed to 'name'.
611 // The list search means it won't return false positive, so can return here.
612 if (a) return a;
613 if (_useNptr) {
614 // See if it might have been renamed
615 const TNamed* nptr= RooNameReg::known(name);
616 //cout << "RooLinkedList::find: possibly renamed '" << name << "', kRenamedArg=" << (nptr&&nptr->TestBit(RooNameReg::kRenamedArg)) << endl;
617 if (nptr && nptr->TestBit(RooNameReg::kRenamedArg)) {
619 while(ptr) {
620 if ( (dynamic_cast<RooAbsArg*>(ptr->_arg) && static_cast<RooAbsArg*>(ptr->_arg)->namePtr() == nptr) ||
621 (dynamic_cast<RooAbsData*>(ptr->_arg) && static_cast<RooAbsData*>(ptr->_arg)->namePtr() == nptr)) {
622 return ptr->_arg ;
623 }
624 ptr = ptr->_next ;
625 }
626 }
627 return nullptr ;
628 }
629 //cout << "RooLinkedList::find: possibly renamed '" << name << "'" << endl;
630 }
631
633
634 // The penalty for RooNameReg lookup seems to be outweighted by the faster search
635 // when the size list is longer than ~7, but let's be a bit conservative.
636 if (_useNptr && _size>9) {
637 const TNamed* nptr= RooNameReg::known(name);
638 if (!nptr) return nullptr;
639
640 while(ptr) {
641 if ( (dynamic_cast<RooAbsArg*>(ptr->_arg) && static_cast<RooAbsArg*>(ptr->_arg)->namePtr() == nptr) ||
642 (dynamic_cast<RooAbsData*>(ptr->_arg) && static_cast<RooAbsData*>(ptr->_arg)->namePtr() == nptr)) {
643 return ptr->_arg ;
644 }
645 ptr = ptr->_next ;
646 }
647 return nullptr ;
648 }
649
650 while(ptr) {
651 if (!strcmp(ptr->_arg->GetName(),name)) {
652 return ptr->_arg ;
653 }
654 ptr = ptr->_next ;
655 }
656 return nullptr ;
657}
658
659////////////////////////////////////////////////////////////////////////////////
660/// Return pointer to object with given name in collection.
661/// If no such object is found, return null pointer.
662
664{
665 if (_htableName) {
666 RooAbsArg* a = (RooAbsArg*) (*_htableName)[arg->GetName()] ;
667 if (a) return a;
668 //cout << "RooLinkedList::findArg: possibly renamed '" << arg->GetName() << "', kRenamedArg=" << arg->namePtr()->TestBit(RooNameReg::kRenamedArg) << endl;
669 // See if it might have been renamed
670 if (!arg->namePtr()->TestBit(RooNameReg::kRenamedArg)) return 0;
671 }
672
674 const TNamed* nptr = arg->namePtr();
675 while(ptr) {
676 if (((RooAbsArg*)(ptr->_arg))->namePtr() == nptr) {
677 return (RooAbsArg*) ptr->_arg ;
678 }
679 ptr = ptr->_next ;
680 }
681 return 0 ;
682}
683
684////////////////////////////////////////////////////////////////////////////////
685/// Return position of given object in list. If object
686/// is not contained in list, return -1
687
689{
691 Int_t idx(0) ;
692 while(ptr) {
693 if (ptr->_arg==arg) return idx ;
694 ptr = ptr->_next ;
695 idx++ ;
696 }
697 return -1 ;
698}
699
700////////////////////////////////////////////////////////////////////////////////
701/// Return position of given object in list. If object
702/// is not contained in list, return -1
703
705{
707 Int_t idx(0) ;
708 while(ptr) {
709 if (strcmp(ptr->_arg->GetName(),name)==0) return idx ;
710 ptr = ptr->_next ;
711 idx++ ;
712 }
713 return -1 ;
714}
715
716////////////////////////////////////////////////////////////////////////////////
717/// Print contents of list, defers to Print() function
718/// of contained objects
719
720void RooLinkedList::Print(const char* opt) const
721{
722 RooLinkedListElem* elem = _first ;
723 while(elem) {
724 cout << elem->_arg << " : " ;
725 elem->_arg->Print(opt) ;
726 elem = elem->_next ;
727 }
728}
729
730////////////////////////////////////////////////////////////////////////////////
731/// Create a TIterator for this list.
732/// \param forward Run in forward direction (default).
733/// \return Pointer to a TIterator. The caller owns the pointer.
734
736 auto iterImpl = std::make_unique<RooLinkedListIterImpl>(this, forward);
737 return new RooLinkedListIter(std::move(iterImpl));
738}
739
740////////////////////////////////////////////////////////////////////////////////
741/// Create an iterator for this list.
742/// \param forward Run in forward direction (default).
743/// \return RooLinkedListIter (subclass of TIterator) over this list
744
746 auto iterImpl = std::make_unique<RooLinkedListIterImpl>(this, forward);
747 return RooLinkedListIter(std::move(iterImpl));
748}
749
750////////////////////////////////////////////////////////////////////////////////
751/// Create a one-time-use forward iterator for this list.
752/// \return RooFIter that only supports next()
753
755 auto iterImpl = std::make_unique<RooFIterForLinkedList>(this);
756 return RooFIter(std::move(iterImpl));
757}
758
760 return {this, true};
761}
762
764 return {this, nullptr, true};
765}
766
768 return {this, false};
769}
770
772 return {this, nullptr, false};
773}
774
775////////////////////////////////////////////////////////////////////////////////
776
778{
779 if (ascend) _first = mergesort_impl<true>(_first, _size, &_last);
780 else _first = mergesort_impl<false>(_first, _size, &_last);
781
782 // rebuild index array
784 for (auto it = _at.begin(); it != _at.end(); ++it, elem = elem->_next) {
785 *it = elem;
786 }
787}
788
789////////////////////////////////////////////////////////////////////////////////
790/// length 0, 1 lists are sorted
791
792template <bool ascending>
794 RooLinkedListElem* l1, const unsigned sz, RooLinkedListElem** tail)
795{
796 if (!l1 || sz < 2) {
797 // if desired, update the tail of the (newly merged sorted) list
798 if (tail) *tail = l1;
799 return l1;
800 }
801 if (sz <= 16) {
802 // for short lists, we sort in an array
803 std::vector<RooLinkedListElem *> arr(sz, nullptr);
804 for (int i = 0; l1; l1 = l1->_next, ++i) arr[i] = l1;
805 // straight insertion sort
806 {
807 int i = 1;
808 do {
809 int j = i - 1;
810 RooLinkedListElem *tmp = arr[i];
811 while (0 <= j) {
812 const bool inOrder = ascending ?
813 (tmp->_arg->Compare(arr[j]->_arg) <= 0) :
814 (arr[j]->_arg->Compare(tmp->_arg) <= 0);
815 if (!inOrder) break;
816 arr[j + 1] = arr[j];
817 --j;
818 }
819 arr[j + 1] = tmp;
820 ++i;
821 } while (int(sz) != i);
822 }
823 // link elements in array
824 arr[0]->_prev = arr[sz - 1]->_next = 0;
825 for (int i = 0; i < int(sz - 1); ++i) {
826 arr[i]->_next = arr[i + 1];
827 arr[i + 1]->_prev = arr[i];
828 }
829 if (tail) *tail = arr[sz - 1];
830 return arr[0];
831 }
832 // find middle of l1, and let a second list l2 start there
833 RooLinkedListElem *l2 = l1;
834 for (RooLinkedListElem *end = l2; end->_next; end = end->_next) {
835 end = end->_next;
836 l2 = l2->_next;
837 if (!end->_next) break;
838 }
839 // disconnect the two sublists
840 l2->_prev->_next = 0;
841 l2->_prev = 0;
842 // sort the two sublists (only recurse if we have to)
843 if (l1->_next) l1 = mergesort_impl<ascending>(l1, sz / 2);
844 if (l2->_next) l2 = mergesort_impl<ascending>(l2, sz - sz / 2);
845 // merge the two (sorted) sublists
846 // l: list head, t: list tail of merged list
847 RooLinkedListElem *l = (ascending ? (l1->_arg->Compare(l2->_arg) <= 0) :
848 (l2->_arg->Compare(l1->_arg) <= 0)) ? l1 : l2;
849 RooLinkedListElem *t = l;
850 if (l == l2) {
851 RooLinkedListElem* tmp = l1;
852 l1 = l2;
853 l2 = tmp;
854 }
855 l1 = l1->_next;
856 while (l1 && l2) {
857 const bool inOrder = ascending ? (l1->_arg->Compare(l2->_arg) <= 0) :
858 (l2->_arg->Compare(l1->_arg) <= 0);
859 if (!inOrder) {
860 // insert l2 just before l1
861 if (l1->_prev) {
862 l1->_prev->_next = l2;
863 l2->_prev = l1->_prev;
864 }
865 // swap l2 and l1
866 RooLinkedListElem *tmp = l1;
867 l1 = l2;
868 l2 = tmp;
869 }
870 // move forward in l1
871 t = l1;
872 l1 = l1->_next;
873 }
874 // attach l2 at t
875 if (l2) {
876 l2->_prev = t;
877 if (t) t->_next = l2;
878 }
879 // if desired, update the tail of the (newly merged sorted) list
880 if (tail) {
881 for (l1 = t; l1; l1 = l1->_next) t = l1;
882 *tail = t;
883 }
884 // return the head of the sorted list
885 return l;
886}
887// void Roo1DTable::Streamer(TBuffer &R__b)
888// {
889// // Stream an object of class Roo1DTable.
890
891// if (R__b.IsReading()) {
892// R__b.ReadClassBuffer(Roo1DTable::Class(),this);
893// } else {
894// R__b.WriteClassBuffer(Roo1DTable::Class(),this);
895// }
896// }
897
898////////////////////////////////////////////////////////////////////////////////
899/// Custom streaming handling schema evolution w.r.t past implementations
900
901void RooLinkedList::Streamer(TBuffer &R__b)
902{
903 if (R__b.IsReading()) {
904
905 Version_t v = R__b.ReadVersion();
906 //R__b.ReadVersion();
907 TObject::Streamer(R__b);
908
909 Int_t size ;
910 TObject* arg ;
911
912 R__b >> size ;
913 while(size--) {
914 R__b >> arg ;
915 Add(arg) ;
916 }
917
918 if (v > 1 && v < 4) {
919 R__b >> _name;
920 }
921
922 } else {
923 R__b.WriteVersion(RooLinkedList::IsA());
924 TObject::Streamer(R__b);
925 R__b << _size ;
926
928 while(ptr) {
929 R__b << ptr->_arg ;
930 ptr = ptr->_next ;
931 }
932
933 R__b << _name ;
934 }
935}
#define c(i)
Definition RSha256.hxx:101
#define a(i)
Definition RSha256.hxx:99
size_t size(const MatrixT &matrix)
retrieve the size of a square matrix
#define coutE(a)
int Int_t
Definition RtypesCore.h:45
short Version_t
Definition RtypesCore.h:65
const char Option_t
Definition RtypesCore.h:66
#define ClassImp(name)
Definition Rtypes.h:364
char name[80]
Definition TGX11.cxx:110
RooAbsArg is the common abstract base class for objects that represent a value and a "shape" in RooFi...
Definition RooAbsArg.h:69
const TNamed * namePtr() const
De-duplicated pointer to this object's name.
Definition RooAbsArg.h:577
RooAbsData is the common abstract base class for binned and unbinned datasets.
Definition RooAbsData.h:82
const TNamed * namePtr() const
De-duplicated pointer to this object's name.
Definition RooAbsData.h:324
A one-time forward iterator working on RooLinkedList or RooAbsCollection.
RooLinkedListElem is an link element for the RooLinkedList class.
void init(TObject *arg, RooLinkedListElem *after=0)
RooLinkedListElem * _prev
RooLinkedListElem * _next
a chunk of memory in a pool for quick allocation of RooLinkedListElems
bool full() const
chunk full?
RooLinkedListElem * _freelist
list of free elements
void push_free_elem(RooLinkedListElem *el)
push a free element back onto the freelist
Chunk(const Chunk &)
forbid copying
bool empty() const
chunk empty?
RooLinkedListElem * pop_free_elem()
pop a free element off the free list
const void * chunkaddr() const
return address of chunk
Int_t size() const
chunk occupied elements
Int_t capacity() const
chunk capacity
Int_t free() const
chunk free elements
int szclass() const
return size class
Chunk & operator=(const Chunk &)
bool contains(RooLinkedListElem *el) const
check if el is in this chunk
Int_t _free
length of free list
RooLinkedListElem * _chunk
chunk from which elements come
UInt_t _szmap[(maxsz - minsz)/szincr]
bool release()
release the pool, return true if the pool is unused
void push_free_elem(RooLinkedListElem *el)
push a free element back into the pool
Int_t nextChunkSz() const
find size of next chunk to allocate (in a hopefully smart way)
void updateCurSz(Int_t sz, Int_t incr)
adjust _cursz to current largest block
void acquire()
acquire the pool
std::map< const void *, Chunk * > AddrMap
RooLinkedListElem * pop_free_elem()
pop a free element out of the pool
@ maxsz
maximum chunk size (just below 1 << maxsz bytes)
@ minsz
minimum chunk size (just below 1 << minsz bytes)
@ szincr
size class increment (sz = 1 << (minsz + k * szincr))
RooLinkedListImplDetails::Chunk Chunk
a chunk of memory in the pool
Implementation of the actual iterator on RooLinkedLists.
A wrapper around TIterator derivatives.
RooLinkedList is an collection class for internal use, storing a collection of RooAbsArg pointers in ...
RooLinkedListIterImpl rend() const
TObject * At(int index) const
Return object stored in sequential position given by index.
TObject * FindObject(const char *name) const
Return pointer to obejct with given name.
static Pool * _pool
shared memory pool for allocation of RooLinkedListElems
TString _name
Hash table by link pointer.
RooLinkedListIterImpl end() const
RooLinkedListImplDetails::Pool Pool
memory pool for quick allocation of RooLinkedListElems
std::vector< RooLinkedListElem * > _at
RooLinkedListIter iterator(Bool_t forward=kTRUE) const
Create an iterator for this list.
std::unique_ptr< HashTableByName > _htableName
RooLinkedListElem * createElement(TObject *obj, RooLinkedListElem *elem=0)
cout << "RooLinkedList::createElem(" << this << ") obj = " << obj << " elem = " << elem << endl ;
RooLinkedList(Int_t htsize=0)
std::unique_ptr< HashTableByLink > _htableLink
Hash table by name.
void Sort(Bool_t ascend=kTRUE)
RooFIter fwdIterator() const
Create a one-time-use forward iterator for this list.
void deleteElement(RooLinkedListElem *)
RooLinkedListElem * findLink(const TObject *arg) const
Find the element link containing the given object.
void Print(const char *opt) const
Print contents of list, defers to Print() function of contained objects.
RooLinkedListIterImpl rbegin() const
std::size_t size() const
TIterator * MakeIterator(Bool_t forward=kTRUE) const
Create a TIterator for this list.
static RooLinkedListElem * mergesort_impl(RooLinkedListElem *l1, const unsigned sz, RooLinkedListElem **tail=0)
length 0, 1 lists are sorted
RooAbsArg * findArg(const RooAbsArg *) const
Return pointer to object with given name in collection.
void Delete(Option_t *o=0)
Remove all elements in collection and delete all elements NB: Collection does not own elements,...
TObject * find(const char *name) const
Return pointer to object with given name in collection.
RooLinkedList & operator=(const RooLinkedList &other)
Assignment operator, copy contents from 'other'.
virtual void RecursiveRemove(TObject *obj)
If one of the TObject we have a referenced to is deleted, remove the reference.
virtual void Add(TObject *arg)
RooLinkedListIterImpl begin() const
RooLinkedListElem * _last
Link to first element of list.
void setHashTableSize(Int_t size)
Change the threshold for hash-table use to given size.
void Clear(Option_t *o=0)
Remove all elements from collection.
Bool_t Replace(const TObject *oldArg, const TObject *newArg)
Replace object 'oldArg' in collection with new object 'newArg'.
RooLinkedListElem * _first
virtual Bool_t Remove(TObject *arg)
Remove object from collection.
Int_t IndexOf(const char *name) const
Return position of given object in list.
virtual ~RooLinkedList()
Destructor.
static const TNamed * known(const char *stringPtr)
If the name is already known, return its TNamed pointer. Otherwise return 0 (don't register the name)...
Buffer base class used for serializing objects.
Definition TBuffer.h:43
virtual Version_t ReadVersion(UInt_t *start=0, UInt_t *bcnt=0, const TClass *cl=0)=0
Bool_t IsReading() const
Definition TBuffer.h:86
virtual UInt_t WriteVersion(const TClass *cl, Bool_t useBcnt=kFALSE)=0
Iterator abstract base class.
Definition TIterator.h:30
The TNamed class is the base class for all named ROOT classes.
Definition TNamed.h:29
virtual const char * GetName() const
Returns name of object.
Definition TNamed.h:47
Mother of all ROOT objects.
Definition TObject.h:41
virtual const char * GetName() const
Returns name of object.
Definition TObject.cxx:429
R__ALWAYS_INLINE Bool_t TestBit(UInt_t f) const
Definition TObject.h:201
virtual Int_t Compare(const TObject *obj) const
Compare abstract method.
Definition TObject.cxx:231
virtual void Print(Option_t *option="") const
This method must be overridden when a class wants to print itself.
Definition TObject.cxx:622
void CallRecursiveRemoveIfNeeded(TObject &obj)
call RecursiveRemove for obj if gROOT is valid and obj.TestBit(kMustCleanup) is true.
Definition TROOT.h:393
auto * l
Definition textangle.C:4