Logo ROOT   6.14/05
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 
22 RooLinkedList is an collection class for internal use, storing
23 a collection of RooAbsArg pointers in a doubly linked list.
24 It can optionally add a hash table to speed up random access
25 in large collections
26 Use 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 
44 using namespace std;
45 
47 ;
48 namespace RooLinkedListImplDetails {
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
353  RooLinkedListElem* ptr = _first ;
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 
395  RooLinkedListElem* ptr = _first;
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 
409 void 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
496  RooLinkedListElem* ptr = _first;
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 
507 Bool_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 {
577  RooLinkedListElem* elem = _first;
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 
604 TObject* RooLinkedList::find(const char* name) const
605 {
606 
607  if (_htableName) {
608  RooAbsArg* a = (RooAbsArg*) _htableName->find(name) ;
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)) {
617  RooLinkedListElem* ptr = _first ;
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 
630  RooLinkedListElem* ptr = _first ;
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) {
663  RooAbsArg* a = (RooAbsArg*) _htableName->findArg(arg) ;
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 
670  RooLinkedListElem* ptr = _first ;
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 {
687  RooLinkedListElem* ptr = _first;
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 
701 Int_t RooLinkedList::IndexOf(const char* name) const
702 {
703  RooLinkedListElem* ptr = _first;
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 
717 void 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 
760 template <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 
876 void 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 
902  RooLinkedListElem* ptr = _first;
903  while(ptr) {
904  R__b << ptr->_arg ;
905  ptr = ptr->_next ;
906  }
907 
908  R__b << _name ;
909  }
910 }
911 
Bool_t IsReading() const
Definition: TBuffer.h:83
Int_t IndexOf(const char *name) const
Return position of given object in list.
#define coutE(a)
Definition: RooMsgService.h:34
static RooLinkedListElem * mergesort_impl(RooLinkedListElem *l1, const unsigned sz, RooLinkedListElem **tail=0)
length 0, 1 lists are sorted
TObject * FindObject(const char *name) const
Return pointer to obejct with given name.
RooHashTable * _htableLink
Hash table by name.
short Version_t
Definition: RtypesCore.h:61
void CallRecursiveRemoveIfNeeded(TObject &obj)
call RecursiveRemove for obj if gROOT is valid and obj.TestBit(kMustCleanup) is true.
Definition: TROOT.h:399
virtual Bool_t Remove(TObject *arg)
Remove object from collection.
void setHashTableSize(Int_t size)
Change the threshold for hash-table use to given size.
const char Option_t
Definition: RtypesCore.h:62
TObject * find(const char *name) const
Return pointer to object with given name in collection.
fill
Definition: fit1_py.py:6
Buffer base class used for serializing objects.
Definition: TBuffer.h:40
R__ALWAYS_INLINE Bool_t TestBit(UInt_t f) const
Definition: TObject.h:172
RooFIter fwdIterator() const
int Int_t
Definition: RtypesCore.h:41
bool Bool_t
Definition: RtypesCore.h:59
Bool_t replace(const TObject *oldArg, const TObject *newArg, const TObject *oldHashArg=0)
Replace oldArg with newArg in the table.
STL namespace.
virtual void Print(Option_t *option="") const
This method must be overridden when a class wants to print itself.
Definition: TObject.cxx:550
virtual UInt_t WriteVersion(const TClass *cl, Bool_t useBcnt=kFALSE)=0
RooLinkedListImplDetails::Pool Pool
memory pool for quick allocation of RooLinkedListElems
void Clear(Option_t *o=0)
Remove all elements from collection.
Iterator abstract base class.
Definition: TIterator.h:30
void Sort(Bool_t ascend=kTRUE)
Bool_t Replace(const TObject *oldArg, const TObject *newArg)
Replace object &#39;oldArg&#39; in collection with new object &#39;newArg&#39;.
friend class RooLinkedListIter
virtual void RecursiveRemove(TObject *obj)
If one of the TObject we have a referenced to is deleted, remove the reference.
RooLinkedListElem * findLinkTo(const TObject *arg) const
Return RooLinkedList element link to object &#39;hashArg&#39;.
RooLinkedListElem * _next
RooLinkedListElem * _first
The TNamed class is the base class for all named ROOT classes.
Definition: TNamed.h:29
TString _name
Hash table by link pointer.
RooHashTable implements a hash table for TObjects.
Definition: RooHashTable.h:28
RooLinkedListElem * findLink(const TObject *arg) const
Find the element link containing the given object.
static const TNamed * known(const char *stringPtr)
If the name is already known, return its TNamed pointer. Otherwise return 0 (don&#39;t register the name)...
Definition: RooNameReg.cxx:145
virtual void Add(TObject *arg)
Definition: RooLinkedList.h:62
void add(TObject *arg, TObject *hashArg=0)
Add given object to table.
RooLinkedListElem * _prev
SVector< double, 2 > v
Definition: Dict.h:5
auto * a
Definition: textangle.C:12
RooLinkedList(Int_t htsize=0)
TObject * At(Int_t index) const
Return object stored in sequential position given by index.
unsigned int UInt_t
Definition: RtypesCore.h:42
RooLinkedListIter iterator(Bool_t dir=kTRUE) const
virtual Int_t Compare(const TObject *obj) const
Compare abstract method.
Definition: TObject.cxx:159
TObject * find(const char *name) const
Return the object with given name from the table.
Bool_t remove(TObject *arg, TObject *hashArg=0)
Remove given object from table.
const Bool_t kFALSE
Definition: RtypesCore.h:88
RooLinkedList is an collection class for internal use, storing a collection of RooAbsArg pointers in ...
Definition: RooLinkedList.h:35
void Delete(Option_t *o=0)
Remove all elements in collection and delete all elements NB: Collection does not own elements...
#define ClassImp(name)
Definition: Rtypes.h:359
#define free
Definition: civetweb.c:1350
Int_t size() const
Definition: RooHashTable.h:48
RooLinkedList & operator=(const RooLinkedList &other)
Assignment operator, copy contents from &#39;other&#39;.
Binding & operator=(OUT(*fun)(void))
Mother of all ROOT objects.
Definition: TObject.h:37
RooLinkedListElem * _last
Link to first element of list.
void deleteElement(RooLinkedListElem *)
static Pool * _pool
shared memory pool for allocation of RooLinkedListElems
auto * l
Definition: textangle.C:4
TIterator * MakeIterator(Bool_t dir=kTRUE) const
Return an iterator over this list.
void Print(const char *opt) const
Print contents of list, defers to Print() function of contained objects.
virtual ~RooLinkedList()
Destructor.
#define c(i)
Definition: RSha256.hxx:101
RooAbsArg * findArg(const RooAbsArg *) const
Return pointer to object with given name in collection.
RooLinkedListElem is an link element for the RooLinkedList class.
RooAbsArg * findArg(const RooAbsArg *arg) const
RooAbsArg is the common abstract base class for objects that represent a value (of arbitrary type) an...
Definition: RooAbsArg.h:66
friend class RooFIter
RooLinkedListElem * createElement(TObject *obj, RooLinkedListElem *elem=0)
cout << "RooLinkedList::createElem(" << this << ") obj = " << obj << " elem = " << elem << endl ; ...
virtual const char * GetName() const
Returns name of object.
Definition: TObject.cxx:357
const Bool_t kTRUE
Definition: RtypesCore.h:87
RooLinkedListIter is the TIterator implementation for RooLinkedList.
char name[80]
Definition: TGX11.cxx:109
const TNamed * namePtr() const
Definition: RooAbsArg.h:461
virtual Version_t ReadVersion(UInt_t *start=0, UInt_t *bcnt=0, const TClass *cl=0)=0
RooHashTable * _htableName
Link to last element of list.
void init(TObject *arg, RooLinkedListElem *after=0)