blob: 0590d7b2d04b395a9092c55fcf65cce6865c23a8 [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() {}
16 // Fetches the most recent message. Returns whether it fetched a new message.
17 bool Fetch() { return fetcher_->Fetch(); }
18
19 const T *get() const {
20 return reinterpret_cast<const T *>(fetcher_->most_recent());
21 }
22 const T &operator*() const { return *get(); }
23 const T *operator->() const { return get(); }
24
25 private:
26 friend class EventLoop;
27 Fetcher(std::unique_ptr<RawFetcher> fetcher) : fetcher_(std::move(fetcher)) {}
28 std::unique_ptr<RawFetcher> fetcher_;
29};
30
31// Sends messages to a queue.
32template <typename T>
33class Sender {
34 public:
35 Sender() {}
36
37 // Represents a single message about to be sent to the queue.
38 // The lifecycle goes:
39 //
40 // Message msg = sender.MakeMessage();
41 // Populate(msg.get());
42 // msg.Send();
43 //
44 // Or:
45 //
46 // Message msg = sender.MakeMessage();
47 // PopulateOrNot(msg.get());
48 class Message {
49 public:
50 Message(RawSender *sender)
51 : msg_(reinterpret_cast<T *>(sender->GetContext()), *sender) {
52 msg_->Zero();
53 }
54
55 T *get() { return msg_.get(); }
56 const T *get() const { return msg_.get(); }
57 T &operator*() { return *get(); }
58 T *operator->() { return get(); }
59 const T &operator*() const { return *get(); }
60 const T *operator->() const { return get(); }
61
Austin Schuh81fc9cc2019-02-02 23:25:47 -080062 // Sends the message to the queue. Should only be called once. Returns true
63 // if the message was successfully sent, and false otherwise.
64 bool Send() {
Parker Schuhe4a70d62017-12-27 20:10:20 -080065 RawSender *sender = &msg_.get_deleter();
66 msg_->SetTimeToNow();
Austin Schuh81fc9cc2019-02-02 23:25:47 -080067 return sender->Send(
68 reinterpret_cast<RawSender::SendContext *>(msg_.release()));
Parker Schuhe4a70d62017-12-27 20:10:20 -080069 }
70
71 private:
72 std::unique_ptr<T, RawSender &> msg_;
73 };
74
75 // Constructs an above message.
76 Message MakeMessage();
77
Austin Schuhd681bbd2019-02-02 12:03:32 -080078 // Returns the name of the underlying queue.
79 const char *name() const { return sender_->name(); }
80
Parker Schuhe4a70d62017-12-27 20:10:20 -080081 private:
82 friend class EventLoop;
83 Sender(std::unique_ptr<RawSender> sender) : sender_(std::move(sender)) {}
84 std::unique_ptr<RawSender> sender_;
85};
86
87// TODO(parker): Consider making EventLoop wrap a RawEventLoop rather than
88// inheriting.
89class EventLoop : public RawEventLoop {
90 public:
91 virtual ~EventLoop() {}
92
93 // Current time.
94 virtual monotonic_clock::time_point monotonic_now() = 0;
95
Austin Schuh81fc9cc2019-02-02 23:25:47 -080096 // Note, it is supported to create:
97 // multiple fetchers, and (one sender or one watcher) per <path, type>
98 // tuple.
99
Parker Schuhe4a70d62017-12-27 20:10:20 -0800100 // Makes a class that will always fetch the most recent value
101 // sent to path.
102 template <typename T>
103 Fetcher<T> MakeFetcher(const std::string &path) {
104 return Fetcher<T>(MakeRawFetcher(path, QueueTypeInfo::Get<T>()));
105 }
106
107 // Makes class that allows constructing and sending messages to
108 // address path.
109 template <typename T>
110 Sender<T> MakeSender(const std::string &path) {
111 return Sender<T>(MakeRawSender(path, QueueTypeInfo::Get<T>()));
112 }
113
114 // Watch is a functor that have a call signature like so:
115 // void Event(const MessageType& type);
116 //
117 // This will watch messages sent to path.
118 // Note that T needs to match both send and recv side.
Austin Schuha1654ed2019-01-27 17:24:54 -0800119 // TODO(parker): Need to support ::std::bind. For now, use lambdas.
Parker Schuhe4a70d62017-12-27 20:10:20 -0800120 template <typename Watch>
121 void MakeWatcher(const std::string &path, Watch &&w);
122
123 // The passed in function will be called when the event loop starts.
124 // Use this to run code once the thread goes into "real-time-mode",
125 virtual void OnRun(std::function<void()>) = 0;
126
127 // Starts receiving events.
128 virtual void Run() = 0;
129
130 // 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