made sure everything's thread safe
Pretty much everything already was, but I tweaked a few things to make
sure they stay that way and added various comments about that fact. Also
cleaned up a few things along the way and removed SafeMessageBuilder
because it wasn't.
diff --git a/aos/common/queue.h b/aos/common/queue.h
index 33dc377..da2a180 100644
--- a/aos/common/queue.h
+++ b/aos/common/queue.h
@@ -3,17 +3,9 @@
#include <assert.h>
-#if defined(__VXWORKS__) || defined(__TEST_VXWORKS__)
-#define USE_UNSAFE
-#else
-#undef USE_UNSAFE
-#endif
-
#include "aos/common/time.h"
#include "aos/common/macros.h"
-#ifndef USE_UNSAFE
#include "aos/linux_code/ipc_lib/queue.h"
-#endif // USE_UNSAFE
#include "aos/common/time.h"
namespace aos {
@@ -53,15 +45,11 @@
template <class T> class Queue;
template <class T> class MessageBuilder;
template <class T> class ScopedMessagePtr;
-#ifndef USE_UNSAFE
-template <class T> class SafeMessageBuilder;
-template <class T> class SafeScopedMessagePtr;
-#endif // USE_UNSAFE
// A ScopedMessagePtr<> manages a queue message pointer.
// It frees it properly when the ScopedMessagePtr<> goes out of scope or gets
// sent. By design, there is no way to get the ScopedMessagePtr to release the
-// message pointer.
+// message pointer to external code.
template <class T>
class ScopedMessagePtr {
public:
@@ -116,7 +104,6 @@
reset();
}
-#ifndef SWIG
// Implements a move constructor. This only takes rvalue references
// because we want to allow someone to say
// ScopedMessagePtr<X> ptr = queue.MakeMessage();
@@ -126,14 +113,9 @@
// clear out the source so there aren't 2 pointers to the message lying
// around.
ScopedMessagePtr(ScopedMessagePtr<T> &&ptr)
- :
-#ifndef USE_UNSAFE
- queue_(ptr.queue_),
-#endif // USE_UNSAFE
- msg_(ptr.msg_) {
+ : queue_(ptr.queue_), msg_(ptr.msg_) {
ptr.msg_ = NULL;
}
-#endif // SWIG
private:
// Provide access to set_queue and the constructor for init.
@@ -141,27 +123,20 @@
// Provide access to the copy constructor for MakeWithBuilder.
friend class aos::MessageBuilder<T>;
-#ifndef USE_UNSAFE
- // Only Queue should be able to build a queue.
+ // Only Queue should be able to build a message.
ScopedMessagePtr(RawQueue *queue, T *msg)
: queue_(queue), msg_(msg) {}
-#else
- ScopedMessagePtr(T *msg)
- : msg_(msg) {}
-#endif // USE_UNSAFE
// Sets the pointer to msg, freeing the old value if it was there.
// This is private because nobody should be able to get a pointer to a message
// that needs to be scoped without using the queue.
void reset(T *msg = NULL);
-#ifndef USE_UNSAFE
// Sets the queue that owns this message.
void set_queue(RawQueue *queue) { queue_ = queue; }
// The queue that the message is a part of.
RawQueue *queue_;
-#endif // USE_UNSAFE
// The message or NULL.
T *msg_;
@@ -171,8 +146,6 @@
// Specializations for the Builders will be automatically generated in the .q.h
// header files with all of the handy builder methods.
-// This builder uses an actual shm message pointer, which is more efficient and
-// more dangerous than the linux only SafeMessageBuilder.
template <class T>
class MessageBuilder {
public:
@@ -182,21 +155,14 @@
// TODO(aschuh): Base class
// T must be a Message with the same format as the messages generated by
-// the q files.
+// the .q files.
template <class T>
class Queue {
public:
typedef T Message;
Queue(const char *queue_name)
- : queue_name_(queue_name),
-#ifdef USE_UNSAFE
- queue_msg_(&msg_)
-#else
- queue_(NULL),
- queue_msg_(NULL, NULL)
-#endif // USE_UNSAFE
- {
+ : queue_name_(queue_name), queue_(NULL), queue_msg_(NULL, NULL) {
static_assert(shm_ok<T>::value,
"The provided message type can't be put in shmem.");
}
@@ -215,6 +181,9 @@
// Returns true if there was a new message available and we successfully
// fetched it.
bool FetchNext();
+
+ // Fetches the next message from the queue, waiting if necessary until there
+ // is one.
void FetchNextBlocking();
// Fetches the last message from the queue.
@@ -227,16 +196,17 @@
void FetchAnother();
// Returns the age of the message.
- const time::Time Age() { return time::Time::Now() - queue_msg_->sent_time; }
+ const time::Time Age() const { return time::Time::Now() - queue_msg_->sent_time; }
// Returns true if the latest value in the queue is newer than age mseconds.
- bool IsNewerThanMS(int age) {
+ // DEPRECATED(brians): Use IsNewerThan(const time::Time&) instead.
+ bool IsNewerThanMS(int age) const {
// TODO(aschuh): Log very verbosely if something is _ever_ stale.
- if (get() != NULL) {
- return Age() < time::Time::InMS(age);
- } else {
- return false;
- }
+ return IsNewerThan(time::Time::InMS(age));
+ }
+
+ bool IsNewerThan(const time::Time &age) const {
+ return get() != nullptr && Age() < age;
}
// Returns a pointer to the current message.
@@ -259,40 +229,26 @@
return msg;
}
-#ifndef USE_UNSAFE
- // Returns a scoped_ptr containing a message.
- // GCC will optimize away the copy constructor, so this is safe.
- SafeScopedMessagePtr<T> SafeMakeMessage();
-
- // Returns a message builder that contains a pre-allocated message.
- aos::SafeMessageBuilder<T> SafeMakeWithBuilder();
-#endif // USE_UNSAFE
-
-#ifndef SWIG
// Returns a scoped_ptr containing a message.
// GCC will optimize away the copy constructor, so this is safe.
ScopedMessagePtr<T> MakeMessage();
// Returns a message builder that contains a pre-allocated message.
aos::MessageBuilder<T> MakeWithBuilder();
-#endif // SWIG
const char *name() const { return queue_name_; }
private:
const char *queue_name_;
-#ifdef USE_UNSAFE
- // The unsafe queue only has 1 entry and no safety, so 1 message is fine.
- T msg_;
-#else
T *MakeRawMessage();
+
// Pointer to the queue that this object fetches from.
RawQueue *queue_;
int index_ = 0;
-#endif
// Scoped pointer holding the latest message or NULL.
ScopedMessagePtr<const T> queue_msg_;
+
DISALLOW_COPY_AND_ASSIGN(Queue<T>);
};
@@ -315,11 +271,6 @@
} // namespace aos
-#ifdef USE_UNSAFE
-#include "aos/crio/queue-tmpl.h"
-#else
#include "aos/linux_code/queue-tmpl.h"
-#endif
-#undef USE_UNSAFE
#endif // AOS_COMMON_QUEUE_H_