15 #include <type_traits>
19 #if defined(__INTEL_COMPILER)
21 #elif defined(_MSC_VER)
23 #elif defined(__GNUC__)
27 #if defined(_M_IA64) || defined(__ia64__)
29 #elif defined(_WIN64) || defined(__amd64__) || defined(_M_X64) || defined(__x86_64__)
31 #elif defined(_M_IX86) || defined(__i386__)
33 #elif defined(_M_PPC) || defined(__powerpc__)
36 #define AE_ARCH_UNKNOWN
41 #define AE_UNUSED(x) ((void)x)
45 #if defined(AE_VCPP) || defined(AE_ICC)
46 #define AE_FORCEINLINE __forceinline
49 #define AE_FORCEINLINE inline
51 #define AE_FORCEINLINE inline
56 #if defined(AE_VCPP) || defined(AE_ICC)
57 #define AE_ALIGN(x) __declspec(align(x))
59 #define AE_ALIGN(x) __attribute__((aligned(x)))
62 #define AE_ALIGN(x) __attribute__((aligned(x)))
68 namespace moodycamel {
79 memory_order_sync = memory_order_seq_cst
84 #if (defined(AE_VCPP) && (_MSC_VER < 1700 || defined(__cplusplus_cli))) || defined(AE_ICC)
89 #if defined(AE_ARCH_X64) || defined(AE_ARCH_X86)
90 #define AeFullSync _mm_mfence
91 #define AeLiteSync _mm_mfence
92 #elif defined(AE_ARCH_IA64)
93 #define AeFullSync __mf
94 #define AeLiteSync __mf
95 #elif defined(AE_ARCH_PPC)
96 #include <ppcintrinsics.h>
97 #define AeFullSync __sync
98 #define AeLiteSync __lwsync
103 #pragma warning(push)
104 #pragma warning(disable: 4365) // Disable erroneous 'conversion from long to unsigned int, signed/unsigned mismatch' error when using `assert`
105 #ifdef __cplusplus_cli
106 #pragma managed(push, off)
110 namespace moodycamel {
112 AE_FORCEINLINE
void compiler_fence(memory_order order)
115 case memory_order_relaxed:
break;
116 case memory_order_acquire: _ReadBarrier();
break;
117 case memory_order_release: _WriteBarrier();
break;
118 case memory_order_acq_rel: _ReadWriteBarrier();
break;
119 case memory_order_seq_cst: _ReadWriteBarrier();
break;
120 default: assert(
false);
127 #if defined(AE_ARCH_X86) || defined(AE_ARCH_X64)
128 AE_FORCEINLINE
void fence(memory_order order)
131 case memory_order_relaxed:
break;
132 case memory_order_acquire: _ReadBarrier();
break;
133 case memory_order_release: _WriteBarrier();
break;
134 case memory_order_acq_rel: _ReadWriteBarrier();
break;
135 case memory_order_seq_cst:
140 default: assert(
false);
144 AE_FORCEINLINE
void fence(memory_order order)
148 case memory_order_relaxed:
150 case memory_order_acquire:
155 case memory_order_release:
160 case memory_order_acq_rel:
165 case memory_order_seq_cst:
170 default: assert(
false);
179 namespace moodycamel {
181 AE_FORCEINLINE
void compiler_fence(memory_order order)
184 case memory_order_relaxed:
break;
185 case memory_order_acquire: std::atomic_signal_fence(std::memory_order_acquire);
break;
186 case memory_order_release: std::atomic_signal_fence(std::memory_order_release);
break;
187 case memory_order_acq_rel: std::atomic_signal_fence(std::memory_order_acq_rel);
break;
188 case memory_order_seq_cst: std::atomic_signal_fence(std::memory_order_seq_cst);
break;
189 default: assert(
false);
193 AE_FORCEINLINE
void fence(memory_order order)
196 case memory_order_relaxed:
break;
197 case memory_order_acquire: std::atomic_thread_fence(std::memory_order_acquire);
break;
198 case memory_order_release: std::atomic_thread_fence(std::memory_order_release);
break;
199 case memory_order_acq_rel: std::atomic_thread_fence(std::memory_order_acq_rel);
break;
200 case memory_order_seq_cst: std::atomic_thread_fence(std::memory_order_seq_cst);
break;
201 default: assert(
false);
210 #if !defined(AE_VCPP) || (_MSC_VER >= 1700 && !defined(__cplusplus_cli))
211 #define AE_USE_STD_ATOMIC_FOR_WEAK_ATOMIC
214 #ifdef AE_USE_STD_ATOMIC_FOR_WEAK_ATOMIC
223 namespace moodycamel {
230 #pragma warning(disable: 4100) // Get rid of (erroneous) 'unreferenced formal parameter' warning
232 template<
typename U>
weak_atomic(U&& x) : value(std::forward<U>(x)) { }
233 #ifdef __cplusplus_cli
240 #pragma warning(default: 4100)
243 AE_FORCEINLINE
operator T()
const {
return load(); }
246 #ifndef AE_USE_STD_ATOMIC_FOR_WEAK_ATOMIC
247 template<
typename U> AE_FORCEINLINE
weak_atomic const& operator=(U&& x) { value = std::forward<U>(x);
return *
this; }
248 AE_FORCEINLINE
weak_atomic const& operator=(
weak_atomic const& other) { value = other.value;
return *
this; }
250 AE_FORCEINLINE T load()
const {
return value; }
252 AE_FORCEINLINE T fetch_add_acquire(T increment)
254 #if defined(AE_ARCH_X64) || defined(AE_ARCH_X86)
255 if (
sizeof(T) == 4)
return _InterlockedExchangeAdd((
long volatile*)&value, (
long)increment);
256 #if defined(_M_AMD64)
257 else if (
sizeof(T) == 8)
return _InterlockedExchangeAdd64((
long long volatile*)&value, (
long long)increment);
260 #error Unsupported platform
262 assert(
false &&
"T must be either a 32 or 64 bit type");
266 AE_FORCEINLINE T fetch_add_release(T increment)
268 #if defined(AE_ARCH_X64) || defined(AE_ARCH_X86)
269 if (
sizeof(T) == 4)
return _InterlockedExchangeAdd((
long volatile*)&value, (
long)increment);
270 #if defined(_M_AMD64)
271 else if (
sizeof(T) == 8)
return _InterlockedExchangeAdd64((
long long volatile*)&value, (
long long)increment);
274 #error Unsupported platform
276 assert(
false &&
"T must be either a 32 or 64 bit type");
283 value.store(std::forward<U>(x), std::memory_order_relaxed);
289 value.store(other.value.load(std::memory_order_relaxed), std::memory_order_relaxed);
293 AE_FORCEINLINE T load()
const {
return value.load(std::memory_order_relaxed); }
295 AE_FORCEINLINE T fetch_add_acquire(T increment)
297 return value.fetch_add(increment, std::memory_order_acquire);
300 AE_FORCEINLINE T fetch_add_release(T increment)
302 return value.fetch_add(increment, std::memory_order_release);
308 #ifndef AE_USE_STD_ATOMIC_FOR_WEAK_ATOMIC
313 std::atomic<T> value;
330 struct _SECURITY_ATTRIBUTES;
331 __declspec(dllimport) void* __stdcall CreateSemaphoreW(_SECURITY_ATTRIBUTES* lpSemaphoreAttributes,
long lInitialCount,
long lMaximumCount, const
wchar_t* lpName);
332 __declspec(dllimport)
int __stdcall CloseHandle(
void* hObject);
333 __declspec(dllimport)
unsigned long __stdcall WaitForSingleObject(
void* hHandle,
unsigned long dwMilliseconds);
334 __declspec(dllimport)
int __stdcall ReleaseSemaphore(
void* hSemaphore,
long lReleaseCount,
long* lpPreviousCount);
336 #elif defined(__MACH__)
337 #include <mach/mach.h>
338 #elif defined(__unix__)
339 #include <semaphore.h>
373 Semaphore(
const Semaphore& other);
374 Semaphore& operator=(
const Semaphore& other);
377 Semaphore(
int initialCount = 0)
379 assert(initialCount >= 0);
380 const long maxLong = 0x7fffffff;
381 m_hSema = CreateSemaphoreW(
nullptr, initialCount, maxLong,
nullptr);
386 CloseHandle(m_hSema);
391 const unsigned long infinite = 0xffffffff;
392 WaitForSingleObject(m_hSema, infinite);
395 void signal(
int count = 1)
397 ReleaseSemaphore(m_hSema, count,
nullptr);
400 #elif defined(__MACH__)
410 Semaphore(
const Semaphore& other);
411 Semaphore& operator=(
const Semaphore& other);
414 Semaphore(
int initialCount = 0)
416 assert(initialCount >= 0);
417 semaphore_create(mach_task_self(), &m_sema, SYNC_POLICY_FIFO, initialCount);
422 semaphore_destroy(mach_task_self(), m_sema);
427 semaphore_wait(m_sema);
432 semaphore_signal(m_sema);
435 void signal(
int count)
439 semaphore_signal(m_sema);
443 #elif defined(__unix__)
452 Semaphore(
const Semaphore& other);
453 Semaphore& operator=(
const Semaphore& other);
456 Semaphore(
int initialCount = 0)
458 assert(initialCount >= 0);
459 sem_init(&m_sema, 0, initialCount);
464 sem_destroy(&m_sema);
473 rc = sem_wait(&m_sema);
475 while (rc == -1 && errno == EINTR);
483 void signal(
int count)
492 #error Unsupported platform! (No semaphore wrapper available)
501 typedef std::make_signed<std::size_t>::type ssize_t;
507 void waitWithPartialSpinning()
516 if (m_count.load() > 0)
518 m_count.fetch_add_acquire(-1);
521 compiler_fence(memory_order_acquire);
523 oldCount = m_count.fetch_add_acquire(-1);
533 assert(initialCount >= 0);
538 if (m_count.load() > 0)
540 m_count.fetch_add_acquire(-1);
549 waitWithPartialSpinning();
552 void signal(ssize_t count = 1)
555 ssize_t oldCount = m_count.fetch_add_release(count);
556 assert(oldCount >= -1);
563 ssize_t availableApprox()
const
565 ssize_t count = m_count.load();
566 return count > 0 ? count : 0;
572 #if defined(AE_VCPP) && (_MSC_VER < 1700 || defined(__cplusplus_cli))
574 #ifdef __cplusplus_cli
Definition: atomicops.h:498
Definition: atomicops.h:225