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