// =================================================================== // $Id: $ // // allocgo2.cpp // // REPLACEMENT_STRING // // Copyright by Vlastimil Havran, 2006 - email to "vhavran AT seznam.cz" // Initial coding by Vlastimil Havran, 2003 // standard headers #include #include // GOLEM headers #include "allocgo2.h" namespace GtpVisibilityPreprocessor { using namespace std; // ************* size-equal item allocator with alligning in the cache **** CAllocContinuous::CAllocContinuous(int sizeOfEntryV, int numEntriesInBlockV, int maxItemsForAllocation, int allignEntrySizeV, int allignBlockSizeV) { if ((sizeOfEntryV < ((int)sizeof(void*))) || (numEntriesInBlockV < 2)) { cerr << "Error: The Spc size-equal allocator initialization wrong.\n"; abort(); } // input variables sizeOfEntry = sizeOfEntryV; granularity = numEntriesInBlockV; maxItemsAtOnce = maxItemsForAllocation; // Increase the allignment to be at least of entry size int ta = allignEntrySizeV; while (sizeOfEntryV > allignEntrySizeV) { allignEntrySizeV += ta; } // while // Increase the allignment of the block to be at least the size of one entry ta = allignBlockSizeV; while (allignEntrySizeV > allignBlockSizeV) { allignBlockSizeV += ta; } // while // The allignment of entry allignEntrySize = allignEntrySizeV; // The allingment of block allignBlockSize = allignBlockSizeV; // Compute the memory needed for one block memoryForOneBlock = (sizeOfEntry * (granularity + 2*maxItemsAtOnce))/allignEntrySize; memoryForOneBlock = (memoryForOneBlock + 1) * allignEntrySize; // Now we want to make sure for the big allignment memoryForOneBlock /= allignBlockSize; memoryForOneBlock = (memoryForOneBlock+2) * allignBlockSize; // status variables initMemBlock = 0; mstor = &initMemBlock; // Release the memory and prepare the variables ReleaseMemory(); #if 0 cout << "CAllocContinuous: item size " << sz << " alligned to size " << size <<" granularity " << gran << "\n"; cout << " BigAlignment=" << bigAllignment << "\n"; #endif } void CAllocContinuous::ReleaseMemory() { // delete all allocated memory blocks void *bk = mstor; void *p; while (bk != &initMemBlock) { p = *(void**)bk; //cout << "Release " << " p = " << (void*)bk << endl; delete [] (char*)bk; bk = p; } // while remainItems = 0; initMemBlock = 0; mstor = &initMemBlock; bytesAllocated = 0; lastEntryInBlockAllocated = 0; nextAllocp = 0; lastValidAddress = 0; } void* CAllocContinuous::AllocNewBlock() { int allocHere = 0; allocHere++; nextAllocp = new char[memoryForOneBlock]; // append to chain if (nextAllocp == NULL) { cerr << "Memory exhausted in CAllocContinuous\n"; abort(); } #ifdef _DEBUG memset((void*)nextAllocp, 0xFF, memoryForOneBlock); #endif // Compute the last valid address to be used in the current block lastValidAddress = (void*) (nextAllocp + memoryForOneBlock - 1); //cout << "ALloc " << allocHere << " p = " << (void*)nextAllocp << endl; // Link the block to the chain of block ! *((void**)nextAllocp) = (void*)mstor; // link the previous chain mstor = (void**)nextAllocp; // link the currently allocated block // set chain of blocks .. allign the starting address nextAllocp = (char*)(allignBlockSize * (((unsigned long)nextAllocp + sizeof(void*) + allignBlockSize - 1) / allignBlockSize)); #ifdef _DEBUG if ((unsigned long)mstor > (unsigned long)nextAllocp) { cerr << "Allignment of the block is wrong" << endl; abort(); } #endif // Compute Allignment unsigned long allignmentTotal = 2 * maxItemsAtOnce * sizeOfEntry; char *maxAddressInBlock = ((char*)mstor + memoryForOneBlock); // We have to put there the place for the last entry maxAddressInBlock -= allignmentTotal; // The maximum number of single items to be allocated, which then allows // also to allocate a last entry by a special routine remainItems = (unsigned long)( maxAddressInBlock - ((char*)nextAllocp) ); remainItems /= sizeOfEntry; remainItems -= 2 * maxItemsAtOnce; #ifdef _DEBUG if (remainItems<0) { cerr << "CAllocContinuous::Alloc Error\n"; abort(); } #endif // Update the statistics, the total number of bytes allocated // by the instance of this allocator bytesAllocated += memoryForOneBlock; //cout << "The Alloc called\n" << flush; // We will be left with the last entry to allocate lastEntryInBlockAllocated = false; // Return the address to be allocated as the next one return (void*)nextAllocp; } // alloc the memory of size "sizeItem*entriesCnt" alligned in the memory // started in the new block void* CAllocContinuous::NewEntryInNewBlock(int entriesCnt) { // We require first to allocate a new block AllocNewBlock(); return New(entriesCnt); } void* CAllocContinuous::New(int entriesCnt) { // void *m; // is unreferenced assert(entriesCnt > 0); assert(entriesCnt <= maxItemsAtOnce); if (remainItems < entriesCnt) { return (void*)0; // not enough space left } unsigned long tmp = (unsigned long)nextAllocp; if ((tmp % allignEntrySize) == 0) { remainItems -= entriesCnt; nextAllocp = (char*)(tmp + entriesCnt * sizeOfEntry); return (void*)tmp; } // We have to allign the address to the allignEntrySize tmp /= allignEntrySize; tmp = (tmp+1) * allignEntrySize; remainItems -= (tmp - (unsigned long)nextAllocp) / entriesCnt; nextAllocp = (char*)(tmp + entriesCnt * sizeOfEntry); assert(nextAllocp < lastValidAddress); return (void*)tmp; } // alloc the memory of size "sizeItem*entriesCnt" alligned in the memory // it can be in the current block, which is definitely the last one in // the current block. This should be used only if function New() above // returns 0. void* CAllocContinuous::NewLastEntry(int entriesCnt) { if (!lastEntryInBlockAllocated) { // if the last entry in the current block was not yet allocated void *tmp = nextAllocp; #ifdef _DEBUG // check if we do not go behind the block if ( (unsigned long)tmp + sizeOfEntry * entriesCnt > (unsigned long)lastValidAddress) { cerr << "Problem with the allocator, using the memory" << endl; abort(); } #endif // _DEBUG lastEntryInBlockAllocated = true; // do not allocate again return nextAllocp; } // if the last entry return (void*)0; // the entry was already allocated } void CAllocContinuous::Report() { cout << "Unused entries in the current block = " << remainItems << "\n"; cout << "Total consumed memory = " << bytesAllocated << "\n"; } }