File indexing completed on 2025-01-18 10:11:27
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018 #ifndef ROOFIT_ROOFITCORE_INC_ROOSTLREFCOUNTLIST_H_
0019 #define ROOFIT_ROOFITCORE_INC_ROOSTLREFCOUNTLIST_H_
0020
0021 #include "RooNameReg.h"
0022
0023 #include "Rtypes.h"
0024
0025 #include <vector>
0026 #include <string>
0027 #include <algorithm>
0028 #include <cassert>
0029
0030 class RooLinkedList;
0031
0032
0033
0034
0035
0036
0037
0038
0039
0040
0041 template <class T>
0042 class RooSTLRefCountList {
0043 public:
0044 using Container_t = std::vector<T*>;
0045
0046 static constexpr std::size_t minSizeForNamePointerOrdering = 7;
0047
0048 RooSTLRefCountList() {
0049
0050
0051 if(_renameCounter == nullptr) _renameCounter =
0052 &RooNameReg::renameCounter();
0053 }
0054 RooSTLRefCountList(const RooSTLRefCountList&) = default;
0055 RooSTLRefCountList& operator=(const RooSTLRefCountList&) = default;
0056 RooSTLRefCountList& operator=(RooSTLRefCountList&&) = default;
0057
0058 virtual ~RooSTLRefCountList() {}
0059
0060
0061
0062 void Add(T * obj, std::size_t initialCount = 1) {
0063
0064 if(initialCount == 0) return;
0065
0066 auto foundItem = findByPointer(obj);
0067
0068 if (foundItem != _storage.end()) {
0069 _refCount[foundItem - _storage.begin()] += initialCount;
0070 }
0071 else {
0072 if(!_orderedStorage.empty()) {
0073 _orderedStorage.insert(lowerBoundByNamePointer(obj), obj);
0074 }
0075 _storage.push_back(obj);
0076 _refCount.push_back(initialCount);
0077 }
0078 }
0079
0080
0081
0082 std::size_t refCount(typename Container_t::const_iterator item) const {
0083 assert(_storage.size() == _refCount.size());
0084
0085 return item != _storage.end() ? _refCount[item - _storage.begin()] : 0;
0086 }
0087
0088
0089
0090 template<typename Obj_t>
0091 std::size_t refCount(const Obj_t * obj) const {
0092 return refCount(findByPointer(obj));
0093 }
0094
0095
0096 typename Container_t::const_iterator begin() const {
0097 return _storage.begin();
0098 }
0099
0100
0101 typename Container_t::const_iterator end() const {
0102 return _storage.end();
0103 }
0104
0105
0106 typename Container_t::value_type operator[](std::size_t index) const {
0107 return _storage[index];
0108 }
0109
0110
0111
0112 const Container_t& containedObjects() const {
0113 return _storage;
0114 }
0115
0116
0117
0118 std::size_t size() const {
0119 assert(_storage.size() == _refCount.size());
0120
0121 return _storage.size();
0122 }
0123
0124 void reserve(std::size_t amount) {
0125 _storage.reserve(amount);
0126 _refCount.reserve(amount);
0127 _orderedStorage.reserve(amount);
0128 }
0129
0130
0131
0132 bool empty() const {
0133 return _storage.empty();
0134 }
0135
0136
0137
0138 template<typename Obj_t>
0139 typename Container_t::const_iterator findByPointer(const Obj_t * item) const {
0140 return std::find(_storage.begin(), _storage.end(), item);
0141 }
0142
0143
0144
0145 typename Container_t::const_iterator findByName(const char * name) const {
0146
0147
0148 const std::string theName(name);
0149 auto byName = [&theName](const T * element) {
0150 return element->GetName() == theName;
0151 };
0152
0153 return std::find_if(_storage.begin(), _storage.end(), byName);
0154 }
0155
0156
0157
0158 inline T* findByNamePointer(const T * item) const {
0159 return findByNamePointer(item->namePtr());
0160 }
0161
0162 T* findByNamePointer(TNamed const* namePtr) const {
0163 if(size() < minSizeForNamePointerOrdering) {
0164 auto byNamePointer = [namePtr](const T * element) {
0165 return element->namePtr() == namePtr;
0166 };
0167
0168 auto found = std::find_if(_storage.begin(), _storage.end(), byNamePointer);
0169 return found != _storage.end() ? *found : nullptr;
0170 } else {
0171
0172
0173 auto first = lowerBoundByNamePointer(namePtr);
0174 if(first == _orderedStorage.end()) return nullptr;
0175 if(namePtr != (*first)->namePtr()) return nullptr;
0176 return *first;
0177 }
0178 }
0179
0180
0181
0182 template<typename Obj_t>
0183 bool containsByPointer(const Obj_t * obj) const {
0184 return findByPointer(obj) != _storage.end();
0185 }
0186
0187
0188
0189 bool containsByNamePtr(const T * obj) const {
0190 return findByNamePointer(obj);
0191 }
0192
0193
0194
0195 bool containsSameName(const char * name) const {
0196 return findByName(name) != _storage.end();
0197 }
0198
0199
0200
0201
0202
0203
0204
0205
0206
0207 int Remove(const T * obj, bool force = false) {
0208 auto item = findByPointer(obj);
0209
0210 if (item != _storage.end()) {
0211 const std::size_t pos = item - _storage.begin();
0212
0213 const UInt_t origRefCount = _refCount[pos];
0214
0215 if (force || --_refCount[pos] == 0) {
0216
0217
0218 _storage.erase(_storage.begin() + pos);
0219 _refCount.erase(_refCount.begin() + pos);
0220 if(!_orderedStorage.empty()) {
0221
0222
0223
0224
0225
0226
0227 _orderedStorage.erase(std::find(_orderedStorage.begin(), _orderedStorage.end(), obj));
0228 }
0229 return origRefCount;
0230 }
0231 return 1;
0232 }
0233
0234 return 0;
0235 }
0236
0237
0238
0239
0240
0241
0242 int Replace(const T * oldObj, T * newObj) {
0243 auto item = findByPointer(oldObj);
0244
0245 if (item != _storage.end()) {
0246 const std::size_t pos = item - _storage.begin();
0247 _storage[pos] = newObj;
0248
0249 _orderedStorage.clear();
0250 return _refCount[pos];
0251 }
0252
0253 return 0;
0254 }
0255
0256
0257
0258 void RemoveAll(const T * obj) {
0259 Remove(obj, true);
0260 }
0261
0262 static RooSTLRefCountList<T> convert(const RooLinkedList& old);
0263
0264 private:
0265
0266
0267 inline typename std::vector<T*>::const_iterator lowerBoundByNamePointer(const T * item) const {
0268 return lowerBoundByNamePointer(item->namePtr());
0269 }
0270
0271 typename std::vector<T*>::const_iterator lowerBoundByNamePointer(TNamed const* namePtr) const {
0272
0273
0274
0275 if(orderedStorageNeedsSorting() || _orderedStorage.size() != _storage.size()) initializeOrderedStorage();
0276
0277 return std::lower_bound(_orderedStorage.begin(), _orderedStorage.end(), namePtr,
0278 [](const auto& x, TNamed const* npt) -> bool {
0279 return x->namePtr() < npt;
0280 });
0281 }
0282
0283 bool orderedStorageNeedsSorting() const {
0284
0285
0286
0287
0288
0289
0290 return _renameCounterForLastSorting != *_renameCounter;
0291 }
0292
0293 void initializeOrderedStorage() const {
0294 _orderedStorage.clear();
0295 _orderedStorage.reserve(_storage.size());
0296 for(std::size_t i = 0; i < _storage.size(); ++i) {
0297 _orderedStorage.push_back(_storage[i]);
0298 }
0299 std::sort(_orderedStorage.begin(), _orderedStorage.end(),
0300 [](auto& a, auto& b) {
0301 return a->namePtr() != b->namePtr() ? a->namePtr() < b->namePtr() : a < b;
0302 });
0303 _renameCounterForLastSorting = *_renameCounter;
0304 }
0305
0306 Container_t _storage;
0307 std::vector<UInt_t> _refCount;
0308 mutable std::vector<T*> _orderedStorage;
0309 mutable unsigned long _renameCounterForLastSorting = 0;
0310
0311
0312
0313
0314 static std::size_t const* _renameCounter;
0315
0316 ClassDef(RooSTLRefCountList<T>,3);
0317 };
0318
0319 template<class T>
0320 std::size_t const* RooSTLRefCountList<T>::_renameCounter = nullptr;
0321
0322 #endif
0323
0324