Files
salmanoff/include/spinLock.h
T

82 lines
1.4 KiB
C++
Raw Normal View History

2025-09-17 16:28:07 -04:00
#ifndef SPIN_LOCK_H
#define SPIN_LOCK_H
#include <atomic>
#ifdef __x86_64__
#include <immintrin.h>
#elif defined(__i386__)
#include <xmmintrin.h>
#elif defined(__arm__)
#include <arm_neon.h>
#elif defined(__aarch64__)
#include <arm_neon.h>
#elif defined(__aarch32__)
#include <arm_neon.h>
#endif
2025-09-17 16:28:07 -04:00
namespace smo {
/**
* @brief Simple spinlock using std::atomic
*/
class SpinLock
{
public:
SpinLock()
: locked(false)
{}
bool tryAcquire()
{
bool expected = false;
return locked.compare_exchange_strong(expected, true);
}
inline void spinPause()
{
#ifdef __x86_64__
_mm_pause();
#elif defined(__i386__)
_mm_pause();
#elif defined(__arm__)
__asm__ volatile("yield");
#elif defined(__aarch64__)
__asm__ volatile("yield");
#elif defined(__aarch32__)
__asm__ volatile("yield");
#else
# error "Unsupported architecture"
#endif
}
void acquire()
{
while (!tryAcquire())
{
/** EXPLANATION:
* Busy-wait: keep trying to acquire the lock
* The CPU will spin here until the lock becomes available
*
* The spinPause() function is architecture-specific and is
* essential because I once fried an older Intel M-class laptop CPU
* when I forgot to include a PAUSE instruction in a for (;;){}
* loop. I'm not interested in frying my RPi or my other testbed
* robot boards.
*/
spinPause();
}
}
2025-09-17 16:28:07 -04:00
void release()
{
locked.store(false);
}
private:
std::atomic<bool> locked;
};
} // namespace smo
#endif // SPIN_LOCK_H