ian@0: // Copyright 2007-2010 Baptiste Lepilleur ian@0: // Distributed under MIT license, or public domain if desired and ian@0: // recognized in your jurisdiction. ian@0: // See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE ian@0: ian@0: #ifndef JSONCPP_BATCHALLOCATOR_H_INCLUDED ian@0: # define JSONCPP_BATCHALLOCATOR_H_INCLUDED ian@0: ian@0: # include ian@0: # include ian@0: ian@0: # ifndef JSONCPP_DOC_EXCLUDE_IMPLEMENTATION ian@0: ian@0: namespace Json { ian@0: ian@0: /* Fast memory allocator. ian@0: * ian@0: * This memory allocator allocates memory for a batch of object (specified by ian@0: * the page size, the number of object in each page). ian@0: * ian@0: * It does not allow the destruction of a single object. All the allocated objects ian@0: * can be destroyed at once. The memory can be either released or reused for future ian@0: * allocation. ian@0: * ian@0: * The in-place new operator must be used to construct the object using the pointer ian@0: * returned by allocate. ian@0: */ ian@0: template ian@0: class BatchAllocator ian@0: { ian@0: public: ian@0: BatchAllocator( unsigned int objectsPerPage = 255 ) ian@0: : freeHead_( 0 ) ian@0: , objectsPerPage_( objectsPerPage ) ian@0: { ian@0: // printf( "Size: %d => %s\n", sizeof(AllocatedType), typeid(AllocatedType).name() ); ian@0: assert( sizeof(AllocatedType) * objectPerAllocation >= sizeof(AllocatedType *) ); // We must be able to store a slist in the object free space. ian@0: assert( objectsPerPage >= 16 ); ian@0: batches_ = allocateBatch( 0 ); // allocated a dummy page ian@0: currentBatch_ = batches_; ian@0: } ian@0: ian@0: ~BatchAllocator() ian@0: { ian@0: for ( BatchInfo *batch = batches_; batch; ) ian@0: { ian@0: BatchInfo *nextBatch = batch->next_; ian@0: free( batch ); ian@0: batch = nextBatch; ian@0: } ian@0: } ian@0: ian@0: /// allocate space for an array of objectPerAllocation object. ian@0: /// @warning it is the responsability of the caller to call objects constructors. ian@0: AllocatedType *allocate() ian@0: { ian@0: if ( freeHead_ ) // returns node from free list. ian@0: { ian@0: AllocatedType *object = freeHead_; ian@0: freeHead_ = *(AllocatedType **)object; ian@0: return object; ian@0: } ian@0: if ( currentBatch_->used_ == currentBatch_->end_ ) ian@0: { ian@0: currentBatch_ = currentBatch_->next_; ian@0: while ( currentBatch_ && currentBatch_->used_ == currentBatch_->end_ ) ian@0: currentBatch_ = currentBatch_->next_; ian@0: ian@0: if ( !currentBatch_ ) // no free batch found, allocate a new one ian@0: { ian@0: currentBatch_ = allocateBatch( objectsPerPage_ ); ian@0: currentBatch_->next_ = batches_; // insert at the head of the list ian@0: batches_ = currentBatch_; ian@0: } ian@0: } ian@0: AllocatedType *allocated = currentBatch_->used_; ian@0: currentBatch_->used_ += objectPerAllocation; ian@0: return allocated; ian@0: } ian@0: ian@0: /// Release the object. ian@0: /// @warning it is the responsability of the caller to actually destruct the object. ian@0: void release( AllocatedType *object ) ian@0: { ian@0: assert( object != 0 ); ian@0: *(AllocatedType **)object = freeHead_; ian@0: freeHead_ = object; ian@0: } ian@0: ian@0: private: ian@0: struct BatchInfo ian@0: { ian@0: BatchInfo *next_; ian@0: AllocatedType *used_; ian@0: AllocatedType *end_; ian@0: AllocatedType buffer_[objectPerAllocation]; ian@0: }; ian@0: ian@0: // disabled copy constructor and assignement operator. ian@0: BatchAllocator( const BatchAllocator & ); ian@0: void operator =( const BatchAllocator &); ian@0: ian@0: static BatchInfo *allocateBatch( unsigned int objectsPerPage ) ian@0: { ian@0: const unsigned int mallocSize = sizeof(BatchInfo) - sizeof(AllocatedType)* objectPerAllocation ian@0: + sizeof(AllocatedType) * objectPerAllocation * objectsPerPage; ian@0: BatchInfo *batch = static_cast( malloc( mallocSize ) ); ian@0: batch->next_ = 0; ian@0: batch->used_ = batch->buffer_; ian@0: batch->end_ = batch->buffer_ + objectsPerPage; ian@0: return batch; ian@0: } ian@0: ian@0: BatchInfo *batches_; ian@0: BatchInfo *currentBatch_; ian@0: /// Head of a single linked list within the allocated space of freeed object ian@0: AllocatedType *freeHead_; ian@0: unsigned int objectsPerPage_; ian@0: }; ian@0: ian@0: ian@0: } // namespace Json ian@0: ian@0: # endif // ifndef JSONCPP_DOC_INCLUDE_IMPLEMENTATION ian@0: ian@0: #endif // JSONCPP_BATCHALLOCATOR_H_INCLUDED