From a221f121bab8d24ea5f30507560a4f2a1c3e0fc1 Mon Sep 17 00:00:00 2001 From: Bartosz Taudul Date: Sat, 21 Sep 2019 14:55:14 +0200 Subject: [PATCH] Extract lock state handling to a separate context class. --- client/TracyLock.hpp | 315 +++++++++++++++++++++++++------------------ 1 file changed, 186 insertions(+), 129 deletions(-) diff --git a/client/TracyLock.hpp b/client/TracyLock.hpp index 5292c41f..2bf265a8 100644 --- a/client/TracyLock.hpp +++ b/client/TracyLock.hpp @@ -11,11 +11,10 @@ namespace tracy { -template -class Lockable +class LockableCtx { public: - tracy_force_inline Lockable( const SourceLocationData* srcloc ) + tracy_force_inline LockableCtx( const SourceLocationData* srcloc ) : m_id( GetLockCounter().fetch_add( 1, std::memory_order_relaxed ) ) #ifdef TRACY_ON_DEMAND , m_lockCount( 0 ) @@ -33,18 +32,16 @@ public: MemWrite( &item->lockAnnounce.time, Profiler::GetTime() ); MemWrite( &item->lockAnnounce.lckloc, (uint64_t)srcloc ); MemWrite( &item->lockAnnounce.type, LockType::Lockable ); - #ifdef TRACY_ON_DEMAND GetProfiler().DeferItem( *item ); #endif - tail.store( magic + 1, std::memory_order_release ); } - Lockable( const Lockable& ) = delete; - Lockable& operator=( const Lockable& ) = delete; + LockableCtx( const LockableCtx& ) = delete; + LockableCtx& operator=( const LockableCtx& ) = delete; - ~Lockable() + tracy_force_inline ~LockableCtx() { Magic magic; auto token = GetToken(); @@ -54,15 +51,13 @@ public: MemWrite( &item->lockTerminate.id, m_id ); MemWrite( &item->lockTerminate.time, Profiler::GetTime() ); MemWrite( &item->lockTerminate.type, LockType::Lockable ); - #ifdef TRACY_ON_DEMAND GetProfiler().DeferItem( *item ); #endif - tail.store( magic + 1, std::memory_order_release ); } - tracy_force_inline void lock() + tracy_force_inline bool BeforeLock() { #ifdef TRACY_ON_DEMAND bool queue = false; @@ -74,40 +69,31 @@ public: if( active != connected ) m_active.store( connected, std::memory_order_relaxed ); if( connected ) queue = true; } - if( !queue ) - { - m_lockable.lock(); - return; - } + if( !queue ) return false; #endif - const auto thread = GetThreadHandle(); - { - auto item = Profiler::QueueSerial(); - MemWrite( &item->hdr.type, QueueType::LockWait ); - MemWrite( &item->lockWait.thread, thread ); - MemWrite( &item->lockWait.id, m_id ); - MemWrite( &item->lockWait.time, Profiler::GetTime() ); - MemWrite( &item->lockWait.type, LockType::Lockable ); - Profiler::QueueSerialFinish(); - } - - m_lockable.lock(); - - { - auto item = Profiler::QueueSerial(); - MemWrite( &item->hdr.type, QueueType::LockObtain ); - MemWrite( &item->lockObtain.thread, thread ); - MemWrite( &item->lockObtain.id, m_id ); - MemWrite( &item->lockObtain.time, Profiler::GetTime() ); - Profiler::QueueSerialFinish(); - } + auto item = Profiler::QueueSerial(); + MemWrite( &item->hdr.type, QueueType::LockWait ); + MemWrite( &item->lockWait.thread, GetThreadHandle() ); + MemWrite( &item->lockWait.id, m_id ); + MemWrite( &item->lockWait.time, Profiler::GetTime() ); + MemWrite( &item->lockWait.type, LockType::Lockable ); + Profiler::QueueSerialFinish(); + return true; } - tracy_force_inline void unlock() + tracy_force_inline void AfterLock() { - m_lockable.unlock(); + auto item = Profiler::QueueSerial(); + MemWrite( &item->hdr.type, QueueType::LockObtain ); + MemWrite( &item->lockObtain.thread, GetThreadHandle() ); + MemWrite( &item->lockObtain.id, m_id ); + MemWrite( &item->lockObtain.time, Profiler::GetTime() ); + Profiler::QueueSerialFinish(); + } + tracy_force_inline void AfterUnlock() + { #ifdef TRACY_ON_DEMAND m_lockCount.fetch_sub( 1, std::memory_order_relaxed ); if( !m_active.load( std::memory_order_relaxed ) ) return; @@ -126,12 +112,10 @@ public: Profiler::QueueSerialFinish(); } - tracy_force_inline bool try_lock() + tracy_force_inline void AfterTryLock( bool acquired ) { - const auto ret = m_lockable.try_lock(); - #ifdef TRACY_ON_DEMAND - if( !ret ) return ret; + if( !acquired ) return; bool queue = false; const auto locks = m_lockCount.fetch_add( 1, std::memory_order_relaxed ); @@ -142,10 +126,10 @@ public: if( active != connected ) m_active.store( connected, std::memory_order_relaxed ); if( connected ) queue = true; } - if( !queue ) return ret; + if( !queue ) return; #endif - if( ret ) + if( acquired ) { auto item = Profiler::QueueSerial(); MemWrite( &item->hdr.type, QueueType::LockObtain ); @@ -154,8 +138,6 @@ public: MemWrite( &item->lockObtain.time, Profiler::GetTime() ); Profiler::QueueSerialFinish(); } - - return ret; } tracy_force_inline void Mark( const SourceLocationData* srcloc ) @@ -180,7 +162,6 @@ public: } private: - T m_lockable; uint32_t m_id; #ifdef TRACY_ON_DEMAND @@ -189,12 +170,53 @@ private: #endif }; - template -class SharedLockable +class Lockable { public: - tracy_force_inline SharedLockable( const SourceLocationData* srcloc ) + tracy_force_inline Lockable( const SourceLocationData* srcloc ) + : m_ctx( srcloc ) + { + } + + Lockable( const Lockable& ) = delete; + Lockable& operator=( const Lockable& ) = delete; + + tracy_force_inline void lock() + { + const auto runAfter = m_ctx.BeforeLock(); + m_lockable.lock(); + if( runAfter ) m_ctx.AfterLock(); + } + + tracy_force_inline void unlock() + { + m_lockable.unlock(); + m_ctx.AfterUnlock(); + } + + tracy_force_inline bool try_lock() + { + const auto acquired = m_lockable.try_lock(); + m_ctx.AfterTryLock( acquired ); + return acquired; + } + + tracy_force_inline void Mark( const SourceLocationData* srcloc ) + { + m_ctx.Mark( srcloc ); + } + +private: + T m_lockable; + LockableCtx m_ctx; +}; + + +class SharedLockableCtx +{ +public: + tracy_force_inline SharedLockableCtx( const SourceLocationData* srcloc ) : m_id( GetLockCounter().fetch_add( 1, std::memory_order_relaxed ) ) #ifdef TRACY_ON_DEMAND , m_lockCount( 0 ) @@ -220,10 +242,10 @@ public: tail.store( magic + 1, std::memory_order_release ); } - SharedLockable( const SharedLockable& ) = delete; - SharedLockable& operator=( const SharedLockable& ) = delete; + SharedLockableCtx( const SharedLockableCtx& ) = delete; + SharedLockableCtx& operator=( const SharedLockableCtx& ) = delete; - ~SharedLockable() + tracy_force_inline ~SharedLockableCtx() { Magic magic; auto token = GetToken(); @@ -241,7 +263,7 @@ public: tail.store( magic + 1, std::memory_order_release ); } - tracy_force_inline void lock() + tracy_force_inline bool BeforeLock() { #ifdef TRACY_ON_DEMAND bool queue = false; @@ -253,40 +275,31 @@ public: if( active != connected ) m_active.store( connected, std::memory_order_relaxed ); if( connected ) queue = true; } - if( !queue ) - { - m_lockable.lock(); - return; - } + if( !queue ) return false; #endif - const auto thread = GetThreadHandle(); - { - auto item = Profiler::QueueSerial(); - MemWrite( &item->hdr.type, QueueType::LockWait ); - MemWrite( &item->lockWait.thread, thread ); - MemWrite( &item->lockWait.id, m_id ); - MemWrite( &item->lockWait.time, Profiler::GetTime() ); - MemWrite( &item->lockWait.type, LockType::SharedLockable ); - Profiler::QueueSerialFinish(); - } - - m_lockable.lock(); - - { - auto item = Profiler::QueueSerial(); - MemWrite( &item->hdr.type, QueueType::LockObtain ); - MemWrite( &item->lockObtain.thread, thread ); - MemWrite( &item->lockObtain.id, m_id ); - MemWrite( &item->lockObtain.time, Profiler::GetTime() ); - Profiler::QueueSerialFinish(); - } + auto item = Profiler::QueueSerial(); + MemWrite( &item->hdr.type, QueueType::LockWait ); + MemWrite( &item->lockWait.thread, GetThreadHandle() ); + MemWrite( &item->lockWait.id, m_id ); + MemWrite( &item->lockWait.time, Profiler::GetTime() ); + MemWrite( &item->lockWait.type, LockType::SharedLockable ); + Profiler::QueueSerialFinish(); + return true; } - tracy_force_inline void unlock() + tracy_force_inline void AfterLock() { - m_lockable.unlock(); + auto item = Profiler::QueueSerial(); + MemWrite( &item->hdr.type, QueueType::LockObtain ); + MemWrite( &item->lockObtain.thread, GetThreadHandle() ); + MemWrite( &item->lockObtain.id, m_id ); + MemWrite( &item->lockObtain.time, Profiler::GetTime() ); + Profiler::QueueSerialFinish(); + } + tracy_force_inline void AfterUnlock() + { #ifdef TRACY_ON_DEMAND m_lockCount.fetch_sub( 1, std::memory_order_relaxed ); if( !m_active.load( std::memory_order_relaxed ) ) return; @@ -305,12 +318,10 @@ public: Profiler::QueueSerialFinish(); } - tracy_force_inline bool try_lock() + tracy_force_inline void AfterTryLock( bool acquired ) { - const auto ret = m_lockable.try_lock(); - #ifdef TRACY_ON_DEMAND - if( !ret ) return ret; + if( !acquired ) return; bool queue = false; const auto locks = m_lockCount.fetch_add( 1, std::memory_order_relaxed ); @@ -321,10 +332,10 @@ public: if( active != connected ) m_active.store( connected, std::memory_order_relaxed ); if( connected ) queue = true; } - if( !queue ) return ret; + if( !queue ) return; #endif - if( ret ) + if( acquired ) { auto item = Profiler::QueueSerial(); MemWrite( &item->hdr.type, QueueType::LockObtain ); @@ -333,11 +344,9 @@ public: MemWrite( &item->lockObtain.time, Profiler::GetTime() ); Profiler::QueueSerialFinish(); } - - return ret; } - tracy_force_inline void lock_shared() + tracy_force_inline bool BeforeLockShared() { #ifdef TRACY_ON_DEMAND bool queue = false; @@ -349,40 +358,31 @@ public: if( active != connected ) m_active.store( connected, std::memory_order_relaxed ); if( connected ) queue = true; } - if( !queue ) - { - m_lockable.lock_shared(); - return; - } + if( !queue ) return false; #endif - const auto thread = GetThreadHandle(); - { - auto item = Profiler::QueueSerial(); - MemWrite( &item->hdr.type, QueueType::LockSharedWait ); - MemWrite( &item->lockWait.thread, thread ); - MemWrite( &item->lockWait.id, m_id ); - MemWrite( &item->lockWait.time, Profiler::GetTime() ); - MemWrite( &item->lockWait.type, LockType::SharedLockable ); - Profiler::QueueSerialFinish(); - } - - m_lockable.lock_shared(); - - { - auto item = Profiler::QueueSerial(); - MemWrite( &item->hdr.type, QueueType::LockSharedObtain ); - MemWrite( &item->lockObtain.thread, thread ); - MemWrite( &item->lockObtain.id, m_id ); - MemWrite( &item->lockObtain.time, Profiler::GetTime() ); - Profiler::QueueSerialFinish(); - } + auto item = Profiler::QueueSerial(); + MemWrite( &item->hdr.type, QueueType::LockSharedWait ); + MemWrite( &item->lockWait.thread, GetThreadHandle() ); + MemWrite( &item->lockWait.id, m_id ); + MemWrite( &item->lockWait.time, Profiler::GetTime() ); + MemWrite( &item->lockWait.type, LockType::SharedLockable ); + Profiler::QueueSerialFinish(); + return true; } - tracy_force_inline void unlock_shared() + tracy_force_inline void AfterLockShared() { - m_lockable.unlock_shared(); + auto item = Profiler::QueueSerial(); + MemWrite( &item->hdr.type, QueueType::LockSharedObtain ); + MemWrite( &item->lockObtain.thread, GetThreadHandle() ); + MemWrite( &item->lockObtain.id, m_id ); + MemWrite( &item->lockObtain.time, Profiler::GetTime() ); + Profiler::QueueSerialFinish(); + } + tracy_force_inline void AfterUnlockShared() + { #ifdef TRACY_ON_DEMAND m_lockCount.fetch_sub( 1, std::memory_order_relaxed ); if( !m_active.load( std::memory_order_relaxed ) ) return; @@ -401,12 +401,10 @@ public: Profiler::QueueSerialFinish(); } - tracy_force_inline bool try_lock_shared() + tracy_force_inline void AfterTryLockShared( bool acquired ) { - const auto ret = m_lockable.try_lock_shared(); - #ifdef TRACY_ON_DEMAND - if( !ret ) return ret; + if( !acquired ) return; bool queue = false; const auto locks = m_lockCount.fetch_add( 1, std::memory_order_relaxed ); @@ -417,10 +415,10 @@ public: if( active != connected ) m_active.store( connected, std::memory_order_relaxed ); if( connected ) queue = true; } - if( !queue ) return ret; + if( !queue ) return; #endif - if( ret ) + if( acquired ) { auto item = Profiler::QueueSerial(); MemWrite( &item->hdr.type, QueueType::LockSharedObtain ); @@ -429,8 +427,6 @@ public: MemWrite( &item->lockObtain.time, Profiler::GetTime() ); Profiler::QueueSerialFinish(); } - - return ret; } tracy_force_inline void Mark( const SourceLocationData* srcloc ) @@ -455,7 +451,6 @@ public: } private: - T m_lockable; uint32_t m_id; #ifdef TRACY_ON_DEMAND @@ -464,6 +459,68 @@ private: #endif }; +template +class SharedLockable +{ +public: + tracy_force_inline SharedLockable( const SourceLocationData* srcloc ) + : m_ctx( srcloc ) + { + } + + SharedLockable( const SharedLockable& ) = delete; + SharedLockable& operator=( const SharedLockable& ) = delete; + + tracy_force_inline void lock() + { + const auto runAfter = m_ctx.BeforeLock(); + m_lockable.lock(); + if( runAfter ) m_ctx.AfterLock(); + } + + tracy_force_inline void unlock() + { + m_lockable.unlock(); + m_ctx.AfterUnlock(); + } + + tracy_force_inline bool try_lock() + { + const auto acquired = m_lockable.try_lock(); + m_ctx.AfterTryLock( acquired ); + return acquired; + } + + tracy_force_inline void lock_shared() + { + const auto runAfter = m_ctx.BeforeLockShared(); + m_lockable.lock_shared(); + if( runAfter ) m_ctx.AfterLockShared(); + } + + tracy_force_inline void unlock_shared() + { + m_lockable.unlock_shared(); + m_ctx.AfterUnlockShared(); + } + + tracy_force_inline bool try_lock_shared() + { + const auto acquired = m_lockable.try_lock_shared(); + m_ctx.AfterTryLockShared( acquired ); + return acquired; + } + + tracy_force_inline void Mark( const SourceLocationData* srcloc ) + { + m_ctx.Mark( srcloc ); + } + +private: + T m_lockable; + SharedLockableCtx m_ctx; +}; + };