1#ifndef NEFORCE_CORE_ASYNC_TIMER_HPP__
2#define NEFORCE_CORE_ASYNC_TIMER_HPP__
20NEFORCE_BEGIN_NAMESPACE__
42template <
typename Clock>
47 using duration =
typename clock_type::duration;
68 node(
const node&) =
default;
69 node& operator=(
const node&) =
default;
70 node(node&&) =
default;
71 node& operator=(node&&) =
default;
78 bool operator<(
const node& other)
const {
79 if (expire < other.expire) {
82 if (expire > other.expire) {
98 atomic<bool> stopped_{
false};
100 friend class thread_pool;
112 while (!stopped_.load()) {
113 unique_lock<mutex> lock(mutex_);
115 if (nodes_.
empty()) {
116 cv_.
wait_for(lock, 500_ms, [
this] {
return stopped_.load() || !nodes_.
empty(); });
117 if (stopped_.load()) {
122 time_point now = clock_type::now();
123 while (!nodes_.
empty() && nodes_.
begin()->expire <= now) {
124 auto it = nodes_.
begin();
125 node current_node = *it;
127 node_map_.
erase(current_node.id);
129 auto flag_it = cancel_flags_.
find(current_node.id);
130 const bool cancelled = (flag_it != cancel_flags_.
end() && flag_it->second->load(memory_order_acquire));
133 if (!stopped_.load() && !cancelled) {
134 current_node.handler();
138 cancel_flags_.
erase(current_node.id);
139 promises_.
erase(current_node.id);
140 now = clock_type::now();
143 if (!nodes_.
empty()) {
144 auto expire_time = nodes_.
begin()->expire;
146 return stopped_.load(memory_order_acquire) || nodes_.
empty() ||
147 nodes_.
begin()->expire <= clock_type::now();
168 stopped_.store(
true);
170 if (thread_.joinable()) {
190 token id = next_id_++;
201 const bool is_earliest = nodes_.empty() || expire < nodes_.begin()->expire;
203 node new_node(expire,
id, _NEFORCE
move(wrapped));
204 auto result = nodes_.insert(new_node);
205 node_map_[id] = result.first;
206 cancel_flags_[id] =
move(flag);
226 const auto flag_it = cancel_flags_.find(
id);
227 if (flag_it == cancel_flags_.end()) {
232 auto node_it = node_map_.find(
id);
233 if (node_it != node_map_.end()) {
234 const bool is_earliest = (node_it->second == nodes_.begin());
235 nodes_.erase(node_it->second);
236 node_map_.erase(node_it);
242 cancel_flags_.erase(flag_it);
245 const auto prom_it = promises_.find(
id);
247 if (prom_it != promises_.end()) {
248 prom = prom_it->second;
249 promises_.erase(prom_it);
254 prom->get_future().wait();
266 for (
const auto& cancel_flag: cancel_flags_) {
271 cancel_flags_.clear();
280 NEFORCE_NODISCARD
size_t size()
const {
282 return nodes_.size();
292 return node_map_.find(
id) != node_map_.end();
304template <
typename Clock>
320 scheduler_(make_shared<timer_scheduler<Clock>>()) {}
338 scheduler_(_NEFORCE
move(other.scheduler_)),
339 task_id_(other.task_id_),
340 expire_(other.expire_) {
353 scheduler_ = _NEFORCE
move(other.scheduler_);
354 task_id_ = other.task_id_;
355 expire_ = other.expire_;
369 expire_ = expiry_time;
399 NEFORCE_NODISCARD
bool is_active()
const {
return task_id_ != 0 && scheduler_ && scheduler_->is_pending(task_id_); }
409 template <
typename WaitHandler>
421 if (scheduler_ && task_id_ != 0) {
422 scheduler_->cancel(task_id_);
442NEFORCE_END_NAMESPACE__
typename clock_type::time_point time_point
时间点类型
time_point expiry() const
获取到期时间点
basic_timer & operator=(basic_timer &&other) noexcept
移动赋值运算符
basic_timer(basic_timer &&other) noexcept
移动构造函数
typename clock_type::duration duration
时长类型
~basic_timer()
析构函数,自动取消未完成的任务
void expires_from_now(const int64_t ms)
设置从当前时间开始的毫秒数
void async_wait(WaitHandler &&handler)
异步等待定时器到期
typename timer_scheduler< Clock >::handler_type handler_type
回调函数类型
void expires_at(const time_point &expiry_time)
设置绝对到期时间
bool is_active() const
检查定时器是否活跃(有待执行的任务)
typename timer_scheduler< Clock >::token token
任务标识符类型
void expires_after(const duration &expiry_duration)
设置相对到期时间
cv_status wait_until(unique_lock< mutex > &lock, const time_point< steady_clock, Dur > &util)
等待直到稳定时钟时间点
cv_status wait_for(unique_lock< mutex > &lock, const duration< Rep, Period > &rest)
等待指定的持续时间
iterator end() noexcept
获取结束迭代器
iterator find(const key_type &key)
查找具有指定键的元素
void erase(iterator position) noexcept(noexcept(tree_.erase(position)))
删除指定位置的元素
void set_value(Res value)
设置结果值
iterator begin() noexcept
获取起始迭代器
void erase(iterator position) noexcept(noexcept(tree_.erase(position)))
删除指定位置的元素
bool empty() const noexcept
检查是否为空
void cancel_all()
取消所有定时任务
token add_task(time_point expire, handler_type &&handler)
添加定时任务
typename clock_type::duration duration
时长类型
size_t size() const
获取当前待处理的任务数量
~timer_scheduler()
析构函数,停止调度线程并等待其结束
timer_scheduler()
构造函数,启动调度线程
bool is_pending(token id) const
检查任务是否仍在等待或执行中
function< void()> handler_type
回调函数类型
bool cancel(token id)
取消定时任务
typename clock_type::time_point time_point
时间点类型
constexpr T * addressof(T &x) noexcept
获取对象的地址
constexpr T && forward(remove_reference_t< T > &x) noexcept
完美转发左值
basic_timer< system_clock > system_timer
基于系统时钟的定时器
basic_timer< steady_clock > steady_timer
基于稳定时钟的定时器
duration< int64_t, milli > milliseconds
毫秒持续时间
constexpr auto memory_order_release
释放内存顺序常量
constexpr auto memory_order_acquire
获取内存顺序常量
enable_if_t<!is_unbounded_array_v< T > &&is_constructible_v< T, Args... >, shared_ptr< T > > make_shared(Args &&... args)
融合分配创建共享指针
constexpr Iterator2 move(Iterator1 first, Iterator1 last, Iterator2 result) noexcept(noexcept(inner::__move_aux(first, last, result)))
移动范围元素
static time_point now() noexcept
获取当前时间点