Skip to content

Instantly share code, notes, and snippets.

@charlie-x
Created April 15, 2020 17:45
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save charlie-x/33cdd141434a5526d49742418c1a1940 to your computer and use it in GitHub Desktop.
Save charlie-x/33cdd141434a5526d49742418c1a1940 to your computer and use it in GitHub Desktop.
timur spin lock without RAII unlock non realtimesafe/overhead
#include <array>
#include <thread>
#include <atomic>
#include <emmintrin.h>
struct spin_mutex {
void lock() noexcept {
// approx. 5x5 ns (= 25 ns), 10x40 ns (= 400 ns), and 3000x350 ns
// (~ 1 ms), respectively, when measured on a 2.9 GHz Intel i9
constexpr std::array iterations = {5, 10, 3000};
for (int i = 0; i < iterations[0]; ++i) {
if (try_lock())
return;
}
for (int i = 0; i < iterations[1]; ++i) {
if (try_lock())
return;
_mm_pause();
}
while (true) {
for (int i = 0; i < iterations[2]; ++i) {
if (try_lock())
return;
_mm_pause(); //Windows can use YieldProcessor()
_mm_pause();
_mm_pause();
_mm_pause();
_mm_pause();
_mm_pause();
_mm_pause();
_mm_pause();
_mm_pause();
_mm_pause();
}
// waiting longer than we should, let's give other threads
// a chance to recover
std::this_thread::yield();
}
bool try_lock() noexcept {
return !flag.test_and_set(std::memory_order_acquire);
}
void unlock() noexcept {
flag.clear(std::memory_order_release);
}
private:
std::atomic_flag flag = ATOMIC_FLAG_INIT;
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment