|
|
@ -1,6 +1,7 @@ |
|
|
|
#pragma once
|
|
|
|
|
|
|
|
#include <atomic>
|
|
|
|
#include <concepts>
|
|
|
|
|
|
|
|
#include "gp_config.hpp"
|
|
|
|
|
|
|
@ -55,4 +56,57 @@ namespace gp { |
|
|
|
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; |
|
|
|
} |
|
|
|
}; |
|
|
|
} |