summaryrefslogtreecommitdiff
path: root/utils/Allocator.cc
blob: d1bdf8da4af3c36731be7113e4481db14e21acd7 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
/*
 *	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 <stdlib.h>
#include <unistd.h>
#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 <OBJECT>} 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 */