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