Skip to content

Instantly share code, notes, and snippets.

@ashvardanian
Created May 24, 2023 14:06
Show Gist options
  • Save ashvardanian/60bd103b82783d56d8739b33cae13cdb to your computer and use it in GitHub Desktop.
Save ashvardanian/60bd103b82783d56d8739b33cae13cdb to your computer and use it in GitHub Desktop.
A tiny userspace mutex class designed to fit in a single integer. Similar to `std::atomic_ref`, but compatible with older versions of C++ standard.
#if defined(WIN32) || defined(_WIN32) || defined(__WIN32__) || defined(__NT__)
#include <Windows.h>
#endif
namespace ashvardanian {
#if defined(WIN32) || defined(_WIN32) || defined(__WIN32__) || defined(__NT__)
/**
* @brief Tiny Fast Userspace Mutex for Windows,
* designed to fit in a single integer.
*/
class tiny_futex_t {
using slot_t = volatile LONG;
slot_t flag_;
public:
inline tiny_futex_t(slot_t flag = 0) noexcept : flag_(flag) {}
inline ~tiny_futex_t() noexcept {}
inline void unlock() noexcept { InterlockedExchange(&flag_, 0); }
inline bool try_lock() noexcept {
slot_t raw = 0;
return InterlockedCompareExchange(&flag_, 1, raw);
}
inline void lock() noexcept {
slot_t raw = 0;
InterlockedCompareExchange(&flag_, 1, raw);
}
};
#else
/**
* @brief Tiny Fast Userspace Mutex using GCC and Clang builtins,
* designed to fit in a single integer.
*/
class tiny_futex_t {
using slot_t = signed;
slot_t flag_;
public:
inline tiny_futex_t(slot_t flag = 0) noexcept : flag_(flag) {}
inline ~tiny_futex_t() noexcept {}
inline void unlock() noexcept { __atomic_store_n(&flag_, 0, __ATOMIC_RELEASE); }
inline bool try_lock() noexcept {
slot_t raw = 0;
return __atomic_compare_exchange_n(&flag_, &raw, 1, true, __ATOMIC_ACQUIRE, __ATOMIC_RELAXED);
}
inline void lock() noexcept {
slot_t raw = 0;
lock_again:
raw = 0;
if (!__atomic_compare_exchange_n(&flag_, &raw, 1, true, __ATOMIC_ACQUIRE, __ATOMIC_RELAXED))
goto lock_again;
}
};
#endif
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment