From de969105d49334390184085572ee1d19956195f1 Mon Sep 17 00:00:00 2001 From: baldurk Date: Fri, 27 Apr 2018 15:11:33 +0100 Subject: [PATCH] Add R/W lock to OS-specific wrapper --- renderdoc/common/threading.h | 27 ++++++++------ renderdoc/os/os_specific.h | 27 ++++++++++++-- renderdoc/os/posix/posix_specific.h | 7 ++++ renderdoc/os/posix/posix_threading.cpp | 50 ++++++++++++++++++++++++++ renderdoc/os/win32/win32_specific.h | 1 + renderdoc/os/win32/win32_threading.cpp | 41 ++++++++++++++++++++- 6 files changed, 138 insertions(+), 15 deletions(-) diff --git a/renderdoc/common/threading.h b/renderdoc/common/threading.h index d04ff00f0..841d36712 100644 --- a/renderdoc/common/threading.h +++ b/renderdoc/common/threading.h @@ -38,21 +38,26 @@ private: CriticalSection *m_CS; }; -class TryScopedLock +class ScopedReadLock { public: - TryScopedLock(CriticalSection &cs) : m_CS(&cs) { m_Owned = m_CS->Trylock(); } - ~TryScopedLock() - { - if(m_Owned) - m_CS->Unlock(); - } - - bool HasLock() const { return m_Owned; } + ScopedReadLock(RWLock &rw) : m_RW(&rw) { m_RW->ReadLock(); } + ~ScopedReadLock() { m_RW->ReadUnlock(); } private: - CriticalSection *m_CS; - bool m_Owned; + RWLock *m_RW; +}; + +class ScopedWriteLock +{ +public: + ScopedWriteLock(RWLock &rw) : m_RW(&rw) { m_RW->WriteLock(); } + ~ScopedWriteLock() { m_RW->WriteUnlock(); } +private: + RWLock *m_RW; }; }; #define SCOPED_LOCK(cs) Threading::ScopedLock CONCAT(scopedlock, __LINE__)(cs); + +#define SCOPED_READLOCK(rw) Threading::ScopedReadLock CONCAT(scopedlock, __LINE__)(rw); +#define SCOPED_WRITELOCK(rw) Threading::ScopedWriteLock CONCAT(scopedlock, __LINE__)(rw); diff --git a/renderdoc/os/os_specific.h b/renderdoc/os/os_specific.h index e87c489a0..dde271b69 100644 --- a/renderdoc/os/os_specific.h +++ b/renderdoc/os/os_specific.h @@ -99,10 +99,31 @@ public: bool Trylock(); void Unlock(); -private: // no copying - CriticalSectionTemplate &operator=(const CriticalSectionTemplate &other); - CriticalSectionTemplate(const CriticalSectionTemplate &other); + CriticalSectionTemplate &operator=(const CriticalSectionTemplate &other) = delete; + CriticalSectionTemplate(const CriticalSectionTemplate &other) = delete; + + data m_Data; +}; + +template +class RWLockTemplate +{ +public: + RWLockTemplate(); + ~RWLockTemplate(); + + void ReadLock(); + bool TryReadlock(); + void ReadUnlock(); + + void WriteLock(); + bool TryWritelock(); + void WriteUnlock(); + + // no copying + RWLockTemplate &operator=(const RWLockTemplate &other) = delete; + RWLockTemplate(const RWLockTemplate &other) = delete; data m_Data; }; diff --git a/renderdoc/os/posix/posix_specific.h b/renderdoc/os/posix/posix_specific.h index 9e1e0c6c7..9391464bf 100644 --- a/renderdoc/os/posix/posix_specific.h +++ b/renderdoc/os/posix/posix_specific.h @@ -83,6 +83,13 @@ struct pthreadLockData pthread_mutexattr_t attr; }; typedef CriticalSectionTemplate CriticalSection; + +struct pthreadRWLockData +{ + pthread_rwlock_t rwlock; + pthread_rwlockattr_t attr; +}; +typedef RWLockTemplate RWLock; }; namespace Bits diff --git a/renderdoc/os/posix/posix_threading.cpp b/renderdoc/os/posix/posix_threading.cpp index 05b888aaa..9360bd410 100644 --- a/renderdoc/os/posix/posix_threading.cpp +++ b/renderdoc/os/posix/posix_threading.cpp @@ -101,6 +101,56 @@ void CriticalSection::Unlock() pthread_mutex_unlock(&m_Data.lock); } +template <> +RWLock::RWLockTemplate() +{ + pthread_rwlockattr_init(&m_Data.attr); + pthread_rwlock_init(&m_Data.rwlock, &m_Data.attr); +} + +template <> +RWLock::~RWLockTemplate() +{ + pthread_rwlock_destroy(&m_Data.rwlock); + pthread_rwlockattr_destroy(&m_Data.attr); +} + +template <> +void RWLock::WriteLock() +{ + pthread_rwlock_wrlock(&m_Data.rwlock); +} + +template <> +bool RWLock::TryWritelock() +{ + return pthread_rwlock_trywrlock(&m_Data.rwlock) == 0; +} + +template <> +void RWLock::WriteUnlock() +{ + pthread_rwlock_unlock(&m_Data.rwlock); +} + +template <> +void RWLock::ReadLock() +{ + pthread_rwlock_rdlock(&m_Data.rwlock); +} + +template <> +bool RWLock::TryReadlock() +{ + return pthread_rwlock_tryrdlock(&m_Data.rwlock) == 0; +} + +template <> +void RWLock::ReadUnlock() +{ + pthread_rwlock_unlock(&m_Data.rwlock); +} + struct ThreadInitData { std::function entryFunc; diff --git a/renderdoc/os/win32/win32_specific.h b/renderdoc/os/win32/win32_specific.h index 39e826559..34c4a626d 100644 --- a/renderdoc/os/win32/win32_specific.h +++ b/renderdoc/os/win32/win32_specific.h @@ -73,6 +73,7 @@ void WriteOutput(int channel, const char *str); namespace Threading { typedef CriticalSectionTemplate CriticalSection; +typedef RWLockTemplate RWLock; }; namespace Bits diff --git a/renderdoc/os/win32/win32_threading.cpp b/renderdoc/os/win32/win32_threading.cpp index 1543f0176..afb3c6e43 100644 --- a/renderdoc/os/win32/win32_threading.cpp +++ b/renderdoc/os/win32/win32_threading.cpp @@ -98,7 +98,7 @@ void CriticalSection::Lock() bool CriticalSection::Trylock() { - return TryEnterCriticalSection(&m_Data) == TRUE; + return TryEnterCriticalSection(&m_Data) != FALSE; } void CriticalSection::Unlock() @@ -106,6 +106,45 @@ void CriticalSection::Unlock() LeaveCriticalSection(&m_Data); } +RWLock::RWLockTemplate() +{ + InitializeSRWLock(&m_Data); +} + +RWLock::~RWLockTemplate() +{ +} + +void RWLock::WriteLock() +{ + AcquireSRWLockExclusive(&m_Data); +} + +bool RWLock::TryWritelock() +{ + return TryAcquireSRWLockExclusive(&m_Data) != FALSE; +} + +void RWLock::WriteUnlock() +{ + ReleaseSRWLockExclusive(&m_Data); +} + +void RWLock::ReadLock() +{ + AcquireSRWLockShared(&m_Data); +} + +bool RWLock::TryReadlock() +{ + return TryAcquireSRWLockShared(&m_Data) != FALSE; +} + +void RWLock::ReadUnlock() +{ + ReleaseSRWLockShared(&m_Data); +} + struct ThreadInitData { std::function entryFunc;