Logo ROOT  
Reference Guide
 
Loading...
Searching...
No Matches
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
19#include "RooNameReg.h"
20
21#include "Rtypes.h"
22
23#include <vector>
24#include <string>
25#include <algorithm>
26#include <cassert>
27
28
29/**
30 * \class RooSTLRefCountList
31 * The RooSTLRefCountList is a simple collection of **pointers** to the template objects with
32 * reference counters.
33 * The pointees are not owned, hence not deleted when removed from the collection.
34 * Objects can be searched for either by pointer or by name (confusion possible when
35 * objects with same name are present). This replicates the behaviour of the RooRefCountList.
36 */
37
38template <class T>
40 public:
41 using Container_t = std::vector<T*>;
42
43 static constexpr std::size_t minSizeForNamePointerOrdering = 7;
44
46 // The static _renameCounter member gets connected to the RooNameReg as
47 // soon as the first RooSTLRefCountList instance is constructed.
48 if(_renameCounter == nullptr) _renameCounter =
50 }
54
56
57 ///Add an object or increase refCount if it is already present. Only compares
58 ///pointers to check for existing objects
59 void Add(T * obj, std::size_t initialCount = 1) {
60 // Nothing to add because `refCount` would be zero.
61 if(initialCount == 0) return;
62
63 auto foundItem = findByPointer(obj);
64
65 if (foundItem != _storage.end()) {
66 _refCount[foundItem - _storage.begin()] += initialCount;
67 }
68 else {
69 if(!_orderedStorage.empty()) {
71 }
72 _storage.push_back(obj);
73 _refCount.push_back(initialCount);
74 }
75 }
76
77
78 ///Return ref count of item that iterator points to.
79 std::size_t refCount(typename Container_t::const_iterator item) const {
80 assert(_storage.size() == _refCount.size());
81
82 return item != _storage.end() ? _refCount[item - _storage.begin()] : 0;
83 }
84
85
86 ///Return ref count of item with given address.
87 template<typename Obj_t>
88 std::size_t refCount(const Obj_t * obj) const {
89 return refCount(findByPointer(obj));
90 }
91
92 ///Iterator over contained objects.
93 typename Container_t::const_iterator begin() const {
94 return _storage.begin();
95 }
96
97 ///End of contained objects.
98 typename Container_t::const_iterator end() const {
99 return _storage.end();
100 }
101
102 /// Retrieve an element from the list.
103 typename Container_t::value_type operator[](std::size_t index) const {
104 return _storage[index];
105 }
106
107
108 ///Direct reference to container of objects held by this list.
110 return _storage;
111 }
112
113
114 ///Number of contained objects (neglecting the ref count).
115 std::size_t size() const {
116 assert(_storage.size() == _refCount.size());
117
118 return _storage.size();
119 }
120
121 void reserve(std::size_t amount) {
122 _storage.reserve(amount);
123 _refCount.reserve(amount);
124 _orderedStorage.reserve(amount);
125 }
126
127
128 ///Check if empty.
129 bool empty() const {
130 return _storage.empty();
131 }
132
133
134 ///Find an item by comparing its adress.
135 template<typename Obj_t>
136 typename Container_t::const_iterator findByPointer(const Obj_t * item) const {
137 return std::find(_storage.begin(), _storage.end(), item);
138 }
139
140
141 ///Find an item by comparing strings returned by RooAbsArg::GetName()
142 typename Container_t::const_iterator findByName(const char * name) const {
143 //If this turns out to be a bottleneck,
144 //one could use the RooNameReg to obtain the pointer to the arg's name and compare these
145 const std::string theName(name);
146 auto byName = [&theName](const T * element) {
147 return element->GetName() == theName;
148 };
149
150 return std::find_if(_storage.begin(), _storage.end(), byName);
151 }
152
153
154 ///Find an item by comparing RooAbsArg::namePtr() adresses.
155 inline T* findByNamePointer(const T * item) const {
156 return findByNamePointer(item->namePtr());
157 }
158
159 T* findByNamePointer(TNamed const* namePtr) const {
161 auto byNamePointer = [namePtr](const T * element) {
162 return element->namePtr() == namePtr;
163 };
164
165 auto found = std::find_if(_storage.begin(), _storage.end(), byNamePointer);
166 return found != _storage.end() ? *found : nullptr;
167 } else {
168 //As the collection is guaranteed to be sorted by namePtr() adress, we
169 //can use a binary search to look for `item` in this collection.
170 auto first = lowerBoundByNamePointer(namePtr);
171 if(first == _orderedStorage.end()) return nullptr;
172 if(namePtr != (*first)->namePtr()) return nullptr;
173 return *first;
174 }
175 }
176
177
178 ///Check if list contains an item using findByPointer().
179 template<typename Obj_t>
180 bool containsByPointer(const Obj_t * obj) const {
181 return findByPointer(obj) != _storage.end();
182 }
183
184
185 ///Check if list contains an item using findByNamePointer().
186 bool containsByNamePtr(const T * obj) const {
187 return findByNamePointer(obj);
188 }
189
190
191 ///Check if list contains an item using findByName().
192 bool containsSameName(const char * name) const {
193 return findByName(name) != _storage.end();
194 }
195
196
197 ///Decrease ref count of given object. Shrink list if ref count reaches 0.
198 ///\param obj Decrease ref count of given object. Compare by pointer.
199 ///\param force If true, remove irrespective of ref count.
200 ///Returns by how much the `refCount` for the element to be removed was
201 ///decreased (zero if nothing was removed). If `force == false`, it can
202 ///only be zero or one, if `force == true`, it can be the full `refCount`
203 ///for that element.
204 int Remove(const T * obj, bool force = false) {
205 auto item = findByPointer(obj);
206
207 if (item != _storage.end()) {
208 const std::size_t pos = item - _storage.begin();
209
210 const UInt_t origRefCount = _refCount[pos];
211
212 if (force || --_refCount[pos] == 0) {
213 //gcc4.x doesn't know how to erase at the position of a const_iterator
214 //Therefore, erase at begin + pos instead of 'item'
215 _storage.erase(_storage.begin() + pos);
216 _refCount.erase(_refCount.begin() + pos);
217 if(!_orderedStorage.empty()) {
218 // For the ordered storage, we could find by name pointer address
219 // with binary search, but this will not work anymore if one of the
220 // object pointers in this collection is dangling (can happen in
221 // RooFit...). However, the linear search by object address is
222 // acceptable, because we already do a linear search through
223 // _storage at the beginning of Remove().
224 _orderedStorage.erase(std::find(_orderedStorage.begin(), _orderedStorage.end(), obj));
225 }
226 return origRefCount;
227 }
228 return 1;
229 }
230
231 return 0;
232 }
233
234
235 ///Replace an element with a new value, keeping the same `refCount`. Will
236 ///return the `refCount` for that element if the replacement succeeded,
237 ///otherwise returns zero in case the `oldObj` could not be found in the
238 ///collection.
239 int Replace(const T * oldObj, T * newObj) {
240 auto item = findByPointer(oldObj);
241
242 if (item != _storage.end()) {
243 const std::size_t pos = item - _storage.begin();
244 _storage[pos] = newObj;
245 // The content has changed, so the ordered-by-name storage was invalidated.
246 _orderedStorage.clear();
247 return _refCount[pos];
248 }
249
250 return 0;
251 }
252
253
254 ///Remove from list irrespective of ref count.
255 void RemoveAll(const T * obj) {
256 Remove(obj, true);
257 }
258
259
260 private:
261 //Return an iterator to the last element in this sorted collection with a
262 //RooAbsArg::namePtr() adress smaller than for `item`.
263 inline typename std::vector<T*>::const_iterator lowerBoundByNamePointer(const T * item) const {
264 return lowerBoundByNamePointer(item->namePtr());
265 }
266
267 typename std::vector<T*>::const_iterator lowerBoundByNamePointer(TNamed const* namePtr) const {
268
269 //If the _orderedStorage has not been initialized yet or needs resorting
270 //for other reasons, (re-)initialize it now.
272
273 return std::lower_bound(_orderedStorage.begin(), _orderedStorage.end(), namePtr,
274 [](const auto& x, TNamed const* npt) -> bool {
275 return x->namePtr() < npt;
276 });
277 }
278
280 //If an RooAbsArg in this collection was renamed, the collection might
281 //not be sorted correctly anymore! The solution: every time any RooAbsArg
282 //is renamed, the RooNameReg::renameCounter gets incremented. The
283 //RooSTLRefCountList keeps track at which value of the counter it has
284 //been sorted last. If the counter increased in the meantime, a
285 //re-sorting is due.
287 }
288
290 _orderedStorage.clear();
291 _orderedStorage.reserve(_storage.size());
292 for(std::size_t i = 0; i < _storage.size(); ++i) {
293 _orderedStorage.push_back(_storage[i]);
294 }
295 std::sort(_orderedStorage.begin(), _orderedStorage.end(),
296 [](auto& a, auto& b) {
297 return a->namePtr() != b->namePtr() ? a->namePtr() < b->namePtr() : a < b;
298 });
300 }
301
303 std::vector<UInt_t> _refCount;
304 mutable std::vector<T*> _orderedStorage; //!
305 mutable unsigned long _renameCounterForLastSorting = 0; ///<!
306
307 // It is expensive to access the RooNameReg instance to get the counter for
308 // the renaming operations. That's why we have out own static pointer to
309 // the counter.
310 static std::size_t const* _renameCounter;
311
313};
314
315template<class T>
316std::size_t const* RooSTLRefCountList<T>::_renameCounter = nullptr;
317
318class RooAbsArg;
319class RooRefCountList;
320
321namespace RooFit {
322namespace STLRefCountListHelpers {
323 /// Converter from the old RooRefCountList to RooSTLRefCountList.
325}
326}
327
328#endif /* ROOFIT_ROOFITCORE_INC_ROOSTLREFCOUNTLIST_H_ */
#define b(i)
Definition RSha256.hxx:100
#define a(i)
Definition RSha256.hxx:99
#define ClassDef(name, id)
Definition Rtypes.h:337
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t index
char name[80]
Definition TGX11.cxx:110
RooAbsArg is the common abstract base class for objects that represent a value and a "shape" in RooFi...
Definition RooAbsArg.h:74
static const std::size_t & renameCounter()
renamed in this RooFit process.
A RooRefCountList is a RooLinkedList that keeps a reference counter with each added node.
The RooSTLRefCountList is a simple collection of pointers to the template objects with reference coun...
void initializeOrderedStorage() const
std::size_t refCount(typename Container_t::const_iterator item) const
Return ref count of item that iterator points to.
bool containsSameName(const char *name) const
Check if list contains an item using findByName().
bool orderedStorageNeedsSorting() const
std::vector< T * >::const_iterator lowerBoundByNamePointer(const T *item) const
bool containsByPointer(const Obj_t *obj) const
Check if list contains an item using findByPointer().
std::size_t refCount(const Obj_t *obj) const
Return ref count of item with given address.
T * findByNamePointer(const T *item) const
Find an item by comparing RooAbsArg::namePtr() adresses.
const Container_t & containedObjects() const
Direct reference to container of objects held by this list.
Container_t::const_iterator begin() const
Iterator over contained objects.
unsigned long _renameCounterForLastSorting
!
std::vector< T * > Container_t
void Add(T *obj, std::size_t initialCount=1)
Add an object or increase refCount if it is already present.
std::vector< T * > _orderedStorage
RooSTLRefCountList & operator=(RooSTLRefCountList &&)=default
int Replace(const T *oldObj, T *newObj)
Replace an element with a new value, keeping the same refCount.
Container_t::value_type operator[](std::size_t index) const
Retrieve an element from the list.
static std::size_t const * _renameCounter
RooSTLRefCountList & operator=(const RooSTLRefCountList &)=default
RooSTLRefCountList(const RooSTLRefCountList &)=default
Container_t::const_iterator end() const
End of contained objects.
std::vector< T * >::const_iterator lowerBoundByNamePointer(TNamed const *namePtr) const
bool empty() const
Check if empty.
static constexpr std::size_t minSizeForNamePointerOrdering
std::vector< UInt_t > _refCount
Container_t::const_iterator findByName(const char *name) const
Find an item by comparing strings returned by RooAbsArg::GetName()
std::size_t size() const
Number of contained objects (neglecting the ref count).
Container_t::const_iterator findByPointer(const Obj_t *item) const
Find an item by comparing its adress.
int Remove(const T *obj, bool force=false)
Decrease ref count of given object.
T * findByNamePointer(TNamed const *namePtr) const
void RemoveAll(const T *obj)
Remove from list irrespective of ref count.
void reserve(std::size_t amount)
bool containsByNamePtr(const T *obj) const
Check if list contains an item using findByNamePointer().
The TNamed class is the base class for all named ROOT classes.
Definition TNamed.h:29
Double_t x[n]
Definition legend1.C:17
RooSTLRefCountList< RooAbsArg > convert(const RooRefCountList &old)
Converter from the old RooRefCountList to RooSTLRefCountList.
The namespace RooFit contains mostly switches that change the behaviour of functions of PDFs (or othe...
Definition Common.h:18
Definition first.py:1