blob: 400a3078b71792f7f7de7cfb2b66c3c1c75229c1 [file] [log] [blame]
Alex Perrycb7da4b2019-08-28 19:35:56 -07001#ifndef AOS_EVENTS_EVENT_SCHEDULER_H_
2#define AOS_EVENTS_EVENT_SCHEDULER_H_
3
4#include <algorithm>
5#include <map>
6#include <memory>
7#include <unordered_set>
8#include <utility>
9#include <vector>
10
11#include "aos/events/event_loop.h"
12#include "aos/time/time.h"
13#include "glog/logging.h"
14
15namespace aos {
16
Austin Schuhac0771c2020-01-07 18:36:30 -080017// This clock is the basis for distributed time. It is used to synchronize time
18// between multiple nodes. This is a new type so conversions to and from the
19// monotonic and realtime clocks aren't implicit.
20class distributed_clock {
21 public:
22 typedef ::std::chrono::nanoseconds::rep rep;
23 typedef ::std::chrono::nanoseconds::period period;
24 typedef ::std::chrono::nanoseconds duration;
25 typedef ::std::chrono::time_point<distributed_clock> time_point;
26
27 // This clock is the base clock for the simulation and everything is synced to
28 // it. It never jumps.
29 static constexpr bool is_steady = true;
30
31 // Returns the epoch (0).
32 static constexpr time_point epoch() { return time_point(zero()); }
33
34 static constexpr duration zero() { return duration(0); }
35
36 static constexpr time_point min_time{
37 time_point(duration(::std::numeric_limits<duration::rep>::min()))};
38 static constexpr time_point max_time{
39 time_point(duration(::std::numeric_limits<duration::rep>::max()))};
40};
41
42std::ostream &operator<<(std::ostream &stream,
43 const aos::distributed_clock::time_point &now);
44
Alex Perrycb7da4b2019-08-28 19:35:56 -070045class EventScheduler {
46 public:
47 using ChannelType =
Austin Schuhac0771c2020-01-07 18:36:30 -080048 std::multimap<distributed_clock::time_point, std::function<void()>>;
Alex Perrycb7da4b2019-08-28 19:35:56 -070049 using Token = ChannelType::iterator;
50
51 // Schedule an event with a callback function
52 // Returns an iterator to the event
Austin Schuhac0771c2020-01-07 18:36:30 -080053 Token Schedule(distributed_clock::time_point time,
Alex Perrycb7da4b2019-08-28 19:35:56 -070054 std::function<void()> callback);
55
Austin Schuh39788ff2019-12-01 18:22:57 -080056 // Schedules a callback when the event scheduler starts.
57 void ScheduleOnRun(std::function<void()> callback) {
58 on_run_.emplace_back(std::move(callback));
59 }
60
Alex Perrycb7da4b2019-08-28 19:35:56 -070061 Token InvalidToken() { return events_list_.end(); }
62
63 // Deschedule an event by its iterator
64 void Deschedule(Token token);
65
66 // Runs until exited.
67 void Run();
68 // Runs for a duration.
Austin Schuhac0771c2020-01-07 18:36:30 -080069 void RunFor(distributed_clock::duration duration);
Alex Perrycb7da4b2019-08-28 19:35:56 -070070
71 void Exit() { is_running_ = false; }
72
73 bool is_running() const { return is_running_; }
74
Austin Schuhac0771c2020-01-07 18:36:30 -080075 distributed_clock::time_point distributed_now() const { return now_; }
Alex Perrycb7da4b2019-08-28 19:35:56 -070076
77 private:
78 // Current execution time.
Austin Schuhac0771c2020-01-07 18:36:30 -080079 distributed_clock::time_point now_ = distributed_clock::epoch();
Alex Perrycb7da4b2019-08-28 19:35:56 -070080
Austin Schuh39788ff2019-12-01 18:22:57 -080081 std::vector<std::function<void()>> on_run_;
82
Alex Perrycb7da4b2019-08-28 19:35:56 -070083 // Multimap holding times to run functions. These are stored in order, and
84 // the order is the callback tree.
85 ChannelType events_list_;
86 bool is_running_ = false;
87};
88
89} // namespace aos
90
91#endif // AOS_EVENTS_EVENT_SCHEDULER_H_