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