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
78#elif _WIN32
79#define _WIN32_WINNT 0x0600
80#include <windows.h>
81#define THREAD_ENTRY DWORD WINAPI
82typedef THREAD_ENTRY ThreadEntry(LPVOID);
83
84typedef HANDLE Thread;
85typedef CRITICAL_SECTION Mutex;
86typedef CONDITION_VARIABLE Condition;
87
88static inline int MutexInit(Mutex* mutex) {
89 InitializeCriticalSection(mutex);
90 return GetLastError();
91}
92
93static inline int MutexDeinit(Mutex* mutex) {
94 DeleteCriticalSection(mutex);
95 return GetLastError();
96}
97
98static inline int MutexLock(Mutex* mutex) {
99 EnterCriticalSection(mutex);
100 return GetLastError();
101}
102
103static inline int MutexUnlock(Mutex* mutex) {
104 LeaveCriticalSection(mutex);
105 return GetLastError();
106}
107
108static inline int ConditionInit(Condition* cond) {
109 InitializeConditionVariable(cond);
110 return GetLastError();
111}
112
113static inline int ConditionDeinit(Condition* cond) {
114 // This is a no-op on Windows
115 UNUSED(cond);
116 return 0;
117}
118
119static inline int ConditionWait(Condition* cond, Mutex* mutex) {
120 SleepConditionVariableCS(cond, mutex, INFINITE);
121 return GetLastError();
122}
123
124static inline int ConditionWaitTimed(Condition* cond, Mutex* mutex, int32_t timeoutMs) {
125 SleepConditionVariableCS(cond, mutex, timeoutMs);
126 return GetLastError();
127}
128
129static inline int ConditionWake(Condition* cond) {
130 WakeAllConditionVariable(cond);
131 return GetLastError();
132}
133
134static inline int ThreadCreate(Thread* thread, ThreadEntry entry, void* context) {
135 *thread = CreateThread(NULL, 0, entry, context, 0, 0);
136 return GetLastError();
137}
138
139static inline int ThreadJoin(Thread thread) {
140 DWORD error = WaitForSingleObject(thread, INFINITE);
141 if (error == WAIT_FAILED) {
142 return GetLastError();
143 }
144 return 0;
145}
146#else
147#define DISABLE_THREADING
148#endif
149#endif
150#ifdef DISABLE_THREADING
151typedef void* Thread;
152typedef void* Mutex;
153typedef void* Condition;
154
155static inline int MutexInit(Mutex* mutex) {
156 UNUSED(mutex);
157 return 0;
158}
159
160static inline int MutexDeinit(Mutex* mutex) {
161 UNUSED(mutex);
162 return 0;
163}
164
165static inline int MutexLock(Mutex* mutex) {
166 UNUSED(mutex);
167 return 0;
168}
169
170static inline int MutexUnlock(Mutex* mutex) {
171 UNUSED(mutex);
172 return 0;
173}
174
175static inline int ConditionInit(Condition* cond) {
176 UNUSED(cond);
177 return 0;
178}
179
180static inline int ConditionDeinit(Condition* cond) {
181 UNUSED(cond);
182 return 0;
183}
184
185static inline int ConditionWait(Condition* cond, Mutex* mutex) {
186 UNUSED(cond);
187 UNUSED(mutex);
188 return 0;
189}
190
191static inline int ConditionWaitTimed(Condition* cond, Mutex* mutex, int32_t timeoutMs) {
192 UNUSED(cond);
193 UNUSED(mutex);
194 UNUSED(timeoutMs);
195 return 0;
196}
197
198static inline int ConditionWake(Condition* cond) {
199 UNUSED(cond);
200 return 0;
201}
202#endif
203
204#endif