blob: a1879813d7dd4d8e14181fe054f74d4ceda88907 [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
62 // Sends the message to the queue. Should only be called once.
63 void Send() {
64 RawSender *sender = &msg_.get_deleter();
65 msg_->SetTimeToNow();
66 sender->Send(reinterpret_cast<RawSender::SendContext *>(msg_.release()));
67 }
68
69 private:
70 std::unique_ptr<T, RawSender &> msg_;
71 };
72
73 // Constructs an above message.
74 Message MakeMessage();
75
Austin Schuhd681bbd2019-02-02 12:03:32 -080076 // Returns the name of the underlying queue.
77 const char *name() const { return sender_->name(); }
78
Parker Schuhe4a70d62017-12-27 20:10:20 -080079 private:
80 friend class EventLoop;
81 Sender(std::unique_ptr<RawSender> sender) : sender_(std::move(sender)) {}
82 std::unique_ptr<RawSender> sender_;
83};
84
85// TODO(parker): Consider making EventLoop wrap a RawEventLoop rather than
86// inheriting.
87class EventLoop : public RawEventLoop {
88 public:
89 virtual ~EventLoop() {}
90
91 // Current time.
92 virtual monotonic_clock::time_point monotonic_now() = 0;
93
94 // Makes a class that will always fetch the most recent value
95 // sent to path.
96 template <typename T>
97 Fetcher<T> MakeFetcher(const std::string &path) {
98 return Fetcher<T>(MakeRawFetcher(path, QueueTypeInfo::Get<T>()));
99 }
100
101 // Makes class that allows constructing and sending messages to
102 // address path.
103 template <typename T>
104 Sender<T> MakeSender(const std::string &path) {
105 return Sender<T>(MakeRawSender(path, QueueTypeInfo::Get<T>()));
106 }
107
108 // Watch is a functor that have a call signature like so:
109 // void Event(const MessageType& type);
110 //
111 // This will watch messages sent to path.
112 // Note that T needs to match both send and recv side.
Austin Schuha1654ed2019-01-27 17:24:54 -0800113 // TODO(parker): Need to support ::std::bind. For now, use lambdas.
Parker Schuhe4a70d62017-12-27 20:10:20 -0800114 template <typename Watch>
115 void MakeWatcher(const std::string &path, Watch &&w);
116
117 // The passed in function will be called when the event loop starts.
118 // Use this to run code once the thread goes into "real-time-mode",
119 virtual void OnRun(std::function<void()>) = 0;
120
121 // Starts receiving events.
122 virtual void Run() = 0;
123
124 // TODO(austin): Sort out how to switch to realtime on run.
125 // virtual void RunRealtime() = 0;
126
127 // Stops receiving events
128 virtual void Exit() = 0;
129};
130
131} // namespace aos
132
133#include "aos/events/event-loop-tmpl.h"
134
135#endif // _AOS_EVENTS_EVENT_LOOP_H