home *** CD-ROM | disk | FTP | other *** search
Text File | 1996-09-17 | 5.8 KB | 200 lines | [TEXT/MPS ] |
- //========================================================================================
- //
- // File: FWFixMem.cpp
- // Release Version: $ ODF 2 $
- //
- // Copyright: (c) 1993 - 1996 by Apple Computer, Inc., all rights reserved.
- //
- //========================================================================================
-
- #include "FWFound.hpp"
-
- #ifndef FWMEMMGR_H
- #include "FWMemMgr.h"
- #endif
-
- #ifndef FWFIXMEM_H
- #include "FWFixMem.h"
- #endif
-
- #ifndef FWDEBUG_H
- #include "FWDebug.h"
- #endif
-
- #ifdef FW_DEBUG
- #include <stdio.h>
- #endif
-
- #ifdef FW_BUILD_MAC
- #pragma segment FWMemory
- #endif
-
- //========================================================================================
- // STRUCT FW_SPrivFixedNode
- //========================================================================================
-
- struct FW_SPrivFixedNode
- {
- FW_SPrivFixedNode* fNext;
-
- static FW_SPrivFixedNode* FromMemBlock(void* memblock);
- };
-
- //----------------------------------------------------------------------------------------
- // FW_SPrivFixedNode::FromMemBlock
- //----------------------------------------------------------------------------------------
-
- FW_SPrivFixedNode* FW_SPrivFixedNode::FromMemBlock(void* memBlock)
- {
- FW_SPrivFixedNode* node = (FW_SPrivFixedNode*) memBlock;
- return node;
- }
-
- //========================================================================================
- // STRUCT FW_SPrivFixedBlock
- //========================================================================================
-
- struct FW_SPrivFixedBlock
- {
- FW_SPrivFixedBlock* fNext;
-
- static FW_SPrivFixedBlock* Allocate(short nNodeSize, short nNodes,
- FW_SPrivFixedNode*& firstNode, FW_SPrivFixedNode*& lastNode);
- static void Free(FW_SPrivFixedBlock* block);
- };
-
- //----------------------------------------------------------------------------------------
- // FW_SPrivFixedBlock::Allocate
- //----------------------------------------------------------------------------------------
-
- FW_SPrivFixedBlock* FW_SPrivFixedBlock::Allocate(short nNodeSize, short nNodes,
- FW_SPrivFixedNode*& firstNode, FW_SPrivFixedNode*& lastNode)
- {
- FW_ASSERT(nNodeSize >= sizeof(FW_SPrivFixedNode));
-
- // Allocate the large memory block
- FW_SPrivFixedBlock* block = (FW_SPrivFixedBlock*)
- FW_CMemoryManager::AllocateBlock((unsigned long) nNodeSize * nNodes + sizeof(FW_SPrivFixedBlock));
- void* blockData = block + 1;
-
- // Set first and last pointers
- firstNode = (FW_SPrivFixedNode*) blockData;
- lastNode = (FW_SPrivFixedNode*) (((char*) blockData) + nNodeSize * (nNodes - 1));
-
- // Slice and dice the block
- lastNode->fNext = NULL;
- FW_SPrivFixedNode* node = (FW_SPrivFixedNode*) blockData;
- for (short n = 0; n < nNodes - 1; ++ n)
- {
- FW_SPrivFixedNode* next = (FW_SPrivFixedNode*) (((char*) node) + nNodeSize);
- node->fNext = next;
- node = next;
- }
- FW_ASSERT(node == lastNode);
-
- // Return the whole block
- return block;
- }
-
- //----------------------------------------------------------------------------------------
- // FW_SPrivFixedBlock::Free
- //----------------------------------------------------------------------------------------
-
- void FW_SPrivFixedBlock::Free(FW_SPrivFixedBlock* block)
- {
- FW_CMemoryManager::FreeBlock(block);
- }
-
- //========================================================================================
- // CLASS FW_CFixedAllocator
- //========================================================================================
-
- const int kNodesPerBlock = 100;
-
- //----------------------------------------------------------------------------------------
- // FW_CFixedAllocator::FW_CFixedAllocator
- //----------------------------------------------------------------------------------------
-
- FW_CFixedAllocator::FW_CFixedAllocator(short allocSize
- #ifdef FW_DEBUG
- , const char* name
- #endif
- ) :
- fAllocCount(0),
- fAllocSize((allocSize + 3) & ~3), // Round the size up to a multiple of 4 bytes
- fFreeList(NULL),
- fBlockList(NULL)
- {
- #ifdef FW_DEBUG
- fDebugName = name;
- #endif
- }
-
- //----------------------------------------------------------------------------------------
- // FW_CFixedAllocator::~FW_CFixedAllocator
- //----------------------------------------------------------------------------------------
-
- FW_CFixedAllocator::~FW_CFixedAllocator()
- {
- #ifdef FW_DEBUG
- if (fAllocCount != 0 || fFreeList != NULL || fBlockList != NULL)
- {
- char s[255];
- sprintf(s, "%s %s %s", "FW_CFixedAllocator: An object of type", fDebugName, "has not been deleted properly.");
- FW_DEBUG_MESSAGE(s);
- }
- #endif
- }
-
- //----------------------------------------------------------------------------------------
- // FW_CFixedAllocator::Allocate
- //----------------------------------------------------------------------------------------
-
- void* FW_CFixedAllocator::Allocate()
- {
- // Make sure there is something on our free list
- if (fFreeList == NULL)
- {
- FW_SPrivFixedNode *firstNode, *lastNode;
- FW_SPrivFixedBlock *newBlock =
- FW_SPrivFixedBlock::Allocate(fAllocSize, kNodesPerBlock, firstNode, lastNode);
-
- lastNode->fNext = fFreeList;
- fFreeList = firstNode;
-
- newBlock->fNext = fBlockList;
- fBlockList = newBlock;
- }
-
- // Take the first node from the free list
- void* newNode = fFreeList;
- fFreeList = fFreeList->fNext;
- ++ fAllocCount;
- return newNode;
- }
-
- //----------------------------------------------------------------------------------------
- // FW_CFixedAllocator::Free
- //----------------------------------------------------------------------------------------
-
- void FW_CFixedAllocator::Free(void* block)
- {
- // Return the block to the free node list
- FW_SPrivFixedNode* node = FW_SPrivFixedNode::FromMemBlock(block);
- node->fNext = fFreeList;
- fFreeList = node;
-
- // If no more nodes, free the whole list
- if (-- fAllocCount == 0)
- {
- while (fBlockList != NULL)
- {
- FW_SPrivFixedBlock* next = fBlockList->fNext;
- FW_SPrivFixedBlock::Free(fBlockList);
- fBlockList = next;
- }
-
- fFreeList = NULL;
- }
- }
-