Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2021-02-14 13:26:25

0001 #ifndef JSONCPP_BATCHALLOCATOR_H_INCLUDED
0002 #define JSONCPP_BATCHALLOCATOR_H_INCLUDED
0003 
0004 #include <cassert>
0005 #include <cstdlib>
0006 
0007 #ifndef JSONCPP_DOC_EXCLUDE_IMPLEMENTATION
0008 
0009 namespace Json {
0010 
0011   /* Fast memory allocator.
0012  *
0013  * This memory allocator allocates memory for a batch of object (specified by
0014  * the page size, the number of object in each page).
0015  *
0016  * It does not allow the destruction of a single object. All the allocated objects
0017  * can be destroyed at once. The memory can be either released or reused for future
0018  * allocation.
0019  * 
0020  * The in-place new operator must be used to construct the object using the pointer
0021  * returned by allocate.
0022  */
0023   template <typename AllocatedType, const unsigned int objectPerAllocation>
0024   class BatchAllocator {
0025   public:
0026     typedef AllocatedType Type;
0027 
0028     BatchAllocator(unsigned int objectsPerPage = 255) : freeHead_(0), objectsPerPage_(objectsPerPage) {
0029       //      printf( "Size: %d => %s\n", sizeof(AllocatedType), typeid(AllocatedType).name() );
0030       assert(sizeof(AllocatedType) * objectPerAllocation >=
0031              sizeof(AllocatedType *));  // We must be able to store a slist in the object free space.
0032       assert(objectsPerPage >= 16);
0033       batches_ = allocateBatch(0);  // allocated a dummy page
0034       currentBatch_ = batches_;
0035     }
0036 
0037     ~BatchAllocator() {
0038       for (BatchInfo *batch = batches_; batch;) {
0039         BatchInfo *nextBatch = batch->next_;
0040         free(batch);
0041         batch = nextBatch;
0042       }
0043     }
0044 
0045     /// allocate space for an array of objectPerAllocation object.
0046     /// @warning it is the responsability of the caller to call objects constructors.
0047     AllocatedType *allocate() {
0048       if (freeHead_)  // returns node from free list.
0049       {
0050         AllocatedType *object = freeHead_;
0051         freeHead_ = *(AllocatedType **)object;
0052         return object;
0053       }
0054       if (currentBatch_->used_ == currentBatch_->end_) {
0055         currentBatch_ = currentBatch_->next_;
0056         while (currentBatch_ && currentBatch_->used_ == currentBatch_->end_)
0057           currentBatch_ = currentBatch_->next_;
0058 
0059         if (!currentBatch_)  // no free batch found, allocate a new one
0060         {
0061           currentBatch_ = allocateBatch(objectsPerPage_);
0062           currentBatch_->next_ = batches_;  // insert at the head of the list
0063           batches_ = currentBatch_;
0064         }
0065       }
0066       AllocatedType *allocated = currentBatch_->used_;
0067       currentBatch_->used_ += objectPerAllocation;
0068       return allocated;
0069     }
0070 
0071     /// Release the object.
0072     /// @warning it is the responsability of the caller to actually destruct the object.
0073     void release(AllocatedType *object) {
0074       assert(object != 0);
0075       *(AllocatedType **)object = freeHead_;
0076       freeHead_ = object;
0077     }
0078 
0079     // disabled copy constructor and assignement operator.
0080     BatchAllocator(const BatchAllocator &) = delete;
0081     void operator=(const BatchAllocator &) = delete;
0082 
0083   private:
0084     struct BatchInfo {
0085       BatchInfo *next_;
0086       AllocatedType *used_;
0087       AllocatedType *end_;
0088       AllocatedType buffer_[objectPerAllocation];
0089     };
0090 
0091     static BatchInfo *allocateBatch(unsigned int objectsPerPage) {
0092       const unsigned int mallocSize = sizeof(BatchInfo) - sizeof(AllocatedType) * objectPerAllocation +
0093                                       sizeof(AllocatedType) * objectPerAllocation * objectsPerPage;
0094       BatchInfo *batch = static_cast<BatchInfo *>(malloc(mallocSize));
0095       batch->next_ = 0;
0096       batch->used_ = batch->buffer_;
0097       batch->end_ = batch->buffer_ + objectsPerPage;
0098       return batch;
0099     }
0100 
0101     BatchInfo *batches_;
0102     BatchInfo *currentBatch_;
0103     /// Head of a single linked list within the allocated space of freeed object
0104     AllocatedType *freeHead_;
0105     unsigned int objectsPerPage_;
0106   };
0107 
0108 }  // namespace Json
0109 
0110 #endif  // ifndef JSONCPP_DOC_INCLUDE_IMPLEMENTATION
0111 
0112 #endif  // JSONCPP_BATCHALLOCATOR_H_INCLUDED