@@ -29,7 +29,6 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29
29
30
30
#pragma once
31
31
32
- #include < iostream>
33
32
#include < algorithm>
34
33
#include < cstring>
35
34
#include < functional>
@@ -51,7 +50,8 @@ struct StaticStorage {
51
50
using value_type = T;
52
51
using size_type = std::size_t ;
53
52
54
- inline static constexpr size_type max_size = MAX_SIZE * sizeof (value_type);
53
+ inline static constexpr size_type max_size =
54
+ MAX_SIZE * sizeof (value_type);
55
55
inline static constexpr bool is_static = true ;
56
56
57
57
StaticStorage () = default ;
@@ -76,7 +76,8 @@ struct StackStorage {
76
76
using value_type = T;
77
77
using size_type = std::size_t ;
78
78
79
- inline static constexpr size_type max_size = MAX_SIZE * sizeof (value_type);
79
+ inline static constexpr size_type max_size =
80
+ MAX_SIZE * sizeof (value_type);
80
81
inline static constexpr bool is_static = false ;
81
82
82
83
StackStorage () = default ;
@@ -103,36 +104,42 @@ struct BestFitMemoryBlock {
103
104
value_type address { nullptr };
104
105
size_type size { 0 };
105
106
106
- value_type get_end () const { return (address + size); }
107
- value_type get_start () const { return (address - size); }
107
+ inline value_type
108
+ get_end () const { return (address + size); }
109
+ inline value_type
110
+ get_start () const { return (address - size); }
108
111
109
112
// Hash function
110
113
//
111
- size_type operator () (const BestFitMemoryBlock &mb) const {
114
+ inline size_type
115
+ operator () (const BestFitMemoryBlock &mb) const {
112
116
113
117
return (std::hash<value_type>{ }(mb.address ));
114
118
}
115
119
116
120
inline friend bool
117
- operator < (const BestFitMemoryBlock &lhs, const BestFitMemoryBlock &rhs) {
121
+ operator < (const BestFitMemoryBlock &lhs,
122
+ const BestFitMemoryBlock &rhs) {
118
123
119
124
return (lhs.size < rhs.size );
120
125
}
121
126
inline friend bool
122
- operator > (const BestFitMemoryBlock &lhs, const BestFitMemoryBlock &rhs) {
127
+ operator > (const BestFitMemoryBlock &lhs,
128
+ const BestFitMemoryBlock &rhs) {
123
129
124
130
return (lhs.size > rhs.size );
125
131
}
126
132
inline friend bool
127
- operator == (const BestFitMemoryBlock &lhs, const BestFitMemoryBlock &rhs) {
133
+ operator == (const BestFitMemoryBlock &lhs,
134
+ const BestFitMemoryBlock &rhs) {
128
135
129
136
return (lhs.address == rhs.address );
130
137
}
131
138
};
132
139
133
140
// ----------------------------------------------------------------------------
134
141
135
- template <typename S>
142
+ template <typename S> // Storage class
136
143
struct BestFitAlgo : public S {
137
144
138
145
using Base = S;
@@ -142,6 +149,8 @@ struct BestFitAlgo : public S {
142
149
BestFitAlgo () : Base() {
143
150
144
151
free_blocks_start_.insert ({ Base::buffer_, Base::max_size });
152
+ free_blocks_assist_.insert (
153
+ std::make_pair (Base::buffer_, free_blocks_start_.begin ()));
145
154
free_blocks_end_.insert (std::make_pair (Base::buffer_ + Base::max_size,
146
155
Base::max_size));
147
156
}
@@ -152,28 +161,31 @@ struct BestFitAlgo : public S {
152
161
[[nodiscard]] pointer
153
162
get_space (size_type requested_size) {
154
163
155
- for (auto iter = free_blocks_start_.begin ();
156
- iter != free_blocks_start_.end ();
157
- ++iter) {
158
- if (iter->size >= requested_size) {
159
- auto found_end = iter->get_end ();
164
+ auto free_iter =
165
+ free_blocks_start_.lower_bound ({ nullptr , requested_size });
160
166
161
- if (iter->size > requested_size) {
162
- auto remaining = iter->size - requested_size;
163
- auto new_address = iter->address + requested_size;
167
+ if (free_iter != free_blocks_start_.end ()) {
168
+ auto found_end = free_iter->get_end ();
164
169
170
+ if (free_iter->size > requested_size) {
171
+ auto remaining = free_iter->size - requested_size;
172
+ auto new_address = free_iter->address + requested_size;
173
+ const auto insert_ret =
165
174
free_blocks_start_.insert ({ new_address, remaining });
166
- free_blocks_end_[found_end] = remaining;
167
- }
168
- else // Exact size match
169
- free_blocks_end_.erase (found_end);
170
-
171
- auto ret = iter->address ;
172
175
173
- free_blocks_start_. erase (iter);
174
- used_blocks_. insert ({ ret, requested_size } );
175
- return (ret) ;
176
+ free_blocks_assist_. insert (
177
+ std::make_pair (new_address, insert_ret) );
178
+ free_blocks_end_[found_end] = remaining ;
176
179
}
180
+ else // Exact size match
181
+ free_blocks_end_.erase (found_end);
182
+
183
+ auto ret = free_iter->address ;
184
+
185
+ free_blocks_assist_.erase (free_iter->address );
186
+ free_blocks_start_.erase (free_iter);
187
+ used_blocks_.insert ({ ret, requested_size });
188
+ return (ret);
177
189
}
178
190
throw std::bad_alloc ();
179
191
}
@@ -188,53 +200,58 @@ struct BestFitAlgo : public S {
188
200
if (used_iter != used_blocks_.end ()) {
189
201
const pointer tail_ptr = to_be_freed + used_iter->size ;
190
202
bool found_tail = false ;
203
+ const auto tail_block = free_blocks_assist_.find (tail_ptr);
191
204
192
- // Try to find a free block that starts where to_be_freed block ends.
193
- // If there is such a free block, join it with to_be_freed block
205
+ // Try to find a free block that starts where to_be_freed block
206
+ // ends. If there is such a free block, join it with to_be_freed
207
+ // block
194
208
//
195
- for ( auto tail_block = free_blocks_start_. begin ();
196
- tail_block != free_blocks_start_. end ();
197
- ++tail_block) {
198
- if (tail_block-> address == tail_ptr) {
199
- const size_type new_len =
200
- used_iter-> size + tail_block->size ;
201
- const BestFitMemoryBlock to_insert { to_be_freed, new_len } ;
202
-
203
- free_blocks_start_.erase (tail_block );
204
- free_blocks_start_. insert (to_insert);
205
- free_blocks_end_[to_insert. get_end ()] = new_len;
206
- found_tail = true ;
207
- break ;
208
- }
209
+ if ( tail_block != free_blocks_assist_. end ()) {
210
+ const size_type new_len =
211
+ used_iter-> size + tail_block-> second -> size ;
212
+ const BestFitMemoryBlock to_insert { to_be_freed, new_len };
213
+
214
+ free_blocks_start_. erase ( tail_block->second ) ;
215
+ free_blocks_assist_. erase (tail_block) ;
216
+
217
+ const auto insert_ret = free_blocks_start_.insert (to_insert );
218
+
219
+ free_blocks_assist_. insert (
220
+ std::make_pair (to_be_freed, insert_ret)) ;
221
+ free_blocks_end_[to_insert. get_end ()] = new_len ;
222
+ found_tail = true ;
209
223
}
210
224
211
- // Try to find a free block that ends where to_be_freed block starts.
212
- // If there is such a free block, join it with to_be_freed block
225
+ // Try to find a free block that ends where to_be_freed block
226
+ // starts. If there is such a free block, join it with to_be_freed
227
+ // block
213
228
//
214
229
const auto end_iter = free_blocks_end_.find (to_be_freed);
215
230
bool found_head = false ;
216
231
217
232
if (end_iter != free_blocks_end_.end ()) {
218
- const pointer head_address =
233
+ const pointer head_ptr =
219
234
end_iter->first - end_iter->second ;
235
+ const auto head_block = free_blocks_assist_.find (head_ptr);
236
+
237
+ if (head_block != free_blocks_assist_.end ()) {
238
+ const size_type new_len =
239
+ used_iter->size + head_block->second ->size ;
240
+ const auto new_head = head_block->second ->address ;
241
+ const auto new_end =
242
+ end_iter->first + used_iter->size ;
220
243
221
- for (auto head_block = free_blocks_start_.begin ();
222
- head_block != free_blocks_start_.end ();
223
- ++head_block) {
224
- if (head_block->address == head_address) {
225
- const size_type new_len =
226
- used_iter->size + head_block->size ;
227
- const auto new_head = head_block->address ;
228
- const auto new_end =
229
- end_iter->first + used_iter->size ;
230
-
231
- free_blocks_start_.erase (head_block);
244
+ free_blocks_start_.erase (head_block->second );
245
+ free_blocks_assist_.erase (head_block);
246
+
247
+ const auto insert_ret =
232
248
free_blocks_start_.insert ({ new_head, new_len });
233
- free_blocks_end_.erase (end_iter);
234
- free_blocks_end_[new_end] = new_len;
235
- found_head = true ;
236
- break ;
237
- }
249
+
250
+ free_blocks_assist_.insert (
251
+ std::make_pair (new_head, insert_ret));
252
+ free_blocks_end_.erase (end_iter);
253
+ free_blocks_end_[new_end] = new_len;
254
+ found_head = true ;
238
255
}
239
256
}
240
257
@@ -244,9 +261,12 @@ struct BestFitAlgo : public S {
244
261
if (! (found_tail || found_head)) {
245
262
const pointer end_address =
246
263
used_iter->address + used_iter->size ;
264
+ const auto insert_ret =
265
+ free_blocks_start_.insert (
266
+ { used_iter->address , used_iter->size });
247
267
248
- free_blocks_start_ .insert (
249
- { used_iter->address , used_iter-> size } );
268
+ free_blocks_assist_ .insert (
269
+ std::make_pair ( used_iter->address , insert_ret) );
250
270
free_blocks_end_[end_address] = used_iter->size ;
251
271
}
252
272
@@ -263,12 +283,29 @@ struct BestFitAlgo : public S {
263
283
// It is based on size, so it must be multi-set
264
284
//
265
285
using blk_set = std::multiset<BestFitMemoryBlock>;
266
- using blk_uoset = std::unordered_set<BestFitMemoryBlock, BestFitMemoryBlock>;
286
+ using blk_uoset =
287
+ std::unordered_set<BestFitMemoryBlock, BestFitMemoryBlock>;
267
288
using blk_uomap = std::unordered_map<pointer, std::size_t >;
289
+ using blk_assist = std::unordered_map<pointer, blk_set::const_iterator>;
268
290
269
- blk_set free_blocks_start_ { }; // Pointres to free block beginnings.
270
- blk_uomap free_blocks_end_ { }; // Pointres to free block ends.
271
- blk_uoset used_blocks_ { }; // Set of used blocks
291
+ // Set of free blocks, keyed by size of the block. There could be multiple
292
+ // blocks with the same size.
293
+ //
294
+ blk_set free_blocks_start_ { };
295
+
296
+ // Map of free blocks to size, keyed by the pointer to the end of the block.
297
+ //
298
+ blk_uomap free_blocks_end_ { };
299
+
300
+ // Hash set of used blocks, keyed by the pointer to the beginning of
301
+ // the block.
302
+ //
303
+ blk_uoset used_blocks_ { };
304
+
305
+ // Map of free blocks to iterators of free_blocks_start_, keyed pointers
306
+ // to the beginning of free blocks
307
+ //
308
+ blk_assist free_blocks_assist_ { };
272
309
};
273
310
274
311
// ----------------------------------------------------------------------------
@@ -333,7 +370,7 @@ struct FirstFitStackBase : public StackStorage<T, MAX_SIZE> {
333
370
334
371
// ----------------------------------------------------------------------------
335
372
336
- template <typename S>
373
+ template <typename S> // Storage class
337
374
struct FirstFitAlgo : public S {
338
375
339
376
using Base = S;
0 commit comments