blob: 5f5d8b0c2eba55e647b55953e4ba4c2d8c98fbda [file] [log] [blame]
brians343bc112013-02-10 01:53:46 +00001#ifndef AOS_COMMON_QUEUE_H_
2#define AOS_COMMON_QUEUE_H_
3
4#include <assert.h>
5
brians343bc112013-02-10 01:53:46 +00006#include "aos/common/macros.h"
Brian Silverman14fd0fb2014-01-14 21:42:01 -08007#include "aos/linux_code/ipc_lib/queue.h"
brians343bc112013-02-10 01:53:46 +00008#include "aos/common/time.h"
9
brians343bc112013-02-10 01:53:46 +000010namespace aos {
11
Brian Silvermanf7986142014-04-21 17:42:35 -070012struct MessageType;
Brian Silverman96395be2014-02-11 18:35:57 -080013
brians343bc112013-02-10 01:53:46 +000014// This class is a base class for all messages sent over queues.
Brian Silverman16c82972014-02-13 15:36:40 -080015// All of the methods are overloaded in (generated) subclasses to do the same
16// thing for the whole thing.
brians343bc112013-02-10 01:53:46 +000017class Message {
18 public:
19 typedef ::aos::time::Time Time;
20 // The time that the message was sent at.
21 Time sent_time;
22
23 Message() : sent_time(0, 0) {}
24
25 // Zeros out the time.
26 void Zero();
Brian Silvermanc4546d22014-02-10 18:03:09 -080027 // Returns the size of the common fields.
brians343bc112013-02-10 01:53:46 +000028 static size_t Size() { return sizeof(Time); }
29
30 // Deserializes the common fields from the buffer.
31 size_t Deserialize(const char *buffer);
32 // Serializes the common fields into the buffer.
33 size_t Serialize(char *buffer) const;
34
35 // Populates sent_time with the current time.
36 void SetTimeToNow() { sent_time = Time::Now(); }
37
38 // Writes the contents of the message to the provided buffer.
39 size_t Print(char *buffer, int length) const;
Brian Silvermanc4546d22014-02-10 18:03:09 -080040
Brian Silverman88457ef2015-02-23 01:56:10 -050041 // Compares two messages for equality, excluding their sent_time.
42 bool EqualsNoTime(const Message & /*other*/) const { return true; }
43
Brian Silverman665e60c2014-02-12 13:57:10 -080044 static const MessageType *GetType();
brians343bc112013-02-10 01:53:46 +000045};
46
47template <class T> class Queue;
48template <class T> class MessageBuilder;
49template <class T> class ScopedMessagePtr;
brians343bc112013-02-10 01:53:46 +000050
51// A ScopedMessagePtr<> manages a queue message pointer.
52// It frees it properly when the ScopedMessagePtr<> goes out of scope or gets
53// sent. By design, there is no way to get the ScopedMessagePtr to release the
Brian Silverman6da04272014-05-18 18:47:48 -070054// message pointer to external code.
brians343bc112013-02-10 01:53:46 +000055template <class T>
56class ScopedMessagePtr {
57 public:
58 // Returns a pointer to the message.
59 // This stays valid until Send or the destructor have been called.
60 const T *get() const { return msg_; }
61 T *get() { return msg_; }
62
63 const T &operator*() const {
64 const T *msg = get();
65 assert(msg != NULL);
66 return *msg;
67 }
68
69 T &operator*() {
70 T *msg = get();
71 assert(msg != NULL);
72 return *msg;
73 }
74
75 const T *operator->() const {
76 const T *msg = get();
77 assert(msg != NULL);
78 return msg;
79 }
80
81 T *operator->() {
82 T *msg = get();
83 assert(msg != NULL);
84 return msg;
85 }
86
87 operator bool() {
88 return msg_ != NULL;
89 }
90
91 // Sends the message and removes our reference to it.
92 // If the queue is full, over-ride the oldest message in it with our new
93 // message.
94 // Returns true on success, and false otherwise.
95 // The message will be freed.
96 bool Send();
97
98 // Sends the message and removes our reference to it.
99 // If the queue is full, block until it is no longer full.
100 // Returns true on success, and false otherwise.
101 // The message will be freed.
102 bool SendBlocking();
103
104 // Frees the contained message.
105 ~ScopedMessagePtr() {
106 reset();
107 }
108
brians343bc112013-02-10 01:53:46 +0000109 // Implements a move constructor. This only takes rvalue references
110 // because we want to allow someone to say
111 // ScopedMessagePtr<X> ptr = queue.MakeMessage();
112 // but we don't want to allow them to then say
113 // ScopedMessagePtr<X> new_ptr = ptr;
Brian Silvermanc4546d22014-02-10 18:03:09 -0800114 // And, if they do actually want to move the pointer, then it will correctly
brians343bc112013-02-10 01:53:46 +0000115 // clear out the source so there aren't 2 pointers to the message lying
116 // around.
117 ScopedMessagePtr(ScopedMessagePtr<T> &&ptr)
Brian Silverman6da04272014-05-18 18:47:48 -0700118 : queue_(ptr.queue_), msg_(ptr.msg_) {
brians343bc112013-02-10 01:53:46 +0000119 ptr.msg_ = NULL;
120 }
brians343bc112013-02-10 01:53:46 +0000121
122 private:
123 // Provide access to set_queue and the constructor for init.
124 friend class aos::Queue<typename std::remove_const<T>::type>;
125 // Provide access to the copy constructor for MakeWithBuilder.
126 friend class aos::MessageBuilder<T>;
127
Brian Silverman6da04272014-05-18 18:47:48 -0700128 // Only Queue should be able to build a message.
Brian Silverman08661c72013-09-01 17:24:38 -0700129 ScopedMessagePtr(RawQueue *queue, T *msg)
brians343bc112013-02-10 01:53:46 +0000130 : queue_(queue), msg_(msg) {}
brians343bc112013-02-10 01:53:46 +0000131
132 // Sets the pointer to msg, freeing the old value if it was there.
133 // This is private because nobody should be able to get a pointer to a message
134 // that needs to be scoped without using the queue.
135 void reset(T *msg = NULL);
136
brians343bc112013-02-10 01:53:46 +0000137 // Sets the queue that owns this message.
Brian Silverman08661c72013-09-01 17:24:38 -0700138 void set_queue(RawQueue *queue) { queue_ = queue; }
brians343bc112013-02-10 01:53:46 +0000139
140 // The queue that the message is a part of.
Brian Silverman08661c72013-09-01 17:24:38 -0700141 RawQueue *queue_;
brians343bc112013-02-10 01:53:46 +0000142 // The message or NULL.
143 T *msg_;
144
145 // Protect evil constructors.
146 DISALLOW_COPY_AND_ASSIGN(ScopedMessagePtr<T>);
147};
148
149// Specializations for the Builders will be automatically generated in the .q.h
150// header files with all of the handy builder methods.
brians343bc112013-02-10 01:53:46 +0000151template <class T>
152class MessageBuilder {
153 public:
154 typedef T Message;
155 bool Send();
156};
157
158// TODO(aschuh): Base class
159// T must be a Message with the same format as the messages generated by
Brian Silverman6da04272014-05-18 18:47:48 -0700160// the .q files.
brians343bc112013-02-10 01:53:46 +0000161template <class T>
162class Queue {
163 public:
164 typedef T Message;
165
Brian Silverman92c3f1e2015-12-08 20:21:31 -0500166 explicit Queue(const char *queue_name)
Brian Silverman6da04272014-05-18 18:47:48 -0700167 : queue_name_(queue_name), queue_(NULL), queue_msg_(NULL, NULL) {
brians343bc112013-02-10 01:53:46 +0000168 static_assert(shm_ok<T>::value,
169 "The provided message type can't be put in shmem.");
170 }
171
172 // Initializes the queue. This may optionally be called to do any one time
Brian Silvermanc4546d22014-02-10 18:03:09 -0800173 // work before sending information, and may be be called multiple times.
brians343bc112013-02-10 01:53:46 +0000174 // Init will be called when a message is sent, but this will cause sending to
175 // take a different amount of time the first cycle.
176 void Init();
177
Austin Schuhdc1c84a2013-02-23 16:33:10 -0800178 // Removes all internal references to shared memory so shared memory can be
179 // restarted safely. This should only be used in testing.
180 void Clear();
181
brians343bc112013-02-10 01:53:46 +0000182 // Fetches the next message from the queue.
183 // Returns true if there was a new message available and we successfully
Brian Silverman428de562014-04-10 15:59:19 -0700184 // fetched it.
brians343bc112013-02-10 01:53:46 +0000185 bool FetchNext();
Brian Silverman6da04272014-05-18 18:47:48 -0700186
187 // Fetches the next message from the queue, waiting if necessary until there
188 // is one.
Brian Silverman428de562014-04-10 15:59:19 -0700189 void FetchNextBlocking();
brians343bc112013-02-10 01:53:46 +0000190
191 // Fetches the last message from the queue.
192 // Returns true if there was a new message available and we successfully
193 // fetched it.
194 bool FetchLatest();
195
Austin Schuh867c11e2015-02-22 21:35:43 -0800196 // Fetches the latest message from the queue, or blocks if we have already
197 // fetched it until another is avilable.
Brian Silverman428de562014-04-10 15:59:19 -0700198 void FetchAnother();
199
brians343bc112013-02-10 01:53:46 +0000200 // Returns the age of the message.
Brian Silverman5d3ab7f2015-02-21 15:54:21 -0500201 const time::Time Age() const {
202 return time::Time::Now() - queue_msg_->sent_time;
203 }
brians343bc112013-02-10 01:53:46 +0000204
205 // Returns true if the latest value in the queue is newer than age mseconds.
Brian Silverman6da04272014-05-18 18:47:48 -0700206 // DEPRECATED(brians): Use IsNewerThan(const time::Time&) instead.
207 bool IsNewerThanMS(int age) const {
Brian Silvermanc4546d22014-02-10 18:03:09 -0800208 // TODO(aschuh): Log very verbosely if something is _ever_ stale.
Brian Silverman6da04272014-05-18 18:47:48 -0700209 return IsNewerThan(time::Time::InMS(age));
210 }
211
212 bool IsNewerThan(const time::Time &age) const {
213 return get() != nullptr && Age() < age;
brians343bc112013-02-10 01:53:46 +0000214 }
215
216 // Returns a pointer to the current message.
217 // This pointer will be valid until a new message is fetched.
218 const T *get() const { return queue_msg_.get(); }
219
220 // Returns a reference to the message.
221 // The message will be valid until a new message is fetched.
222 const T &operator*() const {
223 const T *msg = get();
224 assert(msg != NULL);
225 return *msg;
226 }
227
228 // Returns a pointer to the current message.
229 // This pointer will be valid until a new message is fetched.
230 const T *operator->() const {
231 const T *msg = get();
232 assert(msg != NULL);
233 return msg;
234 }
235
brians343bc112013-02-10 01:53:46 +0000236 // Returns a scoped_ptr containing a message.
237 // GCC will optimize away the copy constructor, so this is safe.
238 ScopedMessagePtr<T> MakeMessage();
239
240 // Returns a message builder that contains a pre-allocated message.
Brian Silverman42456d82014-08-19 12:43:59 -0400241 // This message will start out completely zeroed.
brians343bc112013-02-10 01:53:46 +0000242 aos::MessageBuilder<T> MakeWithBuilder();
brians343bc112013-02-10 01:53:46 +0000243
244 const char *name() const { return queue_name_; }
245
246 private:
247 const char *queue_name_;
248
brians343bc112013-02-10 01:53:46 +0000249 T *MakeRawMessage();
Brian Silverman6da04272014-05-18 18:47:48 -0700250
brians343bc112013-02-10 01:53:46 +0000251 // Pointer to the queue that this object fetches from.
Brian Silverman08661c72013-09-01 17:24:38 -0700252 RawQueue *queue_;
Austin Schuh287d98e2014-03-09 00:41:55 -0800253 int index_ = 0;
brians343bc112013-02-10 01:53:46 +0000254 // Scoped pointer holding the latest message or NULL.
255 ScopedMessagePtr<const T> queue_msg_;
Brian Silverman6da04272014-05-18 18:47:48 -0700256
brians343bc112013-02-10 01:53:46 +0000257 DISALLOW_COPY_AND_ASSIGN(Queue<T>);
258};
259
260// Base class for all queue groups.
261class QueueGroup {
262 public:
263 // Constructs a queue group given its name and a unique hash of the name and
264 // type.
265 QueueGroup(const char *name, uint32_t hash) : name_(name), hash_(hash) {}
266
267 // Returns the name of the queue group.
268 const char *name() const { return name_.c_str(); }
269 // Returns a unique hash representing this instance of the queue group.
270 uint32_t hash() const { return hash_; }
271
272 private:
273 std::string name_;
274 uint32_t hash_;
275};
276
277} // namespace aos
278
Brian Silverman14fd0fb2014-01-14 21:42:01 -0800279#include "aos/linux_code/queue-tmpl.h"
brians343bc112013-02-10 01:53:46 +0000280
281#endif // AOS_COMMON_QUEUE_H_