MRPT  1.9.9
CGenericMemoryPool.h
Go to the documentation of this file.
1 /* +------------------------------------------------------------------------+
2  | Mobile Robot Programming Toolkit (MRPT) |
3  | http://www.mrpt.org/ |
4  | |
5  | Copyright (c) 2005-2018, Individual contributors, see AUTHORS file |
6  | See: http://www.mrpt.org/Authors - All rights reserved. |
7  | Released under BSD License. See details in http://www.mrpt.org/License |
8  +------------------------------------------------------------------------+ */
9 #pragma once
10 
11 #include <list>
12 #include <mutex>
13 #include <utility> // std::pair
14 
15 namespace mrpt::system
16 {
17 /** A generic system for versatile memory pooling.
18  * This class implements the singleton pattern so a unique instance exists
19  *for each combination of template parameters.
20  * All methods are thread-safe.
21  *
22  * Basic usage:
23  * - When needed, call \a request_memory() to check the availability of
24  *memory in the pool.
25  * - At your class destructor, donate the memory to the pool with \a
26  *dump_to_pool().
27  *
28  * Notice that memory requests are checked against memory blocks in the pool
29  *via a user-defined function:
30  *
31  * bool POOLABLE_DATA::isSuitable(const POOLABLE_DATA & req) const { ... }
32  *
33  * For an example of how to handle a memory pool, see the class
34  *mrpt::obs::CObservation3DRangeScan
35  *
36  * \tparam POOLABLE_DATA A struct with user-defined objects which actually
37  *contain the memory blocks (e.g. one or more std::vector).
38  * \tparam DATA_PARAMS A struct with user information about each memory block
39  *(e.g. size of a std::vector)
40  * \ingroup mrpt_memory
41  */
42 template <class DATA_PARAMS, class POOLABLE_DATA>
44 {
45  private:
46  using TList = std::list<std::pair<DATA_PARAMS, POOLABLE_DATA*>>;
48  std::mutex m_pool_cs;
50  /** With this trick we get rid of the "global destruction order fiasco" ;-)
51  */
53 
54  CGenericMemoryPool(const size_t max_pool_entries, bool& was_destroyed)
55  : m_maxPoolEntries(max_pool_entries), m_was_destroyed(was_destroyed)
56  {
57  m_was_destroyed = false;
58  }
59 
60  public:
61  inline size_t getMemoryPoolMaxSize() const { return m_maxPoolEntries; }
62  inline void setMemoryPoolMaxSize(const size_t maxNumEntries)
63  {
64  m_maxPoolEntries = maxNumEntries;
65  }
66 
67  /** Construct-on-first-use (~singleton) pattern: Return the unique instance
68  * of this class for a given template arguments,
69  * or nullptr if it was once created but it's been destroyed (which means
70  * we're in the program global destruction phase).
71  */
73  const size_t max_pool_entries = 5)
74  {
75  static bool was_destroyed = false;
77  max_pool_entries, was_destroyed);
78  return was_destroyed ? nullptr : &inst;
79  }
80 
81  /** Request a block of data which fulfils the size requirements stated in \a
82  * params.
83  * Notice that the decision on the suitability of each pool'ed block is
84  * done by DATA_PARAMS::isSuitable().
85  * \return The block of data, or nullptr if none suitable was found in the
86  * pool.
87  * \note It is a responsibility of the user to free with "delete" the
88  * "POOLABLE_DATA" object itself once the memory has been extracted from its
89  * elements.
90  */
91  POOLABLE_DATA* request_memory(const DATA_PARAMS& params)
92  {
93  // A quick check first:
94  if (m_pool.empty()) return nullptr;
95 
96  std::lock_guard<std::mutex> lock(m_pool_cs);
97  for (typename TList::iterator it = m_pool.begin(); it != m_pool.end();
98  ++it)
99  {
100  if (it->first.isSuitable(params))
101  {
102  POOLABLE_DATA* ret = it->second;
103  m_pool.erase(it);
104  return ret;
105  }
106  }
107  return nullptr;
108  }
109 
110  /** Saves the passed data block (characterized by \a params) to the pool.
111  * If the overall size of the pool is above the limit, the oldest entry is
112  * removed.
113  * \note It is a responsibility of the user to allocate in dynamic memory
114  * the "POOLABLE_DATA" object with "new".
115  */
116  void dump_to_pool(const DATA_PARAMS& params, POOLABLE_DATA* block)
117  {
118  std::lock_guard<std::mutex> lock(m_pool_cs);
119 
120  while (m_pool.size() >= m_maxPoolEntries) // Free old data if needed
121  {
122  if (m_pool.begin()->second) delete m_pool.begin()->second;
123  m_pool.erase(m_pool.begin());
124  }
125 
126  m_pool.push_back(typename TList::value_type(params, block));
127  }
128 
130  {
131  m_was_destroyed = true;
132  // Free remaining memory blocks:
133  std::lock_guard<std::mutex> lock(m_pool_cs);
134  for (typename TList::iterator it = m_pool.begin(); it != m_pool.end();
135  ++it)
136  delete it->second;
137  m_pool.clear();
138  }
139 };
140 
141 }
142 
std::list< std::pair< DATA_PARAMS, POOLABLE_DATA * > > TList
Scalar * iterator
Definition: eigen_plugins.h:26
void dump_to_pool(const DATA_PARAMS &params, POOLABLE_DATA *block)
Saves the passed data block (characterized by params) to the pool.
POOLABLE_DATA * request_memory(const DATA_PARAMS &params)
Request a block of data which fulfils the size requirements stated in params.
A generic system for versatile memory pooling.
void setMemoryPoolMaxSize(const size_t maxNumEntries)
bool & m_was_destroyed
With this trick we get rid of the "global destruction order fiasco" ;-)
CGenericMemoryPool(const size_t max_pool_entries, bool &was_destroyed)
GLenum const GLfloat * params
Definition: glext.h:3534
static CGenericMemoryPool< DATA_PARAMS, POOLABLE_DATA > * getInstance(const size_t max_pool_entries=5)
Construct-on-first-use (~singleton) pattern: Return the unique instance of this class for a given tem...



Page generated by Doxygen 1.8.14 for MRPT 1.9.9 Git: 7d5e6d718 Fri Aug 24 01:51:28 2018 +0200 at lun nov 2 08:35:50 CET 2020