Home | History | Annotate | Download | only in src
      1 /* ------------------------------------------------------------------
      2  * Copyright (C) 1998-2009 PacketVideo
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
     13  * express or implied.
     14  * See the License for the specific language governing permissions
     15  * and limitations under the License.
     16  * -------------------------------------------------------------------
     17  */
     18 // -*- c++ -*-
     19 // = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
     20 
     21 //               O S C L _ M E M _ M E M P O O L
     22 
     23 // = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
     24 
     25 /*! \addtogroup osclmemory OSCL Memory
     26  *
     27  * @{
     28  */
     29 
     30 
     31 /*! \file oscl_mem_mempool.h
     32     \brief This file contains the definition of memory pool allocators
     33 */
     34 
     35 
     36 #ifndef OSCL_MEM_MEMPOOL_H_INCLUDED
     37 #define OSCL_MEM_MEMPOOL_H_INCLUDED
     38 
     39 #ifndef OSCL_MEM_H_INCLUDED
     40 #include "oscl_mem.h"
     41 #endif
     42 
     43 #ifndef OSCL_DEFALLOC_H_INCLUDED
     44 #include "oscl_defalloc.h"
     45 #endif
     46 
     47 #ifndef OSCL_VECTOR_H_INCLUDED
     48 #include "oscl_vector.h"
     49 #endif
     50 
     51 
     52 /** \class allocator
     53 ** A memory allocator class which allocates and deallocates from a fixed size memory pool;
     54 ** The memory pool is a multiple of fixed chunk size and does not grow. All allocation size must be the same as this chunk size.
     55 **
     56 */
     57 
     58 class OsclMemPoolFixedChunkAllocatorObserver
     59 {
     60     public:
     61         virtual void freechunkavailable(OsclAny* aContextData) = 0;
     62         virtual ~OsclMemPoolFixedChunkAllocatorObserver() {}
     63 };
     64 
     65 
     66 class OsclMemPoolFixedChunkAllocator : public Oscl_DefAlloc
     67 {
     68     public:
     69         /** This API throws an exception when the memory allocation for pool fails
     70           * If numchunk and chunksize parameters are not set, memory pool of 1 chunk will be created in the first call to allocate.
     71           * The chunk size will be set to the n passed in for allocate().
     72           * If numchunk parameter is set to 0, the memory pool will use 1 for numchunk.
     73           *
     74           * @return void
     75           *
     76           */
     77         OSCL_IMPORT_REF OsclMemPoolFixedChunkAllocator(const uint32 numchunk = 1, const uint32 chunksize = 0, Oscl_DefAlloc* gen_alloc = NULL);
     78 
     79         /** This API will disable exceptions in case the memory pool runs out of memory
     80           * Instead of doing "OSCL_LEAVE(OsclErrNoResources)" allocate API will return
     81           * NULL.
     82           *
     83           * @return void
     84           *
     85           */
     86         OSCL_IMPORT_REF virtual void enablenullpointerreturn();
     87 
     88         /** The destructor for the memory pool
     89           */
     90         OSCL_IMPORT_REF virtual ~OsclMemPoolFixedChunkAllocator();
     91 
     92         /** This API throws an exception when n is greater than the fixed chunk size or there are no free chunk available in the pool,
     93           * if "enablenullpointerreturn" has not been called.
     94           * If the memory pool hasn't been created yet, the pool will be created with chunk size equal to n so n must be greater than 0.
     95           * Exception will be thrown if memory allocation for the memory pool fails.
     96           *
     97           * @return pointer to available chunk from memory pool
     98           *
     99           */
    100         OSCL_IMPORT_REF virtual OsclAny* allocate(const uint32 n);
    101 
    102         /** This API throws an exception when the pointer p passed in is not part of the memory pool.
    103            * Exception will be thrown if the memory pool is not set up yet.
    104            *
    105            * @return void
    106            *
    107            */
    108         OSCL_IMPORT_REF virtual void deallocate(OsclAny* p);
    109 
    110         /** This API will set the flag to send a callback via specified observer object when the
    111           * next memory chunk is deallocated by deallocate() call..
    112           *
    113           * @return void
    114           *
    115           */
    116         OSCL_IMPORT_REF virtual void notifyfreechunkavailable(OsclMemPoolFixedChunkAllocatorObserver& obs, OsclAny* aContextData = NULL);
    117 
    118         /** This API will cancel any past callback requests..
    119           *
    120           * @return void
    121           *
    122           */
    123         OSCL_IMPORT_REF virtual void CancelFreeChunkAvailableCallback();
    124 
    125         /** Increments the reference count for this memory pool allocator
    126           *
    127           * @return void
    128           *
    129           */
    130         OSCL_IMPORT_REF void addRef();
    131 
    132         /** Decrements the reference count for this memory pool allocator
    133           * When the reference count goes to 0, this instance of the memory pool object is deleted
    134           *
    135           * @return void
    136           *
    137           */
    138         OSCL_IMPORT_REF void removeRef();
    139 
    140     protected:
    141         OSCL_IMPORT_REF virtual void createmempool();
    142         OSCL_IMPORT_REF virtual void destroymempool();
    143 
    144         uint32 iNumChunk;
    145         uint32 iChunkSize;
    146         uint32 iChunkSizeMemAligned;
    147         Oscl_DefAlloc* iMemPoolAllocator;
    148         OsclAny* iMemPool;
    149 
    150         Oscl_Vector<OsclAny*, OsclMemAllocator> iFreeMemChunkList;
    151 
    152         bool iCheckNextAvailableFreeChunk;
    153         OsclMemPoolFixedChunkAllocatorObserver* iObserver;
    154         OsclAny* iNextAvailableContextData;
    155 
    156         int32 iRefCount;
    157         bool iEnableNullPtrReturn;
    158 };
    159 
    160 
    161 /** \class allocator
    162 ** A memory allocator class which allocates and deallocates from a fixed size memory pool;
    163 ** The memory pool is one block of memory and allocations are not fixed in size. The memory pool
    164 ** also has the capability of growing by allocating more block one at a time. This memory pool
    165 ** also provides the capability of returning the tail end of memory previously allocated from
    166 ** the memory pool
    167 **
    168 */
    169 
    170 class OsclMemPoolResizableAllocatorObserver
    171 {
    172     public:
    173         virtual void freeblockavailable(OsclAny* aContextData) = 0;
    174         virtual ~OsclMemPoolResizableAllocatorObserver() {}
    175 };
    176 
    177 class OsclMemPoolResizableAllocatorMemoryObserver
    178 {
    179     public:
    180         virtual void freememoryavailable(OsclAny* aContextData) = 0;
    181         virtual ~OsclMemPoolResizableAllocatorMemoryObserver() {}
    182 };
    183 
    184 class OsclMemPoolResizableAllocator : public Oscl_DefAlloc
    185 {
    186     public:
    187         /** Create the memory pool allocator with resizing functionality.
    188           * The size of the memory pool buffer needs to be passed-in. The maximum number of
    189           * memory pool buffers, expected number of blocks in a memory pool buffer, and outside allocator are optional.
    190           * This API throws an exception when the memory allocation for the pool buffer fails.
    191           * If memory pool buffer number limit parameter is not set, the assumption is that
    192           * there is no limit and memory pool will grow as needed.
    193           * If the expected number of blocks is not set or not known, the memory pool will use
    194           * a default value to 10 to allocate extra memory for the block info header.
    195           *
    196           * @return void
    197           *
    198           */
    199         OSCL_IMPORT_REF OsclMemPoolResizableAllocator(uint32 aMemPoolBufferSize, uint32 aMemPoolBufferNumLimit = 0, uint32 aExpectedNumBlocksPerBuffer = 0, Oscl_DefAlloc* gen_alloc = NULL);
    200 
    201         /** This API will disable exceptions in case the memory pool runs out of memory
    202           * Instead of doing "OSCL_LEAVE(OsclErrNoResources)" allocate API will return
    203           * NULL.
    204           *
    205           * @return void
    206           *
    207           */
    208         OSCL_IMPORT_REF virtual void enablenullpointerreturn();
    209 
    210         /** Allocates a block from the memory pool that is at least in size requested
    211           * This API throws an exception if there isn't enough memory (if "enablenullpointerreturn" has not been called)
    212           * for the requested amount in the pool or if the extra pool buffer cannot be allocated.
    213           *
    214           * @return Pointer to memory buffer from memory pool
    215           *
    216           */
    217         OSCL_IMPORT_REF virtual OsclAny* allocate(const uint32 aNumBytes);
    218 
    219         /** Deallocates and returns a block back to the memory pool
    220           * This API throws an exception if the pointer passed in is not part of the memory pool, aligned, or has corrupted block header.
    221           *
    222           * @return void
    223           *
    224           */
    225         OSCL_IMPORT_REF virtual void deallocate(OsclAny* aPtr);
    226 
    227         /** Returns a tail segment of a previously allocated memory block back to the memory pool. The passed-in
    228           * pointer to the memory buffer is still valid after the call completes but the buffer size is smaller by
    229           * by specified amount that was freed.
    230           * This function allows the user to allocate a larger size block initially when the amount needed is unknown
    231           * and then return the unused portion of the block when the amount becomes known.
    232           * This API throws an exception if the pointer passed in is not part of the memory pool or the
    233           * size to return is bigger than the size of the passed-in block.
    234           * Exception will be thrown if the memory pool is not set up yet.
    235           *
    236           * @return bool True if trim operation successful. False if the block wasn't trimmed
    237           *
    238           */
    239         OSCL_IMPORT_REF virtual bool trim(OsclAny* aPtr, uint32 aBytesToFree);
    240 
    241         /** Returns the size of the buffer <including the overhead bytes that may be allocated by the allocater>
    242           */
    243         OSCL_IMPORT_REF uint32 getBufferSize() const;
    244 
    245         /** Returns the number of bytes allocated from the buffer<including the overhead bytes that may be
    246           * allocated by the allocater to keep track of the chunks allocated>
    247           */
    248         OSCL_IMPORT_REF virtual uint32 getAllocatedSize() const;
    249 
    250         /** Returns the number of bytes available with the buffer
    251           */
    252         OSCL_IMPORT_REF virtual uint32 getAvailableSize() const;
    253 
    254         /** Returns the size of the largest available chunk in the memory.
    255           */
    256         OSCL_IMPORT_REF virtual uint32 getLargestContiguousFreeBlockSize() const;
    257 
    258         OSCL_IMPORT_REF virtual bool setMaxSzForNewMemPoolBuffer(uint32 aMaxNewMemPoolBufferSz);
    259 
    260         /** This API will set the flag to send a callback via specified observer object when the
    261           * next memory block is deallocated by deallocate() call. If the optional requested size
    262           * parameter is set, the callback is sent when a free memory space of requested size becomes available.
    263           * The optional context data is returned with the callback and can be used by the user to
    264           * differentiate.between different instances of memory pool objects.
    265           * This memory pool only allows one notify to be queued. Another call to this function will just overwrite
    266           * the previous call.
    267           *
    268           * @return void
    269           *
    270           */
    271         OSCL_IMPORT_REF virtual void notifyfreeblockavailable(OsclMemPoolResizableAllocatorObserver& aObserver, uint32 aRequestedSize = 0, OsclAny* aContextData = NULL);
    272 
    273         /** This API will cancel any past callback requests..
    274           *
    275           * @return void
    276           *
    277           */
    278         OSCL_IMPORT_REF virtual void CancelFreeChunkAvailableCallback();
    279 
    280         OSCL_IMPORT_REF virtual void notifyfreememoryavailable(OsclMemPoolResizableAllocatorMemoryObserver& aObserver, uint32 aRequestedSize = 0, OsclAny* aContextData = NULL);
    281         OSCL_IMPORT_REF void CancelFreeMemoryAvailableCallback();
    282 
    283         /** Increments the reference count for this memory pool allocator
    284           *
    285           * @return void
    286           *
    287           */
    288         OSCL_IMPORT_REF void addRef();
    289 
    290         /** Decrements the reference count for this memory pool allocator
    291           * When the reference count goes to 0, this instance of the memory pool object is deleted
    292           *
    293           * @return void
    294           *
    295           */
    296         OSCL_IMPORT_REF void removeRef();
    297 
    298 
    299         struct MemPoolBlockInfo;
    300 
    301         struct MemPoolBufferInfo
    302         {
    303             uint32 iBufferPreFence;     // Pre-fence to check for memory corruption
    304             OsclAny* iStartAddr;        // Starting memory address of the memory pool buffer after the buffer info
    305             OsclAny* iEndAddr;          // Ending memory address of the memory pool buffer
    306             uint32 iBufferSize;         // Total size of the memory pool buffer including the buffer info header
    307             uint32 iNumOutstanding;     // Number of outstanding blocks from this memory pool buffer
    308             MemPoolBlockInfo* iNextFreeBlock; // Pointer to the next free memory block
    309             uint32 iAllocatedSz;        //Number of butes allocated from the mempool
    310             uint32 iBufferPostFence;    // Post-fence to check for memory corruption
    311         };
    312 
    313         struct MemPoolBlockInfo
    314         {
    315             uint32 iBlockPreFence;      // Pre-fence to check for memory corruption
    316             MemPoolBlockInfo* iNextFreeBlock; // Pointer to the next (right neighbor) free block in the buffer. NULL if none.
    317             MemPoolBlockInfo* iPrevFreeBlock; // Pointer to the previous (left neighbor) free block in the buffer. NULL if first free block
    318             uint32 iBlockSize;          // Total size of the block including the block info header
    319             uint8* iBlockBuffer;        // Pointer to the buffer area of the block
    320             MemPoolBufferInfo* iParentBuffer; // Pointer to the block's parent memory pool buffer
    321             uint32 iBlockPostFence;     // Post-fence to check for memory corruption
    322         };
    323 
    324     protected:
    325 
    326         /** The destructor for the memory pool. Should not be called directly. Use removeRef() instead.
    327           */
    328         OSCL_IMPORT_REF virtual ~OsclMemPoolResizableAllocator();
    329 
    330         MemPoolBufferInfo* addnewmempoolbuffer(uint32 aBufferSize);
    331         void destroyallmempoolbuffers();
    332         MemPoolBlockInfo* findfreeblock(uint32 aBlockSize);
    333         OsclAny* allocateblock(MemPoolBlockInfo& aBlockPtr, uint32 aNumBytes);
    334         void deallocateblock(MemPoolBlockInfo& aBlockPtr);
    335         bool validateblock(OsclAny* aBlockBufPtr);
    336 
    337         uint32 iMemPoolBufferSize;
    338         uint32 iMemPoolBufferNumLimit;
    339         uint32 iExpectedNumBlocksPerBuffer;
    340         uint32 iMaxNewMemPoolBufferSz;
    341         Oscl_DefAlloc* iMemPoolBufferAllocator;
    342         Oscl_Vector<MemPoolBufferInfo*, OsclMemAllocator> iMemPoolBufferList;
    343 
    344         uint32 iBufferInfoAlignedSize;
    345         uint32 iBlockInfoAlignedSize;
    346 
    347         bool iCheckNextAvailable;
    348         uint32 iRequestedNextAvailableSize;
    349         OsclAny* iNextAvailableContextData;
    350         OsclMemPoolResizableAllocatorObserver* iObserver;
    351 
    352         bool iCheckFreeMemoryAvailable;
    353         uint32  iRequestedAvailableFreeMemSize;
    354         OsclAny* iFreeMemContextData;
    355         OsclMemPoolResizableAllocatorMemoryObserver* iFreeMemPoolObserver;
    356 
    357         int32 iRefCount;
    358         bool iEnableNullPtrReturn;
    359         //To compute the size of the buffer, excluding the extra memory in the buffer for its management
    360         uint32 getMemPoolBufferSize(MemPoolBufferInfo* aBufferInfo) const;
    361         //To compute the number of bytes allocated from the buffer
    362         uint32 getMemPoolBufferAllocatedSize(MemPoolBufferInfo* aBufferInfo) const;
    363         //To compute the addition bytes which were allocated while createing the memory pool for the buffer.
    364         uint32 memoryPoolBufferMgmtOverhead() const;
    365 };
    366 
    367 #endif
    368 
    369 /*! @} */
    370