mirror of
https://github.com/ddnet/ddnet.git
synced 2024-11-10 01:58:19 +00:00
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:
parent
de52ded86d
commit
3d858c28ee
|
@ -1844,7 +1844,7 @@ set_src(BASE GLOB_RECURSE src/base
|
||||||
hash_ctxt.h
|
hash_ctxt.h
|
||||||
hash_libtomcrypt.cpp
|
hash_libtomcrypt.cpp
|
||||||
hash_openssl.cpp
|
hash_openssl.cpp
|
||||||
lock_scope.h
|
lock.h
|
||||||
log.cpp
|
log.cpp
|
||||||
log.h
|
log.h
|
||||||
logger.h
|
logger.h
|
||||||
|
|
135
src/base/lock.h
Normal file
135
src/base/lock.h
Normal 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
|
|
@ -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
|
|
|
@ -3,6 +3,8 @@
|
||||||
#include <atomic>
|
#include <atomic>
|
||||||
#include <cctype>
|
#include <cctype>
|
||||||
#include <charconv>
|
#include <charconv>
|
||||||
|
#include <chrono>
|
||||||
|
#include <cinttypes>
|
||||||
#include <cmath>
|
#include <cmath>
|
||||||
#include <cstdarg>
|
#include <cstdarg>
|
||||||
#include <cstdio>
|
#include <cstdio>
|
||||||
|
@ -10,17 +12,12 @@
|
||||||
#include <iterator> // std::size
|
#include <iterator> // std::size
|
||||||
#include <string_view>
|
#include <string_view>
|
||||||
|
|
||||||
|
#include "lock.h"
|
||||||
|
#include "logger.h"
|
||||||
#include "system.h"
|
#include "system.h"
|
||||||
|
|
||||||
#include "lock_scope.h"
|
|
||||||
#include "logger.h"
|
|
||||||
|
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
|
|
||||||
#include <chrono>
|
|
||||||
|
|
||||||
#include <cinttypes>
|
|
||||||
|
|
||||||
#if defined(CONF_WEBSOCKETS)
|
#if defined(CONF_WEBSOCKETS)
|
||||||
#include <engine/shared/websockets.h>
|
#include <engine/shared/websockets.h>
|
||||||
#endif
|
#endif
|
||||||
|
@ -474,10 +471,9 @@ int io_sync(IOHANDLE io)
|
||||||
#define ASYNC_BUFSIZE (8 * 1024)
|
#define ASYNC_BUFSIZE (8 * 1024)
|
||||||
#define ASYNC_LOCAL_BUFSIZE (64 * 1024)
|
#define ASYNC_LOCAL_BUFSIZE (64 * 1024)
|
||||||
|
|
||||||
// TODO: Use Thread Safety Analysis when this file is converted to C++
|
|
||||||
struct ASYNCIO
|
struct ASYNCIO
|
||||||
{
|
{
|
||||||
LOCK lock;
|
CLock lock;
|
||||||
IOHANDLE io;
|
IOHANDLE io;
|
||||||
SEMAPHORE sphore;
|
SEMAPHORE sphore;
|
||||||
void *thread;
|
void *thread;
|
||||||
|
@ -530,13 +526,12 @@ static void aio_handle_free_and_unlock(ASYNCIO *aio) RELEASE(aio->lock)
|
||||||
aio->refcount--;
|
aio->refcount--;
|
||||||
|
|
||||||
do_free = aio->refcount == 0;
|
do_free = aio->refcount == 0;
|
||||||
lock_unlock(aio->lock);
|
aio->lock.unlock();
|
||||||
if(do_free)
|
if(do_free)
|
||||||
{
|
{
|
||||||
free(aio->buffer);
|
free(aio->buffer);
|
||||||
sphore_destroy(&aio->sphore);
|
sphore_destroy(&aio->sphore);
|
||||||
lock_destroy(aio->lock);
|
delete aio;
|
||||||
free(aio);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -544,7 +539,7 @@ static void aio_thread(void *user)
|
||||||
{
|
{
|
||||||
ASYNCIO *aio = (ASYNCIO *)user;
|
ASYNCIO *aio = (ASYNCIO *)user;
|
||||||
|
|
||||||
lock_wait(aio->lock);
|
aio->lock.lock();
|
||||||
while(true)
|
while(true)
|
||||||
{
|
{
|
||||||
struct BUFFERS buffers;
|
struct BUFFERS buffers;
|
||||||
|
@ -563,9 +558,9 @@ static void aio_thread(void *user)
|
||||||
aio_handle_free_and_unlock(aio);
|
aio_handle_free_and_unlock(aio);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
lock_unlock(aio->lock);
|
aio->lock.unlock();
|
||||||
sphore_wait(&aio->sphore);
|
sphore_wait(&aio->sphore);
|
||||||
lock_wait(aio->lock);
|
aio->lock.lock();
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -589,26 +584,25 @@ static void aio_thread(void *user)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
aio->read_pos = (aio->read_pos + buffers.len1 + buffers.len2) % aio->buffer_size;
|
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_write(aio->io, local_buffer, local_buffer_len);
|
||||||
io_flush(aio->io);
|
io_flush(aio->io);
|
||||||
result_io_error = io_error(aio->io);
|
result_io_error = io_error(aio->io);
|
||||||
|
|
||||||
lock_wait(aio->lock);
|
aio->lock.lock();
|
||||||
aio->error = result_io_error;
|
aio->error = result_io_error;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ASYNCIO *aio_new(IOHANDLE io)
|
ASYNCIO *aio_new(IOHANDLE io)
|
||||||
{
|
{
|
||||||
ASYNCIO *aio = (ASYNCIO *)malloc(sizeof(*aio));
|
ASYNCIO *aio = new ASYNCIO;
|
||||||
if(!aio)
|
if(!aio)
|
||||||
{
|
{
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
aio->io = io;
|
aio->io = io;
|
||||||
aio->lock = lock_create();
|
|
||||||
sphore_init(&aio->sphore);
|
sphore_init(&aio->sphore);
|
||||||
aio->thread = 0;
|
aio->thread = 0;
|
||||||
|
|
||||||
|
@ -616,8 +610,7 @@ ASYNCIO *aio_new(IOHANDLE io)
|
||||||
if(!aio->buffer)
|
if(!aio->buffer)
|
||||||
{
|
{
|
||||||
sphore_destroy(&aio->sphore);
|
sphore_destroy(&aio->sphore);
|
||||||
lock_destroy(aio->lock);
|
delete aio;
|
||||||
free(aio);
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
aio->buffer_size = ASYNC_BUFSIZE;
|
aio->buffer_size = ASYNC_BUFSIZE;
|
||||||
|
@ -632,8 +625,7 @@ ASYNCIO *aio_new(IOHANDLE io)
|
||||||
{
|
{
|
||||||
free(aio->buffer);
|
free(aio->buffer);
|
||||||
sphore_destroy(&aio->sphore);
|
sphore_destroy(&aio->sphore);
|
||||||
lock_destroy(aio->lock);
|
delete aio;
|
||||||
free(aio);
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
return aio;
|
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)
|
void aio_lock(ASYNCIO *aio) ACQUIRE(aio->lock)
|
||||||
{
|
{
|
||||||
lock_wait(aio->lock);
|
aio->lock.lock();
|
||||||
}
|
}
|
||||||
|
|
||||||
void aio_unlock(ASYNCIO *aio) RELEASE(aio->lock)
|
void aio_unlock(ASYNCIO *aio) RELEASE(aio->lock)
|
||||||
{
|
{
|
||||||
lock_unlock(aio->lock);
|
aio->lock.unlock();
|
||||||
sphore_signal(&aio->sphore);
|
sphore_signal(&aio->sphore);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -752,7 +744,7 @@ int aio_error(ASYNCIO *aio)
|
||||||
|
|
||||||
void aio_free(ASYNCIO *aio)
|
void aio_free(ASYNCIO *aio)
|
||||||
{
|
{
|
||||||
lock_wait(aio->lock);
|
aio->lock.lock();
|
||||||
if(aio->thread)
|
if(aio->thread)
|
||||||
{
|
{
|
||||||
thread_detach(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;
|
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)
|
#if defined(CONF_FAMILY_WINDOWS)
|
||||||
void sphore_init(SEMAPHORE *sem)
|
void sphore_init(SEMAPHORE *sem)
|
||||||
{
|
{
|
||||||
|
|
|
@ -14,10 +14,13 @@
|
||||||
#define __USE_GNU
|
#define __USE_GNU
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#include <chrono>
|
||||||
#include <cinttypes>
|
#include <cinttypes>
|
||||||
#include <cstdarg>
|
#include <cstdarg>
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
#include <ctime>
|
#include <ctime>
|
||||||
|
#include <functional>
|
||||||
|
#include <mutex>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
#ifdef __MINGW32__
|
#ifdef __MINGW32__
|
||||||
|
@ -41,9 +44,6 @@
|
||||||
#include <sys/socket.h>
|
#include <sys/socket.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include <chrono>
|
|
||||||
#include <functional>
|
|
||||||
|
|
||||||
#if __cplusplus >= 201703L
|
#if __cplusplus >= 201703L
|
||||||
#define MAYBE_UNUSED [[maybe_unused]]
|
#define MAYBE_UNUSED [[maybe_unused]]
|
||||||
#elif defined(__GNUC__)
|
#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);
|
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
|
* @defgroup Semaphore
|
||||||
*
|
|
||||||
* Synchronization primitives.
|
|
||||||
*
|
|
||||||
* @see Threads
|
* @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)
|
#if defined(CONF_FAMILY_WINDOWS)
|
||||||
typedef void *SEMAPHORE;
|
typedef void *SEMAPHORE;
|
||||||
#elif defined(CONF_PLATFORM_MACOS)
|
#elif defined(CONF_PLATFORM_MACOS)
|
||||||
|
@ -721,19 +625,19 @@ typedef sem_t SEMAPHORE;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @ingroup Locks
|
* @ingroup Semaphore
|
||||||
*/
|
*/
|
||||||
void sphore_init(SEMAPHORE *sem);
|
void sphore_init(SEMAPHORE *sem);
|
||||||
/**
|
/**
|
||||||
* @ingroup Locks
|
* @ingroup Semaphore
|
||||||
*/
|
*/
|
||||||
void sphore_wait(SEMAPHORE *sem);
|
void sphore_wait(SEMAPHORE *sem);
|
||||||
/**
|
/**
|
||||||
* @ingroup Locks
|
* @ingroup Semaphore
|
||||||
*/
|
*/
|
||||||
void sphore_signal(SEMAPHORE *sem);
|
void sphore_signal(SEMAPHORE *sem);
|
||||||
/**
|
/**
|
||||||
* @ingroup Locks
|
* @ingroup Semaphore
|
||||||
*/
|
*/
|
||||||
void sphore_destroy(SEMAPHORE *sem);
|
void sphore_destroy(SEMAPHORE *sem);
|
||||||
|
|
||||||
|
|
|
@ -10,7 +10,7 @@
|
||||||
#include <engine/shared/serverinfo.h>
|
#include <engine/shared/serverinfo.h>
|
||||||
#include <engine/storage.h>
|
#include <engine/storage.h>
|
||||||
|
|
||||||
#include <base/lock_scope.h>
|
#include <base/lock.h>
|
||||||
#include <base/system.h>
|
#include <base/system.h>
|
||||||
|
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
@ -51,7 +51,7 @@ private:
|
||||||
};
|
};
|
||||||
class CJob : public IJob
|
class CJob : public IJob
|
||||||
{
|
{
|
||||||
LOCK m_Lock;
|
CLock m_Lock;
|
||||||
std::shared_ptr<CData> m_pData;
|
std::shared_ptr<CData> m_pData;
|
||||||
std::unique_ptr<CHttpRequest> m_pHead PT_GUARDED_BY(m_Lock);
|
std::unique_ptr<CHttpRequest> m_pHead PT_GUARDED_BY(m_Lock);
|
||||||
std::unique_ptr<CHttpRequest> m_pGet PT_GUARDED_BY(m_Lock);
|
std::unique_ptr<CHttpRequest> m_pGet PT_GUARDED_BY(m_Lock);
|
||||||
|
@ -59,8 +59,7 @@ private:
|
||||||
|
|
||||||
public:
|
public:
|
||||||
CJob(std::shared_ptr<CData> pData) :
|
CJob(std::shared_ptr<CData> pData) :
|
||||||
m_pData(std::move(pData)) { m_Lock = lock_create(); }
|
m_pData(std::move(pData)) {}
|
||||||
~CJob() override { lock_destroy(m_Lock); }
|
|
||||||
void Abort() REQUIRES(!m_Lock);
|
void Abort() REQUIRES(!m_Lock);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
#include "updater.h"
|
#include "updater.h"
|
||||||
#include <base/lock_scope.h>
|
|
||||||
#include <base/system.h>
|
#include <base/system.h>
|
||||||
|
|
||||||
#include <engine/client.h>
|
#include <engine/client.h>
|
||||||
#include <engine/engine.h>
|
#include <engine/engine.h>
|
||||||
#include <engine/external/json-parser/json.h>
|
#include <engine/external/json-parser/json.h>
|
||||||
|
@ -94,7 +95,6 @@ CUpdater::CUpdater()
|
||||||
m_pEngine = NULL;
|
m_pEngine = NULL;
|
||||||
m_State = CLEAN;
|
m_State = CLEAN;
|
||||||
m_Percent = 0;
|
m_Percent = 0;
|
||||||
m_Lock = lock_create();
|
|
||||||
|
|
||||||
IStorage::FormatTmpPath(m_aClientExecTmp, sizeof(m_aClientExecTmp), CLIENT_EXEC);
|
IStorage::FormatTmpPath(m_aClientExecTmp, sizeof(m_aClientExecTmp), CLIENT_EXEC);
|
||||||
IStorage::FormatTmpPath(m_aServerExecTmp, sizeof(m_aServerExecTmp), SERVER_EXEC);
|
IStorage::FormatTmpPath(m_aServerExecTmp, sizeof(m_aServerExecTmp), SERVER_EXEC);
|
||||||
|
@ -107,11 +107,6 @@ void CUpdater::Init()
|
||||||
m_pEngine = Kernel()->RequestInterface<IEngine>();
|
m_pEngine = Kernel()->RequestInterface<IEngine>();
|
||||||
}
|
}
|
||||||
|
|
||||||
CUpdater::~CUpdater()
|
|
||||||
{
|
|
||||||
lock_destroy(m_Lock);
|
|
||||||
}
|
|
||||||
|
|
||||||
void CUpdater::SetCurrentState(int NewState)
|
void CUpdater::SetCurrentState(int NewState)
|
||||||
{
|
{
|
||||||
CLockScope ls(m_Lock);
|
CLockScope ls(m_Lock);
|
||||||
|
|
|
@ -1,7 +1,10 @@
|
||||||
#ifndef ENGINE_CLIENT_UPDATER_H
|
#ifndef ENGINE_CLIENT_UPDATER_H
|
||||||
#define ENGINE_CLIENT_UPDATER_H
|
#define ENGINE_CLIENT_UPDATER_H
|
||||||
|
|
||||||
|
#include <base/lock.h>
|
||||||
|
|
||||||
#include <engine/updater.h>
|
#include <engine/updater.h>
|
||||||
|
|
||||||
#include <map>
|
#include <map>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
|
@ -39,7 +42,7 @@ class CUpdater : public IUpdater
|
||||||
class IStorage *m_pStorage;
|
class IStorage *m_pStorage;
|
||||||
class IEngine *m_pEngine;
|
class IEngine *m_pEngine;
|
||||||
|
|
||||||
LOCK m_Lock;
|
CLock m_Lock;
|
||||||
|
|
||||||
int m_State;
|
int m_State;
|
||||||
char m_aStatus[256] GUARDED_BY(m_Lock);
|
char m_aStatus[256] GUARDED_BY(m_Lock);
|
||||||
|
@ -68,7 +71,6 @@ class CUpdater : public IUpdater
|
||||||
|
|
||||||
public:
|
public:
|
||||||
CUpdater();
|
CUpdater();
|
||||||
~CUpdater();
|
|
||||||
|
|
||||||
int GetCurrentState() override REQUIRES(!m_Lock);
|
int GetCurrentState() override REQUIRES(!m_Lock);
|
||||||
void GetCurrentFile(char *pBuf, int BufSize) override REQUIRES(!m_Lock);
|
void GetCurrentFile(char *pBuf, int BufSize) override REQUIRES(!m_Lock);
|
||||||
|
|
|
@ -1,11 +1,11 @@
|
||||||
#if defined(CONF_VIDEORECORDER)
|
#if defined(CONF_VIDEORECORDER)
|
||||||
|
|
||||||
#include <engine/shared/config.h>
|
#include "video.h"
|
||||||
#include <engine/storage.h>
|
|
||||||
|
|
||||||
#include <base/lock_scope.h>
|
|
||||||
#include <engine/client/graphics_threaded.h>
|
#include <engine/client/graphics_threaded.h>
|
||||||
|
#include <engine/shared/config.h>
|
||||||
#include <engine/sound.h>
|
#include <engine/sound.h>
|
||||||
|
#include <engine/storage.h>
|
||||||
|
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#include <libavutil/avutil.h>
|
#include <libavutil/avutil.h>
|
||||||
|
@ -14,12 +14,9 @@ extern "C" {
|
||||||
#include <libswscale/swscale.h>
|
#include <libswscale/swscale.h>
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#include <chrono>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <mutex>
|
#include <mutex>
|
||||||
|
|
||||||
#include "video.h"
|
|
||||||
|
|
||||||
#include <chrono>
|
|
||||||
#include <thread>
|
#include <thread>
|
||||||
|
|
||||||
using namespace std::chrono_literals;
|
using namespace std::chrono_literals;
|
||||||
|
@ -35,7 +32,7 @@ using namespace std::chrono_literals;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
const size_t FORMAT_GL_NCHANNELS = 4;
|
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) :
|
CVideo::CVideo(CGraphics_Threaded *pGraphics, ISound *pSound, IStorage *pStorage, int Width, int Height, const char *pName) :
|
||||||
m_pGraphics(pGraphics),
|
m_pGraphics(pGraphics),
|
||||||
|
@ -66,13 +63,11 @@ CVideo::CVideo(CGraphics_Threaded *pGraphics, ISound *pSound, IStorage *pStorage
|
||||||
|
|
||||||
ms_TickTime = time_freq() / m_FPS;
|
ms_TickTime = time_freq() / m_FPS;
|
||||||
ms_pCurrentVideo = this;
|
ms_pCurrentVideo = this;
|
||||||
g_WriteLock = lock_create();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
CVideo::~CVideo()
|
CVideo::~CVideo()
|
||||||
{
|
{
|
||||||
ms_pCurrentVideo = 0;
|
ms_pCurrentVideo = 0;
|
||||||
lock_destroy(g_WriteLock);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void CVideo::Start()
|
void CVideo::Start()
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
#ifndef ENGINE_CLIENT_VIDEO_H
|
#ifndef ENGINE_CLIENT_VIDEO_H
|
||||||
#define ENGINE_CLIENT_VIDEO_H
|
#define ENGINE_CLIENT_VIDEO_H
|
||||||
|
|
||||||
|
#include <base/lock.h>
|
||||||
#include <base/system.h>
|
#include <base/system.h>
|
||||||
|
|
||||||
extern "C" {
|
extern "C" {
|
||||||
|
@ -21,7 +22,7 @@ class CGraphics_Threaded;
|
||||||
class ISound;
|
class ISound;
|
||||||
class IStorage;
|
class IStorage;
|
||||||
|
|
||||||
extern LOCK g_WriteLock;
|
extern CLock g_WriteLock;
|
||||||
|
|
||||||
// a wrapper around a single output AVStream
|
// a wrapper around a single output AVStream
|
||||||
struct OutputStream
|
struct OutputStream
|
||||||
|
|
|
@ -1,7 +1,8 @@
|
||||||
#include "register.h"
|
#include "register.h"
|
||||||
|
|
||||||
#include <base/lock_scope.h>
|
#include <base/lock.h>
|
||||||
#include <base/log.h>
|
#include <base/log.h>
|
||||||
|
|
||||||
#include <engine/console.h>
|
#include <engine/console.h>
|
||||||
#include <engine/engine.h>
|
#include <engine/engine.h>
|
||||||
#include <engine/shared/config.h>
|
#include <engine/shared/config.h>
|
||||||
|
@ -40,12 +41,7 @@ class CRegister : public IRegister
|
||||||
class CGlobal
|
class CGlobal
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
~CGlobal()
|
CLock m_Lock;
|
||||||
{
|
|
||||||
lock_destroy(m_Lock);
|
|
||||||
}
|
|
||||||
|
|
||||||
LOCK m_Lock = lock_create();
|
|
||||||
int m_InfoSerial GUARDED_BY(m_Lock) = -1;
|
int m_InfoSerial GUARDED_BY(m_Lock) = -1;
|
||||||
int m_LatestSuccessfulInfoSerial 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))
|
m_pGlobal(std::move(pGlobal))
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
~CShared()
|
|
||||||
{
|
|
||||||
lock_destroy(m_Lock);
|
|
||||||
}
|
|
||||||
|
|
||||||
std::shared_ptr<CGlobal> m_pGlobal;
|
std::shared_ptr<CGlobal> m_pGlobal;
|
||||||
LOCK m_Lock = lock_create();
|
CLock m_Lock;
|
||||||
int m_NumTotalRequests GUARDED_BY(m_Lock) = 0;
|
int m_NumTotalRequests GUARDED_BY(m_Lock) = 0;
|
||||||
int m_LatestResponseStatus GUARDED_BY(m_Lock) = STATUS_NONE;
|
int m_LatestResponseStatus GUARDED_BY(m_Lock) = STATUS_NONE;
|
||||||
int m_LatestResponseIndex GUARDED_BY(m_Lock) = -1;
|
int m_LatestResponseIndex GUARDED_BY(m_Lock) = -1;
|
||||||
|
@ -326,12 +318,11 @@ void CRegister::CProtocol::SendRegister()
|
||||||
|
|
||||||
void CRegister::CProtocol::SendDeleteIfRegistered(bool Shutdown)
|
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)
|
|
||||||
{
|
{
|
||||||
|
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;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -17,7 +17,7 @@
|
||||||
|
|
||||||
// TODO: Non-global pls?
|
// TODO: Non-global pls?
|
||||||
static CURLSH *gs_pShare;
|
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 bool gs_Initialized = false;
|
||||||
|
|
||||||
static int GetLockIndex(int Data)
|
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)pHandle;
|
||||||
(void)Access;
|
(void)Access;
|
||||||
(void)pUser;
|
(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)])
|
static void CurlUnlock(CURL *pHandle, curl_lock_data Data, void *pUser) RELEASE(gs_aLocks[GetLockIndex(Data)])
|
||||||
{
|
{
|
||||||
(void)pHandle;
|
(void)pHandle;
|
||||||
(void)pUser;
|
(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)
|
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);
|
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_DNS);
|
||||||
curl_share_setopt(gs_pShare, CURLSHOPT_SHARE, CURL_LOCK_DATA_SSL_SESSION);
|
curl_share_setopt(gs_pShare, CURLSHOPT_SHARE, CURL_LOCK_DATA_SSL_SESSION);
|
||||||
curl_share_setopt(gs_pShare, CURLSHOPT_SHARE, CURL_LOCK_DATA_CONNECT);
|
curl_share_setopt(gs_pShare, CURLSHOPT_SHARE, CURL_LOCK_DATA_CONNECT);
|
||||||
|
|
|
@ -2,8 +2,6 @@
|
||||||
/* If you are missing that file, acquire a complete release at teeworlds.com. */
|
/* If you are missing that file, acquire a complete release at teeworlds.com. */
|
||||||
#include "jobs.h"
|
#include "jobs.h"
|
||||||
|
|
||||||
#include <base/lock_scope.h>
|
|
||||||
|
|
||||||
IJob::IJob() :
|
IJob::IJob() :
|
||||||
m_Status(STATE_PENDING)
|
m_Status(STATE_PENDING)
|
||||||
{
|
{
|
||||||
|
@ -20,7 +18,6 @@ CJobPool::CJobPool()
|
||||||
{
|
{
|
||||||
// empty the pool
|
// empty the pool
|
||||||
m_Shutdown = false;
|
m_Shutdown = false;
|
||||||
m_Lock = lock_create();
|
|
||||||
sphore_init(&m_Semaphore);
|
sphore_init(&m_Semaphore);
|
||||||
m_pFirstJob = 0;
|
m_pFirstJob = 0;
|
||||||
m_pLastJob = 0;
|
m_pLastJob = 0;
|
||||||
|
@ -85,7 +82,6 @@ void CJobPool::Destroy()
|
||||||
for(void *pThread : m_vpThreads)
|
for(void *pThread : m_vpThreads)
|
||||||
thread_wait(pThread);
|
thread_wait(pThread);
|
||||||
m_vpThreads.clear();
|
m_vpThreads.clear();
|
||||||
lock_destroy(m_Lock);
|
|
||||||
sphore_destroy(&m_Semaphore);
|
sphore_destroy(&m_Semaphore);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
#ifndef ENGINE_SHARED_JOBS_H
|
#ifndef ENGINE_SHARED_JOBS_H
|
||||||
#define ENGINE_SHARED_JOBS_H
|
#define ENGINE_SHARED_JOBS_H
|
||||||
|
|
||||||
|
#include <base/lock.h>
|
||||||
#include <base/system.h>
|
#include <base/system.h>
|
||||||
|
|
||||||
#include <atomic>
|
#include <atomic>
|
||||||
|
@ -41,7 +42,7 @@ class CJobPool
|
||||||
std::vector<void *> m_vpThreads;
|
std::vector<void *> m_vpThreads;
|
||||||
std::atomic<bool> m_Shutdown;
|
std::atomic<bool> m_Shutdown;
|
||||||
|
|
||||||
LOCK m_Lock;
|
CLock m_Lock;
|
||||||
SEMAPHORE m_Semaphore;
|
SEMAPHORE m_Semaphore;
|
||||||
std::shared_ptr<IJob> m_pFirstJob GUARDED_BY(m_Lock);
|
std::shared_ptr<IJob> m_pFirstJob GUARDED_BY(m_Lock);
|
||||||
std::shared_ptr<IJob> m_pLastJob GUARDED_BY(m_Lock);
|
std::shared_ptr<IJob> m_pLastJob GUARDED_BY(m_Lock);
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
#include <gtest/gtest.h>
|
#include <gtest/gtest.h>
|
||||||
|
|
||||||
|
#include <base/lock.h>
|
||||||
#include <base/system.h>
|
#include <base/system.h>
|
||||||
#include <base/tl/threading.h>
|
#include <base/tl/threading.h>
|
||||||
|
|
||||||
|
@ -82,17 +83,16 @@ TEST(Thread, SemaphoreMultiThreaded)
|
||||||
|
|
||||||
static void LockThread(void *pUser)
|
static void LockThread(void *pUser)
|
||||||
{
|
{
|
||||||
LOCK *pLock = (LOCK *)pUser;
|
CLock *pLock = (CLock *)pUser;
|
||||||
lock_wait(*pLock);
|
pLock->lock();
|
||||||
lock_unlock(*pLock);
|
pLock->unlock();
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(Thread, Lock)
|
TEST(Thread, Lock)
|
||||||
{
|
{
|
||||||
LOCK Lock = lock_create();
|
CLock Lock;
|
||||||
lock_wait(Lock);
|
Lock.lock();
|
||||||
void *pThread = thread_init(LockThread, &Lock, "lock");
|
void *pThread = thread_init(LockThread, &Lock, "lock");
|
||||||
lock_unlock(Lock);
|
Lock.unlock();
|
||||||
thread_wait(pThread);
|
thread_wait(pThread);
|
||||||
lock_destroy(Lock);
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue