Drizzled Public API Documentation

json_batchallocator.h
00001 /*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
00002  * 
00003  *  JSON Library, originally from http://jsoncpp.sourceforge.net/
00004  *
00005  *  Copyright (C) 2011 Stewart Smith
00006  *  All rights reserved.
00007  *
00008  *  Redistribution and use in source and binary forms, with or without
00009  *  modification, are permitted provided that the following conditions are
00010  *  met:
00011  *
00012  *      * Redistributions of source code must retain the above copyright
00013  *  notice, this list of conditions and the following disclaimer.
00014  *
00015  *      * Redistributions in binary form must reproduce the above
00016  *  copyright notice, this list of conditions and the following disclaimer
00017  *  in the documentation and/or other materials provided with the
00018  *  distribution.
00019  *
00020  *      * The names of its contributors may not be used to endorse or
00021  *  promote products derived from this software without specific prior
00022  *  written permission.
00023  *
00024  *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
00025  *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
00026  *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
00027  *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
00028  *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
00029  *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
00030  *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
00031  *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
00032  *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
00033  *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
00034  *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00035  *
00036  */
00037 
00038 #pragma once
00039 #ifndef JSONCPP_BATCHALLOCATOR_H_INCLUDED
00040 # define JSONCPP_BATCHALLOCATOR_H_INCLUDED
00041 
00042 # include <stdlib.h>
00043 # include <assert.h>
00044 
00045 # ifndef JSONCPP_DOC_EXCLUDE_IMPLEMENTATION
00046 
00047 namespace Json {
00048 
00049 /* Fast memory allocator.
00050  *
00051  * This memory allocator allocates memory for a batch of object (specified by
00052  * the page size, the number of object in each page).
00053  *
00054  * It does not allow the destruction of a single object. All the allocated objects
00055  * can be destroyed at once. The memory can be either released or reused for future
00056  * allocation.
00057  * 
00058  * The in-place new operator must be used to construct the object using the pointer
00059  * returned by allocate.
00060  */
00061 template<typename AllocatedType
00062         ,const unsigned int objectPerAllocation>
00063 class BatchAllocator
00064 {
00065 public:
00066    typedef AllocatedType Type;
00067 
00068    BatchAllocator( unsigned int objectsPerPage = 255 )
00069       : freeHead_( 0 )
00070       , objectsPerPage_( objectsPerPage )
00071    {
00072 //      printf( "Size: %d => %s\n", sizeof(AllocatedType), typeid(AllocatedType).name() );
00073       assert( sizeof(AllocatedType) * objectPerAllocation >= sizeof(AllocatedType *) ); // We must be able to store a slist in the object free space.
00074       assert( objectsPerPage >= 16 );
00075       batches_ = allocateBatch( 0 );   // allocated a dummy page
00076       currentBatch_ = batches_;
00077    }
00078 
00079    ~BatchAllocator()
00080    {
00081       for ( BatchInfo *batch = batches_; batch;  )
00082       {
00083          BatchInfo *nextBatch = batch->next_;
00084          free( batch );
00085          batch = nextBatch;
00086       }
00087    }
00088 
00091    AllocatedType *allocate()
00092    {
00093       if ( freeHead_ ) // returns node from free list.
00094       {
00095          AllocatedType *object = freeHead_;
00096          freeHead_ = *(AllocatedType **)object;
00097          return object;
00098       }
00099       if ( currentBatch_->used_ == currentBatch_->end_ )
00100       {
00101          currentBatch_ = currentBatch_->next_;
00102          while ( currentBatch_  &&  currentBatch_->used_ == currentBatch_->end_ )
00103             currentBatch_ = currentBatch_->next_;
00104 
00105          if ( !currentBatch_  ) // no free batch found, allocate a new one
00106          { 
00107             currentBatch_ = allocateBatch( objectsPerPage_ );
00108             currentBatch_->next_ = batches_; // insert at the head of the list
00109             batches_ = currentBatch_;
00110          }
00111       }
00112       AllocatedType *allocated = currentBatch_->used_;
00113       currentBatch_->used_ += objectPerAllocation;
00114       return allocated;
00115    }
00116 
00119    void release( AllocatedType *object )
00120    {
00121       assert( object != 0 );
00122       *(AllocatedType **)object = freeHead_;
00123       freeHead_ = object;
00124    }
00125 
00126 private:
00127    struct BatchInfo
00128    {
00129       BatchInfo *next_;
00130       AllocatedType *used_;
00131       AllocatedType *end_;
00132       AllocatedType buffer_[objectPerAllocation];
00133    };
00134 
00135    // disabled copy constructor and assignement operator.
00136    BatchAllocator( const BatchAllocator & );
00137    void operator =( const BatchAllocator &);
00138 
00139    static BatchInfo *allocateBatch( unsigned int objectsPerPage )
00140    {
00141       const unsigned int mallocSize = sizeof(BatchInfo) - sizeof(AllocatedType)* objectPerAllocation
00142                                 + sizeof(AllocatedType) * objectPerAllocation * objectsPerPage;
00143       BatchInfo *batch = static_cast<BatchInfo*>( malloc( mallocSize ) );
00144       batch->next_ = 0;
00145       batch->used_ = batch->buffer_;
00146       batch->end_ = batch->buffer_ + objectsPerPage;
00147       return batch;
00148    }
00149 
00150    BatchInfo *batches_;
00151    BatchInfo *currentBatch_;
00153    AllocatedType *freeHead_;
00154    unsigned int objectsPerPage_;
00155 };
00156 
00157 
00158 } // namespace Json
00159 
00160 # endif // ifndef JSONCPP_DOC_INCLUDE_IMPLEMENTATION
00161 
00162 #endif // JSONCPP_BATCHALLOCATOR_H_INCLUDED
00163