Extract lock state handling to a separate context class.

This commit is contained in:
Bartosz Taudul 2019-09-21 14:55:14 +02:00
parent 4c736aecfa
commit a221f121ba

View File

@ -11,11 +11,10 @@
namespace tracy
{
template<class T>
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 T>
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 T>
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;
};
};