Logo ROOT   6.16/01
Reference Guide
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 "RooHashTable.h"
35#include "RooAbsArg.h"
36#include "RooMsgService.h"
37
38#include "Riostream.h"
39#include "TBuffer.h"
40#include "TROOT.h"
41
42#include <algorithm>
43
44using namespace std;
45
47;
49 /// a chunk of memory in a pool for quick allocation of RooLinkedListElems
50 class Chunk {
51 public:
52 /// constructor
53 Chunk(Int_t sz) :
54 _sz(sz), _free(capacity()),
55 _chunk(new RooLinkedListElem[_free]), _freelist(_chunk)
56 {
57 //cout << "RLLID::Chunk ctor(" << this << ") of size " << _free << " list elements" << endl ;
58 // initialise free list
59 for (Int_t i = 0; i < _free; ++i)
60 _chunk[i]._next = (i + 1 < _free) ? &_chunk[i + 1] : 0;
61 }
62 /// destructor
63 ~Chunk() { delete[] _chunk; }
64 /// chunk capacity
65 Int_t capacity() const
66 { return (1 << _sz) / sizeof(RooLinkedListElem); }
67 /// chunk free elements
68 Int_t free() const { return _free; }
69 /// chunk occupied elements
70 Int_t size() const { return capacity() - free(); }
71 /// return size class
72 int szclass() const { return _sz; }
73 /// chunk full?
74 bool full() const { return !free(); }
75 /// chunk empty?
76 bool empty() const { return capacity() == free(); }
77 /// return address of chunk
78 const void* chunkaddr() const { return _chunk; }
79 /// check if el is in this chunk
80 bool contains(RooLinkedListElem* el) const
81 { return _chunk <= el && el < &_chunk[capacity()]; }
82 /// pop a free element off the free list
83 RooLinkedListElem* pop_free_elem()
84 {
85 if (!_freelist) return 0;
86 RooLinkedListElem* retVal = _freelist;
87 _freelist = retVal->_next;
88 retVal->_arg = 0; retVal->_refCount = 0;
89 retVal->_prev = retVal->_next = 0;
90 --_free;
91 return retVal;
92 }
93 /// push a free element back onto the freelist
94 void push_free_elem(RooLinkedListElem* el)
95 {
96 el->_next = _freelist;
97 _freelist = el;
98 ++_free;
99 }
100 private:
101 Int_t _sz; ///< chunk capacity
102 Int_t _free; ///< length of free list
103 RooLinkedListElem* _chunk; ///< chunk from which elements come
104 RooLinkedListElem* _freelist; ///< list of free elements
105
106 /// forbid copying
107 Chunk(const Chunk&);
108 // forbid assignment
109 Chunk& operator=(const Chunk&);
110 };
111
112 class Pool {
113 private:
114 enum {
115 minsz = 7, ///< minimum chunk size (just below 1 << minsz bytes)
116 maxsz = 18, ///< maximum chunk size (just below 1 << maxsz bytes)
117 szincr = 1 ///< size class increment (sz = 1 << (minsz + k * szincr))
118 };
119 /// a chunk of memory in the pool
120 typedef RooLinkedListImplDetails::Chunk Chunk;
121 typedef std::list<Chunk*> ChunkList;
122 typedef std::map<const void*, Chunk*> AddrMap;
123 public:
124 /// constructor
125 Pool();
126 /// destructor
127 ~Pool();
128 /// acquire the pool
129 inline void acquire() { ++_refCount; }
130 /// release the pool, return true if the pool is unused
131 inline bool release() { return 0 == --_refCount; }
132 /// pop a free element out of the pool
133 RooLinkedListElem* pop_free_elem();
134 /// push a free element back into the pool
135 void push_free_elem(RooLinkedListElem* el);
136 private:
137 AddrMap _addrmap;
138 ChunkList _freelist;
139 UInt_t _szmap[(maxsz - minsz) / szincr];
140 Int_t _cursz;
141 UInt_t _refCount;
142
143 /// adjust _cursz to current largest block
144 void updateCurSz(Int_t sz, Int_t incr);
145 /// find size of next chunk to allocate (in a hopefully smart way)
146 Int_t nextChunkSz() const;
147 };
148
149 Pool::Pool() : _cursz(minsz), _refCount(0)
150 {
151 std::fill(_szmap, _szmap + ((maxsz - minsz) / szincr), 0);
152 }
153
154 Pool::~Pool()
155 {
156 _freelist.clear();
157 for (AddrMap::iterator it = _addrmap.begin(); _addrmap.end() != it; ++it)
158 delete it->second;
159 _addrmap.clear();
160 }
161
162 RooLinkedListElem* Pool::pop_free_elem()
163 {
164 if (_freelist.empty()) {
165 // allocate and register new chunk and put it on the freelist
166 const Int_t sz = nextChunkSz();
167 Chunk *c = new Chunk(sz);
168 _addrmap[c->chunkaddr()] = c;
169 _freelist.push_back(c);
170 updateCurSz(sz, +1);
171 }
172 // get free element from first chunk on _freelist
173 Chunk* c = _freelist.front();
174 RooLinkedListElem* retVal = c->pop_free_elem();
175 // full chunks are removed from _freelist
176 if (c->full()) _freelist.pop_front();
177 return retVal;
178 }
179
180 void Pool::push_free_elem(RooLinkedListElem* el)
181 {
182 // find from which chunk el came
183 AddrMap::iterator ci = _addrmap.end();
184 if (!_addrmap.empty()) {
185 ci = _addrmap.lower_bound(el);
186 if (ci == _addrmap.end()) {
187 // point beyond last element, so get last one
188 ci = (++_addrmap.rbegin()).base();
189 } else {
190 // valid ci, check if we need to decrement ci because el isn't the
191 // first element in the chunk
192 if (_addrmap.begin() != ci && ci->first != el) --ci;
193 }
194 }
195 // either empty addressmap, or ci should now point to the chunk which might
196 // contain el
197 if (_addrmap.empty() || !ci->second->contains(el)) {
198 // el is not in any chunk we know about, so just delete it
199 delete el;
200 return;
201 }
202 Chunk *c = ci->second;
203 const bool moveToFreelist = c->full();
204 c->push_free_elem(el);
205 if (c->empty()) {
206 // delete chunk if all empty
207 ChunkList::iterator it = std::find( _freelist.begin(), _freelist.end(), c);
208 if (_freelist.end() != it) _freelist.erase(it);
209 _addrmap.erase(ci->first);
210 updateCurSz(c->szclass(), -1);
211 delete c;
212 } else if (moveToFreelist) {
213 _freelist.push_back(c);
214 }
215 }
216
217 void Pool::updateCurSz(Int_t sz, Int_t incr)
218 {
219 _szmap[(sz - minsz) / szincr] += incr;
220 _cursz = minsz;
221 for (int i = (maxsz - minsz) / szincr; i--; ) {
222 if (_szmap[i]) {
223 _cursz += i * szincr;
224 break;
225 }
226 }
227 }
228
229 Int_t Pool::nextChunkSz() const
230 {
231 // no chunks with space available, figure out chunk size
232 Int_t sz = _cursz;
233 if (_addrmap.empty()) {
234 // if we start allocating chunks, we start from minsz
235 sz = minsz;
236 } else {
237 if (minsz >= sz) {
238 // minimal sized chunks are always grown
239 sz = minsz + szincr;
240 } else {
241 if (1 != _addrmap.size()) {
242 // if we have more than one completely filled chunk, grow
243 sz += szincr;
244 } else {
245 // just one chunk left, try shrinking chunk size
246 sz -= szincr;
247 }
248 }
249 }
250 // clamp size to allowed range
251 if (sz > maxsz) sz = maxsz;
252 if (sz < minsz) sz = minsz;
253 return sz;
254 }
255}
256
258
259////////////////////////////////////////////////////////////////////////////////
260
262 _hashThresh(htsize), _size(0), _first(0), _last(0), _htableName(0), _htableLink(0), _useNptr(kTRUE)
263{
264 if (!_pool) _pool = new Pool;
265 _pool->acquire();
266}
267
268////////////////////////////////////////////////////////////////////////////////
269/// Copy constructor
270
272 TObject(other), _hashThresh(other._hashThresh), _size(0), _first(0), _last(0), _htableName(0), _htableLink(0),
273 _name(other._name),
274 _useNptr(other._useNptr)
275{
276 if (!_pool) _pool = new Pool;
277 _pool->acquire();
278 if (other._htableName) _htableName = new RooHashTable(other._htableName->size()) ;
280 for (RooLinkedListElem* elem = other._first; elem; elem = elem->_next) {
281 Add(elem->_arg, elem->_refCount) ;
282 }
283}
284
285////////////////////////////////////////////////////////////////////////////////
286/// cout << "RooLinkedList::createElem(" << this << ") obj = " << obj << " elem = " << elem << endl ;
287
289{
290 RooLinkedListElem* ret = _pool->pop_free_elem();
291 ret->init(obj, elem);
292 return ret ;
293}
294
295////////////////////////////////////////////////////////////////////////////////
296
298{
299 elem->release() ;
300 _pool->push_free_elem(elem);
301 //delete elem ;
302}
303
304////////////////////////////////////////////////////////////////////////////////
305/// Assignment operator, copy contents from 'other'
306
308{
309 // Prevent self-assignment
310 if (&other==this) return *this ;
311
312 // remove old elements
313 Clear();
314 // Copy elements
315 for (RooLinkedListElem* elem = other._first; elem; elem = elem->_next) {
316 Add(elem->_arg) ;
317 }
318
319 return *this ;
320}
321
322////////////////////////////////////////////////////////////////////////////////
323/// Change the threshold for hash-table use to given size.
324/// If a hash table exists when this method is called, it is regenerated.
325
327{
328 if (size<0) {
329 coutE(InputArguments) << "RooLinkedList::setHashTable() ERROR size must be positive" << endl ;
330 return ;
331 }
332 if (size==0) {
333 if (!_htableName) {
334 // No hash table present
335 return ;
336 } else {
337 // Remove existing hash table
338 delete _htableName ;
339 delete _htableLink ;
340 _htableName = 0 ;
341 _htableLink = 0 ;
342 }
343 } else {
344
345 // (Re)create hash tables
346 if (_htableName) delete _htableName ;
347 _htableName = new RooHashTable(size) ;
348
349 if (_htableLink) delete _htableLink ;
351
352 // Fill hash table with existing entries
354 while(ptr) {
355 _htableName->add(ptr->_arg) ;
356 _htableLink->add((TObject*)ptr,ptr->_arg) ;
357 ptr = ptr->_next ;
358 }
359 }
360}
361
362////////////////////////////////////////////////////////////////////////////////
363/// Destructor
364
366{
367 // Required since we overload TObject::Hash.
369
370 if (_htableName) {
371 delete _htableName;
372 _htableName = 0;
373 }
374 if (_htableLink) {
375 delete _htableLink ;
376 _htableLink=0 ;
377 }
378
379 Clear() ;
380 if (_pool->release()) {
381 delete _pool;
382 _pool = 0;
383 }
384}
385
386////////////////////////////////////////////////////////////////////////////////
387/// Find the element link containing the given object
388
390{
391 if (_htableLink) {
392 return _htableLink->findLinkTo(arg) ;
393 }
394
396 while(ptr) {
397 if (ptr->_arg == arg) {
398 return ptr ;
399 }
400 ptr = ptr->_next ;
401 }
402 return 0 ;
403
404}
405
406////////////////////////////////////////////////////////////////////////////////
407/// Insert object into collection with given reference count value
408
409void RooLinkedList::Add(TObject* arg, Int_t refCount)
410{
411 if (!arg) return ;
412
413 // Only use RooAbsArg::namePtr() in lookup-by-name if all elements have it
414 if (!dynamic_cast<RooAbsArg*>(arg)) _useNptr = kFALSE;
415
416 // Add to hash table
417 if (_htableName) {
418
419 // Expand capacity of hash table if #entries>#slots
420 if (_size > _htableName->size()) {
422 }
423
424 } else if (_hashThresh>0 && _size>_hashThresh) {
425
427 }
428
429 if (_last) {
430 // Append element at end of list
431 _last = createElement(arg,_last) ;
432 } else {
433 // Append first element, set first,last
434 _last = createElement(arg) ;
435 _first=_last ;
436 }
437
438 if (_htableName){
439 //cout << "storing link " << _last << " with hash arg " << arg << endl ;
440 _htableName->add(arg) ;
441 _htableLink->add((TObject*)_last,arg) ;
442 }
443
444 _size++ ;
445 _last->_refCount = refCount ;
446
447}
448
449////////////////////////////////////////////////////////////////////////////////
450/// Remove object from collection
451
453{
454 // Find link element
455 RooLinkedListElem* elem = findLink(arg) ;
456 if (!elem) return kFALSE ;
457
458 // Remove from hash table
459 if (_htableName) {
460 _htableName->remove(arg) ;
461 }
462 if (_htableLink) {
463 _htableLink->remove((TObject*)elem,arg) ;
464 }
465
466 // Update first,last if necessary
467 if (elem==_first) _first=elem->_next ;
468 if (elem==_last) _last=elem->_prev ;
469
470 // Delete and shrink
471 _size-- ;
472 deleteElement(elem) ;
473 return kTRUE ;
474}
475
476////////////////////////////////////////////////////////////////////////////////
477/// If one of the TObject we have a referenced to is deleted, remove the
478/// reference.
479
481{
482 Remove(obj); // This is a nop if the obj is not in the collection.
483}
484
485////////////////////////////////////////////////////////////////////////////////
486/// Return object stored in sequential position given by index.
487/// If index is out of range, a null pointer is returned.
488
490{
491 // Check range
492 if (index<0 || index>=_size) return 0 ;
493
494
495 // Walk list
497 while(index--) ptr = ptr->_next ;
498
499 // Return arg
500 return ptr->_arg ;
501}
502
503////////////////////////////////////////////////////////////////////////////////
504/// Replace object 'oldArg' in collection with new object 'newArg'.
505/// If 'oldArg' is not found in collection kFALSE is returned
506
507Bool_t RooLinkedList::Replace(const TObject* oldArg, const TObject* newArg)
508{
509 // Find existing element and replace arg
510 RooLinkedListElem* elem = findLink(oldArg) ;
511 if (!elem) return kFALSE ;
512
513 if (_htableName) {
514 _htableName->replace(oldArg,newArg) ;
515 }
516 if (_htableLink) {
517 // Link is hashed by contents and may change slot in hash table
518 _htableLink->remove((TObject*)elem,(TObject*)oldArg) ;
519 _htableLink->add((TObject*)elem,(TObject*)newArg) ;
520 }
521
522 elem->_arg = (TObject*)newArg ;
523 return kTRUE ;
524}
525
526////////////////////////////////////////////////////////////////////////////////
527/// Return pointer to obejct with given name. If no such object
528/// is found return a null pointer
529
531{
532 return find(name) ;
533}
534
535////////////////////////////////////////////////////////////////////////////////
536/// Find object in list. If list contains object return
537/// (same) pointer to object, otherwise return null pointer
538
540{
541 RooLinkedListElem *elem = findLink((TObject*)obj) ;
542 return elem ? elem->_arg : 0 ;
543}
544
545////////////////////////////////////////////////////////////////////////////////
546/// Remove all elements from collection
547
549{
550 for (RooLinkedListElem *elem = _first, *next; elem; elem = next) {
551 next = elem->_next ;
552 deleteElement(elem) ;
553 }
554 _first = 0 ;
555 _last = 0 ;
556 _size = 0 ;
557
558 if (_htableName) {
559 Int_t hsize = _htableName->size() ;
560 delete _htableName ;
561 _htableName = new RooHashTable(hsize) ;
562 }
563 if (_htableLink) {
564 Int_t hsize = _htableLink->size() ;
565 delete _htableLink ;
567 }
568}
569
570////////////////////////////////////////////////////////////////////////////////
571/// Remove all elements in collection and delete all elements
572/// NB: Collection does not own elements, this function should
573/// be used judiciously by caller.
574
576{
578 while(elem) {
579 RooLinkedListElem* next = elem->_next ;
580 delete elem->_arg ;
581 deleteElement(elem) ;
582 elem = next ;
583 }
584 _first = 0 ;
585 _last = 0 ;
586 _size = 0 ;
587
588 if (_htableName) {
589 Int_t hsize = _htableName->size() ;
590 delete _htableName ;
591 _htableName = new RooHashTable(hsize) ;
592 }
593 if (_htableLink) {
594 Int_t hsize = _htableLink->size() ;
595 delete _htableLink ;
597 }
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) {
609 // RooHashTable::find could return false negative if element was renamed to 'name'.
610 // The list search means it won't return false positive, so can return here.
611 if (a) return a;
612 if (_useNptr) {
613 // See if it might have been renamed
614 const TNamed* nptr= RooNameReg::known(name);
615 //cout << "RooLinkedList::find: possibly renamed '" << name << "', kRenamedArg=" << (nptr&&nptr->TestBit(RooNameReg::kRenamedArg)) << endl;
616 if (nptr && nptr->TestBit(RooNameReg::kRenamedArg)) {
618 while(ptr) {
619 if ((((RooAbsArg*)ptr->_arg)->namePtr() == nptr)) {
620 return ptr->_arg ;
621 }
622 ptr = ptr->_next ;
623 }
624 }
625 return 0 ;
626 }
627 //cout << "RooLinkedList::find: possibly renamed '" << name << "'" << endl;
628 }
629
631
632 // The penalty for RooNameReg lookup seems to be outweighted by the faster search
633 // when the size list is longer than ~7, but let's be a bit conservative.
634 if (_useNptr && _size>9) {
635 const TNamed* nptr= RooNameReg::known(name);
636 if (!nptr) return 0;
637
638 while(ptr) {
639 if ((((RooAbsArg*)ptr->_arg)->namePtr() == nptr)) {
640 return ptr->_arg ;
641 }
642 ptr = ptr->_next ;
643 }
644 return 0 ;
645 }
646
647 while(ptr) {
648 if (!strcmp(ptr->_arg->GetName(),name)) {
649 return ptr->_arg ;
650 }
651 ptr = ptr->_next ;
652 }
653 return 0 ;
654}
655
656////////////////////////////////////////////////////////////////////////////////
657/// Return pointer to object with given name in collection.
658/// If no such object is found, return null pointer.
659
661{
662 if (_htableName) {
664 if (a) return a;
665 //cout << "RooLinkedList::findArg: possibly renamed '" << arg->GetName() << "', kRenamedArg=" << arg->namePtr()->TestBit(RooNameReg::kRenamedArg) << endl;
666 // See if it might have been renamed
667 if (!arg->namePtr()->TestBit(RooNameReg::kRenamedArg)) return 0;
668 }
669
671 const TNamed* nptr = arg->namePtr();
672 while(ptr) {
673 if (((RooAbsArg*)(ptr->_arg))->namePtr() == nptr) {
674 return (RooAbsArg*) ptr->_arg ;
675 }
676 ptr = ptr->_next ;
677 }
678 return 0 ;
679}
680
681////////////////////////////////////////////////////////////////////////////////
682/// Return position of given object in list. If object
683/// is not contained in list, return -1
684
686{
688 Int_t idx(0) ;
689 while(ptr) {
690 if (ptr->_arg==arg) return idx ;
691 ptr = ptr->_next ;
692 idx++ ;
693 }
694 return -1 ;
695}
696
697////////////////////////////////////////////////////////////////////////////////
698/// Return position of given object in list. If object
699/// is not contained in list, return -1
700
702{
704 Int_t idx(0) ;
705 while(ptr) {
706 if (strcmp(ptr->_arg->GetName(),name)==0) return idx ;
707 ptr = ptr->_next ;
708 idx++ ;
709 }
710 return -1 ;
711}
712
713////////////////////////////////////////////////////////////////////////////////
714/// Print contents of list, defers to Print() function
715/// of contained objects
716
717void RooLinkedList::Print(const char* opt) const
718{
719 RooLinkedListElem* elem = _first ;
720 while(elem) {
721 cout << elem->_arg << " : " ;
722 elem->_arg->Print(opt) ;
723 elem = elem->_next ;
724 }
725}
726
727////////////////////////////////////////////////////////////////////////////////
728
730{
731 return RooLinkedListIter(this,dir) ;
732}
733
734////////////////////////////////////////////////////////////////////////////////
735
737{
738 return RooFIter(this) ;
739}
740
741////////////////////////////////////////////////////////////////////////////////
742/// Return an iterator over this list
743
745{
746 return new RooLinkedListIter(this,dir) ;
747}
748
749////////////////////////////////////////////////////////////////////////////////
750
752{
753 if (ascend) _first = mergesort_impl<true>(_first, _size, &_last);
754 else _first = mergesort_impl<false>(_first, _size, &_last);
755}
756
757////////////////////////////////////////////////////////////////////////////////
758/// length 0, 1 lists are sorted
759
760template <bool ascending>
762 RooLinkedListElem* l1, const unsigned sz, RooLinkedListElem** tail)
763{
764 if (!l1 || sz < 2) {
765 // if desired, update the tail of the (newly merged sorted) list
766 if (tail) *tail = l1;
767 return l1;
768 }
769 if (sz <= 16) {
770 // for short lists, we sort in an array
771#if !defined(_WIN32) && !defined(R__SOLARIS_CC50)
772 RooLinkedListElem *arr[sz];
773#else // _WIN32 && Solaris
774 // apparently, MSVC is not clever enough to figure out that sz cannot be
775 // zero and is at most sixteen, so we allocate a fixed size array on the
776 // stack instead
777 RooLinkedListElem *arr[16];
778#endif // _WIN32
779 for (int i = 0; l1; l1 = l1->_next, ++i) arr[i] = l1;
780 // straight insertion sort
781 {
782 int i = 1;
783 do {
784 int j = i - 1;
785 RooLinkedListElem *tmp = arr[i];
786 while (0 <= j) {
787 const bool inOrder = ascending ?
788 (tmp->_arg->Compare(arr[j]->_arg) <= 0) :
789 (arr[j]->_arg->Compare(tmp->_arg) <= 0);
790 if (!inOrder) break;
791 arr[j + 1] = arr[j];
792 --j;
793 }
794 arr[j + 1] = tmp;
795 ++i;
796 } while (int(sz) != i);
797 }
798 // link elements in array
799 arr[0]->_prev = arr[sz - 1]->_next = 0;
800 for (int i = 0; i < int(sz - 1); ++i) {
801 arr[i]->_next = arr[i + 1];
802 arr[i + 1]->_prev = arr[i];
803 }
804 if (tail) *tail = arr[sz - 1];
805 return arr[0];
806 }
807 // find middle of l1, and let a second list l2 start there
808 RooLinkedListElem *l2 = l1;
809 for (RooLinkedListElem *end = l2; end->_next; end = end->_next) {
810 end = end->_next;
811 l2 = l2->_next;
812 if (!end->_next) break;
813 }
814 // disconnect the two sublists
815 l2->_prev->_next = 0;
816 l2->_prev = 0;
817 // sort the two sublists (only recurse if we have to)
818 if (l1->_next) l1 = mergesort_impl<ascending>(l1, sz / 2);
819 if (l2->_next) l2 = mergesort_impl<ascending>(l2, sz - sz / 2);
820 // merge the two (sorted) sublists
821 // l: list head, t: list tail of merged list
822 RooLinkedListElem *l = (ascending ? (l1->_arg->Compare(l2->_arg) <= 0) :
823 (l2->_arg->Compare(l1->_arg) <= 0)) ? l1 : l2;
824 RooLinkedListElem *t = l;
825 if (l == l2) {
826 RooLinkedListElem* tmp = l1;
827 l1 = l2;
828 l2 = tmp;
829 }
830 l1 = l1->_next;
831 while (l1 && l2) {
832 const bool inOrder = ascending ? (l1->_arg->Compare(l2->_arg) <= 0) :
833 (l2->_arg->Compare(l1->_arg) <= 0);
834 if (!inOrder) {
835 // insert l2 just before l1
836 if (l1->_prev) {
837 l1->_prev->_next = l2;
838 l2->_prev = l1->_prev;
839 }
840 // swap l2 and l1
841 RooLinkedListElem *tmp = l1;
842 l1 = l2;
843 l2 = tmp;
844 }
845 // move forward in l1
846 t = l1;
847 l1 = l1->_next;
848 }
849 // attach l2 at t
850 if (l2) {
851 l2->_prev = t;
852 if (t) t->_next = l2;
853 }
854 // if desired, update the tail of the (newly merged sorted) list
855 if (tail) {
856 for (l1 = t; l1; l1 = l1->_next) t = l1;
857 *tail = t;
858 }
859 // return the head of the sorted list
860 return l;
861}
862// void Roo1DTable::Streamer(TBuffer &R__b)
863// {
864// // Stream an object of class Roo1DTable.
865
866// if (R__b.IsReading()) {
867// R__b.ReadClassBuffer(Roo1DTable::Class(),this);
868// } else {
869// R__b.WriteClassBuffer(Roo1DTable::Class(),this);
870// }
871// }
872
873////////////////////////////////////////////////////////////////////////////////
874/// Custom streaming handling schema evolution w.r.t past implementations
875
876void RooLinkedList::Streamer(TBuffer &R__b)
877{
878 if (R__b.IsReading()) {
879
880 Version_t v = R__b.ReadVersion();
881 //R__b.ReadVersion();
882 TObject::Streamer(R__b);
883
884 Int_t size ;
885 TObject* arg ;
886
887 R__b >> size ;
888 while(size--) {
889 R__b >> arg ;
890 Add(arg) ;
891 }
892
893 if (v > 1 && v < 4) {
894 R__b >> _name;
895 }
896
897 } else {
898 R__b.WriteVersion(RooLinkedList::IsA());
899 TObject::Streamer(R__b);
900 R__b << _size ;
901
903 while(ptr) {
904 R__b << ptr->_arg ;
905 ptr = ptr->_next ;
906 }
907
908 R__b << _name ;
909 }
910}
911
SVector< double, 2 > v
Definition: Dict.h:5
#define c(i)
Definition: RSha256.hxx:101
#define coutE(a)
Definition: RooMsgService.h:34
int Int_t
Definition: RtypesCore.h:41
short Version_t
Definition: RtypesCore.h:61
unsigned int UInt_t
Definition: RtypesCore.h:42
const Bool_t kFALSE
Definition: RtypesCore.h:88
bool Bool_t
Definition: RtypesCore.h:59
const Bool_t kTRUE
Definition: RtypesCore.h:87
const char Option_t
Definition: RtypesCore.h:62
#define ClassImp(name)
Definition: Rtypes.h:363
Binding & operator=(OUT(*fun)(void))
#define free
Definition: civetweb.c:1539
RooAbsArg is the common abstract base class for objects that represent a value (of arbitrary type) an...
Definition: RooAbsArg.h:66
const TNamed * namePtr() const
Definition: RooAbsArg.h:461
RooHashTable implements a hash table for TObjects.
Definition: RooHashTable.h:28
Bool_t remove(TObject *arg, TObject *hashArg=0)
Remove given object from table.
Int_t size() const
Definition: RooHashTable.h:48
RooLinkedListElem * findLinkTo(const TObject *arg) const
Return RooLinkedList element link to object 'hashArg'.
Bool_t replace(const TObject *oldArg, const TObject *newArg, const TObject *oldHashArg=0)
Replace oldArg with newArg in the table.
TObject * find(const char *name) const
Return the object with given name from the table.
void add(TObject *arg, TObject *hashArg=0)
Add given object to table.
RooAbsArg * findArg(const RooAbsArg *arg) const
RooLinkedListElem is an link element for the RooLinkedList class.
void init(TObject *arg, RooLinkedListElem *after=0)
RooLinkedListElem * _prev
RooLinkedListElem * _next
RooLinkedListIter is the TIterator implementation for RooLinkedList.
RooLinkedList is an collection class for internal use, storing a collection of RooAbsArg pointers in ...
Definition: RooLinkedList.h:35
friend class RooFIter
RooLinkedListIter iterator(Bool_t dir=kTRUE) const
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.
RooLinkedListImplDetails::Pool Pool
memory pool for quick allocation of RooLinkedListElems
TIterator * MakeIterator(Bool_t dir=kTRUE) const
Return an iterator over this list.
RooHashTable * _htableName
Link to last element of list.
RooLinkedListElem * createElement(TObject *obj, RooLinkedListElem *elem=0)
cout << "RooLinkedList::createElem(" << this << ") obj = " << obj << " elem = " << elem << endl ;
RooLinkedList(Int_t htsize=0)
RooHashTable * _htableLink
Hash table by name.
void Sort(Bool_t ascend=kTRUE)
RooFIter fwdIterator() const
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.
static RooLinkedListElem * mergesort_impl(RooLinkedListElem *l1, const unsigned sz, RooLinkedListElem **tail=0)
length 0, 1 lists are sorted
TObject * At(Int_t index) const
Return object stored in sequential position given by index.
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)
Definition: RooLinkedList.h:62
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'.
friend class RooLinkedListIter
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)...
Definition: RooNameReg.cxx:145
Buffer base class used for serializing objects.
Definition: TBuffer.h:40
virtual Version_t ReadVersion(UInt_t *start=0, UInt_t *bcnt=0, const TClass *cl=0)=0
Bool_t IsReading() const
Definition: TBuffer.h:83
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
Mother of all ROOT objects.
Definition: TObject.h:37
virtual const char * GetName() const
Returns name of object.
Definition: TObject.cxx:357
R__ALWAYS_INLINE Bool_t TestBit(UInt_t f) const
Definition: TObject.h:172
virtual Int_t Compare(const TObject *obj) const
Compare abstract method.
Definition: TObject.cxx:159
virtual void Print(Option_t *option="") const
This method must be overridden when a class wants to print itself.
Definition: TObject.cxx:550
void CallRecursiveRemoveIfNeeded(TObject &obj)
call RecursiveRemove for obj if gROOT is valid and obj.TestBit(kMustCleanup) is true.
Definition: TROOT.h:399
@ InputArguments
Definition: RooGlobalFunc.h:58
fill
Definition: fit1_py.py:6
STL namespace.
auto * l
Definition: textangle.C:4
auto * a
Definition: textangle.C:12