ANIMA  4.0
animaBlock.h
Go to the documentation of this file.
1 /* block.h */
2 /*
3  Template classes Block and DBlock
4  Implement adding and deleting items of the same type in blocks.
5 
6  If there there are many items then using Block or DBlock
7  is more efficient than using 'new' and 'delete' both in terms
8  of memory and time since
9  (1) On some systems there is some minimum amount of memory
10  that 'new' can allocate (e.g., 64), so if items are
11  small that a lot of memory is wasted.
12  (2) 'new' and 'delete' are designed for items of varying size.
13  If all items has the same size, then an algorithm for
14  adding and deleting can be made more efficient.
15  (3) All Block and DBlock functions are inline, so there are
16  no extra function calls.
17 
18  Differences between Block and DBlock:
19  (1) DBlock allows both adding and deleting items,
20  whereas Block allows only adding items.
21  (2) Block has an additional operation of scanning
22  items added so far (in the order in which they were added).
23  (3) Block allows to allocate several consecutive
24  items at a time, whereas DBlock can add only a single item.
25 
26  Note that no constructors or destructors are called for items.
27 
28  Example usage for items of type 'MyType':
29 
31  #include "block.h"
32  #define BLOCK_SIZE 1024
33  typedef struct { int a, b; } MyType;
34  MyType *ptr, *array[10000];
35 
36  ...
37 
38  Block<MyType> *block = new Block<MyType>(BLOCK_SIZE);
39 
40  // adding items
41  for (int i=0; i<sizeof(array); i++)
42  {
43  ptr = block -> New();
44  ptr -> a = ptr -> b = rand();
45  }
46 
47  // reading items
48  for (ptr=block->ScanFirst(); ptr; ptr=block->ScanNext())
49  {
50  printf("%d %d\n", ptr->a, ptr->b);
51  }
52 
53  delete block;
54 
55  ...
56 
57  DBlock<MyType> *dblock = new DBlock<MyType>(BLOCK_SIZE);
58 
59  // adding items
60  for (int i=0; i<sizeof(array); i++)
61  {
62  array[i] = dblock -> New();
63  }
64 
65  // deleting items
66  for (int i=0; i<sizeof(array); i+=2)
67  {
68  dblock -> Delete(array[i]);
69  }
70 
71  // adding items
72  for (int i=0; i<sizeof(array); i++)
73  {
74  array[i] = dblock -> New();
75  }
76 
77  delete dblock;
78 
80 
81  Note that DBlock deletes items by marking them as
82  empty (i.e., by adding them to the list of free items),
83  so that this memory could be used for subsequently
84  added items. Thus, at each moment the memory allocated
85  is determined by the maximum number of items allocated
86  simultaneously at earlier moments. All memory is
87  deallocated only when the destructor is called.
88 */
89 
90 #pragma once
91 
92 #include <stdlib.h>
93 
94 /***********************************************************************/
95 /***********************************************************************/
96 /***********************************************************************/
97 
98 
99 namespace anima {
100 
101 template <class Type> class Block
102 {
103 public:
104  /* Constructor. Arguments are the block size and
105  (optionally) the pointer to the function which
106  will be called if allocation failed; the message
107  passed to this function is "Not enough memory!" */
108  Block(int size, void (*err_function)(char *) = NULL) { first = last = NULL; block_size = size; error_function = err_function; }
109 
110  /* Destructor. Deallocates all items added so far */
111  ~Block() { while (first) { block *next = first -> next; delete first; first = next; } }
112 
113  /* Allocates 'num' consecutive items; returns pointer
114  to the first item. 'num' cannot be greater than the
115  block size since items must fit in one block */
116  Type *New(int num = 1)
117  {
118  Type *t;
119 
120  if (!last || last->current + num > last->last)
121  {
122  if (last && last->next) last = last -> next;
123  else
124  {
125  block *next = (block *) new char [sizeof(block) + (block_size-1)*sizeof(Type)];
126  if (!next) { /*if (error_function) (*error_function)("Not enough memory!");*/ exit(1); }
127  if (last) last -> next = next;
128  else first = next;
129  last = next;
130  last -> current = & ( last -> data[0] );
131  last -> last = last -> current + block_size;
132  last -> next = NULL;
133  }
134  }
135 
136  t = last -> current;
137  last -> current += num;
138  return t;
139  }
140 
141  /* Returns the first item (or NULL, if no items were added) */
142  Type *ScanFirst()
143  {
144  for (scan_current_block=first; scan_current_block; scan_current_block = scan_current_block->next)
145  {
146  scan_current_data = & ( scan_current_block -> data[0] );
147  if (scan_current_data < scan_current_block -> current) return scan_current_data ++;
148  }
149  return NULL;
150  }
151 
152  /* Returns the next item (or NULL, if all items have been read)
153  Can be called only if previous ScanFirst() or ScanNext()
154  call returned not NULL. */
155  Type *ScanNext()
156  {
157  while (scan_current_data >= scan_current_block -> current)
158  {
159  scan_current_block = scan_current_block -> next;
160  if (!scan_current_block) return NULL;
161  scan_current_data = & ( scan_current_block -> data[0] );
162  }
163  return scan_current_data ++;
164  }
165 
166  /* Marks all elements as empty */
167  void Reset()
168  {
169  block *b;
170  if (!first) return;
171  for (b=first; ; b=b->next)
172  {
173  b -> current = & ( b -> data[0] );
174  if (b == last) break;
175  }
176  last = first;
177  }
178 
179 /***********************************************************************/
180 
181 private:
182 
183  typedef struct block_st
184  {
185  Type *current, *last;
186  struct block_st *next;
187  Type data[1];
188  } block;
189 
190  int block_size;
191  block *first;
192  block *last;
193 
194  block *scan_current_block;
195  Type *scan_current_data;
196 
197  void (*error_function)(char *);
198 };
199 
200 /***********************************************************************/
201 /***********************************************************************/
202 /***********************************************************************/
203 
204 template <class Type> class DBlock
205 {
206 public:
207  /* Constructor. Arguments are the block size and
208  (optionally) the pointer to the function which
209  will be called if allocation failed; the message
210  passed to this function is "Not enough memory!" */
211  DBlock(int size, void (*err_function)(char *) = NULL) { first = NULL; first_free = NULL; block_size = size; error_function = err_function; }
212 
213  /* Destructor. Deallocates all items added so far */
214  ~DBlock() { while (first) { block *next = first -> next; delete first; first = next; } }
215 
216  /* Allocates one item */
217  Type *New()
218  {
219  block_item *item;
220 
221  if (!first_free)
222  {
223  block *next = first;
224  first = (block *) new char [sizeof(block) + (block_size-1)*sizeof(block_item)];
225  if (!first) { /*if (error_function) (*error_function)("Not enough memory!");*/ exit(1); }
226  first_free = & (first -> data[0] );
227  for (item=first_free; item<first_free+block_size-1; item++)
228  item -> next_free = item + 1;
229  item -> next_free = NULL;
230  first -> next = next;
231  }
232 
233  item = first_free;
234  first_free = item -> next_free;
235  return (Type *) item;
236  }
237 
238  /* Deletes an item allocated previously */
239  void Delete(Type *t)
240  {
241  ((block_item *) t) -> next_free = first_free;
242  first_free = (block_item *) t;
243  }
244 
245 /***********************************************************************/
246 
247 private:
248 
249  typedef union block_item_st
250  {
251  Type t;
252  block_item_st *next_free;
253  } block_item;
254 
255  typedef struct block_st
256  {
257  struct block_st *next;
258  block_item data[1];
259  } block;
260 
261  int block_size;
262  block *first;
263  block_item *first_free;
264 
265  void (*error_function)(char *);
266 };
267 
268 }
269 
Type * ScanNext()
Definition: animaBlock.h:155
Type * New()
Definition: animaBlock.h:217
void Delete(Type *t)
Definition: animaBlock.h:239
Block(int size, void(*err_function)(char *)=NULL)
Definition: animaBlock.h:108
void Reset()
Definition: animaBlock.h:167
DBlock(int size, void(*err_function)(char *)=NULL)
Definition: animaBlock.h:211
Type * New(int num=1)
Definition: animaBlock.h:116
Type * ScanFirst()
Definition: animaBlock.h:142