Logo ROOT   6.30.04
Reference Guide
 All Namespaces Files Pages
RooSTLRefCountList.h
Go to the documentation of this file.
1 // Author: Stephan Hageboeck, CERN, 12/2018
2 /*****************************************************************************
3  * Project: RooFit *
4  * Authors: *
5  * WV, Wouter Verkerke, UC Santa Barbara, verkerke@slac.stanford.edu *
6  * DK, David Kirkby, UC Irvine, dkirkby@uci.edu *
7  * *
8  * Copyright (c) 2000-2005, Regents of the University of California *
9  * and Stanford University. All rights reserved. *
10  * *
11  * Redistribution and use in source and binary forms, *
12  * with or without modification, are permitted according to the terms *
13  * listed in LICENSE (http://roofit.sourceforge.net/license.txt) *
14  *****************************************************************************/
15 
16 #ifndef ROOFIT_ROOFITCORE_INC_ROOSTLREFCOUNTLIST_H_
17 #define ROOFIT_ROOFITCORE_INC_ROOSTLREFCOUNTLIST_H_
18 #include "Rtypes.h"
19 
20 #include <vector>
21 #include <algorithm>
22 #include <assert.h>
23 
24 
25 /**
26  * \class RooSTLRefCountList
27  * The RooSTLRefCountList is a simple collection of **pointers** to the template objects with
28  * reference counters.
29  * The pointees are not owned, hence not deleted when removed from the collection.
30  * Objects can be searched for either by pointer or by name (confusion possible when
31  * objects with same name are present). This replicates the behaviour of the RooRefCountList.
32  */
33 
34 template <class T>
35 class RooSTLRefCountList {
36  public:
37  using Container_t = std::vector<T*>;
38 
39  RooSTLRefCountList() {}
40  RooSTLRefCountList(const RooSTLRefCountList&) = default;
41  RooSTLRefCountList& operator=(const RooSTLRefCountList&) = default;
42  RooSTLRefCountList& operator=(RooSTLRefCountList&&) = default;
43 
44  virtual ~RooSTLRefCountList() {}
45 
46 
47  ///Add an object or increase refCount if it is already present. Only compares
48  ///pointers to check for existing objects
49  void Add(T * obj, std::size_t initialCount = 1) {
50  auto foundItem = findByPointer(obj);
51 
52  if (foundItem != _storage.end()) {
53  _refCount[foundItem - _storage.begin()] += initialCount;
54  }
55  else {
56  _storage.emplace_back(obj);
57  _refCount.emplace_back(initialCount);
58  }
59  }
60 
61 
62  ///Return ref count of item that iterator points to.
63  std::size_t refCount(typename Container_t::const_iterator item) const {
64  assert(_storage.size() == _refCount.size());
65 
66  return item != _storage.end() ? _refCount[item - _storage.begin()] : 0;
67  }
68 
69 
70  ///Return ref count of item with given address.
71  template<typename Obj_t>
72  std::size_t refCount(const Obj_t * obj) const {
73  return refCount(findByPointer(obj));
74  }
75 
76  ///Iterator over contained objects.
77  typename Container_t::const_iterator begin() const {
78  return _storage.begin();
79  }
80 
81  ///End of contained objects.
82  typename Container_t::const_iterator end() const {
83  return _storage.end();
84  }
85 
86 
87  ///Direct reference to container of objects held by this list.
88  const Container_t& containedObjects() const {
89  return _storage;
90  }
91 
92 
93  ///Number of contained objects (neglecting the ref count).
94  std::size_t size() const {
95  assert(_storage.size() == _refCount.size());
96 
97  return _storage.size();
98  }
99 
100  void reserve(std::size_t amount) {
101  _storage.reserve(amount);
102  _refCount.reserve(amount);
103  }
104 
105 
106  ///Check if empty.
107  bool empty() const {
108  return _storage.empty();
109  }
110 
111 
112  ///Find an item by comparing its adress.
113  template<typename Obj_t>
114  typename Container_t::const_iterator findByPointer(const Obj_t * item) const {
115  auto byPointer = [item](const T * listItem) {
116  return listItem == item;
117  };
118 
119  return std::find_if(_storage.begin(), _storage.end(), byPointer);
120  }
121 
122 
123  ///Find an item by comparing strings returned by RooAbsArg::GetName()
124  typename Container_t::const_iterator findByName(const char * name) const {
125  //If this turns out to be a bottleneck,
126  //one could use the RooNameReg to obtain the pointer to the arg's name and compare these
127  const std::string theName(name);
128  auto byName = [&theName](const T * element) {
129  return element->GetName() == theName;
130  };
131 
132  return std::find_if(_storage.begin(), _storage.end(), byName);
133  }
134 
135 
136  ///Find an item by comparing RooAbsArg::namePtr() adresses.
137  typename Container_t::const_iterator findByNamePointer(const T * item) const {
138  auto nptr = item->namePtr();
139  auto byNamePointer = [nptr](const T * element) {
140  return element->namePtr() == nptr;
141  };
142 
143  return std::find_if(_storage.begin(), _storage.end(), byNamePointer);
144  }
145 
146 
147  ///Check if list contains an item using findByPointer().
148  template<typename Obj_t>
149  bool containsByPointer(const Obj_t * obj) const {
150  return findByPointer(obj) != _storage.end();
151  }
152 
153 
154  ///Check if list contains an item using findByNamePointer().
155  bool containsByNamePtr(const T * obj) const {
156  return findByNamePointer(obj) != _storage.end();
157  }
158 
159 
160  ///Check if list contains an item using findByName().
161  bool containsSameName(const char * name) const {
162  return findByName(name) != _storage.end();
163  }
164 
165 
166  ///Decrease ref count of given object. Shrink list if ref count reaches 0.
167  ///\param obj Decrease ref count of given object. Compare by pointer.
168  ///\param force If true, remove irrespective of ref count.
169  void Remove(const T * obj, bool force = false) {
170  auto item = findByPointer(obj);
171 
172  if (item != _storage.end()) {
173  const std::size_t pos = item - _storage.begin();
174 
175  if (force || --_refCount[pos] == 0) {
176  //gcc4.x doesn't know how to erase at the position of a const_iterator
177  //Therefore, erase at begin + pos instead of 'item'
178  _storage.erase(_storage.begin() + pos);
179  _refCount.erase(_refCount.begin() + pos);
180  }
181  }
182  }
183 
184 
185  ///Remove from list irrespective of ref count.
186  void RemoveAll(const T * obj) {
187  Remove(obj, true);
188  }
189 
190 
191  private:
192  Container_t _storage;
193  std::vector<std::size_t> _refCount;
194 
195  ClassDef(RooSTLRefCountList<T>,1);
196 };
197 
198 
199 
200 class RooAbsArg;
201 class RooRefCountList;
202 
203 namespace RooFit {
204 namespace STLRefCountListHelpers {
205  /// Converter from the old RooRefCountList to RooSTLRefCountList.
206  RooSTLRefCountList<RooAbsArg> convert(const RooRefCountList& old);
207 }
208 }
209 
210 #endif /* ROOFIT_ROOFITCORE_INC_ROOSTLREFCOUNTLIST_H_ */