|
|
- #pragma once
-
- #include <atomic>
- #include <mutex>
-
- #ifdef __powerpc__
- #include "../../arch/powerpc/include/uapi/asm/unistd.h"
- #endif
-
- // Simple spinlock mutex based on std::atomic_flag
- // Compatible with std::lock_guard
- namespace vlc
- {
- #if defined(_WIN32)
- #if defined(_MSC_VER) && _MSC_VER >= 1310 && ( defined(_M_ARM) )
- extern "C" void YieldProcessor();
- #else
- extern "C" void _mm_pause();
- #endif
- #endif
-
- static inline void cpu_relax()
- {
-
- #if defined(__arc__) || defined(__mips__) || defined(__arm__) || defined(__powerpc__)
- asm volatile("" ::: "memory");
- #elif defined(__i386__) || defined(__x86_64__)
- asm volatile("rep; nop" ::: "memory");
- #elif defined(__aarch64__)
- asm volatile("yield" ::: "memory");
- #elif defined(__ia64__)
- asm volatile ("hint @pause" ::: "memory");
-
- #elif defined(_WIN32)
- #if defined(_MSC_VER) && _MSC_VER >= 1310 && ( defined(_M_ARM) )
- YieldProcessor();
- #else
- _mm_pause();
- #endif
- #endif
-
- }
-
- // Optimized Spinlock implementation
- // Reference https://rigtorp.se/spinlock/
- class Spinlock
- {
- public:
- Spinlock() : m_lock(false)
- {
- }
-
- Spinlock(const Spinlock&) = delete;
- Spinlock& operator = (const Spinlock&) = delete;
-
- void lock() noexcept
- {
- for (;;)
- {
- // Optimistically assume the lock is free on the first try
- if (!m_lock.exchange(true, std::memory_order_acquire))
- return;
-
- while (m_lock.load(std::memory_order_relaxed))
- {
- // Hint CPU that we're in spin-wait loop
- cpu_relax();
- }
- }
- }
-
- bool try_lock() noexcept
- {
- // Check first that we have free lock without CAS
- // because CAS writes to destination memory even if comparison failed
- // so we can reduce memory traffic just by prior checking for free lock
- return !m_lock.load(std::memory_order_relaxed) &&
- !m_lock.exchange(true, std::memory_order_acquire);
- }
-
- void unlock() noexcept
- {
- m_lock.store(false, std::memory_order_release);
- }
-
- private:
- std::atomic<bool> m_lock;
- };
-
- using SpinlockGuard = std::lock_guard<Spinlock>;
- }
|