blob: 1897773fc7e69f80976754155d9743d641622f18 [file] [log] [blame]
John Park33858a32018-09-28 23:05:48 -07001#ifndef AOS_QUEUE_H_
2#define AOS_QUEUE_H_
brians343bc112013-02-10 01:53:46 +00003
4#include <assert.h>
5
John Park33858a32018-09-28 23:05:48 -07006#include "aos/macros.h"
John Park398c74a2018-10-20 21:17:39 -07007#include "aos/ipc_lib/queue.h"
John Park33858a32018-09-28 23:05:48 -07008#include "aos/messages/message.h"
brians343bc112013-02-10 01:53:46 +00009
brians343bc112013-02-10 01:53:46 +000010namespace aos {
11
brians343bc112013-02-10 01:53:46 +000012template <class T> class Queue;
brians343bc112013-02-10 01:53:46 +000013
14// A ScopedMessagePtr<> manages a queue message pointer.
15// It frees it properly when the ScopedMessagePtr<> goes out of scope or gets
16// sent. By design, there is no way to get the ScopedMessagePtr to release the
Brian Silverman6da04272014-05-18 18:47:48 -070017// message pointer to external code.
brians343bc112013-02-10 01:53:46 +000018template <class T>
19class ScopedMessagePtr {
20 public:
21 // Returns a pointer to the message.
22 // This stays valid until Send or the destructor have been called.
23 const T *get() const { return msg_; }
24 T *get() { return msg_; }
25
26 const T &operator*() const {
27 const T *msg = get();
28 assert(msg != NULL);
29 return *msg;
30 }
31
32 T &operator*() {
33 T *msg = get();
34 assert(msg != NULL);
35 return *msg;
36 }
37
38 const T *operator->() const {
39 const T *msg = get();
40 assert(msg != NULL);
41 return msg;
42 }
43
44 T *operator->() {
45 T *msg = get();
46 assert(msg != NULL);
47 return msg;
48 }
49
50 operator bool() {
51 return msg_ != NULL;
52 }
53
54 // Sends the message and removes our reference to it.
55 // If the queue is full, over-ride the oldest message in it with our new
56 // message.
57 // Returns true on success, and false otherwise.
58 // The message will be freed.
59 bool Send();
60
61 // Sends the message and removes our reference to it.
62 // If the queue is full, block until it is no longer full.
63 // Returns true on success, and false otherwise.
64 // The message will be freed.
65 bool SendBlocking();
66
67 // Frees the contained message.
68 ~ScopedMessagePtr() {
69 reset();
70 }
71
brians343bc112013-02-10 01:53:46 +000072 // Implements a move constructor. This only takes rvalue references
73 // because we want to allow someone to say
74 // ScopedMessagePtr<X> ptr = queue.MakeMessage();
75 // but we don't want to allow them to then say
76 // ScopedMessagePtr<X> new_ptr = ptr;
Brian Silvermanc4546d22014-02-10 18:03:09 -080077 // And, if they do actually want to move the pointer, then it will correctly
brians343bc112013-02-10 01:53:46 +000078 // clear out the source so there aren't 2 pointers to the message lying
79 // around.
80 ScopedMessagePtr(ScopedMessagePtr<T> &&ptr)
Brian Silverman6da04272014-05-18 18:47:48 -070081 : queue_(ptr.queue_), msg_(ptr.msg_) {
brians343bc112013-02-10 01:53:46 +000082 ptr.msg_ = NULL;
83 }
brians343bc112013-02-10 01:53:46 +000084
85 private:
86 // Provide access to set_queue and the constructor for init.
87 friend class aos::Queue<typename std::remove_const<T>::type>;
88 // Provide access to the copy constructor for MakeWithBuilder.
89 friend class aos::MessageBuilder<T>;
90
Brian Silverman6da04272014-05-18 18:47:48 -070091 // Only Queue should be able to build a message.
Brian Silverman08661c72013-09-01 17:24:38 -070092 ScopedMessagePtr(RawQueue *queue, T *msg)
brians343bc112013-02-10 01:53:46 +000093 : queue_(queue), msg_(msg) {}
brians343bc112013-02-10 01:53:46 +000094
95 // Sets the pointer to msg, freeing the old value if it was there.
96 // This is private because nobody should be able to get a pointer to a message
97 // that needs to be scoped without using the queue.
98 void reset(T *msg = NULL);
99
brians343bc112013-02-10 01:53:46 +0000100 // Sets the queue that owns this message.
Brian Silverman08661c72013-09-01 17:24:38 -0700101 void set_queue(RawQueue *queue) { queue_ = queue; }
brians343bc112013-02-10 01:53:46 +0000102
103 // The queue that the message is a part of.
Brian Silverman08661c72013-09-01 17:24:38 -0700104 RawQueue *queue_;
brians343bc112013-02-10 01:53:46 +0000105 // The message or NULL.
106 T *msg_;
107
108 // Protect evil constructors.
109 DISALLOW_COPY_AND_ASSIGN(ScopedMessagePtr<T>);
110};
111
brians343bc112013-02-10 01:53:46 +0000112// TODO(aschuh): Base class
113// T must be a Message with the same format as the messages generated by
Brian Silverman6da04272014-05-18 18:47:48 -0700114// the .q files.
brians343bc112013-02-10 01:53:46 +0000115template <class T>
116class Queue {
117 public:
118 typedef T Message;
119
Brian Silverman92c3f1e2015-12-08 20:21:31 -0500120 explicit Queue(const char *queue_name)
Brian Silverman6da04272014-05-18 18:47:48 -0700121 : queue_name_(queue_name), queue_(NULL), queue_msg_(NULL, NULL) {
brians343bc112013-02-10 01:53:46 +0000122 static_assert(shm_ok<T>::value,
123 "The provided message type can't be put in shmem.");
124 }
125
126 // Initializes the queue. This may optionally be called to do any one time
Brian Silvermanc4546d22014-02-10 18:03:09 -0800127 // work before sending information, and may be be called multiple times.
brians343bc112013-02-10 01:53:46 +0000128 // Init will be called when a message is sent, but this will cause sending to
129 // take a different amount of time the first cycle.
130 void Init();
131
Austin Schuhdc1c84a2013-02-23 16:33:10 -0800132 // Removes all internal references to shared memory so shared memory can be
133 // restarted safely. This should only be used in testing.
134 void Clear();
135
brians343bc112013-02-10 01:53:46 +0000136 // Fetches the next message from the queue.
137 // Returns true if there was a new message available and we successfully
Brian Silverman428de562014-04-10 15:59:19 -0700138 // fetched it.
brians343bc112013-02-10 01:53:46 +0000139 bool FetchNext();
Brian Silverman6da04272014-05-18 18:47:48 -0700140
141 // Fetches the next message from the queue, waiting if necessary until there
142 // is one.
Brian Silverman428de562014-04-10 15:59:19 -0700143 void FetchNextBlocking();
brians343bc112013-02-10 01:53:46 +0000144
145 // Fetches the last message from the queue.
146 // Returns true if there was a new message available and we successfully
147 // fetched it.
148 bool FetchLatest();
149
Austin Schuh867c11e2015-02-22 21:35:43 -0800150 // Fetches the latest message from the queue, or blocks if we have already
151 // fetched it until another is avilable.
Brian Silverman428de562014-04-10 15:59:19 -0700152 void FetchAnother();
153
brians343bc112013-02-10 01:53:46 +0000154 // Returns the age of the message.
Austin Schuhf2a50ba2016-12-24 16:16:26 -0800155 const monotonic_clock::duration Age() const {
156 return monotonic_clock::now() - queue_msg_->sent_time;
Brian Silverman5d3ab7f2015-02-21 15:54:21 -0500157 }
brians343bc112013-02-10 01:53:46 +0000158
Austin Schuhf2a50ba2016-12-24 16:16:26 -0800159 bool IsNewerThan(const monotonic_clock::duration age) const {
Brian Silverman6da04272014-05-18 18:47:48 -0700160 return get() != nullptr && Age() < age;
brians343bc112013-02-10 01:53:46 +0000161 }
162
163 // Returns a pointer to the current message.
164 // This pointer will be valid until a new message is fetched.
165 const T *get() const { return queue_msg_.get(); }
166
167 // Returns a reference to the message.
168 // The message will be valid until a new message is fetched.
169 const T &operator*() const {
170 const T *msg = get();
171 assert(msg != NULL);
172 return *msg;
173 }
174
175 // Returns a pointer to the current message.
176 // This pointer will be valid until a new message is fetched.
177 const T *operator->() const {
178 const T *msg = get();
179 assert(msg != NULL);
180 return msg;
181 }
182
brians343bc112013-02-10 01:53:46 +0000183 // Returns a scoped_ptr containing a message.
184 // GCC will optimize away the copy constructor, so this is safe.
185 ScopedMessagePtr<T> MakeMessage();
186
187 // Returns a message builder that contains a pre-allocated message.
Brian Silverman42456d82014-08-19 12:43:59 -0400188 // This message will start out completely zeroed.
brians343bc112013-02-10 01:53:46 +0000189 aos::MessageBuilder<T> MakeWithBuilder();
brians343bc112013-02-10 01:53:46 +0000190
191 const char *name() const { return queue_name_; }
192
193 private:
194 const char *queue_name_;
195
brians343bc112013-02-10 01:53:46 +0000196 T *MakeRawMessage();
Brian Silverman6da04272014-05-18 18:47:48 -0700197
brians343bc112013-02-10 01:53:46 +0000198 // Pointer to the queue that this object fetches from.
Brian Silverman08661c72013-09-01 17:24:38 -0700199 RawQueue *queue_;
Austin Schuh287d98e2014-03-09 00:41:55 -0800200 int index_ = 0;
brians343bc112013-02-10 01:53:46 +0000201 // Scoped pointer holding the latest message or NULL.
202 ScopedMessagePtr<const T> queue_msg_;
Brian Silverman6da04272014-05-18 18:47:48 -0700203
brians343bc112013-02-10 01:53:46 +0000204 DISALLOW_COPY_AND_ASSIGN(Queue<T>);
205};
206
207// Base class for all queue groups.
208class QueueGroup {
209 public:
210 // Constructs a queue group given its name and a unique hash of the name and
211 // type.
212 QueueGroup(const char *name, uint32_t hash) : name_(name), hash_(hash) {}
213
214 // Returns the name of the queue group.
215 const char *name() const { return name_.c_str(); }
216 // Returns a unique hash representing this instance of the queue group.
217 uint32_t hash() const { return hash_; }
218
219 private:
220 std::string name_;
221 uint32_t hash_;
222};
223
224} // namespace aos
225
John Park398c74a2018-10-20 21:17:39 -0700226#include "aos/queue-tmpl.h"
brians343bc112013-02-10 01:53:46 +0000227
John Park33858a32018-09-28 23:05:48 -0700228#endif // AOS_QUEUE_H_