all repos — mgba @ 4469a9a05f4be9a4c46f36de66398eb61f901c6e

mGBA Game Boy Advance Emulator

src/util/threading.h (view raw)

  1/* Copyright (c) 2013-2014 Jeffrey Pfau
  2 *
  3 * This Source Code Form is subject to the terms of the Mozilla Public
  4 * License, v. 2.0. If a copy of the MPL was not distributed with this
  5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
  6#ifndef THREADING_H
  7#define THREADING_H
  8
  9#include "util/common.h"
 10
 11#ifndef DISABLE_THREADING
 12#ifdef USE_PTHREADS
 13#include <pthread.h>
 14#include <sys/time.h>
 15
 16#define THREAD_ENTRY void*
 17typedef THREAD_ENTRY (*ThreadEntry)(void*);
 18
 19typedef pthread_t Thread;
 20typedef pthread_mutex_t Mutex;
 21typedef pthread_cond_t Condition;
 22
 23static inline int MutexInit(Mutex* mutex) {
 24	return pthread_mutex_init(mutex, 0);
 25}
 26
 27static inline int MutexDeinit(Mutex* mutex) {
 28	return pthread_mutex_destroy(mutex);
 29}
 30
 31static inline int MutexLock(Mutex* mutex) {
 32	return pthread_mutex_lock(mutex);
 33}
 34
 35static inline int MutexUnlock(Mutex* mutex) {
 36	return pthread_mutex_unlock(mutex);
 37}
 38
 39static inline int ConditionInit(Condition* cond) {
 40	return pthread_cond_init(cond, 0);
 41}
 42
 43static inline int ConditionDeinit(Condition* cond) {
 44	return pthread_cond_destroy(cond);
 45}
 46
 47static inline int ConditionWait(Condition* cond, Mutex* mutex) {
 48	return pthread_cond_wait(cond, mutex);
 49}
 50
 51static inline int ConditionWaitTimed(Condition* cond, Mutex* mutex, int32_t timeoutMs) {
 52	struct timespec ts;
 53	struct timeval tv;
 54
 55	gettimeofday(&tv, 0);
 56	ts.tv_sec = tv.tv_sec;
 57	ts.tv_nsec = (tv.tv_usec + timeoutMs * 1000L) * 1000L;
 58	if (ts.tv_nsec >= 1000000000L) {
 59		ts.tv_nsec -= 1000000000L;
 60		++ts.tv_sec;
 61	}
 62
 63	return pthread_cond_timedwait(cond, mutex, &ts);
 64}
 65
 66static inline int ConditionWake(Condition* cond) {
 67	return pthread_cond_broadcast(cond);
 68}
 69
 70static inline int ThreadCreate(Thread* thread, ThreadEntry entry, void* context) {
 71	return pthread_create(thread, 0, entry, context);
 72}
 73
 74static inline int ThreadJoin(Thread thread) {
 75	return pthread_join(thread, 0);
 76}
 77
 78static inline int ThreadSetName(const char* name) {
 79#ifdef __APPLE__
 80	return pthread_setname_np(name);
 81#elif defined(__FreeBSD__)
 82	return pthread_set_name_np(pthread_self(), name);
 83#else
 84	return pthread_setname_np(pthread_self(), name);
 85#endif
 86}
 87
 88#elif _WIN32
 89#define _WIN32_WINNT 0x0600
 90#include <windows.h>
 91#define THREAD_ENTRY DWORD WINAPI
 92typedef THREAD_ENTRY ThreadEntry(LPVOID);
 93
 94typedef HANDLE Thread;
 95typedef CRITICAL_SECTION Mutex;
 96typedef CONDITION_VARIABLE Condition;
 97
 98static inline int MutexInit(Mutex* mutex) {
 99	InitializeCriticalSection(mutex);
100	return GetLastError();
101}
102
103static inline int MutexDeinit(Mutex* mutex) {
104	DeleteCriticalSection(mutex);
105	return GetLastError();
106}
107
108static inline int MutexLock(Mutex* mutex) {
109	EnterCriticalSection(mutex);
110	return GetLastError();
111}
112
113static inline int MutexUnlock(Mutex* mutex) {
114	LeaveCriticalSection(mutex);
115	return GetLastError();
116}
117
118static inline int ConditionInit(Condition* cond) {
119	InitializeConditionVariable(cond);
120	return GetLastError();
121}
122
123static inline int ConditionDeinit(Condition* cond) {
124	// This is a no-op on Windows
125	UNUSED(cond);
126	return 0;
127}
128
129static inline int ConditionWait(Condition* cond, Mutex* mutex) {
130	SleepConditionVariableCS(cond, mutex, INFINITE);
131	return GetLastError();
132}
133
134static inline int ConditionWaitTimed(Condition* cond, Mutex* mutex, int32_t timeoutMs) {
135	SleepConditionVariableCS(cond, mutex, timeoutMs);
136	return GetLastError();
137}
138
139static inline int ConditionWake(Condition* cond) {
140	WakeAllConditionVariable(cond);
141	return GetLastError();
142}
143
144static inline int ThreadCreate(Thread* thread, ThreadEntry entry, void* context) {
145	*thread = CreateThread(NULL, 0, entry, context, 0, 0);
146	return GetLastError();
147}
148
149static inline int ThreadJoin(Thread thread) {
150	DWORD error = WaitForSingleObject(thread, INFINITE);
151	if (error == WAIT_FAILED) {
152		return GetLastError();
153	}
154	return 0;
155}
156
157static inline int ThreadSetName(const char* name) {
158	return -1;
159}
160#else
161#define DISABLE_THREADING
162#endif
163#endif
164#ifdef DISABLE_THREADING
165typedef void* Thread;
166typedef void* Mutex;
167typedef void* Condition;
168
169static inline int MutexInit(Mutex* mutex) {
170	UNUSED(mutex);
171	return 0;
172}
173
174static inline int MutexDeinit(Mutex* mutex) {
175	UNUSED(mutex);
176	return 0;
177}
178
179static inline int MutexLock(Mutex* mutex) {
180	UNUSED(mutex);
181	return 0;
182}
183
184static inline int MutexUnlock(Mutex* mutex) {
185	UNUSED(mutex);
186	return 0;
187}
188
189static inline int ConditionInit(Condition* cond) {
190	UNUSED(cond);
191	return 0;
192}
193
194static inline int ConditionDeinit(Condition* cond) {
195	UNUSED(cond);
196	return 0;
197}
198
199static inline int ConditionWait(Condition* cond, Mutex* mutex) {
200	UNUSED(cond);
201	UNUSED(mutex);
202	return 0;
203}
204
205static inline int ConditionWaitTimed(Condition* cond, Mutex* mutex, int32_t timeoutMs) {
206	UNUSED(cond);
207	UNUSED(mutex);
208	UNUSED(timeoutMs);
209	return 0;
210}
211
212static inline int ConditionWake(Condition* cond) {
213	UNUSED(cond);
214	return 0;
215}
216#endif
217
218#endif