Blame | Last modification | View Log | RSS feed
#ifndef JSONCPP_BATCHALLOCATOR_H_INCLUDED# define JSONCPP_BATCHALLOCATOR_H_INCLUDED# include <stdlib.h># include <assert.h># ifndef JSONCPP_DOC_EXCLUDE_IMPLEMENTATIONnamespace Json {/* Fast memory allocator.** This memory allocator allocates memory for a batch of object (specified by* the page size, the number of object in each page).** It does not allow the destruction of a single object. All the allocated objects* can be destroyed at once. The memory can be either released or reused for future* allocation.** The in-place new operator must be used to construct the object using the pointer* returned by allocate.*/template<typename AllocatedType,const unsigned int objectPerAllocation>class BatchAllocator{public:typedef AllocatedType Type;BatchAllocator( unsigned int objectsPerPage = 255 ): freeHead_( 0 ), objectsPerPage_( objectsPerPage ){// printf( "Size: %d => %s\n", sizeof(AllocatedType), typeid(AllocatedType).name() );assert( sizeof(AllocatedType) * objectPerAllocation >= sizeof(AllocatedType *) ); // We must be able to store a slist in the object free space.assert( objectsPerPage >= 16 );batches_ = allocateBatch( 0 ); // allocated a dummy pagecurrentBatch_ = batches_;}~BatchAllocator(){for ( BatchInfo *batch = batches_; batch; ){BatchInfo *nextBatch = batch->next_;free( batch );batch = nextBatch;}}/// allocate space for an array of objectPerAllocation object./// @warning it is the responsability of the caller to call objects constructors.AllocatedType *allocate(){if ( freeHead_ ) // returns node from free list.{AllocatedType *object = freeHead_;freeHead_ = *(AllocatedType **)object;return object;}if ( currentBatch_->used_ == currentBatch_->end_ ){currentBatch_ = currentBatch_->next_;while ( currentBatch_ && currentBatch_->used_ == currentBatch_->end_ )currentBatch_ = currentBatch_->next_;if ( !currentBatch_ ) // no free batch found, allocate a new one{currentBatch_ = allocateBatch( objectsPerPage_ );currentBatch_->next_ = batches_; // insert at the head of the listbatches_ = currentBatch_;}}AllocatedType *allocated = currentBatch_->used_;currentBatch_->used_ += objectPerAllocation;return allocated;}/// Release the object./// @warning it is the responsability of the caller to actually destruct the object.void release( AllocatedType *object ){assert( object != 0 );*(AllocatedType **)object = freeHead_;freeHead_ = object;}private:struct BatchInfo{BatchInfo *next_;AllocatedType *used_;AllocatedType *end_;AllocatedType buffer_[objectPerAllocation];};// disabled copy constructor and assignement operator.BatchAllocator( const BatchAllocator & );void operator =( const BatchAllocator &);static BatchInfo *allocateBatch( unsigned int objectsPerPage ){const unsigned int mallocSize = sizeof(BatchInfo) - sizeof(AllocatedType)* objectPerAllocation+ sizeof(AllocatedType) * objectPerAllocation * objectsPerPage;BatchInfo *batch = static_cast<BatchInfo*>( malloc( mallocSize ) );batch->next_ = 0;batch->used_ = batch->buffer_;batch->end_ = batch->buffer_ + objectsPerPage;return batch;}BatchInfo *batches_;BatchInfo *currentBatch_;/// Head of a single linked list within the allocated space of freeed objectAllocatedType *freeHead_;unsigned int objectsPerPage_;};} // namespace Json# endif // ifndef JSONCPP_DOC_INCLUDE_IMPLEMENTATION#endif // JSONCPP_BATCHALLOCATOR_H_INCLUDED