OSCL_EXPORT_REF OsclAny* OsclMemPoolResizableAllocator::allocate(const uint32 aNumBytes) { MemPoolBlockInfo* freeblock = NULL; uint32 alignednumbytes = oscl_mem_aligned_size(aNumBytes); if (aNumBytes == 0) { OSCL_LEAVE(OsclErrArgument); // OSCL_UNUSED_RETURN(NULL); This statement was removed to avoid compiler warning for Unreachable Code } // Find a free block that would accomodate the requested size with a block info header freeblock = findfreeblock(alignednumbytes + iBlockInfoAlignedSize); if (freeblock == NULL) { //We could not find a free buffer of requested size. This could be due to: //1) We have not created even a single parent chunk (or in other words this is the first allocation) //2) We are out of memory and might need to expand // Check if the requested size is bigger than the specified buffer size // Some of the users of this allocator, count on the allocator to expand beyond the original size // specified in the constructor. These users do NOT use setMaxSzForNewMemPoolBuffer to control expansion size. // If they did then it is wrong usage and we fail the allocation. // For example the allocator was intialized with 200KB size, // and overtime a request is made for say 300KB. Users of the allocator expect the allocator to do one of the following: // 1) If iMemPoolBufferNumLimit has been set and it has been reached then see // if one of older blocks can be freed up and we allocate a new block of 300KB. If we cannot then alloc will fail. // 2) If iMemPoolBufferNumLimit has not set then simply allocate a new block of 300 KB. Note that if iMemPoolBufferNumLimit // is not set allocator expands indefinitely. if (alignednumbytes > iMemPoolBufferSize) { if (iMaxNewMemPoolBufferSz != 0) { //wrong usage - fail allocation if (iEnableNullPtrReturn) { return NULL; } else { // Leave with resource limitation OSCL_LEAVE(OsclErrNoResources); } } // Would need to create a new buffer to accomodate this request // Check if another buffer can be created if (iMemPoolBufferNumLimit > 0 && iMemPoolBufferList.size() >= iMemPoolBufferNumLimit) { // Check if there is a memory pool buffer that has no outstanding buffers // If present then remove it so a new one can be added bool emptybufferfound = false; for (uint32 j = 0; j < iMemPoolBufferList.size(); ++j) { if (iMemPoolBufferList[j]->iNumOutstanding == 0) { // Free the memory if (iMemPoolBufferAllocator) { iMemPoolBufferAllocator->deallocate((OsclAny*)iMemPoolBufferList[j]); } else { OSCL_FREE((OsclAny*)iMemPoolBufferList[j]); } // Remove the mempool buffer from the list iMemPoolBufferList.erase(iMemPoolBufferList.begin() + j); emptybufferfound = true; break; } } // Need to leave and return if empty buffer not found if (!emptybufferfound) { if (iEnableNullPtrReturn) { return NULL; } else { // Leave with resource limitation OSCL_LEAVE(OsclErrNoResources); } } // Continue on to create a new buffer OSCL_ASSERT(iMemPoolBufferList.size() < iMemPoolBufferNumLimit); } // Determine the size of memory pool buffer and create one uint32 buffersize = alignednumbytes + iBufferInfoAlignedSize; if (iExpectedNumBlocksPerBuffer > 0) { buffersize += (iExpectedNumBlocksPerBuffer * iBlockInfoAlignedSize); } else { buffersize += (OSCLMEMPOOLRESIZABLEALLOCATOR_DEFAULT_NUMBLOCKPERBUFFER * iBlockInfoAlignedSize); } MemPoolBufferInfo* newbuffer = addnewmempoolbuffer(buffersize); OSCL_ASSERT(newbuffer != NULL); OSCL_ASSERT(newbuffer->iNextFreeBlock != NULL); freeblock = (MemPoolBlockInfo*)(newbuffer->iNextFreeBlock); OSCL_ASSERT(freeblock != NULL); OSCL_ASSERT(freeblock->iBlockSize >= alignednumbytes); } else { // Check if another buffer can be created if (iMemPoolBufferNumLimit > 0 && iMemPoolBufferList.size() >= iMemPoolBufferNumLimit) { if (iEnableNullPtrReturn) { return NULL; } else { // Leave with resource limitation OSCL_LEAVE(OsclErrNoResources); } } // Determine the size of memory pool buffer and create one // By default this allocator expands by iMemPoolBufferSize. // iMaxNewMemPoolBufferSz could specify the amount by which this allocator expands. // setMaxSzForNewMemPoolBuffer API can be used to control the expansion size. uint32 expansion_size = iMemPoolBufferSize; if (iMaxNewMemPoolBufferSz != 0) { expansion_size = iMaxNewMemPoolBufferSz; } //if alignednumbytes is larger than expansion_size, we cannot satisfy the request, so fail the allocation if (alignednumbytes > expansion_size) { if (iEnableNullPtrReturn) { return NULL; } else { // Leave with resource limitation OSCL_LEAVE(OsclErrNoResources); } } uint32 buffersize = oscl_mem_aligned_size(expansion_size) + iBufferInfoAlignedSize; if (iExpectedNumBlocksPerBuffer > 0) { buffersize += (iExpectedNumBlocksPerBuffer * iBlockInfoAlignedSize); } else { buffersize += (OSCLMEMPOOLRESIZABLEALLOCATOR_DEFAULT_NUMBLOCKPERBUFFER * iBlockInfoAlignedSize); } MemPoolBufferInfo* newbuffer = addnewmempoolbuffer(buffersize); OSCL_ASSERT(newbuffer != NULL); OSCL_ASSERT(newbuffer->iNextFreeBlock != NULL); freeblock = (MemPoolBlockInfo*)(newbuffer->iNextFreeBlock); OSCL_ASSERT(freeblock != NULL); OSCL_ASSERT(freeblock->iBlockSize >= alignednumbytes); } } // Use the free block and return the buffer pointer OsclAny* bufptr = allocateblock(*freeblock, alignednumbytes); if (bufptr) { addRef(); ++(freeblock->iParentBuffer->iNumOutstanding); } return bufptr; }
void* CMPage::Allocate(void) { // 分配实例对象 return allocateblock(); }