123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126 |
- #pragma once
- #include "atomic.h"
- #include "spin_wait.h"
- class TSpinLockBase {
- protected:
- inline TSpinLockBase() noexcept {
- AtomicSet(Val_, 0);
- }
- public:
- inline bool IsLocked() const noexcept {
- return AtomicGet(Val_);
- }
- inline bool TryAcquire() noexcept {
- return AtomicTryLock(&Val_);
- }
- inline bool try_lock() noexcept {
- return TryAcquire();
- }
- protected:
- TAtomic Val_;
- };
- static inline void SpinLockPause() {
- #if defined(__GNUC__)
- #if defined(_i386_) || defined(_x86_64_)
- __asm __volatile("pause");
- #elif defined(_arm64_)
- __asm __volatile("yield" ::
- : "memory");
- #endif
- #endif
- }
- static inline void AcquireSpinLock(TAtomic* l) {
- if (!AtomicTryLock(l)) {
- do {
- SpinLockPause();
- } while (!AtomicTryAndTryLock(l));
- }
- }
- static inline void ReleaseSpinLock(TAtomic* l) {
- AtomicUnlock(l);
- }
- /*
- * You should almost always use TAdaptiveLock instead of TSpinLock
- */
- class TSpinLock: public TSpinLockBase {
- public:
- using TSpinLockBase::TSpinLockBase;
- inline void Release() noexcept {
- ReleaseSpinLock(&Val_);
- }
- inline void Acquire() noexcept {
- AcquireSpinLock(&Val_);
- }
- inline void unlock() noexcept {
- Release();
- }
- inline void lock() noexcept {
- Acquire();
- }
- };
- static inline void AcquireAdaptiveLock(TAtomic* l) {
- if (!AtomicTryLock(l)) {
- TSpinWait sw;
- while (!AtomicTryAndTryLock(l)) {
- sw.Sleep();
- }
- }
- }
- static inline void ReleaseAdaptiveLock(TAtomic* l) {
- AtomicUnlock(l);
- }
- class TAdaptiveLock: public TSpinLockBase {
- public:
- using TSpinLockBase::TSpinLockBase;
- inline void Release() noexcept {
- ReleaseAdaptiveLock(&Val_);
- }
- inline void Acquire() noexcept {
- AcquireAdaptiveLock(&Val_);
- }
- inline void unlock() noexcept {
- Release();
- }
- inline void lock() noexcept {
- Acquire();
- }
- };
- #include "guard.h"
- template <>
- struct TCommonLockOps<TAtomic> {
- static inline void Acquire(TAtomic* v) noexcept {
- AcquireAdaptiveLock(v);
- }
- static inline bool TryAcquire(TAtomic* v) noexcept {
- return AtomicTryLock(v);
- }
- static inline void Release(TAtomic* v) noexcept {
- ReleaseAdaptiveLock(v);
- }
- };
|