|
|
- #pragma once
-
- #include <atomic>
- #include <concepts>
-
- #include "gp_config.hpp"
-
- namespace gp {
- /**
- * @brief CADR lock_guard for generic locking mechanisms
- *
- * @tparam T
- */
- template<typename T>
- 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<std::integral T, T default_increment, T maximum_increment>
- class fast_semaphore {
- std::atomic<T> 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<T increment = default_increment>
- void lock() {
- while(not try_lock<increment>());
- }
-
- template<T increment = default_increment>
- [[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<T increment = default_increment>
- void unlock() {
- tristate v;
- do{ v = try_unlock<increment>(); }
- while(v == tristate::timing);
- gp_config::assertion(v == tristate::success, "Over unlocking may have happened");
- }
-
- template<T increment = default_increment>
- [[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;
- }
- };
- }
|