ALib C++ Library
Library Version: 2402 R1
Documentation generated by doxygen
Loading...
Searching...
No Matches
stdcontainerma.hpp
Go to the documentation of this file.
1/** ************************************************************************************************
2 * \file
3 * This header file is part of module \alib_monomem 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_STDCONTAINERMA
9#define HPP_ALIB_MONOMEM_STDCONTAINERMA
10
11#if !defined(HPP_ALIB_MONOMEM_UTIL_RTTRALLOCATOR)
13#endif
14
15#if !defined(HPP_ALIB_LANG_SIDILIST)
16# include "alib/lang/sidilist.hpp"
17#endif
18
19namespace alib { namespace monomem {
20namespace detail {
21
22/** ************************************************************************************************
23 * Base struct for types \alib{monomem;StdContMA} and
24 * \alib{monomem;StdContMARecycling} containing entities to satisfy requirements for being a
25 * <c>std::allocator</c>.
26 *
27 * @tparam T The type of objects to be allocated.
28 **************************************************************************************************/
29template<typename T>
31{
32 // #############################################################################################
33 // ### Type definitions
34 // #############################################################################################
35 using size_type = size_t ; ///< Type definition as required by C++ library standards.
36 using difference_type= ptrdiff_t ; ///< Type definition as required by C++ library standards.
37 using value_type = T ; ///< Type definition as required by C++ library standards.
38 using is_always_equal= std::false_type; ///< Type definition as required by C++ library standards.
39
40 // #############################################################################################
41 // ### Other required members
42 // #############################################################################################
43 #if ALIB_CPP_STANDARD == 17 || defined(ALIB_DOX)
44 /**
45 * The possible allocation size.
46 * Note: Available only if <b>ALIB_CPP_STANDARD == 17, as it was deprecated afterwards.</b>.
47 * @return returns the largest supported allocation size.
48 */
49 size_t max_size() const noexcept
50 {
51 return static_cast<size_t>(-1) / 2;
52 }
53 #endif
54}; // struct StdContainerMABase
55
56} // namespace alib::monomem[::detail]
57
58
59/** ************************************************************************************************
60 * Implementation of <c>std::allocator</c> to be used with container types provided by the
61 * C++ standard library.
62 *
63 * This allocator is suitable to use cases of
64 * \ref alib_monomem_intro_strictweak "strict or weak monotonic allocation".
65 * An alternative version that recycles nodes (and for example bucket arrays in case of
66 * <c>std::unordered_set</c> and <c>std::unordered_map</c>), is provided with sibling type
67 * \alib{monomem;StdContMARecycling}.
68 *
69 * A further alternative is given with type \alib{monomem;StdContMAOptional}, which accepts a
70 * pointer instead of a reference to an allocator and allows this pointer to be \c nullptr, which
71 * switches to dynamic allocation.
72 *
73 *
74 * \anchor alib_ns_monomem_StdContMA_reset
75 * ### Resetting A Container ###
76 * While the dedicated container types provided with this \alibmod_nl offer a method named \b Reset
77 * (see for example \alib{monomem;HashTable::Reset}), the C++ \b std containers of-course do not.
78 * This is a challenge, because their internal memory will be invalid with a reset of the
79 * monotonic allocator used, and for example with class <c>std::vector</c> there is no interface
80 * method that makes them "forget" their internal data array. Its method <c>shrink_to_fit</c>
81 * by its specification is not forced to shrink anything or even dispose the data if the size
82 * was \c 0 when called. This is implementation dependent.
83 *
84 * The way out is as simple as radical: The container is just to be reconstructed without
85 * prior destruction. This can be done using a <em>C++ placement new</em>. The following
86 * code snippet demonstrates this:
87 * \snippet "ut_alib_monomem_monomem.cpp" DOX_ALIB_MONOMEM_STDCONTMA_PLACEMENT_NEW
88 *
89 *
90 * @tparam T The type of objects to be allocated.
91 **************************************************************************************************/
92template<typename T>
94{
95 // #############################################################################################
96 // ### Fields
97 // #############################################################################################
98 /** The allocator to use. */
100
101 #if ALIB_DEBUG
102 /** If \c true warnings about de-allocation of objects are suppressed. this should be set
103 * prior to destructing a container that uses this allocator. <br>
104 * Available only in debug builds. */
106 #endif
107
108 // #############################################################################################
109 // ### Construction/Destruction
110 // #############################################################################################
111 /** Default constructor declared, but not defined.
112 *
113 * \attention
114 * Due to the way standard container types use template struct <c>std::allocator</c>) that
115 * this object implements, the default constructor has to be declared. However, because
116 * field #allocator is of reference type, no declaration can be made.<br>
117 * With the construction of a container type that uses this allocator, it has to be assured
118 * that a valid instance is passed. Otherwise the compiler will complain about not
119 * finding this constructor's definition.
120 */
121 inline
123
124
125 /** Defaulted copy constructor */
126 constexpr StdContMA( const StdContMA& ) noexcept =default;
127
128 /** Defaulted move constructor */
129 constexpr StdContMA( StdContMA&& ) noexcept =default;
130
131 /**
132 * Copy constructor using an instance of different template type.
133 * @tparam TSibling The originating allocator's type (<b>StdContMA<X></b>).
134 * @param origin The originating allocator of type \p{TSibling} .
135 */
136 template<typename TSibling>
137 StdContMA( TSibling& origin)
138 : allocator(origin.allocator)
140 {}
141
142#if defined(ALIB_DOX)
143 /**
144 * Constructor for the initial allocator instantiation.
145 *
146 * Parameter \p{dbgDisableDeallocationWarning}, which defaults to \c true might be given
147 * after a code is tested to be stict in respect to allocation.
148 * (Note: unfortunately, due to the ^design of <c>std::allocator</c> and its use, this flag can
149 * not be changed once a container is constructed. This is why it has to be decided upfront
150 * if a warning is to be raised or not). ^
151 *
152 * @param pAllocator The recycler for allocations and de-allocations.
153 * @param dbgDeallocationWarning As described with this method. Available only in debug builds.
154 */
155 constexpr StdContMA( MonoAllocator& pAllocator,
156 bool dbgDeallocationWarning= true );
157#else
158 constexpr StdContMA( MonoAllocator& pAllocator ALIB_DBG(, bool dbgDAWarning= false) )
159 : allocator(pAllocator)
160ALIB_DBG( ,dbgDeallocationWarning(dbgDAWarning) )
161 {}
162#endif // defined(ALIB_DOX)
163
164
165 // #############################################################################################
166 // ### Comparison
167 // #############################################################################################
168 /**
169 * Comparison operator.
170 * @tparam U The allocation type of the other allocator.
171 * @param rhs The right hand side allocator.
172 * @return \c true if this and \p{rhs} use the same #allocator, \c false otherwise.
173 */
174 template< typename U >
175 bool operator==( const StdContMA<U>& rhs ) const noexcept
176 {
177 return &allocator == &rhs.allocator;
178 }
179
180 /**
181 * Comparison operator.
182 * @tparam U The allocation type of the other allocator.
183 * @param rhs The right hand side allocator.
184 * @return \c false if this and \p{rhs} use the same #allocator, \c true otherwise.
185 */
186 template< typename U >
187 bool operator!=( const StdContMA<U>& rhs ) const noexcept
188 {
189 return &allocator != &rhs.allocator;
190 }
191
192
193 // #############################################################################################
194 // ### Allocate/de-allocate
195 // #############################################################################################
196 /** ********************************************************************************************
197 * Passes the allocation request to field #allocator.
198 *
199 * @param n The number of requested objects to allocate storage for.
200 * @return Pointer to the first byte of a memory block suitably aligned and sufficient to hold
201 * an array of n objects of type \p{T} .
202 **********************************************************************************************/
203 [[nodiscard]]
204 T* allocate( size_t n, const void* = nullptr )
205 {
206 DBG_MONOMEM_VERBOSE( "STD_CONTAINER", "Allocating object of type {!Q<>}. ", typeid(T) )
207 return reinterpret_cast<T*>( allocator.AllocArray<T>( n ) );
208 }
209
210 /** ********************************************************************************************
211 * If #allocator is not set, invokes <c>std::free(p)</c>. Otherwise does nothing.
212 * @param p Pointer to the previously allocated memory.
213 * @param n The number of objects allocated.
214 **********************************************************************************************/
215 void deallocate( T* p, std::size_t n )
216 {
217 (void) p;
218 (void) n;
219
220 ALIB_ASSERT_WARNING( !dbgDeallocationWarning || n == 1, "MONOMEM/STDCNTMA",
221 "De-allocation with strict allocator. If this is container destruction, set flag\n"
222 "StdContMA::dbgDeallocationWarning to disable this warning. " )
224 }
225
226}; // struct StdContMA
227
228/** ************************************************************************************************
229 * Implementation of <c>std::allocator</c> to be used with container types provided by the
230 * C++ standard library.
231 *
232 * This allocator only optionally uses monotonic allocation - only if an allocator was given
233 * with construction. This has a very small performance impact, hence the non-optional sibling,
234 * \alib{monomem;StdContMA} is to be used with types that always use monotonic memory.
235 *
236 * @tparam T The type of objects to be allocated.
237 **************************************************************************************************/
238template<typename T>
240{
241 // #############################################################################################
242 // ### Fields
243 // #############################################################################################
244 /** The allocator to use. */
246
247 #if ALIB_DEBUG
248 /** If \c true warnings about de-allocation of objects are suppressed. this should be set
249 * prior to destructing a container that uses this allocator. <br>
250 * Available only in debug builds. */
252 #endif
253
254 // #############################################################################################
255 // ### Construction/Destruction
256 // #############################################################################################
257 /** Default constructor */
259 : allocator(nullptr)
260 {}
261
262
263 /** Defaulted copy constructor */
264 constexpr StdContMAOptional( const StdContMAOptional& ) noexcept =default;
265
266 /** Defaulted move constructor */
267 constexpr StdContMAOptional( StdContMAOptional&& ) noexcept =default;
268
269 /**
270 * Copy constructor using an instance of different template type.
271 * @tparam TSibling The originating allocator's type (<b>StdContMAOptional<X></b>).
272 * @param origin The originating allocator of type \p{TSibling} .
273 */
274 template<typename TSibling>
275 StdContMAOptional( TSibling& origin)
276 : allocator(origin.allocator)
278 {}
279
280#if defined(ALIB_DOX)
281 /**
282 * Constructor for the initial allocator instantiation.
283 *
284 * Parameter \p{dbgDisableDeallocationWarning}, which defaults to \c true might be given
285 * after a code is tested to be stict in respect to allocation.
286 * (Note: unfortunately, due to the design of <c>std::allocator</c> and its use, this flag can
287 * not be changed once a container is constructed. This is why it has to be decided upfront
288 * if a warning is to be raised or not).
289 *
290 * @param pAllocator The recycler for allocations and de-allocations.
291 * @param dbgDeallocationWarning As described with this method. Available only in debug builds.
292 */
293 constexpr StdContMAOptional( MonoAllocator& pAllocator,
294 bool dbgDeallocationWarning= true );
295#else
296 constexpr StdContMAOptional( MonoAllocator* pAllocator ALIB_DBG(, bool dbgDAWarning= false) )
297 : allocator(pAllocator)
298ALIB_DBG( ,dbgDeallocationWarning(dbgDAWarning) )
299 {}
300#endif // defined(ALIB_DOX)
301
302
303 // #############################################################################################
304 // ### Comparison
305 // #############################################################################################
306 /**
307 * Comparison operator.
308 * @tparam U The allocation type of the other allocator.
309 * @param rhs The right hand side allocator.
310 * @return \c true if this and \p{rhs} use the same #allocator, \c false otherwise.
311 */
312 template< typename U >
313 bool operator==( const StdContMAOptional<U>& rhs ) const noexcept
314 {
315 return allocator == rhs.allocator;
316 }
317
318 /**
319 * Comparison operator.
320 * @tparam U The allocation type of the other allocator.
321 * @param rhs The right hand side allocator.
322 * @return \c false if this and \p{rhs} use the same #allocator, \c true otherwise.
323 */
324 template< typename U >
325 bool operator!=( const StdContMAOptional<U>& rhs ) const noexcept
326 {
327 return allocator != rhs.allocator;
328 }
329
330
331 // #############################################################################################
332 // ### Allocate/de-allocate
333 // #############################################################################################
334 /** ********************************************************************************************
335 * If #allocator is set, passes the allocation request to #allocator.
336 * Otherwise invokes <c>std::malloc</c>.
337 *
338 * @param n The number of requested objects to allocate storage for.
339 * @return Pointer to the first byte of a memory block suitably aligned and sufficient to hold
340 * an array of n objects of type \p{T} .
341 **********************************************************************************************/
342 [[nodiscard]]
343 T* allocate( size_t n, const void* = nullptr )
344 {
345 DBG_MONOMEM_VERBOSE( "STD_CONTAINER", "Allocating object of type {!Q<>}. "
346 "Optional allocator set: ",
347 typeid(T), (allocator == nullptr ? "No" : "Yes") )
348 if( allocator == nullptr )
349 {
350 return reinterpret_cast<T*>( std::malloc( sizeof(T) * n ) );
351 }
352
353 return reinterpret_cast<T*>( allocator->AllocArray<T>( n ) );
354 }
355
356 /** ********************************************************************************************
357 * If #allocator is not set, invokes <c>std::free(p)</c>. Otherwise does nothing.
358 * @param p Pointer to the previously allocated memory.
359 * @param n The number of objects allocated.
360 **********************************************************************************************/
361 void deallocate( T* p, std::size_t n )
362 {
363 (void) n;
364 if( allocator == nullptr )
365 {
366 std::free( p );
367 return;
368 }
369 ALIB_ASSERT_WARNING( !dbgDeallocationWarning || n == 1, "MONOMEM/STDCNTMA",
370 "De-allocation with strict allocator. If this is container destruction, set flag\n"
371 "StdContMAOptional::dbgDeallocationWarning to disable this warning. " )
373 }
374
375}; // struct StdContMAOptional
376
377/** ************************************************************************************************
378 * Implementation of <c>std::allocator</c> to be used with container types provided by the
379 * C++ standard library.
380 *
381 * As the C+++ library's specification does not include details of the container class's
382 * implementation, this allocator uses type \alib{monomem;util::RTTRAllocator} which detects
383 * node types automatically.
384 *
385 * \attention
386 * It can not be guaranteed that a certain, uncommon implementation of the C++ library
387 * allocates memory in a way that this allocator truly recycles objects, and - even if the authors
388 * of \alib are optimistic hat this type works with any implementation - it is recommended
389 * to use the alternative container types found in this \alibmod_nl.
390 *
391 * \see
392 * For background information about monotonic memory allocation, recycling and the issues
393 * of C++ standard container types, see the \ref alib_mod_monomem "Programmer's Manual" of
394 * this \alibmod_nl.
395 *
396 * @tparam T The type of objects to be allocated.
397 **************************************************************************************************/
398template<typename T>
400{
401 // #############################################################################################
402 // ### Fields
403 // #############################################################################################
404 /** The only member of this allocator type used to perform all duties. */
406
407 // #############################################################################################
408 // ### Construction/Destruction
409 // #############################################################################################
410 /** Defaulted copy constructor */
411 constexpr StdContMARecycling( const StdContMARecycling& ) noexcept =default;
412
413 /** Defaulted move constructor */
414 constexpr StdContMARecycling( StdContMARecycling&& ) noexcept =default;
415
416 /**
417 * Copy constructor using an instance of different template type.
418 * @tparam TSibling The originating allocator's type (<b>StdContMARecycling<X></b>).
419 * @param StdContMARecycling The originating allocator of type \p{TSibling} .
420 */
421 template<typename TSibling>
425
426 /**
427 * Constructor for the initial allocator instantiation.
428 * @param pRecycler The recycler to for allocations and de-allocations.
429 */
430 constexpr StdContMARecycling( RTTRAllocator& pRecycler)
431 : recycler(pRecycler)
432 {}
433
434 // #############################################################################################
435 // ### Comparison
436 // #############################################################################################
437 /**
438 * Comparison operator.
439 * @tparam U The allocation type of the other allocator.
440 * @param rhs The right hand side allocator.
441 * @return \c true if this and \p{rhs} use the same #recycler, \c false otherwise.
442 */
443 template< typename U >
444 bool operator==( const StdContMARecycling<U>& rhs ) const noexcept
445 {
446 return recycler == rhs.recycler;
447 }
448
449 /**
450 * Comparison operator.
451 * @tparam U The allocation type of the other allocator.
452 * @param rhs The right hand side allocator.
453 * @return \c false if this and \p{rhs} use the same #recycler, \c true otherwise.
454 */
455 template< typename U >
456 bool operator!=( const StdContMARecycling<U>& rhs ) const noexcept
457 {
458 return recycler != rhs.recycler;
459 }
460
461 // #############################################################################################
462 // ### Allocate/de-allocate
463 // #############################################################################################
464 /** ********************************************************************************************
465 * Implementation of <c>std::allocator</c> interface.
466 * Dependent on whether a single or multiple objects are requested, this method invokes
467 * either \alib{monomem::util;RTTRAllocator::Get} or
468 * \alib{monomem::util;RTTRAllocator::AllocUnrelated} on field #recycler.
469 *
470 * @param n The number of requested objects to allocate storage for.
471 * @return Pointer to the first byte of a memory block suitably aligned and sufficient to
472 * hold an array of n objects of type \p{T} .
473 **********************************************************************************************/
474 [[nodiscard]]
475 T* allocate( size_t n, const void* = nullptr )
476 {
477 if( n == 1 )
478 return reinterpret_cast<T*>( recycler.Get( sizeof(T) , alignof(T)
479 ALIB_DBG(, typeid(T) ) ) );
480
481 return reinterpret_cast<T*>( recycler.AllocUnrelated( sizeof(T) * n, alignof(T)
482 ALIB_DBG(, typeid(T) ) ) );
483 }
484
485 /** ********************************************************************************************
486 * Implementation of <c>std::allocator</c> interface.
487 * Dependent on whether a single or multiple objects are de-allocated (parameter \p{n}), this
488 * method invokes either \alib{monomem::util;RTTRAllocator::Recycle} or
489 * \alib{monomem::util;RTTRAllocator::RecycleChunk} on field #recycler.
490 *
491 * @param p Pointer to the object to deallocate.
492 * @param n The number of objects to de-allocate.
493 **********************************************************************************************/
494 void deallocate( T* p, std::size_t n )
495 {
496 // deallocate node
497 if( n == 1 )
498 recycler.Recycle( p, sizeof(T) , alignof(T) ALIB_DBG(, typeid(T) ) );
499 else
500 recycler.RecycleChunk ( p, sizeof(T) * n, alignof(T) ALIB_DBG(, typeid(T) ) );
501 }
502
503
504}; // struct StdContMARecycling
505
506} // namespace alib[::monomem]
507
508/// Type alias in namespace \b alib.
509template<typename T>
511
512/// Type alias in namespace \b alib.
513template<typename T>
515
516/// Type alias in namespace \b alib.
517template<typename T>
519
520} // namespace [alib]
521
522
523
524#endif // HPP_ALIB_MONOMEM_STDCONTAINERMA
ALIB_FORCE_INLINE T * AllocArray(TSize length)
#define ALIB_ASSERT_WARNING(cond,...)
Definition alib.hpp:985
#define ALIB_DBG(...)
Definition alib.hpp:457
Definition alib.cpp:57
void deallocate(T *p, std::size_t n)
constexpr StdContMAOptional(const StdContMAOptional &) noexcept=default
bool operator!=(const StdContMAOptional< U > &rhs) const noexcept
T * allocate(size_t n, const void *=nullptr)
constexpr StdContMAOptional(StdContMAOptional &&) noexcept=default
constexpr StdContMAOptional(MonoAllocator &pAllocator, bool dbgDeallocationWarning=true)
bool operator==(const StdContMAOptional< U > &rhs) const noexcept
void deallocate(T *p, std::size_t n)
constexpr StdContMARecycling(RTTRAllocator &pRecycler)
constexpr StdContMARecycling(const StdContMARecycling &) noexcept=default
bool operator==(const StdContMARecycling< U > &rhs) const noexcept
bool operator!=(const StdContMARecycling< U > &rhs) const noexcept
constexpr StdContMARecycling(StdContMARecycling &&) noexcept=default
T * allocate(size_t n, const void *=nullptr)
constexpr StdContMA(const StdContMA &) noexcept=default
bool operator==(const StdContMA< U > &rhs) const noexcept
void deallocate(T *p, std::size_t n)
bool operator!=(const StdContMA< U > &rhs) const noexcept
constexpr StdContMA(MonoAllocator &pAllocator, bool dbgDeallocationWarning=true)
T * allocate(size_t n, const void *=nullptr)
constexpr StdContMA(StdContMA &&) noexcept=default
T value_type
Type definition as required by C++ library standards.
std::false_type is_always_equal
Type definition as required by C++ library standards.
ptrdiff_t difference_type
Type definition as required by C++ library standards.
size_t size_type
Type definition as required by C++ library standards.
char * AllocUnrelated(size_t size, size_t alignment, const type_info &dbgTypeInfo)
char * Get(size_t size, size_t alignment, const type_info &dbgTypeInfo)
void RecycleChunk(char *mem, size_t size, size_t alignment, const type_info &dbgTypeInfo)
void Recycle(void *mem, size_t size, size_t alignment, const type_info &dbgTypeInfo)