| #ifndef _AOS_EVENTS_EVENT_LOOP_H_ |
| #define _AOS_EVENTS_EVENT_LOOP_H_ |
| |
| #include <string> |
| #include "aos/queue.h" |
| #include "aos/time/time.h" |
| #include "aos/events/raw-event-loop.h" |
| |
| namespace aos { |
| |
| // Fetches the newest message from a queue. |
| template <typename T> |
| class Fetcher { |
| public: |
| Fetcher() {} |
| // Fetches the next message. Returns true if it fetched a new message. This |
| // method will only return messages sent after the Fetcher was created. |
| bool FetchNext() { return fetcher_->FetchNext(); } |
| // Fetches the most recent message. Returns true if it fetched a new message. |
| // This will return the latest message regardless of if it was sent before or |
| // after the fetcher was created. |
| bool Fetch() { return fetcher_->Fetch(); } |
| |
| const T *get() const { |
| return reinterpret_cast<const T *>(fetcher_->most_recent()); |
| } |
| const T &operator*() const { return *get(); } |
| const T *operator->() const { return get(); } |
| |
| private: |
| friend class EventLoop; |
| Fetcher(::std::unique_ptr<RawFetcher> fetcher) : fetcher_(::std::move(fetcher)) {} |
| ::std::unique_ptr<RawFetcher> fetcher_; |
| }; |
| |
| // Sends messages to a queue. |
| template <typename T> |
| class Sender { |
| public: |
| typedef T Type; |
| |
| Sender() {} |
| |
| // Represents a single message about to be sent to the queue. |
| // The lifecycle goes: |
| // |
| // Message msg = sender.MakeMessage(); |
| // Populate(msg.get()); |
| // msg.Send(); |
| // |
| // Or: |
| // |
| // Message msg = sender.MakeMessage(); |
| // PopulateOrNot(msg.get()); |
| class Message { |
| public: |
| Message(RawSender *sender) |
| : msg_(reinterpret_cast<T *>(sender->GetMessage()), *sender) { |
| msg_->Zero(); |
| } |
| |
| T *get() { return msg_.get(); } |
| const T *get() const { return msg_.get(); } |
| T &operator*() { return *get(); } |
| T *operator->() { return get(); } |
| const T &operator*() const { return *get(); } |
| const T *operator->() const { return get(); } |
| |
| // Sends the message to the queue. Should only be called once. Returns true |
| // if the message was successfully sent, and false otherwise. |
| bool Send() { |
| RawSender *sender = &msg_.get_deleter(); |
| return sender->Send(msg_.release()); |
| } |
| |
| private: |
| std::unique_ptr<T, RawSender &> msg_; |
| }; |
| |
| // Constructs an above message. |
| Message MakeMessage(); |
| |
| // Returns the name of the underlying queue. |
| const char *name() const { return sender_->name(); } |
| |
| private: |
| friend class EventLoop; |
| Sender(::std::unique_ptr<RawSender> sender) : sender_(::std::move(sender)) {} |
| ::std::unique_ptr<RawSender> sender_; |
| }; |
| |
| // TODO(parker): Consider making EventLoop wrap a RawEventLoop rather than |
| // inheriting. |
| class EventLoop : public RawEventLoop { |
| public: |
| virtual ~EventLoop() {} |
| |
| // Current time. |
| virtual monotonic_clock::time_point monotonic_now() = 0; |
| |
| // Note, it is supported to create: |
| // multiple fetchers, and (one sender or one watcher) per <path, type> |
| // tuple. |
| |
| // Makes a class that will always fetch the most recent value |
| // sent to path. |
| template <typename T> |
| Fetcher<T> MakeFetcher(const ::std::string &path) { |
| return Fetcher<T>(MakeRawFetcher(path, QueueTypeInfo::Get<T>())); |
| } |
| |
| // Makes class that allows constructing and sending messages to |
| // address path. |
| template <typename T> |
| Sender<T> MakeSender(const ::std::string &path) { |
| return Sender<T>(MakeRawSender(path, QueueTypeInfo::Get<T>())); |
| } |
| |
| // Watch is a functor that have a call signature like so: |
| // void Event(const MessageType& type); |
| // |
| // This will watch messages sent to path. |
| // Note that T needs to match both send and recv side. |
| // TODO(parker): Need to support ::std::bind. For now, use lambdas. |
| template <typename Watch> |
| void MakeWatcher(const ::std::string &path, Watch &&w); |
| |
| // The passed in function will be called when the event loop starts. |
| // Use this to run code once the thread goes into "real-time-mode", |
| virtual void OnRun(::std::function<void()>) = 0; |
| |
| // TODO(austin): OnExit |
| |
| // Sets the scheduler priority to run the event loop at. This may not be |
| // called after we go into "real-time-mode". |
| virtual void SetRuntimeRealtimePriority(int priority) = 0; |
| }; |
| |
| } // namespace aos |
| |
| #include "aos/events/event-loop-tmpl.h" |
| |
| #endif // _AOS_EVENTS_EVENT_LOOP_H |