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