Created
April 15, 2020 17:45
-
-
Save charlie-x/33cdd141434a5526d49742418c1a1940 to your computer and use it in GitHub Desktop.
timur spin lock without RAII unlock non realtimesafe/overhead
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#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