Esempio n. 1
0
bool FixedAllocator::Deallocate( void * p, Chunk * hint )
{
    assert(!chunks_.empty());
    assert(&chunks_.front() <= deallocChunk_);
    assert(&chunks_.back() >= deallocChunk_);
    assert( &chunks_.front() <= allocChunk_ );
    assert( &chunks_.back() >= allocChunk_ );
    assert( CountEmptyChunks() < 2 );

    Chunk * foundChunk = ( NULL == hint ) ? VicinityFind( p ) : hint;
    if ( NULL == foundChunk )
        return false;

    assert( foundChunk->HasBlock( p, numBlocks_ * blockSize_ ) );
#ifdef LOKI_CHECK_FOR_CORRUPTION
    if ( foundChunk->IsCorrupt( numBlocks_, blockSize_, true ) )
    {
        assert( false );
        return false;
    }
    if ( foundChunk->IsBlockAvailable( p, numBlocks_, blockSize_ ) )
    {
        assert( false );
        return false;
    }
#endif
    deallocChunk_ = foundChunk;
    DoDeallocate(p);
    assert( CountEmptyChunks() < 2 );

    return true;
}
Esempio n. 2
0
bool FixedAllocator::MakeNewChunk( void )
{
    bool allocated = false;
    try
    {
        std::size_t size = chunks_.size();
        // Calling chunks_.reserve *before* creating and initializing the new
        // Chunk means that nothing is leaked by this function in case an
        // exception is thrown from reserve.
        if ( chunks_.capacity() == size )
        {
            if ( 0 == size ) size = 4;
            chunks_.reserve( size * 2 );
        }
        Chunk newChunk;
        allocated = newChunk.Init( blockSize_, numBlocks_ );
        if ( allocated )
            chunks_.push_back( newChunk );
    }
    catch ( ... )
    {
        allocated = false;
    }
    if ( !allocated ) return false;

    allocChunk_ = &chunks_.back();
    deallocChunk_ = &chunks_.front();
    return true;
}
Esempio n. 3
0
bool FixedAllocator::Deallocate( void * p, bool doChecks )
{
    if ( doChecks )
    {
        assert(!chunks_.empty());
        assert(&chunks_.front() <= deallocChunk_);
        assert(&chunks_.back() >= deallocChunk_);
        assert( &chunks_.front() <= allocChunk_ );
        assert( &chunks_.back() >= allocChunk_ );
    }

    Chunk * foundChunk = VicinityFind( p );
    if ( doChecks )
    {
        assert( NULL != foundChunk );
    }
    else if ( NULL == foundChunk )
        return false;

    deallocChunk_ = foundChunk;
    DoDeallocate(p);
    return true;
}
Esempio n. 4
0
bool FixedAllocator::TrimEmptyChunk( void )
{
    // prove either emptyChunk_ points nowhere, or points to a truly empty Chunk.
    assert( ( NULL == emptyChunk_ ) || ( emptyChunk_->HasAvailable( numBlocks_ ) ) );
    if ( NULL == emptyChunk_ ) return false;

    // If emptyChunk_ points to valid Chunk, then chunk list is not empty.
    assert( !chunks_.empty() );
    // And there should be exactly 1 empty Chunk.
    assert( 1 == CountEmptyChunks() );

    Chunk * lastChunk = &chunks_.back();
    if ( lastChunk != emptyChunk_ )
        std::swap( *emptyChunk_, *lastChunk );
    assert( lastChunk->HasAvailable( numBlocks_ ) );
    lastChunk->Release();
    chunks_.pop_back();

    if ( chunks_.empty() )
    {
        allocChunk_ = NULL;
        deallocChunk_ = NULL;
    }
    else
    {
        if ( deallocChunk_ == emptyChunk_ )
        {
            deallocChunk_ = &chunks_.front();
            assert( deallocChunk_->blocksAvailable_ < numBlocks_ );
        }
        if ( allocChunk_ == emptyChunk_ )
        {
            allocChunk_ = &chunks_.back();
            assert( allocChunk_->blocksAvailable_ < numBlocks_ );
        }
    }

    emptyChunk_ = NULL;
    assert( 0 == CountEmptyChunks() );

    return true;
}
Esempio n. 5
0
	void FixedAllocator::Deallocate(void *p)
	{
		assert(last_dealloc_);
		assert(!chunks_.empty());
		
		// find the chunk that holds the pointer.
		last_dealloc_ = FindChunk(p);
		assert(last_dealloc_);
		
		// found the chunk, so forwards deallocation request to it.
		last_dealloc_->Deallocate(p, block_size_);
		
		// the chunk is empty, should we free it?
		if (last_dealloc_->blocks_available_ == blocks_)
		{
			MemChunk *last_chunk = &chunks_.back();
			
			if (last_chunk = last_dealloc_)
			{
				if (chunks_.size() > 1 && last_dealloc_[-1].blocks_available_ == blocks_)
				{
					// there are two free chunk, so free one.
					last_chunk->Free();
					chunks_.pop_back();
					last_alloc_ = last_dealloc_ = &chunks_.front();
				}
			}
			else if (last_chunk->blocks_available_ == blocks_)
			{
				// there are two free chunk, so free one.
				last_chunk->Free();
				chunks_.pop_back();
				last_alloc_ = last_dealloc_;
			}
			else
			{
				// move the empty chunk to the bottom.
				std::swap(*last_dealloc_, *last_chunk);
				last_alloc_ = last_dealloc_;
			}
		}
	}
Esempio n. 6
0
FixedAllocator::Chunk * FixedAllocator::VicinityFind( void * p )
{
    if ( chunks_.empty() ) return NULL;
    assert(deallocChunk_);

    unsigned char * pc = static_cast< unsigned char * >( p );
    const std::size_t chunkLength = numBlocks_ * blockSize_;

    Chunk* lo = deallocChunk_;
    Chunk* hi = deallocChunk_ + 1;
    Chunk* loBound = &chunks_.front();
    Chunk* hiBound = &chunks_.back() + 1;

    // Special case: deallocChunk_ is the last in the array
    if (hi == hiBound) hi = NULL;

    for (;;)
    {
        if (lo)
        {
            if ( lo->HasBlock( pc, chunkLength ) ) return lo;
            if ( lo == loBound )
            {
                lo = NULL;
                if ( NULL == hi ) break;
            }
            else --lo;
        }

        if (hi)
        {
            if ( hi->HasBlock( pc, chunkLength ) ) return hi;
            if ( ++hi == hiBound )
            {
                hi = NULL;
                if ( NULL == lo ) break;
            }
        }
    }

    return NULL;
}
Esempio n. 7
0
	MemChunk * FixedAllocator::FindChunk(void *p)
	{
		assert(last_dealloc_);
		assert(!chunks_.empty());

		MemChunk *lo_b = &chunks_.front();
		MemChunk *hi_b = &chunks_.back()+1;
		MemChunk *lo = last_dealloc_;
		MemChunk *hi = last_dealloc_+1;
		
		if (hi == hi_b) hi = NULL;
		
		for (;;)
		{
			if (lo)
			{
				if (InChunk(lo, p))
					return lo;
				if (lo == lo_b)
					lo = NULL;
				else
					--lo;
			}
			if (hi)
			{
				if (InChunk(hi, p))
					return hi;
				if (++hi == hi_b)
					hi = NULL;
			}
		}
		
		// Never gets here.
		assert(false);
		return NULL;
	} 
Esempio n. 8
0
bool FixedAllocator::IsCorrupt( void ) const
{
    const bool isEmpty = chunks_.empty();
    ChunkCIter start( chunks_.begin() );
    ChunkCIter last( chunks_.end() );
    const size_t emptyChunkCount = CountEmptyChunks();

    if ( isEmpty )
    {
        if ( start != last )
        {
            assert( false );
            return true;
        }
        if ( 0 < emptyChunkCount )
        {
            assert( false );
            return true;
        }
        if ( NULL != deallocChunk_ )
        {
            assert( false );
            return true;
        }
        if ( NULL != allocChunk_ )
        {
            assert( false );
            return true;
        }
        if ( NULL != emptyChunk_ )
        {
            assert( false );
            return true;
        }
    }

    else
    {
        const Chunk * front = &chunks_.front();
        const Chunk * back  = &chunks_.back();
        if ( start >= last )
        {
            assert( false );
            return true;
        }
        if ( back < deallocChunk_ )
        {
            assert( false );
            return true;
        }
        if ( back < allocChunk_ )
        {
            assert( false );
            return true;
        }
        if ( front > deallocChunk_ )
        {
            assert( false );
            return true;
        }
        if ( front > allocChunk_ )
        {
            assert( false );
            return true;
        }

        switch ( emptyChunkCount )
        {
            case 0:
                if ( emptyChunk_ != NULL )
                {
                    assert( false );
                    return true;
                }
                break;
            case 1:
                if ( emptyChunk_ == NULL )
                {
                    assert( false );
                    return true;
                }
                if ( back < emptyChunk_ )
                {
                    assert( false );
                    return true;
                }
                if ( front > emptyChunk_ )
                {
                    assert( false );
                    return true;
                }
                if ( !emptyChunk_->HasAvailable( numBlocks_ ) )
                {
                    // This may imply somebody tried to delete a block twice.
                    assert( false );
                    return true;
                }
                break;
            default:
                assert( false );
                return true;
        }
        for ( ChunkCIter it( start ); it != last; ++it )
        {
            const Chunk & chunk = *it;
            if ( chunk.IsCorrupt( numBlocks_, blockSize_, true ) )
                return true;
        }
    }

    return false;
}