Parker Schuh | e4a70d6 | 2017-12-27 20:10:20 -0800 | [diff] [blame] | 1 | #ifndef _AOS_EVENTS_RAW_EVENT_LOOP_H_ |
| 2 | #define _AOS_EVENTS_RAW_EVENT_LOOP_H_ |
| 3 | |
| 4 | #include <atomic> |
| 5 | #include <memory> |
| 6 | #include <string> |
John Park | 33858a3 | 2018-09-28 23:05:48 -0700 | [diff] [blame] | 7 | #include "aos/queue.h" |
| 8 | #include "aos/time/time.h" |
Parker Schuh | e4a70d6 | 2017-12-27 20:10:20 -0800 | [diff] [blame] | 9 | |
| 10 | // This file contains raw versions of the classes in event-loop.h. |
| 11 | // |
| 12 | // Users should look exclusively at event-loop.h. Only people who wish to |
| 13 | // implement a new IPC layer (like a fake layer for example) may wish to use |
| 14 | // these classes. |
| 15 | namespace aos { |
| 16 | |
| 17 | // Raw version of fetcher. Contains a local variable that the fetcher will |
| 18 | // update. |
| 19 | // It is the job of the typed version to cast this to the appropriate type. |
| 20 | class RawFetcher { |
| 21 | public: |
Parker Schuh | e4a70d6 | 2017-12-27 20:10:20 -0800 | [diff] [blame] | 22 | RawFetcher() {} |
| 23 | virtual ~RawFetcher() {} |
| 24 | |
James Kuszmaul | c79768b | 2019-02-18 15:08:44 -0800 | [diff] [blame] | 25 | // Non-blocking fetch of the next message in the queue. Returns true if there |
| 26 | // was a new message and we got it. |
| 27 | virtual bool FetchNext() = 0; |
| 28 | // Non-blocking fetch of the latest message: |
Parker Schuh | e4a70d6 | 2017-12-27 20:10:20 -0800 | [diff] [blame] | 29 | virtual bool Fetch() = 0; |
| 30 | |
James Kuszmaul | af04d73 | 2019-10-06 21:51:55 -0700 | [diff] [blame] | 31 | const void *most_recent() { return most_recent_; } |
Parker Schuh | e4a70d6 | 2017-12-27 20:10:20 -0800 | [diff] [blame] | 32 | |
| 33 | protected: |
| 34 | RawFetcher(const RawFetcher &) = delete; |
| 35 | RawFetcher &operator=(const RawFetcher &) = delete; |
James Kuszmaul | af04d73 | 2019-10-06 21:51:55 -0700 | [diff] [blame] | 36 | void set_most_recent(const void *most_recent) { most_recent_ = most_recent; } |
Parker Schuh | e4a70d6 | 2017-12-27 20:10:20 -0800 | [diff] [blame] | 37 | |
| 38 | private: |
James Kuszmaul | af04d73 | 2019-10-06 21:51:55 -0700 | [diff] [blame] | 39 | const void *most_recent_ = nullptr; |
Parker Schuh | e4a70d6 | 2017-12-27 20:10:20 -0800 | [diff] [blame] | 40 | }; |
| 41 | |
| 42 | // Raw version of sender. Sending a message is a 3 part process. Fetch an opaque |
| 43 | // token, cast that token to the message type, populate and then calling one of |
| 44 | // Send() or Free(). |
| 45 | class RawSender { |
| 46 | public: |
Parker Schuh | e4a70d6 | 2017-12-27 20:10:20 -0800 | [diff] [blame] | 47 | RawSender() {} |
| 48 | virtual ~RawSender() {} |
| 49 | |
James Kuszmaul | cd1db35 | 2019-05-26 16:42:29 -0700 | [diff] [blame] | 50 | virtual aos::Message *GetMessage() = 0; |
Parker Schuh | e4a70d6 | 2017-12-27 20:10:20 -0800 | [diff] [blame] | 51 | |
James Kuszmaul | cd1db35 | 2019-05-26 16:42:29 -0700 | [diff] [blame] | 52 | virtual void Free(aos::Message *msg) = 0; |
Parker Schuh | e4a70d6 | 2017-12-27 20:10:20 -0800 | [diff] [blame] | 53 | |
James Kuszmaul | cd1db35 | 2019-05-26 16:42:29 -0700 | [diff] [blame] | 54 | virtual bool Send(aos::Message *msg) = 0; |
Parker Schuh | e4a70d6 | 2017-12-27 20:10:20 -0800 | [diff] [blame] | 55 | |
| 56 | // Call operator that calls Free(). |
| 57 | template <typename T> |
| 58 | void operator()(T *t) { |
James Kuszmaul | cd1db35 | 2019-05-26 16:42:29 -0700 | [diff] [blame] | 59 | Free(t); |
Parker Schuh | e4a70d6 | 2017-12-27 20:10:20 -0800 | [diff] [blame] | 60 | } |
| 61 | |
Austin Schuh | d681bbd | 2019-02-02 12:03:32 -0800 | [diff] [blame] | 62 | virtual const char *name() const = 0; |
| 63 | |
Parker Schuh | e4a70d6 | 2017-12-27 20:10:20 -0800 | [diff] [blame] | 64 | protected: |
| 65 | RawSender(const RawSender &) = delete; |
| 66 | RawSender &operator=(const RawSender &) = delete; |
| 67 | }; |
| 68 | |
| 69 | // Opaque Information extracted from a particular type passed to the underlying |
| 70 | // system so that it knows how much memory to allocate etc. |
| 71 | struct QueueTypeInfo { |
| 72 | // Message size: |
| 73 | size_t size; |
| 74 | // This should be a globally unique identifier for the type. |
| 75 | int hash; |
| 76 | // Config parameter for how long the queue should be. |
| 77 | int queue_length; |
| 78 | |
| 79 | template <typename T> |
| 80 | static QueueTypeInfo Get() { |
| 81 | QueueTypeInfo info; |
| 82 | info.size = sizeof(T); |
| 83 | info.hash = T::kHash; |
| 84 | info.queue_length = T::kQueueLength; |
| 85 | return info; |
| 86 | } |
Neil Balch | c8f41ed | 2018-01-20 22:06:53 -0800 | [diff] [blame] | 87 | |
| 88 | // Necessary for the comparison of QueueTypeInfo objects in the |
| 89 | // SimulatedEventLoop. |
| 90 | bool operator<(const QueueTypeInfo &other) const { |
| 91 | if (size != other.size) return size < other.size; |
| 92 | if (hash != other.hash) return hash < other.hash; |
| 93 | return queue_length < other.queue_length; |
| 94 | } |
Parker Schuh | e4a70d6 | 2017-12-27 20:10:20 -0800 | [diff] [blame] | 95 | }; |
| 96 | |
Neil Balch | 229001a | 2018-01-07 18:22:52 -0800 | [diff] [blame] | 97 | // Interface for timers |
| 98 | class TimerHandler { |
| 99 | public: |
| 100 | virtual ~TimerHandler() {} |
| 101 | |
| 102 | // Timer should sleep until base, base + offset, base + offset * 2, ... |
| 103 | // If repeat_offset isn't set, the timer only expires once. |
| 104 | virtual void Setup(monotonic_clock::time_point base, |
| 105 | monotonic_clock::duration repeat_offset = |
| 106 | ::aos::monotonic_clock::zero()) = 0; |
| 107 | |
| 108 | // Stop future calls to callback(). |
| 109 | virtual void Disable() = 0; |
| 110 | }; |
| 111 | |
Austin Schuh | 52d325c | 2019-06-23 18:59:06 -0700 | [diff] [blame] | 112 | // Interface for phased loops. They are built on timers. |
| 113 | class PhasedLoopHandler { |
| 114 | public: |
| 115 | virtual ~PhasedLoopHandler() {} |
| 116 | |
| 117 | // Sets the interval and offset. Any changes to interval and offset only take |
| 118 | // effect when the handler finishes running. |
| 119 | virtual void set_interval_and_offset( |
| 120 | const monotonic_clock::duration interval, |
| 121 | const monotonic_clock::duration offset) = 0; |
| 122 | }; |
| 123 | |
Austin Schuh | 44019f9 | 2019-05-19 19:58:27 -0700 | [diff] [blame] | 124 | class EventScheduler; |
| 125 | |
Parker Schuh | e4a70d6 | 2017-12-27 20:10:20 -0800 | [diff] [blame] | 126 | // Virtual base class for all event queue-types. |
| 127 | class RawEventLoop { |
| 128 | public: |
| 129 | virtual ~RawEventLoop() {} |
| 130 | |
| 131 | // Current time. |
| 132 | virtual monotonic_clock::time_point monotonic_now() = 0; |
| 133 | |
| 134 | // The passed in function will be called when the event loop starts. |
| 135 | // Use this to run code once the thread goes into "real-time-mode", |
Austin Schuh | 44019f9 | 2019-05-19 19:58:27 -0700 | [diff] [blame] | 136 | virtual void OnRun(::std::function<void()> on_run) = 0; |
Parker Schuh | e4a70d6 | 2017-12-27 20:10:20 -0800 | [diff] [blame] | 137 | |
Austin Schuh | 0fc3b3e | 2019-06-29 13:56:21 -0700 | [diff] [blame] | 138 | // Sets the name of the event loop. |
| 139 | virtual void set_name(const char *name) = 0; |
| 140 | |
Austin Schuh | 52d325c | 2019-06-23 18:59:06 -0700 | [diff] [blame] | 141 | // Threadsafe. |
Parker Schuh | e4a70d6 | 2017-12-27 20:10:20 -0800 | [diff] [blame] | 142 | bool is_running() const { return is_running_.load(); } |
| 143 | |
Neil Balch | 229001a | 2018-01-07 18:22:52 -0800 | [diff] [blame] | 144 | // Creates a timer that executes callback when the timer expires |
| 145 | // Returns a TimerHandle for configuration of the timer |
| 146 | virtual TimerHandler *AddTimer(::std::function<void()> callback) = 0; |
| 147 | |
Austin Schuh | 52d325c | 2019-06-23 18:59:06 -0700 | [diff] [blame] | 148 | // Creates a timer that executes callback periodically at the specified |
| 149 | // interval and offset. Returns a PhasedLoopHandler for interacting with the |
| 150 | // timer. |
| 151 | virtual PhasedLoopHandler *AddPhasedLoop( |
| 152 | ::std::function<void(int)> callback, |
| 153 | const monotonic_clock::duration interval, |
| 154 | const monotonic_clock::duration offset = ::std::chrono::seconds(0)) = 0; |
| 155 | |
Parker Schuh | e4a70d6 | 2017-12-27 20:10:20 -0800 | [diff] [blame] | 156 | protected: |
Austin Schuh | 44019f9 | 2019-05-19 19:58:27 -0700 | [diff] [blame] | 157 | friend class EventScheduler; |
Parker Schuh | e4a70d6 | 2017-12-27 20:10:20 -0800 | [diff] [blame] | 158 | void set_is_running(bool value) { is_running_.store(value); } |
| 159 | |
| 160 | // Will send new messages from (path, type). |
| 161 | virtual std::unique_ptr<RawSender> MakeRawSender( |
| 162 | const std::string &path, const QueueTypeInfo &type) = 0; |
| 163 | |
| 164 | // Will fetch new messages from (path, type). |
| 165 | virtual std::unique_ptr<RawFetcher> MakeRawFetcher( |
| 166 | const std::string &path, const QueueTypeInfo &type) = 0; |
| 167 | |
| 168 | // Will watch (path, type) for new messages |
| 169 | virtual void MakeRawWatcher( |
| 170 | const std::string &path, const QueueTypeInfo &type, |
| 171 | std::function<void(const Message *message)> watcher) = 0; |
| 172 | |
| 173 | private: |
Austin Schuh | 44019f9 | 2019-05-19 19:58:27 -0700 | [diff] [blame] | 174 | ::std::atomic<bool> is_running_{false}; |
Parker Schuh | e4a70d6 | 2017-12-27 20:10:20 -0800 | [diff] [blame] | 175 | }; |
| 176 | |
| 177 | } // namespace aos |
| 178 | |
| 179 | #endif // _AOS_EVENTS_RAW_EVENT_LOOP_H_ |