1#ifndef MSTL_CORE_ASYNC_TIMER_HPP__
2#define MSTL_CORE_ASYNC_TIMER_HPP__
3#include "../container/map.hpp"
4#include "../container/set.hpp"
11template <
typename Clock>
12class timer_scheduler {
14 using clock_type = Clock;
15 using time_point =
typename clock_type::time_point;
16 using duration =
typename clock_type::duration;
18 using handler_type =
_MSTL function<void()>;
26 node(time_point exp,
const token tid, handler_type&& h)
30 if (expire < other.expire)
return true;
31 if (expire > other.expire)
return false;
36 _MSTL set<node> nodes_;
37 _MSTL map<token, typename _MSTL set<node>::iterator> node_map_;
41 _MSTL condition_variable cv_;
45 friend class thread_pool;
49 while (!stopped_.load()) {
53 cv_.wait(lock, [
this] {
54 return stopped_.load() || !nodes_.empty();
56 if (stopped_.load())
break;
59 time_point now = clock_type::now();
60 while (!nodes_.empty() && nodes_.begin()->expire <= now) {
61 auto it = nodes_.begin();
62 node current_node = *it;
64 node_map_.erase(current_node.id);
67 if (!stopped_.load()) {
68 current_node.handler();
71 now = clock_type::now();
74 if (!nodes_.empty()) {
75 time_point next_expire = nodes_.begin()->expire;
76 cv_.wait_until(lock, next_expire);
82 timer_scheduler() : next_id_(0), stopped_(false) {
83 thread_ =
_MSTL thread(&timer_scheduler::run,
this);
89 if (thread_.joinable()) {
94 timer_scheduler(
const timer_scheduler&) =
delete;
95 timer_scheduler& operator =(
const timer_scheduler&) =
delete;
96 timer_scheduler(timer_scheduler&&) =
default;
97 timer_scheduler& operator =(timer_scheduler&&) =
default;
99 token add_task(time_point expire, handler_type&& handler) {
101 token
id = next_id_++;
103 const bool is_earliest = nodes_.empty() || expire < nodes_.begin()->expire;
105 node new_node(expire,
id,
_MSTL move(handler));
106 auto result = nodes_.insert(new_node);
107 node_map_[
id] = result.first;
118 bool cancel(token
id) {
120 auto it_map = node_map_.find(
id);
121 if (it_map == node_map_.end()) {
125 const bool is_earliest = (it_map->second == nodes_.begin());
126 nodes_.erase(it_map->second);
127 node_map_.erase(it_map);
146 MSTL_NODISCARD
size_t size()
const {
147 _MSTL lock<_MSTL mutex> lock(
const_cast<_MSTL mutex&
>(mutex_));
148 return nodes_.size();
153template <
typename Clock>
156 using clock_type = Clock;
157 using time_point =
typename clock_type::time_point;
158 using duration =
typename clock_type::duration;
159 using token =
typename timer_scheduler<Clock>::token;
160 using handler_type =
typename timer_scheduler<Clock>::handler_type;
163 timer_scheduler<Clock> scheduler_{};
165 time_point expire_ = clock_type::now();
168 basic_timer() =
default;
169 ~basic_timer() { cancel(); }
171 basic_timer(
const basic_timer&) =
delete;
172 basic_timer& operator =(
const basic_timer&) =
delete;
174 basic_timer(basic_timer&& other) noexcept
175 : scheduler_(other.scheduler_)
176 , task_id_(other.task_id_)
177 , expire_(other.expire_) {
181 basic_timer& operator =(basic_timer&& other)
noexcept {
182 if (
this != &other) {
184 task_id_ = other.task_id_;
185 expire_ = other.expire_;
191 void expires_at(
const time_point& expiry_time) {
193 expire_ = expiry_time;
196 void expires_after(
const duration& expiry_duration) {
198 expire_ = clock_type::now() + expiry_duration;
205 MSTL_NODISCARD time_point expiry()
const {
return expire_; }
206 MSTL_NODISCARD
bool is_active()
const {
return task_id_ != 0; }
208 template <
typename WaitHandler>
209 void async_wait(WaitHandler&& handler) {
211 task_id_ = scheduler_.add_task(expire_,
217 scheduler_.cancel(task_id_);
223using steady_timer = basic_timer<steady_clock>;
224using system_timer = basic_timer<system_clock>;
MSTL_NODISCARD constexpr T && forward(remove_reference_t< T > &x) noexcept
完美转发左值
atomic< bool > atomic_bool
布尔原子类型
long long int64_t
64位有符号整数类型
duration< int64_t, milli > milliseconds
毫秒持续时间
lock< Mutex, true > smart_lock
智能锁管理器的便捷类型别名
#define _MSTL
全局命名空间MSTL前缀
#define MSTL_END_NAMESPACE__
结束全局命名空间MSTL
#define MSTL_BEGIN_NAMESPACE__
开始全局命名空间MSTL
MSTL_NODISCARD constexpr bool operator<(const normal_iterator< LeftIter > &lhs, const normal_iterator< RightIter > &rhs) noexcept
小于比较运算符
constexpr Iterator2 move(Iterator1 first, Iterator1 last, Iterator2 result)
移动范围元素
MSTL_ALWAYS_INLINE_INLINE thread::id id() noexcept
获取当前线程标识符
MSTL_NODISCARD MSTL_ALWAYS_INLINE constexpr decltype(auto) size(const Container &cont) noexcept(noexcept(cont.size()))
获取容器的大小