15 , deallocChunk_( NULL )
24 #ifdef DO_EXTRA_LOKI_TESTS
26 assert( chunks_.empty() &&
"Memory leak detected!" );
28 for (
ChunkIter i( chunks_.begin() ); i != chunks_.end(); ++i )
36 assert( blockSize > 0 );
37 assert( pageSize >= blockSize );
38 blockSize_ = blockSize;
40 std::size_t numBlocks = pageSize / blockSize;
41 if ( numBlocks > MaxObjectsPerChunk_ ) numBlocks = MaxObjectsPerChunk_;
42 else if ( numBlocks < MinObjectsPerChunk_ ) numBlocks = MinObjectsPerChunk_;
44 numBlocks_ =
static_cast<unsigned char>(numBlocks);
45 assert(numBlocks_ == numBlocks);
51 #ifdef DO_EXTRA_LOKI_TESTS
55 std::size_t count = 0;
56 for (
ChunkCIter it( chunks_.begin() ); it != chunks_.end(); ++it )
58 const Chunk & chunk = *it;
64 return ( NULL == emptyChunk_ ) ? 0 : 1;
71 const bool isEmpty = chunks_.empty();
74 const size_t emptyChunkCount = CountEmptyChunks();
83 if ( 0 < emptyChunkCount )
88 if ( NULL != deallocChunk_ )
93 if ( NULL != allocChunk_ )
98 if ( NULL != emptyChunk_ )
107 const Chunk * front = &chunks_.front();
108 const Chunk * back = &chunks_.back();
114 if ( back < deallocChunk_ )
119 if ( back < allocChunk_ )
124 if ( front > deallocChunk_ )
129 if ( front > allocChunk_ )
135 switch ( emptyChunkCount )
138 if ( emptyChunk_ != NULL )
145 if ( emptyChunk_ == NULL )
150 if ( back < emptyChunk_ )
155 if ( front > emptyChunk_ )
160 if ( !emptyChunk_->HasAvailable( numBlocks_ ) )
171 for (
ChunkCIter it( start ); it != last; ++it )
173 const Chunk & chunk = *it;
174 if ( chunk.
IsCorrupt( numBlocks_, blockSize_,
true ) )
185 const std::size_t chunkLength = numBlocks_ * blockSize_;
186 for (
ChunkCIter it( chunks_.begin() ); it != chunks_.end(); ++it )
188 const Chunk & chunk = *it;
189 if ( chunk.
HasBlock( p, chunkLength ) )
200 assert( ( NULL == emptyChunk_ ) || ( emptyChunk_->HasAvailable( numBlocks_ ) ) );
201 if ( NULL == emptyChunk_ )
return false;
204 assert( !chunks_.empty() );
206 assert( 1 == CountEmptyChunks() );
208 Chunk * lastChunk = &chunks_.back();
209 if ( lastChunk != emptyChunk_ )
210 std::swap( *emptyChunk_, *lastChunk );
215 if ( chunks_.empty() )
218 deallocChunk_ = NULL;
222 if ( deallocChunk_ == emptyChunk_ )
224 deallocChunk_ = &chunks_.front();
225 assert( deallocChunk_->fNAvail < numBlocks_ );
227 if ( allocChunk_ == emptyChunk_ )
229 allocChunk_ = &chunks_.back();
230 assert( allocChunk_->fNAvail < numBlocks_ );
235 assert( 0 == CountEmptyChunks() );
244 if ( chunks_.empty() )
246 assert( NULL == allocChunk_ );
247 assert( NULL == deallocChunk_ );
250 if ( chunks_.size() == chunks_.capacity() )
253 Chunks( chunks_ ).swap( chunks_ );
262 bool allocated =
false;
265 std::size_t size = chunks_.size();
269 if ( chunks_.capacity() == size )
271 if ( 0 == size ) size = 4;
272 chunks_.reserve( size * 2 );
275 allocated = newChunk.
Init( blockSize_, numBlocks_ );
277 chunks_.push_back( newChunk );
283 if ( !allocated )
return false;
285 allocChunk_ = &chunks_.back();
286 deallocChunk_ = &chunks_.front();
295 assert( ( NULL == emptyChunk_ ) || ( emptyChunk_->HasAvailable( numBlocks_ ) ) );
296 assert( CountEmptyChunks() < 2 );
298 if ( ( NULL == allocChunk_ ) || allocChunk_->IsFilled() )
300 if ( NULL != emptyChunk_ )
302 allocChunk_ = emptyChunk_;
307 for (
ChunkIter i( chunks_.begin() ); ; ++i )
309 if ( chunks_.end() == i )
311 if ( !MakeNewChunk() )
315 if ( !i->IsFilled() )
323 else if ( allocChunk_ == emptyChunk_)
329 assert( allocChunk_ != NULL );
330 assert( !allocChunk_->IsFilled() );
331 void * place = allocChunk_->Allocate( blockSize_ );
334 assert( ( NULL == emptyChunk_ ) || ( emptyChunk_->HasAvailable( numBlocks_ ) ) );
335 assert( CountEmptyChunks() < 2 );
336 #ifdef LOKI_CHECK_FOR_CORRUPTION
337 if ( allocChunk_->IsCorrupt( numBlocks_, blockSize_,
true ) )
351 assert(!chunks_.empty());
352 assert(&chunks_.front() <= deallocChunk_);
353 assert(&chunks_.back() >= deallocChunk_);
354 assert( &chunks_.front() <= allocChunk_ );
355 assert( &chunks_.back() >= allocChunk_ );
356 assert( CountEmptyChunks() < 2 );
358 Chunk * foundChunk = ( NULL == hint ) ? VicinityFind( p ) : hint;
359 if ( NULL == foundChunk )
362 assert( foundChunk->
HasBlock( p, numBlocks_ * blockSize_ ) );
363 #ifdef LOKI_CHECK_FOR_CORRUPTION
364 if ( foundChunk->
IsCorrupt( numBlocks_, blockSize_,
true ) )
375 deallocChunk_ = foundChunk;
377 assert( CountEmptyChunks() < 2 );
385 if ( chunks_.empty() )
return NULL;
386 assert(deallocChunk_);
388 const std::size_t chunkLength = numBlocks_ * blockSize_;
389 Chunk * lo = deallocChunk_;
390 Chunk * hi = deallocChunk_ + 1;
391 const Chunk * loBound = &chunks_.front();
392 const Chunk * hiBound = &chunks_.back() + 1;
395 if (hi == hiBound) hi = NULL;
401 if ( lo->
HasBlock( p, chunkLength ) )
return lo;
405 if ( NULL == hi )
break;
412 if ( hi->
HasBlock( p, chunkLength ) )
return hi;
413 if ( ++hi == hiBound )
416 if ( NULL == lo )
break;
429 assert( deallocChunk_->HasBlock( p, numBlocks_ * blockSize_ ) );
432 assert( emptyChunk_ != deallocChunk_ );
433 assert( !deallocChunk_->HasAvailable( numBlocks_ ) );
435 assert( ( NULL == emptyChunk_ ) || ( emptyChunk_->HasAvailable( numBlocks_ ) ) );
438 deallocChunk_->Deallocate(p, blockSize_);
440 if ( deallocChunk_->HasAvailable( numBlocks_ ) )
442 assert( emptyChunk_ != deallocChunk_ );
447 if ( NULL != emptyChunk_ )
452 Chunk * lastChunk = &chunks_.back();
453 if ( lastChunk == deallocChunk_ )
454 deallocChunk_ = emptyChunk_;
455 else if ( lastChunk != emptyChunk_ )
456 std::swap( *emptyChunk_, *lastChunk );
460 if ( ( allocChunk_ == lastChunk ) || allocChunk_->IsFilled() )
461 allocChunk_ = deallocChunk_;
463 emptyChunk_ = deallocChunk_;
467 assert( ( NULL == emptyChunk_ ) || ( emptyChunk_->HasAvailable( numBlocks_ ) ) );
bool TrimEmptyChunk(void)
void DoDeallocate(void *p)
FixedAllocator()
Create a FixedAllocator which manages blocks of 'blockSize' size.
bool IsCorrupt(void) const
Chunks::iterator ChunkIter
Iterator through container of Chunks.
static unsigned char MaxObjectsPerChunk_
Most # of objects managed by a Chunk - never exceeds UCHAR_MAX.
bool IsCorrupt(unsigned char numBlocks, std::size_t blockSize, bool checkIndexes) const
Chunk * VicinityFind(void *p) const
bool HasBlock(void *p, std::size_t chunkLength) const
Checks if this block belongs to this chunk.
bool HasAvailable(unsigned char numBlocks) const
Checks to see if this number of blocks is available in this chunk.
void Initialize(std::size_t blockSize, std::size_t pageSize)
Initializes a FixedAllocator by calculating # of blocks per Chunk.
bool Deallocate(void *p, Chunk *hint)
const Chunk * HasBlock(void *p) const
Represents a fixed number of blocks.
bool Init(std::size_t size, unsigned char n)
void Release()
Deallocates all blocks in chunck.
static unsigned char MinObjectsPerChunk_
Fewest # of objects managed by a Chunk.
bool IsBlockAvailable(void *p, unsigned char numBlocks, std::size_t blockSize) const
Checks the block starting at p and for p+numBlocks*blockSize checks to see if they're used...
std::size_t CountEmptyChunks(void) const
std::vector< Chunk > Chunks
Type of container used to hold Chunks.
~FixedAllocator()
Destroy the FixedAllocator and release all its Chunks.
Chunks::const_iterator ChunkCIter
Iterator through const container of Chunks.