From 3d858c28ee249ce7b5be60b92ceffde9d61ef506 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Robert=20M=C3=BCller?= Date: Fri, 10 Nov 2023 21:15:51 +0100 Subject: [PATCH] Add `CLock` wrapper for `std::mutex` to replace `lock_*` functions Replace usages of platform specific `lock_*` functions with `std::mutex` through the wrapper class `CLock`. Move lock classes to `base/lock.h`. The `CLock` wrapper class is only necessary because the clang thread-safety attributes are not available for `std::mutex` except when explicitly using libc++. --- CMakeLists.txt | 2 +- src/base/lock.h | 135 ++++++++++++++++++++++ src/base/lock_scope.h | 24 ---- src/base/system.cpp | 136 +++-------------------- src/base/system.h | 112 ++----------------- src/engine/client/serverbrowser_http.cpp | 7 +- src/engine/client/updater.cpp | 9 +- src/engine/client/updater.h | 6 +- src/engine/client/video.cpp | 15 +-- src/engine/client/video.h | 3 +- src/engine/server/register.cpp | 27 ++--- src/engine/shared/http.cpp | 10 +- src/engine/shared/jobs.cpp | 4 - src/engine/shared/jobs.h | 3 +- src/test/thread.cpp | 14 +-- 15 files changed, 199 insertions(+), 308 deletions(-) create mode 100644 src/base/lock.h delete mode 100644 src/base/lock_scope.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 85ed0f03a..d9c1f178e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1844,7 +1844,7 @@ set_src(BASE GLOB_RECURSE src/base hash_ctxt.h hash_libtomcrypt.cpp hash_openssl.cpp - lock_scope.h + lock.h log.cpp log.h logger.h diff --git a/src/base/lock.h b/src/base/lock.h new file mode 100644 index 000000000..ecebfc205 --- /dev/null +++ b/src/base/lock.h @@ -0,0 +1,135 @@ +#ifndef BASE_LOCK_H +#define BASE_LOCK_H + +#include + +// Enable thread safety attributes only with clang. +// The attributes can be safely erased when compiling with other compilers. +#if defined(__clang__) && (!defined(SWIG)) +#define THREAD_ANNOTATION_ATTRIBUTE__(x) __attribute__((x)) +#else +#define THREAD_ANNOTATION_ATTRIBUTE__(x) // no-op +#endif + +#define CAPABILITY(x) \ + THREAD_ANNOTATION_ATTRIBUTE__(capability(x)) + +#define SCOPED_CAPABILITY \ + THREAD_ANNOTATION_ATTRIBUTE__(scoped_lockable) + +#define GUARDED_BY(x) \ + THREAD_ANNOTATION_ATTRIBUTE__(guarded_by(x)) + +#define PT_GUARDED_BY(x) \ + THREAD_ANNOTATION_ATTRIBUTE__(pt_guarded_by(x)) + +#define ACQUIRED_BEFORE(...) \ + THREAD_ANNOTATION_ATTRIBUTE__(acquired_before(__VA_ARGS__)) + +#define ACQUIRED_AFTER(...) \ + THREAD_ANNOTATION_ATTRIBUTE__(acquired_after(__VA_ARGS__)) + +#define REQUIRES(...) \ + THREAD_ANNOTATION_ATTRIBUTE__(requires_capability(__VA_ARGS__)) + +#define REQUIRES_SHARED(...) \ + THREAD_ANNOTATION_ATTRIBUTE__(requires_shared_capability(__VA_ARGS__)) + +#define ACQUIRE(...) \ + THREAD_ANNOTATION_ATTRIBUTE__(acquire_capability(__VA_ARGS__)) + +#define ACQUIRE_SHARED(...) \ + THREAD_ANNOTATION_ATTRIBUTE__(acquire_shared_capability(__VA_ARGS__)) + +#define RELEASE(...) \ + THREAD_ANNOTATION_ATTRIBUTE__(release_capability(__VA_ARGS__)) + +#define RELEASE_SHARED(...) \ + THREAD_ANNOTATION_ATTRIBUTE__(release_shared_capability(__VA_ARGS__)) + +#define RELEASE_GENERIC(...) \ + THREAD_ANNOTATION_ATTRIBUTE__(release_generic_capability(__VA_ARGS__)) + +#define TRY_ACQUIRE(...) \ + THREAD_ANNOTATION_ATTRIBUTE__(try_acquire_capability(__VA_ARGS__)) + +#define TRY_ACQUIRE_SHARED(...) \ + THREAD_ANNOTATION_ATTRIBUTE__(try_acquire_shared_capability(__VA_ARGS__)) + +#define EXCLUDES(...) \ + THREAD_ANNOTATION_ATTRIBUTE__(locks_excluded(__VA_ARGS__)) + +#define ASSERT_CAPABILITY(x) \ + THREAD_ANNOTATION_ATTRIBUTE__(assert_capability(x)) + +#define ASSERT_SHARED_CAPABILITY(x) \ + THREAD_ANNOTATION_ATTRIBUTE__(assert_shared_capability(x)) + +#define RETURN_CAPABILITY(x) \ + THREAD_ANNOTATION_ATTRIBUTE__(lock_returned(x)) + +#define NO_THREAD_SAFETY_ANALYSIS \ + THREAD_ANNOTATION_ATTRIBUTE__(no_thread_safety_analysis) + +/** + * @defgroup Locks + * @see Threads + */ + +/** + * Wrapper for `std::mutex`. + * + * @ingroup Locks + * + * @remark This wrapper is only necessary because the clang thread-safety attributes + * are not available for `std::mutex` except when explicitly using libc++. + */ +class CAPABILITY("mutex") CLock +{ +public: + CLock() = default; + + void lock() ACQUIRE() + { + m_Mutex.lock(); + } + + void unlock() RELEASE() + { + m_Mutex.unlock(); + } + + // To support negative capabilities, otherwise EXCLUDES(m_Lock) must be used instead of REQUIRES(!m_Lock) + const CLock &operator!() const { return *this; } + +private: + std::mutex m_Mutex; +}; + +/** + * RAII-style wrapper for owning a `CLock`. + * + * @ingroup Locks + * + * @remark This wrapper is only necessary because the clang thread-safety attributes + * are not available for `std::lock_guard` except when explicitly using libc++. + */ +class SCOPED_CAPABILITY CLockScope +{ +public: + explicit CLockScope(CLock &Lock) ACQUIRE(Lock, m_Lock) : + m_Lock(Lock) + { + m_Lock.lock(); + } + + ~CLockScope() RELEASE() REQUIRES(m_Lock) + { + m_Lock.unlock(); + } + +private: + CLock &m_Lock; +}; + +#endif diff --git a/src/base/lock_scope.h b/src/base/lock_scope.h deleted file mode 100644 index ce7ea63fc..000000000 --- a/src/base/lock_scope.h +++ /dev/null @@ -1,24 +0,0 @@ -#ifndef BASE_LOCK_SCOPE_H -#define BASE_LOCK_SCOPE_H - -#include "system.h" - -class SCOPED_CAPABILITY CLockScope -{ -public: - CLockScope(LOCK Lock) ACQUIRE(Lock, m_Lock) : - m_Lock(Lock) - { - lock_wait(m_Lock); - } - - ~CLockScope() RELEASE() REQUIRES(m_Lock) - { - lock_unlock(m_Lock); - } - -private: - LOCK m_Lock; -}; - -#endif diff --git a/src/base/system.cpp b/src/base/system.cpp index d737a0998..71298be66 100644 --- a/src/base/system.cpp +++ b/src/base/system.cpp @@ -3,6 +3,8 @@ #include #include #include +#include +#include #include #include #include @@ -10,17 +12,12 @@ #include // std::size #include +#include "lock.h" +#include "logger.h" #include "system.h" -#include "lock_scope.h" -#include "logger.h" - #include -#include - -#include - #if defined(CONF_WEBSOCKETS) #include #endif @@ -474,10 +471,9 @@ int io_sync(IOHANDLE io) #define ASYNC_BUFSIZE (8 * 1024) #define ASYNC_LOCAL_BUFSIZE (64 * 1024) -// TODO: Use Thread Safety Analysis when this file is converted to C++ struct ASYNCIO { - LOCK lock; + CLock lock; IOHANDLE io; SEMAPHORE sphore; void *thread; @@ -530,13 +526,12 @@ static void aio_handle_free_and_unlock(ASYNCIO *aio) RELEASE(aio->lock) aio->refcount--; do_free = aio->refcount == 0; - lock_unlock(aio->lock); + aio->lock.unlock(); if(do_free) { free(aio->buffer); sphore_destroy(&aio->sphore); - lock_destroy(aio->lock); - free(aio); + delete aio; } } @@ -544,7 +539,7 @@ static void aio_thread(void *user) { ASYNCIO *aio = (ASYNCIO *)user; - lock_wait(aio->lock); + aio->lock.lock(); while(true) { struct BUFFERS buffers; @@ -563,9 +558,9 @@ static void aio_thread(void *user) aio_handle_free_and_unlock(aio); break; } - lock_unlock(aio->lock); + aio->lock.unlock(); sphore_wait(&aio->sphore); - lock_wait(aio->lock); + aio->lock.lock(); continue; } @@ -589,26 +584,25 @@ static void aio_thread(void *user) } } aio->read_pos = (aio->read_pos + buffers.len1 + buffers.len2) % aio->buffer_size; - lock_unlock(aio->lock); + aio->lock.unlock(); io_write(aio->io, local_buffer, local_buffer_len); io_flush(aio->io); result_io_error = io_error(aio->io); - lock_wait(aio->lock); + aio->lock.lock(); aio->error = result_io_error; } } ASYNCIO *aio_new(IOHANDLE io) { - ASYNCIO *aio = (ASYNCIO *)malloc(sizeof(*aio)); + ASYNCIO *aio = new ASYNCIO; if(!aio) { return 0; } aio->io = io; - aio->lock = lock_create(); sphore_init(&aio->sphore); aio->thread = 0; @@ -616,8 +610,7 @@ ASYNCIO *aio_new(IOHANDLE io) if(!aio->buffer) { sphore_destroy(&aio->sphore); - lock_destroy(aio->lock); - free(aio); + delete aio; return 0; } aio->buffer_size = ASYNC_BUFSIZE; @@ -632,8 +625,7 @@ ASYNCIO *aio_new(IOHANDLE io) { free(aio->buffer); sphore_destroy(&aio->sphore); - lock_destroy(aio->lock); - free(aio); + delete aio; return 0; } return aio; @@ -662,12 +654,12 @@ static unsigned int next_buffer_size(unsigned int cur_size, unsigned int need_si void aio_lock(ASYNCIO *aio) ACQUIRE(aio->lock) { - lock_wait(aio->lock); + aio->lock.lock(); } void aio_unlock(ASYNCIO *aio) RELEASE(aio->lock) { - lock_unlock(aio->lock); + aio->lock.unlock(); sphore_signal(&aio->sphore); } @@ -752,7 +744,7 @@ int aio_error(ASYNCIO *aio) void aio_free(ASYNCIO *aio) { - lock_wait(aio->lock); + aio->lock.lock(); if(aio->thread) { thread_detach(aio->thread); @@ -885,98 +877,6 @@ bool thread_init_and_detach(void (*threadfunc)(void *), void *u, const char *nam return thread != nullptr; } -#if defined(CONF_FAMILY_UNIX) -typedef pthread_mutex_t LOCKINTERNAL; -#elif defined(CONF_FAMILY_WINDOWS) -typedef CRITICAL_SECTION LOCKINTERNAL; -#else -#error not implemented on this platform -#endif - -LOCK lock_create() -{ - LOCKINTERNAL *lock = (LOCKINTERNAL *)malloc(sizeof(*lock)); -#if defined(CONF_FAMILY_UNIX) - int result; -#endif - - if(!lock) - return 0; - -#if defined(CONF_FAMILY_UNIX) - result = pthread_mutex_init(lock, 0x0); - if(result != 0) - { - dbg_msg("lock", "init failed: %d", result); - free(lock); - return 0; - } -#elif defined(CONF_FAMILY_WINDOWS) - InitializeCriticalSection((LPCRITICAL_SECTION)lock); -#else -#error not implemented on this platform -#endif - return (LOCK)lock; -} - -void lock_destroy(LOCK lock) -{ -#if defined(CONF_FAMILY_UNIX) - int result = pthread_mutex_destroy((LOCKINTERNAL *)lock); - if(result != 0) - dbg_msg("lock", "destroy failed: %d", result); -#elif defined(CONF_FAMILY_WINDOWS) - DeleteCriticalSection((LPCRITICAL_SECTION)lock); -#else -#error not implemented on this platform -#endif - free(lock); -} - -int lock_trylock(LOCK lock) -{ -#if defined(CONF_FAMILY_UNIX) - return pthread_mutex_trylock((LOCKINTERNAL *)lock); -#elif defined(CONF_FAMILY_WINDOWS) - return !TryEnterCriticalSection((LPCRITICAL_SECTION)lock); -#else -#error not implemented on this platform -#endif -} - -#ifdef __clang__ -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wthread-safety-analysis" -#endif -void lock_wait(LOCK lock) -{ -#if defined(CONF_FAMILY_UNIX) - int result = pthread_mutex_lock((LOCKINTERNAL *)lock); - if(result != 0) - dbg_msg("lock", "lock failed: %d", result); -#elif defined(CONF_FAMILY_WINDOWS) - EnterCriticalSection((LPCRITICAL_SECTION)lock); -#else -#error not implemented on this platform -#endif -} - -void lock_unlock(LOCK lock) -{ -#if defined(CONF_FAMILY_UNIX) - int result = pthread_mutex_unlock((LOCKINTERNAL *)lock); - if(result != 0) - dbg_msg("lock", "unlock failed: %d", result); -#elif defined(CONF_FAMILY_WINDOWS) - LeaveCriticalSection((LPCRITICAL_SECTION)lock); -#else -#error not implemented on this platform -#endif -} -#ifdef __clang__ -#pragma clang diagnostic pop -#endif - #if defined(CONF_FAMILY_WINDOWS) void sphore_init(SEMAPHORE *sem) { diff --git a/src/base/system.h b/src/base/system.h index 0347df22b..bb98d36e0 100644 --- a/src/base/system.h +++ b/src/base/system.h @@ -14,10 +14,13 @@ #define __USE_GNU #endif +#include #include #include #include #include +#include +#include #include #ifdef __MINGW32__ @@ -41,9 +44,6 @@ #include #endif -#include -#include - #if __cplusplus >= 201703L #define MAYBE_UNUSED [[maybe_unused]] #elif defined(__GNUC__) @@ -607,107 +607,11 @@ void thread_detach(void *thread); */ bool thread_init_and_detach(void (*threadfunc)(void *), void *user, const char *name); -// Enable thread safety attributes only with clang. -// The attributes can be safely erased when compiling with other compilers. -#if defined(__clang__) && (!defined(SWIG)) -#define THREAD_ANNOTATION_ATTRIBUTE__(x) __attribute__((x)) -#else -#define THREAD_ANNOTATION_ATTRIBUTE__(x) // no-op -#endif - -#define CAPABILITY(x) \ - THREAD_ANNOTATION_ATTRIBUTE__(capability(x)) - -#define SCOPED_CAPABILITY \ - THREAD_ANNOTATION_ATTRIBUTE__(scoped_lockable) - -#define GUARDED_BY(x) \ - THREAD_ANNOTATION_ATTRIBUTE__(guarded_by(x)) - -#define PT_GUARDED_BY(x) \ - THREAD_ANNOTATION_ATTRIBUTE__(pt_guarded_by(x)) - -#define ACQUIRED_BEFORE(...) \ - THREAD_ANNOTATION_ATTRIBUTE__(acquired_before(__VA_ARGS__)) - -#define ACQUIRED_AFTER(...) \ - THREAD_ANNOTATION_ATTRIBUTE__(acquired_after(__VA_ARGS__)) - -#define REQUIRES(...) \ - THREAD_ANNOTATION_ATTRIBUTE__(requires_capability(__VA_ARGS__)) - -#define REQUIRES_SHARED(...) \ - THREAD_ANNOTATION_ATTRIBUTE__(requires_shared_capability(__VA_ARGS__)) - -#define ACQUIRE(...) \ - THREAD_ANNOTATION_ATTRIBUTE__(acquire_capability(__VA_ARGS__)) - -#define ACQUIRE_SHARED(...) \ - THREAD_ANNOTATION_ATTRIBUTE__(acquire_shared_capability(__VA_ARGS__)) - -#define RELEASE(...) \ - THREAD_ANNOTATION_ATTRIBUTE__(release_capability(__VA_ARGS__)) - -#define RELEASE_SHARED(...) \ - THREAD_ANNOTATION_ATTRIBUTE__(release_shared_capability(__VA_ARGS__)) - -#define RELEASE_GENERIC(...) \ - THREAD_ANNOTATION_ATTRIBUTE__(release_generic_capability(__VA_ARGS__)) - -#define TRY_ACQUIRE(...) \ - THREAD_ANNOTATION_ATTRIBUTE__(try_acquire_capability(__VA_ARGS__)) - -#define TRY_ACQUIRE_SHARED(...) \ - THREAD_ANNOTATION_ATTRIBUTE__(try_acquire_shared_capability(__VA_ARGS__)) - -#define EXCLUDES(...) \ - THREAD_ANNOTATION_ATTRIBUTE__(locks_excluded(__VA_ARGS__)) - -#define ASSERT_CAPABILITY(x) \ - THREAD_ANNOTATION_ATTRIBUTE__(assert_capability(x)) - -#define ASSERT_SHARED_CAPABILITY(x) \ - THREAD_ANNOTATION_ATTRIBUTE__(assert_shared_capability(x)) - -#define RETURN_CAPABILITY(x) \ - THREAD_ANNOTATION_ATTRIBUTE__(lock_returned(x)) - -#define NO_THREAD_SAFETY_ANALYSIS \ - THREAD_ANNOTATION_ATTRIBUTE__(no_thread_safety_analysis) - /** - * @defgroup Locks - * - * Synchronization primitives. - * + * @defgroup Semaphore * @see Threads */ -typedef CAPABILITY("mutex") void *LOCK; - -/** - * @ingroup Locks - */ -LOCK lock_create(); -/** - * @ingroup Locks - */ -void lock_destroy(LOCK lock); - -/** - * @ingroup Locks - */ -int lock_trylock(LOCK lock) TRY_ACQUIRE(1, lock); -/** - * @ingroup Locks - */ -void lock_wait(LOCK lock) ACQUIRE(lock); -/** - * @ingroup Locks - */ -void lock_unlock(LOCK lock) RELEASE(lock); - -/* Group: Semaphores */ #if defined(CONF_FAMILY_WINDOWS) typedef void *SEMAPHORE; #elif defined(CONF_PLATFORM_MACOS) @@ -721,19 +625,19 @@ typedef sem_t SEMAPHORE; #endif /** - * @ingroup Locks + * @ingroup Semaphore */ void sphore_init(SEMAPHORE *sem); /** - * @ingroup Locks + * @ingroup Semaphore */ void sphore_wait(SEMAPHORE *sem); /** - * @ingroup Locks + * @ingroup Semaphore */ void sphore_signal(SEMAPHORE *sem); /** - * @ingroup Locks + * @ingroup Semaphore */ void sphore_destroy(SEMAPHORE *sem); diff --git a/src/engine/client/serverbrowser_http.cpp b/src/engine/client/serverbrowser_http.cpp index 978ac9e16..df9221292 100644 --- a/src/engine/client/serverbrowser_http.cpp +++ b/src/engine/client/serverbrowser_http.cpp @@ -10,7 +10,7 @@ #include #include -#include +#include #include #include @@ -51,7 +51,7 @@ private: }; class CJob : public IJob { - LOCK m_Lock; + CLock m_Lock; std::shared_ptr m_pData; std::unique_ptr m_pHead PT_GUARDED_BY(m_Lock); std::unique_ptr m_pGet PT_GUARDED_BY(m_Lock); @@ -59,8 +59,7 @@ private: public: CJob(std::shared_ptr pData) : - m_pData(std::move(pData)) { m_Lock = lock_create(); } - ~CJob() override { lock_destroy(m_Lock); } + m_pData(std::move(pData)) {} void Abort() REQUIRES(!m_Lock); }; diff --git a/src/engine/client/updater.cpp b/src/engine/client/updater.cpp index 16a03048b..5cd7eda19 100644 --- a/src/engine/client/updater.cpp +++ b/src/engine/client/updater.cpp @@ -1,6 +1,7 @@ #include "updater.h" -#include + #include + #include #include #include @@ -94,7 +95,6 @@ CUpdater::CUpdater() m_pEngine = NULL; m_State = CLEAN; m_Percent = 0; - m_Lock = lock_create(); IStorage::FormatTmpPath(m_aClientExecTmp, sizeof(m_aClientExecTmp), CLIENT_EXEC); IStorage::FormatTmpPath(m_aServerExecTmp, sizeof(m_aServerExecTmp), SERVER_EXEC); @@ -107,11 +107,6 @@ void CUpdater::Init() m_pEngine = Kernel()->RequestInterface(); } -CUpdater::~CUpdater() -{ - lock_destroy(m_Lock); -} - void CUpdater::SetCurrentState(int NewState) { CLockScope ls(m_Lock); diff --git a/src/engine/client/updater.h b/src/engine/client/updater.h index 7571d5867..0b5c71c1d 100644 --- a/src/engine/client/updater.h +++ b/src/engine/client/updater.h @@ -1,7 +1,10 @@ #ifndef ENGINE_CLIENT_UPDATER_H #define ENGINE_CLIENT_UPDATER_H +#include + #include + #include #include @@ -39,7 +42,7 @@ class CUpdater : public IUpdater class IStorage *m_pStorage; class IEngine *m_pEngine; - LOCK m_Lock; + CLock m_Lock; int m_State; char m_aStatus[256] GUARDED_BY(m_Lock); @@ -68,7 +71,6 @@ class CUpdater : public IUpdater public: CUpdater(); - ~CUpdater(); int GetCurrentState() override REQUIRES(!m_Lock); void GetCurrentFile(char *pBuf, int BufSize) override REQUIRES(!m_Lock); diff --git a/src/engine/client/video.cpp b/src/engine/client/video.cpp index 8fe839a8f..c8efc7880 100644 --- a/src/engine/client/video.cpp +++ b/src/engine/client/video.cpp @@ -1,11 +1,11 @@ #if defined(CONF_VIDEORECORDER) -#include -#include +#include "video.h" -#include #include +#include #include +#include extern "C" { #include @@ -14,12 +14,9 @@ extern "C" { #include }; +#include #include #include - -#include "video.h" - -#include #include using namespace std::chrono_literals; @@ -35,7 +32,7 @@ using namespace std::chrono_literals; #endif const size_t FORMAT_GL_NCHANNELS = 4; -LOCK g_WriteLock = 0; +CLock g_WriteLock; CVideo::CVideo(CGraphics_Threaded *pGraphics, ISound *pSound, IStorage *pStorage, int Width, int Height, const char *pName) : m_pGraphics(pGraphics), @@ -66,13 +63,11 @@ CVideo::CVideo(CGraphics_Threaded *pGraphics, ISound *pSound, IStorage *pStorage ms_TickTime = time_freq() / m_FPS; ms_pCurrentVideo = this; - g_WriteLock = lock_create(); } CVideo::~CVideo() { ms_pCurrentVideo = 0; - lock_destroy(g_WriteLock); } void CVideo::Start() diff --git a/src/engine/client/video.h b/src/engine/client/video.h index 38a4ec02c..849a0b725 100644 --- a/src/engine/client/video.h +++ b/src/engine/client/video.h @@ -1,6 +1,7 @@ #ifndef ENGINE_CLIENT_VIDEO_H #define ENGINE_CLIENT_VIDEO_H +#include #include extern "C" { @@ -21,7 +22,7 @@ class CGraphics_Threaded; class ISound; class IStorage; -extern LOCK g_WriteLock; +extern CLock g_WriteLock; // a wrapper around a single output AVStream struct OutputStream diff --git a/src/engine/server/register.cpp b/src/engine/server/register.cpp index b262b77ae..34acda919 100644 --- a/src/engine/server/register.cpp +++ b/src/engine/server/register.cpp @@ -1,7 +1,8 @@ #include "register.h" -#include +#include #include + #include #include #include @@ -40,12 +41,7 @@ class CRegister : public IRegister class CGlobal { public: - ~CGlobal() - { - lock_destroy(m_Lock); - } - - LOCK m_Lock = lock_create(); + CLock m_Lock; int m_InfoSerial GUARDED_BY(m_Lock) = -1; int m_LatestSuccessfulInfoSerial GUARDED_BY(m_Lock) = -1; }; @@ -59,13 +55,9 @@ class CRegister : public IRegister m_pGlobal(std::move(pGlobal)) { } - ~CShared() - { - lock_destroy(m_Lock); - } std::shared_ptr m_pGlobal; - LOCK m_Lock = lock_create(); + CLock m_Lock; int m_NumTotalRequests GUARDED_BY(m_Lock) = 0; int m_LatestResponseStatus GUARDED_BY(m_Lock) = STATUS_NONE; int m_LatestResponseIndex GUARDED_BY(m_Lock) = -1; @@ -326,13 +318,12 @@ void CRegister::CProtocol::SendRegister() void CRegister::CProtocol::SendDeleteIfRegistered(bool Shutdown) { - lock_wait(m_pShared->m_Lock); - bool ShouldSendDelete = m_pShared->m_LatestResponseStatus == STATUS_OK; - m_pShared->m_LatestResponseStatus = STATUS_NONE; - lock_unlock(m_pShared->m_Lock); - if(!ShouldSendDelete) { - return; + const CLockScope LockScope(m_pShared->m_Lock); + const bool ShouldSendDelete = m_pShared->m_LatestResponseStatus == STATUS_OK; + m_pShared->m_LatestResponseStatus = STATUS_NONE; + if(!ShouldSendDelete) + return; } char aAddress[64]; diff --git a/src/engine/shared/http.cpp b/src/engine/shared/http.cpp index d024ba5e9..3e812463d 100644 --- a/src/engine/shared/http.cpp +++ b/src/engine/shared/http.cpp @@ -17,7 +17,7 @@ // TODO: Non-global pls? static CURLSH *gs_pShare; -static LOCK gs_aLocks[CURL_LOCK_DATA_LAST + 1]; +static CLock gs_aLocks[CURL_LOCK_DATA_LAST + 1]; static bool gs_Initialized = false; static int GetLockIndex(int Data) @@ -34,14 +34,14 @@ static void CurlLock(CURL *pHandle, curl_lock_data Data, curl_lock_access Access (void)pHandle; (void)Access; (void)pUser; - lock_wait(gs_aLocks[GetLockIndex(Data)]); + gs_aLocks[GetLockIndex(Data)].lock(); } static void CurlUnlock(CURL *pHandle, curl_lock_data Data, void *pUser) RELEASE(gs_aLocks[GetLockIndex(Data)]) { (void)pHandle; (void)pUser; - lock_unlock(gs_aLocks[GetLockIndex(Data)]); + gs_aLocks[GetLockIndex(Data)].unlock(); } int CurlDebug(CURL *pHandle, curl_infotype Type, char *pData, size_t DataSize, void *pUser) @@ -88,10 +88,6 @@ bool HttpInit(IStorage *pStorage) dbg_msg("http", "libcurl version %s (compiled = " LIBCURL_VERSION ")", pVersion->version); } - for(auto &Lock : gs_aLocks) - { - Lock = lock_create(); - } curl_share_setopt(gs_pShare, CURLSHOPT_SHARE, CURL_LOCK_DATA_DNS); curl_share_setopt(gs_pShare, CURLSHOPT_SHARE, CURL_LOCK_DATA_SSL_SESSION); curl_share_setopt(gs_pShare, CURLSHOPT_SHARE, CURL_LOCK_DATA_CONNECT); diff --git a/src/engine/shared/jobs.cpp b/src/engine/shared/jobs.cpp index 36ee17d8d..852243367 100644 --- a/src/engine/shared/jobs.cpp +++ b/src/engine/shared/jobs.cpp @@ -2,8 +2,6 @@ /* If you are missing that file, acquire a complete release at teeworlds.com. */ #include "jobs.h" -#include - IJob::IJob() : m_Status(STATE_PENDING) { @@ -20,7 +18,6 @@ CJobPool::CJobPool() { // empty the pool m_Shutdown = false; - m_Lock = lock_create(); sphore_init(&m_Semaphore); m_pFirstJob = 0; m_pLastJob = 0; @@ -85,7 +82,6 @@ void CJobPool::Destroy() for(void *pThread : m_vpThreads) thread_wait(pThread); m_vpThreads.clear(); - lock_destroy(m_Lock); sphore_destroy(&m_Semaphore); } diff --git a/src/engine/shared/jobs.h b/src/engine/shared/jobs.h index 2a24efbdc..8f347b16c 100644 --- a/src/engine/shared/jobs.h +++ b/src/engine/shared/jobs.h @@ -3,6 +3,7 @@ #ifndef ENGINE_SHARED_JOBS_H #define ENGINE_SHARED_JOBS_H +#include #include #include @@ -41,7 +42,7 @@ class CJobPool std::vector m_vpThreads; std::atomic m_Shutdown; - LOCK m_Lock; + CLock m_Lock; SEMAPHORE m_Semaphore; std::shared_ptr m_pFirstJob GUARDED_BY(m_Lock); std::shared_ptr m_pLastJob GUARDED_BY(m_Lock); diff --git a/src/test/thread.cpp b/src/test/thread.cpp index e0e242b43..76c8422ba 100644 --- a/src/test/thread.cpp +++ b/src/test/thread.cpp @@ -1,5 +1,6 @@ #include +#include #include #include @@ -82,17 +83,16 @@ TEST(Thread, SemaphoreMultiThreaded) static void LockThread(void *pUser) { - LOCK *pLock = (LOCK *)pUser; - lock_wait(*pLock); - lock_unlock(*pLock); + CLock *pLock = (CLock *)pUser; + pLock->lock(); + pLock->unlock(); } TEST(Thread, Lock) { - LOCK Lock = lock_create(); - lock_wait(Lock); + CLock Lock; + Lock.lock(); void *pThread = thread_init(LockThread, &Lock, "lock"); - lock_unlock(Lock); + Lock.unlock(); thread_wait(pThread); - lock_destroy(Lock); }