MRPT  2.0.1
CGenericMemoryPool.h
Go to the documentation of this file.
1 /* +------------------------------------------------------------------------+
2  | Mobile Robot Programming Toolkit (MRPT) |
3  | https://www.mrpt.org/ |
4  | |
5  | Copyright (c) 2005-2020, Individual contributors, see AUTHORS file |
6  | See: https://www.mrpt.org/Authors - All rights reserved. |
7  | Released under BSD License. See: https://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 (auto it = m_pool.begin(); it != m_pool.end(); ++it)
98  {
99  if (it->first.isSuitable(params))
100  {
101  POOLABLE_DATA* ret = it->second;
102  m_pool.erase(it);
103  return ret;
104  }
105  }
106  return nullptr;
107  }
108 
109  /** Saves the passed data block (characterized by \a params) to the pool.
110  * If the overall size of the pool is above the limit, the oldest entry is
111  * removed.
112  * \note It is a responsibility of the user to allocate in dynamic memory
113  * the "POOLABLE_DATA" object with "new".
114  */
115  void dump_to_pool(const DATA_PARAMS& params, POOLABLE_DATA* block)
116  {
117  std::lock_guard<std::mutex> lock(m_pool_cs);
118 
119  while (m_pool.size() >= m_maxPoolEntries) // Free old data if needed
120  {
121  if (m_pool.begin()->second) delete m_pool.begin()->second;
122  m_pool.erase(m_pool.begin());
123  }
124 
125  m_pool.push_back(typename TList::value_type(params, block));
126  }
127 
129  {
130  m_was_destroyed = true;
131  // Free remaining memory blocks:
132  std::lock_guard<std::mutex> lock(m_pool_cs);
133  for (auto it = m_pool.begin(); it != m_pool.end(); ++it)
134  delete it->second;
135  m_pool.clear();
136  }
137 };
138 
139 } // namespace mrpt::system
std::list< std::pair< DATA_PARAMS, POOLABLE_DATA * > > TList
void dump_to_pool(const DATA_PARAMS &params, POOLABLE_DATA *block)
Saves the passed data block (characterized by params) to the pool.
mrpt::vision::TStereoCalibParams params
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)
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 2.0.1 Git: 0fef1a6d7 Fri Apr 3 23:00:21 2020 +0200 at vie abr 3 23:20:28 CEST 2020