Convert threads.c to C++

Also vastly simplify and remove related code.
This commit is contained in:
Chris Robinson
2018-11-17 05:31:29 -08:00
parent ccdaca80c9
commit 1fae8c16a8
7 changed files with 30 additions and 319 deletions
+1 -4
View File
@@ -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
-1
View File
@@ -7,7 +7,6 @@
#include "inprogext.h"
#include "atomic.h"
#include "rwlock.h"
#ifdef __cplusplus
extern "C" {
-59
View File
@@ -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);
}
-32
View File
@@ -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 */
+6 -12
View File
@@ -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)
-182
View File
@@ -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
View File
@@ -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 */