40#ifndef GEOGRAM_BASIC_THREAD_SYNC
41#define GEOGRAM_BASIC_THREAD_SYNC
51# define GEO_USE_DEFAULT_SPINLOCK_ARRAY
52# include <AvailabilityMacros.h>
53# if defined(MAC_OS_X_VERSION_10_12) && MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_12
54# define GEO_APPLE_HAS_UNFAIR_LOCK 1
57# if defined(__IPHONE_OS_VERSION_MIN_REQUIRED) && __IPHONE_OS_VERSION_MIN_REQUIRED >= __IPHONE_10_0
58# define GEO_APPLE_HAS_UNFAIR_LOCK 1
63#ifdef geo_debug_assert
64#define geo_thread_sync_assert(x) geo_debug_assert(x)
66#define geo_thread_sync_assert(x)
78#if defined(GEO_OS_RASPBERRY)
84# define GEOGRAM_SPINLOCK_INIT 0
89 inline void acquire_spinlock(
spinlock& x) {
97 inline void release_spinlock(
spinlock& x) {
98 unlock_mutex_arm32(&x);
101#elif defined(GEO_OS_ANDROID)
107# define GEOGRAM_SPINLOCK_INIT 0
112 inline void acquire_spinlock(
spinlock& x) {
113 lock_mutex_android(&x);
120 inline void release_spinlock(
spinlock& x) {
121 unlock_mutex_android(&x);
124#elif defined(GEO_OS_LINUX) || defined(GEO_COMPILER_MINGW)
130# define GEOGRAM_SPINLOCK_INIT 0
135 inline void acquire_spinlock(
volatile spinlock& x) {
136 while(__sync_lock_test_and_set(&x, 1) == 1) {
147 inline void release_spinlock(
volatile spinlock& x) {
155 __sync_lock_release(&x);
158#elif defined(GEO_OS_APPLE)
160#if defined(GEO_APPLE_HAS_UNFAIR_LOCK)
165# define GEOGRAM_SPINLOCK_INIT OS_UNFAIR_LOCK_INIT
168 inline void acquire_spinlock (
spinlock & s) { os_unfair_lock_lock(&s); }
169 inline void release_spinlock (
spinlock & s) { os_unfair_lock_unlock(&s); }
175# define GEOGRAM_SPINLOCK_INIT OS_SPINLOCK_INIT
176 inline void acquire_spinlock(
volatile spinlock& x) {
180 inline void release_spinlock(
volatile spinlock& x) {
181 OSSpinLockUnlock(&x);
185#elif defined(GEO_OS_WINDOWS) && !defined(GEO_COMPILER_MINGW)
191# define GEOGRAM_SPINLOCK_INIT 0
192 inline void acquire_spinlock(
volatile spinlock& x) {
193 while(_InterlockedCompareExchange16(&x, 1, 0) == 1) {
206 inline void release_spinlock(
volatile spinlock& x) {
213#if defined(GEO_USE_DEFAULT_SPINLOCK_ARRAY)
234 class SpinLockArray {
256 spinlocks_.assign(size_in, GEOGRAM_SPINLOCK_INIT);
270 return index_t(spinlocks_.size());
280 geo_thread_sync_assert(i <
size());
281 GEO::Process::acquire_spinlock(spinlocks_[i]);
290 geo_thread_sync_assert(i <
size());
291 GEO::Process::release_spinlock(spinlocks_[i]);
295 std::vector<spinlock> spinlocks_;
298#elif defined(GEO_OS_RASPBERRY)
308 class SpinLockArray {
336 if(size_ != size_in) {
338 index_t nb_words = (size_ >> 5) + 1;
339 spinlocks_.assign(nb_words, 0);
364 geo_thread_sync_assert(i <
size());
368 while((atomic_bitset_arm32(&spinlocks_[w], b)) != 0) {
373 wait_for_event_arm32();
375 memory_barrier_arm32();
384 geo_thread_sync_assert(i <
size());
385 memory_barrier_android();
388 atomic_bitreset_arm32(&spinlocks_[w], b);
396 std::vector<word_t> spinlocks_;
400#elif defined(GEO_OS_ANDROID)
410 class SpinLockArray {
438 if(size_ != size_in) {
440 index_t nb_words = (size_ >> 5) + 1;
441 spinlocks_.assign(nb_words, 0);
466 geo_thread_sync_assert(i <
size());
470 while((atomic_bitset_android(&spinlocks_[w], b)) != 0) {
475 wait_for_event_android();
477 memory_barrier_android();
486 geo_thread_sync_assert(i <
size());
487 memory_barrier_android();
490 atomic_bitreset_android(&spinlocks_[w], b);
494 send_event_android();
498 std::vector<word_t> spinlocks_;
502#elif defined(GEO_OS_LINUX)
541 if(size_ != size_in) {
543 index_t nb_words = (size_ >> 5) + 1;
544 spinlocks_.assign(nb_words, 0);
569 geo_thread_sync_assert(i <
size());
586 geo_thread_sync_assert(i <
size());
595 std::vector<word_t> spinlocks_;
599#elif defined(GEO_OS_WINDOWS)
609 class SpinLockArray {
640 if(size_ != size_in) {
642 index_t nb_words = (size_ >> 5) + 1;
643 spinlocks_.assign(nb_words, 0);
668 geo_thread_sync_assert(i <
size());
671 while(_interlockedbittestandset((
long *)(&spinlocks_[w]),
long(b))) {
690 geo_thread_sync_assert(i <
size());
698 _interlockedbittestandreset((
long*)(&spinlocks_[w]),
long(b));
702 std::vector<word_t> spinlocks_;
708#error Found no implementation of SpinLockArray
719 typedef CRITICAL_SECTION pthread_mutex_t;
720 typedef unsigned int pthread_mutexattr_t;
722 inline int pthread_mutex_lock(pthread_mutex_t *m) {
723 EnterCriticalSection(m);
727 inline int pthread_mutex_unlock(pthread_mutex_t *m) {
728 LeaveCriticalSection(m);
732 inline int pthread_mutex_trylock(pthread_mutex_t *m) {
733 return TryEnterCriticalSection(m) ? 0 : EBUSY;
736 inline int pthread_mutex_init(pthread_mutex_t *m, pthread_mutexattr_t *a) {
738 InitializeCriticalSection(m);
742 inline int pthread_mutex_destroy(pthread_mutex_t *m) {
743 DeleteCriticalSection(m);
750 typedef CONDITION_VARIABLE pthread_cond_t;
751 typedef unsigned int pthread_condattr_t;
753 inline int pthread_cond_init(pthread_cond_t *c, pthread_condattr_t *a) {
755 InitializeConditionVariable(c);
759 inline int pthread_cond_destroy(pthread_cond_t *c) {
764 inline int pthread_cond_broadcast(pthread_cond_t *c) {
765 WakeAllConditionVariable(c);
769 inline int pthread_cond_wait(pthread_cond_t *c, pthread_mutex_t *m) {
770 SleepConditionVariableCS(c, m, INFINITE);
A function to suppress unused parameters compilation warnings.
Assertion checking mechanism.
Functions for atomic operations.
void geo_pause()
Issues a processor pause (INTEL only)
char atomic_bittestandreset_x86(volatile unsigned int *ptr, unsigned int bit)
Atomically tests and resets a bit (INTEL only)
char atomic_bittestandset_x86(volatile unsigned int *ptr, unsigned int bit)
Atomically tests and sets a bit (INTEL only)
Common include file, providing basic definitions. Should be included before anything else by all head...
An array of light-weight synchronisation primitives (spinlocks).
void clear()
Resets size to 0 and clears all the memory.
void release_spinlock(index_t i)
Releases a spinlock at a given index.
index_t size() const
Gets the number of spinlocks in this array.
void acquire_spinlock(index_t i)
Acquires a spinlock at a given index.
Numeric::uint32 word_t
Internal representation of SpinLockArray elements.
void resize(index_t size_in)
Resizes a SpinLockArray.
SpinLockArray()
Constructs a new SpinLockArray of size 0.
SpinLockArray(index_t size_in)
Constructs a new SpinLockArray of size size_in.
Global Vorpaline namespace.
void geo_argused(const T &)
Suppresses compiler warnings about unused parameters.
geo_index_t index_t
The type for storing and manipulating indices.
Types and functions for numbers manipulation.