#ifndef _apl_memory_mempoolapi_h_
#define _apl_memory_mempoolapi_h_
/*----------------------------------------------------------------------------
** SUMMARY: Memory Pool Interface (MEMPOOL)
**
** DESCRIPTION:
**  This file provides an interface for creating and using memory pools.  
**  Each memory pool contains a collection of N same sized blocks of 
**  memory, i.e. each memory pool is heap that can only  allocate fixed size 
**  blocks.  The application can create many memory pools and each memory 
**  pool has its own block size. This interface can be used in 'parallel' 
**  (i.e. co-exist) with other Memory interfaces. 
**
**  OUT-OF-MEMORY
**  -------------
**  The application can at compile time, determine the behavior for
**  the out-of-memory condition.  By default, Apl_memPoolAllocate() returns
**  a NULL pointer when the heap has been exhausted.  However, by using the
**  the compile switch, USE_APL_MEMPOOL_FATAL_ERROR_WHEN_OUTOFMEMORY, 
**  Apl_memPoolAllocate() will generate a fatal error when it is unable to 
**  satifiy the application request for memory.
**
**  MEMORY ALIGNMENT
**  ----------------
**  By default all blocks allocated from all memory pools are aligned on 
**  even address boundaries.  If the application/platform requires different 
**  alignment then it needs to set 'OPTION_APL_MEMPOOL_ALIGNMENT_SIZE' to the 
**  size, in bytes, of the alignment.  For example, for alignment on 4 byte 
**  boundaries, set OPTION_APL_MEMPOOL_ALIGNMENT_SIZE equal to 4. Boundaries 
**  of 1, 2, and 4 are supported.  
**  NOTE: When creating a memory pool, the application is RESPONSIBLE for 
**        providing the raw memory and that raw memory MUST be properly 
**        aligned to a 'OPTION_APL_MEMPOOL_ALIGNMENT_SIZE' boundary.
**  
**
** CONFIGURATION 
** -------------
**  COMPILE:     USE_APL_MEMPOOL_FATAL_ERROR_WHEN_OUTOFMEMORY
**
**  APPLICATION: OPTION_APL_MEMPOOL_ALIGNMENT_SIZE
**
**  PLATFORM:    none.
**
**
**  NOTES:
**  1. Unless explicitly stated, NONE of the following methods may be called
**     from interrtup service routines.
**  2. For efficency/optimization some methods are 'inlined'.  The inlining
**     is done by using the preprocessor/macros.  The application should
**     treat all methods as function calls and not rely on the fact they may
**     be currently defined as macros.
----------------------------------------------------------------------------*/

#include "aplcfg.h"                 /* For: Application configuration */
#include "apl/types/types.h"        /* For: basic types */


#ifdef __cplusplus
extern "C" {
#endif


/*-------------- ERRORS ----------------------------------------------------*/
/** The handle of the 'offending' memory pool is reported with the error */
#define APL_ERRSTR_MEMPOOL_OUT_OF_MEMORY        "MEMPOOL: No available free blocks.  Memory Pool Handle="
/***/
#define APL_ERR_MEMPOOL_OUT_OF_MEMORY           _APL_ERR_MEMPOOL_OUT_OF_MEMORY


/*-------------- TYPES -----------------------------------------------------*/
/** Memory Pool Handle. 
 */
#define AplMemPoolHdl                           _AplMemPoolHdl


/*-------------- MACROS/CONSTANTS ------------------------------------------*/
/** Aligment boundary (default value) */
#ifndef OPTION_APL_MEMPOOL_ALIGNMENT_SIZE
#define OPTION_APL_MEMPOOL_ALIGNMENT_SIZE       2
#endif

/** Helper macro for calculating the raw memory size for 'numBlocks' blocks 
    of size 'blockSize' (also accounts for alignment bytes when needed).
 */
#define APL_MEMPOOL_RAWSIZE(numBlocks,blockSize)        _APL_MEMPOOL_RAWSIZE(numBlocks,blockSize) 


/*-------------- INLINE IMPLEMENTATION -------------------------------------*/
#include "apl/memory/mempool.h"            /* For: inline implementation */


/*-------------- PUBLIC/PUBLISHED API --------------------------------------*/
/** This method creates a Memory Pool. The handle of the newly created memory
    pool is always returned.  The application must supply the raw memory to 
    be used for the pool.  The memory pool will create N blocks of size 
    'userBlockSize'.  If the method is able to create at least one block, 
    then a handle to the created memory pool is returned.  If there is 
    insufficient memory for even one block, then 0 is returned. The actual 
    number of blocks created is determine by the following formula:

                (rawMemorySize - 'pool_overhead')
    numBlocks = --------------------------------------------
                (userBlockSize + 'block_overhead')

    where pool_overhead and block_overhead represent the internal
          data structure overhead and alignment bytes for the pool
          and each block.

    Always use the the macro APL_MEMPOOL_RAWSIZE() to calculate the
    raw size of the memory required for a memory pool since it properly
    accounts for the internal organization and neccesary alignment byte(s).

    NOTES:
        o The compile option, USE_APL_MEMPOOL_FATAL_ERROR_WHEN_OUTOFMEMORY,
          applies to this method when used.
        o This method is thread-safe since it is re-entrant (i.e. all data
          is local).
        o It is the RESPONSIBILITY of the application to ensure that 
          memory pointed to by 'rawMemory' is properly aligned to an
          alignment boundary specifieid by OPTION_APL_MEMPOOL_ALIGNMENT_SIZE.

    Prototype:
        AplMemPoolHdl Apl_memPoolCreate( void* rawMemory, AplSize_t rawMemorySize, AplSize_t userBlockSize );                        
 */
#define Apl_memPoolCreate                   _Apl_memPoolCreate


/*-------------- PUBLIC/PUBLISHED API --------------------------------------*/
/** This method attempts to allocate a block of memory from the specified 
    memory pool.  The size of the block is determined by the memory pool.
    The method returns a pointer to an available block of memory if successful, 
    else 0 is returned if no blocks are currently available.  
    NOTES:
        o There is compile option to generate a fatal error when the
          out-of-memory condition occurs (see inteface description above
          for more details). 

    Prototype:
        void* Apl_memPoolAllocate( AplMemPoolHdl poolToAllocateFrom );
 */
#define Apl_memPoolAllocate                 _Apl_memPoolAllocate

/** This method returns the block of memory specified to the specified
    memory pool.
        o This method is NOT thread-safe.
        o If 'blockToFree' equals 0, then no operation is performed
        o You must free the same pointer that was originally allocated
          from Apl_memPoolAllocateXXX() AND freed to the SAME memory
          pool that was use.  Freeing 'different' pointers or freeing to
          different memory pools will crash the system!  

    Prototype:
        void Apl_memPoolFree( AplMemPoolHdl poolMemoryWasAllocatedFrom, void* blockToFree );
 */
#define Apl_memPoolFree                     _Apl_memPoolFree





#ifdef __cplusplus
}
#endif
/*--------------------------------------------------------------------------*/
#endif  /* end _apl_memory_mempoolapi_h_ */

