ALib C++ Framework
by
Library Version: 2605 R0
Documentation generated by doxygen
Loading...
Searching...
No Matches
sharedmonoval.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/// Copyright 2013-2026 A-Worx GmbH, Germany.
6/// Published under #"mainpage_license".
7//==================================================================================================
8ALIB_EXPORT namespace alib { namespace monomem {
9
10//==================================================================================================
11/// This templated class is a utility type for #"TMonoAllocator" and supports the
12/// following mechanics:
13/// - It creates a first #"detail::Buffer;buffer" usable by a #"%MonoAllocator".
14/// - A custom type defined by template parameter \p{T} is placed at the beginning of
15/// that buffer.
16/// - Along with the custom type, the #"%MonoAllocator" that receives this first buffer is likewise
17/// placed in the buffer.
18/// - Finally, an atomic usage counter is placed as a third member inside that buffer.
19/// - Only one pointer into this first buffer is stored with this type.
20/// - This type overloads #".operator->()" and #".operator*()" to access the members of the custom
21/// type.
22/// - The concept of an "automatic pointer", similar to <c>std::shared_ptr</c> is
23/// implemented with this type.
24/// - The default-constructor of this type just sets the internal pointer to \c nullptr.
25///
26/// All of the above results in the following:
27/// - The size of an instance of this class is equal to the size of a single C++ pointer.
28/// The only member is a pointer to an object of internal type
29/// #"TSharedMonoVal::FieldMembers".
30/// - A single dynamic memory allocation is performed to create an instance of the class, which
31/// holds all data and allows further monotonic allocations.
32/// - Values of this type are \e nulled, when default constructed.
33/// - Values of this type can be shared (copied as value), which increases the use counter.
34/// - Values of this type can be moved, which keeps the use counter as is.
35/// - Values of this type can be emptied by assigning \c nullptr or invoking #".SetNulled".
36/// - At the moment that the last copy gets out of scope, is deleted or \e nulled,
37/// the contained object is destructed, and all monotonic memory is freed.
38/// - The allocator can be received with #".GetAllocator" and used by the contained type.
39/// A derived type may volunteer to publish the allocator as well to be used by any
40/// entity that gets access to a copy of the automatic pointer.
41/// - Member access is performed with the overloaded <c>operator->()</c>.
42/// Alternatively (and sometimes needed) other provided operators and methods like #".Get" may
43/// be used.
44///
45/// In contrast to the container types #"SharedVal" and #"SharedPtr",
46/// this type is <b>most commonly used as a base class</b> of types that should to be fully
47/// self-contained (like the types listed below).
48///
49/// \see
50/// - A step by step sample that can be used to bootstrap custom usages is presented in chapter
51/// #"alib_contmono_smv" of the Programmer's Manual of this \alibmod.
52/// - The following types found across \alib may be reviewed for understanding this type's usage
53/// and its potential use cases:
54/// - Class #"TSharedConfiguration",
55/// - Class #"TSharedFTree", and
56/// - Class #"exc Exception".
57/// - Chapter #"alib_contmono_smv_locking" of the Programmer's Manual of module
58/// \alib_monomem_nl.
59///
60/// @tparam T The custom type that is embedded along with the #"%MonoAllocator".
61/// @tparam TAllocator The #"alib_contmono_chaining;chained allocator" that is used by the
62/// monotonous allocator that this type creates inside its first buffer.<br>
63/// Usually, type #"HeapAllocator" is to be given here.
64/// @tparam TLock The type of #"alib_threads_locks;ALib lock" to embed besides \p{T}.
65/// With the provision of <c>void</c>, the integration of a lock is
66/// suppressed.<br>
67/// See chapter #"alib_contmono_smv_locking" of the Programmer's Manual of
68/// module \alib_monomem_nl for further details.
69//==================================================================================================
70template<typename T, typename TAllocator, typename TLock>
72 protected:
73 /// Same as #"TSharedMonoVal::FieldMembersWithLock" but missing the lock.
74 /// This type is chosen if template parameter \p{TLock} equals <c>void</c>.<br>
75 /// The internals of this type are not further documented.
77 #if !DOXYGEN
80 std::atomic<unsigned> refCount;
81
82 FieldMembersNoLock( TAllocator& pAllocator,
83 detail::Buffer* firstBuffer,
84 size_t initialBufferSize,
85 unsigned bufferGrowthInPercent )
86 : allocator( pAllocator, firstBuffer, initialBufferSize, bufferGrowthInPercent )
87 , refCount(1) {}
88
89 template<typename TRequires= TAllocator>
90 requires std::default_initializable<TRequires>
92 size_t initialBufferSize,
93 unsigned bufferGrowthInPercent )
94 : allocator(ALIB_DBG("ShardMonoVal",) firstBuffer, initialBufferSize, bufferGrowthInPercent)
95 , refCount(1) {}
96 #endif
97 }; // struct FieldMembersNoLock;
98
99 /// The combined struct of members that are allocated in the first buffer of the
100 /// monotonic allocator.
102 /// The space for the custom member. The instance will be constructed using placement-new.
104
105 /// The allocator that this class is contained in.
107
108 /// The reference counter used to implement the <c>std::shared_ptr</c> behavior.
109 std::atomic<unsigned> refCount;
110
111 /// The embedded lock.
112 TLock lock;
113
114 /// Constructor.
115 /// Creates the allocator and initializes #".refCount". The #".custom" contents will be
116 /// constructed by an obligatory, separated call to #"ConstructT".
117 /// @param pAllocator The chained allocator of the monotonic allocator.
118 /// @param firstBuffer The first argument to field #".allocator".
119 /// @param initialBufferSize The second argument to field #".allocator".
120 /// @param bufferGrowthInPercent Optional growth factor in percent, applied to the buffer size
121 /// with each next buffer allocation.
122 /// Values provided should be greater than 100.<p>
123 FieldMembersWithLock( TAllocator& pAllocator,
124 detail::Buffer* firstBuffer,
125 size_t initialBufferSize,
126 unsigned bufferGrowthInPercent )
127 : allocator( pAllocator, firstBuffer, initialBufferSize, bufferGrowthInPercent )
128 , refCount(1) {}
129
130 /// Alternative constructor missing the allocator instance.
131 /// This is used only with allocators that are default-constructible
132 /// (like #"HeapAllocator" is).
133 /// @tparam TRequires Defaulted template parameter. Must not be specified.
134 /// @param firstBuffer The first argument to field #".allocator".
135 /// @param initialBufferSize The second argument to field #".allocator".
136 /// @param bufferGrowthInPercent Optional growth factor in percent, applied to the buffer
137 /// size with each next buffer allocation.
138 /// Values provided should be greater than 100.<p>
139 template< typename TRequires= TAllocator>
140 requires std::default_initializable<TRequires>
142 size_t initialBufferSize,
143 unsigned bufferGrowthInPercent )
144 : allocator( ALIB_DBG("ShardMonoVal",)
145 firstBuffer, initialBufferSize, bufferGrowthInPercent )
146 , refCount(1) {}
147 }; // struct FieldMembersWithLock;
148
149 #if !DOXYGEN
150 void dbgassert() const { ALIB_ASSERT_ERROR(members,"MONOMEM", "Empty shared instance") }
151 #endif
152
153 /// The type of field members to include.
154 /// Dependent on the template parameter \p{TLock}, either
155 /// #"TSharedMonoVal::FieldMembersNoLock" or
156 /// #"TSharedMonoVal::FieldMembersWithLock" is chosen.
157 using FieldMembers= std::conditional_t<std::same_as<void, TLock>, FieldMembersNoLock, FieldMembersWithLock>;
158
159 /// The object that is placed in the allocator's first buffer.
160 /// Contains \p{T}, the allocator itself, and a reference counter.
162
163 //================================================================================================
164 //=== The self-contained implementation of this type
165 //================================================================================================
166 public:
167 /// Exposes the monotonic allocator used. Equals to <c>TMonoAllocator<TAllocator></c>.
169
170 /// Exposes the stored type specified with template parameter \p{T}.
171 using StoredType = T;
172
173 /// Exposes the lock type specified with template parameter \p{TLock}.
174 using LockType = TLock;
175
176 /// Constructs an initial buffer of given size and creates the mono allocator within.
177 ///
178 /// \attention
179 /// The instance of custom type \p{T} will \b not be constructed with
180 /// any constructor of this type.
181 /// Instead, an explicit call to #"ConstructT" has to be made after construction!
182 ///
183 /// @param allocator The (chained) allocator used to create the initial buffer
184 /// and passed to the monotonous allocator that is created.
185 /// @param initialBufferSizeInKB The initial size of memory buffers used with the monotonic
186 /// allocator in kB (1024 bytes)
187 /// @param bufferGrowthInPercent Optional growth factor in percent, applied to the buffer size
188 /// with each next buffer allocation.
189 /// Should be set to \c 200, to double the size with each
190 /// allocation.
191 TSharedMonoVal( TAllocator& allocator,
192 size_t initialBufferSizeInKB, unsigned bufferGrowthInPercent ) {
193 auto size= initialBufferSizeInKB * 1024;
194 void* mem= allocator.allocate( size, alignof(detail::Buffer) );
195 auto* buffer= new (mem) detail::Buffer( size );
196
197 members= static_cast<FieldMembers*>( buffer->allocate( sizeof( FieldMembers),
198 alignof(FieldMembers) ) );
199 ALIB_ASSERT_ERROR(members, "MONOMEM",
200 "Initial buffer size {} to small to hold shared value of size {}.",
201 size, sizeof( FieldMembers) )
202 new (members) FieldMembers( allocator, buffer, size, bufferGrowthInPercent );
203 }
204
205 /// Constructor missing the allocator instance.
206 /// To be used only with allocators that are default-constructible
207 /// (like #"HeapAllocator" is).
208 ///
209 /// \attention
210 /// The instance of custom type \p{T} will \b not be constructed with
211 /// any constructor of this type.
212 /// Instead, an explicit call to #".ConstructT" has to be made after construction!
213 ///
214 /// @param initialBufferSizeInKB The initial size of memory buffers used with the monotonic
215 /// allocator in kB (1024 bytes)
216 /// @param bufferGrowthInPercent Optional growth factor in percent, applied to the buffer size
217 /// with each next buffer allocation.
218 /// Should be set to \c 200, to double the size with each
219 /// allocation.
220 TSharedMonoVal( size_t initialBufferSizeInKB, unsigned bufferGrowthInPercent ) {
221 auto size= initialBufferSizeInKB * 1024;
222 void* mem= TAllocator().allocate( size, alignof(detail::Buffer) );
223 auto* buffer= new (mem) detail::Buffer( size );
224 members= reinterpret_cast<FieldMembers*>( buffer->allocate( sizeof (FieldMembers),
225 alignof(FieldMembers) ) );
226 ALIB_ASSERT_ERROR(members, "MONOMEM",
227 "Initial buffer size {} to small to hold shared value of size {}.",
228 size, sizeof( FieldMembers) )
229 new (members) FieldMembers( buffer, size, bufferGrowthInPercent );
230 }
231
232 /// Destructor. If this is the last copy, the destructors of \p{T} and of the
233 /// #"%MonoAllocator" are invoked.
235 ALIB_STATIC_ASSERT( Locks_not_supported_when_module_ALibThreads_is_exlcuded,
236 !ALIB_SINGLE_THREADED || std::same_as<void ALIB_COMMA TLock>,
237 "Template parameter TLock of class TSharedMonoVal must be <void> if module ALib Threads is "
238 "not included in the ALib Build." )
239
240 if (members && members->refCount.fetch_sub(1) == 1) {
241 members->custom.Destruct(); // Destruct the contained object first,
242 lang::Destruct( members->allocator); // then the allocator.
243 } }
244
245 /// Resets the monotonic allocator that this object is contained in to the snapshot created
246 /// right after construction.
247 /// The allocated memory buffers will remain allocated and reused. Before resetting,
248 /// the destructor of the custom object \p{T} is invoked, and after
249 /// the reset, in-place construction is performed.
250 ///
251 /// All shared instances remain valid (while, of course, their content is likewise reset).
252 ///
253 /// It is up to the implementation of the derived class if this method should be exposed
254 /// or not. It is also up to the implementation of the derived class if the internal allocator
255 /// should be exposed for 3rd-party usage or not.
256 ///
257 /// @tparam TArgs The argument types used for re-constructing \p{T}.
258 /// @param args The arguments to re-construct the instance of \p{T}.
259 template<typename... TArgs>
260 void Reset( TArgs&&... args ) {
261 // Destruct custom object first
262 members->custom.Destruct();
263
264 // reset allocator to behind members
265 members->allocator.Reset( sizeof(FieldMembers), alignof(FieldMembers) );
266
267 // construct custom object again
268 new (&members->custom) T( std::forward<TArgs>(args)... );
269 }
270
271 /// Constructs the custom members.
272 /// This method <b>has to be called</b> right after this instance was created with a
273 /// non-nulled state.<br>
274 /// Usually, this is done in the constructor of a dedicated derived type.
275 ///
276 /// \note
277 /// The construction of the contained type is intentionally deferred to the (therefore
278 /// mandatory) call of this method.
279 /// The reason is that this way, the monotonic allocator is accessible with the method #
280 /// GetAllocator() and valid and thus can be used here.
281 /// @tparam TArgs The argument types used for constructing \p{T}.
282 /// @param args The arguments to construct the instance of \p{T}.
283 template<typename... TArgs>
284 void ConstructT( TArgs&&... args ) { members->custom.Construct(std::forward<TArgs>(args)... ); }
285
286 /// @return The size of the memory that is allocated for the \p{T} as well as for
287 /// the reference counter and the allocator member.
288 /// (To whom it may concern.)
289 static constexpr size_t SizeOfAllocation() { return sizeof(FieldMembers); }
290
291 /// @return The monotonic allocator that this object has created and embedded itself in.
292 /// It may be used for custom allocations and especially may be passed to the
293 /// constructor of \p{T} with the method #".ConstructT" for further use.
294 AllocatorType& GetAllocator() noexcept { dbgassert(); return members->allocator; }
295
296 /// Returns a non-constant reference to the stored object of type \p{T}.<br>
297 /// This can be used as an alias to <c>(**this)</c>.
298 /// @return A reference to \p{T}.
299 T& Self() noexcept { dbgassert(); return *members->custom; }
300
301 /// Returns a constant reference to the stored object of type \p{T}.<br>
302 /// This can be used as an alias to <c>(**this)</c>.
303 /// @return A constant reference to \p{T}.
304 const T& Self() const noexcept { dbgassert(); return *members->custom; }
305
306 /// Overloaded operator to access members of custom type \p{T}
307 /// @return A pointer to \p{T}.
308 T* operator->() noexcept { dbgassert(); return members->custom.Get(); }
309
310 /// Overloaded operator to access members of custom type \p{T}
311 /// @return A constant pointer to \p{T}.
312 const T* operator->() const noexcept { dbgassert(); return members->custom.Get(); }
313
314 /// Overloaded operator to access members of the custom type \p{T}
315 /// @return A pointer to \p{T}.
316 T& operator*() noexcept { dbgassert(); return *members->custom; }
317
318 /// Overloaded operator to access members of the custom type \p{T}
319 /// @return A constant pointer to \p{T}.
320 const T& operator*() const noexcept { dbgassert(); return *members->custom; }
321
322
323 //================================================================================================
324 //=== The automatic pointer implementation of this type
325 //================================================================================================
326 /// Default Constructor. Leaves this object \e nulled.
327 TSharedMonoVal() noexcept : members(nullptr) {}
328
329 /// Constructs an empty instance from \c std::nullptr.
330 /// This constructor is necessary to allow assignment of \c std::nullptr to values of this type,
331 /// which clears the automatic pointer.
332 /// \note As the common way to use this class is to derive an own type, this own type should
333 /// have this same constructor. Only then, the assignment of \c std::nullptr is possible.
334 TSharedMonoVal(std::nullptr_t) noexcept : members(nullptr) {}
335
336 /// Copy Constructor. Increases the reference counter of the shared pointer (in case given
337 /// \p{other} is not nulled).
338 /// @param other The object to copy.
339 TSharedMonoVal(const TSharedMonoVal& other) noexcept
340 : members(other.members) { if(members) ++(members->refCount); }
341
342
343 /// Move Constructor. Does not increase the reference counter, instead nulls the \p{other}.
344 /// @param other The object to copy.
346 : members(other.members) { other.members= nullptr; }
347
348 /// Copy Assignment Operator. Cares for self-assignment and assignment of a shared pointer with
349 /// the same content.
350 /// Otherwise, the reference counter of the current object is decreased, disposed if
351 /// necessary, and then the object in \p{other} is copied to this object.
352 /// @param other The object to copy into this one.
353 /// @return A reference to \c this.
354 TSharedMonoVal& operator=(const TSharedMonoVal& other) noexcept {
355 // handle self assignment and assignment with same contents
356 if (this == &other || this->members == other.members)
357 return *this;
358
359 // decrement the old reference count and delete the old data if needed
360 if (members && members->refCount.fetch_sub(1) == 1) {
361 members->custom.Destruct(); // Destruct the contained object first,
362 lang::Destruct( members->allocator); // then the allocator.
363 }
364
365 // copy the new data
366 if((members= other.members) != nullptr)
367 ++(members->refCount);
368
369 return *this;
370 }
371
372 /// Move Assignment Operator. Cares for self-assignment.
373 /// Otherwise, the object in \p{other} is copied to this.
374 /// @param other The object to move into this one.
375 /// @return A reference to \c this.
377 // handle self assignment
378 if (this == &other)
379 return *this;
380
381 // decrement the old reference count and delete the old data if needed
382 if (members && members != other.members && members->refCount.fetch_sub(1) == 1) {
383 members->custom.Destruct(); // Destruct the contained object first,
384 lang::Destruct( members->allocator); // then the allocator.
385 }
386
387 // move members
388 members= other.members;
389 other.members= nullptr;
390 return *this;
391 }
392
393 /// Returns the number of shared usages.
394 /// In a multithreaded environment, the value returned is approximate.
395 /// @return \c The number of shared usages.
396 /// If this instance was default-constructed, moved, method #".SetNulled" was called,
397 /// or \c nullptr was assigned, then \c 0 is returned.
398 unsigned UseCount() const noexcept
399 { return members != nullptr ? members->refCount.load() : 0; }
400
401 /// Returns \c true if the #".UseCount" is \c 1.
402 /// @return \c true if this instance is set but not shared.
403 bool Unique() const noexcept { return members && members->refCount.load() == 1; }
404
405 /// Sets this object to \e nulled state, as if default constructed or \c nullptr was assigned.
406 /// If no shared copy exists, all data is destructed and memory is freed.<br>
407 /// As an alternative to this method, \c nullptr can be assigned.
408 void SetNulled() noexcept { lang::Destruct(*this); members= nullptr; }
409
410 /// Returns \c true if this is an empty instance.
411 /// @return \c true if #".UseCount" is \c 0, \c false otherwise.
412 bool IsNulled() const noexcept { return members == nullptr; }
413
414 /// Assignment of <c>nullptr</c>. Same as #".SetNulled".
415 void operator=(std::nullptr_t) { lang::Destruct(*this); members= nullptr; }
416
417 /// Comparison with <c>nullptr</c>.
418 /// @return \c true if #".UseCount" is greater than \c 0.
419 bool operator==(std::nullptr_t) const noexcept { return members == nullptr; }
420
421 /// Comparison with <c>nullptr</c>.
422 /// @return \c false if #".UseCount" is greater than \c 0.
423 bool operator!=(std::nullptr_t) const noexcept { return members != nullptr; }
424
425 /// Returns a non-constant pointer to the stored object of type \p{T}.
426 /// @return A pointer to \p{T}.
427 T* Get() noexcept { dbgassert(); return members->custom.Get(); }
428
429 /// Returns a constant reference to the stored object of type \p{T}.
430 /// @return A constant reference to \p{T}.
431 const T* Get() const noexcept { dbgassert(); return members->custom.Get(); }
432
433 /// @return \c true if this instance is not \e nulled, \c false otherwise.
434 operator bool() const noexcept { return members != nullptr; }
435
436
437 //================================================================================================
438 //=== The threads::XYZLock implementation of this type
439 //================================================================================================
440 #if DOXYGEN
441 /// Returns the embedded \p{TLock}.
442 /// This method is available only if the template parameter \p{TLock} is not equal to
443 /// <c>void</c>.
444 /// @return A reference to the embedded lock.
445 TLock& GetLock() const noexcept;
446
447 /// Calls \b Acquire on the embedded instance specified with template parameter \p{TLock}.
448 /// This method participates in the overload resolution only if \p{TLock} provides an
449 /// equivalent method.
450 /// @param ci Caller information. Available only with debug-builds.
451 inline void Acquire( const CallerInfo& ci ) const noexcept;
452
453 /// Calls \b TryAcquire on the embedded instance specified with template parameter \p{TLock}.
454 /// This method participates in the overload resolution only if \p{TLock} provides an
455 /// equivalent method.
456 /// @param ci Caller information. Available only with debug-builds.
457 /// @return \c true if the lock was not acquired by a different thread and thus, this call
458 /// was successful. \c false otherwise.
459 [[nodiscard]]
460 bool TryAcquire( const CallerInfo& ci ) const noexcept;
461
462 /// Calls \b Release on the embedded instance specified with template parameter \p{TLock}.
463 /// This method participates in the overload resolution only if \p{TLock} provides an
464 /// equivalent method.
465 /// @param ci Caller information. Available only with debug-builds.
466 void Release(const CallerInfo& ci) const noexcept;
467
468 /// Calls \b AcquireRecursive on the embedded instance specified with template parameter \p{TLock}.
469 /// This method participates in the overload resolution only if \p{TLock} provides an
470 /// equivalent method.
471 /// @param ci Caller information. Available only with debug-builds.
472 void AcquireRecursive( const CallerInfo& ci ) const noexcept;
473
474 /// Calls \b ReleaseRecursive on the embedded instance specified with template parameter \p{TLock}.
475 /// This method participates in the overload resolution only if \p{TLock} provides an
476 /// equivalent method.
477 /// @param ci Caller information. Available only with debug-builds.
478 void ReleaseRecursive(const CallerInfo& ci) const noexcept;
479
480 /// Calls \b %AcquireShared on the embedded instance specified with template parameter \p{TLock}.
481 /// This method participates in the overload resolution only if \p{TLock} provides an
482 /// equivalent method.
483 /// @param ci Caller information. Available only with debug-builds.
484 void AcquireShared( const CallerInfo& ci ) const noexcept;
485
486 /// Calls \b %TryAcquireShared on the embedded instance specified with template parameter \p{TLock}.
487 /// This method participates in the overload resolution only if \p{TLock} provides an
488 /// equivalent method.
489 /// @param ci Caller information. Available only with debug-builds.
490 /// @return \c true if the lock was not acquired by a different thread and thus, this call
491 /// was successful. \c false otherwise.
492 [[nodiscard]]
493 bool TryAcquireShared( const CallerInfo& ci ) const noexcept;
494
495 /// Calls \b %ReleaseShared on the embedded instance specified with template parameter \p{TLock}.
496 /// This method participates in the overload resolution only if \p{TLock} provides an
497 /// equivalent method.
498 /// @param ci Caller information. Available only with debug-builds.
499 void ReleaseShared(const CallerInfo& ci) const noexcept;
500
501 /// Calls \b %TryAcquireTimed on the embedded instance specified with template parameter
502 /// \p{TLock}.
503 /// This method participates in the overload resolution only if \p{TLock} provides an
504 /// equivalent method.
505 /// @param waitDuration The point in time, when this method stops waiting.
506 /// @param ci Caller information. Available only with debug-builds.
507 /// @return \c true if the lock was not acquired by a different thread and thus, this call
508 /// was successful. \c false otherwise.
509 [[nodiscard]]
510 bool TryAcquireTimed( const Ticks::Duration& waitDuration, const CallerInfo& ci )
511 const noexcept;
512
513 /// Calls \b %TryAcquireTimed on the embedded instance specified with template parameter
514 /// \p{TLock}.
515 /// This method participates in the overload resolution only if \p{TLock} provides an
516 /// equivalent method.
517 /// @param waitDuration The point in time, when this method stops waiting.
518 /// @param ci Caller information. Available only with debug-builds.
519 /// @return \c true if the lock was not acquired by a different thread and thus, this call
520 /// was successful. \c false otherwise.
521 [[nodiscard]]
522 bool TryAcquireTimed( const Ticks::Duration::TDuration& waitDuration,
523 const CallerInfo& ci ) const noexcept;
524
525 /// Calls \b %TryAcquireTimed on the embedded instance specified with template parameter
526 /// \p{TLock}.
527 /// This method participates in the overload resolution only if \p{TLock} provides an
528 /// equivalent method.
529 /// @param pointInTime The point in time, when this method stops waiting.
530 /// @param ci Caller information. Available only with debug-builds.
531 /// @return \c true if the lock was not acquired by a different thread and thus, this call
532 /// was successful. \c false otherwise.
533 bool TryAcquireTimed( const Ticks& pointInTime, const CallerInfo& ci ) const noexcept;
534
535 /// Calls \b %TryAcquireTimed on the embedded instance specified with template parameter
536 /// \p{TLock}.
537 /// This method participates in the overload resolution only if \p{TLock} provides an
538 /// equivalent method.
539 /// @param pointInTime The point in time, when this method stops waiting.
540 /// @param ci Caller information. Available only with debug-builds.
541 /// @return \c true if the lock was not acquired by a different thread and thus, this call
542 /// was successful. \c false otherwise.
543 [[nodiscard]]
544 bool TryAcquireTimed( const Ticks::TTimePoint& pointInTime,
545 const CallerInfo& ci ) const noexcept;
546
547 /// Calls \b %TryAcquireSharedTimed on the embedded instance specified with template
548 /// parameter \p{TLock}.
549 /// This method participates in the overload resolution only if \p{TLock} provides an
550 /// equivalent method.
551 /// @param waitDuration The point in time, when this method stops waiting.
552 /// @param ci Caller information. Available only with debug-builds.
553 /// @return \c true if the lock was not acquired by a different thread and thus, this call
554 /// was successful. \c false otherwise.
555 [[nodiscard]]
556 bool TryAcquireSharedTimed( const Ticks::Duration& waitDuration,
557 const CallerInfo& ci ) const noexcept;
558
559 /// Calls \b %TryAcquireSharedTimed on the embedded instance specified with template
560 /// parameter \p{TLock}.
561 /// This method participates in the overload resolution only if \p{TLock} provides an
562 /// equivalent method.
563 /// @param waitDuration The point in time, when this method stops waiting.
564 /// @param ci Caller information. Available only with debug-builds.
565 /// @return \c true if the lock was not acquired by a different thread and thus, this call
566 /// was successful. \c false otherwise.
567 [[nodiscard]]
568 bool TryAcquireSharedTimed( const Ticks::Duration::TDuration& waitDuration,
569 const CallerInfo& ci ) const noexcept;
570
571 /// Calls \b %TryAcquireSharedTimed on the embedded instance specified with template
572 /// parameter \p{TLock}.
573 /// This method participates in the overload resolution only if \p{TLock} provides an
574 /// equivalent method.
575 /// @param pointInTime The point in time, when this method stops waiting.
576 /// @param ci Caller information. Available only with debug-builds.
577 /// @return \c true if the lock was not acquired by a different thread and thus, this call
578 /// was successful. \c false otherwise.
579 [[nodiscard]]
580 bool TryAcquireSharedTimed( const Ticks& pointInTime,
581 const CallerInfo& ci ) const noexcept;
582
583 /// Calls \b %TryAcquireSharedTimed on the embedded instance specified with template
584 /// parameter \p{TLock}.
585 /// This method participates in the overload resolution only if \p{TLock} provides an
586 /// equivalent method.
587 /// @param pointInTime The point in time, when this method stops waiting.
588 /// @param ci Caller information. Available only with debug-builds.
589 /// @return \c true if the lock was not acquired by a different thread and thus, this call
590 /// was successful. \c false otherwise.
591 [[nodiscard]]
592 bool TryAcquireSharedTimed( const Ticks::TTimePoint& pointInTime,
593 const CallerInfo& ci ) const noexcept;
594
595
596 #elif !ALIB_SINGLE_THREADED
597 #define ATPASS ALIB_STATIC_ASSERT(ForbiddenTemplateParameterGiven, std::same_as<TRq ALIB_COMMA TLock>, "Template parameter of this method is deduced by the compiler and must not be given!");
598 template<typename TRq= TLock> requires (!std::same_as<TRq, void> )
599 TRq& GetLock() const noexcept { ATPASS dbgassert(); return members->lock; }
600
601 template<typename TRq= TLock> requires ( ALIB_HAS_METHOD(TRq, Acquire,ALIB_DBG(CallerInfo())) )
602 void Acquire(ALIB_DBG(const CallerInfo& ci)) const noexcept { ATPASS dbgassert(); members->lock.Acquire (ALIB_DBG(ci)); }
603
604 template<typename TRq= TLock> requires ( ALIB_HAS_METHOD(TRq, TryAcquire,ALIB_DBG(CallerInfo())) )
605 bool TryAcquire(ALIB_DBG(const CallerInfo& ci)) const noexcept { ATPASS dbgassert(); return members->lock.TryAcquire (ALIB_DBG(ci)); }
606
607 template<typename TRq= TLock> requires ( ALIB_HAS_METHOD(TRq, Release,ALIB_DBG(CallerInfo())) )
608 void Release(ALIB_DBG(const CallerInfo& ci)) const noexcept { ATPASS dbgassert(); members->lock.Release (ALIB_DBG(ci)); }
609
610 template<typename TRq= TLock> requires ( ALIB_HAS_METHOD(TRq, AcquireRecursive,ALIB_DBG(CallerInfo())) )
611 void AcquireRecursive(ALIB_DBG(const CallerInfo& ci)) const noexcept { ATPASS dbgassert(); members->lock.AcquireRecursive (ALIB_DBG(ci)); }
612
613 template<typename TRq= TLock> requires ( ALIB_HAS_METHOD(TRq, ReleaseRecursive,ALIB_DBG(CallerInfo())) )
614 void ReleaseRecursive(ALIB_DBG(const CallerInfo& ci)) const noexcept { ATPASS dbgassert(); members->lock.ReleaseRecursive (ALIB_DBG(ci)); }
615
616 template<typename TRq= TLock> requires ( ALIB_HAS_METHOD(TRq, AcquireShared,ALIB_DBG(CallerInfo())) )
617 void AcquireShared(ALIB_DBG(const CallerInfo& ci)) const noexcept { ATPASS dbgassert(); members->lock.AcquireShared (ALIB_DBG(ci)); }
618
619 template<typename TRq= TLock> requires ( ALIB_HAS_METHOD(TRq, TryAcquireShared,ALIB_DBG(CallerInfo())) )
620 bool TryAcquireShared(ALIB_DBG(const CallerInfo& ci)) const noexcept { ATPASS dbgassert(); return members->lock.TryAcquireShared (ALIB_DBG(ci)); }
621
622 template<typename TRq= TLock> requires ( ALIB_HAS_METHOD(TRq, ReleaseShared,ALIB_DBG(CallerInfo())) )
623 void ReleaseShared(ALIB_DBG(const CallerInfo& ci)) const noexcept { ATPASS dbgassert(); members->lock.ReleaseShared (ALIB_DBG(ci)); }
624
625 template<typename TRq= TLock> requires ( ALIB_HAS_METHOD(TRq, TryAcquireTimed, Ticks::Duration() ALIB_DBG(,CallerInfo())) )
626 bool TryAcquireTimed( const Ticks::Duration& t ALIB_DBG(,const CallerInfo& ci) ) const noexcept { ATPASS dbgassert(); return members->lock.TryAcquireTimed( t ALIB_DBG(,ci)); }
627
628 template<typename TRq= TLock> requires ( ALIB_HAS_METHOD(TRq, TryAcquireTimed, Ticks::Duration().Export() ALIB_DBG(,CallerInfo())) )
629 bool TryAcquireTimed( const Ticks::Duration::TDuration t ALIB_DBG(,const CallerInfo& ci) ) const noexcept { ATPASS dbgassert(); return members->lock.TryAcquireTimed( t ALIB_DBG(,ci)); }
630
631 template<typename TRq= TLock> requires ( ALIB_HAS_METHOD(TRq, TryAcquireTimed, Ticks() ALIB_DBG(,CallerInfo())) )
632 bool TryAcquireTimed( const Ticks& t ALIB_DBG(,const CallerInfo& ci) ) const noexcept { ATPASS dbgassert(); return members->lock.TryAcquireTimed( t ALIB_DBG(,ci)); }
633
634 template<typename TRq= TLock> requires ( ALIB_HAS_METHOD(TRq, TryAcquireTimed, Ticks().Export() ALIB_DBG(,CallerInfo())) )
635 bool TryAcquireTimed( const Ticks::TTimePoint& t ALIB_DBG(,const CallerInfo& ci) ) const noexcept { ATPASS dbgassert(); return members->lock.TryAcquireTimed( t ALIB_DBG(,ci)); }
636
637 template<typename TRq= TLock> requires ( ALIB_HAS_METHOD(TRq, TryAcquireSharedTimed, Ticks::Duration() ALIB_DBG(,CallerInfo())) )
638 bool TryAcquireSharedTimed( const Ticks::Duration& t ALIB_DBG(,const CallerInfo& ci) ) const noexcept { ATPASS dbgassert(); return members->lock.TryAcquireSharedTimed( t ALIB_DBG(,ci)); }
639
640 template<typename TRq= TLock> requires ( ALIB_HAS_METHOD(TRq, TryAcquireSharedTimed, Ticks::Duration().Export() ALIB_DBG(,CallerInfo())) )
641 bool TryAcquireSharedTimed( const Ticks::Duration::TDuration t ALIB_DBG(,const CallerInfo& ci) ) const noexcept { ATPASS dbgassert(); return members->lock.TryAcquireSharedTimed( t ALIB_DBG(,ci)); }
642
643 template<typename TRq= TLock> requires ( ALIB_HAS_METHOD(TRq, TryAcquireSharedTimed, Ticks() ALIB_DBG(,CallerInfo())) )
644 bool TryAcquireSharedTimed( const Ticks& t ALIB_DBG(,const CallerInfo& ci) ) const noexcept { ATPASS dbgassert(); return members->lock.TryAcquireSharedTimed( t ALIB_DBG(,ci)); }
645
646 template<typename TRq= TLock> requires ( ALIB_HAS_METHOD(TRq, TryAcquireSharedTimed, Ticks().Export() ALIB_DBG(,CallerInfo())) )
647 bool TryAcquireSharedTimed( const Ticks::TTimePoint& t ALIB_DBG(,const CallerInfo& ci) ) const noexcept { ATPASS dbgassert(); return members->lock.TryAcquireSharedTimed( t ALIB_DBG(,ci)); }
648
649 #undef ATPASS
650 #endif
651};
652
653} // namespace alib[::monomem]
654
655
656DOX_MARKER([DOX_MANUAL_ALIASES_SHAREDMONOVAL])
657/// Type alias in namespace #"%alib".
658template<typename T, typename TAllocator= lang::HeapAllocator, typename TLock= void>
660DOX_MARKER([DOX_MANUAL_ALIASES_SHAREDMONOVAL])
661
662} // namespace [alib]
#define ALIB_HAS_METHOD(T, Method,...)
#define ALIB_SINGLE_THREADED
#define ALIB_STATIC_ASSERT(CondVariable, Cond, Message)
#define ALIB_EXPORT
#define ALIB_DBG(...)
#define ALIB_ASSERT_ERROR(cond, domain,...)
bool TryAcquireTimed(const Ticks::Duration &waitDuration, const CallerInfo &ci) const noexcept
void ReleaseShared(const CallerInfo &ci) const noexcept
bool Unique() const noexcept
bool IsNulled() const noexcept
const T * Get() const noexcept
void ReleaseRecursive(const CallerInfo &ci) const noexcept
bool TryAcquireShared(const CallerInfo &ci) const noexcept
void ConstructT(TArgs &&... args)
void AcquireRecursive(const CallerInfo &ci) const noexcept
TLock & GetLock() const noexcept
bool TryAcquire(const CallerInfo &ci) const noexcept
unsigned UseCount() const noexcept
void AcquireShared(const CallerInfo &ci) const noexcept
TSharedMonoVal(std::nullptr_t) noexcept
void Reset(TArgs &&... args)
bool operator==(std::nullptr_t) const noexcept
TSharedMonoVal & operator=(const TSharedMonoVal &other) noexcept
void Release(const CallerInfo &ci) const noexcept
static constexpr size_t SizeOfAllocation()
const T & operator*() const noexcept
const T * operator->() const noexcept
TSharedMonoVal(size_t initialBufferSizeInKB, unsigned bufferGrowthInPercent)
TSharedMonoVal(TSharedMonoVal &&other) noexcept
void Acquire(const CallerInfo &ci) const noexcept
TSharedMonoVal() noexcept
Default Constructor. Leaves this object nulled.
TSharedMonoVal(const TSharedMonoVal &other) noexcept
void operator=(std::nullptr_t)
Assignment of nullptr. Same as #".SetNulled".
std::conditional_t< std::same_as< void, TLock >, FieldMembersNoLock, FieldMembersWithLock > FieldMembers
const T & Self() const noexcept
bool TryAcquireSharedTimed(const Ticks::Duration &waitDuration, const CallerInfo &ci) const noexcept
AllocatorType & GetAllocator() noexcept
TSharedMonoVal(TAllocator &allocator, size_t initialBufferSizeInKB, unsigned bufferGrowthInPercent)
TSharedMonoVal & operator=(TSharedMonoVal &&other) noexcept
bool operator!=(std::nullptr_t) const noexcept
typename std::chrono::steady_clock::time_point TTimePoint
void Destruct(T &object)
Definition tmp.hpp:82
Definition alox.cpp:14
monomem::TSharedMonoVal< T, TAllocator, TLock > TSharedMonoVal
Type alias in namespace #"%alib".
lang::CallerInfo CallerInfo
Type alias in namespace #"%alib".
time::Ticks Ticks
Type alias in namespace #"%alib".
Definition ticks.hpp:86
FieldMembersWithLock(detail::Buffer *firstBuffer, size_t initialBufferSize, unsigned bufferGrowthInPercent)
lang::Placeholder< T > custom
The space for the custom member. The instance will be constructed using placement-new.
std::atomic< unsigned > refCount
The reference counter used to implement the std::shared_ptr behavior.
TMonoAllocator< TAllocator > allocator
The allocator that this class is contained in.
FieldMembersWithLock(TAllocator &pAllocator, detail::Buffer *firstBuffer, size_t initialBufferSize, unsigned bufferGrowthInPercent)