Created
May 24, 2023 14:06
-
-
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.
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
#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