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