8namespace Stroika::Foundation::Debug {
15#if qStroika_Foundation_Debug_AssertExternallySynchronizedMutex_Enabled
16 inline AssertExternallySynchronizedMutex::SharedContext ::~SharedContext ()
18 Assert (fFullLocks_ == 0);
19 Assert (fSharedLocks_.fOverflowThreads_.empty () and fSharedLocks_.fInitialThreadsSize_ == 0);
21 inline bool AssertExternallySynchronizedMutex ::SharedContext ::GetSharedLockEmpty_ ()
const
23 lock_guard<mutex> sharedLockProtect{GetSharedLockMutexThreads_ ()};
24 return fSharedLocks_.fInitialThreadsSize_ == 0 and fSharedLocks_.fOverflowThreads_.empty ();
26 inline pair<size_t, size_t> AssertExternallySynchronizedMutex ::SharedContext ::CountSharedLockThreads_ ()
const
28 auto tid = this_thread::get_id ();
29 lock_guard<mutex> sharedLockProtect{GetSharedLockMutexThreads_ ()};
30 size_t thisThreadCnt = std::count (fSharedLocks_.fInitialThreads_.begin (),
31 fSharedLocks_.fInitialThreads_.begin () + fSharedLocks_.fInitialThreadsSize_, tid) and
32 std::count (fSharedLocks_.fOverflowThreads_.begin (), fSharedLocks_.fOverflowThreads_.end (), tid);
33 size_t otherThreadCnt = fSharedLocks_.fInitialThreadsSize_ +
34 std::distance (fSharedLocks_.fOverflowThreads_.begin (), fSharedLocks_.fOverflowThreads_.end ());
35 otherThreadCnt -= thisThreadCnt;
36 return make_pair (thisThreadCnt, otherThreadCnt);
38 inline size_t AssertExternallySynchronizedMutex ::SharedContext ::GetSharedLockThreadsCount_ ()
const
40 lock_guard<mutex> sharedLockProtect{GetSharedLockMutexThreads_ ()};
41 return fSharedLocks_.fInitialThreadsSize_ + std::distance (fSharedLocks_.fOverflowThreads_.begin (), fSharedLocks_.fOverflowThreads_.end ());
43 inline size_t AssertExternallySynchronizedMutex ::SharedContext ::CountOfIInSharedLockThreads_ (thread::id i)
const
45 lock_guard<mutex> sharedLockProtect{GetSharedLockMutexThreads_ ()};
46 return std::count (fSharedLocks_.fInitialThreads_.begin (), fSharedLocks_.fInitialThreads_.begin () + fSharedLocks_.fInitialThreadsSize_, i) +
47 std::count (fSharedLocks_.fOverflowThreads_.begin (), fSharedLocks_.fOverflowThreads_.end (), i);
49 inline void AssertExternallySynchronizedMutex ::SharedContext ::AddSharedLock_ (thread::id i)
51 lock_guard<mutex> sharedLockProtect{GetSharedLockMutexThreads_ ()};
52 if (fSharedLocks_.fInitialThreadsSize_ < kInlineSharedLockBufSize_) {
53 fSharedLocks_.fInitialThreads_[fSharedLocks_.fInitialThreadsSize_++] = i;
56 fSharedLocks_.fOverflowThreads_.push_front (i);
59 inline void AssertExternallySynchronizedMutex ::SharedContext ::RemoveSharedLock_ (thread::id i)
61 lock_guard<mutex> sharedLockProtect{GetSharedLockMutexThreads_ ()};
62 if constexpr (kInlineSharedLockBufSize_ != 0) {
63 auto re = fSharedLocks_.fInitialThreads_.begin () + fSharedLocks_.fInitialThreadsSize_;
64 auto ri = find (fSharedLocks_.fInitialThreads_.begin (), re, i);
67 copy (ri + 1, re, ri);
69 --fSharedLocks_.fInitialThreadsSize_;
73 auto re = fSharedLocks_.fOverflowThreads_.end ();
74 for (
auto beforeI = fSharedLocks_.fOverflowThreads_.before_begin ();; ++beforeI) {
75 Assert (beforeI != re);
80 fSharedLocks_.fOverflowThreads_.erase_after (beforeI);
93#if qStroika_Foundation_Debug_AssertExternallySynchronizedMutex_Enabled
100 : fSharedContext_{sharedContext ? sharedContext : make_shared<SharedContext> ()}
104 const AssertExternallySynchronizedMutex& src) noexcept
105 : AssertExternallySynchronizedMutex{sharedContext}
107 ReadContext readLockSrc{src};
110 : AssertExternallySynchronizedMutex{}
112 ReadContext readLockSrc{src};
115 [[maybe_unused]] AssertExternallySynchronizedMutex&& src) noexcept
116 : AssertExternallySynchronizedMutex{sharedContext}
118 WriteContext declareWriteContext4Src{src};
121 : AssertExternallySynchronizedMutex{}
123 WriteContext writeLockRHS{src};
128 ReadContext readLockRHS{rhs};
129 WriteContext declareWriteContext4This{*
this};
138#if qStroika_Foundation_Debug_AssertExternallySynchronizedMutex_Enabled
139 inline auto AssertExternallySynchronizedMutex::GetSharedContext () const -> shared_ptr<SharedContext>
141 return fSharedContext_;
143 inline void AssertExternallySynchronizedMutex::SetAssertExternallySynchronizedMutexContext (
const shared_ptr<SharedContext>& sharedContext)
145 Require (sharedContext !=
nullptr);
146 fSharedContext_ = sharedContext;
151#if qStroika_Foundation_Debug_AssertExternallySynchronizedMutex_Enabled
157#if qStroika_Foundation_Debug_AssertExternallySynchronizedMutex_Enabled
163#if qStroika_Foundation_Debug_AssertExternallySynchronizedMutex_Enabled
169#if qStroika_Foundation_Debug_AssertExternallySynchronizedMutex_Enabled
#define RequireNotReached()
NOT a real mutex - just a debugging infrastructure support tool so in debug builds can be assured thr...
nonvirtual AssertExternallySynchronizedMutex & operator=(AssertExternallySynchronizedMutex &&rhs) noexcept
constexpr AssertExternallySynchronizedMutex() noexcept=default
nonvirtual void lock_shared() const noexcept
nonvirtual void lock() noexcept
nonvirtual void unlock() noexcept
nonvirtual void unlock_shared() const noexcept
unique_lock< AssertExternallySynchronizedMutex > WriteContext
Instantiate AssertExternallySynchronizedMutex::WriteContext to designate an area of code where protec...