ALib C++ Library
Library Version: 2511 R0
Documentation generated by doxygen
Loading...
Searching...
No Matches
recycling.inl
Go to the documentation of this file.
1//==================================================================================================
2/// \file
3/// This header-file is part of module \alib_containers of the \aliblong.
4///
5/// \emoji :copyright: 2013-2025 A-Worx GmbH, Germany.
6/// Published under \ref mainpage_license "Boost Software License".
7//==================================================================================================
8ALIB_EXPORT namespace alib { namespace containers {
9
10//==================================================================================================
11/// This enumeration contains three elements, which denote the type of node-recycling that a
12/// container instantiation is deemed to perform. One of these elements is to be set as the value
13/// for a corresponding template parameter named \p{TRecycling} found in container types
14/// of this module.
15///
16/// In the case \b Shared is given, the container type will expose a type definition named
17/// \b SharedRecyclerType, which can be used to define the external shared recycler object.
18/// This object has then to be passed to the constructor of the container instance.
19///
20/// \see
21/// Chapter \ref alib_contmono_intro_recycling of the Programmer's Manual
22/// for this \alibmod.
23//==================================================================================================
24enum class Recycling
25{
26 None , ///<< Denotes that no recycling should be performed.
27 Private, ///<< Denotes private recycling. This is usaully the default value.
28 Shared , ///<< Denotes shared recycling.
29};
30
31
32} // namespace alib[::containers]
33
34/// Type alias in namespace \b alib.
36
37} // namespace [alib]
38
41
42/// Stores an element for recycling.
43/// @param recyclables The recycling stack.
44/// @param elem The element to recycle.
45template<typename TNode>
46void recycleImpl( lang::SidiListHook<TNode>& recyclables, TNode* elem )
47{
48 lang::Destruct(*elem);
49 recyclables.pushFront( elem );
50}
51
52
53/// Stores a list of elements for recycling (from the \p{begin} element to the last one).
54/// @param recyclables The recycling stack.
55/// @param begin The first element of the list store, must not be \c nullptr.
56template<typename TNode>
57void recycleListImpl( lang::SidiListHook<TNode>& recyclables, TNode* begin ) {
58 TNode* actual = begin;
59 for (;;) {
60 TNode* next= actual->next();
61 lang::Destruct(*actual);
62 if (next == nullptr)
63 break;
64 actual= next;
65 }
66
67 recyclables.pushFront( begin, actual );
68}
69
70/// Stores a list of elements for recycling. Both given nodes have to exist.
71/// @param recyclables The recycling stack.
72/// @param begin The first element of the list store.
73/// @param end The first element not to be recycled.
74/// @return A pair of values. The first is a pointer to the last node recycled, and the second
75/// provides the number of nodes recycled.
76template<typename TNode>
77std::pair<TNode*,integer> recycleListImpl( lang::SidiListHook<TNode>& recyclables,
78 TNode* begin, TNode* end ) {
79 std::pair<TNode*,integer> result;
80 result.second= 1;
81 result.first = begin;
82 for (;;) {
83 TNode* next= result.first->next();
84 lang::Destruct(*result.first);
85 if (next == end)
86 break;
87 ++result.second;
88 result.first= next;
89 }
90
91 recyclables.pushFront( begin, result.first );
92 return result;
93}
94
95/// Reserves the given \p{qty} of recyclables. If the allocator used returns \c true with
96/// method \alib{lang::Allocator;allowsMemSplit} (like like \b MonoAllocator does), then one
97/// chunk is allocated and cut into pieces.<br>
98/// Otherwise, common allocations are performed
99/// @param allocator The allocator to use.
100/// @param recyclables The recycling stack.
101/// @param qty The quantity of elements to reserve.
102template<typename TAllocator, typename TNode>
103void reserveImpl( TAllocator& allocator, lang::SidiListHook<TNode>& recyclables, integer qty ) {
104 if (qty <= 0)
105 return;
106
107 if constexpr ( TAllocator::allowsMemSplit() ) {
108 TNode* newElements= allocator().template AllocArray<TNode>(qty);
109 for( integer i= qty - 2; i >= 0 ; --i )
110 newElements[i].next( &newElements[i + 1] );
111
112 recyclables.pushFront( &newElements[0], &newElements[qty-1] );
113 } else {
114 TNode* start= allocator().template Alloc<TNode>();
115 TNode* end = start;
116 for( integer i= 1; i < qty ; ++i ) {
117 end->next( allocator().template Alloc<TNode>() );
118 end= end->next();
119 }
120 recyclables.pushFront( start, end );
121} }
122
123/// Frees an element (no recycling).
124/// @param allocator The allocator to use.
125/// @param elem The element to recycle.
126template<typename TAllocator, typename TNode>
127void disposeImpl( TAllocator& allocator, TNode* elem )
128{
129 lang::Destruct(*elem);
130 allocator().Free(elem);
131}
132
133
134/// Deletes the given list.
135/// This shared recycler does not free the node, but recycles them.
136/// @param allocator The allocator to use.
137/// @param begin The first element of the list to free.
138template<typename TAllocator, typename TNode>
139void disposeListImpl( TAllocator& allocator, TNode* begin ) {
140 TNode* actual = begin;
141 for (;;) {
142 TNode* next= actual->next();
143 lang::Destruct(*actual);
144 allocator().Free(actual);
145 if (next == nullptr)
146 return;
147 actual= next;
148} }
149
150/// Deletes a list of elements for recycling. Both given nodes have to exist.
151/// @param allocator The allocator to use.
152/// @param begin The first element of the list to free.
153/// @param end The first element not to be freed.
154/// @return A pair of values. The first is a pointer to the last node deleted, and the second
155/// provides the number of nodes deleted.
156template<typename TAllocator, typename TNode>
157std::pair<TNode*,integer> disposeListImpl( TAllocator& allocator, TNode* begin, TNode* end ) {
158 std::pair<TNode*,integer> result;
159 result.second= 1;
160 result.first= begin;
161 for (;;) {
162 TNode* next= result.first->next();
163 lang::Destruct(*result.first);
164 allocator().Free(result.first);
165 if (next == end)
166 return result;
167 ++result.second;
168 result.first= next;
169} }
170
171/// Recycles a chunk of memory that is \e not of the node type.
172/// Such recycling is useful for example, in combination with hash tables, which usually
173/// allocate a "bucket array" that grows over time. In this case, the former smaller bucket
174/// array may be passed to this method to recycle it as future node elements.
175/// @tparam TChunk The type of the external chunk.
176/// @param recyclables The recycling stack.
177/// @param chunk The recyclable chunk's address.
178/// @param count The number of objects. (For non-array types, \c 1 is to be given.)
179template<typename TNode, typename TChunk>
180void recycleChunkImpl( lang::SidiListHook<TNode>& recyclables, TChunk* chunk, size_t count ) {
181 void* mem = chunk;
182 size_t size= sizeof(TChunk[1]) * count;
183
184 // align beginning of buffer (if necessary)
185 if constexpr( alignof(TNode) > alignof(TChunk[1]) ) {
186 mem = reinterpret_cast<void*>((size_t(chunk) + alignof(TNode) - 1) & ~(alignof(TNode) -1));
187 size-= size_t(reinterpret_cast<char*>(mem) - reinterpret_cast<char*>(chunk));
188 }
189
190 // create recyclables
191 ALIB_DBG( size_t cntRecycledObjects= 0; )
192 while(size > sizeof(TNode)) {
193 recyclables.pushFront( reinterpret_cast<TNode*>( mem ) );
194 mem = reinterpret_cast<char*>(mem) + sizeof(TNode);
195 size -= sizeof (TNode);
196 ALIB_DBG( ++cntRecycledObjects; )
197 }
198
199 #if ALIB_DEBUG
200 if( cntRecycledObjects <= 0 ) {
201 ALIB_WARNING( "MONOMEM/RECYCLER",
202 "De-allocated chunk size is smaller than node size.\n"
203 " Chunk object: Type: <{}>\n"
204 " Size, Count, Alignment: {} * {} = {} bytes, alignment: {}\n"
205 " Recyclable Type: <{}>\n"
206 " Size, Alignment: {} bytes, alignment: {}\n"
207 "Note: If this recycler is used with a <containers::HashTable>, this message may be\n"
208 " eliminated by reserving a reasonable initial bucket size.",
209 &typeid(TChunk), sizeof(TChunk[1]), count, sizeof(TChunk[1]) * count,
210 alignof(TChunk[1]), &typeid(TNode), sizeof(TNode), alignof(TNode) )
211 }
212 #endif
213}
214
215#include "ALib.Lang.CIMethods.H"
216
217/// Implements internal recycling interface. Used by container types of module \alib_containers_nl that
218/// use private recycling (when \b their template parameter \p{TRecycling} evaluates to
219/// \alib{containers;Recycling;Private}).
220///
221/// @tparam TAllocator The allocator to store and use.
222/// @tparam TNode The type to recycle. Has to be derived of \alib{lang::SidiNodeBase}.
223template<typename TAllocator, typename TNode>
225{
226 protected:
227 /// The base type.
229
230 /// The list of recyclables.
232
233 public:
234 /// Parameterless constructor. Used with type \b HeapAllocator.
235 RecyclerPrivate() noexcept =default;
236
237 /// Constructor taking an allocator.
238 /// @param pAllocator The allocator to use.
239 explicit
240 RecyclerPrivate( TAllocator& pAllocator ) noexcept
241 : base( pAllocator ) {}
242
243 /// Copy constructor. Does not copy the recycle node, but clears this one.
244 /// @param copy The object to copy.
245 RecyclerPrivate( const RecyclerPrivate& copy ) noexcept
246 : base( copy ) {}
247
248 /// Move constructor. Grabs the recyclables from the moved one and sets moved to nulled.
249 /// @param move The private recycler to move.
251 : base( move )
252 , recyclables(move) { move.recyclables.reset(); }
253
254 /// Destructor. Frees all recyclables with the allocator.
255 ~RecyclerPrivate() noexcept {
256 TNode* actual = recyclables.first();
257 while (actual) {
258 TNode* next= actual->next();
259 base::AI().Free(actual);
260 actual= next;
261 } }
262
263 /// Resets this recycler. Frees all recyclables with the allocator.
264 void Reset() noexcept {
265 if(recyclables.first()) {
267 recyclables.reset();
268 } }
269
270 /// @return Returns the allocator received with construction.
271 TAllocator& GetAllocator() const noexcept { return base::GetAllocator(); }
272
273 /// @return The allocator interface of the allocator received with construction.
275
276 /// @return Returns \c true to indicate that this is not a non-recycling version.
277 static constexpr bool IsRecycling() noexcept { return true; }
278
279 /// Counts the number of recyclables.<br>
280 /// Attention: This method runs in linear time.
281 /// @return The number of available elements.
282 [[nodiscard]]
283 integer Count() const noexcept { return recyclables.count(); }
284
285
286 /// Reserves the given number of recyclables.
287 /// @param qty The number of new recyclables to allocate.
288 void Reserve( integer qty ) noexcept { reserveImpl( base::GetAllocator(), recyclables, qty); }
289
290 /// Returns a recycled object or allocates a new one.
291 /// @return A recycled or allocated element.
292 [[nodiscard]]
293 TNode* Get() {
294 return !recyclables.isEmpty() ? recyclables.popFront()
295 : base::AI().template Alloc<TNode>();
296 }
297
298 /// Stores an element for recycling.
299 /// @param elem The element to store.
300 void Recycle( TNode* elem ) noexcept { recycleImpl( recyclables, elem ); }
301
302 /// Stores a list of elements for recycling (from the \p{begin} element to the last one).
303 /// @param begin The first element of the list store, must not be \c nullptr.
304 void RecycleList( TNode* begin ) noexcept { recycleListImpl( recyclables, begin ); }
305
306 /// Stores a list of elements for recycling. Both given nodes have to exist.
307 /// @param begin The first element of the list to recycle.
308 /// @param end The first element not to be recycled.
309 /// @return A pair of values. The first is a pointer to the last node recycled, and the second
310 /// provides the number of nodes recycled.
311 std::pair<TNode*, integer> RecycleList(TNode* begin, TNode* end) noexcept
312 { return recycleListImpl( recyclables, begin, end ); }
313
314 /// Deletes the given list.
315 /// This shared recycler does not free the node, but recycles them.
316 /// @param begin The first element of the list to free.
317 void DisposeList( TNode* begin ) noexcept { disposeListImpl( base::GetAllocator(), begin ); }
318
319 /// Deletes a list of elements for recycling. Both given nodes have to exist.
320 /// @param begin The first element of the list to free.
321 /// @param end The first element not to be freed.
322 void DisposeList( TNode* begin, TNode* end ) noexcept
323 { disposeListImpl( base::GetAllocator(), begin, end ); }
324
325
326 /// Converts a given chunk of memory, previously allocated with the same allocator that
327 /// this type uses, into recyclable node objects.<br>
328 /// This is only done if \alib{lang;Allocator::allowsMemSplit} returns \c true.
329 /// @tparam TChunk The type of array that is to be cut into node elements.
330 /// @param chunk The chunk array to convert into nodes
331 /// @param length The length of the chunk array (pass \c 1 if the chunk is not an array type).
332 template<typename TChunk>
333 void RecycleChunk(TChunk* chunk, size_t length ) noexcept {
334 if constexpr ( TAllocator::allowsMemSplit() )
335 recycleChunkImpl( recyclables, chunk, length );
336 else
337 #if !defined(__MINGW32__)
338 base::AI().FreeArray(chunk, length );
339 #else
340 base::AI().template FreeArray(chunk, length );
341 #endif
342 }
343
344 /// Frees the given memory. Note that the shared recycler calls #RecycleChunk with this method.
345 /// @tparam TChunk The type of array that is to be freed.
346 /// @param chunk The chunk array to convert into nodes
347 /// @param length The length of the chunk array (pass \c 1 if the chunk is not an array type).
348 template<typename TChunk>
349 void DisposeChunk(TChunk* chunk, size_t length ) noexcept {
350 #if !defined(__MINGW32__)
351 base::AI().FreeArray(chunk, length );
352 #else
353 base::AI().template FreeArray(chunk, length );
354 #endif
355 }
356};
357
358/// This is the type exposed to users of the \alib containers in case shared recycling is
359/// chosen, for example, with \alib{containers;List::SharedRecyclerType} or
360/// \alib{containers;HashTable::SharedRecyclerType}.<br>
361/// A user has to pass an instance of this type to the constructor of the container.
362/// Constructors that accept this type do not accept an allocator instance, as this is embedded
363/// already here.
364/// @tparam TAllocator The allocator to store and use.
365/// @tparam TNode The node type to recycle.
366template<typename TAllocator, typename TNode>
367class SharedRecycler : public lang::AllocatorMember<TAllocator>
368 , protected lang::SidiListHook<TNode>
369{
370 protected:
371 template<typename TAllocator1, typename TNode1>
372 friend class RecyclerShared;
373
374 /// Shortcut to a base class.
376
377 /// Shortcut to a base class.
379
380
381 public:
382 /// Constructor taking no allocator, used with \b %HeapAllocator.
383 SharedRecycler () noexcept
384 : lang::AllocatorMember<TAllocator>() {}
385
386 /// Constructor taking an allocator.
387 /// @param pAllocator The allocator to use.
388 SharedRecycler ( TAllocator& pAllocator ) noexcept
389 : allocBase( pAllocator ) {}
390
391 /// Destructor. Deletes all recyclables with the allocator.
392 ~SharedRecycler() noexcept { Reset(); }
393
394 /// Reset. Deletes all recyclables with the allocator.
395 void Reset() noexcept {
396 TNode* actual = this->first();
397 while (actual) {
398 TNode* next= actual->next();
399 allocBase::AI().Free(actual);
400 actual= next;
401 }
402 this->reset();
403 }
404
405 /// Counts the number of recyclables.
406 /// @return The number of recycled container elements available.
407 integer Count() const noexcept { return this->count(); }
408
409 /// Reserves space for at least the given number of recyclables.
410 /// @param qty The expected number or increase of elements to be stored in the containers
411 /// that share this recycler.
412 /// @param reference Denotes whether \p{expected} is meant as an absolute size or an increase .
413 void Reserve( integer qty, lang::ValueReference reference ) {
414 auto requiredRecyclables= ( qty - (reference == lang::ValueReference::Absolute ? Count()
415 : 0 ) );
416
417 if( requiredRecyclables > 0 )
418 reserveImpl( allocBase::GetAllocator(), *this, requiredRecyclables );
419 }
420};
421
422/// Implements internal recycling interface. Used by container types of module \alib_containers_nl that
423/// use shared recycling (when \b their template parameter \p{TRecycling} evaluates to
424/// \alib{containers;Recycling;Shared}).
425///
426/// @tparam TAllocator The allocator to store and use.
427/// @tparam TNode The type to recycle. Has to be derived of \alib{lang::SidiNodeBase}.
428template<typename TAllocator, typename TNode>
430{
431 protected:
432 /// The reference to the list of recyclables.
434
435 public:
436
437 /// Constructor taking an allocator and the hook.
438 /// @param hook The external, shared recycling list.
440 : sr(hook) {}
441
442
443 /// Copy constructor. Copies the reference to the shared recycler.
444 /// @param copy The private recycler to copy.
445 RecyclerShared( const RecyclerShared& copy ) noexcept =default;
446
447 /// Move constructor. Just copies the reference but leaves original intact. (We don't care)
448 /// @param move The private recycler to move.
450 : sr(move.sr) {}
451
452 /// Destructor.
453 ~RecyclerShared() noexcept {}
454
455 /// Does nothing. Shared recyclers can't be reset.
456 void Reset() noexcept {}
457
458 /// @return Returns the allocator received with construction.
459 TAllocator& GetAllocator() const noexcept { return sr.GetAllocator(); }
460
461 /// @return The allocator interface of the allocator received with construction.
462 lang::AllocatorInterface<TAllocator> AI() const noexcept { return sr.GetAllocator()(); }
463
464
465 /// @return Returns \c true to indicate that this is not a non-recycling version.
466 static constexpr bool IsRecycling() noexcept { return true; }
467
468 /// Counts the number of recyclables.<br>
469 /// Attention: This method runs in linear time.
470 /// @return The number of available elements.
471 [[nodiscard]]
472 integer Count() const noexcept { return sr.count(); }
473
474 /// Reserves the given number of recyclables.
475 /// @param qty The number of new recyclables to allocate.
476 void Reserve( integer qty ) { reserveImpl( sr.GetAllocator(), sr, qty); }
477
478 /// Returns a recycled object or allocates a new one.
479 /// @return A recycled or allocated element.
480 [[nodiscard]]
481 TNode* Get() { return !sr.isEmpty() ? sr.popFront() : sr.AI().template Alloc<TNode>(); }
482
483 /// Stores an element for recycling.
484 /// @param elem The element to store.
485 void Recycle( TNode* elem ) noexcept { recycleImpl( sr, elem ); }
486
487 /// Stores a list of elements for recycling (from the \p{begin} element to the last one).
488 /// @param begin The first element of the list store, must not be \c nullptr.
489 void RecycleList( TNode* begin ) noexcept { recycleListImpl( sr, begin ); }
490
491 /// Stores a list of elements for recycling. Both given nodes have to exist.
492 /// @param begin The first element of the list to recycle.
493 /// @param end The first element not to be recycled.
494 /// @return A pair of values. The first is a pointer to the last node recycled, and the second
495 /// provides the number of nodes recycled.
496 std::pair<TNode*, integer> RecycleList(TNode* begin, TNode* end) noexcept
497 { return recycleListImpl( sr, begin, end ); }
498
499 /// Does not free, but recycles instead.
500 /// @param begin The first element of the list to free.
501 void DisposeList( TNode* begin ) noexcept { recycleListImpl( sr, begin ); }
502
503 /// Does not free, but recycles instead.
504 /// @param begin The first element of the list to free.
505 /// @param end The first element not to be freed.
506 void DisposeList( TNode* begin, TNode* end ) noexcept { recycleListImpl( sr, begin, end ); }
507
508 /// Converts a given chunk of memory, previously allocated with the same allocator that
509 /// this type uses, into recyclable node objects.<br>
510 /// This is only done if \alib{lang;Allocator::allowsMemSplit} returns \c true.
511 /// @tparam TChunk The type of array that is to be cut into node elements.
512 /// @param chunk The chunk array to convert into nodes
513 /// @param length The length of the chunk array (pass \c 1 if the chunk is not an array type).
514 template<typename TChunk>
515 void RecycleChunk(TChunk* chunk, size_t length ) noexcept {
516 if constexpr ( TAllocator::allowsMemSplit() )
517 recycleChunkImpl( sr, chunk, length );
518 else
519 sr.AI().FreeArray(chunk, length );
520 }
521
522 /// This shared recycler calls #RecycleChunk with this method.
523 /// @tparam TChunk The type of array that is to be freed.
524 /// @param chunk The chunk array to convert into nodes
525 /// @param length The length of the chunk array (pass \c 1 if the chunk is not an array type).
526 template<typename TChunk>
527 void DisposeChunk(TChunk* chunk, size_t length ) noexcept { RecycleChunk( chunk, length ); }
528};
529
530
531/// Implements internal recycling interface. Used by container types of module \alib_containers_nl
532/// that omit recycling (when \b their template parameter \p{TRecycling} evaluates to
533/// \alib{containers;Recycling;None}).
534///
535/// @tparam TAllocator The allocator to store and use.
536/// @tparam TNode The type to recycle. Has to be derived of \alib{lang::SidiNodeBase}.
537template<typename TAllocator, typename TNode>
539{
540 protected:
541 /// The base type.
543
544 public:
545 /// Parameterless constructor. Used with type \b HeapAllocator.
547
548 /// Defaulted default constructor.
549 /// @param pAllocator The allocator to use.
550 RecyclerVoid( TAllocator& pAllocator ) noexcept
551 : base( pAllocator ) {}
552
553 /// Does nothing. Shared recyclers can't be reset.
554 void Reset() noexcept {}
555
556 /// @return Returns \c false to indicate that this is a non-recycling version.
557 static constexpr bool IsRecycling() noexcept { return false; }
558
559 /// This recycler just returns \c 0.
560 /// Attention: With other implementations, this method may run in linear time.
561 /// @return \c 0, which in this case is always the number of available elements.
562 [[nodiscard]]
563 constexpr integer Count() const noexcept { return 0; }
564
565 /// Does nothing. In debug-compilations a \ref alib_mod_assert "warning is raised".
566 void Reserve( integer ) noexcept
567 { ALIB_WARNING("MONOMEM","Requested reservation of recyclables with non-recycling container.") }
568
569 /// Allocates a new one.
570 /// @return An allocated element.
571 [[nodiscard]]
572 TNode* Get() { return base::AI().template Alloc<TNode>(); }
573
574 /// Frees an element.
575 /// @param elem The element to store.
576 void Recycle( TNode* elem ) noexcept { disposeImpl( base::GetAllocator(), elem ); }
577
578 /// Frees the list.
579 /// @param begin The first element of the list store, must not be \c nullptr.
580 void RecycleList( TNode* begin ) noexcept { disposeListImpl( base::GetAllocator(), begin ); }
581
582 /// Frees the list (as this is a non-recycling recycler).
583 /// @param begin The first element of the list recycled.
584 /// @param end The first element not to be recycled.
585 /// @return A pair of values. The first is a pointer to the last node deleted, and the second
586 /// provides the number of nodes deleted.
587 std::pair<TNode*, integer> RecycleList( TNode* begin, TNode* end ) noexcept
588 { return disposeListImpl( base::GetAllocator(), begin, end ); }
589
590
591 /// Deletes a list of elements (from the \p{begin} element to the last one).
592 /// @param begin The first element of the list recycle, must not be \c nullptr.
593 void DisposeList( TNode* begin ) noexcept { disposeListImpl( base::GetAllocator(), begin ); }
594
595 /// Deletes a list of elements for recycling. Both given nodes have to exist.
596 /// @param begin The first element of the list to free.
597 /// @param end The first element not to be freed.
598 /// @return A pair of values. The first is a pointer to the last node deleted, and the second
599 /// provides the number of nodes deleted.
600 std::pair<TNode*, integer> DisposeList( TNode* begin, TNode* end ) noexcept
601 { return disposeListImpl( base::GetAllocator(), begin, end ); }
602
603 /// With other recyclers, this method
604 /// converts a given chunk of memory, previously allocated with the same allocator that
605 /// this type uses, into recyclable node objects.<br>
606 /// This recycler just frees the object.
607 /// @tparam TChunk The type of array that is to be cut into node elements.
608 /// @param chunk The chunk array to convert into nodes
609 /// @param length The length of the chunk array (pass \c 1 if the chunk is not an array type).
610 template<typename TChunk>
611 constexpr void RecycleChunk( TChunk* chunk, size_t length ) noexcept {
612 #if !defined(__MINGW32__)
613 base::AI().FreeArray(chunk, length );
614 #else
615 base::AI().template FreeArray(chunk, length );
616 #endif
617 }
618
619 /// Frees the given memory. Note that the shared recycler calls #RecycleChunk with this method.
620 /// @tparam TChunk The type of array that is to be freed.
621 /// @param chunk The chunk array to convert into nodes
622 /// @param length The length of the chunk array (pass \c 1 if the chunk is not an array type).
623 template<typename TChunk>
624 void DisposeChunk(TChunk* chunk, size_t length ) noexcept {
625 #if !defined(__MINGW32__)
626 base::AI().FreeArray(chunk, length );
627 #else
628 base::AI().template FreeArray(chunk, length );
629 #endif
630 }
631
632}; // struct RecyclerVoid
633
634/// Helper-struct that chooses the right recycler type depending on template parameter
635/// \p{TRecycling}. Specializations exists for each element in enumeration
636/// \alib{containers;Recycling}.
637/// @tparam TRecycling The sort of recycling, as given with template parameter of container types
638/// with the same name.
639template<Recycling TRecycling>
641{
642 #if DOXYGEN
643 /// The type chosen.
644 using Type= void;
645
646 /// The hook type. Only used with shared recycling, otherwise <c>void</c>.
647 using HookType= void;
648 #endif
649};
650#if !DOXYGEN
651template<>
653{
654 template<typename TAllocator, typename TNode> using Type= RecyclerPrivate<TAllocator, TNode>;
655 template<typename TAllocator, typename TNode> using HookType= void;
656};
657
658template<> struct RecyclingSelector<Recycling::Shared>
659{
660 template<typename TAllocator, typename TNode> using Type = RecyclerShared<TAllocator, TNode>;
661 template<typename TAllocator, typename TNode> using HookType= SharedRecycler<TAllocator, TNode>;
662};
663
664template<> struct RecyclingSelector<Recycling::None>
665{
666 template<typename TAllocator, typename TNode> using Type= RecyclerVoid<TAllocator, TNode>;
667 template<typename TAllocator, typename TNode> using HookType= void;
668};
669#endif
670
671#include "ALib.Lang.CIMethods.H"
672} // namespace [alib::containers::detail]
static constexpr bool IsRecycling() noexcept
std::pair< TNode *, integer > RecycleList(TNode *begin, TNode *end) noexcept
void DisposeList(TNode *begin) noexcept
void RecycleList(TNode *begin) noexcept
lang::AllocatorInterface< TAllocator > AI() const noexcept
RecyclerShared(SharedRecycler< TAllocator, TNode > &hook) noexcept
void DisposeChunk(TChunk *chunk, size_t length) noexcept
void DisposeList(TNode *begin, TNode *end) noexcept
SharedRecycler< TAllocator, TNode > & sr
The reference to the list of recyclables.
void RecycleChunk(TChunk *chunk, size_t length) noexcept
RecyclerShared(RecyclerShared &&move) noexcept
void Reset() noexcept
Does nothing. Shared recyclers can't be reset.
void Recycle(TNode *elem) noexcept
TAllocator & GetAllocator() const noexcept
RecyclerShared(const RecyclerShared &copy) noexcept=default
SharedRecycler(TAllocator &pAllocator) noexcept
~SharedRecycler() noexcept
Destructor. Deletes all recyclables with the allocator.
lang::SidiListHook< TNode > hookBase
Shortcut to a base class.
void Reset() noexcept
Reset. Deletes all recyclables with the allocator.
void Reserve(integer qty, lang::ValueReference reference)
SharedRecycler() noexcept
Constructor taking no allocator, used with HeapAllocator.
lang::AllocatorMember< TAllocator > allocBase
Shortcut to a base class.
#define ALIB_WARNING(domain,...)
Definition alib.inl:1063
#define ALIB_EXPORT
Definition alib.inl:497
#define ALIB_DBG(...)
Definition alib.inl:853
Detail namespace of module ALib Containers.
void reserveImpl(TAllocator &allocator, lang::SidiListHook< TNode > &recyclables, integer qty)
void recycleListImpl(lang::SidiListHook< TNode > &recyclables, TNode *begin)
Definition recycling.inl:57
void disposeListImpl(TAllocator &allocator, TNode *begin)
void recycleImpl(lang::SidiListHook< TNode > &recyclables, TNode *elem)
Definition recycling.inl:46
void recycleChunkImpl(lang::SidiListHook< TNode > &recyclables, TChunk *chunk, size_t count)
void disposeImpl(TAllocator &allocator, TNode *elem)
@ Private
< Denotes private recycling. This is usaully the default value.
Definition recycling.inl:27
@ None
< Denotes that no recycling should be performed.
Definition recycling.inl:26
@ Shared
< Denotes shared recycling.
Definition recycling.inl:28
void Destruct(T &object)
Definition tmp.inl:82
ValueReference
Denotes if a value is interpreted as an absolute or relative number.
@ Absolute
Referring to an absolute value.
lang::integer integer
Type alias in namespace alib.
Definition integers.inl:149
containers::Recycling Recycling
Type alias in namespace alib.
Definition recycling.inl:35
void Reset() noexcept
Resets this recycler. Frees all recyclables with the allocator.
void DisposeList(TNode *begin, TNode *end) noexcept
void DisposeList(TNode *begin) noexcept
lang::AllocatorMember< TAllocator > base
The base type.
void DisposeChunk(TChunk *chunk, size_t length) noexcept
std::pair< TNode *, integer > RecycleList(TNode *begin, TNode *end) noexcept
RecyclerPrivate() noexcept=default
Parameterless constructor. Used with type HeapAllocator.
void Recycle(TNode *elem) noexcept
lang::AllocatorInterface< TAllocator > AI() const noexcept
void RecycleChunk(TChunk *chunk, size_t length) noexcept
~RecyclerPrivate() noexcept
Destructor. Frees all recyclables with the allocator.
TAllocator & GetAllocator() const noexcept
lang::SidiListHook< TNode > recyclables
The list of recyclables.
void Reserve(integer qty) noexcept
void RecycleList(TNode *begin) noexcept
RecyclerPrivate(RecyclerPrivate &&move) noexcept
static constexpr bool IsRecycling() noexcept
RecyclerPrivate(const RecyclerPrivate &copy) noexcept
lang::AllocatorMember< TAllocator > base
The base type.
std::pair< TNode *, integer > RecycleList(TNode *begin, TNode *end) noexcept
void DisposeList(TNode *begin) noexcept
void RecycleList(TNode *begin) noexcept
std::pair< TNode *, integer > DisposeList(TNode *begin, TNode *end) noexcept
RecyclerVoid()
Parameterless constructor. Used with type HeapAllocator.
void Reset() noexcept
Does nothing. Shared recyclers can't be reset.
void DisposeChunk(TChunk *chunk, size_t length) noexcept
constexpr void RecycleChunk(TChunk *chunk, size_t length) noexcept
void Recycle(TNode *elem) noexcept
void Reserve(integer) noexcept
Does nothing. In debug-compilations a warning is raised.
RecyclerVoid(TAllocator &pAllocator) noexcept
constexpr integer Count() const noexcept
static constexpr bool IsRecycling() noexcept
void HookType
The hook type. Only used with shared recycling, otherwise void.
AllocatorInterface< TAllocator > AI() const noexcept
TAllocator & GetAllocator() const noexcept
void reset() noexcept
Resets this list to zero elements.
Definition sidilist.inl:213
TNode * first() const noexcept
Definition sidilist.inl:218
void pushFront(TElement *elem) noexcept
Definition sidilist.inl:222
SidiNodeBase< TNode > TNode
Definition sidilist.inl:183
integer count(TNode *end=nullptr) const noexcept
Definition sidilist.inl:305
void next(SidiNodeBase *p)
Definition sidilist.inl:95