CMS 3D CMS Logo

List of all members | Public Types | Public Member Functions | Private Member Functions | Private Attributes
edm::ReusableObjectHolder< T, Deleter > Class Template Reference

#include <ReusableObjectHolder.h>

Public Types

using deleter_type = Deleter
 

Public Member Functions

void add (std::unique_ptr< T, Deleter > iItem)
 
template<typename FM >
std::shared_ptr< TmakeOrGet (FM &&iMakeFunc)
 Takes an object from the queue if one is available, or creates one using iMakeFunc. More...
 
template<typename FM , typename FC >
std::shared_ptr< TmakeOrGetAndClear (FM &&iMakeFunc, FC &&iClearFunc)
 
 ReusableObjectHolder ()
 
 ReusableObjectHolder (ReusableObjectHolder &&iOther)
 
std::shared_ptr< TtryToGet ()
 
 ~ReusableObjectHolder () noexcept
 

Private Member Functions

void addBack (std::unique_ptr< T, Deleter > iItem)
 
std::unique_ptr< TmakeUnique (T *ptr)
 
std::unique_ptr< T, Deleter > makeUnique (std::unique_ptr< T, Deleter > ptr)
 
std::shared_ptr< TwrapCustomDeleter (std::unique_ptr< T, Deleter > item)
 Wraps an object in a shared_ptr<T> with a custom deleter, that hands the wrapped object. More...
 

Private Attributes

oneapi::tbb::concurrent_queue< std::unique_ptr< T, Deleter > > m_availableQueue
 
std::atomic< size_t > m_outstandingObjects
 

Detailed Description

template<class T, class Deleter = std::default_delete<T>>
class edm::ReusableObjectHolder< T, Deleter >

Description: Thread safe way to do create and reuse a group of the same object type.

Usage: This class can be used to safely reuse a series of objects created on demand. The reuse of the objects is safe even across different threads since one can safely call all member functions of this class on the same instance of this class from multiple threads.

This class manages the cache of reusable objects and therefore an instance of this class must live as long as you want the cache to live.

The primary way of using the class is to call makeOrGet:

auto objectToUse = holder.makeOrGet([]() { return new MyObject(); });
use(*objectToUse);

If the returned object should be be automatically set or reset, call makeOrGetAndClear:

auto objectToUse = holder.makeOrGetAndClear([]() { return new MyObject(10); }, // makes new objects
[](MyObject* old) { old->reset(); } // resets any object before returning it
);

which is equivalent to

auto objectToUse = holder.makeOrGet([]() { return new MyObject(10); });
objectToUse->reset();

NOTE: If you hold onto the std::shared_ptr<> until another call to the ReusableObjectHolder, make sure to release the shared_ptr before the call. That way the object you were just using can go back into the cache and be reused for the call you are going to make. An example

std::shared_ptr<MyObject> obj;
while(someCondition()) {
//release object so it can re-enter the cache
obj.release();
obj = holder.makeOrGet([]{ return new MyObject();} );
obj->setValue(someNewValue());
useTheObject(obj);
}

The above example is very contrived, since the better way to do the above is

while(someCondition()) {
auto obj = holder.makeOrGet([]{ return new MyObject();} );
obj->setValue(someNewValue());
useTheObject(obj);
//obj goes out of scope and returns the object to the cache
}

When a custom deleter is used, the deleter type must be the same to all objects. The deleter is allowed to have state that depends on the object. The deleter object is passed along the std::unique_ptr, and is internally kept along the object. The deleter object must be copyable.

Definition at line 82 of file ReusableObjectHolder.h.

Member Typedef Documentation

◆ deleter_type

template<class T, class Deleter = std::default_delete<T>>
using edm::ReusableObjectHolder< T, Deleter >::deleter_type = Deleter

Definition at line 84 of file ReusableObjectHolder.h.

Constructor & Destructor Documentation

◆ ReusableObjectHolder() [1/2]

template<class T, class Deleter = std::default_delete<T>>
edm::ReusableObjectHolder< T, Deleter >::ReusableObjectHolder ( )
inline

Definition at line 86 of file ReusableObjectHolder.h.

std::atomic< size_t > m_outstandingObjects

◆ ReusableObjectHolder() [2/2]

template<class T, class Deleter = std::default_delete<T>>
edm::ReusableObjectHolder< T, Deleter >::ReusableObjectHolder ( ReusableObjectHolder< T, Deleter > &&  iOther)
inline

Definition at line 87 of file ReusableObjectHolder.h.

88  : m_availableQueue(std::move(iOther.m_availableQueue)), m_outstandingObjects(0) {
89  assert(0 == iOther.m_outstandingObjects);
90  }
assert(be >=bs)
std::atomic< size_t > m_outstandingObjects
oneapi::tbb::concurrent_queue< std::unique_ptr< T, Deleter > > m_availableQueue
def move(src, dest)
Definition: eostools.py:511

◆ ~ReusableObjectHolder()

template<class T, class Deleter = std::default_delete<T>>
edm::ReusableObjectHolder< T, Deleter >::~ReusableObjectHolder ( )
inlinenoexcept

Definition at line 91 of file ReusableObjectHolder.h.

91  {
93  std::unique_ptr<T, Deleter> item;
94  while (m_availableQueue.try_pop(item)) {
95  item.reset();
96  }
97  }
assert(be >=bs)
std::atomic< size_t > m_outstandingObjects
oneapi::tbb::concurrent_queue< std::unique_ptr< T, Deleter > > m_availableQueue

Member Function Documentation

◆ add()

template<class T, class Deleter = std::default_delete<T>>
void edm::ReusableObjectHolder< T, Deleter >::add ( std::unique_ptr< T, Deleter >  iItem)
inline

Adds the item to the cache. Use this function if you know ahead of time how many cached items you will need.

Definition at line 102 of file ReusableObjectHolder.h.

Referenced by counter.Counter::register().

102  {
103  if (nullptr != iItem) {
104  m_availableQueue.push(std::move(iItem));
105  }
106  }
oneapi::tbb::concurrent_queue< std::unique_ptr< T, Deleter > > m_availableQueue
def move(src, dest)
Definition: eostools.py:511

◆ addBack()

template<class T, class Deleter = std::default_delete<T>>
void edm::ReusableObjectHolder< T, Deleter >::addBack ( std::unique_ptr< T, Deleter >  iItem)
inlineprivate

Definition at line 158 of file ReusableObjectHolder.h.

Referenced by edm::ReusableObjectHolder< edm::ESProductHost >::wrapCustomDeleter().

158  {
159  m_availableQueue.push(std::move(iItem));
161  }
std::atomic< size_t > m_outstandingObjects
oneapi::tbb::concurrent_queue< std::unique_ptr< T, Deleter > > m_availableQueue
def move(src, dest)
Definition: eostools.py:511

◆ makeOrGet()

template<class T, class Deleter = std::default_delete<T>>
template<typename FM >
std::shared_ptr<T> edm::ReusableObjectHolder< T, Deleter >::makeOrGet ( FM &&  iMakeFunc)
inline

Takes an object from the queue if one is available, or creates one using iMakeFunc.

Definition at line 122 of file ReusableObjectHolder.h.

Referenced by edm::ReusableObjectHolder< edm::ESProductHost >::makeOrGetAndClear(), EcalSeverityLevelESProducer::produce(), RPCInverseCPPFLinkMapESProducer::produce(), RPCInverseTwinMuxLinkMapESProducer::produce(), RPCInverseOMTFLinkMapESProducer::produce(), EcalNextToDeadChannelESProducer::produce(), RPCInverseLBLinkMapESProducer::produce(), EcalLaserCorrectionService::produce(), EcalLaserCorrectionServiceMC::produce(), HcalDbProducer::produce(), HcalTPGCoderULUT::produce(), CastorDbProducer::produce(), edmtest::ESTestProducerBUsingHost::produce(), and DTGeometryESProducer::produce().

122  {
123  std::unique_ptr<T, Deleter> item;
124  if (m_availableQueue.try_pop(item)) {
126  } else {
127  return wrapCustomDeleter(makeUnique(iMakeFunc()));
128  }
129  }
std::unique_ptr< T > makeUnique(T *ptr)
oneapi::tbb::concurrent_queue< std::unique_ptr< T, Deleter > > m_availableQueue
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.
def move(src, dest)
Definition: eostools.py:511

◆ makeOrGetAndClear()

template<class T, class Deleter = std::default_delete<T>>
template<typename FM , typename FC >
std::shared_ptr<T> edm::ReusableObjectHolder< T, Deleter >::makeOrGetAndClear ( FM &&  iMakeFunc,
FC &&  iClearFunc 
)
inline

Takes an object from the queue if one is available, or creates one using iMakeFunc. Then, passes the object to iClearFunc, and returns it.

Definition at line 134 of file ReusableObjectHolder.h.

134  {
135  std::shared_ptr<T> returnValue = makeOrGet(std::forward<FM>(iMakeFunc));
136  iClearFunc(returnValue.get());
137  return returnValue;
138  }
std::shared_ptr< T > makeOrGet(FM &&iMakeFunc)
Takes an object from the queue if one is available, or creates one using iMakeFunc.

◆ makeUnique() [1/2]

template<class T, class Deleter = std::default_delete<T>>
std::unique_ptr<T> edm::ReusableObjectHolder< T, Deleter >::makeUnique ( T ptr)
inlineprivate

Definition at line 150 of file ReusableObjectHolder.h.

Referenced by edm::ReusableObjectHolder< edm::ESProductHost >::makeOrGet().

150  {
151  static_assert(std::is_same_v<Deleter, std::default_delete<T>>,
152  "Generating functions returning raw pointers are supported only with std::default_delete<T>");
153  return std::unique_ptr<T>{ptr};
154  }

◆ makeUnique() [2/2]

template<class T, class Deleter = std::default_delete<T>>
std::unique_ptr<T, Deleter> edm::ReusableObjectHolder< T, Deleter >::makeUnique ( std::unique_ptr< T, Deleter >  ptr)
inlineprivate

Definition at line 156 of file ReusableObjectHolder.h.

156 { return ptr; }

◆ tryToGet()

template<class T, class Deleter = std::default_delete<T>>
std::shared_ptr<T> edm::ReusableObjectHolder< T, Deleter >::tryToGet ( )
inline

Tries to get an already created object, if none are available, returns an empty shared_ptr. Use this function in conjunction with add()

Definition at line 111 of file ReusableObjectHolder.h.

111  {
112  std::unique_ptr<T, Deleter> item;
113  if (m_availableQueue.try_pop(item)) {
115  } else {
116  return std::shared_ptr<T>{};
117  }
118  }
oneapi::tbb::concurrent_queue< std::unique_ptr< T, Deleter > > m_availableQueue
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.
def move(src, dest)
Definition: eostools.py:511

◆ wrapCustomDeleter()

template<class T, class Deleter = std::default_delete<T>>
std::shared_ptr<T> edm::ReusableObjectHolder< T, Deleter >::wrapCustomDeleter ( std::unique_ptr< T, Deleter >  item)
inlineprivate

Wraps an object in a shared_ptr<T> with a custom deleter, that hands the wrapped object.

Definition at line 143 of file ReusableObjectHolder.h.

Referenced by edm::ReusableObjectHolder< edm::ESProductHost >::makeOrGet(), and edm::ReusableObjectHolder< edm::ESProductHost >::tryToGet().

143  {
144  auto deleter = item.get_deleter();
146  return std::shared_ptr<T>{
147  item.release(), [this, deleter](T* iItem) { this->addBack(std::unique_ptr<T, Deleter>{iItem, deleter}); }};
148  }
void addBack(std::unique_ptr< T, Deleter > iItem)
std::atomic< size_t > m_outstandingObjects
long double T

Member Data Documentation

◆ m_availableQueue

template<class T, class Deleter = std::default_delete<T>>
oneapi::tbb::concurrent_queue<std::unique_ptr<T, Deleter> > edm::ReusableObjectHolder< T, Deleter >::m_availableQueue
private

◆ m_outstandingObjects

template<class T, class Deleter = std::default_delete<T>>
std::atomic<size_t> edm::ReusableObjectHolder< T, Deleter >::m_outstandingObjects
private