11// LAF Base Library
2- // Copyright (C) 2020-2024 Igara Studio S.A.
2+ // Copyright (C) 2020-2025 Igara Studio S.A.
33// Copyright (C) 2001-2016 David Capello
44//
55// This file is released under the terms of the MIT license.
1111
1212#include " base/rw_lock.h"
1313
14- // Uncomment this line in case that you want TRACE() lock/unlock
15- // operations.
16- // #define DEBUG_OBJECT_LOCKS
17-
1814#include " base/debug.h"
1915#include " base/thread.h"
2016
2117#include < algorithm>
2218
19+ // Uncomment this line in case that you want TRACEARGS() lock/unlock
20+ // operations.
21+ #define LCK_TRACE (...) // TRACEARGS(__VA_ARGS__)
22+
2323namespace base {
2424
2525RWLock::RWLock ()
@@ -51,7 +51,8 @@ bool RWLock::canWriteLockFromRead() const
5151RWLock::LockResult RWLock::lock (LockType lockType, int timeout)
5252{
5353 // Check for re-entrant write locks (multiple write-lock in the same
54- // thread are allowed).
54+ // thread are allowed, even a read lock if we are writing in the
55+ // same thread).
5556 // if (lockType == WriteLock) {
5657 {
5758 const std::lock_guard lock (m_mutex);
@@ -92,9 +93,7 @@ RWLock::LockResult RWLock::lock(LockType lockType, int timeout)
9293 m_write_lock = true ;
9394 m_write_thread = std::this_thread::get_id ();
9495
95- #ifdef DEBUG_OBJECT_LOCKS
96- TRACE (" LCK: lock: Locked <%p> to write\n " , this );
97- #endif
96+ LCK_TRACE (" LCK: lock: Locked" , this , " to write in thread" , m_write_thread);
9897 return LockResult::OK;
9998 }
10099 break ;
@@ -107,24 +106,22 @@ RWLock::LockResult RWLock::lock(LockType lockType, int timeout)
107106 const int delay = std::min (100 , timeout);
108107 timeout -= delay;
109108
110- #ifdef DEBUG_OBJECT_LOCKS
111- TRACE (" LCK: lock: wait 100 msecs for <%p>\n " , this );
112- #endif
113-
109+ LCK_TRACE (" LCK: lock: wait 100 msecs for" , this );
114110 base::this_thread::sleep_for (double (delay) / 1000.0 );
115111 }
116112 else
117113 break ;
118114 }
119115
120- #ifdef DEBUG_OBJECT_LOCKS
121- TRACE (" LCK: lock: Cannot lock <%p> to %s (has %d read locks and %d write locks)\n " ,
122- this ,
123- (lockType == ReadLock ? " read" : " write" ),
124- m_read_locks,
125- m_write_lock);
126- #endif
127-
116+ LCK_TRACE (" LCK: lock: Cannot lock" ,
117+ this ,
118+ " to" ,
119+ (lockType == ReadLock ? " read" : " write" ),
120+ " (has" ,
121+ m_read_locks,
122+ " read locks and" ,
123+ m_write_lock,
124+ " write locks)" );
128125 return LockResult::Fail;
129126}
130127
@@ -222,10 +219,7 @@ RWLock::LockResult RWLock::upgradeToWrite(int timeout)
222219 m_write_lock = true ;
223220 m_write_thread = std::this_thread::get_id ();
224221
225- #ifdef DEBUG_OBJECT_LOCKS
226- TRACE (" LCK: upgradeToWrite: Locked <%p> to write\n " , this );
227- #endif
228-
222+ LCK_TRACE (" LCK: upgradeToWrite: Locked" , this , " to write in thread" , m_write_thread);
229223 return LockResult::OK;
230224 }
231225
@@ -236,24 +230,31 @@ RWLock::LockResult RWLock::upgradeToWrite(int timeout)
236230 const int delay = std::min (100 , timeout);
237231 timeout -= delay;
238232
239- #ifdef DEBUG_OBJECT_LOCKS
240- TRACE (" LCK: upgradeToWrite: wait 100 msecs for <%p>\n " , this );
241- #endif
242-
233+ LCK_TRACE (" LCK: upgradeToWrite: wait 100 msecs for" , this );
243234 base::this_thread::sleep_for (double (delay) / 1000.0 );
244235 }
245236 else
246237 break ;
247238 }
248239
249- # ifdef DEBUG_OBJECT_LOCKS
250- TRACE ( " LCK: upgradeToWrite: Cannot lock <%p> to write (has %d read locks and %d write locks) \n " ,
251- this ,
252- m_read_locks,
253- m_write_lock);
254- # endif
255-
240+ LCK_TRACE ( " LCK: upgradeToWrite: Cannot lock " ,
241+ this ,
242+ " to write (has " ,
243+ m_read_locks,
244+ " read locks and " ,
245+ m_write_lock,
246+ " write locks) " );
256247 return LockResult::Fail;
257248}
258249
250+ void RWLock::updateWriterThread ()
251+ {
252+ const std::lock_guard lock (m_mutex);
253+ if (m_write_lock) {
254+ m_write_thread = std::this_thread::get_id ();
255+
256+ LCK_TRACE (" LCK: updateWriterThread: Lock" , this , " has new writer thread" , m_write_thread);
257+ }
258+ }
259+
259260} // namespace base
0 commit comments