blob: 5f6adeb4a120f3c725fd4a5871b24aeb45811bb5 [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
Brian Silverman3204dd82013-03-12 18:42:01 -07006#include "aos/common/time.h"
brians343bc112013-02-10 01:53:46 +00007#include "aos/common/macros.h"
Brian Silverman14fd0fb2014-01-14 21:42:01 -08008#include "aos/linux_code/ipc_lib/queue.h"
brians343bc112013-02-10 01:53:46 +00009#include "aos/common/time.h"
10
brians343bc112013-02-10 01:53:46 +000011namespace aos {
12
Brian Silvermanf7986142014-04-21 17:42:35 -070013struct MessageType;
Brian Silverman96395be2014-02-11 18:35:57 -080014
brians343bc112013-02-10 01:53:46 +000015// This class is a base class for all messages sent over queues.
Brian Silverman16c82972014-02-13 15:36:40 -080016// All of the methods are overloaded in (generated) subclasses to do the same
17// thing for the whole thing.
brians343bc112013-02-10 01:53:46 +000018class Message {
19 public:
20 typedef ::aos::time::Time Time;
21 // The time that the message was sent at.
22 Time sent_time;
23
24 Message() : sent_time(0, 0) {}
25
26 // Zeros out the time.
27 void Zero();
Brian Silvermanc4546d22014-02-10 18:03:09 -080028 // Returns the size of the common fields.
brians343bc112013-02-10 01:53:46 +000029 static size_t Size() { return sizeof(Time); }
30
31 // Deserializes the common fields from the buffer.
32 size_t Deserialize(const char *buffer);
33 // Serializes the common fields into the buffer.
34 size_t Serialize(char *buffer) const;
35
36 // Populates sent_time with the current time.
37 void SetTimeToNow() { sent_time = Time::Now(); }
38
39 // Writes the contents of the message to the provided buffer.
40 size_t Print(char *buffer, int length) const;
Brian Silvermanc4546d22014-02-10 18:03:09 -080041
Brian Silverman88457ef2015-02-23 01:56:10 -050042 // Compares two messages for equality, excluding their sent_time.
43 bool EqualsNoTime(const Message & /*other*/) const { return true; }
44
Brian Silverman665e60c2014-02-12 13:57:10 -080045 static const MessageType *GetType();
brians343bc112013-02-10 01:53:46 +000046};
47
48template <class T> class Queue;
49template <class T> class MessageBuilder;
50template <class T> class ScopedMessagePtr;
brians343bc112013-02-10 01:53:46 +000051
52// A ScopedMessagePtr<> manages a queue message pointer.
53// It frees it properly when the ScopedMessagePtr<> goes out of scope or gets
54// sent. By design, there is no way to get the ScopedMessagePtr to release the
Brian Silverman6da04272014-05-18 18:47:48 -070055// message pointer to external code.
brians343bc112013-02-10 01:53:46 +000056template <class T>
57class ScopedMessagePtr {
58 public:
59 // Returns a pointer to the message.
60 // This stays valid until Send or the destructor have been called.
61 const T *get() const { return msg_; }
62 T *get() { return msg_; }
63
64 const T &operator*() const {
65 const T *msg = get();
66 assert(msg != NULL);
67 return *msg;
68 }
69
70 T &operator*() {
71 T *msg = get();
72 assert(msg != NULL);
73 return *msg;
74 }
75
76 const T *operator->() const {
77 const T *msg = get();
78 assert(msg != NULL);
79 return msg;
80 }
81
82 T *operator->() {
83 T *msg = get();
84 assert(msg != NULL);
85 return msg;
86 }
87
88 operator bool() {
89 return msg_ != NULL;
90 }
91
92 // Sends the message and removes our reference to it.
93 // If the queue is full, over-ride the oldest message in it with our new
94 // message.
95 // Returns true on success, and false otherwise.
96 // The message will be freed.
97 bool Send();
98
99 // Sends the message and removes our reference to it.
100 // If the queue is full, block until it is no longer full.
101 // Returns true on success, and false otherwise.
102 // The message will be freed.
103 bool SendBlocking();
104
105 // Frees the contained message.
106 ~ScopedMessagePtr() {
107 reset();
108 }
109
brians343bc112013-02-10 01:53:46 +0000110 // Implements a move constructor. This only takes rvalue references
111 // because we want to allow someone to say
112 // ScopedMessagePtr<X> ptr = queue.MakeMessage();
113 // but we don't want to allow them to then say
114 // ScopedMessagePtr<X> new_ptr = ptr;
Brian Silvermanc4546d22014-02-10 18:03:09 -0800115 // And, if they do actually want to move the pointer, then it will correctly
brians343bc112013-02-10 01:53:46 +0000116 // clear out the source so there aren't 2 pointers to the message lying
117 // around.
118 ScopedMessagePtr(ScopedMessagePtr<T> &&ptr)
Brian Silverman6da04272014-05-18 18:47:48 -0700119 : queue_(ptr.queue_), msg_(ptr.msg_) {
brians343bc112013-02-10 01:53:46 +0000120 ptr.msg_ = NULL;
121 }
brians343bc112013-02-10 01:53:46 +0000122
123 private:
124 // Provide access to set_queue and the constructor for init.
125 friend class aos::Queue<typename std::remove_const<T>::type>;
126 // Provide access to the copy constructor for MakeWithBuilder.
127 friend class aos::MessageBuilder<T>;
128
Brian Silverman6da04272014-05-18 18:47:48 -0700129 // Only Queue should be able to build a message.
Brian Silverman08661c72013-09-01 17:24:38 -0700130 ScopedMessagePtr(RawQueue *queue, T *msg)
brians343bc112013-02-10 01:53:46 +0000131 : queue_(queue), msg_(msg) {}
brians343bc112013-02-10 01:53:46 +0000132
133 // Sets the pointer to msg, freeing the old value if it was there.
134 // This is private because nobody should be able to get a pointer to a message
135 // that needs to be scoped without using the queue.
136 void reset(T *msg = NULL);
137
brians343bc112013-02-10 01:53:46 +0000138 // Sets the queue that owns this message.
Brian Silverman08661c72013-09-01 17:24:38 -0700139 void set_queue(RawQueue *queue) { queue_ = queue; }
brians343bc112013-02-10 01:53:46 +0000140
141 // The queue that the message is a part of.
Brian Silverman08661c72013-09-01 17:24:38 -0700142 RawQueue *queue_;
brians343bc112013-02-10 01:53:46 +0000143 // The message or NULL.
144 T *msg_;
145
146 // Protect evil constructors.
147 DISALLOW_COPY_AND_ASSIGN(ScopedMessagePtr<T>);
148};
149
150// Specializations for the Builders will be automatically generated in the .q.h
151// header files with all of the handy builder methods.
brians343bc112013-02-10 01:53:46 +0000152template <class T>
153class MessageBuilder {
154 public:
155 typedef T Message;
156 bool Send();
157};
158
159// TODO(aschuh): Base class
160// T must be a Message with the same format as the messages generated by
Brian Silverman6da04272014-05-18 18:47:48 -0700161// the .q files.
brians343bc112013-02-10 01:53:46 +0000162template <class T>
163class Queue {
164 public:
165 typedef T Message;
166
167 Queue(const char *queue_name)
Brian Silverman6da04272014-05-18 18:47:48 -0700168 : queue_name_(queue_name), queue_(NULL), queue_msg_(NULL, NULL) {
brians343bc112013-02-10 01:53:46 +0000169 static_assert(shm_ok<T>::value,
170 "The provided message type can't be put in shmem.");
171 }
172
173 // Initializes the queue. This may optionally be called to do any one time
Brian Silvermanc4546d22014-02-10 18:03:09 -0800174 // work before sending information, and may be be called multiple times.
brians343bc112013-02-10 01:53:46 +0000175 // Init will be called when a message is sent, but this will cause sending to
176 // take a different amount of time the first cycle.
177 void Init();
178
Austin Schuhdc1c84a2013-02-23 16:33:10 -0800179 // Removes all internal references to shared memory so shared memory can be
180 // restarted safely. This should only be used in testing.
181 void Clear();
182
brians343bc112013-02-10 01:53:46 +0000183 // Fetches the next message from the queue.
184 // Returns true if there was a new message available and we successfully
Brian Silverman428de562014-04-10 15:59:19 -0700185 // fetched it.
brians343bc112013-02-10 01:53:46 +0000186 bool FetchNext();
Brian Silverman6da04272014-05-18 18:47:48 -0700187
188 // Fetches the next message from the queue, waiting if necessary until there
189 // is one.
Brian Silverman428de562014-04-10 15:59:19 -0700190 void FetchNextBlocking();
brians343bc112013-02-10 01:53:46 +0000191
192 // Fetches the last message from the queue.
193 // Returns true if there was a new message available and we successfully
194 // fetched it.
195 bool FetchLatest();
196
Austin Schuh867c11e2015-02-22 21:35:43 -0800197 // Fetches the latest message from the queue, or blocks if we have already
198 // fetched it until another is avilable.
Brian Silverman428de562014-04-10 15:59:19 -0700199 void FetchAnother();
200
brians343bc112013-02-10 01:53:46 +0000201 // Returns the age of the message.
Brian Silverman5d3ab7f2015-02-21 15:54:21 -0500202 const time::Time Age() const {
203 return time::Time::Now() - queue_msg_->sent_time;
204 }
brians343bc112013-02-10 01:53:46 +0000205
206 // Returns true if the latest value in the queue is newer than age mseconds.
Brian Silverman6da04272014-05-18 18:47:48 -0700207 // DEPRECATED(brians): Use IsNewerThan(const time::Time&) instead.
208 bool IsNewerThanMS(int age) const {
Brian Silvermanc4546d22014-02-10 18:03:09 -0800209 // TODO(aschuh): Log very verbosely if something is _ever_ stale.
Brian Silverman6da04272014-05-18 18:47:48 -0700210 return IsNewerThan(time::Time::InMS(age));
211 }
212
213 bool IsNewerThan(const time::Time &age) const {
214 return get() != nullptr && Age() < age;
brians343bc112013-02-10 01:53:46 +0000215 }
216
217 // Returns a pointer to the current message.
218 // This pointer will be valid until a new message is fetched.
219 const T *get() const { return queue_msg_.get(); }
220
221 // Returns a reference to the message.
222 // The message will be valid until a new message is fetched.
223 const T &operator*() const {
224 const T *msg = get();
225 assert(msg != NULL);
226 return *msg;
227 }
228
229 // Returns a pointer to the current message.
230 // This pointer will be valid until a new message is fetched.
231 const T *operator->() const {
232 const T *msg = get();
233 assert(msg != NULL);
234 return msg;
235 }
236
brians343bc112013-02-10 01:53:46 +0000237 // Returns a scoped_ptr containing a message.
238 // GCC will optimize away the copy constructor, so this is safe.
239 ScopedMessagePtr<T> MakeMessage();
240
241 // Returns a message builder that contains a pre-allocated message.
Brian Silverman42456d82014-08-19 12:43:59 -0400242 // This message will start out completely zeroed.
brians343bc112013-02-10 01:53:46 +0000243 aos::MessageBuilder<T> MakeWithBuilder();
brians343bc112013-02-10 01:53:46 +0000244
245 const char *name() const { return queue_name_; }
246
247 private:
248 const char *queue_name_;
249
brians343bc112013-02-10 01:53:46 +0000250 T *MakeRawMessage();
Brian Silverman6da04272014-05-18 18:47:48 -0700251
brians343bc112013-02-10 01:53:46 +0000252 // Pointer to the queue that this object fetches from.
Brian Silverman08661c72013-09-01 17:24:38 -0700253 RawQueue *queue_;
Austin Schuh287d98e2014-03-09 00:41:55 -0800254 int index_ = 0;
brians343bc112013-02-10 01:53:46 +0000255 // Scoped pointer holding the latest message or NULL.
256 ScopedMessagePtr<const T> queue_msg_;
Brian Silverman6da04272014-05-18 18:47:48 -0700257
brians343bc112013-02-10 01:53:46 +0000258 DISALLOW_COPY_AND_ASSIGN(Queue<T>);
259};
260
261// Base class for all queue groups.
262class QueueGroup {
263 public:
264 // Constructs a queue group given its name and a unique hash of the name and
265 // type.
266 QueueGroup(const char *name, uint32_t hash) : name_(name), hash_(hash) {}
267
268 // Returns the name of the queue group.
269 const char *name() const { return name_.c_str(); }
270 // Returns a unique hash representing this instance of the queue group.
271 uint32_t hash() const { return hash_; }
272
273 private:
274 std::string name_;
275 uint32_t hash_;
276};
277
278} // namespace aos
279
Brian Silverman14fd0fb2014-01-14 21:42:01 -0800280#include "aos/linux_code/queue-tmpl.h"
brians343bc112013-02-10 01:53:46 +0000281
282#endif // AOS_COMMON_QUEUE_H_