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++.
This commit is contained in:
Robert Müller 2023-11-10 21:15:51 +01:00
parent de52ded86d
commit 3d858c28ee
15 changed files with 199 additions and 308 deletions

View file

@ -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

135
src/base/lock.h Normal file
View file

@ -0,0 +1,135 @@
#ifndef BASE_LOCK_H
#define BASE_LOCK_H
#include <mutex>
// 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

View file

@ -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

View file

@ -3,6 +3,8 @@
#include <atomic>
#include <cctype>
#include <charconv>
#include <chrono>
#include <cinttypes>
#include <cmath>
#include <cstdarg>
#include <cstdio>
@ -10,17 +12,12 @@
#include <iterator> // std::size
#include <string_view>
#include "lock.h"
#include "logger.h"
#include "system.h"
#include "lock_scope.h"
#include "logger.h"
#include <sys/types.h>
#include <chrono>
#include <cinttypes>
#if defined(CONF_WEBSOCKETS)
#include <engine/shared/websockets.h>
#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)
{

View file

@ -14,10 +14,13 @@
#define __USE_GNU
#endif
#include <chrono>
#include <cinttypes>
#include <cstdarg>
#include <cstdint>
#include <ctime>
#include <functional>
#include <mutex>
#include <string>
#ifdef __MINGW32__
@ -41,9 +44,6 @@
#include <sys/socket.h>
#endif
#include <chrono>
#include <functional>
#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);

View file

@ -10,7 +10,7 @@
#include <engine/shared/serverinfo.h>
#include <engine/storage.h>
#include <base/lock_scope.h>
#include <base/lock.h>
#include <base/system.h>
#include <memory>
@ -51,7 +51,7 @@ private:
};
class CJob : public IJob
{
LOCK m_Lock;
CLock m_Lock;
std::shared_ptr<CData> m_pData;
std::unique_ptr<CHttpRequest> m_pHead PT_GUARDED_BY(m_Lock);
std::unique_ptr<CHttpRequest> m_pGet PT_GUARDED_BY(m_Lock);
@ -59,8 +59,7 @@ private:
public:
CJob(std::shared_ptr<CData> 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);
};

View file

@ -1,6 +1,7 @@
#include "updater.h"
#include <base/lock_scope.h>
#include <base/system.h>
#include <engine/client.h>
#include <engine/engine.h>
#include <engine/external/json-parser/json.h>
@ -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<IEngine>();
}
CUpdater::~CUpdater()
{
lock_destroy(m_Lock);
}
void CUpdater::SetCurrentState(int NewState)
{
CLockScope ls(m_Lock);

View file

@ -1,7 +1,10 @@
#ifndef ENGINE_CLIENT_UPDATER_H
#define ENGINE_CLIENT_UPDATER_H
#include <base/lock.h>
#include <engine/updater.h>
#include <map>
#include <string>
@ -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);

View file

@ -1,11 +1,11 @@
#if defined(CONF_VIDEORECORDER)
#include <engine/shared/config.h>
#include <engine/storage.h>
#include "video.h"
#include <base/lock_scope.h>
#include <engine/client/graphics_threaded.h>
#include <engine/shared/config.h>
#include <engine/sound.h>
#include <engine/storage.h>
extern "C" {
#include <libavutil/avutil.h>
@ -14,12 +14,9 @@ extern "C" {
#include <libswscale/swscale.h>
};
#include <chrono>
#include <memory>
#include <mutex>
#include "video.h"
#include <chrono>
#include <thread>
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()

View file

@ -1,6 +1,7 @@
#ifndef ENGINE_CLIENT_VIDEO_H
#define ENGINE_CLIENT_VIDEO_H
#include <base/lock.h>
#include <base/system.h>
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

View file

@ -1,7 +1,8 @@
#include "register.h"
#include <base/lock_scope.h>
#include <base/lock.h>
#include <base/log.h>
#include <engine/console.h>
#include <engine/engine.h>
#include <engine/shared/config.h>
@ -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<CGlobal> 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];

View file

@ -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);

View file

@ -2,8 +2,6 @@
/* If you are missing that file, acquire a complete release at teeworlds.com. */
#include "jobs.h"
#include <base/lock_scope.h>
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);
}

View file

@ -3,6 +3,7 @@
#ifndef ENGINE_SHARED_JOBS_H
#define ENGINE_SHARED_JOBS_H
#include <base/lock.h>
#include <base/system.h>
#include <atomic>
@ -41,7 +42,7 @@ class CJobPool
std::vector<void *> m_vpThreads;
std::atomic<bool> m_Shutdown;
LOCK m_Lock;
CLock m_Lock;
SEMAPHORE m_Semaphore;
std::shared_ptr<IJob> m_pFirstJob GUARDED_BY(m_Lock);
std::shared_ptr<IJob> m_pLastJob GUARDED_BY(m_Lock);

View file

@ -1,5 +1,6 @@
#include <gtest/gtest.h>
#include <base/lock.h>
#include <base/system.h>
#include <base/tl/threading.h>
@ -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);
}