Add channel method to fetchers and senders.
This makes it easy to figure out which channel a fetcher or sender
is connected to.
Also add a test to confirm that the channel pointer points to a channel
inside configuration() for the event loop.
Change-Id: Iee0edca66394ef825dac482d7e3f568c6ed3441f
diff --git a/aos/events/BUILD b/aos/events/BUILD
index 3b3fb52..53b3b05 100644
--- a/aos/events/BUILD
+++ b/aos/events/BUILD
@@ -34,7 +34,10 @@
cc_library(
name = "event_loop",
- srcs = ["event_loop_tmpl.h"],
+ srcs = [
+ "event_loop.cc",
+ "event_loop_tmpl.h",
+ ],
hdrs = [
"event_loop.h",
],
diff --git a/aos/events/event_loop.cc b/aos/events/event_loop.cc
new file mode 100644
index 0000000..6891f92
--- /dev/null
+++ b/aos/events/event_loop.cc
@@ -0,0 +1,18 @@
+#include "aos/events/event_loop.h"
+
+#include "aos/configuration.h"
+#include "aos/configuration_generated.h"
+#include "glog/logging.h"
+
+namespace aos {
+
+void EventLoop::ValidateChannel(const Channel *channel) {
+ CHECK(configuration_->channels() != nullptr) << ": No channels";
+
+ CHECK(std::find(configuration_->channels()->begin(),
+ configuration_->channels()->end(),
+ channel) != configuration_->channels()->end())
+ << ": Channel pointer not found in configuration()->channels()";
+}
+
+} // namespace aos
diff --git a/aos/events/event_loop.h b/aos/events/event_loop.h
index f614517..278fc9c 100644
--- a/aos/events/event_loop.h
+++ b/aos/events/event_loop.h
@@ -34,7 +34,7 @@
// fetchers.
class RawFetcher {
public:
- RawFetcher() {}
+ RawFetcher(const Channel *channel) : channel_(channel) {}
virtual ~RawFetcher() {}
// Non-blocking fetch of the next message in the queue. Returns true if there
@@ -50,19 +50,22 @@
const Context &context() const { return context_; }
+ const Channel *channel() const { return channel_; }
+
protected:
RawFetcher(const RawFetcher &) = delete;
RawFetcher &operator=(const RawFetcher &) = delete;
void *data_ = nullptr;
Context context_;
+ const Channel *channel_;
};
// Raw version of sender. Sends a block of data. This is used for reflection
// and as a building block to implement typed senders.
class RawSender {
public:
- RawSender() {}
+ RawSender(const Channel *channel) : channel_(channel) {}
virtual ~RawSender() {}
// Sends a message without copying it. The users starts by copying up to
@@ -78,9 +81,13 @@
// Returns the name of this sender.
virtual const absl::string_view name() const = 0;
+ const Channel *channel() const { return channel_; }
+
protected:
RawSender(const RawSender &) = delete;
RawSender &operator=(const RawSender &) = delete;
+
+ const Channel *channel_;
};
@@ -306,11 +313,14 @@
// Returns the configuration that this event loop was built with.
const Configuration *configuration() const { return configuration_; }
+ // Will send new messages from channel (path, type).
+ virtual std::unique_ptr<RawSender> MakeRawSender(const Channel *channel) = 0;
+
protected:
void set_is_running(bool value) { is_running_.store(value); }
- // Will send new messages from channel (path, type).
- virtual std::unique_ptr<RawSender> MakeRawSender(const Channel *channel) = 0;
+ // Validates that channel exists inside configuration_.
+ void ValidateChannel(const Channel *channel);
private:
::std::atomic<bool> is_running_{false};
diff --git a/aos/events/event_loop_param_test.cc b/aos/events/event_loop_param_test.cc
index 8a0f9b6..3cace56 100644
--- a/aos/events/event_loop_param_test.cc
+++ b/aos/events/event_loop_param_test.cc
@@ -6,8 +6,9 @@
#include "gmock/gmock.h"
#include "gtest/gtest.h"
-#include "glog/logging.h"
#include "aos/events/test_message_generated.h"
+#include "aos/flatbuffer_merge.h"
+#include "glog/logging.h"
namespace aos {
namespace testing {
@@ -535,6 +536,31 @@
EXPECT_EQ(iteration_list.size(), 3);
}
+// Verifies that the event loop implementations detect when Channel is not a
+// pointer into confguration()
+TEST_P(AbstractEventLoopDeathTest, InvalidChannel) {
+ auto loop = MakePrimary();
+
+ const Channel *channel = loop->configuration()->channels()->Get(0);
+
+ FlatbufferDetachedBuffer<Channel> channel_copy = CopyFlatBuffer(channel);
+
+ EXPECT_DEATH(
+ { loop->MakeRawSender(&channel_copy.message()); },
+ "Channel pointer not found in configuration\\(\\)->channels\\(\\)");
+
+ EXPECT_DEATH(
+ { loop->MakeRawFetcher(&channel_copy.message()); },
+ "Channel pointer not found in configuration\\(\\)->channels\\(\\)");
+
+ EXPECT_DEATH(
+ {
+ loop->MakeRawWatcher(&channel_copy.message(),
+ [](const Context, const void *) {});
+ },
+ "Channel pointer not found in configuration\\(\\)->channels\\(\\)");
+}
+
// Verify that the send time on a message is roughly right.
TEST_P(AbstractEventLoopTest, MessageSendTime) {
auto loop1 = MakePrimary();
diff --git a/aos/events/shm_event_loop.cc b/aos/events/shm_event_loop.cc
index 5a88717..7506954 100644
--- a/aos/events/shm_event_loop.cc
+++ b/aos/events/shm_event_loop.cc
@@ -144,7 +144,8 @@
class ShmFetcher : public RawFetcher {
public:
explicit ShmFetcher(const Channel *channel)
- : lockless_queue_memory_(channel),
+ : RawFetcher(channel),
+ lockless_queue_memory_(channel),
lockless_queue_(lockless_queue_memory_.memory(),
lockless_queue_memory_.config()),
data_storage_(static_cast<AlignedChar *>(aligned_alloc(
@@ -273,7 +274,7 @@
class ShmSender : public RawSender {
public:
explicit ShmSender(const Channel *channel, const ShmEventLoop *shm_event_loop)
- : RawSender(),
+ : RawSender(channel),
shm_event_loop_(shm_event_loop),
name_(channel->name()->str()),
lockless_queue_memory_(channel),
@@ -449,11 +450,13 @@
::std::unique_ptr<RawFetcher> ShmEventLoop::MakeRawFetcher(
const Channel *channel) {
+ ValidateChannel(channel);
return ::std::unique_ptr<RawFetcher>(new ShmFetcher(channel));
}
::std::unique_ptr<RawSender> ShmEventLoop::MakeRawSender(
const Channel *channel) {
+ ValidateChannel(channel);
Take(channel);
return ::std::unique_ptr<RawSender>(new ShmSender(channel, this));
}
@@ -461,6 +464,7 @@
void ShmEventLoop::MakeRawWatcher(
const Channel *channel,
std::function<void(const Context &context, const void *message)> watcher) {
+ ValidateChannel(channel);
Take(channel);
::std::unique_ptr<internal::WatcherState> state(
diff --git a/aos/events/simulated_event_loop.cc b/aos/events/simulated_event_loop.cc
index 9bc74d5..02270ce 100644
--- a/aos/events/simulated_event_loop.cc
+++ b/aos/events/simulated_event_loop.cc
@@ -98,7 +98,9 @@
class SimulatedSender : public RawSender {
public:
SimulatedSender(SimulatedChannel *simulated_channel, EventLoop *event_loop)
- : simulated_channel_(simulated_channel), event_loop_(event_loop) {}
+ : RawSender(simulated_channel->channel()),
+ simulated_channel_(simulated_channel),
+ event_loop_(event_loop) {}
~SimulatedSender() {}
void *data() override {
@@ -156,7 +158,8 @@
class SimulatedFetcher : public RawFetcher {
public:
- explicit SimulatedFetcher(SimulatedChannel *queue) : queue_(queue) {}
+ explicit SimulatedFetcher(SimulatedChannel *queue)
+ : RawFetcher(queue->channel()), queue_(queue) {}
~SimulatedFetcher() { queue_->UnregisterFetcher(this); }
bool FetchNext() override {
@@ -393,18 +396,21 @@
void SimulatedEventLoop::MakeRawWatcher(
const Channel *channel,
std::function<void(const Context &channel, const void *message)> watcher) {
+ ValidateChannel(channel);
Take(channel);
GetSimulatedChannel(channel)->MakeRawWatcher(watcher);
}
std::unique_ptr<RawSender> SimulatedEventLoop::MakeRawSender(
const Channel *channel) {
+ ValidateChannel(channel);
Take(channel);
return GetSimulatedChannel(channel)->MakeRawSender(this);
}
std::unique_ptr<RawFetcher> SimulatedEventLoop::MakeRawFetcher(
const Channel *channel) {
+ ValidateChannel(channel);
return GetSimulatedChannel(channel)->MakeRawFetcher();
}