Joedb 9.1.4
The Journal-Only Embedded Database
Loading...
Searching...
No Matches
Freedom_Keeper.h
Go to the documentation of this file.
1#ifndef joedb_Freedom_Keeper_declared
2#define joedb_Freedom_Keeper_declared
3
4#include <cstddef>
5#include <vector>
6
8
9namespace joedb
10{
11 ////////////////////////////////////////////////////////////////////////////
13 ////////////////////////////////////////////////////////////////////////////
14 {
15 private: //////////////////////////////////////////////////////////////////
16 struct Record
17 {
18 public:
19 bool is_free;
20 size_t next;
21 size_t previous;
22
23 public:
24 Record() {}
25 Record(bool is_free, size_t next, size_t previous):
26 is_free(is_free),
27 next(next),
28 previous(previous)
29 {}
30 };
31
32 size_t used_count;
33 std::vector<Record> records;
34 enum {used_list = 0, free_list = 1};
35
36 public: ///////////////////////////////////////////////////////////////////
37 Freedom_Keeper(): used_count(0), records(2)
38 {
39 records[used_list].is_free = false;
40 records[used_list].next = used_list;
41 records[used_list].previous = used_list;
42
43 records[free_list].is_free = true;
44 records[free_list].next = free_list;
45 records[free_list].previous = free_list;
46 }
47
48 bool is_empty() const {return used_count == 0;}
49 size_t get_used_count() const {return used_count;}
50 size_t size() const {return records.size() - 2;}
51 size_t get_first_free() const {return records[free_list].next;}
52 size_t get_first_used() const {return records[used_list].next;}
53 size_t get_next(size_t index) const {return records[index].next;}
54 size_t get_previous(size_t index) const {return records[index].previous;}
55 bool is_free(size_t index) const {return records[index].is_free;}
56 bool is_used(size_t index) const
57 {
58 return index > 1 &&
59 index < records.size() &&
60 !records[index].is_free;
61 }
62
63 //////////////////////////////////////////////////////////////////////////
65 {
66 size_t result = records[free_list].next;
67 if (result == free_list)
68 {
69 push_back();
70 result = records[free_list].next;
71 }
72 return result;
73 }
74
75 //////////////////////////////////////////////////////////////////////////
76 size_t allocate()
77 {
78 const size_t result = get_free_record();
79 use(result);
80 return result;
81 }
82
83 //////////////////////////////////////////////////////////////////////////
84 size_t push_back()
85 {
86 const size_t index = records.size();
87 records.emplace_back(true, records[free_list].next, free_list);
88
89 records[records[free_list].next].previous = index;
90 records[free_list].next = index;
91
92 return index;
93 }
94
95 //////////////////////////////////////////////////////////////////////////
96 void resize(size_t new_size)
97 {
98 while(size() < new_size)
99 push_back();
100 }
101
102 //////////////////////////////////////////////////////////////////////////
103 void use(size_t index)
104 {
105 JOEDB_ASSERT(index > 1);
106 JOEDB_ASSERT(index < records.size());
107 JOEDB_ASSERT(records[index].is_free);
108
109 Record &record = records[index];
110 record.is_free = false;
111
112 records[record.previous].next = record.next;
113 records[record.next].previous = record.previous;
114
115 record.previous = records[used_list].previous;
116 record.next = used_list;
117
118 records[record.previous].next = index;
119 records[record.next].previous = index;
120
121 used_count++;
122 }
123
124 //////////////////////////////////////////////////////////////////////////
125 void free(size_t index)
126 {
127 JOEDB_ASSERT(index > 1);
128 JOEDB_ASSERT(index < records.size());
129 JOEDB_ASSERT(!records[index].is_free);
130
131 Record &record = records[index];
132 record.is_free = true;
133
134 records[record.previous].next = record.next;
135 records[record.next].previous = record.previous;
136
137 record.next = records[free_list].next;
138 record.previous = 1;
139
140 records[records[free_list].next].previous = index;
141 records[free_list].next = index;
142
143 used_count--;
144 }
145 };
146
147 ////////////////////////////////////////////////////////////////////////////
149 ////////////////////////////////////////////////////////////////////////////
150 {
151 private:
152 bool compact;
153 size_t compact_used_size;
154 size_t compact_free_size;
155
157
158 void lose_compactness()
159 {
160 compact = false;
161
162 while (fk.size() < compact_free_size)
163 fk.push_back();
164
165 for (size_t i = 0; i < compact_used_size; i++)
166 fk.use(i + 2);
167 }
168
169 public:
171 compact(true),
172 compact_used_size(0),
173 compact_free_size(0)
174 {
175 }
176
177 size_t size() const
178 {
179 if (compact)
180 return compact_free_size;
181 else
182 return fk.size();
183 }
184
185 bool is_empty() const
186 {
187 if (compact)
188 return compact_used_size == 0;
189 else
190 return fk.is_empty();
191 }
192
193 size_t get_used_count() const
194 {
195 if (compact)
196 return compact_used_size;
197 else
198 return fk.get_used_count();
199 }
200
201 bool is_used(size_t index) const
202 {
203 if (compact)
204 return index - 2 < compact_used_size;
205 else
206 return fk.is_used(index);
207 }
208
209 bool is_free(size_t index) const
210 {
211 if (compact)
212 return index - 2 >= compact_used_size;
213 else
214 return fk.is_free(index);
215 }
216
218 {
219 if (compact)
220 {
221 if (compact_free_size == compact_used_size)
222 ++compact_free_size;
223 return compact_used_size + 2;
224 }
225 else
226 return fk.get_free_record();
227 }
228
229 void use(size_t index)
230 {
231 if (compact)
232 {
233 if (index == compact_used_size + 2 && compact_used_size < compact_free_size)
234 compact_used_size++;
235 else
236 {
237 lose_compactness();
238 fk.use(index);
239 }
240 }
241 else
242 fk.use(index);
243 }
244
245 void use_vector(size_t index, size_t size)
246 {
247 if
248 (
249 compact &&
250 index == compact_used_size + 2 &&
251 compact_used_size + size <= compact_free_size
252 )
253 {
254 compact_used_size += size;
255 }
256 else
257 {
258 for (size_t i = 0; i < size; i++)
259 use(index + i);
260 }
261 }
262
263 void free(size_t index)
264 {
265 if (compact)
266 {
267 if (index == compact_used_size + 1 && index > 1)
268 --compact_used_size;
269 else
270 {
271 lose_compactness();
272 fk.free(index);
273 }
274 }
275 else
276 fk.free(index);
277 }
278
279 size_t push_back()
280 {
281 if (compact)
282 return ++compact_free_size + 1;
283 else
284 return fk.push_back();
285 }
286
287 bool is_compact() const
288 {
289 return compact;
290 }
291
292 size_t get_first_free() const
293 {
294 if (compact)
295 {
296 if (compact_used_size == compact_free_size)
297 return 1;
298 else
299 return compact_used_size + 2;
300 }
301 else
302 return fk.get_first_free();
303 }
304
305 size_t get_first_used() const
306 {
307 if (compact)
308 {
309 if (compact_used_size == 0)
310 return 0;
311 else
312 return 2;
313 }
314 else
315 return fk.get_first_used();
316 }
317
318 size_t get_next(size_t index) const
319 {
320 if (compact)
321 {
322 if (index == 0)
323 return get_first_used();
324
325 if (index == 1)
326 return get_first_free();
327
328 const size_t result = index + 1;
329
330 if (result == compact_used_size + 2)
331 return 0;
332
333 if (index == compact_free_size + 2)
334 return 1;
335
336 return result;
337 }
338 else
339 return fk.get_next(index);
340 }
341
342 size_t get_previous(size_t index) const
343 {
344 if (compact)
345 {
346 if (index == 0)
347 {
348 if (compact_used_size == 0)
349 return 0;
350 else
351 return compact_used_size + 1;
352 }
353
354 if (index == 1)
355 {
356 if (compact_used_size == compact_free_size)
357 return 1;
358 else
359 return compact_free_size + 1;
360 }
361
362 const size_t result = index - 1;
363
364 if (result == 1)
365 return 0;
366 if (result == compact_used_size + 1)
367 return 1;
368 return index - 1;
369 }
370 else
371 return fk.get_previous(index);
372 }
373
374 void resize(size_t size)
375 {
376 if (compact)
377 {
378 if (compact_free_size < size)
379 compact_free_size = size;
380 }
381 else
382 fk.resize(size);
383 }
384
385 void append_vector(size_t size)
386 {
387 if (compact && compact_free_size == compact_used_size)
388 {
389 compact_free_size += size;
390 compact_used_size += size;
391 }
392 else
393 {
394 for (size_t i = 0; i < size; i++)
395 use(push_back());
396 }
397 }
398 };
399}
400
401#endif
bool is_used(size_t index) const
void use_vector(size_t index, size_t size)
size_t get_previous(size_t index) const
bool is_free(size_t index) const
size_t get_next(size_t index) const
bool is_free(size_t index) const
void resize(size_t new_size)
bool is_used(size_t index) const
size_t get_used_count() const
size_t get_previous(size_t index) const
size_t get_next(size_t index) const
void free(size_t index)
size_t get_first_free() const
size_t get_first_used() const
void use(size_t index)
#define JOEDB_ASSERT(x)
Definition assert.h:18
Definition Blob.h:7