blob: 7f43a3e117ac1a3ac56ac557ad907704700017cb [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:
brians343bc112013-02-10 01:53:46 +000019 // The time that the message was sent at.
Austin Schuhf2a50ba2016-12-24 16:16:26 -080020 monotonic_clock::time_point sent_time;
brians343bc112013-02-10 01:53:46 +000021
Austin Schuhf2a50ba2016-12-24 16:16:26 -080022 Message() : sent_time(monotonic_clock::min_time) {}
brians343bc112013-02-10 01:53:46 +000023
24 // Zeros out the time.
25 void Zero();
Brian Silvermanc4546d22014-02-10 18:03:09 -080026 // Returns the size of the common fields.
Austin Schuhf2a50ba2016-12-24 16:16:26 -080027 static size_t Size() { return sizeof(sent_time); }
brians343bc112013-02-10 01:53:46 +000028
29 // Deserializes the common fields from the buffer.
30 size_t Deserialize(const char *buffer);
31 // Serializes the common fields into the buffer.
32 size_t Serialize(char *buffer) const;
33
34 // Populates sent_time with the current time.
Austin Schuhf2a50ba2016-12-24 16:16:26 -080035 void SetTimeToNow() { sent_time = monotonic_clock::now(); }
brians343bc112013-02-10 01:53:46 +000036
37 // Writes the contents of the message to the provided buffer.
38 size_t Print(char *buffer, int length) const;
Brian Silvermanc4546d22014-02-10 18:03:09 -080039
Brian Silverman88457ef2015-02-23 01:56:10 -050040 // Compares two messages for equality, excluding their sent_time.
41 bool EqualsNoTime(const Message & /*other*/) const { return true; }
42
Brian Silverman665e60c2014-02-12 13:57:10 -080043 static const MessageType *GetType();
brians343bc112013-02-10 01:53:46 +000044};
45
46template <class T> class Queue;
47template <class T> class MessageBuilder;
48template <class T> class ScopedMessagePtr;
brians343bc112013-02-10 01:53:46 +000049
50// A ScopedMessagePtr<> manages a queue message pointer.
51// It frees it properly when the ScopedMessagePtr<> goes out of scope or gets
52// sent. By design, there is no way to get the ScopedMessagePtr to release the
Brian Silverman6da04272014-05-18 18:47:48 -070053// message pointer to external code.
brians343bc112013-02-10 01:53:46 +000054template <class T>
55class ScopedMessagePtr {
56 public:
57 // Returns a pointer to the message.
58 // This stays valid until Send or the destructor have been called.
59 const T *get() const { return msg_; }
60 T *get() { return msg_; }
61
62 const T &operator*() const {
63 const T *msg = get();
64 assert(msg != NULL);
65 return *msg;
66 }
67
68 T &operator*() {
69 T *msg = get();
70 assert(msg != NULL);
71 return *msg;
72 }
73
74 const T *operator->() const {
75 const T *msg = get();
76 assert(msg != NULL);
77 return msg;
78 }
79
80 T *operator->() {
81 T *msg = get();
82 assert(msg != NULL);
83 return msg;
84 }
85
86 operator bool() {
87 return msg_ != NULL;
88 }
89
90 // Sends the message and removes our reference to it.
91 // If the queue is full, over-ride the oldest message in it with our new
92 // message.
93 // Returns true on success, and false otherwise.
94 // The message will be freed.
95 bool Send();
96
97 // Sends the message and removes our reference to it.
98 // If the queue is full, block until it is no longer full.
99 // Returns true on success, and false otherwise.
100 // The message will be freed.
101 bool SendBlocking();
102
103 // Frees the contained message.
104 ~ScopedMessagePtr() {
105 reset();
106 }
107
brians343bc112013-02-10 01:53:46 +0000108 // Implements a move constructor. This only takes rvalue references
109 // because we want to allow someone to say
110 // ScopedMessagePtr<X> ptr = queue.MakeMessage();
111 // but we don't want to allow them to then say
112 // ScopedMessagePtr<X> new_ptr = ptr;
Brian Silvermanc4546d22014-02-10 18:03:09 -0800113 // And, if they do actually want to move the pointer, then it will correctly
brians343bc112013-02-10 01:53:46 +0000114 // clear out the source so there aren't 2 pointers to the message lying
115 // around.
116 ScopedMessagePtr(ScopedMessagePtr<T> &&ptr)
Brian Silverman6da04272014-05-18 18:47:48 -0700117 : queue_(ptr.queue_), msg_(ptr.msg_) {
brians343bc112013-02-10 01:53:46 +0000118 ptr.msg_ = NULL;
119 }
brians343bc112013-02-10 01:53:46 +0000120
121 private:
122 // Provide access to set_queue and the constructor for init.
123 friend class aos::Queue<typename std::remove_const<T>::type>;
124 // Provide access to the copy constructor for MakeWithBuilder.
125 friend class aos::MessageBuilder<T>;
126
Brian Silverman6da04272014-05-18 18:47:48 -0700127 // Only Queue should be able to build a message.
Brian Silverman08661c72013-09-01 17:24:38 -0700128 ScopedMessagePtr(RawQueue *queue, T *msg)
brians343bc112013-02-10 01:53:46 +0000129 : queue_(queue), msg_(msg) {}
brians343bc112013-02-10 01:53:46 +0000130
131 // Sets the pointer to msg, freeing the old value if it was there.
132 // This is private because nobody should be able to get a pointer to a message
133 // that needs to be scoped without using the queue.
134 void reset(T *msg = NULL);
135
brians343bc112013-02-10 01:53:46 +0000136 // Sets the queue that owns this message.
Brian Silverman08661c72013-09-01 17:24:38 -0700137 void set_queue(RawQueue *queue) { queue_ = queue; }
brians343bc112013-02-10 01:53:46 +0000138
139 // The queue that the message is a part of.
Brian Silverman08661c72013-09-01 17:24:38 -0700140 RawQueue *queue_;
brians343bc112013-02-10 01:53:46 +0000141 // The message or NULL.
142 T *msg_;
143
144 // Protect evil constructors.
145 DISALLOW_COPY_AND_ASSIGN(ScopedMessagePtr<T>);
146};
147
148// Specializations for the Builders will be automatically generated in the .q.h
149// header files with all of the handy builder methods.
brians343bc112013-02-10 01:53:46 +0000150template <class T>
151class MessageBuilder {
152 public:
153 typedef T Message;
154 bool Send();
155};
156
157// TODO(aschuh): Base class
158// T must be a Message with the same format as the messages generated by
Brian Silverman6da04272014-05-18 18:47:48 -0700159// the .q files.
brians343bc112013-02-10 01:53:46 +0000160template <class T>
161class Queue {
162 public:
163 typedef T Message;
164
Brian Silverman92c3f1e2015-12-08 20:21:31 -0500165 explicit Queue(const char *queue_name)
Brian Silverman6da04272014-05-18 18:47:48 -0700166 : queue_name_(queue_name), queue_(NULL), queue_msg_(NULL, NULL) {
brians343bc112013-02-10 01:53:46 +0000167 static_assert(shm_ok<T>::value,
168 "The provided message type can't be put in shmem.");
169 }
170
171 // Initializes the queue. This may optionally be called to do any one time
Brian Silvermanc4546d22014-02-10 18:03:09 -0800172 // work before sending information, and may be be called multiple times.
brians343bc112013-02-10 01:53:46 +0000173 // Init will be called when a message is sent, but this will cause sending to
174 // take a different amount of time the first cycle.
175 void Init();
176
Austin Schuhdc1c84a2013-02-23 16:33:10 -0800177 // Removes all internal references to shared memory so shared memory can be
178 // restarted safely. This should only be used in testing.
179 void Clear();
180
brians343bc112013-02-10 01:53:46 +0000181 // Fetches the next message from the queue.
182 // Returns true if there was a new message available and we successfully
Brian Silverman428de562014-04-10 15:59:19 -0700183 // fetched it.
brians343bc112013-02-10 01:53:46 +0000184 bool FetchNext();
Brian Silverman6da04272014-05-18 18:47:48 -0700185
186 // Fetches the next message from the queue, waiting if necessary until there
187 // is one.
Brian Silverman428de562014-04-10 15:59:19 -0700188 void FetchNextBlocking();
brians343bc112013-02-10 01:53:46 +0000189
190 // Fetches the last message from the queue.
191 // Returns true if there was a new message available and we successfully
192 // fetched it.
193 bool FetchLatest();
194
Austin Schuh867c11e2015-02-22 21:35:43 -0800195 // Fetches the latest message from the queue, or blocks if we have already
196 // fetched it until another is avilable.
Brian Silverman428de562014-04-10 15:59:19 -0700197 void FetchAnother();
198
brians343bc112013-02-10 01:53:46 +0000199 // Returns the age of the message.
Austin Schuhf2a50ba2016-12-24 16:16:26 -0800200 const monotonic_clock::duration Age() const {
201 return monotonic_clock::now() - queue_msg_->sent_time;
Brian Silverman5d3ab7f2015-02-21 15:54:21 -0500202 }
brians343bc112013-02-10 01:53:46 +0000203
Austin Schuhf2a50ba2016-12-24 16:16:26 -0800204 bool IsNewerThan(const monotonic_clock::duration age) const {
Brian Silverman6da04272014-05-18 18:47:48 -0700205 return get() != nullptr && Age() < age;
brians343bc112013-02-10 01:53:46 +0000206 }
207
208 // Returns a pointer to the current message.
209 // This pointer will be valid until a new message is fetched.
210 const T *get() const { return queue_msg_.get(); }
211
212 // Returns a reference to the message.
213 // The message will be valid until a new message is fetched.
214 const T &operator*() const {
215 const T *msg = get();
216 assert(msg != NULL);
217 return *msg;
218 }
219
220 // Returns a pointer to the current message.
221 // This pointer 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
brians343bc112013-02-10 01:53:46 +0000228 // Returns a scoped_ptr containing a message.
229 // GCC will optimize away the copy constructor, so this is safe.
230 ScopedMessagePtr<T> MakeMessage();
231
232 // Returns a message builder that contains a pre-allocated message.
Brian Silverman42456d82014-08-19 12:43:59 -0400233 // This message will start out completely zeroed.
brians343bc112013-02-10 01:53:46 +0000234 aos::MessageBuilder<T> MakeWithBuilder();
brians343bc112013-02-10 01:53:46 +0000235
236 const char *name() const { return queue_name_; }
237
238 private:
239 const char *queue_name_;
240
brians343bc112013-02-10 01:53:46 +0000241 T *MakeRawMessage();
Brian Silverman6da04272014-05-18 18:47:48 -0700242
brians343bc112013-02-10 01:53:46 +0000243 // Pointer to the queue that this object fetches from.
Brian Silverman08661c72013-09-01 17:24:38 -0700244 RawQueue *queue_;
Austin Schuh287d98e2014-03-09 00:41:55 -0800245 int index_ = 0;
brians343bc112013-02-10 01:53:46 +0000246 // Scoped pointer holding the latest message or NULL.
247 ScopedMessagePtr<const T> queue_msg_;
Brian Silverman6da04272014-05-18 18:47:48 -0700248
brians343bc112013-02-10 01:53:46 +0000249 DISALLOW_COPY_AND_ASSIGN(Queue<T>);
250};
251
252// Base class for all queue groups.
253class QueueGroup {
254 public:
255 // Constructs a queue group given its name and a unique hash of the name and
256 // type.
257 QueueGroup(const char *name, uint32_t hash) : name_(name), hash_(hash) {}
258
259 // Returns the name of the queue group.
260 const char *name() const { return name_.c_str(); }
261 // Returns a unique hash representing this instance of the queue group.
262 uint32_t hash() const { return hash_; }
263
264 private:
265 std::string name_;
266 uint32_t hash_;
267};
268
269} // namespace aos
270
Brian Silverman14fd0fb2014-01-14 21:42:01 -0800271#include "aos/linux_code/queue-tmpl.h"
brians343bc112013-02-10 01:53:46 +0000272
273#endif // AOS_COMMON_QUEUE_H_