4#ifndef _Stroika_Foundation_Execution_Synchronized_h_
5#define _Stroika_Foundation_Execution_Synchronized_h_ 1
7#include "Stroika/Foundation/StroikaPreComp.h"
13#include <shared_mutex>
16#include "Stroika/Foundation/Common/Common.h"
19#include "Stroika/Foundation/Execution/Common.h"
54 eInternallySynchronized,
55 eNotKnownInternallySynchronized
57 constexpr InternallySynchronized eInternallySynchronized = InternallySynchronized::eInternallySynchronized;
58 constexpr InternallySynchronized eNotKnownInternallySynchronized = InternallySynchronized::eNotKnownInternallySynchronized;
88 template <
typename MUTEX = recursive_mutex>
90 using MutexType = MUTEX;
95 static constexpr bool kIsRecursiveReadMutex = same_as<MUTEX, recursive_mutex> or same_as<MUTEX, recursive_timed_mutex> or
96 same_as<MUTEX, shared_timed_mutex> or same_as<MUTEX, shared_mutex>;
101 static constexpr bool kIsRecursiveLockMutex = same_as<MUTEX, recursive_mutex> or same_as<MUTEX, recursive_timed_mutex>;
110 static constexpr bool kSupportsTimedLocks =
111 same_as<MUTEX, shared_timed_mutex> or same_as<MUTEX, recursive_timed_mutex> or same_as<MUTEX, timed_mutex>;
115 static constexpr bool kSupportSharedLocks = same_as<MUTEX, shared_timed_mutex> or same_as<MUTEX, shared_mutex>;
119 using ReadLockType = conditional_t<kSupportSharedLocks, shared_lock<MUTEX>, unique_lock<MUTEX>>;
123 using WriteLockType = unique_lock<MUTEX>;
127 struct DbgTraceNameObj_ {
129 optional<std::wstring> fDbgTraceLocksName;
135 template <
typename MUTEX>
136 struct Tracing_Synchronized_Traits : Synchronized_Traits<MUTEX> {
137 static constexpr bool kDbgTraceLockUnlockIfNameSet =
true;
240 template <
typename T,
typename TRAITS = Synchronized_Traits<>>
241 class Synchronized :
public conditional_t<TRAITS::kDbgTraceLockUnlockIfNameSet, Private_::DbgTraceNameObj_, Common::Empty> {
243 using element_type = T;
246 using MutexType =
typename TRAITS::MutexType;
252 class WritableReference;
264 template <
typename... ARGUMENT_TYPES>
290 nonvirtual
operator T ()
const
291 requires (TRAITS::kIsRecursiveReadMutex);
313 nonvirtual T
load ()
const
314 requires (TRAITS::kIsRecursiveReadMutex);
315 nonvirtual T
load (
const chrono::duration<double>& tryFor)
const
316 requires (TRAITS::kIsRecursiveReadMutex and TRAITS::kSupportsTimedLocks);
329 nonvirtual
void store (
const T& v)
330 requires (TRAITS::kIsRecursiveLockMutex);
331 nonvirtual
void store (T&& v)
332 requires (TRAITS::kIsRecursiveLockMutex);
333 nonvirtual
void store (
const T& v,
const chrono::duration<double>& tryFor)
334 requires (TRAITS::kIsRecursiveLockMutex and TRAITS::kSupportsTimedLocks);
335 nonvirtual
void store (T&& v,
const chrono::duration<double>& tryFor)
336 requires (TRAITS::kIsRecursiveLockMutex and TRAITS::kSupportsTimedLocks);
372 requires (TRAITS::kSupportsTimedLocks);
381 nonvirtual WritableReference
rwget ();
382 nonvirtual WritableReference
rwget (
const chrono::duration<double>& tryFor)
383 requires (TRAITS::kSupportsTimedLocks);
410 requires (TRAITS::kIsRecursiveReadMutex and TRAITS::kSupportSharedLocks);
421 requires (TRAITS::kIsRecursiveReadMutex and TRAITS::kSupportSharedLocks);
431 nonvirtual
void lock ()
const
432 requires (TRAITS::kIsRecursiveReadMutex);
443 requires (TRAITS::kIsRecursiveReadMutex);
453 nonvirtual
bool try_lock_for (
const chrono::duration<double>& tryFor)
const
454 requires (TRAITS::kIsRecursiveReadMutex and TRAITS::kSupportsTimedLocks);
464 nonvirtual
void unlock ()
const
465 requires (TRAITS::kIsRecursiveReadMutex);
470 nonvirtual
bool operator== (
const Synchronized& rhs)
const
471 requires (TRAITS::kIsRecursiveReadMutex and equality_comparable<T>);
472 nonvirtual
bool operator== (
const T& rhs)
const
473 requires (TRAITS::kIsRecursiveReadMutex and equality_comparable<T>);
478 nonvirtual
auto operator<=> (
const Synchronized& rhs)
const
479 requires (TRAITS::kIsRecursiveReadMutex and three_way_comparable<T>);
480 nonvirtual
auto operator<=> (
const T& rhs)
const
481 requires (TRAITS::kIsRecursiveReadMutex and three_way_comparable<T>);
529 requires (TRAITS::kSupportSharedLocks and TRAITS::kSupportsTimedLocks);
531 const function<
bool (WritableReference&&,
bool interveningWriteLock)>& doWithWriteLock,
533 requires (TRAITS::kSupportSharedLocks and TRAITS::kSupportsTimedLocks);
564 requires (TRAITS::kSupportSharedLocks and TRAITS::kSupportsTimedLocks);
566 const function<
bool (WritableReference&&,
bool interveningWriteLock)>& doWithWriteLock,
568 requires (TRAITS::kSupportSharedLocks and TRAITS::kSupportsTimedLocks);
572 nonvirtual
void NoteLockStateChanged_ (
const wchar_t* m)
const noexcept;
575 using ReadLockType_ =
typename TRAITS::ReadLockType;
578 using WriteLockType_ =
typename TRAITS::WriteLockType;
582 mutable MutexType fMutex_;
587 mutable unsigned int fWriteLockCount_{0};
594 template <
typename T,
typename TRAITS>
596 :
public conditional_t<TRAITS::kDbgTraceLockUnlockIfNameSet, Private_::DbgTraceNameObj_, Common::Empty> {
612 ReadableReference (
const Synchronized* s);
614 ReadableReference (
const Synchronized* s, ReadLockType_&& readLock);
617 ReadableReference (
const ReadableReference& src) =
delete;
620 ReadableReference (ReadableReference&& src);
623 nonvirtual
const ReadableReference& operator= (
const ReadableReference& rhs) =
delete;
626 ~ReadableReference ();
634 nonvirtual
const T* operator->()
const;
639 nonvirtual
const T& cref ()
const;
647 nonvirtual
operator const T& ()
const;
653 nonvirtual T
load ()
const;
659 nonvirtual
void _NoteLockStateChanged (
const wchar_t* m)
const;
662 ReadLockType_ fSharedLock_{};
670 template <
typename T,
typename TRAITS>
671 class Synchronized<T, TRAITS>::WritableReference :
public Synchronized<T, TRAITS>::ReadableReference {
673 using inherited =
typename Synchronized<T, TRAITS>::ReadableReference;
678 WritableReference (Synchronized* s);
679 WritableReference (Synchronized* s, WriteLockType_&& writeLock);
680 WritableReference (Synchronized* s, Time::DurationSeconds timeout);
681 WritableReference (
const WritableReference& src) =
delete;
684 WritableReference (WritableReference&& src);
685 nonvirtual WritableReference& operator= (
const WritableReference& rhs) =
delete;
686 nonvirtual
const WritableReference& operator= (T rhs);
694 nonvirtual T* operator->();
695 nonvirtual
const T* operator->()
const;
707 nonvirtual T& rwref ();
712 nonvirtual
void store (
const T& v);
713 nonvirtual
void store (T&& v);
716 WriteLockType_ fWriteLock_;
724 template <
typename T,
typename TRAITS>
725 auto operator^ (
const Synchronized<T, TRAITS>& lhs, T rhs) ->
decltype (T{} ^ T{});
726 template <
typename T,
typename TRAITS>
727 auto operator^ (T lhs,
const Synchronized<T, TRAITS>& rhs) ->
decltype (T{} ^ T{});
728 template <
typename T,
typename TRAITS>
729 auto operator^ (
const Synchronized<T, TRAITS>& lhs,
const Synchronized<T, TRAITS>& rhs) ->
decltype (T{} ^ T{});
733 template <
typename T,
typename TRAITS>
734 auto operator* (
const Synchronized<T, TRAITS>& lhs, T rhs) ->
decltype (T{} * T{});
735 template <
typename T,
typename TRAITS>
736 auto operator* (T lhs,
const Synchronized<T, TRAITS>& rhs) ->
decltype (T{} * T{});
737 template <
typename T,
typename TRAITS>
738 auto operator* (
const Synchronized<T, TRAITS>& lhs,
const Synchronized<T, TRAITS>& rhs) ->
decltype (T{} * T{});
742 template <
typename T,
typename TRAITS>
743 auto operator+ (
const Synchronized<T, TRAITS>& lhs, T rhs) ->
decltype (T{} + T{});
744 template <
typename T,
typename TRAITS>
745 auto operator+ (T lhs,
const Synchronized<T, TRAITS>& rhs) ->
decltype (T{} + T{});
746 template <
typename T,
typename TRAITS>
747 auto operator+ (
const Synchronized<T, TRAITS>& lhs,
const Synchronized<T, TRAITS>& rhs) ->
decltype (T{} + T{});
751 template <
typename T,
typename TRAITS,
typename RHSTYPE>
752 auto operator-= (Synchronized<T, TRAITS>& lhs, RHSTYPE rhs) ->
decltype (lhs.rwget ()->operator-= (rhs));
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>
762 auto operator- (
const Synchronized<T, TRAITS>& lhs, T rhs) ->
decltype (T{} - T{});
763 template <
typename T,
typename TRAITS>
764 auto operator- (T lhs,
const Synchronized<T, TRAITS>& rhs) ->
decltype (T{} - T{});
765 template <
typename T,
typename TRAITS>
766 auto operator- (
const Synchronized<T, TRAITS>& lhs,
const Synchronized<T, TRAITS>& rhs) ->
decltype (T{} - T{});
773 template <
typename T>
780 template <
typename T>
790 template <
typename T>
800#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...
Synchronized(ARGUMENT_TYPES &&... args)
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...
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