Main MRPT website > C++ reference
MRPT logo
CGenericMemoryPool.h
Go to the documentation of this file.
1 /* +---------------------------------------------------------------------------+
2  | The Mobile Robot Programming Toolkit (MRPT) C++ library |
3  | |
4  | http://www.mrpt.org/ |
5  | |
6  | Copyright (C) 2005-2012 University of Malaga |
7  | |
8  | This software was written by the Machine Perception and Intelligent |
9  | Robotics Lab, University of Malaga (Spain). |
10  | Contact: Jose-Luis Blanco <jlblanco@ctima.uma.es> |
11  | |
12  | This file is part of the MRPT project. |
13  | |
14  | MRPT is free software: you can redistribute it and/or modify |
15  | it under the terms of the GNU General Public License as published by |
16  | the Free Software Foundation, either version 3 of the License, or |
17  | (at your option) any later version. |
18  | |
19  | MRPT is distributed in the hope that it will be useful, |
20  | but WITHOUT ANY WARRANTY; without even the implied warranty of |
21  | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
22  | GNU General Public License for more details. |
23  | |
24  | You should have received a copy of the GNU General Public License |
25  | along with MRPT. If not, see <http://www.gnu.org/licenses/>. |
26  | |
27  +---------------------------------------------------------------------------+ */
28 #ifndef MRPT_MEMORY_POOL_H
29 #define MRPT_MEMORY_POOL_H
30 
32 
33 namespace mrpt
34 {
35  namespace system
36  {
37  /** A generic system for versatile memory pooling.
38  * This class implements the singleton pattern so a unique instance exists for each combination of template parameters.
39  * All methods are thread-safe.
40  *
41  * Basic usage:
42  * - When needed, call \a request_memory() to check the availability of memory in the pool.
43  * - At your class destructor, donate the memory to the pool with \a dump_to_pool().
44  *
45  * Notice that memory requests are checked against memory blocks in the pool via a user-defined function:
46  *
47  * bool POOLABLE_DATA::isSuitable(const POOLABLE_DATA & req) const { ... }
48  *
49  * For an example of how to handle a memory pool, see the class mrpt::slam::CObservation3DRangeScan
50  *
51  * \tparam POOLABLE_DATA A struct with user-defined objects which actually contain the memory blocks (e.g. one or more std::vector).
52  * \tparam DATA_PARAMS A struct with user information about each memory block (e.g. size of a std::vector)
53  * \ingroup mrpt_memory
54  */
55  template <class DATA_PARAMS,class POOLABLE_DATA>
57  {
58  private:
59  typedef std::list<std::pair<DATA_PARAMS,POOLABLE_DATA*> > TList;
63  bool & m_was_destroyed; //!< With this trick we get rid of the "global destruction order fiasco" ;-)
64 
65  CGenericMemoryPool(const size_t max_pool_entries, bool &was_destroyed ) : m_maxPoolEntries(max_pool_entries), m_was_destroyed(was_destroyed)
66  {
67  m_was_destroyed = false;
68  }
69 
70  public:
71  inline size_t getMemoryPoolMaxSize() const { return m_maxPoolEntries; }
72  inline void setMemoryPoolMaxSize(const size_t maxNumEntries) { m_maxPoolEntries = maxNumEntries; }
73 
74  /** Construct-on-first-use (~singleton) pattern: Return the unique instance of this class for a given template arguments,
75  * or NULL if it was once created but it's been destroyed (which means we're in the program global destruction phase).
76  */
77  static CGenericMemoryPool<DATA_PARAMS,POOLABLE_DATA> * getInstance(const size_t max_pool_entries = 5)
78  {
79  static bool was_destroyed = false;
80  static CGenericMemoryPool<DATA_PARAMS,POOLABLE_DATA> inst(max_pool_entries, was_destroyed);
81  return was_destroyed ? NULL : &inst;
82  }
83 
84  /** Request a block of data which fulfils the size requirements stated in \a params.
85  * Notice that the decision on the suitability of each pool'ed block is done by DATA_PARAMS::isSuitable().
86  * \return The block of data, or NULL if none suitable was found in the pool.
87  * \note It is a responsibility of the user to free with "delete" the "POOLABLE_DATA" object itself once the memory has been extracted from its elements.
88  */
89  POOLABLE_DATA * request_memory(const DATA_PARAMS &params)
90  {
91  // A quick check first:
92  if (m_pool.empty()) return NULL;
93 
95  for (typename TList::iterator it=m_pool.begin();it!=m_pool.end();++it) {
96  if (it->first.isSuitable(params))
97  {
98  POOLABLE_DATA * ret = it->second;
99  m_pool.erase(it);
100  return ret;
101  }
102  }
103  return NULL;
104  }
105 
106  /** Saves the passed data block (characterized by \a params) to the pool.
107  * If the overall size of the pool is above the limit, the oldest entry is removed.
108  * \note It is a responsibility of the user to allocate in dynamic memory the "POOLABLE_DATA" object with "new".
109  */
110  void dump_to_pool(const DATA_PARAMS &params, POOLABLE_DATA *block)
111  {
113 
114  while (m_pool.size()>=m_maxPoolEntries) // Free old data if needed
115  {
116  if (m_pool.begin()->second) delete m_pool.begin()->second;
117  m_pool.erase(m_pool.begin());
118  }
119 
120  m_pool.push_back( typename TList::value_type(params,block) );
121  }
122 
124  {
125  m_was_destroyed = true;
126  // Free remaining memory blocks:
128  for (typename TList::iterator it=m_pool.begin();it!=m_pool.end();++it)
129  delete it->second;
130  m_pool.clear();
131  }
132  };
133 
134  } // End of namespace
135 } // End of namespace
136 
137 #endif



Page generated by Doxygen 1.8.3 for MRPT 0.9.6 SVN: at Fri Feb 15 22:05:02 EST 2013