ReadFramework
block.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 #ifndef __BLOCK_H__
91 #define __BLOCK_H__
92 
93 #include <stdlib.h>
94 
95 /***********************************************************************/
96 /***********************************************************************/
97 /***********************************************************************/
98 
99 template <class Type> class Block
100 {
101 public:
102  /* Constructor. Arguments are the block size and
103  (optionally) the pointer to the function which
104  will be called if allocation failed; the message
105  passed to this function is "Not enough memory!" */
106  Block(int size, void (*err_function)(const char *) = NULL) { first = last = NULL; block_size = size; error_function = err_function; }
107 
108  /* Destructor. Deallocates all items added so far */
109  ~Block() { while (first) { block *next = first -> next; delete first; first = next; } }
110 
111  /* Allocates 'num' consecutive items; returns pointer
112  to the first item. 'num' cannot be greater than the
113  block size since items must fit in one block */
114  Type *New(int num = 1)
115  {
116  Type *t;
117 
118  if (!last || last->current + num > last->last)
119  {
120  if (last && last->next) last = last -> next;
121  else
122  {
123  block *next = (block *) new char [sizeof(block) + (block_size-1)*sizeof(Type)];
124  if (!next) { if (error_function) (*error_function)("Not enough memory!"); exit(1); }
125  if (last) last -> next = next;
126  else first = next;
127  last = next;
128  last -> current = & ( last -> data[0] );
129  last -> last = last -> current + block_size;
130  last -> next = NULL;
131  }
132  }
133 
134  t = last -> current;
135  last -> current += num;
136  return t;
137  }
138 
139  /* Returns the first item (or NULL, if no items were added) */
140  Type *ScanFirst()
141  {
142  for (scan_current_block=first; scan_current_block; scan_current_block = scan_current_block->next)
143  {
144  scan_current_data = & ( scan_current_block -> data[0] );
145  if (scan_current_data < scan_current_block -> current) return scan_current_data ++;
146  }
147  return NULL;
148  }
149 
150  /* Returns the next item (or NULL, if all items have been read)
151  Can be called only if previous ScanFirst() or ScanNext()
152  call returned not NULL. */
153  Type *ScanNext()
154  {
155  while (scan_current_data >= scan_current_block -> current)
156  {
157  scan_current_block = scan_current_block -> next;
158  if (!scan_current_block) return NULL;
159  scan_current_data = & ( scan_current_block -> data[0] );
160  }
161  return scan_current_data ++;
162  }
163 
164  /* Marks all elements as empty */
165  void Reset()
166  {
167  block *b;
168  if (!first) return;
169  for (b=first; ; b=b->next)
170  {
171  b -> current = & ( b -> data[0] );
172  if (b == last) break;
173  }
174  last = first;
175  }
176 
177 /***********************************************************************/
178 
179 private:
180 
181  typedef struct block_st
182  {
183  Type *current, *last;
184  struct block_st *next;
185  Type data[1];
186  } block;
187 
188  int block_size;
189  block *first;
190  block *last;
191 
192  block *scan_current_block;
193  Type *scan_current_data;
194 
195  void (*error_function)(const char *);
196 };
197 
198 /***********************************************************************/
199 /***********************************************************************/
200 /***********************************************************************/
201 
202 template <class Type> class DBlock
203 {
204 public:
205  /* Constructor. Arguments are the block size and
206  (optionally) the pointer to the function which
207  will be called if allocation failed; the message
208  passed to this function is "Not enough memory!" */
209  DBlock(int size, void (*err_function)(const char *) = NULL) { first = NULL; first_free = NULL; block_size = size; error_function = err_function; }
210 
211  /* Destructor. Deallocates all items added so far */
212  ~DBlock() { while (first) { block *next = first -> next; delete first; first = next; } }
213 
214  /* Allocates one item */
215  Type *New()
216  {
217  block_item *item;
218 
219  if (!first_free)
220  {
221  block *next = first;
222  first = (block *) new char [sizeof(block) + (block_size-1)*sizeof(block_item)];
223  if (!first) { if (error_function) (*error_function)("Not enough memory!"); exit(1); }
224  first_free = & (first -> data[0] );
225  for (item=first_free; item<first_free+block_size-1; item++)
226  item -> next_free = item + 1;
227  item -> next_free = NULL;
228  first -> next = next;
229  }
230 
231  item = first_free;
232  first_free = item -> next_free;
233  return (Type *) item;
234  }
235 
236  /* Deletes an item allocated previously */
237  void Delete(Type *t)
238  {
239  ((block_item *) t) -> next_free = first_free;
240  first_free = (block_item *) t;
241  }
242 
243 /***********************************************************************/
244 
245 private:
246 
247  typedef union block_item_st
248  {
249  Type t;
250  block_item_st *next_free;
251  } block_item;
252 
253  typedef struct block_st
254  {
255  struct block_st *next;
256  block_item data[1];
257  } block;
258 
259  int block_size;
260  block *first;
261  block_item *first_free;
262 
263  void (*error_function)(const char *);
264 };
265 
266 
267 #endif
268 
~Block()
Definition: block.h:109
Type * New(int num=1)
Definition: block.h:114
~DBlock()
Definition: block.h:212
Block(int size, void(*err_function)(const char *)=NULL)
Definition: block.h:106
Type * ScanFirst()
Definition: block.h:140
DBlock(int size, void(*err_function)(const char *)=NULL)
Definition: block.h:209
Definition: block.h:99
void Delete(Type *t)
Definition: block.h:237
Type * ScanNext()
Definition: block.h:153
Type * New()
Definition: block.h:215
void Reset()
Definition: block.h:165
Definition: block.h:202