json_batchallocator.h 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130
  1. // Copyright 2007-2010 Baptiste Lepilleur
  2. // Distributed under MIT license, or public domain if desired and
  3. // recognized in your jurisdiction.
  4. // See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE
  5. #ifndef JSONCPP_BATCHALLOCATOR_H_INCLUDED
  6. # define JSONCPP_BATCHALLOCATOR_H_INCLUDED
  7. # include <stdlib.h>
  8. # include <assert.h>
  9. # ifndef JSONCPP_DOC_EXCLUDE_IMPLEMENTATION
  10. namespace Json {
  11. /* Fast memory allocator.
  12. *
  13. * This memory allocator allocates memory for a batch of object (specified by
  14. * the page size, the number of object in each page).
  15. *
  16. * It does not allow the destruction of a single object. All the allocated objects
  17. * can be destroyed at once. The memory can be either released or reused for future
  18. * allocation.
  19. *
  20. * The in-place new operator must be used to construct the object using the pointer
  21. * returned by allocate.
  22. */
  23. template<typename AllocatedType
  24. ,const unsigned int objectPerAllocation>
  25. class BatchAllocator
  26. {
  27. public:
  28. typedef AllocatedType Type;
  29. BatchAllocator( unsigned int objectsPerPage = 255 )
  30. : freeHead_( 0 )
  31. , objectsPerPage_( objectsPerPage )
  32. {
  33. // printf( "Size: %d => %s\n", sizeof(AllocatedType), typeid(AllocatedType).name() );
  34. assert( sizeof(AllocatedType) * objectPerAllocation >= sizeof(AllocatedType *) ); // We must be able to store a slist in the object free space.
  35. assert( objectsPerPage >= 16 );
  36. batches_ = allocateBatch( 0 ); // allocated a dummy page
  37. currentBatch_ = batches_;
  38. }
  39. ~BatchAllocator()
  40. {
  41. for ( BatchInfo *batch = batches_; batch; )
  42. {
  43. BatchInfo *nextBatch = batch->next_;
  44. free( batch );
  45. batch = nextBatch;
  46. }
  47. }
  48. /// allocate space for an array of objectPerAllocation object.
  49. /// @warning it is the responsability of the caller to call objects constructors.
  50. AllocatedType *allocate()
  51. {
  52. if ( freeHead_ ) // returns node from free list.
  53. {
  54. AllocatedType *object = freeHead_;
  55. freeHead_ = *(AllocatedType **)object;
  56. return object;
  57. }
  58. if ( currentBatch_->used_ == currentBatch_->end_ )
  59. {
  60. currentBatch_ = currentBatch_->next_;
  61. while ( currentBatch_ && currentBatch_->used_ == currentBatch_->end_ )
  62. currentBatch_ = currentBatch_->next_;
  63. if ( !currentBatch_ ) // no free batch found, allocate a new one
  64. {
  65. currentBatch_ = allocateBatch( objectsPerPage_ );
  66. currentBatch_->next_ = batches_; // insert at the head of the list
  67. batches_ = currentBatch_;
  68. }
  69. }
  70. AllocatedType *allocated = currentBatch_->used_;
  71. currentBatch_->used_ += objectPerAllocation;
  72. return allocated;
  73. }
  74. /// Release the object.
  75. /// @warning it is the responsability of the caller to actually destruct the object.
  76. void release( AllocatedType *object )
  77. {
  78. assert( object != 0 );
  79. *(AllocatedType **)object = freeHead_;
  80. freeHead_ = object;
  81. }
  82. private:
  83. struct BatchInfo
  84. {
  85. BatchInfo *next_;
  86. AllocatedType *used_;
  87. AllocatedType *end_;
  88. AllocatedType buffer_[objectPerAllocation];
  89. };
  90. // disabled copy constructor and assignement operator.
  91. BatchAllocator( const BatchAllocator & );
  92. void operator =( const BatchAllocator &);
  93. static BatchInfo *allocateBatch( unsigned int objectsPerPage )
  94. {
  95. const unsigned int mallocSize = sizeof(BatchInfo) - sizeof(AllocatedType)* objectPerAllocation
  96. + sizeof(AllocatedType) * objectPerAllocation * objectsPerPage;
  97. BatchInfo *batch = static_cast<BatchInfo*>( malloc( mallocSize ) );
  98. batch->next_ = 0;
  99. batch->used_ = batch->buffer_;
  100. batch->end_ = batch->buffer_ + objectsPerPage;
  101. return batch;
  102. }
  103. BatchInfo *batches_;
  104. BatchInfo *currentBatch_;
  105. /// Head of a single linked list within the allocated space of freeed object
  106. AllocatedType *freeHead_;
  107. unsigned int objectsPerPage_;
  108. };
  109. } // namespace Json
  110. # endif // ifndef JSONCPP_DOC_INCLUDE_IMPLEMENTATION
  111. #endif // JSONCPP_BATCHALLOCATOR_H_INCLUDED