CMS 3D CMS Logo

ReusableObjectHolder.h
Go to the documentation of this file.
1 #ifndef FWCore_Utilities_ReusableObjectHolder_h
2 #define FWCore_Utilities_ReusableObjectHolder_h
3 
4 // -*- C++ -*-
5 //
6 // Package: FWCore/Utilities
7 // Class : ReusableObjectHolder
8 //
69 //
70 // Original Author: Chris Jones
71 // Created: Fri, 31 July 2014 14:29:41 GMT
72 //
73 
74 #include <atomic>
75 #include <cassert>
76 #include <memory>
77 
78 #include <oneapi/tbb/concurrent_queue.h>
79 
80 namespace edm {
81  template <class T, class Deleter = std::default_delete<T>>
83  public:
84  using deleter_type = Deleter;
85 
89  assert(0 == iOther.m_outstandingObjects);
90  }
91  ~ReusableObjectHolder() noexcept {
93  std::unique_ptr<T, Deleter> item;
94  while (m_availableQueue.try_pop(item)) {
95  item.reset();
96  }
97  }
98 
102  void add(std::unique_ptr<T, Deleter> iItem) {
103  if (nullptr != iItem) {
104  m_availableQueue.push(std::move(iItem));
105  }
106  }
107 
111  std::shared_ptr<T> tryToGet() {
112  std::unique_ptr<T, Deleter> item;
113  if (m_availableQueue.try_pop(item)) {
115  } else {
116  return std::shared_ptr<T>{};
117  }
118  }
119 
121  template <typename FM>
122  std::shared_ptr<T> makeOrGet(FM&& iMakeFunc) {
123  std::unique_ptr<T, Deleter> item;
124  if (m_availableQueue.try_pop(item)) {
126  } else {
127  return wrapCustomDeleter(makeUnique(iMakeFunc()));
128  }
129  }
130 
133  template <typename FM, typename FC>
134  std::shared_ptr<T> makeOrGetAndClear(FM&& iMakeFunc, FC&& iClearFunc) {
135  std::shared_ptr<T> returnValue = makeOrGet(std::forward<FM>(iMakeFunc));
136  iClearFunc(returnValue.get());
137  return returnValue;
138  }
139 
140  private:
142  // back to the queue instead of deleting it
143  std::shared_ptr<T> wrapCustomDeleter(std::unique_ptr<T, Deleter> item) {
144  auto deleter = item.get_deleter();
146  return std::shared_ptr<T>{item.release(), [this, deleter](T* iItem) {
147  this->addBack(std::unique_ptr<T, Deleter>{iItem, deleter});
148  }};
149  }
150 
151  std::unique_ptr<T> makeUnique(T* ptr) {
152  static_assert(std::is_same_v<Deleter, std::default_delete<T>>,
153  "Generating functions returning raw pointers are supported only with std::default_delete<T>");
154  return std::unique_ptr<T>{ptr};
155  }
156 
157  std::unique_ptr<T, Deleter> makeUnique(std::unique_ptr<T, Deleter> ptr) { return ptr; }
158 
159  void addBack(std::unique_ptr<T, Deleter> iItem) {
160  m_availableQueue.push(std::move(iItem));
162  }
163 
164  oneapi::tbb::concurrent_queue<std::unique_ptr<T, Deleter>> m_availableQueue;
165  std::atomic<size_t> m_outstandingObjects;
166  };
167 
168 } // namespace edm
169 
170 #endif /* end of include guard: FWCore_Utilities_ReusableObjectHolder_h */
std::default_delete< edm::ESProductHost > deleter_type
std::unique_ptr< T > makeUnique(T *ptr)
assert(be >=bs)
void add(std::unique_ptr< T, Deleter > iItem)
void addBack(std::unique_ptr< T, Deleter > iItem)
std::atomic< size_t > m_outstandingObjects
std::unique_ptr< T, Deleter > makeUnique(std::unique_ptr< T, Deleter > ptr)
oneapi::tbb::concurrent_queue< std::unique_ptr< T, Deleter > > m_availableQueue
std::shared_ptr< T > makeOrGetAndClear(FM &&iMakeFunc, FC &&iClearFunc)
std::shared_ptr< T > makeOrGet(FM &&iMakeFunc)
Takes an object from the queue if one is available, or creates one using iMakeFunc.
std::shared_ptr< T > tryToGet()
ReusableObjectHolder(ReusableObjectHolder &&iOther)
HLT enums.
std::shared_ptr< T > wrapCustomDeleter(std::unique_ptr< T, Deleter > item)
Wraps an object in a shared_ptr<T> with a custom deleter, that hands the wrapped object.
long double T
def move(src, dest)
Definition: eostools.py:511