IPoolDataPtr MemoryPool::allocate( const std::size_t size ) { // Try to reuse a buffer available in the MemoryPool IPoolData* pData = getOneAvailableData( size ); if( pData != NULL ) { TUTTLE_LOG_TRACE("[Memory Pool] Reuse a buffer available in the MemoryPool"); pData->setSize( size ); return pData; } // Try to remove unused element in MemoryCache, and reuse the buffer available in the MemoryPool memory::IMemoryCache& memoryCache = core().getMemoryCache(); CACHE_ELEMENT unusedCacheElement = memoryCache.getUnusedWithSize( size ); if( unusedCacheElement.get() != NULL ) { TUTTLE_LOG_TRACE("[Memory Pool] Pop element in the MemoryCache from " << unusedCacheElement->getFullName() << " of size " << size); memoryCache.remove( unusedCacheElement ); pData = getOneAvailableData( size ); if( pData != NULL ) { TUTTLE_LOG_TRACE("[Memory Pool] Reuse a buffer available in the MemoryPool"); pData->setSize( size ); return pData; } } // Try to allocate a new buffer in MemoryPool std::size_t availableSize = getAvailableMemorySize(); if( size > availableSize ) { // Try to release elements from the MemoryCache (make them available to the MemoryPool) TUTTLE_LOG_TRACE("[Memory Pool] Release elements from the MemoryCache"); memoryCache.clearUnused(); availableSize = getAvailableMemorySize(); if( size > availableSize ) { // Release elements from the MemoryPool (make them available to the OS) TUTTLE_LOG_TRACE("[Memory Pool] Release elements from the MemoryPool"); clear(); } availableSize = getAvailableMemorySize(); if( size > availableSize ) { std::stringstream s; s << "[Memory Pool] can't allocate size:" << size << " because memory available is equal to " << availableSize << " bytes"; BOOST_THROW_EXCEPTION( std::length_error( s.str() ) ); } } // Allocate a new buffer in MemoryPool TUTTLE_TLOG( TUTTLE_TRACE, "[Memory Pool] allocate " << size << " bytes" ); return new PoolData( *this, size ); }
boost::intrusive_ptr<IPoolData> MemoryPool::allocate( const std::size_t size ) { TUTTLE_TCOUT( "MemoryPool::allocate: " << size ); PoolData* pData = NULL; { boost::mutex::scoped_lock locker( _mutex ); // checking within unused data pData = std::for_each( _dataUnused.begin(), _dataUnused.end(), DataFitSize( size ) ).bestMatch(); } if( pData != NULL ) { pData->_size = size; return pData; } const std::size_t availableSize = getAvailableMemorySize(); if( size > availableSize ) { std::stringstream s; s << "MemoryPool can't allocate size:" << size << " because memorySizeAvailable=" << availableSize; BOOST_THROW_EXCEPTION( std::length_error( s.str() ) ); } return new PoolData( *this, size ); }
boost::intrusive_ptr<IPoolData> MemoryPool::allocate( const std::size_t size ) { // checking within unused data PoolData* const pData = std::for_each( _dataUnused.begin(), _dataUnused.end(), DataFitSize( size ) ).bestMatch(); if( pData != NULL ) { pData->_size = size; return pData; } if( size > getAvailableMemorySize() ) { std::stringstream s; s << "MemoryPool can't allocate size:" << size << " because memorySizeAvailable=" << getAvailableMemorySize(); BOOST_THROW_EXCEPTION( std::length_error( s.str() ) ); } return new PoolData( *this, size ); }
MemoryPool::~MemoryPool() { if( !_dataUsed.empty() ) { TUTTLE_COUT_ERROR( "Error inside memory pool. Some data always mark used at the destruction (nb elements:" << _dataUsed.size() << ")" ); } TUTTLE_TCOUT_X( 20, "-" ); TUTTLE_TCOUT( "~MemoryPool()" ); TUTTLE_TCOUT_VAR( _dataUsed.size() ); TUTTLE_TCOUT_VAR( _dataUnused.size() ); TUTTLE_TCOUT_VAR( _allDatas.size() ); TUTTLE_TCOUT_VAR( _memoryAuthorized ); TUTTLE_TCOUT( "" ); TUTTLE_TCOUT_VAR( getUsedMemorySize() ); TUTTLE_TCOUT_VAR( getAllocatedMemorySize() ); TUTTLE_TCOUT_VAR( getMaxMemorySize() ); TUTTLE_TCOUT_VAR( getAvailableMemorySize() ); TUTTLE_TCOUT_VAR( getWastedMemorySize() ); TUTTLE_TCOUT_X( 20, "-" ); }