126 lines
		
	
	
		
			3.8 KiB
		
	
	
	
		
			C++
		
	
	
	
			
		
		
	
	
			126 lines
		
	
	
		
			3.8 KiB
		
	
	
	
		
			C++
		
	
	
	
| #ifndef JSONCPP_BATCHALLOCATOR_H_INCLUDED
 | |
| # define JSONCPP_BATCHALLOCATOR_H_INCLUDED
 | |
| 
 | |
| # include <stdlib.h>
 | |
| # include <assert.h>
 | |
| 
 | |
| # ifndef JSONCPP_DOC_EXCLUDE_IMPLEMENTATION
 | |
| 
 | |
| namespace 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 page
 | |
|       currentBatch_ = 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 list
 | |
|             batches_ = 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 object
 | |
|    AllocatedType *freeHead_;
 | |
|    unsigned int objectsPerPage_;
 | |
| };
 | |
| 
 | |
| 
 | |
| } // namespace Json
 | |
| 
 | |
| # endif // ifndef JSONCPP_DOC_INCLUDE_IMPLEMENTATION
 | |
| 
 | |
| #endif // JSONCPP_BATCHALLOCATOR_H_INCLUDED
 | |
| 
 |