blob: 6cf28350513cee8bc29f7733b9cf758f1805c19a [file] [log] [blame]
brians343bc112013-02-10 01:53:46 +00001#ifndef __AOS_MESSAGES_QUEUE_HOLDER_H_
2#define __AOS_MESSAGES_QUEUE_HOLDER_H_
3
4#include <stddef.h>
5
6#include <algorithm>
7
8#include "aos/aos_core.h"
9#include "aos/common/control_loop/Timing.h"
10#include "aos/common/byteorder.h"
11#include "aos/common/time.h"
12#include "aos/common/type_traits.h"
13
14namespace aos {
15
16// Specializations of TypeOperator and QueueBuilder that are actually
17// implemented are created in the generated code for all message value types.
18// These specializations have the same functions declared in the actual types.
19
20// Defines a way for types to be manipulated.
21template<typename T> class TypeOperator {
22 public:
23 // Sets all fields to their default constructor.
24 static void Zero(T &t_);
25 // Returns the size of buffer NToH and HToN use.
26 static size_t Size();
27 // Converts everything from network to host byte order.
28 // input must have Size() bytes available in it.
29 static void NToH(char *input, T &t_);
30 // Converts everything from host to network byte order and puts it into output.
31 // output must have Size() bytes available in it.
32 static void HToN(const T &t_, char *output);
33 // Creates a string with the names and values of all the fields.
34 // The return value might will be to a static buffer.
35 static const char *Print(const T &t_);
36};
37
38template<typename T> class QueueHolder;
39
40// An easy way to set values for queue messages.
41// Each specialization has chainable setter functions for building a message
42// of type T to put into a queue (like QueueBuilder<T> &field(int value);).
43template<class T> class QueueBuilder {
44 public:
45 QueueBuilder(QueueHolder<T> &holder);
46 bool Send();
47};
48
49// Internal class to make implementing identical behavior with structs that go
50// into queues easier. Also a central location for the documentation.
51//
52// When compiled for the cRIO, everything except Clear does nothing (and Get
53// turns into just a Clear) which means that the internal T instance is the only one.
54// Also, the internal instance becomes static.
55//
56// To look at the current message, you Get a copy and then View the result.
57// To make changes, you modify the message that you can View (after possibly
58// Clearing it) and then you Send it. You can also just Clear the message, put
59// data into it, and then Send it. A way to modify the local message is using
60// the Builder function.
61// Note that there is no way to avoid potentially overwriting other changes between
62// when you Get one and when you Send it (mainly applicable to 1-length queues).
63//
64// T must be POD and have a "timespec set_time;" field.
65//
66// This first class doesn't have the builder; QueueHolder does.
67#define aos_check_rv __attribute__((warn_unused_result))
68template<typename T> class QueueHolderNoBuilder {
69#ifndef __VXWORKS__
70 aos_queue *const queue_;
71 static_assert(shm_ok<T>::value, "T must be able to"
72 " go through shared memory and memcpy");
73 T t_;
74#else
75 static T t_;
76#endif
77 public:
78#ifndef __VXWORKS__
79 explicit QueueHolderNoBuilder(aos_queue *queue) : queue_(queue) {}
80#else
81 QueueHolderNoBuilder() {}
82#endif
83 // Gets the current value and stores it in View().
84 // check_time is whether or not to check to see if the last time a value was Sent
85 // was too long ago (returns false if it was)
86 // Returns true if View() is now the current value.
87 // IMPORTANT: If this function returns false, the contents of View() are
88 // either the same as they were before or (if check_time is true) the current
89 // message. That is why it creates compile-time warnings if the return value
90 // is not checked.
91 bool Get(bool check_time) aos_check_rv;
92 // Looks at the current value. Starts out undefined.
93 // If the last Get call returned false, then this the contents of the
94 // return value are undefined.
95#ifdef __VXWORKS__
96 static
97#endif
98 inline T &View() { return t_; }
99 // Clears (calls the default constructor of) all the fields of the current
100 // Goal.
101 void Clear() { TypeOperator<T>::Zero(t_); }
102 // Sends the current value. Does not affect the current value.
103 // Returns whether or not the Send succeeded.
104 bool Send();
105 // Returns a string containing the values of all the fields in the current
106 // value.
107 // The return value is valid until Print is called again. The class owns the
108 // memory.
109 const char *Print() const { return TypeOperator<T>::Print(t_); }
110};
111
112template<typename T>
113bool QueueHolderNoBuilder<T>::Get(bool check_time) {
114#ifdef __VXWORKS__
115 (void)check_time;
116 return true;
117#else
118 const T *msg = static_cast<const T *>(aos_queue_read_msg(queue_,
119 PEEK | NON_BLOCK));
120 if (msg == NULL) {
121 return false;
122 }
123 static_assert(sizeof(t_) == sizeof(*msg), "something is wrong here");
124 memcpy(&t_, msg, sizeof(t_));
125 aos_queue_free_msg(queue_, msg);
126 if (check_time && !((time::Time::Now() - time::Time(t_.set_time)) > time::Time::InMS(45))) {
127 LOG(WARNING, "too long since last Set msg={%s}\n", Print());
128 return false;
129 } else {
130 return true;
131 }
132#endif
133}
134template<typename T>
135bool QueueHolderNoBuilder<T>::Send() {
136#ifndef __VXWORKS__
137 T *msg = static_cast<T *>(aos_queue_get_msg(queue_));
138 if (msg == NULL) {
139 return false;
140 }
141 static_assert(sizeof(*msg) == sizeof(t_), "something is wrong here");
142 memcpy(msg, &t_, sizeof(t_));
143 msg->set_time = ::aos::time::Time::Now().ToTimespec();
144
145 return aos_queue_write_msg_free(queue_, msg, OVERRIDE) == 0;
146#else
147 return true;
148#endif
149}
150#ifdef __VXWORKS__
151template<typename T> T QueueHolderNoBuilder<T>::t_;
152#endif
153template<typename T> class QueueHolder : public QueueHolderNoBuilder<T> {
154 QueueBuilder<T> builder_;
155 public:
156#ifndef __VXWORKS__
157 explicit QueueHolder(aos_queue *queue) : QueueHolderNoBuilder<T>(queue),
158 builder_(*this) {}
159#else
160 QueueHolder() : builder_(*this) {}
161#endif
162 // Clears the current Goal and returns an object that allows setting various
163 // fields with chained method calls and then calling Send() on it.
164 QueueBuilder<T> &Builder() {
165 QueueHolderNoBuilder<T>::Clear();
166 return builder_;
167 }
168};
169
170} // namespace aos
171
172#endif
173