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()) {
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);
130 if (!stopped_.load()) {
131 current_node.handler();
135 cancel_flags_.erase(current_node.id);
136 promises_.erase(current_node.id);
137 now = clock_type::now();
140 if (!nodes_.empty()) {
141 auto expire_time = nodes_.begin()->expire;
142 cv_.wait_until(lock, expire_time, [
this] {
144 nodes_.begin()->expire <= clock_type::now();
160 stopped_.store(
true);
162 if (thread_.joinable()) {
182 token id = next_id_++;
193 const bool is_earliest = nodes_.empty() || expire < nodes_.begin()->expire;
195 node new_node(expire,
id, _NEFORCE
move(wrapped));
196 auto result = nodes_.insert(new_node);
197 node_map_[
id] = result.first;
198 cancel_flags_[
id] =
move(flag);
218 const auto flag_it = cancel_flags_.find(
id);
219 if (flag_it == cancel_flags_.end()) {
224 auto node_it = node_map_.find(
id);
225 if (node_it != node_map_.end()) {
226 const bool is_earliest = (node_it->second == nodes_.begin());
227 nodes_.erase(node_it->second);
228 node_map_.erase(node_it);
234 cancel_flags_.erase(flag_it);
237 const auto prom_it = promises_.find(
id);
239 if (prom_it != promises_.end()) {
240 prom = prom_it->second;
241 promises_.erase(prom_it);
246 prom->get_future().wait();
258 for (
auto& cancel_flag: cancel_flags_) {
263 cancel_flags_.clear();
272 NEFORCE_NODISCARD
size_t size()
const {
274 return nodes_.size();
284 return node_map_.find(
id) != node_map_.end();
296template <
typename Clock>
312 scheduler_(
make_shared<timer_scheduler<Clock>>()) {}
330 scheduler_(_NEFORCE
move(other.scheduler_)),
331 task_id_(other.task_id_),
332 expire_(other.expire_) {
345 scheduler_ = _NEFORCE
move(other.scheduler_);
346 task_id_ = other.task_id_;
347 expire_ = other.expire_;
361 expire_ = expiry_time;
391 NEFORCE_NODISCARD
bool is_active()
const {
return task_id_ != 0 && scheduler_ && scheduler_->is_pending(task_id_); }
401 template <
typename WaitHandler>
413 if (scheduler_ && task_id_ != 0) {
414 scheduler_->cancel(task_id_);
434NEFORCE_END_NAMESPACE__
void expires_from_now(const int64_t ms)
设置从当前时间开始的毫秒数
void async_wait(WaitHandler &&handler)
异步等待定时器到期
void expires_after(const duration &expiry_duration)
设置相对到期时间
void expires_at(const time_point &expiry_time)
设置绝对到期时间
typename timer_scheduler< Clock >::token token
任务标识符类型
typename timer_scheduler< Clock >::handler_type handler_type
回调函数类型
typename clock_type::duration duration
时长类型
basic_timer & operator=(basic_timer &&other) noexcept
移动赋值运算符
basic_timer(basic_timer &&other) noexcept
移动构造函数
~basic_timer()
析构函数,自动取消未完成的任务
typename clock_type::time_point time_point
时间点类型
time_point expiry() const
获取到期时间点
bool is_active() const
检查定时器是否活跃(有待执行的任务)
void set_value(Res value)
设置结果值
typename clock_type::time_point time_point
时间点类型
bool is_pending(token id) const
检查任务是否仍在等待或执行中
timer_scheduler()
构造函数,启动调度线程
~timer_scheduler()
析构函数,停止调度线程并等待其结束
typename clock_type::duration duration
时长类型
bool cancel(token id)
取消定时任务
size_t size() const
获取当前待处理的任务数量
void cancel_all()
取消所有定时任务
token add_task(time_point expire, handler_type &&handler)
添加定时任务
function< void()> handler_type
回调函数类型
constexpr T && forward(remove_reference_t< T > &x) noexcept
完美转发左值
constexpr T * addressof(T &x) noexcept
获取对象的地址
basic_timer< system_clock > system_timer
基于系统时钟的定时器
basic_timer< steady_clock > steady_timer
基于稳定时钟的定时器
long long int64_t
64位有符号整数类型
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)))
移动范围元素
thread::id id() noexcept
获取当前线程标识符
static time_point now() noexcept
获取当前时间点