qpcpp/include/qmpool.h
Quantum Leaps e0f9c36c2f 4.5.01
2012-08-14 18:00:48 -04:00

209 lines
7.6 KiB
C++

//////////////////////////////////////////////////////////////////////////////
// Product: QP/C++
// Last Updated for Version: 4.5.02
// Date of the Last Update: Jul 02, 2012
//
// Q u a n t u m L e a P s
// ---------------------------
// innovating embedded systems
//
// Copyright (C) 2002-2012 Quantum Leaps, LLC. All rights reserved.
//
// This program is open source software: you can redistribute it and/or
// modify it under the terms of the GNU General Public License as published
// by the Free Software Foundation, either version 2 of the License, or
// (at your option) any later version.
//
// Alternatively, this program may be distributed and modified under the
// terms of Quantum Leaps commercial licenses, which expressly supersede
// the GNU General Public License and are specifically designed for
// licensees interested in retaining the proprietary status of their code.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
//
// Contact information:
// Quantum Leaps Web sites: http://www.quantum-leaps.com
// http://www.state-machine.com
// e-mail: info@quantum-leaps.com
//////////////////////////////////////////////////////////////////////////////
#ifndef qmpool_h
#define qmpool_h
/// \file
/// \ingroup qf
/// \brief platform-independent memory pool interface.
///
/// This header file must be included in all QF ports that use native QF
/// memory pool implementation.
#ifndef QF_MPOOL_SIZ_SIZE
/// \brief macro to override the default ::QMPoolSize size.
/// Valid values 1, 2, or 4; default 2
#define QF_MPOOL_SIZ_SIZE 2
#endif
#ifndef QF_MPOOL_CTR_SIZE
/// \brief macro to override the default QMPoolCtr size.
/// Valid values 1, 2, or 4; default 2
#define QF_MPOOL_CTR_SIZE 2
#endif
//////////////////////////////////////////////////////////////////////////////
QP_BEGIN_
#if (QF_MPOOL_SIZ_SIZE == 1)
/// \brief The data type to store the block-size based on the macro
/// #QF_MPOOL_SIZ_SIZE.
///
/// The dynamic range of this data type determines the maximum size
/// of blocks that can be managed by the native QF event pool.
typedef uint8_t QMPoolSize;
#elif (QF_MPOOL_SIZ_SIZE == 2)
typedef uint16_t QMPoolSize;
#elif (QF_MPOOL_SIZ_SIZE == 4)
typedef uint32_t QMPoolSize;
#else
#error "QF_MPOOL_SIZ_SIZE defined incorrectly, expected 1, 2, or 4"
#endif
#if (QF_MPOOL_CTR_SIZE == 1)
/// \brief The data type to store the block-counter based on the macro
/// #QF_MPOOL_CTR_SIZE.
///
/// The dynamic range of this data type determines the maximum number
/// of blocks that can be stored in the pool.
typedef uint8_t QMPoolCtr;
#elif (QF_MPOOL_CTR_SIZE == 2)
typedef uint16_t QMPoolCtr;
#elif (QF_MPOOL_CTR_SIZE == 4)
typedef uint32_t QMPoolCtr;
#else
#error "QF_MPOOL_CTR_SIZE defined incorrectly, expected 1, 2, or 4"
#endif
//////////////////////////////////////////////////////////////////////////////
/// \brief Native QF memory pool class
///
/// This class describes the native QF memory pool, which can be used as
/// the event pool for dynamic event allocation, or as a fast, deterministic
/// fixed block-size heap for any other objects in your application.
///
/// The ::QMPool structure contains only data members for managing a memory
/// pool, but does not contain the pool storage, which must be provided
/// externally during the pool initialization.
///
/// The native QF event pool is configured by defining the macro
/// #QF_EPOOL_TYPE_ as QEQueue in the specific QF port header file.
class QMPool {
private:
/// start of the memory managed by this memory pool
void *m_start;
/// end of the memory managed by this memory pool
void *m_end;
/// linked list of free blocks
void *m_free;
/// maximum block size (in bytes)
QMPoolSize m_blockSize;
/// total number of blocks
QMPoolCtr m_nTot;
/// number of free blocks remaining
QMPoolCtr m_nFree;
/// minimum number of free blocks ever present in this pool
///
/// \note this attribute remembers the low watermark of the pool,
/// which provides a valuable information for sizing event pools.
/// \sa QF::getPoolMargin().
QMPoolCtr m_nMin;
public:
/// \brief Initializes the native QF event pool
///
/// The parameters are as follows: \a poolSto is the pool storage,
/// \a poolSize is the size of the pool storage in bytes, and
/// \a blockSize is the block size of this pool.
///
/// The caller of this method must make sure that the \a poolSto pointer
/// is properly aligned. In particular, it must be possible to efficiently
/// store a pointer at the location pointed to by \a poolSto.
/// Internally, the QMPool::init() function rounds up the block size
/// \a blockSize so that it can fit an integer number of pointers.
/// This is done to achieve proper alignment of the blocks within the
/// pool.
///
/// \note Due to the rounding of block size the actual capacity of the
/// pool might be less than (\a poolSize / \a blockSize). You can check
/// the capacity of the pool by calling the QF::getPoolMargin() function.
void init(void * const poolSto, uint32_t const poolSize,
QMPoolSize const blockSize);
/// \brief Obtains a memory block from a memory pool.
///
/// The only parameter \a me is a pointer to the ::QMPool from which the
/// block is requested. The function returns a pointer to the allocated
/// memory block or NULL if no free blocks are available.
///
/// A allocated block must be returned to the same pool from which it has
/// been allocated.
///
/// This function can be called from any task level or ISR level.
///
/// \note The memory pool \a me must be initialized before any events can
/// be requested from it. Also, the QMPool::get() function uses internally
/// a QF critical section, so you should be careful not to call it from
/// within a critical section when nesting of critical section is not
/// supported.
///
/// \sa QMPool::put()
void *get(void);
/// \brief Returns a memory block back to a memory pool.
///
///
/// This function can be called from any task level or ISR level.
///
/// \note The block must be allocated from the same memory pool to which
/// it is returned. The QMPool::put() function raises an assertion if the
/// returned pointer to the block points outside of the original memory
/// buffer managed by the memory pool. Also, the QMPool::put() function
/// uses internally a QF critical section, so you should be careful not
/// to call it from within a critical section when nesting of critical
/// section is not supported.
///
/// \sa QMPool::get()
void put(void * const b);
/// \brief return the fixed block-size of the blocks managed by this pool
QMPoolSize getBlockSize(void) const {
return m_blockSize;
}
private:
friend class QF;
};
QP_END_
/// \brief Memory pool element to allocate correctly aligned storage
/// for QMPool class.
///
#define QF_MPOOL_EL(type_) \
struct { void *sto_[((sizeof(type_) - 1U)/sizeof(void*)) + 1U]; }
#endif // qmpool_h