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