Skip to content

Instantly share code, notes, and snippets.

@edimetia3d
Last active March 23, 2022 03:34
Show Gist options
  • Save edimetia3d/02a531bbf7b0e9c83e9e352a735c87fb to your computer and use it in GitHub Desktop.
Save edimetia3d/02a531bbf7b0e9c83e9e352a735c87fb to your computer and use it in GitHub Desktop.
A lock-free user space "mutex" implemented by std
#include <condition_variable>
#include <mutex>
#include <atomic>
/**
* A lock-free user space "mutex" implemented by std
*
* The core idea is very simple:
* 1. when there is no contention, we use atomic release/acquire synchronization to do a lock-free lock/unlock.
* 2. when there is contention, we use the syscall lock/unlock.
*
* Note:
* cpp20 introduced `wait` `notify_one` `notify_all` to atomic types, it might be better than condition variable.
*/
class Futex {
private:
std::atomic<int> m_counter{0};
std::mutex mutex;
std::condition_variable cv;
public:
void lock() {
if (m_counter.fetch_add(1, std::memory_order_acquire) > 0) {
std::unique_lock<std::mutex> lock(mutex);
// std::cout << "Non-lock-free wait" << std::endl;
cv.wait(lock);
// std::cout << "Non-lock-free locked" << std::endl;
} else {
// std::cout << "lock-free locked" << std::endl;
}
}
void unlock() {
if (m_counter.fetch_add(-1, std::memory_order_release) == 1) {
// std::cout << "lock-free unlocked" << std::endl;
} else {
std::unique_lock<std::mutex> lock(mutex);
cv.notify_one();
// std::cout << "Non-lock-free unlocked" << std::endl;
}
}
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment