#include "pls/internal/base/swmr_spin_lock.h" #include "pls/internal/base/system_details.h" namespace pls { namespace internal { namespace base { bool swmr_spin_lock::reader_try_lock() { PROFILE_LOCK("Try Acquire Read Lock") if (write_request_.load(std::memory_order_relaxed) == 1) { return false; } // We think we can enter the region readers_.fetch_add(1, std::memory_order_acquire); if (write_request_.load() == 1) { // Whoops, the writer acquires the lock, so we back off again readers_--; return false; } return true; } void swmr_spin_lock::reader_unlock() { PROFILE_LOCK("Release Read Lock") readers_.fetch_add(-1, std::memory_order_release); } void swmr_spin_lock::writer_lock() { PROFILE_LOCK("Acquire Write Lock") // Tell the readers that we would like to write int expected; while (true) { expected = 0; if (write_request_.compare_exchange_weak(expected, 1, std::memory_order_acquire)) { break; } system_details::relax_cpu(); // Spin until WE set the write lock flag } // Wait for all of them to exit the critical section while (readers_.load() > 0) system_details::relax_cpu(); // Spin, not expensive as relaxed load } void swmr_spin_lock::writer_unlock() { PROFILE_LOCK("Release Write Lock") write_request_.store(0, std::memory_order_release); } } } }