-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathpool.hpp
153 lines (122 loc) · 3.88 KB
/
pool.hpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
// Copyright 2020 Joren Brunekreef and Andrzej Görlich
#pragma once
/****
A Simplex<T> contains a single pool of objects of type ....
There exists only a single copy of a pool for given type.
****/
#include <cstdio>
#include <array>
#include <cassert>
#include <random>
#include <string>
#include <typeinfo>
/****
*
* Pool is a template class that maintains
* a single, static pool (array) of objects of given class T.
* The T class should then extend the Pool<T>
*
****/
template<class T>
class Pool {
private:
static T *elements; // elements shouldn't be public so not to change it outside but can be returned
static int first; // Index of the first empty cell
static int total; // No. used cells
static int capacity;
int next; // Label or next free entry in pool (maybe protected)
friend T; // Private constructor only to prevent inheriting wrong template class realization,
Pool() = default; // like: Link : Pool<Vertex>. Has to be a friend
protected:
static const unsigned pool_size = -1; // Has to be overshaded in child class
public:
Pool(const Pool&) = delete; // Make poolable objects non-copyable
Pool& operator=(const Pool&) = delete;
Pool(Pool&&) = delete; // Make poolable objects non-movable
Pool& operator=(Pool&&) = delete;
/**** Label ****
*
* The nested Label type serves as a pointer to T,
* but internally it is an integer.
* Can be referred as T::Label.
*
***************/
class Label {
private:
int i; // const?
public:
Label() = default;
Label(int i) : i{i} { }
T& operator*() const { return T::at(i); }
T* operator->() const { return &T::at(i); }
operator int&() { return i; } // Basically a getter/setter
operator int() const { return i; } // Basically a getter
};
operator Label() const { return Label{next}; }
static T* create_pool() {
static_assert(T::pool_size > 0, "Pool size not defined in child class");
capacity = T::pool_size;
elements = new T[capacity];
for(auto i = 0; i < capacity; i++)
elements[i].next = ~(i + 1); // Using not (~) solves the negative zero problem. ~x == -(x + 1)
return elements;
}
static Label create() {
auto tmp = first;
assert(elements[tmp].next < 0); // Check if element is really free
first = ~elements[tmp].next;
elements[tmp].next = tmp;
total++;
return tmp; // Implicit 'Label(int)'' constructor
}
static void destroy(Label i) {
elements[i].next = ~first; // 'deactivate' object at position i
first = i; // Reset index of the first inactive object. Implicit Label::operator int&().
total--;
}
static T& at(int i) { return elements[i]; }
static int size() noexcept { return total; }
static int pool_capacity() noexcept { return capacity; }
//// Checks if the object is indeed in the right position in array 'elements' ////
void check_in_pool() {
assert(this->next >= 0);
assert(this->next < capacity);
assert(this == elements + this->next);
}
void destroy() {
check_in_pool();
destroy(this->next);
}
//// Pool iterator - even though there are no pool objects ////
struct Iterator {
private:
int i;
int cnt;
public:
Iterator(int i = 0, int cnt = 0) : i{i}, cnt{cnt} {}
T& operator*() { return elements[i]; }
bool operator==(const Iterator& b) const { return cnt == b.cnt; }
bool operator!=(const Iterator& b) const { return !operator == (b); }
Iterator& operator++() {
if(cnt < total - 1)
while(elements[++i].next < 0) continue;
cnt++;
return *this;
}
};
struct Items {
auto begin() {
int i;
for(i = 0; elements[i].next < 0; i++) continue;
return Iterator{i, 0};
}
auto end() {
return Iterator{-1, total};
}
};
static Items items() { return Items{}; } // items() return Items object with begin() and end() methods
};
template<class T> T* Pool<T>::elements = Pool<T>::create_pool();
template<class T> int Pool<T>::first{0};
template<class T> int Pool<T>::total{0};
template<class T> int Pool<T>::capacity;