#pragma once #include #include #include "gp_config.hpp" namespace gp { /** * @brief CADR lock_guard for generic locking mechanisms * * @tparam T */ template class lock_guard { T& ref; public: lock_guard(T& _ref) : ref(_ref) { ref.lock(); } ~lock_guard() { ref.unlock(); } }; /** * @brief A fast mutual exclusion handler WITHOUT deadlock detection */ class fast_bottleneck { std::atomic_bool flag; public: fast_bottleneck() = default; fast_bottleneck(fast_bottleneck&) = delete; fast_bottleneck(fast_bottleneck&&) = delete; void lock() { while(not try_lock()); } [[nodiscard]] bool try_lock() { bool f = false; bool t = true; return flag.compare_exchange_strong(f,t,std::memory_order::acquire); } void unlock() { gp_config::assertion(try_unlock(), "Unlocking failed in fast_bottleneck: potential double unlocking issue"); } [[nodiscard]] bool try_unlock() { bool f = false; bool t = true; return flag.compare_exchange_strong(t,f,std::memory_order::release); } }; /** * @brief A fast semaphore exclusion handler WITHOUT deadlock detection */ template class fast_semaphore { std::atomic flag; public: fast_semaphore() = default; fast_semaphore(fast_semaphore&) = delete; fast_semaphore(fast_semaphore&&) = delete; enum class tristate { success, timing, error }; void lock_super() { auto value = flag.fetch_add(maximum_increment, std::memory_order::relaxed); while(value > maximum_increment) { value = flag.load(std::memory_order::release); } } template void lock() { while(not try_lock()); } template [[nodiscard]] bool try_lock() { T expect = flag.load(std::memory_order::relaxed); T target = expect + increment; if(target > maximum_increment) return false; return flag.compare_exchange_strong(expect,target,std::memory_order::acquire); } template void unlock() { tristate v; do{ v = try_unlock(); } while(v == tristate::timing); gp_config::assertion(v == tristate::success, "Over unlocking may have happened"); } template [[nodiscard]] tristate try_unlock() { T expect = flag.load(std::memory_order::relaxed); T target = expect - increment; if(target < 0) return tristate::error; return flag.compare_exchange_strong(expect,target,std::memory_order::release) ? tristate::success : tristate::timing; } }; }