51Degrees Device Detection C/C++  4.1

A device detection library that is used natively or by 51Degrees products

threading.h

1 /* *********************************************************************
2  * This Original Work is copyright of 51 Degrees Mobile Experts Limited.
3  * Copyright 2019 51 Degrees Mobile Experts Limited, 5 Charlotte Close,
4  * Caversham, Reading, Berkshire, United Kingdom RG4 7BY.
5  *
6  * This Original Work is licensed under the European Union Public Licence (EUPL)
7  * v.1.2 and is subject to its terms as set out below.
8  *
9  * If a copy of the EUPL was not distributed with this file, You can obtain
10  * one at https://opensource.org/licenses/EUPL-1.2.
11  *
12  * The 'Compatible Licences' set out in the Appendix to the EUPL (as may be
13  * amended by the European Commission) shall be deemed incompatible for
14  * the purposes of the Work and the provisions of the compatibility
15  * clause in Article 5 of the EUPL shall not apply.
16  *
17  * If using the Work as, or as part of, a network application, by
18  * including the attribution notice(s) required under Article 5 of the EUPL
19  * in the end user terms of the application under an appropriate heading,
20  * such notice(s) shall fulfill the requirements of that article.
21  * ********************************************************************* */
22 
33 #ifndef FIFTYONE_DEGREES_THREADING_INCLUDED
34 #define FIFTYONE_DEGREES_THREADING_INCLUDED
35 
36 #include <stdbool.h>
37 
38 #ifdef __cplusplus
39 #define EXTERNAL extern "C"
40 #else
41 #define EXTERNAL
42 #endif
43 
52 
56 #ifdef _MSC_VER
57 #define FIFTYONE_DEGREES_THREAD_ROUTINE LPTHREAD_START_ROUTINE
58 #else
59 typedef void*(*FIFTYONE_DEGREES_THREAD_ROUTINE)(void*);
60 #endif
61 
62 /* Define NDEBUG if needed, to ensure asserts are disabled in release builds */
63 #if !defined(DEBUG) && !defined(_DEBUG) && !defined(NDEBUG)
64 #define NDEBUG
65 #endif
66 
67 #ifdef _MSC_VER
68 #include <windows.h>
69 #include <intrin.h>
70 #pragma intrinsic (_InterlockedIncrement)
71 #pragma intrinsic (_InterlockedDecrement)
72 #else
73 #include <pthread.h>
74 #include <signal.h>
75 #endif
76 #include <assert.h>
77 
86 #ifdef _MSC_VER
87 typedef HANDLE fiftyoneDegreesMutex;
88 #else
89 typedef pthread_mutex_t fiftyoneDegreesMutex;
104 EXTERNAL void fiftyoneDegreesMutexLock(fiftyoneDegreesMutex *mutex);
110 #endif
111 
116 #ifdef _MSC_VER
117 typedef HANDLE fiftyoneDegreesSignal;
118 #else
119 typedef struct fiftyone_degrees_signal_t {
120  volatile bool wait;
121  pthread_cond_t cond;
122  pthread_mutex_t mutex;
124 #endif
125 
136 
147 
156 
164 
168 #ifdef _MSC_VER
169 #define FIFTYONE_DEGREES_THREAD HANDLE
170 #else
171 #define FIFTYONE_DEGREES_THREAD pthread_t
172 #endif
173 
179 #define FIFTYONE_DEGREES_SIGNAL_CREATE(s) s = fiftyoneDegreesSignalCreate()
180 
185 #define FIFTYONE_DEGREES_SIGNAL_CLOSE(s) fiftyoneDegreesSignalClose(s)
186 
191 #define FIFTYONE_DEGREES_SIGNAL_SET(s) fiftyoneDegreesSignalSet(s)
192 
197 #define FIFTYONE_DEGREES_SIGNAL_WAIT(s) fiftyoneDegreesSignalWait(s)
198 
203 #ifdef _MSC_VER
204 #define FIFTYONE_DEGREES_MUTEX_CREATE(m) m = CreateMutex(NULL,FALSE,NULL)
205 #else
206 #define FIFTYONE_DEGREES_MUTEX_CREATE(m) fiftyoneDegreesMutexCreate(&m)
207 #endif
208 
213 #ifdef _MSC_VER
214 #define FIFTYONE_DEGREES_MUTEX_CLOSE(m) if (m != NULL) { CloseHandle(m); }
215 #else
216 #define FIFTYONE_DEGREES_MUTEX_CLOSE(m) fiftyoneDegreesMutexClose(&m)
217 #endif
218 
223 #ifdef _MSC_VER
224 #define FIFTYONE_DEGREES_MUTEX_LOCK(m) WaitForSingleObject(*m, INFINITE)
225 #else
226 #define FIFTYONE_DEGREES_MUTEX_LOCK(m) fiftyoneDegreesMutexLock(m)
227 #endif
228 
233 #ifdef _MSC_VER
234 #define FIFTYONE_DEGREES_MUTEX_UNLOCK(m) ReleaseMutex(*m)
235 #else
236 #define FIFTYONE_DEGREES_MUTEX_UNLOCK(m) fiftyoneDegreesMutexUnlock(m)
237 #endif
238 
244 #ifdef _MSC_VER
245 #define FIFTYONE_DEGREES_MUTEX_VALID(m) (*m != NULL)
246 #else
247 #define FIFTYONE_DEGREES_MUTEX_VALID(m) fiftyoneDegreesMutexValid(m)
248 #endif
249 
257 #ifdef _MSC_VER
258 #define FIFTYONE_DEGREES_THREAD_CREATE(t, m, s) t = \
259  (FIFTYONE_DEGREES_THREAD)CreateThread(NULL, 0, m, s, 0, NULL)
260 #else
261 #define FIFTYONE_DEGREES_THREAD_CREATE(t, m, s) pthread_create(&t, NULL, m, s)
262 #endif
263 
269 #ifdef _MSC_VER
270 #define FIFTYONE_DEGREES_THREAD_JOIN(t) WaitForSingleObject(t, INFINITE)
271 #else
272 #define FIFTYONE_DEGREES_THREAD_JOIN(t) pthread_join(t, NULL)
273 #endif
274 
279 #ifdef _MSC_VER
280 #define FIFTYONE_DEGREES_THREAD_CLOSE(t) CloseHandle(t)
281 #else
282 #define FIFTYONE_DEGREES_THREAD_CLOSE(t)
283 #endif
284 
288 #ifdef _MSC_VER
289 #define FIFTYONE_DEGREES_THREAD_EXIT ExitThread(0)
290 #else
291 #define FIFTYONE_DEGREES_THREAD_EXIT pthread_exit(NULL)
292 #endif
293 
299 #ifdef _MSC_VER
300 #define FIFTYONE_DEGREES_INTERLOCK_INC(v) _InterlockedIncrement(v)
301 #else
302 #define FIFTYONE_DEGREES_INTERLOCK_INC(v) (__sync_add_and_fetch(v, 1))
303 #endif
304 
310 #ifdef _MSC_VER
311 #define FIFTYONE_DEGREES_INTERLOCK_DEC(v) _InterlockedDecrement(v)
312 #else
313 #define FIFTYONE_DEGREES_INTERLOCK_DEC(v) (__sync_add_and_fetch(v, -1))
314 #endif
315 
324 #ifdef _MSC_VER
325 #define FIFTYONE_DEGREES_INTERLOCK_EXCHANGE(d,e,c) \
326  InterlockedCompareExchange(&d, e, c)
327 #else
328 #define FIFTYONE_DEGREES_INTERLOCK_EXCHANGE(d,e,c) \
329  __sync_val_compare_and_swap(&d,c,e)
330 #endif
331 
340 #ifdef _MSC_VER
341 #define FIFTYONE_DEGREES_INTERLOCK_EXCHANGE_64(d,e,c) \
342  InterlockedCompareExchange64((volatile __int64*)&d, (__int64)e, (__int64)c)
343 #else
344 #define FIFTYONE_DEGREES_INTERLOCK_EXCHANGE_64(d,e,c) \
345  FIFTYONE_DEGREES_INTERLOCK_EXCHANGE(d,e,c)
346 #endif
347 
356 #ifdef _MSC_VER
357 #ifdef _WIN64
358 #define FIFTYONE_DEGREES_INTERLOCK_EXCHANGE_PTR(d,e,c) \
359  FIFTYONE_DEGREES_INTERLOCK_EXCHANGE_64(d,e,c)
360 #else
361 #define FIFTYONE_DEGREES_INTERLOCK_EXCHANGE_PTR(d,e,c) \
362  FIFTYONE_DEGREES_INTERLOCK_EXCHANGE(d,e,c)
363 #endif
364 #else
365 #define FIFTYONE_DEGREES_INTERLOCK_EXCHANGE_PTR(d,e,c) \
366  FIFTYONE_DEGREES_INTERLOCK_EXCHANGE(d,e,c)
367 #endif
368 
369 #ifndef _MSC_VER
370 
389 static __inline int
391  void* destination,
392  const void* exchange,
393  void* compare)
394 {
395  char result;
396  __asm __volatile("lock cmpxchg16b %0; setz %3"
397  : "+m" (*(void**)destination),
398  "=a" (((void**)compare)[0]),
399  "=d" (((void**)compare)[1]),
400  "=q" (result)
401  : "a" (((void**)compare)[0]),
402  "d" (((void**)compare)[1]),
403  "b" (((const void**)exchange)[0]),
404  "c" (((const void**)exchange)[1])
405  : "memory", "cc");
406  return (result);
407 }
408 #endif
409 
419 #ifdef _MSC_VER
420 #ifdef _WIN64
421 #define FIFTYONE_DEGREES_INTERLOCK_EXCHANGE_PTR_DW(d,e,c) \
422  InterlockedCompareExchange128((__int64*)d, *(((__int64*)&e) + 1), *(((__int64*)&e)), (__int64*)&c)
423 #else
424 #define FIFTYONE_DEGREES_INTERLOCK_EXCHANGE_PTR_DW(d,e,c) \
425  (InterlockedCompareExchange64((__int64*)d, *((__int64*)&e), *(__int64*)&c) != *((__int64*)d))
426 #endif
427 #else
428 #define FIFTYONE_DEGREES_INTERLOCK_EXCHANGE_PTR_DW(d,e,c) \
429  (sizeof(void*) == 8 ? \
430  __fod_sync_bool_compare_and_swap_16((void*)d, (void*)&e, (void*)&c) : \
431  __sync_bool_compare_and_swap((long*)d, *((long*)&c), *((long*)&e)))
432 #endif
433 
438 #endif
void fiftyoneDegreesMutexCreate(fiftyoneDegreesMutex *mutex)
Initialises the mutex passed to the method.
void fiftyoneDegreesMutexUnlock(fiftyoneDegreesMutex *mutex)
Unlocks the mutex passed to the method.
pthread_mutex_t mutex
Mutex for the signal.
Definition: threading.h:122
void fiftyoneDegreesMutexLock(fiftyoneDegreesMutex *mutex)
Locks the mutex passed to the method.
fiftyoneDegreesSignal * fiftyoneDegreesSignalCreate()
Initialises the signal pointer by setting the condition first followed by the mutex if the condition ...
pthread_mutex_t fiftyoneDegreesMutex
MUTEX AND THREADING MACROS.
Definition: threading.h:89
void fiftyoneDegreesMutexClose(fiftyoneDegreesMutex *mutex)
Closes the mutex passed to the method.
pthread_cond_t cond
Condition variable for the signal.
Definition: threading.h:121
A signal used to limit the number of items that can be created by the pool.
Definition: threading.h:119
bool fiftyoneDegreesThreadingGetIsThreadSafe()
Determines if the methods that should be thread safe have been compiled so they are thread safe.
void fiftyoneDegreesSignalWait(fiftyoneDegreesSignal *signal)
Wait for a signal to be set.
static __inline int __fod_sync_bool_compare_and_swap_16(void *destination, const void *exchange, void *compare)
Implements the __sync_bool_compare_and_swap_16 function which is often not implemtned by the compiler...
Definition: threading.h:390
void fiftyoneDegreesSignalClose(fiftyoneDegreesSignal *signal)
Closes the signal ensuring there is a lock on the signal before destroying the signal.
volatile bool wait
Flag indicating if the thread should wait.
Definition: threading.h:120
void fiftyoneDegreesSignalSet(fiftyoneDegreesSignal *signal)
If the signal has not been destroyed then sends a signal to a waiting thread that the signal has been...