From aaa97edf001e8a527fba8b8a5bcdfbe66d65e81f Mon Sep 17 00:00:00 2001 From: Alex Biddulph Date: Mon, 9 Oct 2023 16:36:26 +1100 Subject: [PATCH] Allow extra arguments to be passed to reactor constructor (#97) --- src/PowerPlant.hpp | 7 +++-- src/PowerPlant.ipp | 7 +++-- tests/api/ReactorArgs.cpp | 62 +++++++++++++++++++++++++++++++++++++++ 3 files changed, 71 insertions(+), 5 deletions(-) create mode 100644 tests/api/ReactorArgs.cpp diff --git a/src/PowerPlant.hpp b/src/PowerPlant.hpp index 9ec3374db..ca1807483 100644 --- a/src/PowerPlant.hpp +++ b/src/PowerPlant.hpp @@ -121,12 +121,15 @@ class PowerPlant { * in the environment of that reactor so that it can be used to filter logs. * * @tparam T The type of the reactor to build and install + * @tparam Args The types of the extra arguments to pass to the reactor constructor * @tparam level The initial logging level for this reactor to use * + * @param arg Extra arguments to pass to the reactor constructor + * * @return A reference to the installed reactor */ - template - T& install(); + template + T& install(Args&&... args); /** * @brief Generic submit function for submitting tasks to the thread pool. diff --git a/src/PowerPlant.ipp b/src/PowerPlant.ipp index 3f12de36b..002c15d5c 100644 --- a/src/PowerPlant.ipp +++ b/src/PowerPlant.ipp @@ -52,14 +52,15 @@ inline PowerPlant::PowerPlant(Configuration config, int argc, const char* argv[] emit(std::make_unique(args)); } -template -T& PowerPlant::install() { +template +T& PowerPlant::install(Args&&... args) { // Make sure that the class that we received is a reactor static_assert(std::is_base_of::value, "You must install Reactors"); // The reactor constructor should handle subscribing to events - reactors.push_back(std::make_unique(std::make_unique(*this, util::demangle(typeid(T).name())))); + reactors.push_back(std::make_unique(std::make_unique(*this, util::demangle(typeid(T).name())), + std::forward(args)...)); return static_cast(*reactors.back()); } diff --git a/tests/api/ReactorArgs.cpp b/tests/api/ReactorArgs.cpp new file mode 100644 index 000000000..07ba1ffd5 --- /dev/null +++ b/tests/api/ReactorArgs.cpp @@ -0,0 +1,62 @@ +/* + * MIT License + * + * Copyright (c) 2015 NUClear Contributors + * + * This file is part of the NUClear codebase. + * See https://github.com/Fastcode/NUClear for further info. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE + * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR + * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#include +#include + +// Anonymous namespace to keep everything file local +namespace { + +class TestReactorNoArgs : public NUClear::Reactor { +public: + TestReactorNoArgs(std::unique_ptr environment) : NUClear::Reactor(std::move(environment)) {} + + std::string s{}; + bool b{false}; + uint32_t i{0}; +}; +class TestReactorArgs : public NUClear::Reactor { +public: + TestReactorArgs(std::unique_ptr environment, std::string s, const bool& b, const uint32_t& i) + : NUClear::Reactor(std::move(environment)), s(std::move(s)), b(b), i(i) {} + + std::string s{}; + bool b{false}; + uint32_t i{0}; +}; + +} // namespace + +TEST_CASE("Testing Reactor installation arguments", "[api][reactorargs]") { + NUClear::Configuration config; + config.thread_count = 1; + NUClear::PowerPlant plant(config); + const TestReactorArgs& r1 = plant.install("Hello NUClear", true, 0x00E298A2); + const TestReactorNoArgs& r2 = plant.install(); + + REQUIRE(r1.s == "Hello NUClear"); + REQUIRE(r1.b); + REQUIRE(r1.i == 0x00E298A2); + REQUIRE(r2.s.empty()); + REQUIRE(!r2.b); + REQUIRE(r2.i == 0); +}