Implement simulated FetchNext and fix its behavior
Simulation was missing FetchNext, so let's add that. And since this is
core infrastructure, add tests.
These tests caught that ShmEventLoop was fetching messages sent before
the fetcher was constructed. This behavior is confusing and wrong. So
fix it.
Change-Id: I03c79731688a150e30ba871dee13b7c9c68e75b7
diff --git a/aos/events/shm-event-loop.cc b/aos/events/shm-event-loop.cc
index c4c2c88..11d9312 100644
--- a/aos/events/shm-event-loop.cc
+++ b/aos/events/shm-event-loop.cc
@@ -16,7 +16,14 @@
namespace {
class ShmFetcher : public RawFetcher {
public:
- explicit ShmFetcher(RawQueue *queue) : queue_(queue) {}
+ explicit ShmFetcher(RawQueue *queue) : queue_(queue) {
+ // Move index_ to point to the end of the queue as it is at construction
+ // time. Also grab the oldest message but don't expose it to the user yet.
+ static constexpr Options<RawQueue> kOptions =
+ RawQueue::kFromEnd | RawQueue::kNonBlock;
+ msg_ = static_cast<const FetchValue *>(
+ queue_->ReadMessageIndex(kOptions, &index_));
+ }
~ShmFetcher() {
if (msg_) {
queue_->FreeMessage(msg_);
@@ -27,12 +34,12 @@
const FetchValue *msg = static_cast<const FetchValue *>(
queue_->ReadMessageIndex(RawQueue::kNonBlock, &index_));
// Only update the internal pointer if we got a new message.
- if (msg != NULL) {
+ if (msg != nullptr) {
queue_->FreeMessage(msg_);
msg_ = msg;
set_most_recent(msg_);
}
- return msg != NULL;
+ return msg != nullptr;
}
bool Fetch() override {
@@ -41,16 +48,24 @@
const FetchValue *msg = static_cast<const FetchValue *>(
queue_->ReadMessageIndex(kOptions, &index_));
// Only update the internal pointer if we got a new message.
- if (msg != NULL && msg != msg_) {
+ if (msg != nullptr && msg != msg_) {
queue_->FreeMessage(msg_);
msg_ = msg;
set_most_recent(msg_);
return true;
+ } else {
+ // The message has to get freed if we didn't use it (and
+ // RawQueue::FreeMessage is ok to call on nullptr).
+ queue_->FreeMessage(msg);
+
+ // We have a message from construction time. Give it to the user now.
+ if (msg_ != nullptr && most_recent() != msg_) {
+ set_most_recent(msg_);
+ return true;
+ } else {
+ return false;
+ }
}
- // The message has to get freed if we didn't use it (and
- // RawQueue::FreeMessage is ok to call on NULL).
- queue_->FreeMessage(msg);
- return false;
}
private:
@@ -70,7 +85,7 @@
void Free(aos::Message *msg) override { queue_->FreeMessage(msg); }
bool Send(aos::Message *msg) override {
- assert(queue_ != NULL);
+ assert(queue_ != nullptr);
{
// TODO(austin): This lets multiple senders reorder messages since time
// isn't acquired with a lock held.