22 virtual void notify() = 0;
26void notifyScheduler(T& scheduler);
37template <
typename Clock = std::chrono::steady_clock>
51 : name(name), newEventAdded(false), quitting(false), nextID(0),
66 scheduleCV.notify_one();
79 schedule =
decltype(schedule)();
108 const std::function<
void()>& fn) {
113 auto now = Clock::now();
114 schedule.push({id, now + period, period, fn});
115 newEventAdded =
true;
117 scheduleCV.notify_one();
124 void notify()
override {
125 scheduleCV.notify_all();
132 if (name.has_value()) {
133 loguru::set_thread_name(name->c_str());
135 std::unique_lock
lock(scheduleMutex);
137 if (schedule.empty()) {
138 scheduleCV.wait(lock, [&] {
return newEventAdded; });
139 newEventAdded =
false;
141 auto now = Clock::now();
142 schedule_t
event = schedule.top();
143 if (toRemove.find(event.id) != toRemove.end()) {
146 toRemove.erase(event.id);
147 }
else if (event.nextSendTime <= now) {
151 event.nextSendTime +=
event.period;
152 schedule.push(event);
155 scheduleCV.wait_until(lock, event.nextSendTime,
156 [&] { return newEventAdded; });
157 newEventAdded =
false;
168 std::chrono::time_point<Clock> nextSendTime;
170 std::function<void()> fn;
171 friend bool operator>(
const PeriodicScheduler::schedule_t& t1,
172 const PeriodicScheduler::schedule_t& t2) {
173 return t1.nextSendTime > t2.nextSendTime;
177 std::optional<std::string> name;
183 std::priority_queue<schedule_t, std::vector<schedule_t>, std::greater<schedule_t>>
185 std::mutex scheduleMutex;
186 std::condition_variable scheduleCV;
187 std::unordered_set<eventid_t> toRemove;
201template <
typename Clock = std::chrono::steady_clock>
216 const std::function<
void()>& callback,
bool keepCallingOnDeath =
false)
217 : name(name), duration(duration), callback(callback),
218 keepCallingOnDeath(keepCallingOnDeath), fed(false), quitting(false),
232 bool keepCallingOnDeath =
false)
233 : name(
std::
nullopt), duration(duration), callback(callback),
234 keepCallingOnDeath(keepCallingOnDeath), fed(false), quitting(false),
245 if (thread.joinable()) {
266 friend void util::impl::notifyScheduler<>(
Watchdog&);
268 std::optional<std::string> name;
270 std::function<void()> callback;
271 const bool keepCallingOnDeath;
278 void notify()
override {
283 if (name.has_value()) {
284 loguru::set_thread_name(name->c_str());
286 std::unique_lock
lock(mutex);
288 std::chrono::time_point<Clock> wakeTime = Clock::now() + duration;
289 if (cv.wait_until(lock, wakeTime, [&]() { return fed || quitting; })) {
296 if (!keepCallingOnDeath) {
297 cv.wait(lock, [&]() {
return fed || quitting; });
315template <
typename Clock = std::chrono::steady_clock>
323 AsyncTask(
const std::optional<std::string>& name = std::nullopt)
324 : name(name), running(false), quitting(false) {}
330 if (thread.joinable()) {
346 if (thread.joinable()) {
372 if (thread.joinable()) {
419 return cv.wait_until(
lock, tp, [&]() {
return quitting; });
429 template <
typename Rep,
typename Period>
441 return cv.wait(
lock, [&]() {
return quitting; });
452 std::optional<std::string> name;
462 friend void util::impl::notifyScheduler<>(
AsyncTask&);
465 if (name.has_value()) {
466 loguru::set_thread_name(name->c_str());
470 RAIIHelper r([&]() { running = quitting =
false; });
483template <
typename Clock = std::chrono::steady_clock>
493 :
AsyncTask<Clock>(), period(period), f(f) {}
497 auto event = scheduler.scheduleEvent(period, f);
499 scheduler.removeEvent(event);
503 impl::notifyScheduler(scheduler);
509 std::function<void()> f;
514 friend void util::impl::notifyScheduler<>(
PeriodicTask&);
531void notifyScheduler(T& scheduler) {
532 Notifiable& n = scheduler;
_GLIBCXX_END_NAMESPACE_CXX11 typedef basic_string< char > string
_Bind_helper< __is_socketlike< _Func >::value, _Func, _BoundArgs... >::type bind(_Func &&__f, _BoundArgs &&... __args)
constexpr nullopt_t nullopt
void lock(_L1 &__l1, _L2 &__l2, _L3 &... __l3)
duration< int64_t, milli > milliseconds
An abstract class that can be overridden to run long-running tasks and encapsulate task-related data.
Definition scheduler.h:316
virtual void task(std::unique_lock< std::mutex > &lock)=0
The long-running task, overridden by client code.
bool isRunningInternal()
Version of AsyncTask::isRunning() that does no synchronization.
Definition scheduler.h:406
bool wait_for(std::unique_lock< std::mutex > &lock, const std::chrono::duration< Rep, Period > &dur)
Wait for a given duration, or until the task has been stopped.
Definition scheduler.h:430
virtual void stop()
Stop the task and wait for it to finish.
Definition scheduler.h:360
bool isRunning()
Check if the task is running.
Definition scheduler.h:383
void wait_until_done(std::unique_lock< std::mutex > &lock)
Wait until the task has been stopped.
Definition scheduler.h:440
AsyncTask(const std::optional< std::string > &name=std::nullopt)
Construct a new task.
Definition scheduler.h:323
void notify() override
Not for use by client code.
Definition scheduler.h:447
bool wait_until(std::unique_lock< std::mutex > &lock, const std::chrono::time_point< Clock > &tp)
Wait until the specified time point, or until the task has been stopped.
Definition scheduler.h:417
virtual void start()
Start the task.
Definition scheduler.h:342
Uses a single thread to periodically invoke callbacks at a given frequency.
Definition scheduler.h:38
PeriodicScheduler(const std::optional< std::string > &name=std::nullopt)
Create a new PeriodicScheduler.
Definition scheduler.h:50
uint64_t eventid_t
The type of event ids.
Definition scheduler.h:43
eventid_t scheduleEvent(std::chrono::milliseconds period, const std::function< void()> &fn)
Schedule a new event to be executed periodically.
Definition scheduler.h:107
void clear()
Clears all currently scheduled recurring events.
Definition scheduler.h:77
void removeEvent(eventid_t id)
Remove an event from the schedule.
Definition scheduler.h:92
~PeriodicScheduler()
Join the thread and destruct.
Definition scheduler.h:59
Implements a task that executes a function periodically.
Definition scheduler.h:484
void task(std::unique_lock< std::mutex > &lock) override
The long-running task, overridden by client code.
Definition scheduler.h:496
PeriodicTask(const std::chrono::milliseconds &period, const std::function< void()> &f)
Construct a new periodic task.
Definition scheduler.h:492
void notify() override
Not for use by client code.
Definition scheduler.h:502
Implements a thread-safe watchdog.
Definition scheduler.h:202
void feed()
Feed the watchdog.
Definition scheduler.h:257
Watchdog(std::chrono::milliseconds duration, const std::function< void()> &callback, bool keepCallingOnDeath=false)
Construct a new Watchdog.
Definition scheduler.h:231
Watchdog(const std::string &name, std::chrono::milliseconds duration, const std::function< void()> &callback, bool keepCallingOnDeath=false)
Construct a new Watchdog.
Definition scheduler.h:215
Definition scheduler.h:20
softfloat & operator=(const softfloat &c)
A collection of utility functions and classes with common use-cases.
Definition SwerveController.cpp:145