4#ifndef _Stroika_Foundation_Execution_Synchronized_h_
5#define _Stroika_Foundation_Execution_Synchronized_h_ 1
7#include "Stroika/Foundation/StroikaPreComp.h"
14#include <shared_mutex>
17#include "Stroika/Foundation/Common/Common.h"
20#include "Stroika/Foundation/Execution/Common.h"
59 eInternallySynchronized,
60 eNotKnownInternallySynchronized
62 constexpr InternallySynchronized eInternallySynchronized = InternallySynchronized::eInternallySynchronized;
63 constexpr InternallySynchronized eNotKnownInternallySynchronized = InternallySynchronized::eNotKnownInternallySynchronized;
93 template <
typename MUTEX = recursive_mutex>
95 using MutexType = MUTEX;
100 static constexpr bool kIsRecursiveReadMutex = same_as<MUTEX, recursive_mutex> or same_as<MUTEX, recursive_timed_mutex> or
101 same_as<MUTEX, shared_timed_mutex> or same_as<MUTEX, shared_mutex>;
106 static constexpr bool kIsRecursiveLockMutex = same_as<MUTEX, recursive_mutex> or same_as<MUTEX, recursive_timed_mutex>;
115 static constexpr bool kSupportsTimedLocks =
116 same_as<MUTEX, shared_timed_mutex> or same_as<MUTEX, recursive_timed_mutex> or same_as<MUTEX, timed_mutex>;
120 static constexpr bool kSupportSharedLocks = same_as<MUTEX, shared_timed_mutex> or same_as<MUTEX, shared_mutex>;
124 using ReadLockType = conditional_t<kSupportSharedLocks, shared_lock<MUTEX>, unique_lock<MUTEX>>;
128 using WriteLockType = unique_lock<MUTEX>;
132 struct DbgTraceNameObj_ {
134 optional<std::wstring> fDbgTraceLocksName;
140 template <
typename MUTEX>
141 struct Tracing_Synchronized_Traits : Synchronized_Traits<MUTEX> {
142 static constexpr bool kDbgTraceLockUnlockIfNameSet =
true;
245 template <
typename T,
typename TRAITS = Synchronized_Traits<>>
246 class Synchronized :
public conditional_t<TRAITS::kDbgTraceLockUnlockIfNameSet, Private_::DbgTraceNameObj_, Common::Empty> {
248 using element_type = T;
251 using MutexType =
typename TRAITS::MutexType;
257 class WritableReference;
269 template <
typename... ARGUMENT_TYPES>
271 requires (constructible_from<T, ARGUMENT_TYPES...>);
295 nonvirtual
operator T ()
const
296 requires (TRAITS::kIsRecursiveReadMutex);
318 nonvirtual T
load ()
const
319 requires (TRAITS::kIsRecursiveReadMutex);
320 nonvirtual T
load (
const chrono::duration<double>& tryFor)
const
321 requires (TRAITS::kIsRecursiveReadMutex and TRAITS::kSupportsTimedLocks);
334 nonvirtual
void store (
const T& v)
335 requires (TRAITS::kIsRecursiveLockMutex);
336 nonvirtual
void store (T&& v)
337 requires (TRAITS::kIsRecursiveLockMutex);
338 nonvirtual
void store (
const T& v,
const chrono::duration<double>& tryFor)
339 requires (TRAITS::kIsRecursiveLockMutex and TRAITS::kSupportsTimedLocks);
340 nonvirtual
void store (T&& v,
const chrono::duration<double>& tryFor)
341 requires (TRAITS::kIsRecursiveLockMutex and TRAITS::kSupportsTimedLocks);
377 requires (TRAITS::kSupportsTimedLocks);
386 nonvirtual WritableReference
rwget ();
387 nonvirtual WritableReference
rwget (
const chrono::duration<double>& tryFor)
388 requires (TRAITS::kSupportsTimedLocks);
415 requires (TRAITS::kIsRecursiveReadMutex and TRAITS::kSupportSharedLocks);
426 requires (TRAITS::kIsRecursiveReadMutex and TRAITS::kSupportSharedLocks);
436 nonvirtual
void lock ()
const
437 requires (TRAITS::kIsRecursiveReadMutex);
448 requires (TRAITS::kIsRecursiveReadMutex);
458 nonvirtual
bool try_lock_for (
const chrono::duration<double>& tryFor)
const
459 requires (TRAITS::kIsRecursiveReadMutex and TRAITS::kSupportsTimedLocks);
469 nonvirtual
void unlock ()
const
470 requires (TRAITS::kIsRecursiveReadMutex);
475 nonvirtual
bool operator== (
const Synchronized& rhs)
const
476 requires (TRAITS::kIsRecursiveReadMutex and equality_comparable<T>);
477 nonvirtual
bool operator== (
const T& rhs)
const
478 requires (TRAITS::kIsRecursiveReadMutex and equality_comparable<T>);
483 nonvirtual
auto operator<=> (
const Synchronized& rhs)
const
484 requires (TRAITS::kIsRecursiveReadMutex and three_way_comparable<T>);
485 nonvirtual
auto operator<=> (
const T& rhs)
const
486 requires (TRAITS::kIsRecursiveReadMutex and three_way_comparable<T>);
534 requires (TRAITS::kSupportSharedLocks and TRAITS::kSupportsTimedLocks);
536 const function<
bool (WritableReference&&,
bool interveningWriteLock)>& doWithWriteLock,
538 requires (TRAITS::kSupportSharedLocks and TRAITS::kSupportsTimedLocks);
569 requires (TRAITS::kSupportSharedLocks and TRAITS::kSupportsTimedLocks);
571 const function<
bool (WritableReference&&,
bool interveningWriteLock)>& doWithWriteLock,
573 requires (TRAITS::kSupportSharedLocks and TRAITS::kSupportsTimedLocks);
577 nonvirtual
void NoteLockStateChanged_ (
const wchar_t* m)
const noexcept;
580 using ReadLockType_ =
typename TRAITS::ReadLockType;
583 using WriteLockType_ =
typename TRAITS::WriteLockType;
587 mutable MutexType fMutex_;
592 mutable unsigned int fWriteLockCount_{0};
599 template <
typename T,
typename TRAITS>
601 :
public conditional_t<TRAITS::kDbgTraceLockUnlockIfNameSet, Private_::DbgTraceNameObj_, Common::Empty> {
617 ReadableReference (
const Synchronized* s);
619 ReadableReference (
const Synchronized* s, ReadLockType_&& readLock);
622 ReadableReference (
const ReadableReference& src) =
delete;
625 ReadableReference (ReadableReference&& src);
628 nonvirtual
const ReadableReference& operator= (
const ReadableReference& rhs) =
delete;
631 ~ReadableReference ();
639 nonvirtual
const T* operator->()
const;
644 nonvirtual
const T& cref ()
const;
652 nonvirtual
operator const T& ()
const;
658 nonvirtual T
load ()
const;
664 nonvirtual
void _NoteLockStateChanged (
const wchar_t* m)
const;
667 ReadLockType_ fSharedLock_{};
675 template <
typename T,
typename TRAITS>
676 class Synchronized<T, TRAITS>::WritableReference :
public Synchronized<T, TRAITS>::ReadableReference {
678 using inherited =
typename Synchronized<T, TRAITS>::ReadableReference;
683 WritableReference (Synchronized* s);
684 WritableReference (Synchronized* s, WriteLockType_&& writeLock);
685 WritableReference (Synchronized* s, Time::DurationSeconds timeout);
686 WritableReference (
const WritableReference& src) =
delete;
689 WritableReference (WritableReference&& src);
690 nonvirtual WritableReference& operator= (
const WritableReference& rhs) =
delete;
691 nonvirtual
const WritableReference& operator= (T rhs);
699 nonvirtual T* operator->();
700 nonvirtual
const T* operator->()
const;
712 nonvirtual T& rwref ();
717 nonvirtual
void store (
const T& v);
718 nonvirtual
void store (T&& v);
721 WriteLockType_ fWriteLock_;
729 template <
typename T,
typename TRAITS>
730 auto operator^ (
const Synchronized<T, TRAITS>& lhs, T rhs) ->
decltype (T{} ^ T{});
731 template <
typename T,
typename TRAITS>
732 auto operator^ (T lhs,
const Synchronized<T, TRAITS>& rhs) ->
decltype (T{} ^ T{});
733 template <
typename T,
typename TRAITS>
734 auto operator^ (
const Synchronized<T, TRAITS>& lhs,
const Synchronized<T, TRAITS>& rhs) ->
decltype (T{} ^ T{});
738 template <
typename T,
typename TRAITS>
739 auto operator* (
const Synchronized<T, TRAITS>& lhs, T rhs) ->
decltype (T{} * T{});
740 template <
typename T,
typename TRAITS>
741 auto operator* (T lhs,
const Synchronized<T, TRAITS>& rhs) ->
decltype (T{} * T{});
742 template <
typename T,
typename TRAITS>
743 auto operator* (
const Synchronized<T, TRAITS>& lhs,
const Synchronized<T, TRAITS>& rhs) ->
decltype (T{} * T{});
747 template <
typename T,
typename TRAITS>
748 auto operator+ (
const Synchronized<T, TRAITS>& lhs, T rhs) ->
decltype (T{} + T{});
749 template <
typename T,
typename TRAITS>
750 auto operator+ (T lhs,
const Synchronized<T, TRAITS>& rhs) ->
decltype (T{} + T{});
751 template <
typename T,
typename TRAITS>
752 auto operator+ (
const Synchronized<T, TRAITS>& lhs,
const Synchronized<T, TRAITS>& rhs) ->
decltype (T{} + T{});
756 template <
typename T,
typename TRAITS,
typename RHSTYPE>
757 auto operator-= (Synchronized<T, TRAITS>& lhs, RHSTYPE rhs) ->
decltype (lhs.rwget ()->operator-= (rhs));
761 template <
typename T,
typename TRAITS,
typename RHSTYPE>
762 auto operator+= (Synchronized<T, TRAITS>& lhs, RHSTYPE rhs) ->
decltype (lhs.rwget ()->operator+= (rhs));
766 template <
typename T,
typename TRAITS>
767 auto operator- (
const Synchronized<T, TRAITS>& lhs, T rhs) ->
decltype (T{} - T{});
768 template <
typename T,
typename TRAITS>
769 auto operator- (T lhs,
const Synchronized<T, TRAITS>& rhs) ->
decltype (T{} - T{});
770 template <
typename T,
typename TRAITS>
771 auto operator- (
const Synchronized<T, TRAITS>& lhs,
const Synchronized<T, TRAITS>& rhs) ->
decltype (T{} - T{});
778 template <
typename T>
785 template <
typename T>
795 template <
typename T>
805#include "Synchronized.inl"
chrono::duration< double > DurationSeconds
chrono::duration<double> - a time span (length of time) measured in seconds, but high precision.
Wrap any object with Synchronized<> and it can be used similarly to the base type,...
nonvirtual WritableReference rwget()
get a read-write smart pointer to the underlying Synchronized<> object, holding the full lock the who...
nonvirtual void store(const T &v)
nonvirtual bool try_lock() const
nonvirtual void UpgradeLockNonAtomically(ReadableReference *lockBeingUpgraded, const function< void(WritableReference &&)> &doWithWriteLock, Time::DurationSeconds timeout=Time::kInfinity)
Same as UpgradeLockNonAtomicallyQuietly, but throws on failure (either timeout or if argument functio...
nonvirtual bool UpgradeLockNonAtomicallyQuietly(ReadableReference *lockBeingUpgraded, const function< void(WritableReference &&)> &doWithWriteLock, Time::DurationSeconds timeout=Time::kInfinity)
Upgrade a shared_lock (ReadableReference) to a (WritableReference) full lock temporarily in the conte...
nonvirtual bool try_lock_for(const chrono::duration< double > &tryFor) const
nonvirtual void lock() const
nonvirtual ReadableReference cget() const
get a read-only smart pointer to the underlying Synchronized<> object, holding the readlock the whole...
Synchronized(ARGUMENT_TYPES &&... args)
nonvirtual void unlock() const
nonvirtual void lock_shared() const
nonvirtual void unlock_shared() const
nonvirtual T load() const
conditional_t< kSpinLock_IsFasterThan_mutex, Synchronized< T, Synchronized_Traits< SpinLock > >, Synchronized< T, Synchronized_Traits< mutex > > > QuickSynchronized
static constexpr bool kDbgTraceLockUnlockIfNameSet
static constexpr bool kIsRecursiveReadMutex
static constexpr bool kIsRecursiveLockMutex