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