21#if defined(__INTEL_COMPILER) 
   23#elif defined(_MSC_VER) 
   25#elif defined(__GNUC__) 
   29#if defined(_M_IA64) || defined(__ia64__) 
   31#elif defined(_WIN64) || defined(__amd64__) || defined(_M_X64) || defined(__x86_64__) 
   33#elif defined(_M_IX86) || defined(__i386__) 
   35#elif defined(_M_PPC) || defined(__powerpc__) 
   38#define AE_ARCH_UNKNOWN 
   43#define AE_UNUSED(x) ((void)x) 
   47#if defined(AE_VCPP) || defined(AE_ICC) 
   48#define AE_FORCEINLINE __forceinline 
   51#define AE_FORCEINLINE inline 
   53#define AE_FORCEINLINE inline 
   58#if defined(AE_VCPP) || defined(AE_ICC) 
   59#define AE_ALIGN(x) __declspec(align(x)) 
   61#define AE_ALIGN(x) __attribute__((aligned(x))) 
   64#define AE_ALIGN(x) __attribute__((aligned(x))) 
   81    memory_order_sync = memory_order_seq_cst
 
   86#if (defined(AE_VCPP) && (_MSC_VER < 1700 || defined(__cplusplus_cli))) || (defined(AE_ICC) && __INTEL_COMPILER < 1600) 
   91#if defined(AE_ARCH_X64) || defined(AE_ARCH_X86) 
   92#define AeFullSync _mm_mfence 
   93#define AeLiteSync _mm_mfence 
   94#elif defined(AE_ARCH_IA64) 
   95#define AeFullSync __mf 
   96#define AeLiteSync __mf 
   97#elif defined(AE_ARCH_PPC) 
   98#include <ppcintrinsics.h> 
   99#define AeFullSync __sync 
  100#define AeLiteSync __lwsync 
  106#pragma warning(disable: 4365)       
  107#ifdef __cplusplus_cli 
  108#pragma managed(push, off) 
  112namespace moodycamel {
 
  114AE_FORCEINLINE 
void compiler_fence(memory_order order)
 
  117        case memory_order_relaxed: 
break;
 
  118        case memory_order_acquire: _ReadBarrier(); 
break;
 
  119        case memory_order_release: _WriteBarrier(); 
break;
 
  120        case memory_order_acq_rel: _ReadWriteBarrier(); 
break;
 
  121        case memory_order_seq_cst: _ReadWriteBarrier(); 
break;
 
  122        default: assert(
false);
 
  129#if defined(AE_ARCH_X86) || defined(AE_ARCH_X64) 
  130AE_FORCEINLINE 
void fence(memory_order order)
 
  133        case memory_order_relaxed: 
break;
 
  134        case memory_order_acquire: _ReadBarrier(); 
break;
 
  135        case memory_order_release: _WriteBarrier(); 
break;
 
  136        case memory_order_acq_rel: _ReadWriteBarrier(); 
break;
 
  137        case memory_order_seq_cst:
 
  142        default: assert(
false);
 
  146AE_FORCEINLINE 
void fence(memory_order order)
 
  150        case memory_order_relaxed:
 
  152        case memory_order_acquire:
 
  157        case memory_order_release:
 
  162        case memory_order_acq_rel:
 
  167        case memory_order_seq_cst:
 
  172        default: assert(
false);
 
  181namespace moodycamel {
 
  183AE_FORCEINLINE 
void compiler_fence(memory_order order)
 
  186        case memory_order_relaxed: 
break;
 
  187        case memory_order_acquire: std::atomic_signal_fence(std::memory_order_acquire); 
break;
 
  188        case memory_order_release: std::atomic_signal_fence(std::memory_order_release); 
break;
 
  189        case memory_order_acq_rel: std::atomic_signal_fence(std::memory_order_acq_rel); 
break;
 
  190        case memory_order_seq_cst: std::atomic_signal_fence(std::memory_order_seq_cst); 
break;
 
  191        default: assert(
false);
 
  195AE_FORCEINLINE 
void fence(memory_order order)
 
  198        case memory_order_relaxed: 
break;
 
  199        case memory_order_acquire: std::atomic_thread_fence(std::memory_order_acquire); 
break;
 
  200        case memory_order_release: std::atomic_thread_fence(std::memory_order_release); 
break;
 
  201        case memory_order_acq_rel: std::atomic_thread_fence(std::memory_order_acq_rel); 
break;
 
  202        case memory_order_seq_cst: std::atomic_thread_fence(std::memory_order_seq_cst); 
break;
 
  203        default: assert(
false);
 
  212#if !defined(AE_VCPP) || (_MSC_VER >= 1700 && !defined(__cplusplus_cli)) 
  213#define AE_USE_STD_ATOMIC_FOR_WEAK_ATOMIC 
  216#ifdef AE_USE_STD_ATOMIC_FOR_WEAK_ATOMIC 
  225namespace moodycamel {
 
  233#pragma warning(disable: 4100)       
  235    template<
typename U> 
weak_atomic(U&& x) : value(std::forward<U>(x)) {  }
 
  236#ifdef __cplusplus_cli 
  246    AE_FORCEINLINE 
operator T()
 const { 
return load(); }
 
  249#ifndef AE_USE_STD_ATOMIC_FOR_WEAK_ATOMIC 
  250    template<
typename U> AE_FORCEINLINE 
weak_atomic const& operator=(U&& x) { value = std::forward<U>(x); 
return *
this; }
 
  251    AE_FORCEINLINE 
weak_atomic const& operator=(
weak_atomic const& other) { value = other.value; 
return *
this; }
 
  253    AE_FORCEINLINE T load()
 const { 
return value; }
 
  255    AE_FORCEINLINE T fetch_add_acquire(T increment)
 
  257#if defined(AE_ARCH_X64) || defined(AE_ARCH_X86) 
  258        if (
sizeof(T) == 4) 
return _InterlockedExchangeAdd((
long volatile*)&value, (
long)increment);
 
  260        else if (
sizeof(T) == 8) 
return _InterlockedExchangeAdd64((
long long volatile*)&value, (
long long)increment);
 
  263#error Unsupported platform 
  265        assert(
false && 
"T must be either a 32 or 64 bit type");
 
  269    AE_FORCEINLINE T fetch_add_release(T increment)
 
  271#if defined(AE_ARCH_X64) || defined(AE_ARCH_X86) 
  272        if (
sizeof(T) == 4) 
return _InterlockedExchangeAdd((
long volatile*)&value, (
long)increment);
 
  274        else if (
sizeof(T) == 8) 
return _InterlockedExchangeAdd64((
long long volatile*)&value, (
long long)increment);
 
  277#error Unsupported platform 
  279        assert(
false && 
"T must be either a 32 or 64 bit type");
 
  286        value.store(std::forward<U>(x), std::memory_order_relaxed);
 
  292        value.store(other.value.load(std::memory_order_relaxed), std::memory_order_relaxed);
 
  296    AE_FORCEINLINE T load()
 const { 
return value.load(std::memory_order_relaxed); }
 
  298    AE_FORCEINLINE T fetch_add_acquire(T increment)
 
  300        return value.fetch_add(increment, std::memory_order_acquire);
 
  303    AE_FORCEINLINE T fetch_add_release(T increment)
 
  305        return value.fetch_add(increment, std::memory_order_release);
 
  311#ifndef AE_USE_STD_ATOMIC_FOR_WEAK_ATOMIC 
  316    std::atomic<T> value;
 
  333    struct _SECURITY_ATTRIBUTES;
 
  334    __declspec(dllimport) 
void* __stdcall CreateSemaphoreW(_SECURITY_ATTRIBUTES* lpSemaphoreAttributes, 
long lInitialCount, 
long lMaximumCount, 
const wchar_t* lpName);
 
  335    __declspec(dllimport) 
int __stdcall CloseHandle(
void* hObject);
 
  336    __declspec(dllimport) 
unsigned long __stdcall WaitForSingleObject(
void* hHandle, 
unsigned long dwMilliseconds);
 
  337    __declspec(dllimport) 
int __stdcall ReleaseSemaphore(
void* hSemaphore, 
long lReleaseCount, 
long* lpPreviousCount);
 
  339#elif defined(__MACH__) 
  340#include <mach/mach.h> 
  341#elif defined(__unix__) 
  342#include <semaphore.h> 
  376            Semaphore(
const Semaphore& other);
 
  377            Semaphore& operator=(
const Semaphore& other);
 
  380            Semaphore(
int initialCount = 0)
 
  382                assert(initialCount >= 0);
 
  383                const long maxLong = 0x7fffffff;
 
  384                m_hSema = CreateSemaphoreW(
nullptr, initialCount, maxLong, 
nullptr);
 
  389                CloseHandle(m_hSema);
 
  394                const unsigned long infinite = 0xffffffff;
 
  395                WaitForSingleObject(m_hSema, infinite);
 
  400                const unsigned long RC_WAIT_TIMEOUT = 0x00000102;
 
  401                return WaitForSingleObject(m_hSema, 0) != RC_WAIT_TIMEOUT;
 
  404            bool timed_wait(std::uint64_t usecs)
 
  406                const unsigned long RC_WAIT_TIMEOUT = 0x00000102;
 
  407                return WaitForSingleObject(m_hSema, (
unsigned long)(usecs / 1000)) != RC_WAIT_TIMEOUT;
 
  410            void signal(
int count = 1)
 
  412                ReleaseSemaphore(m_hSema, count, 
nullptr);
 
  415#elif defined(__MACH__) 
  425            Semaphore(
const Semaphore& other);
 
  426            Semaphore& operator=(
const Semaphore& other);
 
  429            Semaphore(
int initialCount = 0)
 
  431                assert(initialCount >= 0);
 
  432                semaphore_create(mach_task_self(), &m_sema, SYNC_POLICY_FIFO, initialCount);
 
  437                semaphore_destroy(mach_task_self(), m_sema);
 
  442                semaphore_wait(m_sema);
 
  447                return timed_wait(0);
 
  450            bool timed_wait(std::int64_t timeout_usecs)
 
  453                ts.tv_sec = 
static_cast<unsigned int>(timeout_usecs / 1000000);
 
  454                ts.tv_nsec = (timeout_usecs % 1000000) * 1000;
 
  457                kern_return_t rc = semaphore_timedwait(m_sema, ts);
 
  459                return rc != KERN_OPERATION_TIMED_OUT && rc != KERN_ABORTED;
 
  464                semaphore_signal(m_sema);
 
  467            void signal(
int count)
 
  471                    semaphore_signal(m_sema);
 
  475#elif defined(__unix__) 
  484            Semaphore(
const Semaphore& other);
 
  485            Semaphore& operator=(
const Semaphore& other);
 
  488            Semaphore(
int initialCount = 0)
 
  490                assert(initialCount >= 0);
 
  491                sem_init(&m_sema, 0, initialCount);
 
  496                sem_destroy(&m_sema);
 
  505                    rc = sem_wait(&m_sema);
 
  507                while (rc == -1 && errno == EINTR);
 
  514                    rc = sem_trywait(&m_sema);
 
  515                } 
while (rc == -1 && errno == EINTR);
 
  516                return !(rc == -1 && errno == EAGAIN);
 
  519            bool timed_wait(std::uint64_t usecs)
 
  522                const int usecs_in_1_sec = 1000000;
 
  523                const int nsecs_in_1_sec = 1000000000;
 
  524                clock_gettime(CLOCK_REALTIME, &ts);
 
  525                ts.tv_sec += usecs / usecs_in_1_sec;
 
  526                ts.tv_nsec += (usecs % usecs_in_1_sec) * 1000;
 
  529                if (ts.tv_nsec >= nsecs_in_1_sec) {
 
  530                    ts.tv_nsec -= nsecs_in_1_sec;
 
  536                    rc = sem_timedwait(&m_sema, &ts);
 
  537                } 
while (rc == -1 && errno == EINTR);
 
  538                return !(rc == -1 && errno == ETIMEDOUT);
 
  546            void signal(
int count)
 
  555#error Unsupported platform! (No semaphore wrapper available) 
  564            typedef std::make_signed<std::size_t>::type ssize_t;
 
  570            bool waitWithPartialSpinning(std::int64_t timeout_usecs = -1)
 
  579                    if (m_count.load() > 0)
 
  581                        m_count.fetch_add_acquire(-1);
 
  584                    compiler_fence(memory_order_acquire);     
 
  586                oldCount = m_count.fetch_add_acquire(-1);
 
  589                if (timeout_usecs < 0)
 
  594                if (m_sema.timed_wait(timeout_usecs))
 
  603                    oldCount = m_count.fetch_add_release(1);
 
  607                    oldCount = m_count.fetch_add_acquire(-1);
 
  608                    if (oldCount > 0 && m_sema.try_wait())
 
  616                assert(initialCount >= 0);
 
  621                if (m_count.load() > 0)
 
  623                    m_count.fetch_add_acquire(-1);
 
  632                    waitWithPartialSpinning();
 
  635            bool wait(std::int64_t timeout_usecs)
 
  637                return tryWait() || waitWithPartialSpinning(timeout_usecs);
 
  640            void signal(ssize_t count = 1)
 
  643                ssize_t oldCount = m_count.fetch_add_release(count);
 
  644                assert(oldCount >= -1);
 
  651            ssize_t availableApprox()
 const 
  653                ssize_t count = m_count.load();
 
  654                return count > 0 ? count : 0;
 
  660#if defined(AE_VCPP) && (_MSC_VER < 1700 || defined(__cplusplus_cli)) 
  662#ifdef __cplusplus_cli 
Definition: atomicops.h:562
Definition: atomicops.h:228