Alex Perry | cb7da4b | 2019-08-28 19:35:56 -0700 | [diff] [blame] | 1 | #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 | |
| 15 | namespace aos { |
| 16 | |
Austin Schuh | ac0771c | 2020-01-07 18:36:30 -0800 | [diff] [blame^] | 17 | // 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. |
| 20 | class 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 | |
| 42 | std::ostream &operator<<(std::ostream &stream, |
| 43 | const aos::distributed_clock::time_point &now); |
| 44 | |
Alex Perry | cb7da4b | 2019-08-28 19:35:56 -0700 | [diff] [blame] | 45 | class EventScheduler { |
| 46 | public: |
| 47 | using ChannelType = |
Austin Schuh | ac0771c | 2020-01-07 18:36:30 -0800 | [diff] [blame^] | 48 | std::multimap<distributed_clock::time_point, std::function<void()>>; |
Alex Perry | cb7da4b | 2019-08-28 19:35:56 -0700 | [diff] [blame] | 49 | using Token = ChannelType::iterator; |
| 50 | |
| 51 | // Schedule an event with a callback function |
| 52 | // Returns an iterator to the event |
Austin Schuh | ac0771c | 2020-01-07 18:36:30 -0800 | [diff] [blame^] | 53 | Token Schedule(distributed_clock::time_point time, |
Alex Perry | cb7da4b | 2019-08-28 19:35:56 -0700 | [diff] [blame] | 54 | std::function<void()> callback); |
| 55 | |
Austin Schuh | 39788ff | 2019-12-01 18:22:57 -0800 | [diff] [blame] | 56 | // 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 Perry | cb7da4b | 2019-08-28 19:35:56 -0700 | [diff] [blame] | 61 | 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 Schuh | ac0771c | 2020-01-07 18:36:30 -0800 | [diff] [blame^] | 69 | void RunFor(distributed_clock::duration duration); |
Alex Perry | cb7da4b | 2019-08-28 19:35:56 -0700 | [diff] [blame] | 70 | |
| 71 | void Exit() { is_running_ = false; } |
| 72 | |
| 73 | bool is_running() const { return is_running_; } |
| 74 | |
Austin Schuh | ac0771c | 2020-01-07 18:36:30 -0800 | [diff] [blame^] | 75 | distributed_clock::time_point distributed_now() const { return now_; } |
Alex Perry | cb7da4b | 2019-08-28 19:35:56 -0700 | [diff] [blame] | 76 | |
| 77 | private: |
| 78 | // Current execution time. |
Austin Schuh | ac0771c | 2020-01-07 18:36:30 -0800 | [diff] [blame^] | 79 | distributed_clock::time_point now_ = distributed_clock::epoch(); |
Alex Perry | cb7da4b | 2019-08-28 19:35:56 -0700 | [diff] [blame] | 80 | |
Austin Schuh | 39788ff | 2019-12-01 18:22:57 -0800 | [diff] [blame] | 81 | std::vector<std::function<void()>> on_run_; |
| 82 | |
Alex Perry | cb7da4b | 2019-08-28 19:35:56 -0700 | [diff] [blame] | 83 | // 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_ |