@@ -64,10 +64,11 @@ struct alignas(void*) SDoublyLinkedNode
64
64
}
65
65
};
66
66
67
- template <typename Value>
67
+ template <typename Value, class allocator = core::allocator<SDoublyLinkedNode<Value>> >
68
68
class DoublyLinkedList
69
69
{
70
70
public:
71
+ using allocator_t = allocator;
71
72
using address_allocator_t = PoolAddressAllocator<uint32_t >;
72
73
using node_t = SDoublyLinkedNode<Value>;
73
74
using value_t = Value;
@@ -121,7 +122,7 @@ class DoublyLinkedList
121
122
{
122
123
disposeAll ();
123
124
124
- m_addressAllocator = std::unique_ptr< address_allocator_t >( new address_allocator_t ( m_reservedSpace, 0u , 0u , 1u , m_cap, 1u ) );
125
+ m_addressAllocator = address_allocator_t ( m_reservedSpace, 0u , 0u , 1u , m_cap, 1u );
125
126
m_back = invalid_iterator;
126
127
m_begin = invalid_iterator;
127
128
@@ -186,9 +187,9 @@ class DoublyLinkedList
186
187
// Must at least make list grow
187
188
if (newCapacity <= m_cap)
188
189
return false ;
189
- // Same as code found in ContiguousMemoryLinkedListBase to create aligned space
190
+ // Have to consider allocating enough space for list AND state of the address allocator
190
191
const auto firstPart = core::alignUp (address_allocator_t::reserved_size (1u , newCapacity, 1u ), alignof (node_t ));
191
- void * newReservedSpace = _NBL_ALIGNED_MALLOC ( firstPart + newCapacity * sizeof (node_t ), alignof ( node_t ));
192
+ void * newReservedSpace = reinterpret_cast < void *>(m_allocator. allocate ( firstPart + newCapacity * sizeof (node_t )));
192
193
193
194
// Malloc failed, not possible to grow
194
195
if (!newReservedSpace)
@@ -198,9 +199,9 @@ class DoublyLinkedList
198
199
// Copy memory over to new buffer
199
200
memcpy (newArray, m_array, m_cap * sizeof (node_t ));
200
201
// Create new address allocator from old one
201
- m_addressAllocator = std::make_unique< address_allocator_t > (newCapacity, std::move (*( m_addressAllocator) ), newReservedSpace);
202
+ m_addressAllocator = address_allocator_t (newCapacity, std::move (m_addressAllocator), newReservedSpace);
202
203
// After address allocator creation we can free the old buffer
203
- _NBL_ALIGNED_FREE ( m_reservedSpace);
204
+ m_allocator. deallocate ( reinterpret_cast < node_t *>( m_reservedSpace) );
204
205
m_cap = newCapacity;
205
206
m_array = newArray;
206
207
m_reservedSpace = newReservedSpace;
@@ -210,13 +211,15 @@ class DoublyLinkedList
210
211
}
211
212
212
213
// Constructor, capacity determines the amount of allocated space
213
- DoublyLinkedList (const uint32_t capacity, disposal_func_t && dispose_f = disposal_func_t ()) : m_dispose_f(std::move(dispose_f))
214
+ DoublyLinkedList (const uint32_t capacity, disposal_func_t && dispose_f = disposal_func_t (), const allocator_t & _allocator = allocator_t ())
215
+ : m_dispose_f(std::move(dispose_f)), m_allocator(_allocator)
214
216
{
217
+ // Have to consider allocating enough space for list AND state of the address allocator
215
218
const auto firstPart = core::alignUp (address_allocator_t::reserved_size (1u , capacity, 1u ), alignof (node_t ));
216
- m_reservedSpace = _NBL_ALIGNED_MALLOC ( firstPart + capacity * sizeof (node_t ), alignof ( node_t ));
219
+ m_reservedSpace = reinterpret_cast < void *>(m_allocator. allocate ( firstPart + capacity * sizeof (node_t )));
217
220
m_array = reinterpret_cast <node_t *>(reinterpret_cast <uint8_t *>(m_reservedSpace) + firstPart);
218
221
219
- m_addressAllocator = std::make_unique< address_allocator_t > (m_reservedSpace, 0u , 0u , 1u , capacity, 1u );
222
+ m_addressAllocator = address_allocator_t (m_reservedSpace, 0u , 0u , 1u , capacity, 1u );
220
223
m_cap = capacity;
221
224
m_back = invalid_iterator;
222
225
m_begin = invalid_iterator;
@@ -230,35 +233,36 @@ class DoublyLinkedList
230
233
231
234
DoublyLinkedList& operator =(DoublyLinkedList&& other)
232
235
{
236
+ m_allocator = std::move (other.m_allocator );
233
237
m_addressAllocator = std::move (other.m_addressAllocator );
234
- m_reservedSpace = other.m_reservedSpace ;
235
- m_array = other.m_array ;
236
- m_dispose_f = std::move (other.m_dispose_f );
237
- m_cap = other.m_cap ;
238
- m_back = other. m_back ;
238
+ m_reservedSpace = std::move ( other.m_reservedSpace ) ;
239
+ m_array = std::move ( other.m_array ) ;
240
+ m_dispose_f = std::move (std::move ( other.m_dispose_f ) );
241
+ m_cap = std::move ( other.m_cap ) ;
242
+
239
243
m_begin = other.m_begin ;
244
+ m_back = other.m_back ;
245
+ other.m_begin = invalid_iterator;
246
+ other.m_back = invalid_iterator;
240
247
241
- // Nullify other
242
- other.m_addressAllocator = nullptr ;
243
- other.m_reservedSpace = nullptr ;
244
- other.m_array = nullptr ;
245
- other.m_cap = 0u ;
246
- other.m_back = 0u ;
247
- other.m_begin = 0u ;
248
248
return *this ;
249
249
}
250
250
251
251
~DoublyLinkedList ()
252
252
{
253
253
disposeAll ();
254
- _NBL_ALIGNED_FREE (m_reservedSpace);
254
+ // Could be null if list was moved out of
255
+ if (m_reservedSpace)
256
+ {
257
+ m_allocator.deallocate (reinterpret_cast <node_t *>(m_reservedSpace));
258
+ }
255
259
}
256
260
257
261
private:
258
262
// allocate and get the address of the next free node
259
263
inline uint32_t reserveAddress ()
260
264
{
261
- uint32_t addr = m_addressAllocator-> alloc_addr (1u , 1u );
265
+ uint32_t addr = m_addressAllocator. alloc_addr (1u , 1u );
262
266
return addr;
263
267
}
264
268
@@ -301,7 +305,7 @@ class DoublyLinkedList
301
305
if (m_dispose_f)
302
306
m_dispose_f (get (address)->data );
303
307
get (address)->~node_t ();
304
- m_addressAllocator-> free_addr (address, 1u );
308
+ m_addressAllocator. free_addr (address, 1u );
305
309
}
306
310
307
311
inline void common_detach (node_t * node)
@@ -312,7 +316,8 @@ class DoublyLinkedList
312
316
get (node->prev )->next = node->next ;
313
317
}
314
318
315
- std::unique_ptr<address_allocator_t > m_addressAllocator;
319
+ allocator_t m_allocator;
320
+ address_allocator_t m_addressAllocator;
316
321
void * m_reservedSpace;
317
322
node_t * m_array;
318
323
0 commit comments