aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChris Robinson <[email protected]>2014-04-16 05:19:34 -0700
committerChris Robinson <[email protected]>2014-04-16 05:19:34 -0700
commit18ab9cbbdd4b8db8e5cd9ea6155efafdb79fcad0 (patch)
tree236179c2cc0c0933946416a04a224e81a3eedc1f
parent29cb5058c0b05cca8ebeb40d84aba8a8d2e11075 (diff)
Implement a C11-like thread wrapper and use it in mmdevapi and pulseaudio
-rw-r--r--Alc/backends/mmdevapi.c16
-rw-r--r--Alc/backends/pulseaudio.c17
-rw-r--r--Alc/helpers.c169
-rw-r--r--OpenAL32/Include/threads.h82
4 files changed, 250 insertions, 34 deletions
diff --git a/Alc/backends/mmdevapi.c b/Alc/backends/mmdevapi.c
index b713e831..75d80749 100644
--- a/Alc/backends/mmdevapi.c
+++ b/Alc/backends/mmdevapi.c
@@ -72,7 +72,7 @@ typedef struct {
volatile UINT32 Padding;
volatile int killNow;
- althread_t thread;
+ althrd_t thread;
} MMDevApiData;
@@ -212,7 +212,7 @@ static DevMap *ProbeDevices(IMMDeviceEnumerator *devenum, EDataFlow flowdir, ALu
}
-FORCE_ALIGN static ALuint MMDevApiProc(ALvoid *ptr)
+FORCE_ALIGN static int MMDevApiProc(void *ptr)
{
ALCdevice *device = ptr;
MMDevApiData *data = device->ExtraData;
@@ -692,7 +692,8 @@ static DWORD CALLBACK MMDevApiMsgProc(void *ptr)
if(SUCCEEDED(hr))
{
data->render = ptr;
- if(!StartThread(&data->thread, MMDevApiProc, device))
+ data->killNow = 0;
+ if(althrd_create(&data->thread, MMDevApiProc, device) != althrd_success)
{
if(data->render)
IAudioRenderClient_Release(data->render);
@@ -712,13 +713,12 @@ static DWORD CALLBACK MMDevApiMsgProc(void *ptr)
device = (ALCdevice*)msg.lParam;
data = device->ExtraData;
- if(data->thread)
+ if(data->render)
{
- data->killNow = 1;
- StopThread(data->thread);
- data->thread = NULL;
+ int res;
- data->killNow = 0;
+ data->killNow = 1;
+ althrd_join(data->thread, &res);
IAudioRenderClient_Release(data->render);
data->render = NULL;
diff --git a/Alc/backends/pulseaudio.c b/Alc/backends/pulseaudio.c
index bb371453..6b7b00a3 100644
--- a/Alc/backends/pulseaudio.c
+++ b/Alc/backends/pulseaudio.c
@@ -479,7 +479,7 @@ typedef struct ALCpulsePlayback {
pa_context *context;
volatile ALboolean killNow;
- althread_t thread;
+ althrd_t thread;
} ALCpulsePlayback;
DECLARE_ALCBACKEND_VTABLE(ALCpulsePlayback);
@@ -496,7 +496,7 @@ static pa_stream *ALCpulsePlayback_connectStream(const char *device_name, pa_thr
pa_context *context, pa_stream_flags_t flags,
pa_buffer_attr *attr, pa_sample_spec *spec,
pa_channel_map *chanmap);
-static ALuint ALCpulsePlayback_mixerProc(ALvoid *ptr);
+static int ALCpulsePlayback_mixerProc(void *ptr);
static void ALCpulsePlayback_Construct(ALCpulsePlayback *self, ALCdevice *device);
static DECLARE_FORWARD(ALCpulsePlayback, ALCbackend, void, Destruct)
@@ -751,7 +751,7 @@ static pa_stream *ALCpulsePlayback_connectStream(const char *device_name,
}
-static ALuint ALCpulsePlayback_mixerProc(ALvoid *ptr)
+static int ALCpulsePlayback_mixerProc(void *ptr)
{
ALCpulsePlayback *self = ptr;
ALCdevice *device = STATIC_CAST(ALCbackend,self)->mDevice;
@@ -1051,7 +1051,8 @@ static ALCboolean ALCpulsePlayback_reset(ALCpulsePlayback *self)
static ALCboolean ALCpulsePlayback_start(ALCpulsePlayback *self)
{
- if(!StartThread(&self->thread, ALCpulsePlayback_mixerProc, self))
+ self->killNow = AL_FALSE;
+ if(althrd_create(&self->thread, ALCpulsePlayback_mixerProc, self) != althrd_success)
return ALC_FALSE;
return ALC_TRUE;
}
@@ -1059,17 +1060,13 @@ static ALCboolean ALCpulsePlayback_start(ALCpulsePlayback *self)
static void ALCpulsePlayback_stop(ALCpulsePlayback *self)
{
pa_operation *o;
+ int res;
if(!self->stream)
return;
self->killNow = AL_TRUE;
- if(self->thread)
- {
- StopThread(self->thread);
- self->thread = NULL;
- }
- self->killNow = AL_FALSE;
+ althrd_join(self->thread, &res);
pa_threaded_mainloop_lock(self->loop);
diff --git a/Alc/helpers.c b/Alc/helpers.c
index dc8eefaf..7e6b59a5 100644
--- a/Alc/helpers.c
+++ b/Alc/helpers.c
@@ -309,11 +309,88 @@ void RestoreFPUMode(const FPUCtl *ctl)
}
+extern inline int althrd_equal(althrd_t thr0, althrd_t thr1);
+extern inline void althrd_exit(int res);
+extern inline void althrd_yield(void);
+
extern inline int almtx_lock(almtx_t *mtx);
extern inline int almtx_unlock(almtx_t *mtx);
extern inline int almtx_trylock(almtx_t *mtx);
#ifdef _WIN32
+
+#define THREAD_STACK_SIZE (1*1024*1024) /* 1MB */
+
+typedef struct thread_cntr {
+ althrd_start_t func;
+ void *arg;
+} thread_cntr;
+
+static DWORD WINAPI thread_starter(void *arg)
+{
+ thread_cntr cntr;
+ memcpy(&cntr, arg, sizeof(cntr));
+ free(arg);
+
+ return (DWORD)((*cntr.func)(cntr.arg));
+}
+
+
+int althrd_create(althrd_t *thr, althrd_start_t func, void *arg)
+{
+ thread_cntr *cntr;
+ DWORD dummy;
+ HANDLE hdl;
+
+ cntr = malloc(sizeof(*cntr));
+ if(!cntr) return althrd_nomem;
+
+ cntr->func = func;
+ cntr->arg = arg;
+
+ hdl = CreateThread(NULL, THREAD_STACK_SIZE, thread_starter, cntr, 0, &dummy);
+ if(!hdl)
+ {
+ free(cntr);
+ return althrd_error;
+ }
+
+ *thr = hdl;
+ return althrd_success;
+}
+
+int althrd_detach(althrd_t thr)
+{
+ if(!thr) return althrd_error;
+ CloseHandle(thr);
+
+ return althrd_success;
+}
+
+int althrd_join(althrd_t thr, int *res)
+{
+ DWORD code;
+
+ if(!thr) return althrd_error;
+
+ WaitForSingleObject(thr, INFINITE);
+ GetExitCodeThread(thr, &code);
+ CloseHandle(thr);
+
+ *res = (int)code;
+ return althrd_success;
+}
+
+int althrd_sleep(const struct timespec *ts, struct timespec* UNUSED(rem))
+{
+ DWORD msec;
+ msec = ts->tv_sec * 1000;
+ msec += (ts->tv_nsec+999999) / 1000000;
+ Sleep(msec);
+ return 0;
+}
+
+
int almtx_init(almtx_t *mtx, int type)
{
if(!mtx) return althrd_error;
@@ -329,16 +406,16 @@ void almtx_destroy(almtx_t *mtx)
DeleteCriticalSection(mtx);
}
-int almtx_timedlock(almtx_t *mtx, const alxtime *xt)
+int almtx_timedlock(almtx_t *mtx, const struct timespec *ts)
{
DWORD expire;
int ret;
- if(!mtx || !xt)
+ if(!mtx || !ts)
return althrd_error;
- expire = xt->sec * 1000;
- expire += (xt->nsec+999999) / 1000000;
+ expire = ts->tv_sec * 1000;
+ expire += (ts->tv_nsec+999999) / 1000000;
expire += timeGetTime();
while((ret=almtx_trylock(mtx)) == althrd_busy)
@@ -465,6 +542,80 @@ FILE *al_fopen(const char *fname, const char *mode)
#include <sys/time.h>
+extern inline althrd_t althrd_current(void);
+extern inline int althrd_sleep(const struct timespec *ts, struct timespec *rem);
+
+
+#define THREAD_STACK_SIZE (1*1024*1024) /* 1MB */
+
+typedef struct thread_cntr {
+ althrd_start_t func;
+ void *arg;
+} thread_cntr;
+
+static void *thread_starter(void *arg)
+{
+ thread_cntr cntr;
+ memcpy(&cntr, arg, sizeof(cntr));
+ free(arg);
+
+ return (void*)(intptr_t)((*cntr.func)(cntr.arg));
+}
+
+
+int althrd_create(althrd_t *thr, althrd_start_t func, void *arg)
+{
+ thread_cntr *cntr;
+ pthread_attr_t attr;
+
+ cntr = malloc(sizeof(*cntr));
+ if(!cntr) return althrd_nomem;
+
+ if(pthread_attr_init(&attr) != 0)
+ {
+ free(cntr);
+ return althrd_error;
+ }
+ if(pthread_attr_setstacksize(&attr, THREAD_STACK_SIZE) != 0)
+ {
+ pthread_attr_destroy(&attr);
+ free(cntr);
+ return althrd_error;
+ }
+
+ cntr->func = func;
+ cntr->arg = arg;
+ if(pthread_create(thr, &attr, thread_starter, cntr) != 0)
+ {
+ pthread_attr_destroy(&attr);
+ free(cntr);
+ return althrd_error;
+ }
+ pthread_attr_destroy(&attr);
+
+ return althrd_success;
+}
+
+int althrd_detach(althrd_t thr)
+{
+ if(pthread_detach(thr) != 0)
+ return althrd_error;
+ return althrd_success;
+}
+
+int althrd_join(althrd_t thr, int *res)
+{
+ void *code;
+
+ if(!res) return althrd_error;
+
+ if(pthread_join(thr, &code) != 0)
+ return althrd_error;
+ *res = (int)(intptr_t)code;
+ return althrd_success;
+}
+
+
int almtx_init(almtx_t *mtx, int type)
{
int ret;
@@ -513,16 +664,12 @@ void almtx_destroy(almtx_t *mtx)
pthread_mutex_destroy(mtx);
}
-int almtx_timedlock(almtx_t *mtx, const alxtime *xt)
+int almtx_timedlock(almtx_t *mtx, const struct timespec *ts)
{
- struct timespec ts;
-
- if(!mtx || !xt)
+ if(!mtx || !ts)
return althrd_error;
- ts.tv_sec = xt->sec;
- ts.tv_nsec = xt->nsec;
- if(pthread_mutex_timedlock(mtx, &ts) != 0)
+ if(pthread_mutex_timedlock(mtx, ts) != 0)
return althrd_busy;
return althrd_success;
}
diff --git a/OpenAL32/Include/threads.h b/OpenAL32/Include/threads.h
index 03589d15..8f564cd1 100644
--- a/OpenAL32/Include/threads.h
+++ b/OpenAL32/Include/threads.h
@@ -1,6 +1,8 @@
#ifndef AL_THREADS_H
#define AL_THREADS_H
+#include <time.h>
+
#include "alMain.h"
struct althread_info;
@@ -28,18 +30,55 @@ enum {
almtx_errorcheck = 8
};
-typedef struct alxtime {
- time_t sec;
- long nsec;
-} alxtime;
+
+typedef int (*althrd_start_t)(void*);
#ifdef _WIN32
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
+typedef HANDLE althrd_t;
typedef CRITICAL_SECTION almtx_t;
+#ifndef __MINGW32__
+struct timespec {
+ time_t tv_sec;
+ long tv_nsec;
+};
+#endif
+
+
+int althrd_sleep(const struct timespec *ts, struct timespec *rem);
+
+
+#if 0
+inline althrd_t althrd_current(void)
+{
+ /* This is wrong. GetCurrentThread() returns a psuedo-handle of -1 which
+ * various functions will interpret as the calling thread. There is no
+ * apparent way to retrieve the same handle that was returned by
+ * CreateThread. */
+ return GetCurrentThread();
+}
+#endif
+
+inline int althrd_equal(althrd_t thr0, althrd_t thr1)
+{
+ return GetThreadId(thr0) == GetThreadId(thr1);
+}
+
+inline void althrd_exit(int res)
+{
+ ExitThread(res);
+}
+
+inline void althrd_yield(void)
+{
+ SwitchToThread();
+}
+
+
inline int almtx_lock(almtx_t *mtx)
{
if(!mtx) return althrd_error;
@@ -67,8 +106,36 @@ inline int almtx_trylock(almtx_t *mtx)
#include <pthread.h>
+typedef pthread_t althrd_t;
typedef pthread_mutex_t almtx_t;
+
+inline althrd_t althrd_current(void)
+{
+ return pthread_self();
+}
+
+inline int althrd_equal(althrd_t thr0, althrd_t thr1)
+{
+ return pthread_equal(thr0, thr1);
+}
+
+inline void althrd_exit(int res)
+{
+ pthread_exit((void*)(intptr_t)res);
+}
+
+inline void althrd_yield(void)
+{
+ sched_yield();
+}
+
+inline int althrd_sleep(const struct timespec *ts, struct timespec *rem)
+{
+ return nanosleep(ts, rem);
+}
+
+
inline int almtx_lock(almtx_t *mtx)
{
if(!mtx) return althrd_error;
@@ -93,8 +160,13 @@ inline int almtx_trylock(almtx_t *mtx)
#endif
+
+int althrd_create(althrd_t *thr, althrd_start_t func, void *arg);
+int althrd_detach(althrd_t thr);
+int althrd_join(althrd_t thr, int *res);
+
int almtx_init(almtx_t *mtx, int type);
void almtx_destroy(almtx_t *mtx);
-int almtx_timedlock(almtx_t *mtx, const alxtime *xt);
+int almtx_timedlock(almtx_t *mtx, const struct timespec *ts);
#endif /* AL_THREADS_H */