ALib C++ Library
Library Version: 2412 R0
Documentation generated by doxygen
Loading...
Searching...
No Matches
stdcontainerallocator.hpp
Go to the documentation of this file.
1//==================================================================================================
2/// \file
3/// This header file is part of the \aliblong. It does not belong to an \alibmod and is
4/// included in any \alibdist.
5///
6/// \emoji :copyright: 2013-2024 A-Worx GmbH, Germany.
7/// Published under \ref mainpage_license "Boost Software License".
8//==================================================================================================
9#ifndef HPP_ALIB_LANG_STDCONTAINERALLOCATOR
10#define HPP_ALIB_LANG_STDCONTAINERALLOCATOR
11#pragma once
13
14namespace alib::lang {
15namespace detail {
16
17//==================================================================================================
18/// Base struct for types \alib{lang;StdContainerAllocator} and
19/// \alib{lang;StdContainerAllocatorRecycling} containing entities to satisfy requirements for
20/// being a <c>std::allocator</c>.
21///
22/// @tparam T The type of objects to be allocated.
23/// @tparam TAllocator The allocator type, as prototyped with \alib{lang;Allocator}.
24//==================================================================================================
25template<typename T, typename TAllocator>
27{
28 // #############################################################################################
29 // ### Type definitions
30 // #############################################################################################
31 using size_type = size_t ; ///< Type definition as required by C++ library standards.
32 using difference_type= ptrdiff_t ; ///< Type definition as required by C++ library standards.
33 using value_type = T ; ///< Type definition as required by C++ library standards.
34 using is_always_equal= std::false_type; ///< Type definition as required by C++ library standards.
35 using reference = T& ; ///< Type definition as required by C++ library standards.
36 using const_reference= const T& ; ///< Type definition as required by C++ library standards.
37
38
39 /// The allocator type that \p{TAllocator} specifies.
40 using AllocatorType= TAllocator;
41
42 // #############################################################################################
43 // ### Other required members
44 // #############################################################################################
45 #if ALIB_CPP_STANDARD == 17 || DOXYGEN
46 /// The possible allocation size.
47 /// Note: Available only if <b>ALIB_CPP_STANDARD == 17, as it was deprecated afterwards.</b>.
48 /// @return Returns the largest supported allocation size.
49 size_t max_size() const noexcept
50 {
51 return size_t(-1) / 2;
52 }
53 #endif
54
55}; // struct StdContainerAllocatorBase
56
57} // namespace alib::lang[::detail]
58
59
60//==================================================================================================
61/// This struct is an implementation of C++ standard library type <c>std::allocator</c>.
62/// It is to be used with container types provided by the C++ standard library in combination
63/// with \alib{lang;Allocator;ALib Allocators}.
64///
65/// With the inclusion of module \alib_monomem in the \alibdist, this allocator is suitable to use
66/// cases of \ref alib_contmono_intro_strictweak "strict or weak monotonic allocation".
67///
68/// ### Shortcuts for Specific ALib Allocators ###
69/// The following alias type definitions exist for this type, each addressing a specific allocator:
70/// - \alib{SCAMono}, and
71/// - \alib{SCAPool}.
72///
73/// Along with this, shortcuts to the container types are likewise provided with:
74/// - \alib{StdVectorMono}, \alib{StdVectorPool},
75/// - \alib{StdListMono}, \alib{StdListPool}, and
76/// - \alib{StdDequeMono}, \alib{StdDequePool}.
77///
78/// \anchor alib_ns_monomem_scamono_reset
79/// ### Resetting A Container ###
80/// While the dedicated container types provided with module \alib_containers offer a method
81/// named \b Reset (see for example \alib{containers;HashTable::Reset}), the C++ standard
82/// containers do not. This is a challenge because their internal memory will be invalid
83/// with a reset. For example, if allocator type \alib{MonoAllocator} was used with calss
84/// <c>std::vector</c>, there is no interface method that makes the vector "forget" its internal
85/// data array. Its method <c>shrink_to_fit</c> by its specification is not forced to shrink
86/// anything or even dispose the data if the size was \c 0 when called.
87/// This is implementation-dependent.
88///
89/// The way out is as simple as radical: The container is just to be destructed and reconstructed
90/// "in place". This can be done using a <em>C++ placement-new</em>. The following
91/// code snippet demonstrates this:
92/// \snippet "ut_stdcontainers.cpp" DOX_MONOMEM_SCAMONO_PLACEMENT_NEW
93///
94/// \see
95/// - An alternative version that \ref alib_contmono_intro_recycling "recycles nodes" (and also
96/// bucket arrays in case of <c>std::unordered_set</c> and <c>std::unordered_map</c>), is
97/// provided with sibling type \alib{lang;StdContainerAllocatorRecycling}.
98/// - Type definitions \alib{SCAMono} and \alib{SCAPool} given with module \alib_monomem.
99/// - Further shortcuts for standard container types, given with \alib{StdVectorMono},
100/// \alib{StdVectorPool}, \alib{StdListMono}, \alib{StdListPool}, \alib{StdDequeMono}, and
101/// \alib{StdDequePool}.
102///
103/// @tparam T The type of objects to be allocated.
104/// @tparam TAllocator The allocator type, as prototyped with \alib{lang;Allocator}.
105//==================================================================================================
106template<typename T, typename TAllocator>
108 , AllocatorMember<TAllocator>
109{
110 /// The allocator type that \p{TAllocator} specifies.
112
113 /// Defaulted copy constructor
114 constexpr StdContainerAllocator( const StdContainerAllocator& ) noexcept =default;
115
116 /// Defaulted move constructor
117 constexpr StdContainerAllocator( StdContainerAllocator&& ) noexcept =default;
118
119 /// Copy constructor using an instance of different template type.
120 /// @tparam TSibling The originating allocator's type (<b>StdContainerAllocator<X></b>).
121 /// @param origin The originating allocator of type \p{TSibling} .
122 template<typename TSibling, typename TEnableIf=
123 ATMP_T_IF(void, ATMP_ISOF(TAllocator&, typename TSibling::allocator))>
124 StdContainerAllocator(const TSibling& origin)
125 : allocBase(origin)
126 {}
127
128 /// Copy constructor using an instance of different template type.
129 /// @tparam TSibling The originating allocator's type (<b>StdContainerAllocator<X></b>).
130 /// @param origin The originating allocator of type \p{TSibling} .
131 template<typename TSibling>
135
136 /// Constructor for the initial allocator instantiation.
137 /// @param pAllocator The allocator.
138 StdContainerAllocator( TAllocator& pAllocator )
139 : allocBase(pAllocator)
140 {}
141
142 /// Parameterless constructor used with heap allocation.
144
145
146 // #############################################################################################
147 // ### Comparison
148 // #############################################################################################
149 /// Comparison operator.
150 /// @tparam U The allocation type of the other allocator.
151 /// @param rhs The right hand side allocator.
152 /// @return \c true if this and \p{rhs} use the same #allocator, \c false otherwise.
153 template< typename U >
154 bool operator==( const StdContainerAllocator<U,TAllocator>& rhs ) const noexcept
155 {
156 return &allocBase::getAllocator() == &rhs.getAllocator();
157 }
158
159 /// Comparison operator.
160 /// @tparam U The allocation type of the other allocator.
161 /// @param rhs The right hand side allocator.
162 /// @return \c false if this and \p{rhs} use the same #allocator, \c true otherwise.
163 template< typename U >
164 bool operator!=( const StdContainerAllocator<U,TAllocator>& rhs ) const noexcept
165 {
166 return &allocBase::GetAllocator() != &rhs.GetAllocator();
167 }
168
169
170 // #############################################################################################
171 // ### Allocate/de-allocate
172 // #############################################################################################
173 //==============================================================================================
174 /// Passes the allocation request to field #allocator.
175 ///
176 /// @param n The number of requested objects to allocate storage for.
177 /// @return Pointer to the start of the array of \p{n} objects of type \p{T}.
178 //==============================================================================================
179 [[nodiscard]]
180 T* allocate( size_t n, const void* = nullptr )
181 { return allocBase::AI().template AllocArray<T>( n ); }
182
183 //==============================================================================================
184 /// Frees the given array of objects.
185 /// @param p Pointer to the previously allocated memory.
186 /// @param n The number of objects allocated.
187 //==============================================================================================
188 void deallocate( T* p, std::size_t n )
189 { allocBase::AI().FreeArray( p, n ); }
190
191}; // struct StdContainerAllocator
192
193//==================================================================================================
194/// Implementation of <c>std::allocator</c> to be used with container types provided by the
195/// C++ standard library.
196///
197/// As the C+++ library's specification does not include details of the container class's
198/// implementation, this allocator uses type \alib{lang;RTTRAllocator} which detects
199/// node types automatically.
200///
201/// \attention
202/// It cannot be guaranteed that a certain, uncommon implementation of the C++ library
203/// allocates memory in a way that this allocator truly recycles objects, and - even if the authors
204/// of \alib are optimistic hat this type works with any implementation - it is recommended
205/// to use the alternative container types found in this \alibmod_nl.
206///
207/// \see
208/// For background information about monotonic memory allocation, recycling, and the issues
209/// of C++ standard container types, see the \ref alib_mods_contmono "Programmer's Manual" of
210/// \alibmods_nl \b Containers and \b Monomem.
211///
212/// @tparam T The type of objects to be allocated.
213/// @tparam TAllocator The allocator type, as prototyped with \alib{lang;Allocator}.
214//==================================================================================================
215template<typename T, typename TAllocator>
217{
218 // #############################################################################################
219 // ### Fields
220 // #############################################################################################
221 /// The only member of this allocator type used to perform all duties.
223
224 // #############################################################################################
225 // ### Construction/Destruction
226 // #############################################################################################
227 /// Defaulted copy constructor
229
230 /// Defaulted move constructor
232
233 /// Copy constructor using an instance of different template type.
234 /// @tparam TSibling The originating allocator's type (<b>StdContainerAllocatorRecycling<X></b>).
235 /// @param StdContainerAllocatorRecycling The originating allocator of type \p{TSibling} .
236 template<typename TSibling>
239
240 /// Constructor for the initial allocator instantiation.
241 /// @param pRecycler The recycler to for allocations and de-allocations.
243 : recycler(pRecycler)
244 {}
245
246 // #############################################################################################
247 // ### Comparison
248 // #############################################################################################
249 /// Comparison operator.
250 /// @tparam U The allocation type of the other allocator.
251 /// @param rhs The right hand side allocator.
252 /// @return \c true if this and \p{rhs} use the same #recycler, \c false otherwise.
253 template< typename U >
255 { return recycler == rhs.recycler; }
256
257 /// Comparison operator.
258 /// @tparam U The allocation type of the other allocator.
259 /// @param rhs The right hand side allocator.
260 /// @return \c false if this and \p{rhs} use the same #recycler, \c true otherwise.
261 template< typename U >
263 { return recycler != rhs.recycler; }
264
265 // #############################################################################################
266 // ### Allocate/de-allocate
267 // #############################################################################################
268 //==============================================================================================
269 /// Implementation of <c>std::allocator</c> interface.
270 /// Dependent on whether a single or multiple objects are requested, this method invokes
271 /// either \alib{lang;RTTRAllocator::Get} or
272 /// \alib{lang;RTTRAllocator::AllocUnrelated} on field #recycler.
273 ///
274 /// @param n The number of requested objects to allocate storage for.
275 /// @return Pointer to the start of the array of \p{n} objects of type \p{T}.
276 //==============================================================================================
277 [[nodiscard]]
278 T* allocate( size_t n, const void* = nullptr )
279 {
280 if( n == 1 )
281 return reinterpret_cast<T*>( recycler.Get( sizeof(T),
282 alignof(T)
283 ALIB_DBG(, typeid(T) ) ) );
284
285 return reinterpret_cast<T*>( recycler.AllocUnrelated( sizeof(T) * n,
286 alignof(T)
287 ALIB_DBG(, typeid(T) ) ) );
288 }
289
290 //==============================================================================================
291 /// Implementation of <c>std::allocator</c> interface.
292 /// Dependent on whether a single or multiple objects are de-allocated (parameter \p{n}), this
293 /// method invokes either \alib{lang;RTTRAllocator::Recycle} or
294 /// \alib{lang;RTTRAllocator::RecycleChunk} on field #recycler.
295 ///
296 /// @param p Pointer to the object to deallocate.
297 /// @param n The number of objects to de-allocate.
298 //==============================================================================================
299 void deallocate( T* p, std::size_t n )
300 {
301 // deallocate node
302 if( n == 1 ) recycler.Recycle( p, sizeof(T) , alignof(T) ALIB_DBG(, typeid(T) ) );
303 else recycler.RecycleChunk ( p, sizeof(T) * n ALIB_DBG(, typeid(T) ) );
304 }
305}; // struct StdContainerAllocatorRecycling
306
307} // namespace [alib::lang]
308
309
310#endif // HPP_ALIB_LANG_STDCONTAINERALLOCATOR
311
#define ATMP_ISOF( T, TBase)
Definition tmp.hpp:28
#define ALIB_DBG(...)
Definition alib.hpp:390
#define ATMP_T_IF(T, Cond)
Definition tmp.hpp:49
AllocatorInterface< TAllocator > AI() const noexcept
TAllocator & GetAllocator() const noexcept
TAllocator & allocator
A reference to the allocator.
constexpr StdContainerAllocatorRecycling(StdContainerAllocatorRecycling &&) noexcept=default
Defaulted move constructor.
bool operator!=(const StdContainerAllocatorRecycling< U, TAllocator > &rhs) const noexcept
RTTRAllocator< TAllocator > & recycler
The only member of this allocator type used to perform all duties.
constexpr StdContainerAllocatorRecycling(const StdContainerAllocatorRecycling &) noexcept=default
Defaulted copy constructor.
bool operator==(const StdContainerAllocatorRecycling< U, TAllocator > &rhs) const noexcept
T * allocate(size_t n, const void *=nullptr)
constexpr StdContainerAllocatorRecycling(RTTRAllocator< TAllocator > &pRecycler)
constexpr StdContainerAllocator(const StdContainerAllocator &) noexcept=default
Defaulted copy constructor.
StdContainerAllocator()=default
Parameterless constructor used with heap allocation.
constexpr StdContainerAllocator(StdContainerAllocator &&) noexcept=default
Defaulted move constructor.
bool operator!=(const StdContainerAllocator< U, TAllocator > &rhs) const noexcept
T * allocate(size_t n, const void *=nullptr)
bool operator==(const StdContainerAllocator< U, TAllocator > &rhs) const noexcept
StdContainerAllocator(const StdContainerAllocator< TSibling, TAllocator > &origin)
T & reference
Type definition as required by C++ library standards.
TAllocator AllocatorType
The allocator type that TAllocator specifies.
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.
const T & const_reference
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.