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 2026 51 Degrees Mobile Experts Limited, Davidson House,
4 * Forbury Square, Reading, Berkshire, United Kingdom RG1 3EU.
5 *
6 * This Original Work is licensed under the European Union Public Licence
7 * (EUPL) 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
32
33#ifndef FIFTYONE_DEGREES_THREADING_INCLUDED
34#define FIFTYONE_DEGREES_THREADING_INCLUDED
35
36#ifdef FIFTYONE_DEGREES_IPI_SYMBOLS
37#include "ipiSymbols.h"
38#endif
39
40#include <stdbool.h>
41#include <stdint.h>
42
43#include <stdio.h>
44#include "common.h"
45
54
58#ifdef _MSC_VER
59#define FIFTYONE_DEGREES_THREAD_ROUTINE LPTHREAD_START_ROUTINE
60#else
61typedef void*(*FIFTYONE_DEGREES_THREAD_ROUTINE)(void*);
62#endif
63
64/* Define NDEBUG if needed, to ensure asserts are disabled in release builds */
65#if !defined(DEBUG) && !defined(_DEBUG) && !defined(NDEBUG)
66#define NDEBUG
67#endif
68
69#ifdef _MSC_VER
70#pragma warning (push)
71#pragma warning (disable: 5105)
72#include <windows.h>
73#pragma warning (default: 5105)
74#pragma warning (pop)
75#include <intrin.h>
76#pragma intrinsic (_InterlockedIncrement)
77#pragma intrinsic (_InterlockedDecrement)
78#else
79#include <pthread.h>
80#include <signal.h>
81#endif
82#include <assert.h>
83
87
95#ifdef _MSC_VER
96typedef SRWLOCK fiftyoneDegreesMutex;
97#else
98typedef pthread_mutex_t fiftyoneDegreesMutex;
119#endif
120
125#ifdef _MSC_VER
126typedef HANDLE fiftyoneDegreesSignal;
127#else
128typedef struct fiftyone_degrees_signal_t {
129 volatile bool wait;
130 pthread_cond_t cond;
131 pthread_mutex_t mutex;
133#endif
134
145
156
165
173
177#ifdef _MSC_VER
178#define FIFTYONE_DEGREES_THREAD HANDLE
179#else
180#define FIFTYONE_DEGREES_THREAD pthread_t
181#endif
182
188#define FIFTYONE_DEGREES_SIGNAL_CREATE(s) s = fiftyoneDegreesSignalCreate()
189
194#define FIFTYONE_DEGREES_SIGNAL_CLOSE(s) fiftyoneDegreesSignalClose(s)
195
200#define FIFTYONE_DEGREES_SIGNAL_SET(s) fiftyoneDegreesSignalSet(s)
201
206#define FIFTYONE_DEGREES_SIGNAL_WAIT(s) fiftyoneDegreesSignalWait(s)
207
212#ifdef _MSC_VER
213#define FIFTYONE_DEGREES_MUTEX_CREATE(m) InitializeSRWLock(&m)
214#else
215#define FIFTYONE_DEGREES_MUTEX_CREATE(m) fiftyoneDegreesMutexCreate(&m)
216#endif
217
223#ifdef _MSC_VER
224#define FIFTYONE_DEGREES_MUTEX_CLOSE(m)
225#else
226#define FIFTYONE_DEGREES_MUTEX_CLOSE(m) fiftyoneDegreesMutexClose(&m)
227#endif
228
233#ifdef _MSC_VER
234#define FIFTYONE_DEGREES_MUTEX_LOCK(m) AcquireSRWLockExclusive(m)
235#else
236#define FIFTYONE_DEGREES_MUTEX_LOCK(m) fiftyoneDegreesMutexLock(m)
237#endif
238
243#ifdef _MSC_VER
244#define FIFTYONE_DEGREES_MUTEX_UNLOCK(m) ReleaseSRWLockExclusive(m)
245#else
246#define FIFTYONE_DEGREES_MUTEX_UNLOCK(m) fiftyoneDegreesMutexUnlock(m)
247#endif
248
254#ifdef _MSC_VER
255#define FIFTYONE_DEGREES_MUTEX_VALID(m) (m != NULL)
256#else
257#define FIFTYONE_DEGREES_MUTEX_VALID(m) fiftyoneDegreesMutexValid(m)
258#endif
259
267#ifdef _MSC_VER
268#define FIFTYONE_DEGREES_THREAD_CREATE(t, m, s) t = \
269 (FIFTYONE_DEGREES_THREAD)CreateThread(NULL, 0, m, s, 0, NULL)
270#else
271#define FIFTYONE_DEGREES_THREAD_CREATE(t, m, s) pthread_create(&t, NULL, m, s)
272#endif
273
279#ifdef _MSC_VER
280#define FIFTYONE_DEGREES_THREAD_JOIN(t) WaitForSingleObject(t, INFINITE)
281#else
282#define FIFTYONE_DEGREES_THREAD_JOIN(t) pthread_join(t, NULL)
283#endif
284
289#ifdef _MSC_VER
290#define FIFTYONE_DEGREES_THREAD_CLOSE(t) CloseHandle(t)
291#else
292#define FIFTYONE_DEGREES_THREAD_CLOSE(t)
293#endif
294
298#ifdef _MSC_VER
299#define FIFTYONE_DEGREES_THREAD_EXIT ExitThread(0)
300#else
301#define FIFTYONE_DEGREES_THREAD_EXIT pthread_exit(NULL)
302#endif
303
309#ifdef _MSC_VER
310#define FIFTYONE_DEGREES_INTERLOCK_INC(v) _InterlockedIncrement(v)
311#else
312#define FIFTYONE_DEGREES_INTERLOCK_INC(v) (__atomic_add_fetch(v, 1, __ATOMIC_SEQ_CST))
313#endif
314
320#ifdef _MSC_VER
321#define FIFTYONE_DEGREES_INTERLOCK_DEC(v) _InterlockedDecrement(v)
322#else
323#define FIFTYONE_DEGREES_INTERLOCK_DEC(v) (__atomic_add_fetch(v, -1, __ATOMIC_SEQ_CST))
324#endif
325
334#ifdef _MSC_VER
335#define FIFTYONE_DEGREES_INTERLOCK_EXCHANGE(d,e,c) \
336 InterlockedCompareExchange(&d, e, c)
337#else
338/* __sync is still used here, as __atomic only offers a bool return value.
339This will end up being resolved to __atomic functions anyway, so is still
340supported. */
341#define FIFTYONE_DEGREES_INTERLOCK_EXCHANGE(d,e,c) \
342 __sync_val_compare_and_swap(&d,c,e)
343#endif
344
353#ifdef _MSC_VER
354#define FIFTYONE_DEGREES_INTERLOCK_EXCHANGE_64(d,e,c) \
355 InterlockedCompareExchange64((volatile __int64*)&d, (__int64)e, (__int64)c)
356#else
357#define FIFTYONE_DEGREES_INTERLOCK_EXCHANGE_64(d,e,c) \
358 FIFTYONE_DEGREES_INTERLOCK_EXCHANGE(d,e,c)
359#endif
360
369#ifdef _MSC_VER
370#define FIFTYONE_DEGREES_INTERLOCK_EXCHANGE_PTR(d,e,c) \
371 InterlockedCompareExchangePointer((volatile PVOID*)&d,e,c)
372#else
373#define FIFTYONE_DEGREES_INTERLOCK_EXCHANGE_PTR(d,e,c) \
374 FIFTYONE_DEGREES_INTERLOCK_EXCHANGE(d,e,c)
375#endif
376
408#ifdef _MSC_VER
409#ifdef _WIN64
410typedef struct fiftyone_degrees_interlock_dw_type_t {
411 LONG64 low;
412 LONG64 high;
414#define FIFTYONE_DEGREES_INTERLOCK_EXCHANGE_DW(d,e,c) \
415 InterlockedCompareExchange128(&d.low, e.high, e.low, &c.low)
416#else // _WIN64
417typedef struct fiftyone_degrees_interlock_dw_type_t {
418 LONG64 value;
420#define FIFTYONE_DEGREES_INTERLOCK_EXCHANGE_DW(d,e,c) \
421 InterlockedCompareExchange64(&d.value, e.value, c.value) == c.value
422#endif // _WIN64
423#else // _MSC_VER
424#if (defined(_LP64) || defined(__MINGW64__))
425typedef struct fiftyone_degrees_interlock_dw_type_t {
426 int64_t low;
427 int64_t high;
428} __attribute__((aligned(16),packed)) fiftyoneDegreesInterlockDoubleWidth;
429#else // _LP64
430typedef struct fiftyone_degrees_interlock_dw_type_t {
431 int64_t value;
433#endif //_LP64
434#define FIFTYONE_DEGREES_INTERLOCK_EXCHANGE_DW(d,e,c) \
435 (__atomic_compare_exchange( \
436 (fiftyoneDegreesInterlockDoubleWidth*)&d, \
437 (fiftyoneDegreesInterlockDoubleWidth*)&c, \
438 (fiftyoneDegreesInterlockDoubleWidth*)&e, \
439 false, \
440 __ATOMIC_SEQ_CST, \
441 __ATOMIC_SEQ_CST))
442#endif // _MSC_VER
443
444
445#ifdef _MSC_VER
446#ifdef _WIN64
447#define FIFTYONE_DEGREES_IS_LOCK_FREE IsProcessorFeaturePresent(PF_COMPARE_EXCHANGE128)
448#else
449#define FIFTYONE_DEGREES_IS_LOCK_FREE true
450#endif
451#else
452#define FIFTYONE_DEGREES_IS_LOCK_FREE __atomic_is_lock_free(sizeof(fiftyoneDegreesInterlockDoubleWidth), NULL)
453#endif
454
458
459#endif
pthread_mutex_t fiftyoneDegreesMutex
MUTEX AND THREADING MACROS.
Definition threading.h:98
void fiftyoneDegreesMutexUnlock(fiftyoneDegreesMutex *mutex)
Unlocks the mutex passed to the method.
void fiftyoneDegreesSignalClose(fiftyoneDegreesSignal *signal)
Closes the signal ensuring there is a lock on the signal before destroying the signal.
void fiftyoneDegreesMutexCreate(fiftyoneDegreesMutex *mutex)
Initialises the mutex passed to the method.
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.
void fiftyoneDegreesSignalSet(fiftyoneDegreesSignal *signal)
If the signal has not been destroyed then sends a signal to a waiting thread that the signal has been...
fiftyoneDegreesSignal * fiftyoneDegreesSignalCreate()
Initialises the signal pointer by setting the condition first followed by the mutex if the condition ...
void fiftyoneDegreesMutexClose(fiftyoneDegreesMutex *mutex)
Closes the mutex passed to the method.
void fiftyoneDegreesMutexLock(fiftyoneDegreesMutex *mutex)
Locks the mutex passed to the method.
Double width (64 or 128 depending on the architecture) compare and exchange.
Definition threading.h:430
A signal used to limit the number of items that can be created by the pool.
Definition threading.h:128
pthread_cond_t cond
Condition variable for the signal.
Definition threading.h:130
pthread_mutex_t mutex
Mutex for the signal.
Definition threading.h:131
volatile bool wait
Flag indicating if the thread should wait.
Definition threading.h:129