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