00001 // Copyright 2007-2010 Baptiste Lepilleur 00002 // Distributed under MIT license, or public domain if desired and 00003 // recognized in your jurisdiction. 00004 // See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE 00005 00006 #ifndef JSONCPP_BATCHALLOCATOR_H_INCLUDED 00007 # define JSONCPP_BATCHALLOCATOR_H_INCLUDED 00008 00009 # include <stdlib.h> 00010 # include <assert.h> 00011 00012 # ifndef JSONCPP_DOC_EXCLUDE_IMPLEMENTATION 00013 00014 namespace Json { 00015 00016 /* Fast memory allocator. 00017 * 00018 * This memory allocator allocates memory for a batch of object (specified by 00019 * the page size, the number of object in each page). 00020 * 00021 * It does not allow the destruction of a single object. All the allocated objects 00022 * can be destroyed at once. The memory can be either released or reused for future 00023 * allocation. 00024 * 00025 * The in-place new operator must be used to construct the object using the pointer 00026 * returned by allocate. 00027 */ 00028 template<typename AllocatedType 00029 ,const unsigned int objectPerAllocation> 00030 class BatchAllocator 00031 { 00032 public: 00033 typedef AllocatedType Type; 00034 00035 BatchAllocator( unsigned int objectsPerPage = 255 ) 00036 : freeHead_( 0 ) 00037 , objectsPerPage_( objectsPerPage ) 00038 { 00039 // printf( "Size: %d => %s\n", sizeof(AllocatedType), typeid(AllocatedType).name() ); 00040 assert( sizeof(AllocatedType) * objectPerAllocation >= sizeof(AllocatedType *) ); // We must be able to store a slist in the object free space. 00041 assert( objectsPerPage >= 16 ); 00042 batches_ = allocateBatch( 0 ); // allocated a dummy page 00043 currentBatch_ = batches_; 00044 } 00045 00046 ~BatchAllocator() 00047 { 00048 for ( BatchInfo *batch = batches_; batch; ) 00049 { 00050 BatchInfo *nextBatch = batch->next_; 00051 free( batch ); 00052 batch = nextBatch; 00053 } 00054 } 00055 00058 AllocatedType *allocate() 00059 { 00060 if ( freeHead_ ) // returns node from free list. 00061 { 00062 AllocatedType *object = freeHead_; 00063 freeHead_ = *(AllocatedType **)object; 00064 return object; 00065 } 00066 if ( currentBatch_->used_ == currentBatch_->end_ ) 00067 { 00068 currentBatch_ = currentBatch_->next_; 00069 while ( currentBatch_ && currentBatch_->used_ == currentBatch_->end_ ) 00070 currentBatch_ = currentBatch_->next_; 00071 00072 if ( !currentBatch_ ) // no free batch found, allocate a new one 00073 { 00074 currentBatch_ = allocateBatch( objectsPerPage_ ); 00075 currentBatch_->next_ = batches_; // insert at the head of the list 00076 batches_ = currentBatch_; 00077 } 00078 } 00079 AllocatedType *allocated = currentBatch_->used_; 00080 currentBatch_->used_ += objectPerAllocation; 00081 return allocated; 00082 } 00083 00086 void release( AllocatedType *object ) 00087 { 00088 assert( object != 0 ); 00089 *(AllocatedType **)object = freeHead_; 00090 freeHead_ = object; 00091 } 00092 00093 private: 00094 struct BatchInfo 00095 { 00096 BatchInfo *next_; 00097 AllocatedType *used_; 00098 AllocatedType *end_; 00099 AllocatedType buffer_[objectPerAllocation]; 00100 }; 00101 00102 // disabled copy constructor and assignement operator. 00103 BatchAllocator( const BatchAllocator & ); 00104 void operator =( const BatchAllocator &); 00105 00106 static BatchInfo *allocateBatch( unsigned int objectsPerPage ) 00107 { 00108 const unsigned int mallocSize = sizeof(BatchInfo) - sizeof(AllocatedType)* objectPerAllocation 00109 + sizeof(AllocatedType) * objectPerAllocation * objectsPerPage; 00110 BatchInfo *batch = static_cast<BatchInfo*>( malloc( mallocSize ) ); 00111 batch->next_ = 0; 00112 batch->used_ = batch->buffer_; 00113 batch->end_ = batch->buffer_ + objectsPerPage; 00114 return batch; 00115 } 00116 00117 BatchInfo *batches_; 00118 BatchInfo *currentBatch_; 00120 AllocatedType *freeHead_; 00121 unsigned int objectsPerPage_; 00122 }; 00123 00124 00125 } // namespace Json 00126 00127 # endif // ifndef JSONCPP_DOC_INCLUDE_IMPLEMENTATION 00128 00129 #endif // JSONCPP_BATCHALLOCATOR_H_INCLUDED 00130