Orbiter 2022
Combinatorial Objects
page_storage.cpp
Go to the documentation of this file.
1// page_storage.cpp
2//
3// Anton Betten
4// October 23, 2002
5
6#include "foundations.h"
7
8
9using namespace std;
10
11
12namespace orbiter {
13namespace layer1_foundations {
14namespace data_structures {
15
16
18{
20 entry_size = 0;
22 page_length = 0;
23 page_size = 0;
25
26 page_ptr_used = 0;
29
30 pages = NULL;
31 allocation_tables = NULL;
32
35
37 elt_print = NULL;
38 elt_print_data = NULL;
39}
40
42{
43 long int i;
44
45 //cout << "page_storage::~page_storage" << endl;
46 if (pages) {
47 //cout << "page_ptr_used=" << page_ptr_used << endl;
48 for (i = 0; i < page_ptr_used; i++) {
49 //cout << "deleting page" << i << endl;
50 FREE_uchar(pages[i]);
52 //cout << "deleting page" << i << " done" << endl;
53 }
54 //cout << "deleting pages" << endl;
56 //cout << "deleting allocation_tables" << endl;
58 pages = NULL;
59 allocation_tables = NULL;
60 }
61 //cout << "page_storage::~page_storage done" << endl;
62}
63
64void page_storage::init(int entry_size,
65 int page_length_log, int verbose_level)
66{
67 int f_v = (verbose_level >= 1);
68 //int f_vv = (verbose_level >= 2);
69 int i;
70
71 if (f_v) {
72 cout << "page_storage::init "
73 "verbose_level=" << verbose_level << endl;
74 }
76
78 next_free_entry = -1;
80
81 //f_v = TRUE;
82
84 if (entry_size < (int)sizeof(int)) {
85 page_storage::entry_size = sizeof(int);
86 if (f_v) {
87 cout << "warning: raising entry_size to sizeof(int) = "
88 << page_storage::entry_size << endl;
89 }
90 }
91
93 while (TRUE) {
96
97 if (f_v) {
98 cout << "page_storage::entry_size="
99 << page_storage::entry_size << endl;
100 cout << "(int)sizeof(int)="
101 << (int)sizeof(int) << endl;
102 cout << "page_length_log = "
104 cout << "page_length = "
105 << page_length << endl;
106 cout << "page_size = "
107 << page_size << endl;
108 }
110 if (f_v) {
111 cout << "page_storage::init page_size "
112 "too big (arithmetic overflow)" << endl;
113 }
115 continue;
116 }
118 if (f_v) {
119 cout << "page_storage::init page_size too big" << endl;
120 cout << "the maximum page size in char is "
121 << MAX_PAGE_SIZE_IN_charS << endl;
122 }
124 continue;
125 }
126 if (f_v) {
127 cout << "page_size is OK" << endl;
128 }
129 break;
130 }
131
132
135 overall_length = 0;
136 if (f_v) {
137 cout << "allocation_table_length="
138 << allocation_table_length << endl;
139 cout << "allocating pages / allocation_tables" << endl;
140 }
143
145 page_ptr_used = 1;
146 if (f_v) {
147 cout << "allocating page[0] of size " << page_size << endl;
148 }
150 if (f_v) {
151 cout << "allocating allocation_tables[0] "
152 "of size " << allocation_table_length << endl;
153 }
155 for (i = 0; i < allocation_table_length; i++) {
156 allocation_tables[0][i] = 0;
157 }
158 if (f_v) {
159 cout << "pages[0]/allocation_tables[0] allocated" << endl;
160 //print();
161 }
162}
163
165 void (* elt_print)(void *p, void *data, ostream &ost),
166 void *elt_print_data)
167{
171}
172
174{
175 cout << "page_storage:" << endl;
176 cout << "entry_size=" << entry_size << endl;
177 cout << "page_length_log=" << page_length_log << endl;
178 cout << "page_length=" << page_length << endl;
179 cout << "page_size (in char )=" << page_size << endl;
180 cout << "page_ptr_oversize=" << page_ptr_oversize << endl;
181 cout << "allocation_table_length (in char)="
182 << allocation_table_length << endl;
183 cout << "overall_length=" << overall_length << endl;
184 cout << "page_ptr_used=" << page_ptr_used << endl;
185 cout << "nb_free_entries = " << nb_free_entries << endl;
186 cout << "next_free_entry = " << next_free_entry << endl;
188}
189
191{
192 uchar *p, *q;
193 int j;
194 algorithms Algo;
195
196 long int page_idx = i & (page_length - 1);
197 long int page = i >> page_length_log;
198 if (page >= page_ptr_used) {
199 cout << "page_storage::s_i_and_allocate "
200 "page >= page_ptr_used" << endl;
201 cout << "i=" << i << endl;
202 print();
203 exit(1);
204 }
205 //cout << "s_i(" << i << ") page=" << page
206 // << " page_idx=" << page_idx << endl;
207 if (page_idx * entry_size >= page_size) {
208 cout << "page_idx * entry_size >= page_size" << endl;
209 exit(1);
210 }
211 p = pages[page];
212 p += page_idx * entry_size;
213 q = allocation_tables[page];
214 int word = page_idx >> 3;
215 int bit = page_idx & 7;
216 uchar mask = ((uchar) 1) << bit;
217 //cout << "p=" << ((int) p) << " q=" << ((int)(q + word)) << endl;
218
219 if (word >= allocation_table_length) {
220 cout << "page_storage::s_i_and_allocate "
221 "word >= allocation_table_length" << endl;
222 cout << "word=" << word << endl;
223 cout << "allocation_table_length="
224 << allocation_table_length << endl;
225 print();
226 exit(1);
227 }
228#if 0
229 cout << "page_idx=" << page_idx << " word=" << word
230 << " bit=" << bit << " ";
231 if (word)
232 j = - 1;
233 else
234 j = 0;
235 for (; j < 5; j++) {
236 uchar_print_bitwise(cout, q[word + j]);
237 cout << " ";
238 }
239 cout << endl;
240#endif
241 if (q[word] & mask) {
242 cout << "page_storage::s_i_and_allocate "
243 "allocating entry which is currently in use" << endl;
244 cout << "i=" << i << endl;
245 cout << "page=" << page << endl;
246 cout << "word=" << word << endl;
247 cout << "bit=" << bit << endl;
248 cout << "mask=" << (int)mask << endl;
249 for (j = 0; j < 10; j++) {
250 cout << (int)q[word + j] << " ";
251 }
252 cout << endl;
253 for (j = 0; j < 10; j++) {
254 Algo.uchar_print_bitwise(cout, q[word + j]);
255 cout << " ";
256 }
257 cout << endl;
258 print();
259 exit(1);
260 }
261 q[word] |= mask;
262#if 0
263 cout << "page_idx=" << page_idx << " word="
264 << word << " bit=" << bit << " ";
265 if (word)
266 j = - 1;
267 else
268 j = 0;
269 for (; j < 5; j++) {
270 uchar_print_bitwise(cout, q[word + j]);
271 cout << " ";
272 }
273 cout << endl;
274#endif
275 return p;
276}
277
279{
280 uchar *p;
281
282 if (i >= overall_length) {
283 cout << "page_storage::s_i_and_deallocate "
284 "i >= overall_length" << endl;
285 cout << "i=" << i << endl;
286 print();
287 exit(1);
288 }
289 long int page_idx = i & (page_length - 1);
290 long int page = i >> page_length_log;
291 if (page >= page_ptr_used) {
292 cout << "page_storage::s_i_and_deallocate "
293 "page >= page_ptr_used" << endl;
294 cout << "i=" << i << endl;
295 print();
296 exit(1);
297 }
298 //cout << "s_i(" << i << ") page=" << page
299 // << " page_idx=" << page_idx << endl;
300 p = pages[page] + page_idx * entry_size;
301 int word = page_idx >> 3;
302 int bit = page_idx & 7;
303 uchar mask = ((uchar) 1) << bit;
304 uchar not_mask = ~mask;
305 if ((allocation_tables[page][word] & mask) == 0) {
306 cout << "page_storage::s_i_and_deallocate "
307 "deallocating entry which is currently not in use" << endl;
308 cout << "i=" << i << endl;
309 print();
310 exit(1);
311 }
312 allocation_tables[page][word] &= not_mask;
313 return p;
314}
315
317{
318 if (i >= overall_length) {
319 cout << "page_storage::s_i "
320 "i >= overall_length" << endl;
321 cout << "i=" << i << endl;
322 print();
323 exit(1);
324 }
325
326 long int page_idx = i & (page_length - 1);
327 long int page = i >> page_length_log;
328 if (page >= page_ptr_used) {
329 cout << "page_storage::s_i "
330 "page >= page_ptr_used" << endl;
331 cout << "i=" << i << endl;
332 print();
333 exit(1);
334 }
335 int word = page_idx >> 3;
336 int bit = page_idx & 7;
337 uchar mask = ((uchar) 1) << bit;
338 if ((allocation_tables[page][word] & mask) == 0) {
339 cout << "page_storage::s_i "
340 "access to entry which is currently not used" << endl;
341 cout << "i=" << i << endl;
342 print();
343 exit(1);
344 }
345 //cout << "s_i(" << i << ") page=" << page
346 // << " page_idx=" << page_idx << endl;
347 return pages[page] + page_idx * entry_size;
348}
349
350uchar *page_storage::s_i_and_allocation_bit(long int i, int &f_allocated)
351{
352 if (i >= overall_length) {
353 cout << "page_storage::s_i "
354 "i >= overall_length" << endl;
355 cout << "i=" << i << endl;
356 print();
357 exit(1);
358 }
359
360 long int page_idx = i & (page_length - 1);
361 long int page = i >> page_length_log;
362 if (page >= page_ptr_used) {
363 cout << "page_storage::s_i "
364 "page >= page_ptr_used" << endl;
365 cout << "i=" << i << endl;
366 print();
367 exit(1);
368 }
369 int word = page_idx >> 3;
370 int bit = page_idx & 7;
371 uchar mask = ((uchar) 1) << bit;
372 if (allocation_tables[page][word] & mask) {
373 f_allocated = TRUE;
374 }
375 else
376 f_allocated = FALSE;
377 //cout << "s_i(" << i << ") page=" << page
378 // << " page_idx=" << page_idx << endl;
379 return pages[page] + page_idx * entry_size;
380}
381
383{
384 long int page_idx = overall_length & (page_length - 1);
385 long int page = overall_length >> page_length_log;
386 algorithms Algo;
387
388 if (page >= page_ptr_used) {
389 cout << "check_allocation_table::s_i "
390 "page >= page_ptr_used" << endl;
391 print();
392 exit(1);
393 }
394 int word = page_idx >> 3;
395 //int bit = page_idx & 7;
396 //uchar mask = ((uchar) 1) << bit;
397 for (word++; word < allocation_table_length; word++) {
398 if (allocation_tables[page][word]) {
399 int j;
400
401 cout << "page_storage::check_allocation_table "
402 "allocation_tables[page][word]" << endl;
403 cout << "page_idx >> 3 = " << (page_idx >> 3) << endl;
404 cout << "word = " << word << endl;
405 for (j = 0; j < 10; j++) {
406 cout << (int)allocation_tables[page][word + j] << " ";
407 }
408 cout << endl;
409 for (j = 0; j < 10; j++) {
410 Algo.uchar_print_bitwise(cout,
411 allocation_tables[page][word + j]);
412 cout << " ";
413 }
414 cout << endl;
415 print();
416 exit(1);
417 }
418 }
419}
420
422{
423 long int i, hdl;
424 uchar *p, *q;
425 algorithms Algo;
426
427 if (nb_free_entries) {
428 long int nfe = next_free_entry;
429
430 p = s_i_and_allocate(nfe);
431 long int next_next_free_entry;
432
433 Algo.uchar_move(p, (uchar *) &next_next_free_entry, sizeof(long int));
434 if (nb_free_entries > 1) {
435 if (next_next_free_entry < 0 ||
436 next_next_free_entry >= overall_length) {
437 cout << "page_storage::store "
438 "next_next_free_entry illegal" << endl;
439 exit(1);
440 }
441 }
442 else {
443 if (next_next_free_entry != -1) {
444 cout << "page_storage::store "
445 "next_next_free_entry should be -1" << endl;
446 exit(1);
447 }
448 }
449 next_free_entry = next_next_free_entry;
450
451 Algo.uchar_move(elt, p, entry_size);
453 hdl = nfe;
454#ifdef DEBUG_PAGE_STORAGE
455 cout << "page_storage: " << hdl << " reused" << endl;
457 (*elt_print)(p, elt_print_data, cout);
458 cout << endl;
459 }
460#endif
461 }
462 else {
463 if (overall_length > (long int) page_ptr_used * page_length) {
464 cout << "page_storage::store "
465 "overall_length > page_ptr_used * page_length" << endl;
466 cout << "overall_length=" << overall_length << endl;
467 cout << "page_ptr_used=" << page_ptr_used << endl;
468 cout << "page_length=" << page_length << endl;
469 exit(1);
470 }
472 cout << "\npage_storage::store "
473 "allocating page # "
474 << (overall_length >> page_length_log) << endl;
476 uchar **pages1 =
478 uchar **allocation_tables1 =
480 for (i = 0; i < page_ptr_used; i++) {
481 pages1[i] = pages[i];
482 allocation_tables1[i] = allocation_tables[i];
483 }
486 pages = pages1;
487 allocation_tables = allocation_tables1;
489 }
490 p = NEW_uchar(page_size);
492 for (i = 0; i < page_size; i++) {
493 p[i] = 0;
494 }
495 for (i = 0; i < allocation_table_length; i++) {
496 q[i] = 0;
497 }
498 pages[page_ptr_used] = p;
501 }
502
503#ifdef DEBUG_PAGE_STORAGE
504 cout << "calling s_i_and_allocate" << endl;
505 cout << "calling s_i_and_allocate "
506 "overall_length = " << overall_length << endl;
507#endif
509 Algo.uchar_move(elt, p, entry_size);
510 //cout << "storing at " << p << endl;
511 //check_allocation_table();
512 hdl = overall_length++;
513#ifdef DEBUG_PAGE_STORAGE
514 cout << "page_storage: " << hdl << " allocated" << endl;
516 (*elt_print)(p, elt_print_data, cout);
517 cout << endl;
518 }
519#endif
520 }
521 //check_free_list();
522 return hdl;
523}
524
525void page_storage::dispose(long int hdl)
526{
527#if 1
528 uchar *p = s_i_and_deallocate(hdl);
529 algorithms Algo;
530
531 long int next_next_free_entry = next_free_entry;
532 Algo.uchar_move((uchar *) &next_next_free_entry, p, sizeof(long int));
533 next_free_entry = hdl;
535 //check_free_list();
536#ifdef DEBUG_PAGE_STORAGE
537 cout << "page_storage: " << hdl << " deallocated" << endl;
538#endif
539#endif
540}
541
543{
544 long int nb = 0, nfe;
545 int f_allocated;
546 uchar *p;
547 algorithms Algo;
548
549 if (nb_free_entries == 0)
550 return;
551 nfe = next_free_entry;
552 while (TRUE) {
553 nb++;
554 p = s_i_and_allocation_bit(nfe, f_allocated);
555 if (f_allocated) {
556 cout << "page_storage::check_free_list "
557 "inconsistency: empty entry marked "
558 "as allocated" << endl;
559 cout << "nb_free_entries = " << nb_free_entries;
560 cout << "entry = " << nfe << endl;
561 print();
562 exit(1);
563 }
564 Algo.uchar_move(p, (uchar *) &nfe, sizeof(long int));
565 if (nfe == -1)
566 break;
567 }
568 if (nb != nb_free_entries) {
569 cout << "page_storage::check_free_list "
570 "inconsistency" << endl;
571 cout << "nb_free_entries = " << nb_free_entries;
572 cout << "nb = " << nb << endl;
573 print();
574 exit(1);
575 }
576}
577
579{
580 cout << overall_length << " group elements stored overall on "
581 << page_ptr_used << " pages a "
582 << " 2^{" << page_length_log << "} entries\n"
583 << nb_free_entries << " entries currently empty" << endl;
584}
585
586#if 0
587void test_page_storage(int verbose_level)
588{
589 int f_v = (verbose_level >= 1);
590
591 if (f_v) {
592 cout << "test_page_storage" << endl;
593 }
594 {
595 page_storage *Elts;
596 Elts = NEW_OBJECT(page_storage);
597
598 int char_per_elt = 20;
599 int page_length_log = PAGE_LENGTH_LOG;
600
601 Elts->init(char_per_elt /* entry_size */, page_length_log, verbose_level - 1);
602 cout << "destroying Elts" << endl;
603 FREE_OBJECT(Elts);
604 }
605 if (f_v) {
606 cout << "test_page_storage done" << endl;
607 }
608}
609#endif
610
611}}}
612
void uchar_print_bitwise(std::ostream &ost, uchar u)
Definition: algorithms.cpp:82
void(* elt_print)(void *p, void *data, std::ostream &ost)
void init(int entry_size, int page_length_log, int verbose_level)
void add_elt_print_function(void(*elt_print)(void *p, void *data, std::ostream &ost), void *elt_print_data)
uchar * s_i_and_allocation_bit(long int i, int &f_allocated)
#define PAGE_LENGTH_LOG
Definition: foundations.h:210
#define NEW_uchar(n)
Definition: foundations.h:634
#define FREE_uchar(p)
Definition: foundations.h:647
#define FREE_puchar(p)
Definition: foundations.h:649
#define NEW_puchar(n)
Definition: foundations.h:636
unsigned char uchar
Definition: foundations.h:204
#define NEW_OBJECT(type)
Definition: foundations.h:638
#define FREE_OBJECT(p)
Definition: foundations.h:651
#define TRUE
Definition: foundations.h:231
#define FALSE
Definition: foundations.h:234
#define MAX_PAGE_SIZE_IN_charS
Definition: foundations.h:211
the orbiter library for the classification of combinatorial objects