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"
55 eInternallySynchronized,
56 eNotKnownInternallySynchronized
58 constexpr InternallySynchronized eInternallySynchronized = InternallySynchronized::eInternallySynchronized;
59 constexpr InternallySynchronized eNotKnownInternallySynchronized = InternallySynchronized::eNotKnownInternallySynchronized;
89 template <
typename MUTEX = recursive_mutex>
91 using MutexType = MUTEX;
96 static constexpr bool kIsRecursiveReadMutex = same_as<MUTEX, recursive_mutex> or same_as<MUTEX, recursive_timed_mutex> or
97 same_as<MUTEX, shared_timed_mutex> or same_as<MUTEX, shared_mutex>;
102 static constexpr bool kIsRecursiveLockMutex = same_as<MUTEX, recursive_mutex> or same_as<MUTEX, recursive_timed_mutex>;
111 static constexpr bool kSupportsTimedLocks =
112 same_as<MUTEX, shared_timed_mutex> or same_as<MUTEX, recursive_timed_mutex> or same_as<MUTEX, timed_mutex>;
116 static constexpr bool kSupportSharedLocks = same_as<MUTEX, shared_timed_mutex> or same_as<MUTEX, shared_mutex>;
120 using ReadLockType = conditional_t<kSupportSharedLocks, shared_lock<MUTEX>, unique_lock<MUTEX>>;
124 using WriteLockType = unique_lock<MUTEX>;
128 struct DbgTraceNameObj_ {
130 optional<std::wstring> fDbgTraceLocksName;
136 template <
typename MUTEX>
137 struct Tracing_Synchronized_Traits : Synchronized_Traits<MUTEX> {
138 static constexpr bool kDbgTraceLockUnlockIfNameSet =
true;
241 template <
typename T,
typename TRAITS = Synchronized_Traits<>>
242 class Synchronized :
public conditional_t<TRAITS::kDbgTraceLockUnlockIfNameSet, Private_::DbgTraceNameObj_, Common::Empty> {
244 using element_type = T;
247 using MutexType =
typename TRAITS::MutexType;
253 class WritableReference;
265 template <
typename... ARGUMENT_TYPES>
267 requires (constructible_from<T, ARGUMENT_TYPES...>);
291 nonvirtual
operator T ()
const
292 requires (TRAITS::kIsRecursiveReadMutex);
314 nonvirtual T
load ()
const
315 requires (TRAITS::kIsRecursiveReadMutex);
316 nonvirtual T
load (
const chrono::duration<double>& tryFor)
const
317 requires (TRAITS::kIsRecursiveReadMutex and TRAITS::kSupportsTimedLocks);
330 nonvirtual
void store (
const T& v)
331 requires (TRAITS::kIsRecursiveLockMutex);
332 nonvirtual
void store (T&& v)
333 requires (TRAITS::kIsRecursiveLockMutex);
334 nonvirtual
void store (
const T& v,
const chrono::duration<double>& tryFor)
335 requires (TRAITS::kIsRecursiveLockMutex and TRAITS::kSupportsTimedLocks);
336 nonvirtual
void store (T&& v,
const chrono::duration<double>& tryFor)
337 requires (TRAITS::kIsRecursiveLockMutex and TRAITS::kSupportsTimedLocks);
373 requires (TRAITS::kSupportsTimedLocks);
382 nonvirtual WritableReference
rwget ();
383 nonvirtual WritableReference
rwget (
const chrono::duration<double>& tryFor)
384 requires (TRAITS::kSupportsTimedLocks);
411 requires (TRAITS::kIsRecursiveReadMutex and TRAITS::kSupportSharedLocks);
422 requires (TRAITS::kIsRecursiveReadMutex and TRAITS::kSupportSharedLocks);
432 nonvirtual
void lock ()
const
433 requires (TRAITS::kIsRecursiveReadMutex);
444 requires (TRAITS::kIsRecursiveReadMutex);
454 nonvirtual
bool try_lock_for (
const chrono::duration<double>& tryFor)
const
455 requires (TRAITS::kIsRecursiveReadMutex and TRAITS::kSupportsTimedLocks);
465 nonvirtual
void unlock ()
const
466 requires (TRAITS::kIsRecursiveReadMutex);
471 nonvirtual
bool operator== (
const Synchronized& rhs)
const
472 requires (TRAITS::kIsRecursiveReadMutex and equality_comparable<T>);
473 nonvirtual
bool operator== (
const T& rhs)
const
474 requires (TRAITS::kIsRecursiveReadMutex and equality_comparable<T>);
479 nonvirtual
auto operator<=> (
const Synchronized& rhs)
const
480 requires (TRAITS::kIsRecursiveReadMutex and three_way_comparable<T>);
481 nonvirtual
auto operator<=> (
const T& rhs)
const
482 requires (TRAITS::kIsRecursiveReadMutex and three_way_comparable<T>);
530 requires (TRAITS::kSupportSharedLocks and TRAITS::kSupportsTimedLocks);
532 const function<
bool (WritableReference&&,
bool interveningWriteLock)>& doWithWriteLock,
534 requires (TRAITS::kSupportSharedLocks and TRAITS::kSupportsTimedLocks);
565 requires (TRAITS::kSupportSharedLocks and TRAITS::kSupportsTimedLocks);
567 const function<
bool (WritableReference&&,
bool interveningWriteLock)>& doWithWriteLock,
569 requires (TRAITS::kSupportSharedLocks and TRAITS::kSupportsTimedLocks);
573 nonvirtual
void NoteLockStateChanged_ (
const wchar_t* m)
const noexcept;
576 using ReadLockType_ =
typename TRAITS::ReadLockType;
579 using WriteLockType_ =
typename TRAITS::WriteLockType;
583 mutable MutexType fMutex_;
588 mutable unsigned int fWriteLockCount_{0};
595 template <
typename T,
typename TRAITS>
597 :
public conditional_t<TRAITS::kDbgTraceLockUnlockIfNameSet, Private_::DbgTraceNameObj_, Common::Empty> {
613 ReadableReference (
const Synchronized* s);
615 ReadableReference (
const Synchronized* s, ReadLockType_&& readLock);
618 ReadableReference (
const ReadableReference& src) =
delete;
621 ReadableReference (ReadableReference&& src);
624 nonvirtual
const ReadableReference& operator= (
const ReadableReference& rhs) =
delete;
627 ~ReadableReference ();
635 nonvirtual
const T* operator->()
const;
640 nonvirtual
const T& cref ()
const;
648 nonvirtual
operator const T& ()
const;
654 nonvirtual T
load ()
const;
660 nonvirtual
void _NoteLockStateChanged (
const wchar_t* m)
const;
663 ReadLockType_ fSharedLock_{};
671 template <
typename T,
typename TRAITS>
672 class Synchronized<T, TRAITS>::WritableReference :
public Synchronized<T, TRAITS>::ReadableReference {
674 using inherited =
typename Synchronized<T, TRAITS>::ReadableReference;
679 WritableReference (Synchronized* s);
680 WritableReference (Synchronized* s, WriteLockType_&& writeLock);
681 WritableReference (Synchronized* s, Time::DurationSeconds timeout);
682 WritableReference (
const WritableReference& src) =
delete;
685 WritableReference (WritableReference&& src);
686 nonvirtual WritableReference& operator= (
const WritableReference& rhs) =
delete;
687 nonvirtual
const WritableReference& operator= (T rhs);
695 nonvirtual T* operator->();
696 nonvirtual
const T* operator->()
const;
708 nonvirtual T& rwref ();
713 nonvirtual
void store (
const T& v);
714 nonvirtual
void store (T&& v);
717 WriteLockType_ fWriteLock_;
725 template <
typename T,
typename TRAITS>
726 auto operator^ (
const Synchronized<T, TRAITS>& lhs, T rhs) ->
decltype (T{} ^ T{});
727 template <
typename T,
typename TRAITS>
728 auto operator^ (T lhs,
const Synchronized<T, TRAITS>& rhs) ->
decltype (T{} ^ T{});
729 template <
typename T,
typename TRAITS>
730 auto operator^ (
const Synchronized<T, TRAITS>& lhs,
const Synchronized<T, TRAITS>& rhs) ->
decltype (T{} ^ T{});
734 template <
typename T,
typename TRAITS>
735 auto operator* (
const Synchronized<T, TRAITS>& lhs, T rhs) ->
decltype (T{} * T{});
736 template <
typename T,
typename TRAITS>
737 auto operator* (T lhs,
const Synchronized<T, TRAITS>& rhs) ->
decltype (T{} * T{});
738 template <
typename T,
typename TRAITS>
739 auto operator* (
const Synchronized<T, TRAITS>& lhs,
const Synchronized<T, TRAITS>& rhs) ->
decltype (T{} * T{});
743 template <
typename T,
typename TRAITS>
744 auto operator+ (
const Synchronized<T, TRAITS>& lhs, T rhs) ->
decltype (T{} + T{});
745 template <
typename T,
typename TRAITS>
746 auto operator+ (T lhs,
const Synchronized<T, TRAITS>& rhs) ->
decltype (T{} + T{});
747 template <
typename T,
typename TRAITS>
748 auto operator+ (
const Synchronized<T, TRAITS>& lhs,
const Synchronized<T, TRAITS>& rhs) ->
decltype (T{} + T{});
752 template <
typename T,
typename TRAITS,
typename RHSTYPE>
753 auto operator-= (Synchronized<T, TRAITS>& lhs, RHSTYPE rhs) ->
decltype (lhs.rwget ()->operator-= (rhs));
757 template <
typename T,
typename TRAITS,
typename RHSTYPE>
758 auto operator+= (Synchronized<T, TRAITS>& lhs, RHSTYPE rhs) ->
decltype (lhs.rwget ()->operator+= (rhs));
762 template <
typename T,
typename TRAITS>
763 auto operator- (
const Synchronized<T, TRAITS>& lhs, T rhs) ->
decltype (T{} - T{});
764 template <
typename T,
typename TRAITS>
765 auto operator- (T lhs,
const Synchronized<T, TRAITS>& rhs) ->
decltype (T{} - T{});
766 template <
typename T,
typename TRAITS>
767 auto operator- (
const Synchronized<T, TRAITS>& lhs,
const Synchronized<T, TRAITS>& rhs) ->
decltype (T{} - T{});
774 template <
typename T>
781 template <
typename T>
791 template <
typename T>
801#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