136 lines
4.8 KiB
C++
136 lines
4.8 KiB
C++
#pragma once
|
|
#include <string_view>
|
|
#include "global.h"
|
|
template <typename Mutex_Type = std::mutex>
|
|
class Frequency_Limit_T {
|
|
public:
|
|
explicit Frequency_Limit_T(double times_per_second = 1.0) : interval(1.0 / times_per_second),
|
|
last(std::chrono::steady_clock::now()) {
|
|
}
|
|
bool test() {
|
|
using namespace std::chrono;
|
|
std::lock_guard<std::mutex> lock(mtx);
|
|
auto now = steady_clock::now();
|
|
double dt = duration_cast<microseconds>(now - last).count() * 1e-6;
|
|
if (dt >= interval) {
|
|
last = now;
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
private:
|
|
double interval;
|
|
std::chrono::steady_clock::time_point last;
|
|
Mutex_Type mtx;
|
|
};
|
|
using Frequency_Limit_ST = Frequency_Limit_T<Psc::Empty_Lock>;
|
|
using Frequency_Limit = Frequency_Limit_T<std::mutex>;
|
|
template <typename State_Type = std::monostate, typename Mutex_Type = std::mutex>
|
|
class Frequency_Limit_Multi_T {
|
|
public:
|
|
using Clock = std::chrono::steady_clock;
|
|
struct Type_Info {
|
|
double interval{};
|
|
Clock::time_point last{};
|
|
[[no_unique_address]] State_Type state{};
|
|
};
|
|
explicit Frequency_Limit_Multi_T(double default_times_per_second = 1.0) : default_interval_(1.0 / default_times_per_second) {
|
|
}
|
|
void set_rate(std::string_view type, double times_per_second) {
|
|
std::lock_guard<Mutex_Type> lock(mtx_);
|
|
map_[std::string(type)].interval = 1.0 / times_per_second;
|
|
}
|
|
bool test(std::string_view type) {
|
|
return test_ex(type);
|
|
}
|
|
State_Type* test_ex(std::string_view type) {
|
|
const auto now = Clock::now();
|
|
std::lock_guard<Mutex_Type> lock(mtx_);
|
|
auto& info = map_[std::string(type)];
|
|
if (info.interval == 0.0) {
|
|
info.interval = default_interval_;
|
|
info.last = now;
|
|
return &info.state;
|
|
}
|
|
const double dt = std::chrono::duration<double>(now - info.last).count();
|
|
if (dt < info.interval) {
|
|
return nullptr;
|
|
}
|
|
info.last = now;
|
|
return &info.state;
|
|
}
|
|
State_Type* get_state(std::string_view type) {
|
|
std::lock_guard<Mutex_Type> lock(mtx_);
|
|
auto& info = map_[std::string(type)];
|
|
return &info.state;
|
|
}
|
|
private:
|
|
double default_interval_;
|
|
std::map<std::string, Type_Info> map_;
|
|
Mutex_Type mtx_;
|
|
};
|
|
using Frequency_Limit_Multi_ST = Frequency_Limit_Multi_T<Psc::Empty_Lock>;
|
|
using Frequency_Limit_Multi = Frequency_Limit_Multi_T<std::mutex>;
|
|
template <typename Value_Type = std::size_t, typename State_Type = std::monostate, typename Mutex_Type = std::mutex>
|
|
class Value_Growth_Multi_T {
|
|
public:
|
|
struct Type_Info {
|
|
std::size_t required_increase_count{};
|
|
Value_Type last_value{};
|
|
std::size_t increase_count{};
|
|
bool initialized{};
|
|
[[no_unique_address]] State_Type state{};
|
|
};
|
|
explicit Value_Growth_Multi_T(std::size_t default_required_increase_count = 5) : default_required_increase_count_(default_required_increase_count) {
|
|
}
|
|
void set_count(std::string_view type, std::size_t required_increase_count) {
|
|
std::lock_guard<Mutex_Type> lock(mtx_);
|
|
auto& info = map_[std::string(type)];
|
|
info.required_increase_count = required_increase_count;
|
|
info.initialized = false;
|
|
info.increase_count = 0;
|
|
}
|
|
bool test(std::string_view type, Value_Type value) {
|
|
return test_ex(type, value);
|
|
}
|
|
State_Type* test_ex(std::string_view type, Value_Type value) {
|
|
std::lock_guard<Mutex_Type> lock(mtx_);
|
|
auto& info = map_[std::string(type)];
|
|
if (info.required_increase_count == 0) {
|
|
info.required_increase_count = default_required_increase_count_;
|
|
}
|
|
if (!info.initialized) {
|
|
info.last_value = value;
|
|
info.initialized = true;
|
|
return nullptr;
|
|
}
|
|
if (value <= info.last_value) {
|
|
info.last_value = value;
|
|
info.increase_count = 0;
|
|
return nullptr;
|
|
}
|
|
info.last_value = value;
|
|
if (info.increase_count < info.required_increase_count) {
|
|
++info.increase_count;
|
|
}
|
|
if (info.increase_count < info.required_increase_count) {
|
|
return nullptr;
|
|
}
|
|
return &info.state;
|
|
}
|
|
State_Type* get_state(std::string_view type) {
|
|
std::lock_guard<Mutex_Type> lock(mtx_);
|
|
return &map_[std::string(type)].state;
|
|
}
|
|
void reset(std::string_view type) {
|
|
std::lock_guard<Mutex_Type> lock(mtx_);
|
|
auto& info = map_[std::string(type)];
|
|
info.initialized = false;
|
|
info.increase_count = 0;
|
|
}
|
|
private:
|
|
std::size_t default_required_increase_count_;
|
|
std::map<std::string, Type_Info> map_;
|
|
Mutex_Type mtx_;
|
|
};
|