blob: fb11f4f37dda2fbfac3f6ac01fa0839858fa755c [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
brians343bc112013-02-10 01:53:46 +000061 // Frees the contained message.
62 ~ScopedMessagePtr() {
63 reset();
64 }
65
brians343bc112013-02-10 01:53:46 +000066 // Implements a move constructor. This only takes rvalue references
67 // because we want to allow someone to say
68 // ScopedMessagePtr<X> ptr = queue.MakeMessage();
69 // but we don't want to allow them to then say
70 // ScopedMessagePtr<X> new_ptr = ptr;
Brian Silvermanc4546d22014-02-10 18:03:09 -080071 // And, if they do actually want to move the pointer, then it will correctly
brians343bc112013-02-10 01:53:46 +000072 // clear out the source so there aren't 2 pointers to the message lying
73 // around.
74 ScopedMessagePtr(ScopedMessagePtr<T> &&ptr)
Brian Silverman6da04272014-05-18 18:47:48 -070075 : queue_(ptr.queue_), msg_(ptr.msg_) {
brians343bc112013-02-10 01:53:46 +000076 ptr.msg_ = NULL;
77 }
brians343bc112013-02-10 01:53:46 +000078
79 private:
80 // Provide access to set_queue and the constructor for init.
81 friend class aos::Queue<typename std::remove_const<T>::type>;
82 // Provide access to the copy constructor for MakeWithBuilder.
83 friend class aos::MessageBuilder<T>;
84
Brian Silverman6da04272014-05-18 18:47:48 -070085 // Only Queue should be able to build a message.
Brian Silverman08661c72013-09-01 17:24:38 -070086 ScopedMessagePtr(RawQueue *queue, T *msg)
brians343bc112013-02-10 01:53:46 +000087 : queue_(queue), msg_(msg) {}
brians343bc112013-02-10 01:53:46 +000088
89 // Sets the pointer to msg, freeing the old value if it was there.
90 // This is private because nobody should be able to get a pointer to a message
91 // that needs to be scoped without using the queue.
92 void reset(T *msg = NULL);
93
brians343bc112013-02-10 01:53:46 +000094 // Sets the queue that owns this message.
Brian Silverman08661c72013-09-01 17:24:38 -070095 void set_queue(RawQueue *queue) { queue_ = queue; }
brians343bc112013-02-10 01:53:46 +000096
97 // The queue that the message is a part of.
Brian Silverman08661c72013-09-01 17:24:38 -070098 RawQueue *queue_;
brians343bc112013-02-10 01:53:46 +000099 // The message or NULL.
100 T *msg_;
101
102 // Protect evil constructors.
103 DISALLOW_COPY_AND_ASSIGN(ScopedMessagePtr<T>);
104};
105
brians343bc112013-02-10 01:53:46 +0000106// TODO(aschuh): Base class
107// T must be a Message with the same format as the messages generated by
Brian Silverman6da04272014-05-18 18:47:48 -0700108// the .q files.
brians343bc112013-02-10 01:53:46 +0000109template <class T>
110class Queue {
111 public:
112 typedef T Message;
113
Brian Silverman92c3f1e2015-12-08 20:21:31 -0500114 explicit Queue(const char *queue_name)
Brian Silverman6da04272014-05-18 18:47:48 -0700115 : queue_name_(queue_name), queue_(NULL), queue_msg_(NULL, NULL) {
brians343bc112013-02-10 01:53:46 +0000116 static_assert(shm_ok<T>::value,
117 "The provided message type can't be put in shmem.");
118 }
119
120 // Initializes the queue. This may optionally be called to do any one time
Brian Silvermanc4546d22014-02-10 18:03:09 -0800121 // work before sending information, and may be be called multiple times.
brians343bc112013-02-10 01:53:46 +0000122 // Init will be called when a message is sent, but this will cause sending to
123 // take a different amount of time the first cycle.
124 void Init();
125
Austin Schuhdc1c84a2013-02-23 16:33:10 -0800126 // Removes all internal references to shared memory so shared memory can be
127 // restarted safely. This should only be used in testing.
128 void Clear();
129
brians343bc112013-02-10 01:53:46 +0000130 // Fetches the next message from the queue.
131 // Returns true if there was a new message available and we successfully
Brian Silverman428de562014-04-10 15:59:19 -0700132 // fetched it.
brians343bc112013-02-10 01:53:46 +0000133 bool FetchNext();
Brian Silverman6da04272014-05-18 18:47:48 -0700134
135 // Fetches the next message from the queue, waiting if necessary until there
136 // is one.
Brian Silverman428de562014-04-10 15:59:19 -0700137 void FetchNextBlocking();
brians343bc112013-02-10 01:53:46 +0000138
139 // Fetches the last message from the queue.
140 // Returns true if there was a new message available and we successfully
141 // fetched it.
142 bool FetchLatest();
143
Austin Schuh867c11e2015-02-22 21:35:43 -0800144 // Fetches the latest message from the queue, or blocks if we have already
145 // fetched it until another is avilable.
Brian Silverman428de562014-04-10 15:59:19 -0700146 void FetchAnother();
147
brians343bc112013-02-10 01:53:46 +0000148 // Returns the age of the message.
Austin Schuhf2a50ba2016-12-24 16:16:26 -0800149 const monotonic_clock::duration Age() const {
150 return monotonic_clock::now() - queue_msg_->sent_time;
Brian Silverman5d3ab7f2015-02-21 15:54:21 -0500151 }
brians343bc112013-02-10 01:53:46 +0000152
Austin Schuhf2a50ba2016-12-24 16:16:26 -0800153 bool IsNewerThan(const monotonic_clock::duration age) const {
Brian Silverman6da04272014-05-18 18:47:48 -0700154 return get() != nullptr && Age() < age;
brians343bc112013-02-10 01:53:46 +0000155 }
156
157 // Returns a pointer to the current message.
158 // This pointer will be valid until a new message is fetched.
159 const T *get() const { return queue_msg_.get(); }
160
161 // Returns a reference to the message.
162 // The message will be valid until a new message is fetched.
163 const T &operator*() const {
164 const T *msg = get();
165 assert(msg != NULL);
166 return *msg;
167 }
168
169 // Returns a pointer to the current message.
170 // This pointer will be valid until a new message is fetched.
171 const T *operator->() const {
172 const T *msg = get();
173 assert(msg != NULL);
174 return msg;
175 }
176
brians343bc112013-02-10 01:53:46 +0000177 // Returns a scoped_ptr containing a message.
178 // GCC will optimize away the copy constructor, so this is safe.
179 ScopedMessagePtr<T> MakeMessage();
180
181 // Returns a message builder that contains a pre-allocated message.
Brian Silverman42456d82014-08-19 12:43:59 -0400182 // This message will start out completely zeroed.
brians343bc112013-02-10 01:53:46 +0000183 aos::MessageBuilder<T> MakeWithBuilder();
brians343bc112013-02-10 01:53:46 +0000184
185 const char *name() const { return queue_name_; }
186
187 private:
188 const char *queue_name_;
189
brians343bc112013-02-10 01:53:46 +0000190 T *MakeRawMessage();
Brian Silverman6da04272014-05-18 18:47:48 -0700191
brians343bc112013-02-10 01:53:46 +0000192 // Pointer to the queue that this object fetches from.
Brian Silverman08661c72013-09-01 17:24:38 -0700193 RawQueue *queue_;
Austin Schuh287d98e2014-03-09 00:41:55 -0800194 int index_ = 0;
brians343bc112013-02-10 01:53:46 +0000195 // Scoped pointer holding the latest message or NULL.
196 ScopedMessagePtr<const T> queue_msg_;
Brian Silverman6da04272014-05-18 18:47:48 -0700197
brians343bc112013-02-10 01:53:46 +0000198 DISALLOW_COPY_AND_ASSIGN(Queue<T>);
199};
200
201// Base class for all queue groups.
202class QueueGroup {
203 public:
204 // Constructs a queue group given its name and a unique hash of the name and
205 // type.
Austin Schuh7660fcd2019-01-27 13:07:52 -0800206 QueueGroup(const char *name) : name_(name) {}
brians343bc112013-02-10 01:53:46 +0000207
208 // Returns the name of the queue group.
209 const char *name() const { return name_.c_str(); }
brians343bc112013-02-10 01:53:46 +0000210
211 private:
212 std::string name_;
brians343bc112013-02-10 01:53:46 +0000213};
214
215} // namespace aos
216
John Park398c74a2018-10-20 21:17:39 -0700217#include "aos/queue-tmpl.h"
brians343bc112013-02-10 01:53:46 +0000218
John Park33858a32018-09-28 23:05:48 -0700219#endif // AOS_QUEUE_H_