Convert threads.c to C++
Also vastly simplify and remove related code.
This commit is contained in:
+1
-4
@@ -764,12 +764,9 @@ SET(COMMON_OBJS
|
||||
common/atomic.h
|
||||
common/bool.h
|
||||
common/math_defs.h
|
||||
common/rwlock.c
|
||||
common/rwlock.h
|
||||
common/static_assert.h
|
||||
common/threads.c
|
||||
common/threads.cpp
|
||||
common/threads.h
|
||||
common/uintmap.c
|
||||
common/uintmap.h
|
||||
)
|
||||
SET(OPENAL_OBJS
|
||||
|
||||
@@ -7,7 +7,6 @@
|
||||
|
||||
#include "inprogext.h"
|
||||
#include "atomic.h"
|
||||
#include "rwlock.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
|
||||
@@ -1,59 +0,0 @@
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include "rwlock.h"
|
||||
|
||||
#include "bool.h"
|
||||
#include "atomic.h"
|
||||
#include "threads.h"
|
||||
|
||||
|
||||
/* A simple spinlock. Yield the thread while the given integer is set by
|
||||
* another. Could probably be improved... */
|
||||
#define LOCK(l) do { \
|
||||
while(ATOMIC_EXCHANGE(&(l), 1, almemory_order_acq_rel) == true) \
|
||||
althrd_yield(); \
|
||||
} while(0)
|
||||
#define UNLOCK(l) ATOMIC_STORE(&(l), 0, almemory_order_release)
|
||||
|
||||
|
||||
void RWLockInit(RWLock *lock)
|
||||
{
|
||||
InitRef(&lock->read_count, 0);
|
||||
InitRef(&lock->write_count, 0);
|
||||
ATOMIC_INIT(&lock->read_lock, 0);
|
||||
ATOMIC_INIT(&lock->read_entry_lock, 0);
|
||||
ATOMIC_INIT(&lock->write_lock, 0);
|
||||
}
|
||||
|
||||
void ReadLock(RWLock *lock)
|
||||
{
|
||||
LOCK(lock->read_entry_lock);
|
||||
LOCK(lock->read_lock);
|
||||
/* NOTE: ATOMIC_ADD returns the *old* value! */
|
||||
if(ATOMIC_ADD(&lock->read_count, 1, almemory_order_acq_rel) == 0)
|
||||
LOCK(lock->write_lock);
|
||||
UNLOCK(lock->read_lock);
|
||||
UNLOCK(lock->read_entry_lock);
|
||||
}
|
||||
|
||||
void ReadUnlock(RWLock *lock)
|
||||
{
|
||||
/* NOTE: ATOMIC_SUB returns the *old* value! */
|
||||
if(ATOMIC_SUB(&lock->read_count, 1, almemory_order_acq_rel) == 1)
|
||||
UNLOCK(lock->write_lock);
|
||||
}
|
||||
|
||||
void WriteLock(RWLock *lock)
|
||||
{
|
||||
if(ATOMIC_ADD(&lock->write_count, 1, almemory_order_acq_rel) == 0)
|
||||
LOCK(lock->read_lock);
|
||||
LOCK(lock->write_lock);
|
||||
}
|
||||
|
||||
void WriteUnlock(RWLock *lock)
|
||||
{
|
||||
UNLOCK(lock->write_lock);
|
||||
if(ATOMIC_SUB(&lock->write_count, 1, almemory_order_acq_rel) == 1)
|
||||
UNLOCK(lock->read_lock);
|
||||
}
|
||||
@@ -1,32 +0,0 @@
|
||||
#ifndef AL_RWLOCK_H
|
||||
#define AL_RWLOCK_H
|
||||
|
||||
#include "bool.h"
|
||||
#include "atomic.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef struct {
|
||||
RefCount read_count;
|
||||
RefCount write_count;
|
||||
ATOMIC(int) read_lock;
|
||||
ATOMIC(int) read_entry_lock;
|
||||
ATOMIC(int) write_lock;
|
||||
} RWLock;
|
||||
#define RWLOCK_STATIC_INITIALIZE { ATOMIC_INIT_STATIC(0), ATOMIC_INIT_STATIC(0), \
|
||||
ATOMIC_INIT_STATIC(0), ATOMIC_INIT_STATIC(0), \
|
||||
ATOMIC_INIT_STATIC(0) }
|
||||
|
||||
void RWLockInit(RWLock *lock);
|
||||
void ReadLock(RWLock *lock);
|
||||
void ReadUnlock(RWLock *lock);
|
||||
void WriteLock(RWLock *lock);
|
||||
void WriteUnlock(RWLock *lock);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* AL_RWLOCK_H */
|
||||
@@ -29,11 +29,6 @@
|
||||
#include "uintmap.h"
|
||||
|
||||
|
||||
extern inline althrd_t althrd_current(void);
|
||||
extern inline int althrd_equal(althrd_t thr0, althrd_t thr1);
|
||||
extern inline void althrd_yield(void);
|
||||
|
||||
|
||||
#ifndef UNUSED
|
||||
#if defined(__cplusplus)
|
||||
#define UNUSED(x)
|
||||
@@ -62,7 +57,7 @@ extern inline void althrd_yield(void);
|
||||
* referenced by multiple different HANDLEs. This map allows retrieving the
|
||||
* original handle which is needed to join the thread and get its return value.
|
||||
*/
|
||||
static UIntMap ThrdIdHandle = UINTMAP_STATIC_INITIALIZE;
|
||||
static ThrSafeMap<DWORD,HANDLE> ThrdIdHandle{};
|
||||
|
||||
|
||||
void althrd_setname(althrd_t thr, const char *name)
|
||||
@@ -116,7 +111,7 @@ int althrd_create(althrd_t *thr, althrd_start_t func, void *arg)
|
||||
DWORD thrid;
|
||||
HANDLE hdl;
|
||||
|
||||
cntr = malloc(sizeof(*cntr));
|
||||
cntr = static_cast<thread_cntr*>(malloc(sizeof(*cntr)));
|
||||
if(!cntr) return althrd_nomem;
|
||||
|
||||
cntr->func = func;
|
||||
@@ -128,7 +123,7 @@ int althrd_create(althrd_t *thr, althrd_start_t func, void *arg)
|
||||
free(cntr);
|
||||
return althrd_error;
|
||||
}
|
||||
InsertUIntMapEntry(&ThrdIdHandle, thrid, hdl);
|
||||
ThrdIdHandle.InsertEntry(thrid, hdl);
|
||||
|
||||
*thr = thrid;
|
||||
return althrd_success;
|
||||
@@ -136,7 +131,7 @@ int althrd_create(althrd_t *thr, althrd_start_t func, void *arg)
|
||||
|
||||
int althrd_detach(althrd_t thr)
|
||||
{
|
||||
HANDLE hdl = RemoveUIntMapKey(&ThrdIdHandle, thr);
|
||||
HANDLE hdl = ThrdIdHandle.RemoveKey(thr);
|
||||
if(!hdl) return althrd_error;
|
||||
|
||||
CloseHandle(hdl);
|
||||
@@ -147,7 +142,7 @@ int althrd_join(althrd_t thr, int *res)
|
||||
{
|
||||
DWORD code;
|
||||
|
||||
HANDLE hdl = RemoveUIntMapKey(&ThrdIdHandle, thr);
|
||||
HANDLE hdl = ThrdIdHandle.RemoveKey(thr);
|
||||
if(!hdl) return althrd_error;
|
||||
|
||||
WaitForSingleObject(hdl, INFINITE);
|
||||
@@ -215,7 +210,6 @@ int alsem_trywait(alsem_t *sem)
|
||||
|
||||
void althrd_deinit(void)
|
||||
{
|
||||
ResetUIntMap(&ThrdIdHandle);
|
||||
}
|
||||
|
||||
#else
|
||||
@@ -270,7 +264,7 @@ int althrd_create(althrd_t *thr, althrd_start_t func, void *arg)
|
||||
size_t stackmult = 1;
|
||||
int err;
|
||||
|
||||
cntr = malloc(sizeof(*cntr));
|
||||
cntr = static_cast<thread_cntr*>(malloc(sizeof(*cntr)));
|
||||
if(!cntr) return althrd_nomem;
|
||||
|
||||
if(pthread_attr_init(&attr) != 0)
|
||||
@@ -1,182 +0,0 @@
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include "uintmap.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "almalloc.h"
|
||||
|
||||
|
||||
extern inline void LockUIntMapRead(UIntMap *map);
|
||||
extern inline void UnlockUIntMapRead(UIntMap *map);
|
||||
extern inline void LockUIntMapWrite(UIntMap *map);
|
||||
extern inline void UnlockUIntMapWrite(UIntMap *map);
|
||||
|
||||
|
||||
void InitUIntMap(UIntMap *map, ALsizei limit)
|
||||
{
|
||||
map->keys = NULL;
|
||||
map->values = NULL;
|
||||
map->size = 0;
|
||||
map->capacity = 0;
|
||||
map->limit = limit;
|
||||
RWLockInit(&map->lock);
|
||||
}
|
||||
|
||||
void ResetUIntMap(UIntMap *map)
|
||||
{
|
||||
WriteLock(&map->lock);
|
||||
al_free(map->keys);
|
||||
map->keys = NULL;
|
||||
map->values = NULL;
|
||||
map->size = 0;
|
||||
map->capacity = 0;
|
||||
WriteUnlock(&map->lock);
|
||||
}
|
||||
|
||||
ALenum InsertUIntMapEntry(UIntMap *map, ALuint key, ALvoid *value)
|
||||
{
|
||||
ALsizei pos = 0;
|
||||
|
||||
WriteLock(&map->lock);
|
||||
if(map->size > 0)
|
||||
{
|
||||
ALsizei count = map->size;
|
||||
do {
|
||||
ALsizei step = count>>1;
|
||||
ALsizei i = pos+step;
|
||||
if(map->keys[i] >= key)
|
||||
count = step;
|
||||
else
|
||||
{
|
||||
pos = i+1;
|
||||
count -= step+1;
|
||||
}
|
||||
} while(count > 0);
|
||||
}
|
||||
|
||||
if(pos == map->size || map->keys[pos] != key)
|
||||
{
|
||||
if(map->size >= map->limit)
|
||||
{
|
||||
WriteUnlock(&map->lock);
|
||||
return AL_OUT_OF_MEMORY;
|
||||
}
|
||||
|
||||
if(map->size == map->capacity)
|
||||
{
|
||||
ALuint *keys = NULL;
|
||||
ALvoid **values;
|
||||
ALsizei newcap, keylen;
|
||||
|
||||
newcap = (map->capacity ? (map->capacity<<1) : 4);
|
||||
if(map->limit > 0 && newcap > map->limit)
|
||||
newcap = map->limit;
|
||||
if(newcap > map->capacity)
|
||||
{
|
||||
/* Round the memory size for keys up to a multiple of the
|
||||
* pointer size.
|
||||
*/
|
||||
keylen = newcap * sizeof(map->keys[0]);
|
||||
keylen += sizeof(map->values[0]) - 1;
|
||||
keylen -= keylen%sizeof(map->values[0]);
|
||||
|
||||
keys = al_malloc(16, keylen + newcap*sizeof(map->values[0]));
|
||||
}
|
||||
if(!keys)
|
||||
{
|
||||
WriteUnlock(&map->lock);
|
||||
return AL_OUT_OF_MEMORY;
|
||||
}
|
||||
values = (ALvoid**)((ALbyte*)keys + keylen);
|
||||
|
||||
if(map->keys)
|
||||
{
|
||||
memcpy(keys, map->keys, map->size*sizeof(map->keys[0]));
|
||||
memcpy(values, map->values, map->size*sizeof(map->values[0]));
|
||||
}
|
||||
al_free(map->keys);
|
||||
map->keys = keys;
|
||||
map->values = values;
|
||||
map->capacity = newcap;
|
||||
}
|
||||
|
||||
if(pos < map->size)
|
||||
{
|
||||
memmove(&map->keys[pos+1], &map->keys[pos],
|
||||
(map->size-pos)*sizeof(map->keys[0]));
|
||||
memmove(&map->values[pos+1], &map->values[pos],
|
||||
(map->size-pos)*sizeof(map->values[0]));
|
||||
}
|
||||
map->size++;
|
||||
}
|
||||
map->keys[pos] = key;
|
||||
map->values[pos] = value;
|
||||
WriteUnlock(&map->lock);
|
||||
|
||||
return AL_NO_ERROR;
|
||||
}
|
||||
|
||||
ALvoid *RemoveUIntMapKey(UIntMap *map, ALuint key)
|
||||
{
|
||||
ALvoid *ptr = NULL;
|
||||
WriteLock(&map->lock);
|
||||
if(map->size > 0)
|
||||
{
|
||||
ALsizei pos = 0;
|
||||
ALsizei count = map->size;
|
||||
do {
|
||||
ALsizei step = count>>1;
|
||||
ALsizei i = pos+step;
|
||||
if(map->keys[i] >= key)
|
||||
count = step;
|
||||
else
|
||||
{
|
||||
pos = i+1;
|
||||
count -= step+1;
|
||||
}
|
||||
} while(count > 0);
|
||||
if(pos < map->size && map->keys[pos] == key)
|
||||
{
|
||||
ptr = map->values[pos];
|
||||
if(pos < map->size-1)
|
||||
{
|
||||
memmove(&map->keys[pos], &map->keys[pos+1],
|
||||
(map->size-1-pos)*sizeof(map->keys[0]));
|
||||
memmove(&map->values[pos], &map->values[pos+1],
|
||||
(map->size-1-pos)*sizeof(map->values[0]));
|
||||
}
|
||||
map->size--;
|
||||
}
|
||||
}
|
||||
WriteUnlock(&map->lock);
|
||||
return ptr;
|
||||
}
|
||||
|
||||
ALvoid *LookupUIntMapKey(UIntMap *map, ALuint key)
|
||||
{
|
||||
ALvoid *ptr = NULL;
|
||||
ReadLock(&map->lock);
|
||||
if(map->size > 0)
|
||||
{
|
||||
ALsizei pos = 0;
|
||||
ALsizei count = map->size;
|
||||
do {
|
||||
ALsizei step = count>>1;
|
||||
ALsizei i = pos+step;
|
||||
if(map->keys[i] >= key)
|
||||
count = step;
|
||||
else
|
||||
{
|
||||
pos = i+1;
|
||||
count -= step+1;
|
||||
}
|
||||
} while(count > 0);
|
||||
if(pos < map->size && map->keys[pos] == key)
|
||||
ptr = map->values[pos];
|
||||
}
|
||||
ReadUnlock(&map->lock);
|
||||
return ptr;
|
||||
}
|
||||
+23
-29
@@ -1,41 +1,35 @@
|
||||
#ifndef AL_UINTMAP_H
|
||||
#define AL_UINTMAP_H
|
||||
|
||||
#include <limits.h>
|
||||
#include <unordered_map>
|
||||
#include <mutex>
|
||||
|
||||
#include "AL/al.h"
|
||||
#include "rwlock.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
template<typename T0, typename T1>
|
||||
class ThrSafeMap {
|
||||
std::unordered_map<T0, T1> mValues;
|
||||
std::mutex mLock;
|
||||
|
||||
typedef struct UIntMap {
|
||||
ALuint *keys;
|
||||
/* Shares memory with keys. */
|
||||
ALvoid **values;
|
||||
public:
|
||||
void InsertEntry(T0 key, T1 value) noexcept
|
||||
{
|
||||
std::lock_guard<std::mutex> _{mLock};
|
||||
mValues[key] = value;
|
||||
}
|
||||
|
||||
ALsizei size;
|
||||
ALsizei capacity;
|
||||
ALsizei limit;
|
||||
RWLock lock;
|
||||
} UIntMap;
|
||||
#define UINTMAP_STATIC_INITIALIZE_N(_n) { NULL, NULL, 0, 0, (_n), RWLOCK_STATIC_INITIALIZE }
|
||||
#define UINTMAP_STATIC_INITIALIZE UINTMAP_STATIC_INITIALIZE_N(INT_MAX)
|
||||
T1 RemoveKey(T0 key) noexcept
|
||||
{
|
||||
T1 retval{};
|
||||
|
||||
void InitUIntMap(UIntMap *map, ALsizei limit);
|
||||
void ResetUIntMap(UIntMap *map);
|
||||
ALenum InsertUIntMapEntry(UIntMap *map, ALuint key, ALvoid *value);
|
||||
ALvoid *RemoveUIntMapKey(UIntMap *map, ALuint key);
|
||||
ALvoid *LookupUIntMapKey(UIntMap *map, ALuint key);
|
||||
std::lock_guard<std::mutex> _{mLock};
|
||||
auto iter = mValues.find(key);
|
||||
if(iter != mValues.end())
|
||||
retval = iter->second;
|
||||
mValues.erase(iter);
|
||||
|
||||
inline void LockUIntMapRead(UIntMap *map) { ReadLock(&map->lock); }
|
||||
inline void UnlockUIntMapRead(UIntMap *map) { ReadUnlock(&map->lock); }
|
||||
inline void LockUIntMapWrite(UIntMap *map) { WriteLock(&map->lock); }
|
||||
inline void UnlockUIntMapWrite(UIntMap *map) { WriteUnlock(&map->lock); }
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
return retval;
|
||||
}
|
||||
};
|
||||
|
||||
#endif /* AL_UINTMAP_H */
|
||||
|
||||
Reference in New Issue
Block a user