home *** CD-ROM | disk | FTP | other *** search
Text File | 1994-04-21 | 27.4 KB | 959 lines | [TEXT/MPS ] |
- //========================================================================================
- //
- // File: FWBestFH.cpp
- // Release Version: $ 1.0d1 $
- //
- // Creation Date: 3/28/94
- //
- // Copyright: © 1993, 1994 by Apple Computer, Inc., all rights reserved.
- //
- //========================================================================================
-
- #ifndef FWPLATME_H
- #include <FWPlatMe.h>
- #endif
-
- #ifndef FWBESTFH_H
- #include <FWBestFH.h>
- #endif
-
- #ifndef __MEMORY__
- #include <Memory.h>
- #endif
-
- #ifndef __LIMITS__
- #include <limits.h>
- #endif
-
- #ifndef __STRING__
- #include <string.h>
- #endif
-
- #ifndef __STDIO__
- #include <stdio.h>
- #endif
-
-
- //========================================================================================
- // FW_CPrivBestFitBlock
- //========================================================================================
-
- //----------------------------------------------------------------------------------------
- // FW_CPrivBestFitBlock::operator >
- //----------------------------------------------------------------------------------------
- #pragma segment HeapSeg
-
- Boolean FW_CPrivBestFitBlock::operator>(const FW_CPrivBestFitBlock& blk) const
- {
- if (GetSize() == blk.GetSize())
- return this > &blk;
- else
- return GetSize() > blk.GetSize();
- }
-
- //----------------------------------------------------------------------------------------
- // FW_CPrivBestFitBlock::operator <
- //----------------------------------------------------------------------------------------
- #pragma segment HeapSeg
-
- Boolean FW_CPrivBestFitBlock::operator<(const FW_CPrivBestFitBlock& blk) const
- {
- if (GetSize() == blk.GetSize())
- return this < &blk;
- else
- return GetSize() < blk.GetSize();
- }
-
- //----------------------------------------------------------------------------------------
- // FW_CPrivBestFitBlock::operator ==
- //----------------------------------------------------------------------------------------
- #pragma segment HeapSeg
-
- Boolean FW_CPrivBestFitBlock::operator==(const FW_CPrivBestFitBlock& blk) const
- {
- return GetSize() == blk.GetSize() && this == &blk;
- }
-
- //----------------------------------------------------------------------------------------
- // FW_CPrivBestFitBlock::StuffAddressAtEnd
- //----------------------------------------------------------------------------------------
- #pragma segment HeapSeg
-
- void FW_CPrivBestFitBlock::StuffAddressAtEnd()
- {
- // coalescence possible in constant time.
-
- if (!this->GetBusy())
- {
- void** addr= (void**) ((FW_BytePtr) this + this->GetSize() - sizeof(FW_CPrivBestFitBlock *));
- *addr = this;
- }
- #ifdef FW_DEBUG
- else
- PLATFORM_DEBUGGER_STRING("FW_CPrivBestFitBlock::StuffAddressAtEnd: corrupt heap!");
- #endif
- }
-
-
- //========================================================================================
- // FW_CBestFitHeap
- //========================================================================================
-
- //----------------------------------------------------------------------------------------
- // FW_CBestFitHeap::FW_CBestFitHeap
- //----------------------------------------------------------------------------------------
- #pragma segment HeapSeg
-
- FW_CBestFitHeap::FW_CBestFitHeap(unsigned long sizeInitial,
- unsigned long sizeIncrement) :
- FW_CMemoryHeap(false, true, false)
- {
- #ifdef FW_DEBUG
- CompilerCheck();
- #endif
-
- fSizeIncrement = sizeIncrement;
- fSizeInitial = sizeInitial;
- fSegments = NULL;
-
- // this->GrowHeap(fSizeInitial); * MEB *
- }
-
- //----------------------------------------------------------------------------------------
- // FW_CBestFitHeap::~FW_CBestFitHeap
- //----------------------------------------------------------------------------------------
- #pragma segment HeapSeg
-
- FW_CBestFitHeap::~FW_CBestFitHeap()
- {
- this->DeleteSegments();
- }
-
- //----------------------------------------------------------------------------------------
- // FW_CBestFitHeap::IBestFitHeap * MEB *
- //----------------------------------------------------------------------------------------
- #pragma segment HeapSeg
-
- void FW_CBestFitHeap::IBestFitHeap()
- {
- this->GrowHeap(fSizeInitial);
- }
-
- //----------------------------------------------------------------------------------------
- // FW_CBestFitHeap::ExpandHeap * MEB *
- //----------------------------------------------------------------------------------------
- #pragma segment HeapSeg
-
- void FW_CBestFitHeap::ExpandHeap(unsigned long sizeInitial, unsigned long sizeIncrement)
- {
- if (sizeInitial > fSizeInitial)
- fSizeInitial = sizeInitial;
- if (sizeIncrement > fSizeIncrement)
- fSizeIncrement = sizeIncrement;
-
- if (sizeInitial > this->HeapSize())
- this->GrowHeap(sizeInitial);
- else
- this->GrowHeap(sizeIncrement);
- }
-
- //----------------------------------------------------------------------------------------
- // FW_CBestFitHeap::BytesFree
- //----------------------------------------------------------------------------------------
- #pragma segment HeapSeg
-
- unsigned long FW_CBestFitHeap::BytesFree() const
- {
- unsigned long bytesFree, numberOfNodes;
-
- fFreeTree.TreeInfo(bytesFree, numberOfNodes);
- bytesFree -= numberOfNodes * FW_CPrivBestFitBlock::kBusyOverhead;
-
- return bytesFree;
- }
-
- #ifdef FW_DEBUG
- //----------------------------------------------------------------------------------------
- // FW_CBestFitHeap::Check
- //----------------------------------------------------------------------------------------
- #pragma segment HeapSeg
-
- void FW_CBestFitHeap::Check() const
- {
- fFreeTree.CheckTree();
- }
- #endif
-
- //----------------------------------------------------------------------------------------
- // FW_CBestFitHeap::DoAllocate
- //----------------------------------------------------------------------------------------
- #pragma segment HeapSeg
-
- void* FW_CBestFitHeap::DoAllocate(FW_BlockSize size, FW_BlockSize& allocatedSize)
- {
- FW_BlockSize blkSize = size + FW_CPrivBestFitBlock::kBusyOverhead;
-
- if (blkSize < FW_CPrivBestFitBlock::kMinBlockSize)
- blkSize = FW_CPrivBestFitBlock::kMinBlockSize;
-
- // Make sure blkSize is even
-
- if (blkSize & 0x01)
- blkSize++;
-
- #ifdef FW_DEBUG
- PLATFORM_ASSERT(blkSize <= BestFitBlock_kMaxBlockSize);
- #endif
-
- FW_CPrivBestFitBlock * blk = this->SearchFreeBlocks(blkSize);
-
- // Make an attempt to expand the heap
-
- if (blk == NULL && fSizeIncrement > 0)
- {
- this->GrowHeap(fSizeIncrement);
- blk = this->SearchFreeBlocks(blkSize);
- }
-
- allocatedSize = 0;
- void* newPtr = NULL;
-
- if (blk != NULL)
- {
- // We found a block, so mark it busy and remove it from the free list.
-
- blk->SetBusy(true);
- this->RemoveFromFreeBlocks(blk);
-
- if (blk->GetSize() - blkSize >= FW_CPrivBestFitBlock::kMinBlockSize)
- {
- // The block is big enough to split, so here we do the split.
-
- FW_CPrivBestFitBlock *newBlk
- = new((void *) ((FW_BytePtr) blk + blkSize))
- FW_CPrivBestFitBlock(false, true, blk->GetSize() - blkSize);
- this->AddToFreeBlocks(newBlk);
- blk->SetSize(blkSize);
- }
-
- FW_CPrivBestFitBlock * nextBlk
- = (FW_CPrivBestFitBlock *) ((FW_BytePtr) blk + blk->GetSize());
- nextBlk->SetPrevBusy(true);
-
- newPtr = (void *) ((FW_BytePtr) blk + FW_CPrivBestFitBlock::kBusyOverhead);
- allocatedSize = blk->GetSize() - FW_CPrivBestFitBlock::kBusyOverhead;
- }
-
- return newPtr;
- }
-
- //----------------------------------------------------------------------------------------
- // FW_CBestFitHeap::DoBlockSize
- //----------------------------------------------------------------------------------------
- #pragma segment HeapSeg
-
- FW_BlockSize FW_CBestFitHeap::DoBlockSize(const void* block) const
- {
- FW_CPrivBestFitBlock * blk
- = (FW_CPrivBestFitBlock *) ((FW_BytePtr) block - FW_CPrivBestFitBlock::kBusyOverhead);
-
- #ifdef FW_DEBUG
- PLATFORM_ASSERT(blk->GetBusy());
- #endif
-
- return blk->GetSize() - FW_CPrivBestFitBlock::kBusyOverhead;
- }
-
- //----------------------------------------------------------------------------------------
- // FW_CBestFitHeap::DoFree
- //----------------------------------------------------------------------------------------
- #pragma segment HeapSeg
-
- void FW_CBestFitHeap::DoFree(void* ptr)
- {
- FW_CPrivBestFitBlock *blk
- = (FW_CPrivBestFitBlock *) ((FW_BytePtr) ptr - FW_CPrivBestFitBlock::kBusyOverhead);
-
- #ifdef FW_DEBUG
- PLATFORM_ASSERT(blk->GetBusy());
- #endif
-
- blk->SetBusy(false);
- blk->StuffAddressAtEnd();
-
- FW_CPrivBestFitBlock *nextBlk
- = (FW_CPrivBestFitBlock *) ((FW_BytePtr) blk + blk->GetSize());
- nextBlk->SetPrevBusy(false);
-
- if (this->Coalesce(nextBlk))
- this->RemoveFromFreeBlocks(nextBlk);
-
- FW_CPrivBestFitBlock * prevBlk = this->Coalesce(blk);
- if (prevBlk)
- {
- this->RemoveFromFreeBlocks(prevBlk);
- this->AddToFreeBlocks(prevBlk);
- }
- else
- this->AddToFreeBlocks(blk);
- }
-
- #ifdef FW_DEBUG
- //----------------------------------------------------------------------------------------
- // FW_CBestFitHeap::DoIsValidBlock
- //----------------------------------------------------------------------------------------
- #pragma segment HeapSeg
-
- Boolean FW_CBestFitHeap::DoIsValidBlock(void* ptr) const
- {
- FW_CPrivBestFitBlock *blk
- = (FW_CPrivBestFitBlock *) ((FW_BytePtr) ptr - FW_CPrivBestFitBlock::kBusyOverhead);
-
- FW_BlockSize blkSize = blk->GetSize();
-
- return (blkSize <= fSizeIncrement || blkSize <= fSizeInitial) && blk->GetBusy() && blk->GetMagicNumber() == (unsigned int)FW_CPrivBestFitBlock::kMagicNumber;
- }
- #endif
-
- //----------------------------------------------------------------------------------------
- // FW_CBestFitHeap::DoReset
- //----------------------------------------------------------------------------------------
- #pragma segment HeapSeg
-
- void FW_CBestFitHeap::DoReset()
- {
- this->DeleteSegments();
- fSegments = NULL;
- fFreeTree = FW_CPrivFreeBlockTree();
-
- this->GrowHeap(fSizeInitial);
- }
-
- //----------------------------------------------------------------------------------------
- // FW_CBestFitHeap::HeapSize
- //----------------------------------------------------------------------------------------
- #pragma segment HeapSeg
-
- unsigned long FW_CBestFitHeap::HeapSize() const
- {
- FW_CPrivBestFitSegment * segment = fSegments;
- unsigned long heapSize = 0;
-
- while (segment != NULL)
- {
- heapSize += segment->fSegmentSize;
- segment = segment->fNextSegment;
- }
-
- return heapSize;
- }
-
- #ifdef FW_DEBUG
- //----------------------------------------------------------------------------------------
- // FW_CBestFitHeap::IsMyBlock
- //----------------------------------------------------------------------------------------
- #pragma segment HeapSeg
-
- Boolean FW_CBestFitHeap::IsMyBlock(void* blk) const
- {
- Boolean myBlock = false;
-
- FW_CPrivBestFitSegment * segment = fSegments;
- while (segment != NULL && myBlock == false)
- {
- myBlock = segment->AddressInSegment(blk);
- segment = segment->fNextSegment;
- }
-
- return myBlock;
- }
- #endif
-
- #ifdef FW_DEBUG
- //----------------------------------------------------------------------------------------
- // FW_CBestFitHeap::Print
- //----------------------------------------------------------------------------------------
- #pragma segment HeapSeg
-
- void FW_CBestFitHeap::Print(char* msg) const
- {
- PLATFORM_PRINT_STRING("********** FW_CBestFitHeap **********\n");
- fFreeTree.PrintTree();
- PLATFORM_PRINT_STRING("\n");
- }
- #endif
-
- //----------------------------------------------------------------------------------------
- // FW_CBestFitHeap::AddToFreeBlocks
- //----------------------------------------------------------------------------------------
- #pragma segment HeapSeg
-
- void FW_CBestFitHeap::AddToFreeBlocks(FW_CPrivBestFitBlock* blk)
- {
- fFreeTree.AddBlock(blk);
- }
-
- //----------------------------------------------------------------------------------------
- // FW_CBestFitHeap::Coalesce: Coalesce blk with the previous block if both are free.
- //----------------------------------------------------------------------------------------
- #pragma segment HeapSeg
-
- FW_CPrivBestFitBlock* FW_CBestFitHeap::Coalesce(FW_CPrivBestFitBlock* blk)
- {
- FW_CPrivBestFitBlock * prevBlk = NULL;
-
- if (!blk->GetBusy() && !blk->GetPreviousBusy())
- {
- #ifdef FW_DEBUG
- if (blk->GetSize() < FW_CPrivBestFitBlock::kMinBlockSize)
- PLATFORM_DEBUGGER_STRING("FW_CBestFitHeap::Coalesce: corrupt heap!");
- #endif
-
- prevBlk = *(FW_CPrivBestFitBlock **) ((FW_BytePtr) blk - sizeof(FW_BlockSize));
- prevBlk->SetSize(prevBlk->GetSize() + blk->GetSize());
- prevBlk->StuffAddressAtEnd();
- }
-
- return prevBlk;
- }
-
- //----------------------------------------------------------------------------------------
- // FW_CBestFitHeap::CreateNewSegment
- //----------------------------------------------------------------------------------------
- #pragma segment HeapSeg
-
- void FW_CBestFitHeap::CreateNewSegment(unsigned long size)
- {
- #ifdef BUILD_WIN16
- PLATFORM_ASSERT(size < 64L * 1024L);
- #endif
-
- if (size & 0x01)
- size++;
-
- FW_CPrivBestFitSegment * segment
- = (FW_CPrivBestFitSegment *)this->AllocateRawMemory((FW_BlockSize) size);
-
- // The actual usable space is offset by the size of the fields
- // of a FW_CPrivBestFitSegment.
-
- segment->fSegmentSpace
- = (void *) ((FW_BytePtr) segment + FW_CPrivBestFitSegment::kSegmentPrefixSize);
- segment->fSegmentSize = size - FW_CPrivBestFitSegment::kSegmentPrefixSize;
-
- // Add the segment to the list of segments in this heap.
-
- segment->fNextSegment = fSegments;
- fSegments = segment;
-
- // Suffix the segment with a busy block of zero length so that the last free
- // block is not coalesced with a block past the fEnd of the segment.
-
- void * endOfSegment
- = (void *) ((FW_BytePtr) segment->fSegmentSpace + segment->fSegmentSize);
- FW_CPrivBestFitBlock *blk
- = new((void *) ((FW_BytePtr) endOfSegment - sizeof(FW_CPrivBestFitBlock)))
- FW_CPrivBestFitBlock(true, false, 0);
-
- // Create one free block out of this entire segment and Add it to the
- // free block list.
-
- blk = new(segment->fSegmentSpace)FW_CPrivBestFitBlock(false, true, segment->fSegmentSize - sizeof(FW_CPrivBestFitBlock));
-
- this->AddToFreeBlocks(blk);
- }
-
- //----------------------------------------------------------------------------------------
- // FW_CBestFitHeap::DeleteSegments
- //----------------------------------------------------------------------------------------
- #pragma segment HeapSeg
-
- void FW_CBestFitHeap::DeleteSegments()
- {
- FW_CPrivBestFitSegment * segment = fSegments;
- while (segment != NULL)
- {
- FW_CPrivBestFitSegment * nextSegment = segment->fNextSegment;
- this->FreeRawMemory(segment);
- segment = nextSegment;
- }
- }
-
- //----------------------------------------------------------------------------------------
- // FW_CBestFitHeap::GrowHeap
- //----------------------------------------------------------------------------------------
- #pragma segment HeapSeg
-
- void FW_CBestFitHeap::GrowHeap(unsigned long sizeIncrement)
- {
- #ifdef BUILD_WIN16
- // To avoid crossing 64K boundries on pointer arithmatic, the size of each segment
- // must be limited to 64K. So a single grow request may result in more than one
- // segment being allocated.
-
- const unsigned long kSegmentSizeLimit = 1024L * 62L; // Allow for 2K overhead
-
- while (sizeIncrement > 0)
- {
- unsigned long segmentSize = sizeIncrement;
- if (segmentSize > kSegmentSizeLimit)
- segmentSize = kSegmentSizeLimit;
- this->CreateNewSegment(segmentSize);
- sizeIncrement -= segmentSize;
- }
- #else
- this->CreateNewSegment(sizeIncrement);
- #endif
- }
-
- //----------------------------------------------------------------------------------------
- // FW_CBestFitHeap::RemoveFromFreeBlocks
- //----------------------------------------------------------------------------------------
- #pragma segment HeapSeg
-
- void FW_CBestFitHeap::RemoveFromFreeBlocks(FW_CPrivBestFitBlock* blk)
- {
- fFreeTree.RemoveBlock(blk);
- }
-
- //----------------------------------------------------------------------------------------
- // FW_CBestFitHeap::SearchFreeBlocks
- //----------------------------------------------------------------------------------------
- #pragma segment HeapSeg
-
- FW_CPrivBestFitBlock* FW_CBestFitHeap::SearchFreeBlocks(FW_BlockSize size)
- {
- //all blocks are of even length, so round up to fNext even number
-
- if (size & 1)
- size++;
-
- return fFreeTree.SearchForBlock(size, NULL, NULL);
- }
-
- #ifdef FW_DEBUG
- //----------------------------------------------------------------------------------------
- // FW_CBestFitHeap::CompilerCheck
- //----------------------------------------------------------------------------------------
- #pragma segment HeapSeg
-
- void FW_CBestFitHeap::CompilerCheck()
- {
- FW_CMemoryHeap::CompilerCheck();
-
- char buffer[sizeof(FW_CPrivBestFitBlock) + sizeof(void *)];
- FW_CPrivBestFitBlock &block = *((FW_CPrivBestFitBlock *) buffer);
-
- // Check to make sure the bit field setters and getters work.
-
- block.SetBlockType(3);
- block.SetBusy(true);
- block.SetPrevBusy(false);
- #ifndef BUILD_WIN16
- block.SetSize(100201);
- #endif
- block.SetMagicNumber(3);
-
- PLATFORM_ASSERT(block.GetBlockType() == 3);
- PLATFORM_ASSERT(block.GetBusy() == true);
- PLATFORM_ASSERT(block.GetPreviousBusy() == false);
- #ifndef BUILD_WIN16
- PLATFORM_ASSERT(block.GetSize() == 100201);
- #endif
- PLATFORM_ASSERT(block.GetMagicNumber() == 3);
-
- block.SetBlockType(2);
- block.SetBusy(false);
- block.SetPrevBusy(true);
- block.SetSize(150);
- block.SetMagicNumber(2);
-
- PLATFORM_ASSERT(block.GetBlockType() == 2);
- PLATFORM_ASSERT(block.GetBusy() == false);
- PLATFORM_ASSERT(block.GetPreviousBusy() == true);
- PLATFORM_ASSERT(block.GetSize() == 150);
- PLATFORM_ASSERT(block.GetMagicNumber() == 2);
- }
- #endif
-
-
- //========================================================================================
- // CLASS FW_CPrivFreeBlockTree
- //========================================================================================
-
- //----------------------------------------------------------------------------------------
- // FW_CPrivFreeBlockTree::FW_CPrivFreeBlockTree
- //----------------------------------------------------------------------------------------
- #pragma segment HeapSeg
-
- FW_CPrivFreeBlockTree::FW_CPrivFreeBlockTree() :
- fRoot(true, true, 0)
- {
- fRoot.SetRight(NULL);
- fRoot.SetLeft(NULL);
- }
-
- //----------------------------------------------------------------------------------------
- // FW_CPrivFreeBlockTree::FW_CPrivFreeBlockTree
- //----------------------------------------------------------------------------------------
- #pragma segment HeapSeg
-
- FW_CPrivFreeBlockTree::FW_CPrivFreeBlockTree(const FW_CPrivFreeBlockTree& blk) :
- fRoot(blk.fRoot)
- {
- }
-
- //----------------------------------------------------------------------------------------
- // FW_CPrivFreeBlockTree::operator=
- //----------------------------------------------------------------------------------------
- #pragma segment HeapSeg
-
- FW_CPrivFreeBlockTree& FW_CPrivFreeBlockTree::operator=(const FW_CPrivFreeBlockTree& blk)
- {
- fRoot = blk.fRoot;
- return (*this);
- }
-
- //----------------------------------------------------------------------------------------
- // FW_CPrivFreeBlockTree::AddBlock
- //----------------------------------------------------------------------------------------
- #pragma segment HeapSeg
-
- void FW_CPrivFreeBlockTree::AddBlock(FW_CPrivBestFitBlock* blk)
- {
- #ifdef FW_DEBUG
- this->CheckTree();
-
- #ifdef FW_INTENSE_DEBUG
- PLATFORM_PRINT_STRING("FW_CPrivFreeBlockTree::AddBlock Entry-------------------------------------\n");
- this->PrintTree();
- #endif
- #endif
-
- FW_CPrivBestFitBlock * parent;
-
- this->SearchForBlock(blk->GetSize(), blk, &parent);
-
- blk->SetRight(NULL);
- blk->SetLeft(NULL);
- blk->SetParent(parent);
-
- if (*blk > *parent)
- parent->SetRight(blk);
- else
- parent->SetLeft(blk);
-
- #ifdef FW_DEBUG
- this->CheckTree();
-
- #ifdef FW_INTENSE_DEBUG
- PLATFORM_PRINT_STRING("FW_CPrivFreeBlockTree::AddBlock Exit\n");
- this->PrintTree();
- PLATFORM_PRINT_STRING("\n");
- #endif
- #endif
- }
-
- #ifdef FW_DEBUG
- //----------------------------------------------------------------------------------------
- // FW_CPrivFreeBlockTree::CheckTree
- //----------------------------------------------------------------------------------------
- #pragma segment HeapSeg
-
- void FW_CPrivFreeBlockTree::CheckTree() const
- {
- this->CheckTreeHelper(&((FW_CPrivFreeBlockTree *)this)->fRoot);
- }
- #endif
-
- #ifdef FW_DEBUG
- //----------------------------------------------------------------------------------------
- // FW_CPrivFreeBlockTree::PrintTree
- //----------------------------------------------------------------------------------------
- #pragma segment HeapSeg
-
- void FW_CPrivFreeBlockTree::PrintTree() const
- {
- this->PrintTreeHelper(&((FW_CPrivFreeBlockTree *)this)->fRoot);
- }
- #endif
-
- //----------------------------------------------------------------------------------------
- // FW_CPrivFreeBlockTree::RemoveBlock
- //----------------------------------------------------------------------------------------
- #pragma segment HeapSeg
-
- void FW_CPrivFreeBlockTree::RemoveBlock(FW_CPrivBestFitBlock* blk)
- {
- #ifdef FW_DEBUG
- this->CheckTree();
-
- #ifdef FW_INTENSE_DEBUG
- PLATFORM_PRINT_STRING("FW_CPrivFreeBlockTree::RemoveBlock Entry----------------------------------\n");
- this->PrintTree();
- #endif
- #endif
-
- FW_CPrivBestFitBlock * spliceOutBlk;
-
- // Decide which block to splice out of the tree. Either the block being
- // removed, or its successor block in the tree.
-
- if (blk->GetLeft() == NULL || blk->GetRight() == NULL)
- spliceOutBlk = blk;
- else
- spliceOutBlk = this->GetSuccessorBlk(blk);
-
- // Splice the node out of the tree
-
- FW_CPrivBestFitBlock * tmp;
- FW_CPrivBestFitBlock * parent = spliceOutBlk->GetParent();
- if (spliceOutBlk->GetLeft())
- tmp = spliceOutBlk->GetLeft();
- else
- tmp = spliceOutBlk->GetRight();
- if (tmp)
- tmp->SetParent(parent);
- if (spliceOutBlk == parent->GetLeft())
- parent->SetLeft(tmp);
- else
- parent->SetRight(tmp);
-
- // If we spliced out the successor to blk above then we need to patch the successor
- // back in, in Place of blk.
-
- if (spliceOutBlk != blk)
- {
- FW_CPrivBestFitBlock * parent = blk->GetParent();
-
- // Fix up the parent's child pointer.
-
- if (parent->GetLeft() == blk)
- parent->SetLeft(spliceOutBlk);
- else
- parent->SetRight(spliceOutBlk);
-
- // Fix up the splice in block's pointers.
-
- spliceOutBlk->SetParent(parent);
- spliceOutBlk->SetLeft(blk->GetLeft());
- spliceOutBlk->SetRight(blk->GetRight());
-
- // Fix up the children of the splice in block's parent pointers.
-
- if (spliceOutBlk->GetLeft())
- (spliceOutBlk->GetLeft())->SetParent(spliceOutBlk);
- if (spliceOutBlk->GetRight())
- (spliceOutBlk->GetRight())->SetParent(spliceOutBlk);
- }
-
- #ifdef FW_DEBUG
- this->CheckTree();
-
- #ifdef FW_INTENSE_DEBUG
- PLATFORM_PRINT_STRING("FW_CPrivFreeBlockTree::RemoveBlock Exit\n");
- this->PrintTree();
- PLATFORM_PRINT_STRING("\n");
- #endif
- #endif
- }
-
- //----------------------------------------------------------------------------------------
- // FW_CPrivFreeBlockTree::SearchForBlock
- //----------------------------------------------------------------------------------------
- #pragma segment HeapSeg
-
- FW_CPrivBestFitBlock* FW_CPrivFreeBlockTree::SearchForBlock(FW_BlockSize size,
- void* blk,
- FW_CPrivBestFitBlock** insertLeaf)
- {
- #ifdef FW_DEBUG
- this->CheckTree();
-
- #ifdef FW_INTENSE_DEBUG
- char str[80];
- sprintf(str, "FW_CPrivFreeBlockTree::SearchForBlock(%d)---------------------------------\n", size);
- PLATFORM_PRINT_STRING(str);
- this->PrintTree();
- #endif
- #endif
-
- long minDiff = LONG_MAX;
- FW_CPrivBestFitBlock * minDiffBlock = NULL;
- FW_CPrivBestFitBlock * currentBlock = &fRoot;
- do
- {
- long diff = currentBlock->GetSize() - size;
- if (diff >= 0 && diff < minDiff)
- {
- minDiffBlock = currentBlock;
- minDiff = diff;
- }
-
- if (insertLeaf)
- *insertLeaf = currentBlock;
-
- // Determine which branch of the tree to continue down. Since duplicate keys are
- // difficult to deal with in binary trees, we use the address of blocks to break
- // ties, in the case of two blocks whose size are equal.
-
- if (size < currentBlock->GetSize())
- currentBlock = currentBlock->GetLeft();
- else if (size > currentBlock->GetSize())
- currentBlock = currentBlock->GetRight();
- else if (blk)
- {
- if (blk <= currentBlock)
- currentBlock = currentBlock->GetLeft();
- else
- currentBlock = currentBlock->GetRight();
- }
- else
- currentBlock = currentBlock->GetLeft();
-
- } while (currentBlock != NULL);
-
- return minDiffBlock;
- }
-
- //----------------------------------------------------------------------------------------
- // FW_CPrivFreeBlockTree::TreeInfo
- //----------------------------------------------------------------------------------------
- #pragma segment HeapSeg
-
- void FW_CPrivFreeBlockTree::TreeInfo(unsigned long& bytesFree,
- unsigned long& numberOfNodes) const
- {
- bytesFree = numberOfNodes = 0;
- this->TreeInfoHelper(&((FW_CPrivFreeBlockTree *)this)->fRoot, bytesFree, numberOfNodes);
-
- // Subtract one from the number of nodes to account for the header node which
- // is always empty.
-
- numberOfNodes--;
- }
-
- #ifdef FW_DEBUG
- //----------------------------------------------------------------------------------------
- // FW_CPrivFreeBlockTree::CheckTreeHelper
- //----------------------------------------------------------------------------------------
- #pragma segment HeapSeg
-
- void FW_CPrivFreeBlockTree::CheckTreeHelper(FW_CPrivBestFitBlock* blk) const
- {
- if (blk == NULL)
- return;
-
- this->CheckTreeHelper(blk->GetLeft());
-
- FW_CPrivBestFitBlock * parent = blk->GetParent();
- if (parent != NULL)
- {
- if (parent->GetRight() == blk)
- {
- if (*blk < *parent)
- {
- this->PrintTree();
- PLATFORM_DEBUGGER_STRING("FW_CPrivFreeBlockTree::CheckTreeHelper"
- "Corrupt free list tree: "
- "right child less than parent.");
- }
- }
- else if (parent->GetLeft() == blk)
- {
- if (*blk > *parent)
- {
- PLATFORM_DEBUGGER_STRING("FW_CPrivFreeBlockTree::CheckTreeHelper"
- "Corrupt free list tree: "
- "left child greater than parent.");
- }
- }
- else
- {
- PLATFORM_DEBUGGER_STRING("FW_CPrivFreeBlockTree::CheckTreeHelper"
- "Corrupt free list tree: "
- "I am not my parent's child.");
- }
- }
-
- // AMB_TODO: Recursing down the right side of the tree trashes the tree. This is
- // very strange, and as of yet I don't understand what the problem is. I
- // had suspected stack over-run.
- //this->CheckTreeHelper(blk->GetRight());
- }
- #endif
-
- //----------------------------------------------------------------------------------------
- // FW_CPrivFreeBlockTree::GetSuccessorBlk
- //----------------------------------------------------------------------------------------
- #pragma segment HeapSeg
-
- FW_CPrivBestFitBlock* FW_CPrivFreeBlockTree::GetSuccessorBlk(FW_CPrivBestFitBlock* blk)
- {
- if (blk->GetRight())
- {
- FW_CPrivBestFitBlock * current = blk->GetRight();
- while (current->GetLeft())
- current = current->GetLeft();
- return current;
- }
- else
- {
- FW_CPrivBestFitBlock * parent = blk->GetParent();
- FW_CPrivBestFitBlock * current = NULL;
- while (parent != NULL && current == parent->GetRight())
- {
- current = parent;
- parent = parent->GetParent();
- }
- return parent;
- }
- }
-
- #ifdef FW_DEBUG
- //----------------------------------------------------------------------------------------
- // FW_CPrivFreeBlockTree::PrintTreeHelper
- //----------------------------------------------------------------------------------------
- #pragma segment HeapSeg
-
- void FW_CPrivFreeBlockTree::PrintTreeHelper(FW_CPrivBestFitBlock* blk,
- int level) const
- {
- for (int i = 0; i < level; i++)
- PLATFORM_PRINT_STRING("\t");
-
- if (blk == NULL)
- {
- PLATFORM_PRINT_STRING("NULL\n");
- return;
- }
-
- char str[80];
- //sprintf(str, "Block=%lx fSize=%ld\n", blk, blk->GetSize());
- PLATFORM_PRINT_STRING(str);
-
- this->PrintTreeHelper(blk->GetLeft(), level + 1);
- this->PrintTreeHelper(blk->GetRight(), level + 1);
- }
- #endif
-
- //----------------------------------------------------------------------------------------
- // FW_CPrivFreeBlockTree::TreeInfoHelper
- //----------------------------------------------------------------------------------------
- #pragma segment HeapSeg
-
- void FW_CPrivFreeBlockTree::TreeInfoHelper(FW_CPrivBestFitBlock* blk,
- unsigned long& bytesFree,
- unsigned long& numberOfNodes) const
- {
- if (blk == NULL)
- return;
-
- this->TreeInfoHelper(blk->GetLeft(), bytesFree, numberOfNodes);
-
- numberOfNodes++;
- bytesFree += blk->GetSize();
-
- this->TreeInfoHelper(blk->GetRight(), bytesFree, numberOfNodes);
- }
-