blob: d1885bbf5265abc108eeae6e08b91e9030fff534 [file] [log] [blame]
Parker Schuhe4a70d62017-12-27 20:10:20 -08001#ifndef _AOS_EVENTS_EVENT_LOOP_H_
2#define _AOS_EVENTS_EVENT_LOOP_H_
3
4#include <string>
John Park33858a32018-09-28 23:05:48 -07005#include "aos/queue.h"
6#include "aos/time/time.h"
Parker Schuhe4a70d62017-12-27 20:10:20 -08007#include "aos/events/raw-event-loop.h"
8
9namespace aos {
10
11// Fetches the newest message from a queue.
12template <typename T>
13class Fetcher {
14 public:
15 Fetcher() {}
James Kuszmaulc79768b2019-02-18 15:08:44 -080016 // Fetches the next message. Returns whether it fetched a new message.
17 bool FetchNext() { return fetcher_->FetchNext(); }
Parker Schuhe4a70d62017-12-27 20:10:20 -080018 // Fetches the most recent message. Returns whether it fetched a new message.
19 bool Fetch() { return fetcher_->Fetch(); }
20
21 const T *get() const {
22 return reinterpret_cast<const T *>(fetcher_->most_recent());
23 }
24 const T &operator*() const { return *get(); }
25 const T *operator->() const { return get(); }
26
27 private:
28 friend class EventLoop;
29 Fetcher(std::unique_ptr<RawFetcher> fetcher) : fetcher_(std::move(fetcher)) {}
30 std::unique_ptr<RawFetcher> fetcher_;
31};
32
33// Sends messages to a queue.
34template <typename T>
35class Sender {
36 public:
Austin Schuhdf6cbb12019-02-02 13:46:52 -080037 typedef T Type;
38
Parker Schuhe4a70d62017-12-27 20:10:20 -080039 Sender() {}
40
41 // Represents a single message about to be sent to the queue.
42 // The lifecycle goes:
43 //
44 // Message msg = sender.MakeMessage();
45 // Populate(msg.get());
46 // msg.Send();
47 //
48 // Or:
49 //
50 // Message msg = sender.MakeMessage();
51 // PopulateOrNot(msg.get());
52 class Message {
53 public:
54 Message(RawSender *sender)
55 : msg_(reinterpret_cast<T *>(sender->GetContext()), *sender) {
56 msg_->Zero();
57 }
58
59 T *get() { return msg_.get(); }
60 const T *get() const { return msg_.get(); }
61 T &operator*() { return *get(); }
62 T *operator->() { return get(); }
63 const T &operator*() const { return *get(); }
64 const T *operator->() const { return get(); }
65
Austin Schuh81fc9cc2019-02-02 23:25:47 -080066 // Sends the message to the queue. Should only be called once. Returns true
67 // if the message was successfully sent, and false otherwise.
68 bool Send() {
Parker Schuhe4a70d62017-12-27 20:10:20 -080069 RawSender *sender = &msg_.get_deleter();
Austin Schuh81fc9cc2019-02-02 23:25:47 -080070 return sender->Send(
71 reinterpret_cast<RawSender::SendContext *>(msg_.release()));
Parker Schuhe4a70d62017-12-27 20:10:20 -080072 }
73
74 private:
75 std::unique_ptr<T, RawSender &> msg_;
76 };
77
78 // Constructs an above message.
79 Message MakeMessage();
80
Austin Schuhd681bbd2019-02-02 12:03:32 -080081 // Returns the name of the underlying queue.
82 const char *name() const { return sender_->name(); }
83
Parker Schuhe4a70d62017-12-27 20:10:20 -080084 private:
85 friend class EventLoop;
86 Sender(std::unique_ptr<RawSender> sender) : sender_(std::move(sender)) {}
87 std::unique_ptr<RawSender> sender_;
88};
89
90// TODO(parker): Consider making EventLoop wrap a RawEventLoop rather than
91// inheriting.
92class EventLoop : public RawEventLoop {
93 public:
94 virtual ~EventLoop() {}
95
96 // Current time.
97 virtual monotonic_clock::time_point monotonic_now() = 0;
98
Austin Schuh81fc9cc2019-02-02 23:25:47 -080099 // Note, it is supported to create:
100 // multiple fetchers, and (one sender or one watcher) per <path, type>
101 // tuple.
102
Parker Schuhe4a70d62017-12-27 20:10:20 -0800103 // Makes a class that will always fetch the most recent value
104 // sent to path.
105 template <typename T>
106 Fetcher<T> MakeFetcher(const std::string &path) {
107 return Fetcher<T>(MakeRawFetcher(path, QueueTypeInfo::Get<T>()));
108 }
109
110 // Makes class that allows constructing and sending messages to
111 // address path.
112 template <typename T>
113 Sender<T> MakeSender(const std::string &path) {
114 return Sender<T>(MakeRawSender(path, QueueTypeInfo::Get<T>()));
115 }
116
117 // Watch is a functor that have a call signature like so:
118 // void Event(const MessageType& type);
119 //
120 // This will watch messages sent to path.
121 // Note that T needs to match both send and recv side.
Austin Schuha1654ed2019-01-27 17:24:54 -0800122 // TODO(parker): Need to support ::std::bind. For now, use lambdas.
Parker Schuhe4a70d62017-12-27 20:10:20 -0800123 template <typename Watch>
124 void MakeWatcher(const std::string &path, Watch &&w);
125
126 // The passed in function will be called when the event loop starts.
127 // Use this to run code once the thread goes into "real-time-mode",
128 virtual void OnRun(std::function<void()>) = 0;
129
Parker Schuhe4a70d62017-12-27 20:10:20 -0800130 // TODO(austin): Sort out how to switch to realtime on run.
131 // virtual void RunRealtime() = 0;
132
133 // Stops receiving events
134 virtual void Exit() = 0;
135};
136
137} // namespace aos
138
139#include "aos/events/event-loop-tmpl.h"
140
141#endif // _AOS_EVENTS_EVENT_LOOP_H