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