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: |
| 22 | class FetchValue; |
| 23 | RawFetcher() {} |
| 24 | virtual ~RawFetcher() {} |
| 25 | |
James Kuszmaul | c79768b | 2019-02-18 15:08:44 -0800 | [diff] [blame] | 26 | // Non-blocking fetch of the next message in the queue. Returns true if there |
| 27 | // was a new message and we got it. |
| 28 | virtual bool FetchNext() = 0; |
| 29 | // Non-blocking fetch of the latest message: |
Parker Schuh | e4a70d6 | 2017-12-27 20:10:20 -0800 | [diff] [blame] | 30 | virtual bool Fetch() = 0; |
| 31 | |
| 32 | const FetchValue *most_recent() { return most_recent_; } |
| 33 | |
| 34 | protected: |
| 35 | RawFetcher(const RawFetcher &) = delete; |
| 36 | RawFetcher &operator=(const RawFetcher &) = delete; |
| 37 | void set_most_recent(const FetchValue *most_recent) { |
| 38 | most_recent_ = most_recent; |
| 39 | } |
| 40 | |
| 41 | private: |
| 42 | const FetchValue *most_recent_ = nullptr; |
| 43 | }; |
| 44 | |
| 45 | // Raw version of sender. Sending a message is a 3 part process. Fetch an opaque |
| 46 | // token, cast that token to the message type, populate and then calling one of |
| 47 | // Send() or Free(). |
| 48 | class RawSender { |
| 49 | public: |
Parker Schuh | e4a70d6 | 2017-12-27 20:10:20 -0800 | [diff] [blame] | 50 | RawSender() {} |
| 51 | virtual ~RawSender() {} |
| 52 | |
James Kuszmaul | cd1db35 | 2019-05-26 16:42:29 -0700 | [diff] [blame] | 53 | virtual aos::Message *GetMessage() = 0; |
Parker Schuh | e4a70d6 | 2017-12-27 20:10:20 -0800 | [diff] [blame] | 54 | |
James Kuszmaul | cd1db35 | 2019-05-26 16:42:29 -0700 | [diff] [blame] | 55 | virtual void Free(aos::Message *msg) = 0; |
Parker Schuh | e4a70d6 | 2017-12-27 20:10:20 -0800 | [diff] [blame] | 56 | |
James Kuszmaul | cd1db35 | 2019-05-26 16:42:29 -0700 | [diff] [blame] | 57 | virtual bool Send(aos::Message *msg) = 0; |
Parker Schuh | e4a70d6 | 2017-12-27 20:10:20 -0800 | [diff] [blame] | 58 | |
| 59 | // Call operator that calls Free(). |
| 60 | template <typename T> |
| 61 | void operator()(T *t) { |
James Kuszmaul | cd1db35 | 2019-05-26 16:42:29 -0700 | [diff] [blame] | 62 | Free(t); |
Parker Schuh | e4a70d6 | 2017-12-27 20:10:20 -0800 | [diff] [blame] | 63 | } |
| 64 | |
Austin Schuh | d681bbd | 2019-02-02 12:03:32 -0800 | [diff] [blame] | 65 | virtual const char *name() const = 0; |
| 66 | |
Parker Schuh | e4a70d6 | 2017-12-27 20:10:20 -0800 | [diff] [blame] | 67 | protected: |
| 68 | RawSender(const RawSender &) = delete; |
| 69 | RawSender &operator=(const RawSender &) = delete; |
| 70 | }; |
| 71 | |
| 72 | // Opaque Information extracted from a particular type passed to the underlying |
| 73 | // system so that it knows how much memory to allocate etc. |
| 74 | struct QueueTypeInfo { |
| 75 | // Message size: |
| 76 | size_t size; |
| 77 | // This should be a globally unique identifier for the type. |
| 78 | int hash; |
| 79 | // Config parameter for how long the queue should be. |
| 80 | int queue_length; |
| 81 | |
| 82 | template <typename T> |
| 83 | static QueueTypeInfo Get() { |
| 84 | QueueTypeInfo info; |
| 85 | info.size = sizeof(T); |
| 86 | info.hash = T::kHash; |
| 87 | info.queue_length = T::kQueueLength; |
| 88 | return info; |
| 89 | } |
Neil Balch | c8f41ed | 2018-01-20 22:06:53 -0800 | [diff] [blame] | 90 | |
| 91 | // Necessary for the comparison of QueueTypeInfo objects in the |
| 92 | // SimulatedEventLoop. |
| 93 | bool operator<(const QueueTypeInfo &other) const { |
| 94 | if (size != other.size) return size < other.size; |
| 95 | if (hash != other.hash) return hash < other.hash; |
| 96 | return queue_length < other.queue_length; |
| 97 | } |
Parker Schuh | e4a70d6 | 2017-12-27 20:10:20 -0800 | [diff] [blame] | 98 | }; |
| 99 | |
Neil Balch | 229001a | 2018-01-07 18:22:52 -0800 | [diff] [blame] | 100 | // Interface for timers |
| 101 | class TimerHandler { |
| 102 | public: |
| 103 | virtual ~TimerHandler() {} |
| 104 | |
| 105 | // Timer should sleep until base, base + offset, base + offset * 2, ... |
| 106 | // If repeat_offset isn't set, the timer only expires once. |
| 107 | virtual void Setup(monotonic_clock::time_point base, |
| 108 | monotonic_clock::duration repeat_offset = |
| 109 | ::aos::monotonic_clock::zero()) = 0; |
| 110 | |
| 111 | // Stop future calls to callback(). |
| 112 | virtual void Disable() = 0; |
| 113 | }; |
| 114 | |
Austin Schuh | 44019f9 | 2019-05-19 19:58:27 -0700 | [diff] [blame] | 115 | class EventScheduler; |
| 116 | |
Parker Schuh | e4a70d6 | 2017-12-27 20:10:20 -0800 | [diff] [blame] | 117 | // Virtual base class for all event queue-types. |
| 118 | class RawEventLoop { |
| 119 | public: |
| 120 | virtual ~RawEventLoop() {} |
| 121 | |
| 122 | // Current time. |
| 123 | virtual monotonic_clock::time_point monotonic_now() = 0; |
| 124 | |
| 125 | // The passed in function will be called when the event loop starts. |
| 126 | // 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] | 127 | virtual void OnRun(::std::function<void()> on_run) = 0; |
Parker Schuh | e4a70d6 | 2017-12-27 20:10:20 -0800 | [diff] [blame] | 128 | |
| 129 | bool is_running() const { return is_running_.load(); } |
| 130 | |
Neil Balch | 229001a | 2018-01-07 18:22:52 -0800 | [diff] [blame] | 131 | // Creates a timer that executes callback when the timer expires |
| 132 | // Returns a TimerHandle for configuration of the timer |
| 133 | virtual TimerHandler *AddTimer(::std::function<void()> callback) = 0; |
| 134 | |
Parker Schuh | e4a70d6 | 2017-12-27 20:10:20 -0800 | [diff] [blame] | 135 | // Stops receiving events. |
| 136 | virtual void Exit() = 0; |
| 137 | |
Austin Schuh | 44019f9 | 2019-05-19 19:58:27 -0700 | [diff] [blame] | 138 | // TODO(austin): This shouldn't belong. |
| 139 | virtual void Run() = 0; |
| 140 | |
Parker Schuh | e4a70d6 | 2017-12-27 20:10:20 -0800 | [diff] [blame] | 141 | protected: |
Austin Schuh | 44019f9 | 2019-05-19 19:58:27 -0700 | [diff] [blame] | 142 | friend class EventScheduler; |
Parker Schuh | e4a70d6 | 2017-12-27 20:10:20 -0800 | [diff] [blame] | 143 | void set_is_running(bool value) { is_running_.store(value); } |
| 144 | |
| 145 | // Will send new messages from (path, type). |
| 146 | virtual std::unique_ptr<RawSender> MakeRawSender( |
| 147 | const std::string &path, const QueueTypeInfo &type) = 0; |
| 148 | |
| 149 | // Will fetch new messages from (path, type). |
| 150 | virtual std::unique_ptr<RawFetcher> MakeRawFetcher( |
| 151 | const std::string &path, const QueueTypeInfo &type) = 0; |
| 152 | |
| 153 | // Will watch (path, type) for new messages |
| 154 | virtual void MakeRawWatcher( |
| 155 | const std::string &path, const QueueTypeInfo &type, |
| 156 | std::function<void(const Message *message)> watcher) = 0; |
| 157 | |
| 158 | private: |
Austin Schuh | 44019f9 | 2019-05-19 19:58:27 -0700 | [diff] [blame] | 159 | ::std::atomic<bool> is_running_{false}; |
Parker Schuh | e4a70d6 | 2017-12-27 20:10:20 -0800 | [diff] [blame] | 160 | }; |
| 161 | |
| 162 | } // namespace aos |
| 163 | |
| 164 | #endif // _AOS_EVENTS_RAW_EVENT_LOOP_H_ |