Add fetcher-side utilities for constants code
This make it possible to use the ConstantsFetcher<> to actually get at
published constants easily.
Change-Id: Ib5a7b91ae69b91a221ecef36f1bdc117b89e9fc4
Signed-off-by: James Kuszmaul <jabukuszmaul+collab@gmail.com>
diff --git a/frc971/constants/constants_sender_lib.h b/frc971/constants/constants_sender_lib.h
index 92c14fa..48cacb5 100644
--- a/frc971/constants/constants_sender_lib.h
+++ b/frc971/constants/constants_sender_lib.h
@@ -2,6 +2,7 @@
#define FRC971_CONSTANTS_CONSTANTS_SENDER_H_
#include "aos/events/event_loop.h"
+#include "aos/events/shm_event_loop.h"
#include "aos/flatbuffer_merge.h"
#include "aos/json_to_flatbuffer.h"
#include "aos/network/team_number.h"
@@ -27,11 +28,9 @@
constants_path_(constants_path),
event_loop_(event_loop),
sender_(event_loop_->MakeSender<ConstantsData>(channel_name_)) {
- event_loop->OnRun([this]() {
- typename aos::Sender<ConstantsData>::Builder builder =
- sender_.MakeBuilder();
- builder.CheckOk(builder.Send(GetConstantsForTeamNumber(builder.fbb())));
- });
+ typename aos::Sender<ConstantsData>::Builder builder =
+ sender_.MakeBuilder();
+ builder.CheckOk(builder.Send(GetConstantsForTeamNumber(builder.fbb())));
}
private:
@@ -63,6 +62,56 @@
aos::Sender<ConstantsData> sender_;
};
+// This class fetches the current constants for the device, with appropriate
+// CHECKs to ensure that (a) the constants never change and (b) that the
+// constants are always available. This can be paired with WaitForConstants to
+// create the conditions for (b). In simulation, the constants should simply be
+// sent before starting up other EventLoops.
+template <typename ConstantsData>
+class ConstantsFetcher {
+ public:
+ ConstantsFetcher(aos::EventLoop *event_loop,
+ std::string_view channel = "/constants")
+ : fetcher_(event_loop->MakeFetcher<ConstantsData>(channel)) {
+ CHECK(fetcher_.Fetch())
+ << "Constants information must be available at startup.";
+ event_loop->MakeNoArgWatcher<ConstantsData>(channel, []() {
+ LOG(FATAL)
+ << "Don't know how to handle changes to constants information.";
+ });
+ }
+
+ const ConstantsData& constants() const {
+ return *fetcher_.get();
+ }
+
+ private:
+ aos::Fetcher<ConstantsData> fetcher_;
+};
+
+// Blocks until data is available on the requested channel using a ShmEventLoop.
+// This is for use during initialization in C++ binaries so that we can delay
+// initialization until everything is available. This allows applications to
+// depend on constants data during their initialization.
+template <typename ConstantsData>
+void WaitForConstants(const aos::Configuration *config,
+ std::string_view channel = "/constants") {
+ aos::ShmEventLoop event_loop(config);
+ aos::Fetcher fetcher = event_loop.MakeFetcher<ConstantsData>(channel);
+ event_loop.MakeNoArgWatcher<ConstantsData>(
+ channel, [&event_loop]() { event_loop.Exit(); });
+ event_loop.OnRun([&event_loop, &fetcher]() {
+ // If the constants were already published, we don't need to wait for them.
+ if (fetcher.Fetch()) {
+ event_loop.Exit();
+ }
+ });
+ LOG(INFO) << "Waiting for constants data on " << channel << " "
+ << ConstantsData::GetFullyQualifiedName();
+ event_loop.Run();
+ LOG(INFO) << "Got constants data.";
+}
+
} // namespace frc971::constants
#endif // FRC971_CONSTANTS_CONSTANTS_SENDER_H_