CMS 3D CMS Logo

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

#include <ReusableObjectHolder.h>

Public Member Functions

void add (std::unique_ptr< T > iItem)
 
template<typename F >
std::shared_ptr< TmakeOrGet (F iFunc)
 If there isn't an object already available, creates a new one using iFunc. More...
 
template<typename FM , typename FC >
std::shared_ptr< TmakeOrGetAndClear (FM iMakeFunc, FC iClearFunc)
 
 ReusableObjectHolder ()
 
std::shared_ptr< TtryToGet ()
 
 ~ReusableObjectHolder ()
 

Private Member Functions

void addBack (T *iItem)
 

Private Attributes

tbb::concurrent_queue< T * > m_availableQueue
 
std::atomic< size_t > m_outstandingObjects
 

Detailed Description

template<class T>
class edm::ReusableObjectHolder< T >

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 it to call makeOrGetAndClear An example use would be

auto objectToUse = holder.makeOrGetAndClear(
[]() { return new MyObject(10); }, //makes new one
[](MyObject* old) {old->reset(); } //resets old one
);

If you always want to set the values you can use makeOrGet

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

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
}

Definition at line 77 of file ReusableObjectHolder.h.

Constructor & Destructor Documentation

template<class T >
edm::ReusableObjectHolder< T >::ReusableObjectHolder ( )
inline

Definition at line 79 of file ReusableObjectHolder.h.

std::atomic< size_t > m_outstandingObjects
template<class T >
edm::ReusableObjectHolder< T >::~ReusableObjectHolder ( )
inline

Definition at line 81 of file ReusableObjectHolder.h.

References edm::ReusableObjectHolder< T >::m_availableQueue, and edm::ReusableObjectHolder< T >::m_outstandingObjects.

81  {
82  assert(0==m_outstandingObjects);
83  T* item = 0;
84  while( m_availableQueue.try_pop(item)) {
85  delete item;
86  }
87  }
tbb::concurrent_queue< T * > m_availableQueue
std::atomic< size_t > m_outstandingObjects
long double T

Member Function Documentation

template<class T >
void edm::ReusableObjectHolder< T >::add ( std::unique_ptr< T 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 92 of file ReusableObjectHolder.h.

References edm::ReusableObjectHolder< T >::m_availableQueue.

Referenced by edm::ReusableObjectHolder< T >::makeOrGet(), edm::ReusableObjectHolder< T >::makeOrGetAndClear(), and counter.Counter::register().

92  {
93  if(0!=iItem) {
94  m_availableQueue.push(iItem.release());
95  }
96  }
tbb::concurrent_queue< T * > m_availableQueue
template<class T >
void edm::ReusableObjectHolder< T >::addBack ( T iItem)
inlineprivate

Definition at line 137 of file ReusableObjectHolder.h.

References edm::ReusableObjectHolder< T >::m_availableQueue, and edm::ReusableObjectHolder< T >::m_outstandingObjects.

137  {
138  m_availableQueue.push(iItem);
140  }
tbb::concurrent_queue< T * > m_availableQueue
std::atomic< size_t > m_outstandingObjects
template<class T >
template<typename F >
std::shared_ptr<T> edm::ReusableObjectHolder< T >::makeOrGet ( F  iFunc)
inline

If there isn't an object already available, creates a new one using iFunc.

Definition at line 115 of file ReusableObjectHolder.h.

References edm::ReusableObjectHolder< T >::add(), and edm::ReusableObjectHolder< T >::tryToGet().

115  {
116  std::shared_ptr<T> returnValue;
117  while ( ! ( returnValue = tryToGet()) ) {
118  add( std::unique_ptr<T>(iFunc()) );
119  }
120  return returnValue;
121  }
void add(std::unique_ptr< T > iItem)
std::shared_ptr< T > tryToGet()
template<class T >
template<typename FM , typename FC >
std::shared_ptr<T> edm::ReusableObjectHolder< T >::makeOrGetAndClear ( FM  iMakeFunc,
FC  iClearFunc 
)
inline

If there is an object already available, passes the object to iClearFunc and then returns the object. If there is not an object already available, creates a new one using iMakeFunc

Definition at line 127 of file ReusableObjectHolder.h.

References edm::ReusableObjectHolder< T >::add(), and edm::ReusableObjectHolder< T >::tryToGet().

127  {
128  std::shared_ptr<T> returnValue;
129  while ( ! ( returnValue = tryToGet()) ) {
130  add( std::unique_ptr<T>(iMakeFunc()) );
131  }
132  iClearFunc(returnValue.get());
133  return returnValue;
134  }
void add(std::unique_ptr< T > iItem)
std::shared_ptr< T > tryToGet()
template<class T >
std::shared_ptr<T> edm::ReusableObjectHolder< T >::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 101 of file ReusableObjectHolder.h.

References edm::ReusableObjectHolder< T >::m_availableQueue, and edm::ReusableObjectHolder< T >::m_outstandingObjects.

Referenced by edm::ReusableObjectHolder< T >::makeOrGet(), and edm::ReusableObjectHolder< T >::makeOrGetAndClear().

101  {
102  T* item = 0;
103  m_availableQueue.try_pop(item);
104  if (0==item) {
105  return std::shared_ptr<T>{};
106  }
107  //instead of deleting, hand back to queue
108  auto pHolder = this;
110  return std::shared_ptr<T>{item, [pHolder](T* iItem) {pHolder->addBack(iItem);} };
111  }
tbb::concurrent_queue< T * > m_availableQueue
std::atomic< size_t > m_outstandingObjects
long double T

Member Data Documentation

template<class T >
tbb::concurrent_queue<T*> edm::ReusableObjectHolder< T >::m_availableQueue
private
template<class T >
std::atomic<size_t> edm::ReusableObjectHolder< T >::m_outstandingObjects
private