NexusForce 1.0.0
A Modern C++ Library with extended functionality, web components, and utility libraries
载入中...
搜索中...
未找到
timer.hpp
浏览该文件的文档.
1#ifndef NEFORCE_CORE_ASYNC_TIMER_HPP__
2#define NEFORCE_CORE_ASYNC_TIMER_HPP__
3
11
18NEFORCE_BEGIN_NAMESPACE__
19
25
31
40template <typename Clock>
42public:
43 using clock_type = Clock;
44 using time_point = typename clock_type::time_point;
45 using duration = typename clock_type::duration;
46 using token = size_t;
47 using handler_type = function<void()>;
48
49private:
56 struct node {
57 time_point expire;
58 token id;
59 handler_type handler;
60
61 node(time_point exp, const token tid, handler_type&& h) :
62 expire(exp),
63 id(tid),
64 handler(move(h)) {}
65
66 node(const node&) = default;
67 node& operator=(const node&) = default;
68 node(node&&) = default;
69 node& operator=(node&&) = default;
70
74 bool operator<(const node& other) const {
75 if (expire < other.expire) {
76 return true;
77 }
78 if (expire > other.expire) {
79 return false;
80 }
81 return id < other.id;
82 }
83 };
84
85 set<node> nodes_;
87
88 thread thread_;
89 mutable mutex mutex_;
91 token next_id_;
92 atomic<bool> stopped_;
93
94 friend class thread_pool;
95
96private:
105 void run() {
106 while (!stopped_.load()) {
107 unique_lock<mutex> lock(mutex_);
108
109 if (nodes_.empty()) {
110 cv_.wait(lock, [this] { return stopped_.load() || !nodes_.empty(); });
111 if (stopped_.load()) {
112 break;
113 }
114 }
115
116 time_point now = clock_type::now();
117 while (!nodes_.empty() && nodes_.begin()->expire <= now) {
118 auto it = nodes_.begin();
119 node current_node = *it;
120 nodes_.erase(it);
121 node_map_.erase(current_node.id);
122
123 lock.unlock_quiet();
124 if (!stopped_.load()) {
125 current_node.handler();
126 }
127 lock.lock_quiet();
128 now = clock_type::now();
129 }
130
131 if (!nodes_.empty()) {
132 time_point next_expire = nodes_.begin()->expire;
133 cv_.wait_until(lock, next_expire);
134 }
135 }
136 }
137
138public:
143 next_id_(0),
144 stopped_(false) {
145 thread_ = thread(&timer_scheduler::run, this);
146 }
147
152 stopped_.store(true);
153 cv_.notify_one();
154 if (thread_.joinable()) {
155 thread_.join();
156 }
157 }
158
159 timer_scheduler(const timer_scheduler&) = delete;
160 timer_scheduler& operator=(const timer_scheduler&) = delete;
161 timer_scheduler(timer_scheduler&&) = default;
162 timer_scheduler& operator=(timer_scheduler&&) = default;
163
173 unique_lock<mutex> lock(mutex_);
174 token id = next_id_++;
175
176 const bool is_earliest = nodes_.empty() || expire < nodes_.begin()->expire;
177
178 node new_node(expire, id, _NEFORCE move(handler));
179 auto result = nodes_.insert(new_node);
180 node_map_[id] = result.first;
181
182 lock.unlock_quiet();
183
184 if (is_earliest) {
185 cv_.notify_one();
186 }
187
188 return id;
189 }
190
198 bool cancel(token id) {
199 unique_lock<mutex> lock(mutex_);
200 auto it_map = node_map_.find(id);
201 if (it_map == node_map_.end()) {
202 return false;
203 }
204
205 const bool is_earliest = (it_map->second == nodes_.begin());
206 nodes_.erase(it_map->second);
207 node_map_.erase(it_map);
208
209 lock.unlock_quiet();
210
211 if (is_earliest) {
212 cv_.notify_one();
213 }
214
215 return true;
216 }
217
221 void cancel_all() {
222 unique_lock<mutex> lock(mutex_);
223 nodes_.clear();
224 node_map_.clear();
225 lock.unlock_quiet();
226 cv_.notify_one();
227 }
228
233 NEFORCE_NODISCARD size_t size() const {
234 lock<mutex> lock(mutex_);
235 return nodes_.size();
236 }
237};
238
247template <typename Clock>
248class basic_timer {
249public:
250 using clock_type = Clock;
251 using time_point = typename clock_type::time_point;
252 using duration = typename clock_type::duration;
255
256private:
257 timer_scheduler<Clock> scheduler_{};
258 token task_id_ = 0;
259 time_point expire_ = clock_type::now();
260
261public:
262 basic_timer() = default;
263
268
269 basic_timer(const basic_timer&) = delete;
270 basic_timer& operator=(const basic_timer&) = delete;
271
275 basic_timer(basic_timer&& other) noexcept :
276 scheduler_(other.scheduler_),
277 task_id_(other.task_id_),
278 expire_(other.expire_) {
279 other.task_id_ = 0;
280 }
281
285 basic_timer& operator=(basic_timer&& other) noexcept {
286 if (addressof(other) == this) {
287 return *this;
288 }
289
290 cancel();
291 task_id_ = other.task_id_;
292 expire_ = other.expire_;
293 other.task_id_ = 0;
294
295 return *this;
296 }
297
304 void expires_at(const time_point& expiry_time) {
305 cancel();
306 expire_ = expiry_time;
307 }
308
315 void expires_after(const duration& expiry_duration) {
316 cancel();
317 expire_ = clock_type::now() + expiry_duration;
318 }
319
325
330 NEFORCE_NODISCARD time_point expiry() const { return expire_; }
331
336 NEFORCE_NODISCARD bool is_active() const { return task_id_ != 0; }
337
346 template <typename WaitHandler>
347 void async_wait(WaitHandler&& handler) {
348 cancel();
349 task_id_ = scheduler_.add_task(expire_, handler_type(_NEFORCE forward<WaitHandler>(handler)));
350 }
351
357 void cancel() {
358 if (task_id_ != 0) {
359 scheduler_.cancel(task_id_);
360 task_id_ = 0;
361 }
362 }
363};
364
369
374 // AsyncTimer
376 // AsyncComponents
378
379NEFORCE_END_NAMESPACE__
380#endif // NEFORCE_CORE_ASYNC_TIMER_HPP__
原子类型完整实现
基本定时器
void expires_from_now(const int64_t ms)
设置从当前时间开始的毫秒数
NEFORCE_NODISCARD time_point expiry() const
获取到期时间点
void async_wait(WaitHandler &&handler)
异步等待定时器到期
void expires_after(const duration &expiry_duration)
设置相对到期时间
void expires_at(const time_point &expiry_time)
设置绝对到期时间
NEFORCE_NODISCARD bool is_active() const
检查定时器是否活跃(有待执行的任务)
void cancel()
取消定时任务
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
移动赋值运算符
Clock clock_type
时钟类型
basic_timer(basic_timer &&other) noexcept
移动构造函数
~basic_timer()
析构函数,自动取消未完成的任务
typename clock_type::time_point time_point
时间点类型
void wait(unique_lock< mutex > &lock)
无限期等待
函数包装器主模板声明
锁管理器模板
映射容器
定义 map.hpp:37
非递归互斥锁
集合容器
NEFORCE_NODISCARD bool empty() const noexcept
检查是否为空
线程类
定时任务调度器
size_t token
任务标识符类型
typename clock_type::time_point time_point
时间点类型
timer_scheduler()
构造函数,启动调度线程
~timer_scheduler()
析构函数,停止调度线程并等待其结束
Clock clock_type
时钟类型
typename clock_type::duration duration
时长类型
NEFORCE_NODISCARD size_t size() const
获取当前待处理的任务数量
bool cancel(token id)
取消定时任务
void cancel_all()
取消所有定时任务
token add_task(time_point expire, handler_type &&handler)
添加定时任务
function< void()> handler_type
回调函数类型
独占锁管理器模板
条件变量行为
集合容器
通用函数包装器
NEFORCE_NODISCARD constexpr T * addressof(T &x) noexcept
获取对象的地址
NEFORCE_NODISCARD constexpr T && forward(remove_reference_t< 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
毫秒持续时间
NEFORCE_NODISCARD constexpr bool operator<(const normal_iterator< LeftIter > &lhs, const normal_iterator< RightIter > &rhs) noexcept
小于比较运算符
uint64_t size_t
无符号大小类型
constexpr Iterator2 move(Iterator1 first, Iterator1 last, Iterator2 result) noexcept(noexcept(inner::__move_aux(first, last, result)))
移动范围元素
NEFORCE_ALWAYS_INLINE_INLINE thread::id id() noexcept
获取当前线程标识符
映射容器
通用原子类型模板
T load(const memory_order mo=memory_order_seq_cst) const noexcept
原子加载操作
static time_point now() noexcept
获取当前时间点
时间点类模板
线程管理类