Made on Kubuntu
00001 // Copyright (C) 2009-2010 Ferdinand Majerech 00002 // This file is part of MiniINI 00003 // For conditions of distribution and use, see copyright notice in LICENSE.txt 00004 00005 #include "allocator.h" 00006 #include <cstring> 00007 #include <cassert> 00008 00009 namespace miniini_private 00010 { 00011 00012 Allocator::Allocator(const ui size, const ui blocks) 00013 :NumBlocks(blocks) 00014 ,CurrentBlock(0) 00015 ,BlockMinSize(size / NumBlocks + 1) 00016 ,Blocks(new Block * [NumBlocks]) 00017 { 00018 //Allocate enough blocks to have size of space 00019 for(ui block = 0; block < NumBlocks; ++block) 00020 { 00021 Blocks[block] = new Block(BlockMinSize); 00022 } 00023 } 00024 00025 void Allocator::Trim() 00026 { 00027 //Since current block can only be incremented, 00028 //if the current block is not the last block, there are 00029 //some blocks left since the construction that we can delete. 00030 if(CurrentBlock < (NumBlocks - 1)) 00031 { 00032 for(ui block = CurrentBlock + 1; block < NumBlocks; ++block) 00033 { 00034 delete Blocks[block]; 00035 } 00036 //Reallocate Blocks to only hold pointers to used blocks. 00037 NumBlocks = CurrentBlock + 1; 00038 Block * * tempblocks = new Block * [NumBlocks]; 00039 memcpy(tempblocks, Blocks, NumBlocks * sizeof(Block *)); 00040 delete [] Blocks; 00041 Blocks = tempblocks; 00042 } 00043 } 00044 00045 void Allocator::DeleteSpace(c * const ptr) 00046 { 00047 assert(ptr); 00048 Block * block; 00049 //Find which block does ptr point to 00050 for(ui blockidx = 0; blockidx < NumBlocks; ++blockidx) 00051 { 00052 block = Blocks[blockidx]; 00053 //Ptr is inside this block 00054 if(ptr >= block->Data && ptr < (block->Data + block->Allocated)) 00055 { 00056 ++block->PtrsDeleted; 00057 //If as many pointers as given were deleted, we can delete this block 00058 const bool readytodelete = block->PtrsDeleted == block->PtrsGiven ? 00059 true : false; 00060 if(readytodelete) 00061 { 00062 //This is the current block: no need to delete it as it's not yet full 00063 if(blockidx == CurrentBlock) 00064 { 00065 return; 00066 } 00067 NumBlocks -= 1; 00068 //This is the only block left, so delete it and replace by an empty block. 00069 if(!NumBlocks) 00070 { 00071 delete block; 00072 Blocks[0] = new Block(BlockMinSize); 00073 NumBlocks = 1; 00074 return; 00075 } 00076 //Reallocate Blocks to smaller size. 00077 Block * * tempblocks = new Block * [NumBlocks]; 00078 memcpy(tempblocks, Blocks, blockidx * sizeof(Block *)); 00079 memcpy(tempblocks + blockidx, Blocks + blockidx + 1, 00080 (NumBlocks - blockidx) * sizeof(Block *)); 00081 delete block; 00082 delete [] Blocks; 00083 Blocks = tempblocks; 00084 } 00085 return; 00086 } 00087 } 00088 //If we get here, ptr does not point to any block which is an error 00089 assert(false); 00090 } 00091 00092 c * Allocator::NewSpace(const ui size) 00093 { 00094 Block * block = Blocks[CurrentBlock]; 00095 //Not enough space in this block. Add new block and allocate from there 00096 if((block->Allocated - block->Used) < size) 00097 { 00098 NewBlock(size); 00099 return NewSpace(size); 00100 } 00101 //Pointer to allocated space 00102 c * out = block->Data + block->Used; 00103 //Update block data 00104 block->Used += size; 00105 ++block->PtrsGiven; 00106 return out; 00107 } 00108 00109 Allocator::~Allocator() 00110 { 00111 //Delete all blocks 00112 for(ui block = 0; block < NumBlocks; ++block) 00113 { 00114 delete Blocks[block]; 00115 } 00116 delete [] Blocks; 00117 } 00118 00119 //PROBABLY ERROR HERE 00120 void Allocator::NewBlock(const ui minsize) 00121 { 00122 ++CurrentBlock; 00123 //Size of the new block is max(minsize, BlockMinSize) 00124 if(minsize > BlockMinSize) 00125 { 00126 BlockMinSize = minsize; 00127 } 00128 //Not the last block, we just need to move to the next one 00129 if(CurrentBlock < NumBlocks) 00130 { 00131 //If the block is not large enough, enlarge it 00132 if(Blocks[CurrentBlock]->GetFreeSpace() < minsize) 00133 { 00134 Blocks[CurrentBlock]->Reallocate(BlockMinSize); 00135 } 00136 } 00137 //We need to allocate a new block (and reallocate the Blocks ptr array) 00138 else 00139 { 00140 Block * * tempblocks = new Block * [NumBlocks + 1]; 00141 memcpy(tempblocks, Blocks, NumBlocks * sizeof(Block *)); 00142 tempblocks[NumBlocks] = new Block(BlockMinSize); 00143 delete [] Blocks; 00144 Blocks = tempblocks; 00145 ++NumBlocks; 00146 } 00147 } 00148 00149 }