//+------------------------------------------------------------------------- // // Microsoft Windows // Copyright (C) Microsoft Corporation, 1996 - 1999. // // File: tmem.cxx // // Contents: tmem - test mem allocators for big tables. // //-------------------------------------------------------------------------- #include "pch.cxx" #pragma hdrstop DECLARE_INFOLEVEL(tb) #include "tblalloc.hxx" BYTE MemPool[4096]; //BYTE* PoolPtrs[409]; //ULONG PoolOffs[409]; BOOL fInMemPool = TRUE; // // ReportHeap - report heap blocks // void ReportHeap( void* pBlock, USHORT cbSize, USHORT fFree ) { BYTE* pbBlock = (BYTE*) pBlock; printf("%08x %d%s\n", pbBlock, cbSize, fFree? " FREE": ""); if (fInMemPool && (pbBlock < &MemPool[0] || pbBlock + cbSize > &MemPool[ sizeof MemPool ])) { printf("\007***\tpBlock outside mem pool\t***\007"); } } // // FreeBlocks -- free some of the allocated blocks // void FreeBlocks( BYTE* apbPtrs[], unsigned cPtrs, int fVerbose, CWindowDataAllocator& Alloc ) { unsigned i; // Free every third allocated block for (i = 2; i < cPtrs; i += 3) { if (apbPtrs[i]) { Alloc.Free((void*)apbPtrs[i]); apbPtrs[i] = 0; } } if (fVerbose) { printf("\nAfter freeing every third allocation\n"); Alloc.WalkHeap(ReportHeap); } // Free every other allocated block, will cause some coalescing for (i = 0; i < cPtrs; i += 2) { if (apbPtrs[i]) { Alloc.Free((void*)apbPtrs[i]); apbPtrs[i] = 0; } } if (fVerbose) { printf("\nAfter freeing every other allocation\n"); Alloc.WalkHeap(ReportHeap); } // Finally, Free every fourth allocated block, will cause more coalescing for (i = 3; i < cPtrs; i += 4) { if (apbPtrs[i]) { Alloc.Free((void*)apbPtrs[i]); apbPtrs[i] = 0; } } if (fVerbose) { printf("\nAfter freeing every other allocation\n"); Alloc.WalkHeap(ReportHeap); } } __cdecl main(int argc, char** argv) { BYTE* pMem = MemPool; int fVerbose = 0; unsigned i; for (i=1; i<(unsigned)argc; i++) { if (argv[i][0] == '-' && tolower(argv[i][1]) == 'v') fVerbose++; else { printf("Usage: %s [-v]\n", argv[0]); } } // Test the simple allocator with forward allocation. memset(pMem, 0xD5, sizeof MemPool); CVarBufferAllocator Alloc1(pMem, sizeof MemPool); BYTE* pbuf; BOOL fBreak = FALSE; for (i=0; i<0xFFFFFFFF && !fBreak; i++) { TRY { pbuf = 0; pbuf = (BYTE *)Alloc1.Allocate(10); } CATCH (CException, e) { if (e.GetErrorCode() == E_OUTOFMEMORY) fBreak = TRUE; else RETHROW(); } END_CATCH if (pbuf) memset(pbuf, '0' + i%10, 10); } Win4Assert(i == sizeof MemPool/10); for (i=0; i<sizeof MemPool - (sizeof MemPool % 10); i++) { Win4Assert(MemPool[i] == ((i/10) % 10 + '0')); } #if 0 // Test the simple allocator with top-down allocation. memset(pMem, 0xD5, sizeof MemPool); CVarBufferAllocator Alloc2(pMem, sizeof MemPool, TRUE); for (i=0; pbuf = (BYTE *)Alloc2.Allocate(10); i++) { memset(pbuf, '0' + i%10, 10); } Win4Assert(i == sizeof MemPool/10); for (i=0; i<sizeof MemPool; i++) { if (i < (sizeof MemPool % 10)) { Win4Assert(MemPool[i] == 0xD5); } else { Win4Assert(MemPool[i] == ((((sizeof MemPool - 1) - i)/10) % 10 + '0')); } } #endif //0 // Test the heap allocator memset(pMem, 0, sizeof MemPool); BYTE **paPoolPtrs = (BYTE**)&MemPool; unsigned cPoolPtrs = sizeof MemPool / sizeof (BYTE *); CWindowDataAllocator Alloc3; fInMemPool = FALSE; for (i=0; pbuf = (BYTE *)Alloc3.Allocate(10); i++) { if (i == cPoolPtrs) break; paPoolPtrs[i] = pbuf; memset(pbuf, '0' + i%10, 10); } Win4Assert(i == cPoolPtrs); for (i=0; i<sizeof MemPool; i++) { Win4Assert(paPoolPtrs[i/10][i%10] == ((i/10) % 10 + '0')); } if (fVerbose) { printf("Grow forward allocation\n"); Alloc3.WalkHeap(ReportHeap); } FreeBlocks(paPoolPtrs, cPoolPtrs, fVerbose, Alloc3); // Test the fixed/variable allocator memset(pMem, 0, sizeof MemPool); Win4Assert(sizeof (BYTE*) == sizeof (ULONG)); paPoolPtrs = (BYTE **)&MemPool; cPoolPtrs = (sizeof MemPool / sizeof (BYTE *)) / 2; ULONG *paPoolOffs = (ULONG *)&paPoolPtrs[cPoolPtrs]; memset(paPoolPtrs, 0, sizeof (BYTE *) * cPoolPtrs); memset(paPoolOffs, 0, sizeof (BYTE *) * cPoolPtrs); CFixedVarAllocator Alloc4(TRUE, TRUE, 10); // for (i=0; i<sizeof MemPool; i++) { // Alloc4.SetLimit(i); // Win4Assert(Alloc4.Limit() == i); // } // // Alloc4.SetLimit(1000); for (i=0; (pbuf = (BYTE *)Alloc4.Allocate(10)) && i < cPoolPtrs; i++) { memset(pbuf, '0' + i%10, 10); paPoolOffs[i] = Alloc4.PointerToOffset(pbuf); pbuf = (BYTE*)Alloc4.AllocFixed(); memset(pbuf, '9' - i%10, 10); } Win4Assert(i == cPoolPtrs); CWindowDataAllocator* pVAlloc = Alloc4.VarAllocator(); if (fVerbose && pVAlloc) { printf("\nFixed/Var allocation\n"); pVAlloc->WalkHeap(ReportHeap); } if (pVAlloc) { for (i=0; i<cPoolPtrs; i++) { if (paPoolOffs[i]) { paPoolPtrs[i] = (BYTE*)Alloc4.OffsetToPointer(paPoolOffs[i]); } } FreeBlocks(paPoolPtrs, cPoolPtrs, fVerbose, *pVAlloc); } // Test the fixed/variable allocator memset(pMem, 0, sizeof MemPool); Win4Assert(sizeof (BYTE*) == sizeof (ULONG)); paPoolPtrs = (BYTE **)&MemPool; cPoolPtrs = (sizeof MemPool / sizeof (BYTE *)); memset(paPoolPtrs, 0, sizeof (BYTE *) * cPoolPtrs); CFixedVarAllocator Alloc5(TRUE, TRUE, 0x28); for (i=0; (pbuf = (BYTE *)Alloc5.AllocFixed()) && i < cPoolPtrs; i++) { memset(pbuf, '0' + i%10, 0x28); } Win4Assert(i == cPoolPtrs); for (i=0; i<cPoolPtrs; i++) { if (paPoolOffs[i]) { paPoolPtrs[i] = (BYTE*)Alloc5.OffsetToPointer(paPoolOffs[i]); } } return 0; }