Main MRPT website > C++ reference
MRPT logo
CGenericMemoryPool.h
Go to the documentation of this file.
00001 /* +---------------------------------------------------------------------------+
00002    |          The Mobile Robot Programming Toolkit (MRPT) C++ library          |
00003    |                                                                           |
00004    |                       http://www.mrpt.org/                                |
00005    |                                                                           |
00006    |   Copyright (C) 2005-2011  University of Malaga                           |
00007    |                                                                           |
00008    |    This software was written by the Machine Perception and Intelligent    |
00009    |      Robotics Lab, University of Malaga (Spain).                          |
00010    |    Contact: Jose-Luis Blanco  <jlblanco@ctima.uma.es>                     |
00011    |                                                                           |
00012    |  This file is part of the MRPT project.                                   |
00013    |                                                                           |
00014    |     MRPT is free software: you can redistribute it and/or modify          |
00015    |     it under the terms of the GNU General Public License as published by  |
00016    |     the Free Software Foundation, either version 3 of the License, or     |
00017    |     (at your option) any later version.                                   |
00018    |                                                                           |
00019    |   MRPT is distributed in the hope that it will be useful,                 |
00020    |     but WITHOUT ANY WARRANTY; without even the implied warranty of        |
00021    |     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         |
00022    |     GNU General Public License for more details.                          |
00023    |                                                                           |
00024    |     You should have received a copy of the GNU General Public License     |
00025    |     along with MRPT.  If not, see <http://www.gnu.org/licenses/>.         |
00026    |                                                                           |
00027    +---------------------------------------------------------------------------+ */
00028 #ifndef  MRPT_MEMORY_POOL_H
00029 #define  MRPT_MEMORY_POOL_H
00030 
00031 #include <mrpt/synch/CCriticalSection.h>
00032 
00033 namespace mrpt
00034 {
00035         namespace system
00036         {
00037                 /** A generic system for versatile memory pooling.
00038                   *   This class implements the singleton pattern so a unique instance exists for each combination of template parameters.
00039                   *   All methods are thread-safe.
00040                   *
00041                   *   Basic usage:
00042                   *     - When needed, call \a request_memory() to check the availability of memory in the pool.
00043                   *             - At your class destructor, donate the memory to the pool with \a dump_to_pool().
00044                   *
00045                   *   Notice that memory requests are checked against memory blocks in the pool via a user-defined function:
00046                   *
00047                   *    bool POOLABLE_DATA::isSuitable(const POOLABLE_DATA & req) const { ... }
00048                   *
00049                   *   For an example of how to handle a memory pool, see the class mrpt::slam::CObservation3DRangeScan
00050                   *
00051                   *  \tparam POOLABLE_DATA A struct with user-defined objects which actually contain the memory blocks (e.g. one or more std::vector).
00052                   *  \tparam DATA_PARAMS A struct with user information about each memory block (e.g. size of a std::vector)
00053                   * \ingroup mrpt_memory
00054                   */
00055                 template <class DATA_PARAMS,class POOLABLE_DATA>
00056                 class CGenericMemoryPool
00057                 {
00058                 private:
00059                         typedef std::list<std::pair<DATA_PARAMS,POOLABLE_DATA*> > TList;
00060                         TList                          m_pool;
00061                         mrpt::synch::CCriticalSection  m_pool_cs;
00062                         size_t                         m_maxPoolEntries;
00063 
00064                         CGenericMemoryPool() : m_maxPoolEntries(5)
00065                         {
00066                         }
00067 
00068                 public:
00069                         inline size_t getMemoryPoolMaxSize() const                     { return m_maxPoolEntries; }
00070                         inline void   setMemoryPoolMaxSize(const size_t maxNumEntries) { m_maxPoolEntries = maxNumEntries; }
00071 
00072                         /** Singleton: Return the unique instance of this class for a given template arguments: */
00073                         static CGenericMemoryPool<DATA_PARAMS,POOLABLE_DATA> & getInstance()
00074                         {
00075                                 static CGenericMemoryPool<DATA_PARAMS,POOLABLE_DATA> inst;
00076                                 return inst;
00077                         }
00078 
00079                         /** Request a block of data which fulfils the size requirements stated in \a params.
00080                           *  Notice that the decision on the suitability of each pool'ed block is done by DATA_PARAMS::isSuitable().
00081                           *  \return The block of data, or NULL if none suitable was found in the pool.
00082                           *  \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.
00083                           */
00084                         POOLABLE_DATA * request_memory(const DATA_PARAMS &params)
00085                         {
00086                                 // A quick check first:
00087                                 if (m_pool.empty()) return NULL;
00088 
00089                                 mrpt::synch::CCriticalSectionLocker lock( &m_pool_cs );
00090                                 for (typename TList::iterator it=m_pool.begin();it!=m_pool.end();++it) {
00091                                         if (it->first.isSuitable(params))
00092                                         {
00093                                                 POOLABLE_DATA * ret = it->second;
00094                                                 m_pool.erase(it);
00095                                                 return ret;
00096                                         }
00097                                 }
00098                                 return NULL;
00099                         }
00100 
00101                         /** Saves the passed data block (characterized by \a params) to the pool.
00102                           *  If the overall size of the pool is above the limit, the oldest entry is removed.
00103                           *  \note It is a responsibility of the user to allocate in dynamic memory the "POOLABLE_DATA" object with "new".
00104                           */
00105                         void dump_to_pool(const DATA_PARAMS &params, POOLABLE_DATA *block)
00106                         {
00107                                 mrpt::synch::CCriticalSectionLocker lock( &m_pool_cs );
00108 
00109                                 while (m_pool.size()>=m_maxPoolEntries) // Free old data if needed
00110                                         m_pool.erase(m_pool.begin());
00111 
00112                                 m_pool.push_back( typename TList::value_type(params,block) );
00113                         }
00114 
00115                         ~CGenericMemoryPool()
00116                         {
00117                                 // Free remaining memory blocks:
00118                                 mrpt::synch::CCriticalSectionLocker lock( &m_pool_cs );
00119                                 for (typename TList::iterator it=m_pool.begin();it!=m_pool.end();++it)
00120                                         delete it->second;
00121                                 m_pool.clear();
00122                         }
00123                 };
00124 
00125         } // End of namespace
00126 } // End of namespace
00127 
00128 #endif



Page generated by Doxygen 1.7.5 for MRPT 0.9.5 SVN: at Thu Oct 13 21:25:36 UTC 2011