20 #include <type_traits> 
   23 #if defined(__INTEL_COMPILER) 
   25 #elif defined(_MSC_VER) 
   27 #elif defined(__GNUC__) 
   31 #if defined(_M_IA64) || defined(__ia64__) 
   33 #elif defined(_WIN64) || defined(__amd64__) || defined(_M_X64) || \ 
   36 #elif defined(_M_IX86) || defined(__i386__) 
   38 #elif defined(_M_PPC) || defined(__powerpc__) 
   41 #define AE_ARCH_UNKNOWN 
   45 #define AE_UNUSED(x) ((void)x) 
   48 #if defined(AE_VCPP) || defined(AE_ICC) 
   49 #define AE_FORCEINLINE __forceinline 
   52 #define AE_FORCEINLINE inline 
   54 #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))) 
   85 #if (defined(AE_VCPP) && (_MSC_VER < 1700 || defined(__cplusplus_cli))) || \ 
   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 
  104 #pragma warning(push) 
  108 #ifdef __cplusplus_cli 
  109 #pragma managed(push, off) 
  139 #if defined(AE_ARCH_X86) || defined(AE_ARCH_X64) 
  247 #if !defined(AE_VCPP) || (_MSC_VER >= 1700 && !defined(__cplusplus_cli)) 
  248 #define AE_USE_STD_ATOMIC_FOR_WEAK_ATOMIC 
  251 #ifdef AE_USE_STD_ATOMIC_FOR_WEAK_ATOMIC 
  262 template <
typename T>
 
  267 #pragma warning(push) 
  268 #pragma warning(disable : 4100)   
  271   template <
typename U>
 
  273 #ifdef __cplusplus_cli 
  286 #ifndef AE_USE_STD_ATOMIC_FOR_WEAK_ATOMIC 
  287   template <
typename U>
 
  289     value = std::forward<U>(x);
 
  300 #if defined(AE_ARCH_X64) || defined(AE_ARCH_X86) 
  302       return _InterlockedExchangeAdd((
long volatile*)&value, (
long)increment);
 
  303 #if defined(_M_AMD64) 
  304     else if (
sizeof(T) == 8)
 
  305       return _InterlockedExchangeAdd64((
long long volatile*)&value,
 
  306                                        (
long long)increment);
 
  309 #error Unsupported platform 
  311     assert(
false && 
"T must be either a 32 or 64 bit type");
 
  316 #if defined(AE_ARCH_X64) || defined(AE_ARCH_X86) 
  318       return _InterlockedExchangeAdd((
long volatile*)&value, (
long)increment);
 
  319 #if defined(_M_AMD64) 
  320     else if (
sizeof(T) == 8)
 
  321       return _InterlockedExchangeAdd64((
long long volatile*)&value,
 
  322                                        (
long long)increment);
 
  325 #error Unsupported platform 
  327     assert(
false && 
"T must be either a 32 or 64 bit type");
 
  331   template <
typename U>
 
  357 #ifndef AE_USE_STD_ATOMIC_FOR_WEAK_ATOMIC 
  363   std::atomic<T> value;
 
  378 struct _SECURITY_ATTRIBUTES;
 
  379 __declspec(dllimport) 
void* __stdcall CreateSemaphoreW(
 
  380     _SECURITY_ATTRIBUTES* lpSemaphoreAttributes, 
long lInitialCount,
 
  381     long lMaximumCount, 
const wchar_t* lpName);
 
  382 __declspec(dllimport) 
int __stdcall CloseHandle(
void* hObject);
 
  383 __declspec(dllimport) 
unsigned long __stdcall WaitForSingleObject(
 
  384     void* hHandle, 
unsigned long dwMilliseconds);
 
  385 __declspec(dllimport) 
int __stdcall ReleaseSemaphore(
void* hSemaphore,
 
  387                                                      long* lpPreviousCount);
 
  389 #elif defined(__MACH__) 
  390 #include <mach/mach.h> 
  391 #elif defined(__unix__) 
  392 #include <semaphore.h> 
  417 namespace spsc_sema {
 
  423   Semaphore(
const Semaphore& other);
 
  424   Semaphore& operator=(
const Semaphore& other);
 
  427   Semaphore(
int initialCount = 0) {
 
  428     assert(initialCount >= 0);
 
  429     const long maxLong = 0x7fffffff;
 
  430     m_hSema = CreateSemaphoreW(
nullptr, initialCount, maxLong, 
nullptr);
 
  433   ~Semaphore() { CloseHandle(m_hSema); }
 
  436     const unsigned long infinite = 0xffffffff;
 
  437     WaitForSingleObject(m_hSema, infinite);
 
  441     const unsigned long RC_WAIT_TIMEOUT = 0x00000102;
 
  442     return WaitForSingleObject(m_hSema, 0) != RC_WAIT_TIMEOUT;
 
  445   bool timed_wait(std::uint64_t usecs) {
 
  446     const unsigned long RC_WAIT_TIMEOUT = 0x00000102;
 
  447     return WaitForSingleObject(m_hSema, (
unsigned long)(usecs / 1000)) !=
 
  451   void signal(
int count = 1) { ReleaseSemaphore(m_hSema, count, 
nullptr); }
 
  453 #elif defined(__MACH__) 
  463   Semaphore(
const Semaphore& other);
 
  464   Semaphore& operator=(
const Semaphore& other);
 
  467   Semaphore(
int initialCount = 0) {
 
  468     assert(initialCount >= 0);
 
  469     semaphore_create(mach_task_self(), &m_sema, SYNC_POLICY_FIFO, initialCount);
 
  472   ~Semaphore() { semaphore_destroy(mach_task_self(), m_sema); }
 
  474   void wait() { semaphore_wait(m_sema); }
 
  476   bool try_wait() { 
return timed_wait(0); }
 
  478   bool timed_wait(std::int64_t timeout_usecs) {
 
  480     ts.tv_sec = timeout_usecs / 1000000;
 
  481     ts.tv_nsec = (timeout_usecs % 1000000) * 1000;
 
  485     kern_return_t rc = semaphore_timedwait(m_sema, ts);
 
  487     return rc != KERN_OPERATION_TIMED_OUT;
 
  490   void signal() { semaphore_signal(m_sema); }
 
  492   void signal(
int count) {
 
  493     while (count-- > 0) {
 
  494       semaphore_signal(m_sema);
 
  498 #elif defined(__unix__) 
  506   Semaphore(
const Semaphore& other);
 
  507   Semaphore& operator=(
const Semaphore& other);
 
  510   Semaphore(
int initialCount = 0) {
 
  511     assert(initialCount >= 0);
 
  512     sem_init(&m_sema, 0, initialCount);
 
  515   ~Semaphore() { sem_destroy(&m_sema); }
 
  521       rc = sem_wait(&m_sema);
 
  522     } 
while (rc == -1 && errno == EINTR);
 
  528       rc = sem_trywait(&m_sema);
 
  529     } 
while (rc == -1 && errno == EINTR);
 
  530     return !(rc == -1 && errno == EAGAIN);
 
  533   bool timed_wait(std::uint64_t usecs) {
 
  535     const int usecs_in_1_sec = 1000000;
 
  536     const int nsecs_in_1_sec = 1000000000;
 
  537     clock_gettime(CLOCK_REALTIME, &ts);
 
  538     ts.tv_sec += usecs / usecs_in_1_sec;
 
  539     ts.tv_nsec += (usecs % usecs_in_1_sec) * 1000;
 
  542     if (ts.tv_nsec > nsecs_in_1_sec) {
 
  543       ts.tv_nsec -= nsecs_in_1_sec;
 
  549       rc = sem_timedwait(&m_sema, &ts);
 
  550     } 
while (rc == -1 && errno == EINTR);
 
  551     return !(rc == -1 && errno == ETIMEDOUT);
 
  554   void signal() { sem_post(&m_sema); }
 
  556   void signal(
int count) {
 
  557     while (count-- > 0) {
 
  563 #error Unsupported platform! (No semaphore wrapper available) 
  571   typedef std::make_signed<std::size_t>::type 
ssize_t;
 
  577   bool waitWithPartialSpinning(std::int64_t timeout_usecs = -1) {
 
  583     while (--spin >= 0) {
 
  584       if (m_count.
load() > 0) {
 
  592     if (oldCount > 0) 
return true;
 
  593     if (timeout_usecs < 0) {
 
  597     if (m_sema.timed_wait(timeout_usecs)) 
return true;
 
  610       if (oldCount > 0 && m_sema.try_wait()) 
return true;
 
  616     assert(initialCount >= 0);
 
  620     if (m_count.
load() > 0) {
 
  628     if (!
tryWait()) waitWithPartialSpinning();
 
  631   bool wait(std::int64_t timeout_usecs) {
 
  632     return tryWait() || waitWithPartialSpinning(timeout_usecs);
 
  638     assert(oldCount >= -1);
 
  646     return count > 0 ? count : 0;
 
  652 #if defined(AE_VCPP) && (_MSC_VER < 1700 || defined(__cplusplus_cli)) 
  654 #ifdef __cplusplus_cli 
#define AE_FORCEINLINE
Definition: atomicops.h:54
Definition: atomicops.h:569
bool tryWait()
Definition: atomicops.h:619
std::make_signed< std::size_t >::type ssize_t
Definition: atomicops.h:571
void wait()
Definition: atomicops.h:627
ssize_t availableApprox() const
Definition: atomicops.h:644
bool wait(std::int64_t timeout_usecs)
Definition: atomicops.h:631
LightweightSemaphore(ssize_t initialCount=0)
Definition: atomicops.h:615
void signal(ssize_t count=1)
Definition: atomicops.h:635
Definition: atomicops.h:263
AE_FORCEINLINE T fetch_add_release(T increment)
Definition: atomicops.h:351
AE_FORCEINLINE T load() const
Definition: atomicops.h:343
AE_FORCEINLINE weak_atomic const  & operator=(weak_atomic const &other)
Definition: atomicops.h:337
AE_FORCEINLINE T fetch_add_acquire(T increment)
Definition: atomicops.h:347
weak_atomic(weak_atomic &&other)
Definition: atomicops.h:279
weak_atomic()
Definition: atomicops.h:265
AE_FORCEINLINE weak_atomic const  & operator=(U &&x)
Definition: atomicops.h:332
weak_atomic(weak_atomic const &other)
Definition: atomicops.h:278
weak_atomic(U &&x)
Definition: atomicops.h:272
Definition: atomicops.h:69
memory_order
Definition: atomicops.h:71
@ memory_order_acq_rel
Definition: atomicops.h:75
@ memory_order_seq_cst
Definition: atomicops.h:76
@ memory_order_acquire
Definition: atomicops.h:73
@ memory_order_relaxed
Definition: atomicops.h:72
@ memory_order_sync
Definition: atomicops.h:80
@ memory_order_release
Definition: atomicops.h:74
AE_FORCEINLINE void fence(memory_order order)
Definition: atomicops.h:222
AE_FORCEINLINE void compiler_fence(memory_order order)
Definition: atomicops.h:201