Replaced NULL with nullptr.
git-svn-id: svn://svn.code.sf.net/p/loki-lib/code/trunk@1070 7ec92016-0320-0410-acc4-a06ded1c099a
This commit is contained in:
parent
6bc2851497
commit
1b9364270f
1 changed files with 84 additions and 79 deletions
163
src/SmallObj.cpp
163
src/SmallObj.cpp
|
@ -2,14 +2,14 @@
|
||||||
// The Loki Library
|
// The Loki Library
|
||||||
// Copyright (c) 2001 by Andrei Alexandrescu
|
// Copyright (c) 2001 by Andrei Alexandrescu
|
||||||
// This code accompanies the book:
|
// This code accompanies the book:
|
||||||
// Alexandrescu, Andrei. "Modern C++ Design: Generic Programming and Design
|
// Alexandrescu, Andrei. "Modern C++ Design: Generic Programming and Design
|
||||||
// Patterns Applied". Copyright (c) 2001. Addison-Wesley.
|
// Patterns Applied". Copyright (c) 2001. Addison-Wesley.
|
||||||
// Permission to use, copy, modify, distribute and sell this software for any
|
// Permission to use, copy, modify, distribute and sell this software for any
|
||||||
// purpose is hereby granted without fee, provided that the above copyright
|
// purpose is hereby granted without fee, provided that the above copyright
|
||||||
// notice appear in all copies and that both that copyright notice and this
|
// notice appear in all copies and that both that copyright notice and this
|
||||||
// permission notice appear in supporting documentation.
|
// permission notice appear in supporting documentation.
|
||||||
// The author or Addison-Wesley Longman make no representations about the
|
// The author or Addison-Wesley Longman make no representations about the
|
||||||
// suitability of this software for any purpose. It is provided "as is"
|
// suitability of this software for any purpose. It is provided "as is"
|
||||||
// without express or implied warranty.
|
// without express or implied warranty.
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
@ -31,6 +31,11 @@
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if !defined( nullptr )
|
||||||
|
#define nullptr
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
namespace Loki
|
namespace Loki
|
||||||
{
|
{
|
||||||
|
|
||||||
|
@ -157,12 +162,12 @@ namespace Loki
|
||||||
|
|
||||||
@par Class Level Invariants
|
@par Class Level Invariants
|
||||||
- There is always either zero or one Chunk which is empty.
|
- There is always either zero or one Chunk which is empty.
|
||||||
- If this has no empty Chunk, then emptyChunk_ is NULL.
|
- If this has no empty Chunk, then emptyChunk_ is nullptr.
|
||||||
- If this has an empty Chunk, then emptyChunk_ points to it.
|
- If this has an empty Chunk, then emptyChunk_ points to it.
|
||||||
- If the Chunk container is empty, then deallocChunk_ and allocChunk_
|
- If the Chunk container is empty, then deallocChunk_ and allocChunk_
|
||||||
are NULL.
|
are nullptr.
|
||||||
- If the Chunk container is not-empty, then deallocChunk_ and allocChunk_
|
- If the Chunk container is not-empty, then deallocChunk_ and allocChunk_
|
||||||
are either NULL or point to Chunks within the container.
|
are either nullptr or point to Chunks within the container.
|
||||||
- allocChunk_ will often point to the last Chunk in the container since
|
- allocChunk_ will often point to the last Chunk in the container since
|
||||||
it was likely allocated most recently, and therefore likely to have an
|
it was likely allocated most recently, and therefore likely to have an
|
||||||
available block.
|
available block.
|
||||||
|
@ -194,7 +199,7 @@ namespace Loki
|
||||||
were allocated. Opposite order = objects are deallocated in a last to
|
were allocated. Opposite order = objects are deallocated in a last to
|
||||||
first order. Complexity is O(C) where C is count of all Chunks. This
|
first order. Complexity is O(C) where C is count of all Chunks. This
|
||||||
never throws.
|
never throws.
|
||||||
@return Pointer to Chunk that owns p, or NULL if no owner found.
|
@return Pointer to Chunk that owns p, or nullptr if no owner found.
|
||||||
*/
|
*/
|
||||||
Chunk * VicinityFind( void * p ) const;
|
Chunk * VicinityFind( void * p ) const;
|
||||||
|
|
||||||
|
@ -227,7 +232,7 @@ namespace Loki
|
||||||
Chunk * allocChunk_;
|
Chunk * allocChunk_;
|
||||||
/// Pointer to Chunk used for last or next deallocation.
|
/// Pointer to Chunk used for last or next deallocation.
|
||||||
Chunk * deallocChunk_;
|
Chunk * deallocChunk_;
|
||||||
/// Pointer to the only empty Chunk if there is one, else NULL.
|
/// Pointer to the only empty Chunk if there is one, else nullptr.
|
||||||
Chunk * emptyChunk_;
|
Chunk * emptyChunk_;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
@ -240,7 +245,7 @@ namespace Loki
|
||||||
/// Initializes a FixedAllocator by calculating # of blocks per Chunk.
|
/// Initializes a FixedAllocator by calculating # of blocks per Chunk.
|
||||||
void Initialize( std::size_t blockSize, std::size_t pageSize );
|
void Initialize( std::size_t blockSize, std::size_t pageSize );
|
||||||
|
|
||||||
/** Returns pointer to allocated memory block of fixed size - or NULL
|
/** Returns pointer to allocated memory block of fixed size - or nullptr
|
||||||
if it failed to allocate.
|
if it failed to allocate.
|
||||||
*/
|
*/
|
||||||
void * Allocate( void );
|
void * Allocate( void );
|
||||||
|
@ -313,9 +318,9 @@ bool Chunk::Init( std::size_t blockSize, unsigned char blocks )
|
||||||
pData_ = static_cast< unsigned char * >( ::operator new ( allocSize ) );
|
pData_ = static_cast< unsigned char * >( ::operator new ( allocSize ) );
|
||||||
#else
|
#else
|
||||||
// malloc can't throw, so its only way to indicate an error is to return
|
// malloc can't throw, so its only way to indicate an error is to return
|
||||||
// a NULL pointer, so we have to check for that.
|
// a nullptr pointer, so we have to check for that.
|
||||||
pData_ = static_cast< unsigned char * >( ::std::malloc( allocSize ) );
|
pData_ = static_cast< unsigned char * >( ::std::malloc( allocSize ) );
|
||||||
if ( NULL == pData_ ) return false;
|
if ( nullptr == pData_ ) return false;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
Reset( blockSize, blocks );
|
Reset( blockSize, blocks );
|
||||||
|
@ -345,7 +350,7 @@ void Chunk::Reset(std::size_t blockSize, unsigned char blocks)
|
||||||
|
|
||||||
void Chunk::Release()
|
void Chunk::Release()
|
||||||
{
|
{
|
||||||
assert( NULL != pData_ );
|
assert( nullptr != pData_ );
|
||||||
#ifdef USE_NEW_TO_ALLOCATE
|
#ifdef USE_NEW_TO_ALLOCATE
|
||||||
::operator delete ( pData_ );
|
::operator delete ( pData_ );
|
||||||
#else
|
#else
|
||||||
|
@ -357,9 +362,9 @@ void Chunk::Release()
|
||||||
|
|
||||||
void* Chunk::Allocate(std::size_t blockSize)
|
void* Chunk::Allocate(std::size_t blockSize)
|
||||||
{
|
{
|
||||||
if ( IsFilled() ) return NULL;
|
if ( IsFilled() ) return nullptr;
|
||||||
|
|
||||||
assert((firstAvailableBlock_ * blockSize) / blockSize ==
|
assert((firstAvailableBlock_ * blockSize) / blockSize ==
|
||||||
firstAvailableBlock_);
|
firstAvailableBlock_);
|
||||||
unsigned char * pResult = pData_ + (firstAvailableBlock_ * blockSize);
|
unsigned char * pResult = pData_ + (firstAvailableBlock_ * blockSize);
|
||||||
firstAvailableBlock_ = *pResult;
|
firstAvailableBlock_ = *pResult;
|
||||||
|
@ -428,7 +433,7 @@ bool Chunk::IsCorrupt( unsigned char numBlocks, std::size_t blockSize,
|
||||||
found on the linked-list.
|
found on the linked-list.
|
||||||
*/
|
*/
|
||||||
std::bitset< UCHAR_MAX > foundBlocks;
|
std::bitset< UCHAR_MAX > foundBlocks;
|
||||||
unsigned char * nextBlock = NULL;
|
unsigned char * nextBlock = nullptr;
|
||||||
|
|
||||||
/* The loop goes along singly linked-list of stealth indexes and makes sure
|
/* The loop goes along singly linked-list of stealth indexes and makes sure
|
||||||
that each index is within bounds (0 <= index < numBlocks) and that the
|
that each index is within bounds (0 <= index < numBlocks) and that the
|
||||||
|
@ -503,7 +508,7 @@ bool Chunk::IsBlockAvailable( void * p, unsigned char numBlocks,
|
||||||
std::size_t blockSize ) const
|
std::size_t blockSize ) const
|
||||||
{
|
{
|
||||||
(void) numBlocks;
|
(void) numBlocks;
|
||||||
|
|
||||||
if ( IsFilled() )
|
if ( IsFilled() )
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
@ -522,7 +527,7 @@ bool Chunk::IsBlockAvailable( void * p, unsigned char numBlocks,
|
||||||
found on the linked-list.
|
found on the linked-list.
|
||||||
*/
|
*/
|
||||||
std::bitset< UCHAR_MAX > foundBlocks;
|
std::bitset< UCHAR_MAX > foundBlocks;
|
||||||
unsigned char * nextBlock = NULL;
|
unsigned char * nextBlock = nullptr;
|
||||||
for ( unsigned char cc = 0; ; )
|
for ( unsigned char cc = 0; ; )
|
||||||
{
|
{
|
||||||
nextBlock = pData_ + ( index * blockSize );
|
nextBlock = pData_ + ( index * blockSize );
|
||||||
|
@ -547,9 +552,9 @@ FixedAllocator::FixedAllocator()
|
||||||
: blockSize_( 0 )
|
: blockSize_( 0 )
|
||||||
, numBlocks_( 0 )
|
, numBlocks_( 0 )
|
||||||
, chunks_( 0 )
|
, chunks_( 0 )
|
||||||
, allocChunk_( NULL )
|
, allocChunk_( nullptr )
|
||||||
, deallocChunk_( NULL )
|
, deallocChunk_( nullptr )
|
||||||
, emptyChunk_( NULL )
|
, emptyChunk_( nullptr )
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -598,7 +603,7 @@ std::size_t FixedAllocator::CountEmptyChunks( void ) const
|
||||||
}
|
}
|
||||||
return count;
|
return count;
|
||||||
#else
|
#else
|
||||||
return ( NULL == emptyChunk_ ) ? 0 : 1;
|
return ( nullptr == emptyChunk_ ) ? 0 : 1;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -623,17 +628,17 @@ bool FixedAllocator::IsCorrupt( void ) const
|
||||||
assert( false );
|
assert( false );
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
if ( NULL != deallocChunk_ )
|
if ( nullptr != deallocChunk_ )
|
||||||
{
|
{
|
||||||
assert( false );
|
assert( false );
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
if ( NULL != allocChunk_ )
|
if ( nullptr != allocChunk_ )
|
||||||
{
|
{
|
||||||
assert( false );
|
assert( false );
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
if ( NULL != emptyChunk_ )
|
if ( nullptr != emptyChunk_ )
|
||||||
{
|
{
|
||||||
assert( false );
|
assert( false );
|
||||||
return true;
|
return true;
|
||||||
|
@ -673,14 +678,14 @@ bool FixedAllocator::IsCorrupt( void ) const
|
||||||
switch ( emptyChunkCount )
|
switch ( emptyChunkCount )
|
||||||
{
|
{
|
||||||
case 0:
|
case 0:
|
||||||
if ( emptyChunk_ != NULL )
|
if ( emptyChunk_ != nullptr )
|
||||||
{
|
{
|
||||||
assert( false );
|
assert( false );
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 1:
|
case 1:
|
||||||
if ( emptyChunk_ == NULL )
|
if ( emptyChunk_ == nullptr )
|
||||||
{
|
{
|
||||||
assert( false );
|
assert( false );
|
||||||
return true;
|
return true;
|
||||||
|
@ -728,7 +733,7 @@ const Chunk * FixedAllocator::HasBlock( void * p ) const
|
||||||
if ( chunk.HasBlock( p, chunkLength ) )
|
if ( chunk.HasBlock( p, chunkLength ) )
|
||||||
return &chunk;
|
return &chunk;
|
||||||
}
|
}
|
||||||
return NULL;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
// FixedAllocator::TrimEmptyChunk ---------------------------------------------
|
// FixedAllocator::TrimEmptyChunk ---------------------------------------------
|
||||||
|
@ -736,8 +741,8 @@ const Chunk * FixedAllocator::HasBlock( void * p ) const
|
||||||
bool FixedAllocator::TrimEmptyChunk( void )
|
bool FixedAllocator::TrimEmptyChunk( void )
|
||||||
{
|
{
|
||||||
// prove either emptyChunk_ points nowhere, or points to a truly empty Chunk.
|
// prove either emptyChunk_ points nowhere, or points to a truly empty Chunk.
|
||||||
assert( ( NULL == emptyChunk_ ) || ( emptyChunk_->HasAvailable( numBlocks_ ) ) );
|
assert( ( nullptr == emptyChunk_ ) || ( emptyChunk_->HasAvailable( numBlocks_ ) ) );
|
||||||
if ( NULL == emptyChunk_ ) return false;
|
if ( nullptr == emptyChunk_ ) return false;
|
||||||
|
|
||||||
// If emptyChunk_ points to valid Chunk, then chunk list is not empty.
|
// If emptyChunk_ points to valid Chunk, then chunk list is not empty.
|
||||||
assert( !chunks_.empty() );
|
assert( !chunks_.empty() );
|
||||||
|
@ -753,8 +758,8 @@ bool FixedAllocator::TrimEmptyChunk( void )
|
||||||
|
|
||||||
if ( chunks_.empty() )
|
if ( chunks_.empty() )
|
||||||
{
|
{
|
||||||
allocChunk_ = NULL;
|
allocChunk_ = nullptr;
|
||||||
deallocChunk_ = NULL;
|
deallocChunk_ = nullptr;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -770,7 +775,7 @@ bool FixedAllocator::TrimEmptyChunk( void )
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
emptyChunk_ = NULL;
|
emptyChunk_ = nullptr;
|
||||||
assert( 0 == CountEmptyChunks() );
|
assert( 0 == CountEmptyChunks() );
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
@ -782,8 +787,8 @@ bool FixedAllocator::TrimChunkList( void )
|
||||||
{
|
{
|
||||||
if ( chunks_.empty() )
|
if ( chunks_.empty() )
|
||||||
{
|
{
|
||||||
assert( NULL == allocChunk_ );
|
assert( nullptr == allocChunk_ );
|
||||||
assert( NULL == deallocChunk_ );
|
assert( nullptr == deallocChunk_ );
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( chunks_.size() == chunks_.capacity() )
|
if ( chunks_.size() == chunks_.capacity() )
|
||||||
|
@ -833,15 +838,15 @@ bool FixedAllocator::MakeNewChunk( void )
|
||||||
void * FixedAllocator::Allocate( void )
|
void * FixedAllocator::Allocate( void )
|
||||||
{
|
{
|
||||||
// prove either emptyChunk_ points nowhere, or points to a truly empty Chunk.
|
// prove either emptyChunk_ points nowhere, or points to a truly empty Chunk.
|
||||||
assert( ( NULL == emptyChunk_ ) || ( emptyChunk_->HasAvailable( numBlocks_ ) ) );
|
assert( ( nullptr == emptyChunk_ ) || ( emptyChunk_->HasAvailable( numBlocks_ ) ) );
|
||||||
assert( CountEmptyChunks() < 2 );
|
assert( CountEmptyChunks() < 2 );
|
||||||
|
|
||||||
if ( ( NULL == allocChunk_ ) || allocChunk_->IsFilled() )
|
if ( ( nullptr == allocChunk_ ) || allocChunk_->IsFilled() )
|
||||||
{
|
{
|
||||||
if ( NULL != emptyChunk_ )
|
if ( nullptr != emptyChunk_ )
|
||||||
{
|
{
|
||||||
allocChunk_ = emptyChunk_;
|
allocChunk_ = emptyChunk_;
|
||||||
emptyChunk_ = NULL;
|
emptyChunk_ = nullptr;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -850,7 +855,7 @@ void * FixedAllocator::Allocate( void )
|
||||||
if ( chunks_.end() == i )
|
if ( chunks_.end() == i )
|
||||||
{
|
{
|
||||||
if ( !MakeNewChunk() )
|
if ( !MakeNewChunk() )
|
||||||
return NULL;
|
return nullptr;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if ( !i->IsFilled() )
|
if ( !i->IsFilled() )
|
||||||
|
@ -862,23 +867,23 @@ void * FixedAllocator::Allocate( void )
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if ( allocChunk_ == emptyChunk_)
|
else if ( allocChunk_ == emptyChunk_)
|
||||||
// detach emptyChunk_ from allocChunk_, because after
|
// detach emptyChunk_ from allocChunk_, because after
|
||||||
// calling allocChunk_->Allocate(blockSize_); the chunk
|
// calling allocChunk_->Allocate(blockSize_); the chunk
|
||||||
// is no longer empty.
|
// is no longer empty.
|
||||||
emptyChunk_ = NULL;
|
emptyChunk_ = nullptr;
|
||||||
|
|
||||||
assert( allocChunk_ != NULL );
|
assert( allocChunk_ != nullptr );
|
||||||
assert( !allocChunk_->IsFilled() );
|
assert( !allocChunk_->IsFilled() );
|
||||||
void * place = allocChunk_->Allocate( blockSize_ );
|
void * place = allocChunk_->Allocate( blockSize_ );
|
||||||
|
|
||||||
// prove either emptyChunk_ points nowhere, or points to a truly empty Chunk.
|
// prove either emptyChunk_ points nowhere, or points to a truly empty Chunk.
|
||||||
assert( ( NULL == emptyChunk_ ) || ( emptyChunk_->HasAvailable( numBlocks_ ) ) );
|
assert( ( nullptr == emptyChunk_ ) || ( emptyChunk_->HasAvailable( numBlocks_ ) ) );
|
||||||
assert( CountEmptyChunks() < 2 );
|
assert( CountEmptyChunks() < 2 );
|
||||||
#ifdef LOKI_CHECK_FOR_CORRUPTION
|
#ifdef LOKI_CHECK_FOR_CORRUPTION
|
||||||
if ( allocChunk_->IsCorrupt( numBlocks_, blockSize_, true ) )
|
if ( allocChunk_->IsCorrupt( numBlocks_, blockSize_, true ) )
|
||||||
{
|
{
|
||||||
assert( false );
|
assert( false );
|
||||||
return NULL;
|
return nullptr;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -896,8 +901,8 @@ bool FixedAllocator::Deallocate( void * p, Chunk * hint )
|
||||||
assert( &chunks_.back() >= allocChunk_ );
|
assert( &chunks_.back() >= allocChunk_ );
|
||||||
assert( CountEmptyChunks() < 2 );
|
assert( CountEmptyChunks() < 2 );
|
||||||
|
|
||||||
Chunk * foundChunk = ( NULL == hint ) ? VicinityFind( p ) : hint;
|
Chunk * foundChunk = ( nullptr == hint ) ? VicinityFind( p ) : hint;
|
||||||
if ( NULL == foundChunk )
|
if ( nullptr == foundChunk )
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
assert( foundChunk->HasBlock( p, numBlocks_ * blockSize_ ) );
|
assert( foundChunk->HasBlock( p, numBlocks_ * blockSize_ ) );
|
||||||
|
@ -924,7 +929,7 @@ bool FixedAllocator::Deallocate( void * p, Chunk * hint )
|
||||||
|
|
||||||
Chunk * FixedAllocator::VicinityFind( void * p ) const
|
Chunk * FixedAllocator::VicinityFind( void * p ) const
|
||||||
{
|
{
|
||||||
if ( chunks_.empty() ) return NULL;
|
if ( chunks_.empty() ) return nullptr;
|
||||||
assert(deallocChunk_);
|
assert(deallocChunk_);
|
||||||
|
|
||||||
const std::size_t chunkLength = numBlocks_ * blockSize_;
|
const std::size_t chunkLength = numBlocks_ * blockSize_;
|
||||||
|
@ -934,7 +939,7 @@ Chunk * FixedAllocator::VicinityFind( void * p ) const
|
||||||
const Chunk * hiBound = &chunks_.back() + 1;
|
const Chunk * hiBound = &chunks_.back() + 1;
|
||||||
|
|
||||||
// Special case: deallocChunk_ is the last in the array
|
// Special case: deallocChunk_ is the last in the array
|
||||||
if (hi == hiBound) hi = NULL;
|
if (hi == hiBound) hi = nullptr;
|
||||||
|
|
||||||
for (;;)
|
for (;;)
|
||||||
{
|
{
|
||||||
|
@ -943,8 +948,8 @@ Chunk * FixedAllocator::VicinityFind( void * p ) const
|
||||||
if ( lo->HasBlock( p, chunkLength ) ) return lo;
|
if ( lo->HasBlock( p, chunkLength ) ) return lo;
|
||||||
if ( lo == loBound )
|
if ( lo == loBound )
|
||||||
{
|
{
|
||||||
lo = NULL;
|
lo = nullptr;
|
||||||
if ( NULL == hi ) break;
|
if ( nullptr == hi ) break;
|
||||||
}
|
}
|
||||||
else --lo;
|
else --lo;
|
||||||
}
|
}
|
||||||
|
@ -954,13 +959,13 @@ Chunk * FixedAllocator::VicinityFind( void * p ) const
|
||||||
if ( hi->HasBlock( p, chunkLength ) ) return hi;
|
if ( hi->HasBlock( p, chunkLength ) ) return hi;
|
||||||
if ( ++hi == hiBound )
|
if ( ++hi == hiBound )
|
||||||
{
|
{
|
||||||
hi = NULL;
|
hi = nullptr;
|
||||||
if ( NULL == lo ) break;
|
if ( nullptr == lo ) break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return NULL;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
// FixedAllocator::DoDeallocate -----------------------------------------------
|
// FixedAllocator::DoDeallocate -----------------------------------------------
|
||||||
|
@ -974,7 +979,7 @@ void FixedAllocator::DoDeallocate(void* p)
|
||||||
assert( emptyChunk_ != deallocChunk_ );
|
assert( emptyChunk_ != deallocChunk_ );
|
||||||
assert( !deallocChunk_->HasAvailable( numBlocks_ ) );
|
assert( !deallocChunk_->HasAvailable( numBlocks_ ) );
|
||||||
// prove either emptyChunk_ points nowhere, or points to a truly empty Chunk.
|
// prove either emptyChunk_ points nowhere, or points to a truly empty Chunk.
|
||||||
assert( ( NULL == emptyChunk_ ) || ( emptyChunk_->HasAvailable( numBlocks_ ) ) );
|
assert( ( nullptr == emptyChunk_ ) || ( emptyChunk_->HasAvailable( numBlocks_ ) ) );
|
||||||
|
|
||||||
// call into the chunk, will adjust the inner list but won't release memory
|
// call into the chunk, will adjust the inner list but won't release memory
|
||||||
deallocChunk_->Deallocate(p, blockSize_);
|
deallocChunk_->Deallocate(p, blockSize_);
|
||||||
|
@ -986,7 +991,7 @@ void FixedAllocator::DoDeallocate(void* p)
|
||||||
// empty chunks. Since emptyChunk_ may only point to a previously
|
// empty chunks. Since emptyChunk_ may only point to a previously
|
||||||
// cleared Chunk, if it points to something else besides deallocChunk_,
|
// cleared Chunk, if it points to something else besides deallocChunk_,
|
||||||
// then FixedAllocator currently has 2 empty Chunks.
|
// then FixedAllocator currently has 2 empty Chunks.
|
||||||
if ( NULL != emptyChunk_ )
|
if ( nullptr != emptyChunk_ )
|
||||||
{
|
{
|
||||||
// If last Chunk is empty, just change what deallocChunk_
|
// If last Chunk is empty, just change what deallocChunk_
|
||||||
// points to, and release the last. Otherwise, swap an empty
|
// points to, and release the last. Otherwise, swap an empty
|
||||||
|
@ -999,14 +1004,14 @@ void FixedAllocator::DoDeallocate(void* p)
|
||||||
assert( lastChunk->HasAvailable( numBlocks_ ) );
|
assert( lastChunk->HasAvailable( numBlocks_ ) );
|
||||||
lastChunk->Release();
|
lastChunk->Release();
|
||||||
chunks_.pop_back();
|
chunks_.pop_back();
|
||||||
if ( ( allocChunk_ == lastChunk ) || allocChunk_->IsFilled() )
|
if ( ( allocChunk_ == lastChunk ) || allocChunk_->IsFilled() )
|
||||||
allocChunk_ = deallocChunk_;
|
allocChunk_ = deallocChunk_;
|
||||||
}
|
}
|
||||||
emptyChunk_ = deallocChunk_;
|
emptyChunk_ = deallocChunk_;
|
||||||
}
|
}
|
||||||
|
|
||||||
// prove either emptyChunk_ points nowhere, or points to a truly empty Chunk.
|
// prove either emptyChunk_ points nowhere, or points to a truly empty Chunk.
|
||||||
assert( ( NULL == emptyChunk_ ) || ( emptyChunk_->HasAvailable( numBlocks_ ) ) );
|
assert( ( nullptr == emptyChunk_ ) || ( emptyChunk_->HasAvailable( numBlocks_ ) ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetOffset ------------------------------------------------------------------
|
// GetOffset ------------------------------------------------------------------
|
||||||
|
@ -1025,7 +1030,7 @@ inline std::size_t GetOffset( std::size_t numBytes, std::size_t alignment )
|
||||||
the size which can be handled by any FixedAllocator.
|
the size which can be handled by any FixedAllocator.
|
||||||
@param numBytes number of bytes
|
@param numBytes number of bytes
|
||||||
@param doThrow True if this function should throw an exception, or false if it
|
@param doThrow True if this function should throw an exception, or false if it
|
||||||
should indicate failure by returning a NULL pointer.
|
should indicate failure by returning a nullptr pointer.
|
||||||
*/
|
*/
|
||||||
void * DefaultAllocator( std::size_t numBytes, bool doThrow )
|
void * DefaultAllocator( std::size_t numBytes, bool doThrow )
|
||||||
{
|
{
|
||||||
|
@ -1034,7 +1039,7 @@ void * DefaultAllocator( std::size_t numBytes, bool doThrow )
|
||||||
::operator new( numBytes, std::nothrow_t() );
|
::operator new( numBytes, std::nothrow_t() );
|
||||||
#else
|
#else
|
||||||
void * p = ::std::malloc( numBytes );
|
void * p = ::std::malloc( numBytes );
|
||||||
if ( doThrow && ( NULL == p ) )
|
if ( doThrow && ( nullptr == p ) )
|
||||||
throw std::bad_alloc();
|
throw std::bad_alloc();
|
||||||
return p;
|
return p;
|
||||||
#endif
|
#endif
|
||||||
|
@ -1042,7 +1047,7 @@ void * DefaultAllocator( std::size_t numBytes, bool doThrow )
|
||||||
|
|
||||||
// DefaultDeallocator ---------------------------------------------------------
|
// DefaultDeallocator ---------------------------------------------------------
|
||||||
/** @ingroup SmallObjectGroupInternal
|
/** @ingroup SmallObjectGroupInternal
|
||||||
Calls default deallocator when SmallObjAllocator decides not to handle a
|
Calls default deallocator when SmallObjAllocator decides not to handle a
|
||||||
request. The default deallocator could be the global delete operator or the
|
request. The default deallocator could be the global delete operator or the
|
||||||
free function. The free function is the preferred default deallocator since
|
free function. The free function is the preferred default deallocator since
|
||||||
it matches malloc which is the preferred default allocator. SmallObjAllocator
|
it matches malloc which is the preferred default allocator. SmallObjAllocator
|
||||||
|
@ -1061,7 +1066,7 @@ void DefaultDeallocator( void * p )
|
||||||
|
|
||||||
SmallObjAllocator::SmallObjAllocator( std::size_t pageSize,
|
SmallObjAllocator::SmallObjAllocator( std::size_t pageSize,
|
||||||
std::size_t maxObjectSize, std::size_t objectAlignSize ) :
|
std::size_t maxObjectSize, std::size_t objectAlignSize ) :
|
||||||
pool_( NULL ),
|
pool_( nullptr ),
|
||||||
maxSmallObjectSize_( maxObjectSize ),
|
maxSmallObjectSize_( maxObjectSize ),
|
||||||
objectAlignSize_( objectAlignSize )
|
objectAlignSize_( objectAlignSize )
|
||||||
{
|
{
|
||||||
|
@ -1113,7 +1118,7 @@ void * SmallObjAllocator::Allocate( std::size_t numBytes, bool doThrow )
|
||||||
if ( numBytes > GetMaxObjectSize() )
|
if ( numBytes > GetMaxObjectSize() )
|
||||||
return DefaultAllocator( numBytes, doThrow );
|
return DefaultAllocator( numBytes, doThrow );
|
||||||
|
|
||||||
assert( NULL != pool_ );
|
assert( nullptr != pool_ );
|
||||||
if ( 0 == numBytes ) numBytes = 1;
|
if ( 0 == numBytes ) numBytes = 1;
|
||||||
const std::size_t index = GetOffset( numBytes, GetAlignment() ) - 1;
|
const std::size_t index = GetOffset( numBytes, GetAlignment() ) - 1;
|
||||||
const std::size_t allocCount = GetOffset( GetMaxObjectSize(), GetAlignment() );
|
const std::size_t allocCount = GetOffset( GetMaxObjectSize(), GetAlignment() );
|
||||||
|
@ -1125,10 +1130,10 @@ void * SmallObjAllocator::Allocate( std::size_t numBytes, bool doThrow )
|
||||||
assert( allocator.BlockSize() < numBytes + GetAlignment() );
|
assert( allocator.BlockSize() < numBytes + GetAlignment() );
|
||||||
void * place = allocator.Allocate();
|
void * place = allocator.Allocate();
|
||||||
|
|
||||||
if ( ( NULL == place ) && TrimExcessMemory() )
|
if ( ( nullptr == place ) && TrimExcessMemory() )
|
||||||
place = allocator.Allocate();
|
place = allocator.Allocate();
|
||||||
|
|
||||||
if ( ( NULL == place ) && doThrow )
|
if ( ( nullptr == place ) && doThrow )
|
||||||
{
|
{
|
||||||
#ifdef _MSC_VER
|
#ifdef _MSC_VER
|
||||||
throw std::bad_alloc( "could not allocate small object" );
|
throw std::bad_alloc( "could not allocate small object" );
|
||||||
|
@ -1145,13 +1150,13 @@ void * SmallObjAllocator::Allocate( std::size_t numBytes, bool doThrow )
|
||||||
|
|
||||||
void SmallObjAllocator::Deallocate( void * p, std::size_t numBytes )
|
void SmallObjAllocator::Deallocate( void * p, std::size_t numBytes )
|
||||||
{
|
{
|
||||||
if ( NULL == p ) return;
|
if ( nullptr == p ) return;
|
||||||
if ( numBytes > GetMaxObjectSize() )
|
if ( numBytes > GetMaxObjectSize() )
|
||||||
{
|
{
|
||||||
DefaultDeallocator( p );
|
DefaultDeallocator( p );
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
assert( NULL != pool_ );
|
assert( nullptr != pool_ );
|
||||||
if ( 0 == numBytes ) numBytes = 1;
|
if ( 0 == numBytes ) numBytes = 1;
|
||||||
const std::size_t index = GetOffset( numBytes, GetAlignment() ) - 1;
|
const std::size_t index = GetOffset( numBytes, GetAlignment() ) - 1;
|
||||||
const std::size_t allocCount = GetOffset( GetMaxObjectSize(), GetAlignment() );
|
const std::size_t allocCount = GetOffset( GetMaxObjectSize(), GetAlignment() );
|
||||||
|
@ -1160,7 +1165,7 @@ void SmallObjAllocator::Deallocate( void * p, std::size_t numBytes )
|
||||||
FixedAllocator & allocator = pool_[ index ];
|
FixedAllocator & allocator = pool_[ index ];
|
||||||
assert( allocator.BlockSize() >= numBytes );
|
assert( allocator.BlockSize() >= numBytes );
|
||||||
assert( allocator.BlockSize() < numBytes + GetAlignment() );
|
assert( allocator.BlockSize() < numBytes + GetAlignment() );
|
||||||
const bool found = allocator.Deallocate( p, NULL );
|
const bool found = allocator.Deallocate( p, nullptr );
|
||||||
(void) found;
|
(void) found;
|
||||||
assert( found );
|
assert( found );
|
||||||
}
|
}
|
||||||
|
@ -1169,28 +1174,28 @@ void SmallObjAllocator::Deallocate( void * p, std::size_t numBytes )
|
||||||
|
|
||||||
void SmallObjAllocator::Deallocate( void * p )
|
void SmallObjAllocator::Deallocate( void * p )
|
||||||
{
|
{
|
||||||
if ( NULL == p ) return;
|
if ( nullptr == p ) return;
|
||||||
assert( NULL != pool_ );
|
assert( nullptr != pool_ );
|
||||||
FixedAllocator * pAllocator = NULL;
|
FixedAllocator * pAllocator = nullptr;
|
||||||
const std::size_t allocCount = GetOffset( GetMaxObjectSize(), GetAlignment() );
|
const std::size_t allocCount = GetOffset( GetMaxObjectSize(), GetAlignment() );
|
||||||
Chunk * chunk = NULL;
|
Chunk * chunk = nullptr;
|
||||||
|
|
||||||
for ( std::size_t ii = 0; ii < allocCount; ++ii )
|
for ( std::size_t ii = 0; ii < allocCount; ++ii )
|
||||||
{
|
{
|
||||||
chunk = pool_[ ii ].HasBlock( p );
|
chunk = pool_[ ii ].HasBlock( p );
|
||||||
if ( NULL != chunk )
|
if ( nullptr != chunk )
|
||||||
{
|
{
|
||||||
pAllocator = &pool_[ ii ];
|
pAllocator = &pool_[ ii ];
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if ( NULL == pAllocator )
|
if ( nullptr == pAllocator )
|
||||||
{
|
{
|
||||||
DefaultDeallocator( p );
|
DefaultDeallocator( p );
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
assert( NULL != chunk );
|
assert( nullptr != chunk );
|
||||||
const bool found = pAllocator->Deallocate( p, chunk );
|
const bool found = pAllocator->Deallocate( p, chunk );
|
||||||
(void) found;
|
(void) found;
|
||||||
assert( found );
|
assert( found );
|
||||||
|
@ -1200,7 +1205,7 @@ void SmallObjAllocator::Deallocate( void * p )
|
||||||
|
|
||||||
bool SmallObjAllocator::IsCorrupt( void ) const
|
bool SmallObjAllocator::IsCorrupt( void ) const
|
||||||
{
|
{
|
||||||
if ( NULL == pool_ )
|
if ( nullptr == pool_ )
|
||||||
{
|
{
|
||||||
assert( false );
|
assert( false );
|
||||||
return true;
|
return true;
|
||||||
|
|
Loading…
Add table
Reference in a new issue