lintel 0.2.0
Loading...
Searching...
No Matches
SchedulerService.h
Go to the documentation of this file.
1#ifndef LOGGING_SCHEDULERSERVICE_H
2#define LOGGING_SCHEDULERSERVICE_H
3
4#include <algorithm>
5#include <chrono>
6#include <functional>
7#include <future>
8#include <thread>
9#include <type_traits>// needed for decay_t and invoke_result_t
10#include <vector>
11
13
14namespace lintel {
18class SchedulerService : public PropertyRegistration<SchedulerService>
19{
20private:
22 struct Task
23 {
29 Task(std::chrono::steady_clock::time_point time, std::function<void()> func)
30 : time(time), func(std::move(func)), period(std::chrono::seconds(0))
31 {}
32
39 Task(std::chrono::steady_clock::time_point time,
40 std::function<void()> func,
41 std::chrono::steady_clock::duration period)
42 : time(time), func(std::move(func)), period(period)
43 {}
44
45 std::chrono::steady_clock::time_point time;
46 std::function<void()> func;
47 std::chrono::steady_clock::duration period;
48 };
49
50 struct TaskComperator
51 {
52 bool operator()(const Task &left, const Task &right) const { return right.time < left.time; }
53 };
54
55 std::vector<Task> m_tasks;
56 std::mutex m_mutex;
57 std::condition_variable m_conditionVariable;
58 std::atomic<bool> m_exit{ false };
59 std::vector<std::thread> m_threads;
60
61 void run();
62
63 std::shared_ptr<Property<int>> numberOfThreads;
64
65public:
74 template<class F, class... Args>
75 auto schedule(F &&f, Args &&...args) -> std::future<std::invoke_result_t<std::decay_t<F>, std::decay_t<Args>...>>;
76
86 template<class F, class... Args>
87 auto schedule_after(const std::chrono::steady_clock::duration &d, F &&f, Args &&...args)
88 -> std::future<std::invoke_result_t<std::decay_t<F>, std::decay_t<Args>...>>;
89
99 template<class F, class... Args>
100 auto schedule_at(const std::chrono::steady_clock::time_point &t, F &&f, Args &&...args)
101 -> std::future<std::invoke_result_t<std::decay_t<F>, std::decay_t<Args>...>>;
102
112 template<class F, class... Args>
113 void schedule_at_fixed_rate(const std::chrono::steady_clock::duration &d,
114 const std::chrono::steady_clock::duration &period,
115 F &&f,
116 Args &&...args);
117
119 void clear();
120
125 explicit SchedulerService(const std::shared_ptr<ProcessName> &processName);
126 void onInitialize() override;
127 void onShutdown() override;
129};
130
131// ==================== Implementations ====================
132
133template<class F, class... Args>
135 -> std::future<std::invoke_result_t<std::decay_t<F>, std::decay_t<Args>...>>
136{
137 return schedule_at(std::chrono::steady_clock::now(), std::forward<F>(f), std::forward<Args>(args)...);
138}
139
140template<class F, class... Args>
141auto SchedulerService::schedule_after(const std::chrono::steady_clock::duration &d, F &&f, Args &&...args)
142 -> std::future<std::invoke_result_t<std::decay_t<F>, std::decay_t<Args>...>>
143{
144 return schedule_at(std::chrono::steady_clock::now() + d, std::forward<F>(f), std::forward<Args>(args)...);
145}
146
147template<class F, class... Args>
148auto SchedulerService::schedule_at(const std::chrono::steady_clock::time_point &t, F &&f, Args &&...args)
149 -> std::future<std::invoke_result_t<std::decay_t<F>, std::decay_t<Args>...>>
150{
151 using ReturnType = std::invoke_result_t<std::decay_t<F>, std::decay_t<Args>...>;
152
153 auto task =
154 std::make_shared<std::packaged_task<ReturnType()>>(std::bind(std::forward<F>(f), std::forward<Args>(args)...));
155
156 auto future = task->get_future();
157
158 {
159 std::unique_lock<std::mutex> lock(m_mutex);
160 m_tasks.emplace_back(Task(t, [task = std::move(task)]() { (*task)(); }));
161 std::push_heap(m_tasks.begin(), m_tasks.end(), TaskComperator());
162 }
163
164 m_conditionVariable.notify_one();
165 return future;
166}
167
168template<class F, class... Args>
169void SchedulerService::schedule_at_fixed_rate(const std::chrono::steady_clock::duration &d,
170 const std::chrono::steady_clock::duration &period,
171 F &&f,
172 Args &&...args)
173{
174 auto bound_task = std::bind(std::forward<F>(f), std::forward<Args>(args)...);
175
176 {
177 std::unique_lock<std::mutex> lock(m_mutex);
178 m_tasks.emplace_back(Task(std::chrono::steady_clock::now() + d, std::move(bound_task), period));
179 std::push_heap(m_tasks.begin(), m_tasks.end(), TaskComperator());
180 }
181
182 m_conditionVariable.notify_one();
183}
184
185}// namespace lintel
186#endif// LOGGING_SCHEDULERSERVICE_H
Definition PropertyRegistration.h:14
Definition SchedulerService.h:19
void onShutdown() override
auto schedule_after(const std::chrono::steady_clock::duration &d, F &&f, Args &&...args) -> std::future< std::invoke_result_t< std::decay_t< F >, std::decay_t< Args >... > >
Definition SchedulerService.h:141
auto schedule_at(const std::chrono::steady_clock::time_point &t, F &&f, Args &&...args) -> std::future< std::invoke_result_t< std::decay_t< F >, std::decay_t< Args >... > >
Definition SchedulerService.h:148
SchedulerService(const std::shared_ptr< ProcessName > &processName)
void schedule_at_fixed_rate(const std::chrono::steady_clock::duration &d, const std::chrono::steady_clock::duration &period, F &&f, Args &&...args)
Definition SchedulerService.h:169
void onInitialize() override
auto schedule(F &&f, Args &&...args) -> std::future< std::invoke_result_t< std::decay_t< F >, std::decay_t< Args >... > >
Definition SchedulerService.h:134
Definition BaseFeature.h:6
constexpr std::string_view type_name()
Definition TypeName.h:9