forked from OSchip/llvm-project
				
			
		
			
				
	
	
		
			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
 | 
						|
 |