16 #include <type_traits> 22 #if defined(__INTEL_COMPILER) 24 #elif defined(_MSC_VER) 26 #elif defined(__GNUC__) 30 #if defined(_M_IA64) || defined(__ia64__) 32 #elif defined(_WIN64) || defined(__amd64__) || defined(_M_X64) || defined(__x86_64__) 34 #elif defined(_M_IX86) || defined(__i386__) 36 #elif defined(_M_PPC) || defined(__powerpc__) 39 #define AE_ARCH_UNKNOWN 43 #define AE_UNUSED(x) ((void)x) 46 #if defined(__has_feature) 47 #if __has_feature(thread_sanitizer) 48 #define AE_NO_TSAN __attribute__((no_sanitize("thread"))) 57 #if defined(AE_VCPP) || defined(AE_ICC) 58 #define AE_FORCEINLINE __forceinline 61 #define AE_FORCEINLINE inline 63 #define AE_FORCEINLINE inline 67 #if defined(AE_VCPP) || defined(AE_ICC) 68 #define AE_ALIGN(x) __declspec(align(x)) 70 #define AE_ALIGN(x) __attribute__((aligned(x))) 73 #define AE_ALIGN(x) __attribute__((aligned(x))) 95 #if (defined(AE_VCPP) && (_MSC_VER < 1700 || defined(__cplusplus_cli))) || (defined(AE_ICC) && __INTEL_COMPILER < 1600) 100 #if defined(AE_ARCH_X64) || defined(AE_ARCH_X86) 101 #define AeFullSync _mm_mfence 102 #define AeLiteSync _mm_mfence 103 #elif defined(AE_ARCH_IA64) 104 #define AeFullSync __mf 105 #define AeLiteSync __mf 106 #elif defined(AE_ARCH_PPC) 107 #include <ppcintrinsics.h> 108 #define AeFullSync __sync 109 #define AeLiteSync __lwsync 113 #pragma warning(push) 114 #pragma warning(disable : 4365) // Disable erroneous 'conversion from long to unsigned int, signed/unsigned mismatch' 116 #ifdef __cplusplus_cli 117 #pragma managed(push, off) 149 #if defined(AE_ARCH_X86) || defined(AE_ARCH_X64) 264 #if !defined(AE_VCPP) || (_MSC_VER >= 1700 && !defined(__cplusplus_cli)) 265 #define AE_USE_STD_ATOMIC_FOR_WEAK_ATOMIC 268 #ifdef AE_USE_STD_ATOMIC_FOR_WEAK_ATOMIC 279 template <
typename T>
287 #pragma warning(push) 288 #pragma warning(disable : 4100) // Get rid of (erroneous) 'unreferenced formal parameter' warning 290 template <
typename U>
294 #ifdef __cplusplus_cli 315 #ifndef AE_USE_STD_ATOMIC_FOR_WEAK_ATOMIC 316 template <
typename U>
319 value = std::forward<U>(x);
335 #if defined(AE_ARCH_X64) || defined(AE_ARCH_X86) 337 return _InterlockedExchangeAdd((
long volatile*)&
value, (
long)increment);
338 #if defined(_M_AMD64) 339 else if (
sizeof(T) == 8)
340 return _InterlockedExchangeAdd64((
long long volatile*)&value, (
long long)increment);
343 #error Unsupported platform 345 assert(
false &&
"T must be either a 32 or 64 bit type");
351 #if defined(AE_ARCH_X64) || defined(AE_ARCH_X86) 353 return _InterlockedExchangeAdd((
long volatile*)&
value, (
long)increment);
354 #if defined(_M_AMD64) 355 else if (
sizeof(T) == 8)
356 return _InterlockedExchangeAdd64((
long long volatile*)&value, (
long long)increment);
359 #error Unsupported platform 361 assert(
false &&
"T must be either a 32 or 64 bit type");
365 template <
typename U>
395 #ifndef AE_USE_STD_ATOMIC_FOR_WEAK_ATOMIC 415 struct _SECURITY_ATTRIBUTES;
416 __declspec(dllimport)
void* __stdcall CreateSemaphoreW(_SECURITY_ATTRIBUTES* lpSemaphoreAttributes,
long lInitialCount,
417 long lMaximumCount,
const wchar_t* lpName);
418 __declspec(dllimport)
int __stdcall CloseHandle(
void* hObject);
419 __declspec(dllimport)
unsigned long __stdcall WaitForSingleObject(
void* hHandle,
unsigned long dwMilliseconds);
420 __declspec(dllimport)
int __stdcall ReleaseSemaphore(
void* hSemaphore,
long lReleaseCount,
long* lpPreviousCount);
422 #elif defined(__MACH__) 423 #include <mach/mach.h> 424 #elif defined(__unix__) 425 #include <semaphore.h> 459 Semaphore(
const Semaphore& other);
460 Semaphore&
operator=(
const Semaphore& other);
465 assert(initialCount >= 0);
466 const long maxLong = 0x7fffffff;
467 m_hSema = CreateSemaphoreW(
nullptr, initialCount, maxLong,
nullptr);
473 CloseHandle(m_hSema);
478 const unsigned long infinite = 0xffffffff;
479 return WaitForSingleObject(m_hSema, infinite) == 0;
484 return WaitForSingleObject(m_hSema, 0) == 0;
487 bool timed_wait(std::uint64_t usecs)
AE_NO_TSAN 489 return WaitForSingleObject(m_hSema, (
unsigned long)(usecs / 1000)) == 0;
494 while (!ReleaseSemaphore(m_hSema, count,
nullptr))
498 #elif defined(__MACH__) 508 Semaphore(
const Semaphore& other);
509 Semaphore&
operator=(
const Semaphore& other);
514 assert(initialCount >= 0);
515 kern_return_t rc = semaphore_create(mach_task_self(), &m_sema, SYNC_POLICY_FIFO, initialCount);
516 assert(rc == KERN_SUCCESS);
522 semaphore_destroy(mach_task_self(), m_sema);
527 return semaphore_wait(m_sema) == KERN_SUCCESS;
532 return timed_wait(0);
535 bool timed_wait(std::int64_t timeout_usecs)
AE_NO_TSAN 538 ts.tv_sec =
static_cast<unsigned int>(timeout_usecs / 1000000);
539 ts.tv_nsec = (timeout_usecs % 1000000) * 1000;
543 kern_return_t rc = semaphore_timedwait(m_sema, ts);
544 return rc == KERN_SUCCESS;
549 while (semaphore_signal(m_sema) != KERN_SUCCESS)
557 while (semaphore_signal(m_sema) != KERN_SUCCESS)
562 #elif defined(__unix__) 571 Semaphore(
const Semaphore& other);
572 Semaphore&
operator=(
const Semaphore& other);
577 assert(initialCount >= 0);
578 int rc = sem_init(&m_sema, 0, initialCount);
585 sem_destroy(&m_sema);
594 rc = sem_wait(&m_sema);
595 }
while (rc == -1 && errno == EINTR);
604 rc = sem_trywait(&m_sema);
605 }
while (rc == -1 && errno == EINTR);
609 bool timed_wait(std::uint64_t usecs)
AE_NO_TSAN 612 const int usecs_in_1_sec = 1000000;
613 const int nsecs_in_1_sec = 1000000000;
614 clock_gettime(CLOCK_REALTIME, &ts);
615 ts.tv_sec += usecs / usecs_in_1_sec;
616 ts.tv_nsec += (usecs % usecs_in_1_sec) * 1000;
619 if (ts.tv_nsec >= nsecs_in_1_sec)
621 ts.tv_nsec -= nsecs_in_1_sec;
628 rc = sem_timedwait(&m_sema, &ts);
629 }
while (rc == -1 && errno == EINTR);
635 while (sem_post(&m_sema) == -1)
643 while (sem_post(&m_sema) == -1)
649 #error Unsupported platform! (No semaphore wrapper available) 658 typedef std::make_signed<std::size_t>::type
ssize_t;
673 if (m_count.
load() > 0)
683 if (timeout_usecs < 0)
684 return m_sema.wait();
685 if (m_sema.timed_wait(timeout_usecs))
699 if (oldCount > 0 && m_sema.try_wait())
707 assert(initialCount >= 0);
712 if (m_count.
load() > 0)
722 return tryWait() || waitWithPartialSpinning();
727 return tryWait() || waitWithPartialSpinning(timeout_usecs);
734 assert(oldCount >= -1);
743 ssize_t count = m_count.
load();
744 return count > 0 ? count : 0;
750 #if defined(AE_VCPP) && (_MSC_VER < 1700 || defined(__cplusplus_cli)) 752 #ifdef __cplusplus_cli
AE_NO_TSAN LightweightSemaphore(ssize_t initialCount=0)
AE_NO_TSAN weak_atomic(weak_atomic const &other)
AE_FORCEINLINE weak_atomic const & operator=(weak_atomic const &other) AE_NO_TSAN
bool wait(std::int64_t timeout_usecs) AE_NO_TSAN
AE_FORCEINLINE T fetch_add_acquire(T increment) AE_NO_TSAN
ssize_t availableApprox() const AE_NO_TSAN
AE_FORCEINLINE void fence(memory_order order) AE_NO_TSAN
AE_FORCEINLINE T load() const AE_NO_TSAN
AE_NO_TSAN weak_atomic(weak_atomic &&other)
weak_atomic< ssize_t > m_count
bool tryWait() AE_NO_TSAN
AE_NO_TSAN weak_atomic(U &&x)
void signal(ssize_t count=1) AE_NO_TSAN
std::make_signed< std::size_t >::type ssize_t
AE_FORCEINLINE T fetch_add_release(T increment) AE_NO_TSAN
void move(std::vector< T > &a, std::vector< T > &b)
AE_FORCEINLINE void compiler_fence(memory_order order) AE_NO_TSAN
bool waitWithPartialSpinning(std::int64_t timeout_usecs=-1) AE_NO_TSAN
AE_FORCEINLINE weak_atomic const & operator=(U &&x) AE_NO_TSAN
void increment(int *value)