Stroika Library 3.0d25
 
Loading...
Searching...
No Matches
AssertExternallySynchronizedChecker.cpp
1/*
2 * Copyright(c) Sophist Solutions, Inc. 1990-2026. All rights reserved
3 */
4#include "Stroika/Foundation/StroikaPreComp.h"
5
8
11
13
14using namespace Stroika::Foundation;
16using namespace Stroika::Foundation::Debug;
17
18#if qStroika_Foundation_Debug_AssertExternallySynchronizedChecker_Enabled
19/*
20 ********************************************************************************
21 ****************** Debug::AssertExternallySynchronizedChecker ********************
22 ********************************************************************************
23 */
24void AssertExternallySynchronizedChecker::lock_ () noexcept
25{
26 try {
27 SharedContext* sharedContext = fSharedContext_.get ();
28 if (sharedContext->fFullLocks_++ == 0) {
29 // If first time in, save thread-id
30 sharedContext->fThreadWithFullLock_ = this_thread::get_id ();
31 if (not sharedContext->GetSharedLockEmpty_ ()) {
32 // If first already shared locks - OK - so long as same thread
33 Require (sharedContext->CountOfIInSharedLockThreads_ (sharedContext->fThreadWithFullLock_) ==
34 sharedContext->GetSharedLockThreadsCount_ ());
35 }
36 }
37 else {
38 // If first already locked - OK - so long as same thread
39 if (sharedContext->fThreadWithFullLock_ != this_thread::get_id ()) {
40 // Duplicate the Require() below, but with more debug information, because this is a COMMON and IMPORANT case;
41 // If this happens, this means one thread has (the object containing this) is using this object (fake locked)
42 // while we are trying to use it (again doing fake write lock) - so we want to PRINT INFO about that thread!!!
43 DbgTrace ("ATTEMPT TO modify (lock for write) an object which is already in use (debuglocked) in another thread (thisthread={})"_f,
44 this_thread::get_id ());
45 DbgTrace ("Original thread holding lock: threadID={}, and DbgTraceThreadName={}"_f,
46 Execution::Thread::FormatThreadID (sharedContext->fThreadWithFullLock_),
47 Characters::ToString (Debug::GetDbgTraceThreadName_A (sharedContext->fThreadWithFullLock_)));
48 }
49 Require (sharedContext->fThreadWithFullLock_ == this_thread::get_id ());
50 }
51 }
52 catch (...) {
54 }
55}
56
57bool AssertExternallySynchronizedChecker::try_lock_ () noexcept
58{
59 // Note - not critical if there are races in this, as its just a diagnostic for debugging, and false-negatives OK
60 bool lockedSuccessfully = true;
61 try {
62 SharedContext* sharedContext = fSharedContext_.get ();
63 if (sharedContext->fFullLocks_++ == 0) {
64 // If first time in, save thread-id
65 sharedContext->fThreadWithFullLock_ = this_thread::get_id ();
66 if (not sharedContext->GetSharedLockEmpty_ ()) {
67 // If first already shared locks - OK - so long as same thread
68 lockedSuccessfully = sharedContext->CountOfIInSharedLockThreads_ (sharedContext->fThreadWithFullLock_) ==
69 sharedContext->GetSharedLockThreadsCount_ ();
70 }
71 }
72 else {
73 // If first already locked - OK - so long as same thread
74 lockedSuccessfully = (sharedContext->fThreadWithFullLock_ == this_thread::get_id ());
75 }
76 if (not lockedSuccessfully) {
77 unlock_ ();
78 }
79 }
80 catch (...) {
82 lockedSuccessfully = false;
83 }
84 return lockedSuccessfully;
85}
86
87void AssertExternallySynchronizedChecker::unlock_ () noexcept
88{
89 SharedContext* sharedContext = fSharedContext_.get ();
90 Require (sharedContext->fThreadWithFullLock_ == this_thread::get_id ());
91 Require (sharedContext->fFullLocks_ > 0); // else unbalanced
92 --sharedContext->fFullLocks_;
93 // Note at this point - it would make some sense to CLEAR fThreadWithFullLock_, but that could be a race, cuz someone
94 // else could lock just as we are unlocking...
95}
96
97void AssertExternallySynchronizedChecker::lock_shared_ () const noexcept
98{
99 try {
100 SharedContext* sharedContext = fSharedContext_.get ();
101 // OK to shared lock from various threads
102 // But if already locked, NOT OK (would have blocked in real impl) - if you try to shared lock from another thread while locked
103 if (sharedContext->fFullLocks_ != 0) {
104 // If first already locks - OK - so long as same thread
105 if (sharedContext->fThreadWithFullLock_ != this_thread::get_id ()) {
106 // Duplicate the Require() below, but with more debug information, because this is a COMMON and IMPORANT case;
107 // If this happens, this means one thread has (the object containing this) is using this object (fake locked)
108 // while we are trying to use it (again doing fake write lock) - so we want to PRINT INFO about that thread!!!
109 DbgTrace ("ATTEMPT TO shared_lock (lock for READ) an object which is already in use (debuglocked for WRITE) in another thread"_f);
110 DbgTrace ("Original thread holding (write) lock: threadID={}, and DbgTraceThreadName={}"_f,
111 Characters::ToString (Execution::Thread::FormatThreadID_A (sharedContext->fThreadWithFullLock_)),
112 Characters::ToString (Debug::GetDbgTraceThreadName_A (sharedContext->fThreadWithFullLock_)));
113 }
114 Require (sharedContext->fThreadWithFullLock_ == this_thread::get_id ());
115 }
116 sharedContext->AddSharedLock_ (this_thread::get_id ());
117 }
118 catch (...) {
120 }
121}
122
123void AssertExternallySynchronizedChecker::unlock_shared_ () const noexcept
124{
125 try {
126 SharedContext* sharedContext = fSharedContext_.get ();
127 sharedContext->RemoveSharedLock_ (this_thread::get_id ());
128 }
129 catch (...) {
131 }
132}
133
134mutex& AssertExternallySynchronizedChecker::GetSharedLockMutexThreads_ ()
135{
136 static mutex sMutex_; // must be out-of-line so we can have just one mutex object. Could use static member, but then trouble using
137 // AssertExternallySynchronizedChecker before main
138 return sMutex_;
139}
140#endif
#define AssertNotReached()
Definition Assertions.h:358
#define DbgTrace
Definition Trace.h:327
String ToString(T &&t, ARGS... args)
Return a debug-friendly, display version of the argument: not guaranteed parsable or usable except fo...
Definition ToString.inl:424
wstring FormatThreadID(Thread::IDType threadID, const FormatThreadInfo &formatInfo={})
Definition Thread.cpp:984