/* * CENA C++ Utilities * * by Stephane Chatty * * Copyright 1992 * Centre d'Etudes de la Navigation Aerienne (CENA) * * Memory allocation (original C version by Michel Beaudouin-Lafon) * * $Id$ * $CurLog$ */ #include "Allocator.h" #include #include #include "Signal.h" /*?class CcuAllocator The memory manager is implemented through a C++ class called \typ{CcuAllocator}. Each instance of this class is a memory allocator, which delivers memory blocks of a given size. Allocators work as follow: each allocator obtains pages of memory through \fun{malloc}. It then splits that memory in blocks in order to deliver them. When a block is freed, it is stored in a list of free blocks so as to be reused. In the current implementation, memory pages are never released. ?*/ #define CHUNKSIZE 1024 /* * Supposing that memory blocks must always be aligned on * word boundaries, we allocate chunks as arrays of words, * and express all sizes in words. * */ #ifndef WORD_TYPE #define WORD_TYPE int #endif typedef WORD_TYPE Word; inline unsigned int SizeInWords (unsigned int size) { return (size + sizeof (Word) -1) / sizeof (Word); } /*? This function is called when there is no more memory. It issues an error message to the standard error output, then calls \fun{exit}. ?*/ void CcuAllocator :: MemoryOverflow () { static char msg [] = "Memory overflow. Bye ...\n"; write (2, msg, sizeof (msg)); exit (99); } /*? Constructor for \typ{CcuAllocator}s. It initializes an allocator for structures of size \var{size}. For implementation reasons, allocated blocks will be at least the size of a pointer. ?*/ CcuAllocator :: CcuAllocator (unsigned int size) : BlockSize (SizeInWords (size)), ChunkSize (SizeInWords (CHUNKSIZE)), FreeList (0), AllocEnd (0), AllocNext (0) { /* if blocks are too small to hold a pointer, enlarge them */ unsigned int ptr_size = SizeInWords (sizeof (Word*)); if (BlockSize < ptr_size) BlockSize = ptr_size; /* if chunks are too small to hold two blocks, enlarge them */ if (ChunkSize < 2*BlockSize) ChunkSize = 2*BlockSize; } /*?nodoc?*/ CcuAllocator :: ~CcuAllocator () { } /*? Allocate a block of memory with an \typ{CcuAllocator}. This function returns the address of the allocated block, or 0 if the allocation failed for some reason. The allocated block is aligned on a word boundary, and it is {\em not} filled with zeroes. ?*/ void* CcuAllocator :: Alloc () { #ifdef MEMORY_DEBUG CcuSignalBlocker b (AllSigs); void* w = new Word [BlockSize]; return w; #else register Word* block; /* give memory from the free-list */ if (FreeList) { block = (Word*) FreeList; FreeList = ((Word**) FreeList)[0]; /* or from fresh memory */ } else { block = (Word*) AllocNext; AllocNext = ((Word*) AllocNext) + BlockSize; if (AllocNext > AllocEnd) { /* here we have to get new chunk */ CcuSignalBlocker b (AllSigs); block = new Word [ChunkSize]; if (block == 0) MemoryOverflow (); /* we suppose we can put at least 2 objects in a chunk */ AllocNext = block + BlockSize; AllocEnd = block + ChunkSize; } } return block; #endif } /*? Free the memory allocated at \var{p} by this \typ{CcuAllocator}. No check is performed, and you should take care that \var{p} was allocated by this allocator. ?*/ void CcuAllocator :: Free (void* p) { #ifdef MEMORY_DEBUG CcuSignalBlocker b (AllSigs); delete [] ((Word*) p); #else /* Prepend the block to the list of free blocks */ ((Word**) p)[0] = (Word*) FreeList; FreeList = p; #endif } #ifdef DOC /*?class CcuAllocatorOf The template class \typ{CcuAllocatorOf } is a generic version of the class \typ{CcuAllocator} that is designed to allocate memory for objects of the class \typ{OBJECT}. The following functions are redefined: ?*/ /*? Build an allocator that will allow blocks with the same size as objects of class \typ{OBJECT}. ?*/ CcuAllocatorOf :: CcuAllocatorOf () { } /*? This function is the same as \typ{CcuAllocator}::\fun{Alloc} except that it returns \typ{OBJECT*} instead of \typ{void*}. ?*/ OBJECT* CcuAllocatorOf :: Alloc () { } #endif /* DOC */