Crow  1.1
A C++ microframework for the web
 
Loading...
Searching...
No Matches
task_timer.h
1#pragma once
2
3#ifdef CROW_USE_BOOST
4#include <boost/asio.hpp>
5#include <boost/asio/basic_waitable_timer.hpp>
6#else
7#ifndef ASIO_STANDALONE
8#define ASIO_STANDALONE
9#endif
10#include <asio.hpp>
11#include <asio/basic_waitable_timer.hpp>
12#endif
13
14#include <chrono>
15#include <functional>
16#include <map>
17#include <vector>
18
19#include "crow/logging.h"
20
21namespace crow
22{
23#ifdef CROW_USE_BOOST
24 namespace asio = boost::asio;
25 using error_code = boost::system::error_code;
26#else
27 using error_code = asio::error_code;
28#endif
29 namespace detail
30 {
31
32 /// A class for scheduling functions to be called after a specific amount of ticks. A tick is equal to 1 second.
34 {
35 public:
36 using task_type = std::function<void()>;
37 using identifier_type = size_t;
38
39 private:
40 using clock_type = std::chrono::steady_clock;
41 using time_type = clock_type::time_point;
42
43 public:
44 task_timer(asio::io_service& io_service):
45 io_service_(io_service), timer_(io_service_)
46 {
47 timer_.expires_after(std::chrono::seconds(1));
48 timer_.async_wait(
49 std::bind(&task_timer::tick_handler, this, std::placeholders::_1));
50 }
51
52 ~task_timer() { timer_.cancel(); }
53
54 void cancel(identifier_type id)
55 {
56 tasks_.erase(id);
57 CROW_LOG_DEBUG << "task_timer cancelled: " << this << ' ' << id;
58 }
59
60 /// Schedule the given task to be executed after the default amount of ticks.
61
62 ///
63 /// \return identifier_type Used to cancel the thread.
64 /// It is not bound to this task_timer instance and in some cases could lead to
65 /// undefined behavior if used with other task_timer objects or after the task
66 /// has been successfully executed.
67 identifier_type schedule(const task_type& task)
68 {
69 tasks_.insert(
70 {++highest_id_,
71 {clock_type::now() + std::chrono::seconds(get_default_timeout()),
72 task}});
73 CROW_LOG_DEBUG << "task_timer scheduled: " << this << ' ' << highest_id_;
74 return highest_id_;
75 }
76
77 /// Schedule the given task to be executed after the given time.
78
79 ///
80 /// \param timeout The amount of ticks (seconds) to wait before execution.
81 ///
82 /// \return identifier_type Used to cancel the thread.
83 /// It is not bound to this task_timer instance and in some cases could lead to
84 /// undefined behavior if used with other task_timer objects or after the task
85 /// has been successfully executed.
86 identifier_type schedule(const task_type& task, std::uint8_t timeout)
87 {
88 tasks_.insert({++highest_id_,
89 {clock_type::now() + std::chrono::seconds(timeout), task}});
90 CROW_LOG_DEBUG << "task_timer scheduled: " << this << ' ' << highest_id_;
91 return highest_id_;
92 }
93
94 /// Set the default timeout for this task_timer instance. (Default: 5)
95
96 ///
97 /// \param timeout The amount of ticks (seconds) to wait before execution.
98 void set_default_timeout(std::uint8_t timeout) { default_timeout_ = timeout; }
99
100 /// Get the default timeout. (Default: 5)
101 std::uint8_t get_default_timeout() const { return default_timeout_; }
102
103 private:
104 void process_tasks()
105 {
106 time_type current_time = clock_type::now();
107 std::vector<identifier_type> finished_tasks;
108
109 for (const auto& task : tasks_)
110 {
111 if (task.second.first < current_time)
112 {
113 (task.second.second)();
114 finished_tasks.push_back(task.first);
115 CROW_LOG_DEBUG << "task_timer called: " << this << ' ' << task.first;
116 }
117 }
118
119 for (const auto& task : finished_tasks)
120 tasks_.erase(task);
121
122 // If no task is currently scheduled, reset the issued ids back to 0.
123 if (tasks_.empty()) highest_id_ = 0;
124 }
125
126 void tick_handler(const error_code& ec)
127 {
128 if (ec) return;
129
130 process_tasks();
131
132 timer_.expires_after(std::chrono::seconds(1));
133 timer_.async_wait(
134 std::bind(&task_timer::tick_handler, this, std::placeholders::_1));
135 }
136
137 private:
138 std::uint8_t default_timeout_{5};
139 asio::io_service& io_service_;
140 asio::basic_waitable_timer<clock_type> timer_;
141 std::map<identifier_type, std::pair<time_type, task_type>> tasks_;
142
143 // A continuosly increasing number to be issued to threads to identify them.
144 // If no tasks are scheduled, it will be reset to 0.
145 identifier_type highest_id_{0};
146 };
147 } // namespace detail
148} // namespace crow
A class for scheduling functions to be called after a specific amount of ticks. A tick is equal to 1 ...
Definition task_timer.h:34
identifier_type schedule(const task_type &task, std::uint8_t timeout)
Schedule the given task to be executed after the given time.
Definition task_timer.h:86
void set_default_timeout(std::uint8_t timeout)
Set the default timeout for this task_timer instance. (Default: 5)
Definition task_timer.h:98
identifier_type schedule(const task_type &task)
Schedule the given task to be executed after the default amount of ticks.
Definition task_timer.h:67
std::uint8_t get_default_timeout() const
Get the default timeout. (Default: 5)
Definition task_timer.h:101
The main namespace of the library. In this namespace is defined the most important classes and functi...