From 971f512ff9b7a002ef7d03e76b5df7b631e8b6b7 Mon Sep 17 00:00:00 2001 From: cameron Date: Sun, 15 Dec 2024 17:28:24 +1100 Subject: [PATCH 1/3] [#56] Fix update current thread priority for linux and make an enum --- src/Reactor.hpp | 4 +- src/dsl/Parse.hpp | 2 +- src/dsl/fusion/NoOp.hpp | 4 +- src/dsl/fusion/PriorityFusion.hpp | 4 +- src/dsl/word/Always.hpp | 2 +- src/dsl/word/Priority.hpp | 57 +++------------------ src/dsl/word/Shutdown.hpp | 3 +- src/extension/ChronoController.cpp | 2 +- src/threading/ReactionTask.hpp | 3 +- src/threading/scheduler/Group.cpp | 4 +- src/threading/scheduler/Group.hpp | 7 +-- src/threading/scheduler/Pool.cpp | 2 +- src/threading/scheduler/Scheduler.cpp | 2 +- src/threading/scheduler/Scheduler.hpp | 2 +- src/util/CallbackGenerator.hpp | 1 + src/util/Priority.hpp | 44 ++++++++++++++++ src/util/update_current_thread_priority.hpp | 34 +++++------- 17 files changed, 88 insertions(+), 89 deletions(-) create mode 100644 src/util/Priority.hpp diff --git a/src/Reactor.hpp b/src/Reactor.hpp index f072002e8..4f593ce67 100644 --- a/src/Reactor.hpp +++ b/src/Reactor.hpp @@ -51,6 +51,7 @@ namespace dsl { struct Once; + template struct Priority; template @@ -192,7 +193,8 @@ class Reactor { using Trigger = dsl::word::Trigger; /// @copydoc dsl::word::Priority - using Priority = dsl::word::Priority; + template + using Priority = dsl::word::Priority; /// @copydoc dsl::word::Always using Always = dsl::word::Always; diff --git a/src/dsl/Parse.hpp b/src/dsl/Parse.hpp index 1e38116db..7d923b911 100644 --- a/src/dsl/Parse.hpp +++ b/src/dsl/Parse.hpp @@ -76,7 +76,7 @@ namespace dsl { Parse>(task); } - static int priority(threading::ReactionTask& task) { + static util::Priority priority(threading::ReactionTask& task) { return std::conditional_t::value, DSL, fusion::NoOp>::template priority< Parse>(task); } diff --git a/src/dsl/fusion/NoOp.hpp b/src/dsl/fusion/NoOp.hpp index 5b20e5ee0..47576f33d 100644 --- a/src/dsl/fusion/NoOp.hpp +++ b/src/dsl/fusion/NoOp.hpp @@ -80,8 +80,8 @@ namespace dsl { } template - static int priority(const threading::ReactionTask& /*task*/) { - return word::Priority::NORMAL::value; + static util::Priority priority(const threading::ReactionTask& /*task*/) { + return util::Priority::NORMAL; } template diff --git a/src/dsl/fusion/PriorityFusion.hpp b/src/dsl/fusion/PriorityFusion.hpp index afd8b5175..34a6dd70d 100644 --- a/src/dsl/fusion/PriorityFusion.hpp +++ b/src/dsl/fusion/PriorityFusion.hpp @@ -44,7 +44,7 @@ namespace dsl { struct PriorityFuser> { template - static int priority(threading::ReactionTask& task) { + static util::Priority priority(threading::ReactionTask& task) { // Return our priority return Word::template priority(task); @@ -56,7 +56,7 @@ namespace dsl { struct PriorityFuser> { template - static int priority(threading::ReactionTask& task) { + static util::Priority priority(threading::ReactionTask& task) { // Choose our maximum priority return std::max(Word1::template priority(task), diff --git a/src/dsl/word/Always.hpp b/src/dsl/word/Always.hpp index 9292f7395..53310effd 100644 --- a/src/dsl/word/Always.hpp +++ b/src/dsl/word/Always.hpp @@ -131,7 +131,7 @@ namespace dsl { auto idle_task = std::make_unique( reaction, false, - [](threading::ReactionTask& task) { return DSL::priority(task) - 1; }, + [](threading::ReactionTask& task) { return prev(DSL::priority(task)); }, DSL::run_inline, DSL::pool, DSL::group); diff --git a/src/dsl/word/Priority.hpp b/src/dsl/word/Priority.hpp index 38e5d9540..7b10853a7 100644 --- a/src/dsl/word/Priority.hpp +++ b/src/dsl/word/Priority.hpp @@ -24,11 +24,11 @@ #define NUCLEAR_DSL_WORD_PRIORITY_HPP #include "../../threading/Reaction.hpp" +#include "../../util/Priority.hpp" namespace NUClear { namespace dsl { namespace word { - /** * Task priority can be controlled using an assigned setting. * @@ -67,57 +67,12 @@ namespace dsl { * @par Implements * Fusion */ + template struct Priority { - - struct REALTIME { - /// Realtime priority runs with 1000 value - static constexpr int value = 1000; - - template - static int priority(const threading::ReactionTask& /*task*/) { - return value; - } - }; - - struct HIGH { - /// High priority runs with 750 value - static constexpr int value = 750; - - template - static int priority(const threading::ReactionTask& /*task*/) { - return value; - } - }; - - struct NORMAL { - /// Normal priority runs with 500 value - static constexpr int value = 500; - - template - static int priority(const threading::ReactionTask& /*task*/) { - return value; - } - }; - - struct LOW { - /// Low priority runs with 250 value - static constexpr int value = 250; - - template - static int priority(const threading::ReactionTask& /*task*/) { - return value; - } - }; - - struct IDLE { - /// Idle tasks run with 0 priority, they run when there is free time - static constexpr int value = 0; - - template - static int priority(const threading::ReactionTask& /*task*/) { - return value; - } - }; + template + static util::Priority priority(const threading::ReactionTask& /*task*/) { + return value; + } }; } // namespace word diff --git a/src/dsl/word/Shutdown.hpp b/src/dsl/word/Shutdown.hpp index 20ea2c160..90f0b9d1e 100644 --- a/src/dsl/word/Shutdown.hpp +++ b/src/dsl/word/Shutdown.hpp @@ -24,6 +24,7 @@ #define NUCLEAR_DSL_WORD_SHUTDOWN_HPP #include "../operation/TypeBind.hpp" +#include "../../util/Priority.hpp" namespace NUClear { namespace dsl { @@ -54,7 +55,7 @@ namespace dsl { */ struct Shutdown : operation::TypeBind - , Priority::IDLE {}; + , Priority {}; } // namespace word } // namespace dsl diff --git a/src/extension/ChronoController.cpp b/src/extension/ChronoController.cpp index f7c01bf36..3c97cc921 100644 --- a/src/extension/ChronoController.cpp +++ b/src/extension/ChronoController.cpp @@ -121,7 +121,7 @@ namespace extension { wait.notify_all(); }); - on().then("Chrono Controller", [this] { + on>().then("Chrono Controller", [this] { // Run until we are told to stop while (running.load(std::memory_order_acquire)) { diff --git a/src/threading/ReactionTask.hpp b/src/threading/ReactionTask.hpp index 10979681b..c0fe54e62 100644 --- a/src/threading/ReactionTask.hpp +++ b/src/threading/ReactionTask.hpp @@ -32,6 +32,7 @@ #include "../util/GroupDescriptor.hpp" #include "../util/Inline.hpp" #include "../util/ThreadPoolDescriptor.hpp" +#include "../util/Priority.hpp" #include "../util/platform.hpp" #include "Reaction.hpp" @@ -136,7 +137,7 @@ namespace threading { bool run_inline{false}; /// The priority to run this task at - int priority; + util::Priority priority; /// If the task should be executed inline (in the current thread) or not util::Inline should_inline{util::Inline::NEUTRAL}; /// Details about the thread pool that this task will run from, this will also influence what task queue diff --git a/src/threading/scheduler/Group.cpp b/src/threading/scheduler/Group.cpp index 883180c30..d4cfb1e07 100644 --- a/src/threading/scheduler/Group.cpp +++ b/src/threading/scheduler/Group.cpp @@ -33,7 +33,7 @@ namespace NUClear { namespace threading { namespace scheduler { - Group::LockHandle::LockHandle(const NUClear::id_t& task_id, const int& priority, std::function notify) + Group::LockHandle::LockHandle(const NUClear::id_t& task_id, const util::Priority& priority, std::function notify) : task_id(task_id), priority(priority), notify(std::move(notify)) {} Group::GroupLock::GroupLock(Group& group, std::shared_ptr handle) @@ -109,7 +109,7 @@ namespace threading { Group::Group(std::shared_ptr descriptor) : descriptor(std::move(descriptor)) {} std::unique_ptr Group::lock(const NUClear::id_t& task_id, - const int& priority, + const util::Priority& priority, const std::function& notify) { auto handle = std::make_shared(task_id, priority, notify); diff --git a/src/threading/scheduler/Group.hpp b/src/threading/scheduler/Group.hpp index 785b9da85..5a7a0059a 100644 --- a/src/threading/scheduler/Group.hpp +++ b/src/threading/scheduler/Group.hpp @@ -28,6 +28,7 @@ #include #include "../../util/GroupDescriptor.hpp" +#include "../../util/Priority.hpp" #include "Lock.hpp" namespace NUClear { @@ -50,7 +51,7 @@ namespace threading { * It holds if the lock should currently be locked, as well as ordering which locks should be locked first. */ struct LockHandle { - LockHandle(const NUClear::id_t& task_id, const int& priority, std::function notify); + LockHandle(const NUClear::id_t& task_id, const util::Priority& priority, std::function notify); /** * Compare two lock handles by comparing their priority and task id @@ -78,7 +79,7 @@ namespace threading { /// The task id of the reaction that is waiting, lower task ids run first NUClear::id_t task_id; /// The priority of the reaction that is waiting, higher priorities run first - int priority; + util::Priority priority; /// If this lock has been successfully locked bool locked{false}; /// If this lock has been notified that it can lock @@ -156,7 +157,7 @@ namespace threading { * @return a lock which can be locked once a token is available */ std::unique_ptr lock(const NUClear::id_t& task_id, - const int& priority, + const util::Priority& priority, const std::function& notify); /// The descriptor for this group diff --git a/src/threading/scheduler/Pool.cpp b/src/threading/scheduler/Pool.cpp index a9b6cb97a..611a6354b 100644 --- a/src/threading/scheduler/Pool.cpp +++ b/src/threading/scheduler/Pool.cpp @@ -257,7 +257,7 @@ namespace threading { auto task = std::make_unique( nullptr, true, - [](const ReactionTask&) { return 0; }, + [](const ReactionTask&) { return util::Priority::LOWEST; }, [](const ReactionTask&) { return util::Inline::ALWAYS; }, [](const ReactionTask&) { return dsl::word::Pool<>::descriptor(); }, [](const ReactionTask&) { return std::set>{}; }); diff --git a/src/threading/scheduler/Scheduler.cpp b/src/threading/scheduler/Scheduler.cpp index cf1c4e002..c178d50cf 100644 --- a/src/threading/scheduler/Scheduler.cpp +++ b/src/threading/scheduler/Scheduler.cpp @@ -150,7 +150,7 @@ namespace threading { std::unique_ptr Scheduler::get_groups_lock( const NUClear::id_t& task_id, - const int& priority, + const util::Priority& priority, const std::shared_ptr& pool, const std::set>& descs) { diff --git a/src/threading/scheduler/Scheduler.hpp b/src/threading/scheduler/Scheduler.hpp index 0c30970a6..651ca2157 100644 --- a/src/threading/scheduler/Scheduler.hpp +++ b/src/threading/scheduler/Scheduler.hpp @@ -126,7 +126,7 @@ namespace threading { * @return a combined lock representing the state of all the groups */ std::unique_ptr get_groups_lock(const NUClear::id_t& task_id, - const int& priority, + const util::Priority& priority, const std::shared_ptr& pool, const std::set>& descs); diff --git a/src/util/CallbackGenerator.hpp b/src/util/CallbackGenerator.hpp index 93ada18c1..30530ae46 100644 --- a/src/util/CallbackGenerator.hpp +++ b/src/util/CallbackGenerator.hpp @@ -29,6 +29,7 @@ #include "../message/ReactionStatistics.hpp" #include "../util/MergeTransient.hpp" #include "../util/TransientDataElements.hpp" +#include "../util/Priority.hpp" #include "../util/apply.hpp" #include "../util/unpack.hpp" #include "../util/update_current_thread_priority.hpp" diff --git a/src/util/Priority.hpp b/src/util/Priority.hpp new file mode 100644 index 000000000..32348aa8b --- /dev/null +++ b/src/util/Priority.hpp @@ -0,0 +1,44 @@ +/* + * MIT License + * + * Copyright (c) 2024 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. + */ + +#ifndef NUCLEAR_UTIL_PRIORITY_HPP +#define NUCLEAR_UTIL_PRIORITY_HPP + +#include +#include +#include + +namespace NUClear { +namespace util { + + enum class Priority : uint8_t { LOWEST = 0, LOW = 1, NORMAL = 2, HIGH = 3, HIGHEST = 4 }; + inline Priority prev(Priority value) { + value = static_cast(static_cast>(value) - 1); + value = std::min(value, Priority::LOWEST); + return value; + } + constexpr Priority MAX_PRIORITY = Priority::HIGHEST; + +} // namespace util +} // namespace NUClear + +#endif // NUCLEAR_UTIL_PRIORITY_HPP diff --git a/src/util/update_current_thread_priority.hpp b/src/util/update_current_thread_priority.hpp index dbdb09990..1aa6e52d8 100644 --- a/src/util/update_current_thread_priority.hpp +++ b/src/util/update_current_thread_priority.hpp @@ -23,18 +23,18 @@ #ifndef NUCLEAR_UTIL_UPDATE_CURRENT_THREAD_PRIORITY_HPP #define NUCLEAR_UTIL_UPDATE_CURRENT_THREAD_PRIORITY_HPP +#include "../util/Priority.hpp" + #ifndef _WIN32 #include -inline void update_current_thread_priority(int priority) { - - // TODO(Trent) SCHED_NORMAL for normal threads - // TODO(Trent) SCHED_FIFO for realtime threads - // TODO(Trent) SCHED_RR for high priority threads +inline void update_current_thread_priority(NUClear::util::Priority priority) { + auto priority_int = static_cast>(priority); - auto sched_priority = sched_get_priority_min(SCHED_RR) - + (priority / (sched_get_priority_max(SCHED_RR) - sched_get_priority_min(SCHED_RR))); + auto step = (sched_get_priority_max(SCHED_RR) - sched_get_priority_min(SCHED_RR)) + / static_cast>(NUClear::util::MAX_PRIORITY); + auto sched_priority = priority_int * step; sched_param p{}; p.sched_priority = sched_priority; @@ -46,30 +46,24 @@ inline void update_current_thread_priority(int priority) { #include "platform.hpp" -inline void update_current_thread_priority(int priority) { +inline void update_current_thread_priority(NUClear::util::Priority priority) { - switch ((priority * 7) / 1000) { - case 0: { - SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_IDLE); - } break; - case 1: { + switch (priority) { + case LOWEST: { SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_LOWEST); } break; - case 2: { + case LOW: { SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_BELOW_NORMAL); } break; - case 3: { + case NORMAL: { SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_NORMAL); } break; - case 4: { + case HIGH: { SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_ABOVE_NORMAL); } break; - case 5: { + case HIGHEST: { SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_HIGHEST); } break; - case 6: { - SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_TIME_CRITICAL); - } break; } } From 016dce31c153a7098440931481956b8287c0665f Mon Sep 17 00:00:00 2001 From: cameron Date: Sun, 15 Dec 2024 17:41:53 +1100 Subject: [PATCH 2/3] add documentation to Priority DSL and util --- src/dsl/word/Priority.hpp | 20 ++++---------------- src/util/Priority.hpp | 7 ++++++- src/util/update_current_thread_priority.hpp | 2 +- 3 files changed, 11 insertions(+), 18 deletions(-) diff --git a/src/dsl/word/Priority.hpp b/src/dsl/word/Priority.hpp index 7b10853a7..1c6ee7154 100644 --- a/src/dsl/word/Priority.hpp +++ b/src/dsl/word/Priority.hpp @@ -32,36 +32,24 @@ namespace dsl { /** * Task priority can be controlled using an assigned setting. * - * @code on, Priority::HIGH>() @endcode + * @code on, Priority>() @endcode * The PowerPlant uses this setting to determine the scheduling order in the threadpool, as well as assign a * priority to the thread on the OS. * * The available priority settings are: * - * REALTIME: Tasks assigned with this will be queued with all other REALTIME tasks. - * + * HIGHEST: * HIGH: - * Tasks assigned with this will be queued with all other HIGH tasks. - * They will be scheduled for execution when there are no REALTIME tasks in the queue. - * * NORMAL: - * Tasks assigned with this will be queued with all other NORMAL tasks. - * They will be scheduled for execution when there are no REALTIME and HIGH tasks in the queue. - * * LOW: - * Tasks assigned with this will be queued with all other LOW tasks. - * They will be scheduled for execution when there are no REALTIME, HIGH and NORMAL tasks in the queue. - * - * IDLE: - * Tasks assigned with this priority will be queued with all other IDLE tasks. - * They will be scheduled for execution when there are no other tasks running in the system. + * LOWEST: * * @par Default Behaviour * @code on>() @endcode * When the priority is not specified, tasks will be assigned a default setting; NORMAL. * * @attention - * If the OS allows the user to set thread priority, this word can also be used to assign the priority of the + * If the OS allows the user to set thread priority, this word will also be used to assign the priority of the * thread in its runtime environment. * * @par Implements diff --git a/src/util/Priority.hpp b/src/util/Priority.hpp index 32348aa8b..6e5781810 100644 --- a/src/util/Priority.hpp +++ b/src/util/Priority.hpp @@ -30,13 +30,18 @@ namespace NUClear { namespace util { + /** + * The priority value for Priority dsl word + */ enum class Priority : uint8_t { LOWEST = 0, LOW = 1, NORMAL = 2, HIGH = 3, HIGHEST = 4 }; + /** + * Gets one lower priority unless already lowest + */ inline Priority prev(Priority value) { value = static_cast(static_cast>(value) - 1); value = std::min(value, Priority::LOWEST); return value; } - constexpr Priority MAX_PRIORITY = Priority::HIGHEST; } // namespace util } // namespace NUClear diff --git a/src/util/update_current_thread_priority.hpp b/src/util/update_current_thread_priority.hpp index 1aa6e52d8..940d86a39 100644 --- a/src/util/update_current_thread_priority.hpp +++ b/src/util/update_current_thread_priority.hpp @@ -33,7 +33,7 @@ inline void update_current_thread_priority(NUClear::util::Priority priority) { auto priority_int = static_cast>(priority); auto step = (sched_get_priority_max(SCHED_RR) - sched_get_priority_min(SCHED_RR)) - / static_cast>(NUClear::util::MAX_PRIORITY); + / static_cast>(NUClear::util::Priority::HIGHEST); auto sched_priority = priority_int * step; sched_param p{}; From 2dba179205fc4083ceb5e1079afab7ee3293dbf7 Mon Sep 17 00:00:00 2001 From: cameron Date: Sun, 15 Dec 2024 18:36:09 +1100 Subject: [PATCH 3/3] fix tests --- src/dsl/word/emit/Initialise.hpp | 2 +- tests/tests/api/ReactionHandle.cpp | 4 +- tests/tests/api/ReactionStatistics.cpp | 4 +- tests/tests/api/ReactionStatisticsTiming.cpp | 4 +- tests/tests/dsl/BlockNoData.cpp | 2 +- tests/tests/dsl/Buffer.cpp | 10 ++-- tests/tests/dsl/DSLOrdering.cpp | 6 +-- tests/tests/dsl/FlagMessage.cpp | 2 +- tests/tests/dsl/IdleGlobal.cpp | 2 +- tests/tests/dsl/IdleSingle.cpp | 4 +- tests/tests/dsl/Once.cpp | 2 +- tests/tests/dsl/Priority.cpp | 44 ++++++++--------- tests/tests/dsl/RawFunction.cpp | 8 +-- tests/tests/dsl/Shutdown.cpp | 2 +- tests/tests/dsl/Transient.cpp | 18 +++---- tests/tests/dsl/With.cpp | 10 ++-- tests/tests/threading/Group.cpp | 52 ++++++++++---------- 17 files changed, 88 insertions(+), 88 deletions(-) diff --git a/src/dsl/word/emit/Initialise.hpp b/src/dsl/word/emit/Initialise.hpp index cd013fdd8..435d808a0 100644 --- a/src/dsl/word/emit/Initialise.hpp +++ b/src/dsl/word/emit/Initialise.hpp @@ -59,7 +59,7 @@ namespace dsl { auto emitter = std::make_unique( nullptr, false, - [](threading::ReactionTask& /*task*/) { return 1000; }, + [](threading::ReactionTask& /*task*/) { return NUClear::util::Priority::HIGHEST; }, [](threading::ReactionTask& /*task*/) { return util::Inline::NEVER; }, [](threading::ReactionTask& /*task*/) { return Pool<>::descriptor(); }, [](threading::ReactionTask& /*task*/) { diff --git a/tests/tests/api/ReactionHandle.cpp b/tests/tests/api/ReactionHandle.cpp index 427ecf014..794a32c2d 100644 --- a/tests/tests/api/ReactionHandle.cpp +++ b/tests/tests/api/ReactionHandle.cpp @@ -37,13 +37,13 @@ class TestReactor : public test_util::TestBase { TestReactor(std::unique_ptr environment) : TestBase(std::move(environment)) { // Make an always disabled reaction - a = on, Priority::HIGH>().then([this](const Message& msg) { // + a = on, Priority>().then([this](const Message& msg) { // events.push_back("Executed disabled reaction " + std::to_string(msg.i)); }); a.disable(); // Make a reaction that we toggle on and off - b = on, Priority::HIGH>().then([this](const Message& msg) { // + b = on, Priority>().then([this](const Message& msg) { // events.push_back("Executed toggled reaction " + std::to_string(msg.i)); b.disable(); emit(std::make_unique(1)); diff --git a/tests/tests/api/ReactionStatistics.cpp b/tests/tests/api/ReactionStatistics.cpp index 9d8d412d9..54dc989f0 100644 --- a/tests/tests/api/ReactionStatistics.cpp +++ b/tests/tests/api/ReactionStatistics.cpp @@ -40,13 +40,13 @@ class TestReactor : public test_util::TestBase { // This reaction is here to emit something from a ReactionStatistics trigger // This shouldn't cause reaction statistics of their own otherwise everything would explode - on, Priority::HIGH>().then("Loop Statistics", [this](const ReactionEvent&) { // + on, Priority>().then("Loop Statistics", [this](const ReactionEvent&) { // emit(std::make_unique()); }); on>().then("No Statistics", [] {}); - on, Priority::HIGH>().then("Reaction Stats Handler", [this](const ReactionEvent& event) { + on, Priority>().then("Reaction Stats Handler", [this](const ReactionEvent& event) { const auto& stats = *event.statistics; // Other reactions statistics run on this because of built in NUClear reactors (e.g. chrono controller etc) diff --git a/tests/tests/api/ReactionStatisticsTiming.cpp b/tests/tests/api/ReactionStatisticsTiming.cpp index f0ee99045..a35065bab 100644 --- a/tests/tests/api/ReactionStatisticsTiming.cpp +++ b/tests/tests/api/ReactionStatisticsTiming.cpp @@ -60,7 +60,7 @@ class TestReactor : public test_util::TestBase { TestReactor(std::unique_ptr environment) : TestBase(std::move(environment), true, std::chrono::seconds(2)) { - on>, Priority::LOW>().then(initial_name + ":" + heavy_name, [this] { + on>, Priority>().then(initial_name + ":" + heavy_name, [this] { code_events.emplace_back("Started " + initial_name + ":" + heavy_name, NUClear::clock::now()); code_events.emplace_back("Created " + heavy_name, NUClear::clock::now()); emit(std::make_unique()); @@ -74,7 +74,7 @@ class TestReactor : public test_util::TestBase { code_events.emplace_back("Finished " + heavy_name, NUClear::clock::now()); }); - on>, Priority::LOW>().then(initial_name + ":" + light_name, [this] { + on>, Priority>().then(initial_name + ":" + light_name, [this] { code_events.emplace_back("Started " + initial_name + ":" + light_name, NUClear::clock::now()); code_events.emplace_back("Created " + light_name, NUClear::clock::now()); emit(std::make_unique()); diff --git a/tests/tests/dsl/BlockNoData.cpp b/tests/tests/dsl/BlockNoData.cpp index 702728ac4..c9d8294ef 100644 --- a/tests/tests/dsl/BlockNoData.cpp +++ b/tests/tests/dsl/BlockNoData.cpp @@ -47,7 +47,7 @@ class TestReactor : public test_util::TestBase { events.push_back("MessageB with MessageA triggered"); }); - on>, Priority::LOW>().then([this] { + on>, Priority>().then([this] { events.push_back("Emitting MessageA"); emit(std::make_unique()); }); diff --git a/tests/tests/dsl/Buffer.cpp b/tests/tests/dsl/Buffer.cpp index 5e465ef09..14e38a352 100644 --- a/tests/tests/dsl/Buffer.cpp +++ b/tests/tests/dsl/Buffer.cpp @@ -51,29 +51,29 @@ class TestReactor : public test_util::TestBase { events.push_back("Buffer<4> reaction " + std::to_string(msg.i)); }); - on>, Priority::LOW>().then([this] { + on>, Priority>().then([this] { events.push_back("Step 1"); emit(std::make_unique(1)); }); - on>, Priority::LOW>().then([this] { + on>, Priority>().then([this] { events.push_back("Step 2"); emit(std::make_unique(2)); emit(std::make_unique(3)); }); - on>, Priority::LOW>().then([this] { + on>, Priority>().then([this] { events.push_back("Step 3"); emit(std::make_unique(4)); emit(std::make_unique(5)); emit(std::make_unique(6)); }); - on>, Priority::LOW>().then([this] { + on>, Priority>().then([this] { events.push_back("Step 4"); emit(std::make_unique(7)); emit(std::make_unique(8)); emit(std::make_unique(9)); emit(std::make_unique(10)); }); - on>, Priority::LOW>().then([this] { + on>, Priority>().then([this] { events.push_back("Step 5"); emit(std::make_unique(11)); emit(std::make_unique(12)); diff --git a/tests/tests/dsl/DSLOrdering.cpp b/tests/tests/dsl/DSLOrdering.cpp index 7deea04f1..aee901b98 100644 --- a/tests/tests/dsl/DSLOrdering.cpp +++ b/tests/tests/dsl/DSLOrdering.cpp @@ -47,15 +47,15 @@ class TestReactor : public test_util::TestBase { events.push_back("Empty function"); }); - on>, Priority::LOW>().then([this] { + on>, Priority>().then([this] { events.push_back("Emitting 1"); emit(std::make_unique>("1")); }); - on>, Priority::LOW>().then([this] { + on>, Priority>().then([this] { events.push_back("Emitting 2"); emit(std::make_unique>("2")); }); - on>, Priority::LOW>().then([this] { + on>, Priority>().then([this] { events.push_back("Emitting 3"); emit(std::make_unique>("3")); }); diff --git a/tests/tests/dsl/FlagMessage.cpp b/tests/tests/dsl/FlagMessage.cpp index 33b81b19a..817b367c4 100644 --- a/tests/tests/dsl/FlagMessage.cpp +++ b/tests/tests/dsl/FlagMessage.cpp @@ -50,7 +50,7 @@ class TestReactor : public test_util::TestBase { events.push_back("MessageA with MessageB triggered"); }); - on>, Priority::LOW>().then([this] { + on>, Priority>().then([this] { events.push_back("Step<1> triggered"); events.push_back("Emitting MessageA"); emit(std::make_unique()); diff --git a/tests/tests/dsl/IdleGlobal.cpp b/tests/tests/dsl/IdleGlobal.cpp index 47d280ffb..2b012f846 100644 --- a/tests/tests/dsl/IdleGlobal.cpp +++ b/tests/tests/dsl/IdleGlobal.cpp @@ -89,7 +89,7 @@ class TestReactor : public test_util::TestBase { }); // At low priority shutdown, this will run after all the global idles (should be 1) have been fired - on>, Priority::LOW>().then([this] { powerplant.shutdown(); }); + on>, Priority>().then([this] { powerplant.shutdown(); }); // This shutdown is here in case the test times out so all the spinlocks don't hang the test on>().then([this] { diff --git a/tests/tests/dsl/IdleSingle.cpp b/tests/tests/dsl/IdleSingle.cpp index 27459cf4d..17c44de85 100644 --- a/tests/tests/dsl/IdleSingle.cpp +++ b/tests/tests/dsl/IdleSingle.cpp @@ -76,7 +76,7 @@ class TestReactor : public test_util::TestBase { // Run this at low priority but have it first // This way MainThread will get notified that it has access to Sync but then it will lose it when // The other task on the default pool gets created so it'll be notified but unable to act - on, MainThread, Priority::LOW, Sync>().then([this](const TaskB& t) { + on, MainThread, Priority, Sync>().then([this](const TaskB& t) { main_calls[t.i].fetch_add(1, std::memory_order_relaxed); if (t.i + 1 < n_loops) { @@ -87,7 +87,7 @@ class TestReactor : public test_util::TestBase { } }); // This is the high priority task that preempts the main thread and makes it go idle again - on, Pool<>, Priority::HIGH, Sync>().then([this](const TaskB& t) { // + on, Pool<>, Priority, Sync>().then([this](const TaskB& t) { // default_calls[t.i].fetch_add(1, std::memory_order_relaxed); }); diff --git a/tests/tests/dsl/Once.cpp b/tests/tests/dsl/Once.cpp index d8bff7e4d..f482c3f18 100644 --- a/tests/tests/dsl/Once.cpp +++ b/tests/tests/dsl/Once.cpp @@ -36,7 +36,7 @@ class TestReactor : public NUClear::Reactor { TestReactor(std::unique_ptr environment) : Reactor(std::move(environment)) { // Make this priority high so it will always run first if it is able - on, Priority::HIGH, Once>().then([this](const SimpleMessage& msg) { // + on, Priority, Once>().then([this](const SimpleMessage& msg) { // events.push_back("Once Trigger executed " + std::to_string(msg.run)); }); diff --git a/tests/tests/dsl/Priority.cpp b/tests/tests/dsl/Priority.cpp index ae650f738..3404ff0bd 100644 --- a/tests/tests/dsl/Priority.cpp +++ b/tests/tests/dsl/Priority.cpp @@ -35,20 +35,20 @@ class TestReactor : public test_util::TestBase { TestReactor(std::unique_ptr environment) : TestBase(std::move(environment)) { // Declare in the order you'd expect them to fire - on>, Priority::REALTIME>().then([this] { events.push_back("Realtime Message<1>"); }); - on>, Priority::HIGH>().then("High", [this] { events.push_back("High Message<1>"); }); + on>, Priority>().then([this] { events.push_back("Highest Message<1>"); }); + on>, Priority>().then("High", [this] { events.push_back("High Message<1>"); }); on>>().then([this] { events.push_back("Default Message<1>"); }); - on>, Priority::NORMAL>().then("Normal", [this] { events.push_back("Normal Message<1>"); }); - on>, Priority::LOW>().then("Low", [this] { events.push_back("Low Message<1>"); }); - on>, Priority::IDLE>().then([this] { events.push_back("Idle Message<1>"); }); + on>, Priority>().then("Normal", [this] { events.push_back("Normal Message<1>"); }); + on>, Priority>().then("Low", [this] { events.push_back("Low Message<1>"); }); + on>, Priority>().then([this] { events.push_back("Lowest Message<1>"); }); // Declare in the opposite order to what you'd expect them to fire - on>, Priority::IDLE>().then([this] { events.push_back("Idle Message<2>"); }); - on>, Priority::LOW>().then([this] { events.push_back("Low Message<2>"); }); - on>, Priority::NORMAL>().then([this] { events.push_back("Normal Message<2>"); }); + on>, Priority>().then([this] { events.push_back("Lowest Message<2>"); }); + on>, Priority>().then([this] { events.push_back("Low Message<2>"); }); + on>, Priority>().then([this] { events.push_back("Normal Message<2>"); }); on>>().then([this] { events.push_back("Default Message<2>"); }); - on>, Priority::HIGH>().then([this] { events.push_back("High Message<2>"); }); - on>, Priority::REALTIME>().then([this] { events.push_back("Realtime Message<2>"); }); + on>, Priority>().then([this] { events.push_back("High Message<2>"); }); + on>, Priority>().then([this] { events.push_back("Highest Message<2>"); }); // Declare in a random order std::array order = {0, 1, 2, 3, 4}; @@ -56,21 +56,21 @@ class TestReactor : public test_util::TestBase { for (const auto& i : order) { switch (i) { case 0: - on>, Priority::REALTIME>().then( - [this] { events.push_back("Realtime Message<3>"); }); + on>, Priority>().then( + [this] { events.push_back("Highest Message<3>"); }); break; case 1: - on>, Priority::HIGH>().then([this] { events.push_back("High Message<3>"); }); + on>, Priority>().then([this] { events.push_back("High Message<3>"); }); break; case 2: - on>, Priority::NORMAL>().then([this] { events.push_back("Normal Message<3>"); }); + on>, Priority>().then([this] { events.push_back("Normal Message<3>"); }); on>>().then([this] { events.push_back("Default Message<3>"); }); break; case 3: - on>, Priority::LOW>().then([this] { events.push_back("Low Message<3>"); }); + on>, Priority>().then([this] { events.push_back("Low Message<3>"); }); break; case 4: - on>, Priority::IDLE>().then([this] { events.push_back("Idle Message<3>"); }); + on>, Priority>().then([this] { events.push_back("Lowest Message<3>"); }); break; default: throw std::invalid_argument("Should be impossible"); } @@ -98,9 +98,9 @@ TEST_CASE("Tests that priority orders the tasks appropriately", "[api][priority] plant.start(); const std::vector expected = { - "Realtime Message<1>", - "Realtime Message<2>", - "Realtime Message<3>", + "Highest Message<1>", + "Highest Message<2>", + "Highest Message<3>", "High Message<1>", "High Message<2>", "High Message<3>", @@ -113,9 +113,9 @@ TEST_CASE("Tests that priority orders the tasks appropriately", "[api][priority] "Low Message<1>", "Low Message<2>", "Low Message<3>", - "Idle Message<1>", - "Idle Message<2>", - "Idle Message<3>", + "Lowest Message<1>", + "Lowest Message<2>", + "Lowest Message<3>", }; // Make an info print the diff in an easy to read way if we fail diff --git a/tests/tests/dsl/RawFunction.cpp b/tests/tests/dsl/RawFunction.cpp index b7d7c7dda..7750c70ad 100644 --- a/tests/tests/dsl/RawFunction.cpp +++ b/tests/tests/dsl/RawFunction.cpp @@ -88,10 +88,10 @@ class TestReactor : public test_util::TestBase { on, Trigger>().then(raw_function_test_right_arg); on, Trigger>().then(raw_function_test_both_args); - on>, Priority::LOW>().then([this] { emit(std::make_unique("D1")); }); - on>, Priority::LOW>().then([this] { emit(std::make_unique("M2")); }); - on>, Priority::LOW>().then([this] { emit(std::make_unique("D3")); }); - on>, Priority::LOW>().then([this] { emit(std::make_unique("M4")); }); + on>, Priority>().then([this] { emit(std::make_unique("D1")); }); + on>, Priority>().then([this] { emit(std::make_unique("M2")); }); + on>, Priority>().then([this] { emit(std::make_unique("D3")); }); + on>, Priority>().then([this] { emit(std::make_unique("M4")); }); on().then([this] { emit(std::make_unique>()); diff --git a/tests/tests/dsl/Shutdown.cpp b/tests/tests/dsl/Shutdown.cpp index 9f644217d..5741092a7 100644 --- a/tests/tests/dsl/Shutdown.cpp +++ b/tests/tests/dsl/Shutdown.cpp @@ -34,7 +34,7 @@ class TestReactor : public test_util::TestBase { events.push_back("Shutdown task executed"); }); - on>, Priority::LOW>().then([this] { + on>, Priority>().then([this] { events.push_back("Requesting shutdown"); powerplant.shutdown(); }); diff --git a/tests/tests/dsl/Transient.cpp b/tests/tests/dsl/Transient.cpp index dd9574060..d36a135b7 100644 --- a/tests/tests/dsl/Transient.cpp +++ b/tests/tests/dsl/Transient.cpp @@ -72,39 +72,39 @@ class TestReactor : public test_util::TestBase { events.push_back(m.msg + " : " + t.msg); }); - on>, Priority::LOW>().then([this] { + on>, Priority>().then([this] { events.push_back("Emitting Message 1"); emit(std::make_unique("S1")); }); - on>, Priority::LOW>().then([this] { + on>, Priority>().then([this] { events.push_back("Emitting Transient 1"); emit(std::make_unique("T1", true)); }); - on>, Priority::LOW>().then([this] { + on>, Priority>().then([this] { events.push_back("Emitting Message 2"); emit(std::make_unique("S2")); }); - on>, Priority::LOW>().then([this] { + on>, Priority>().then([this] { events.push_back("Emitting Invalid Transient 2"); emit(std::make_unique("T2", false)); }); - on>, Priority::LOW>().then([this] { + on>, Priority>().then([this] { events.push_back("Emitting Message 3"); emit(std::make_unique("S3")); }); - on>, Priority::LOW>().then([this] { + on>, Priority>().then([this] { events.push_back("Emitting Transient 3"); emit(std::make_unique("T3", true)); }); - on>, Priority::LOW>().then([this] { + on>, Priority>().then([this] { events.push_back("Emitting Transient 4"); emit(std::make_unique("T4", true)); }); - on>, Priority::LOW>().then([this] { + on>, Priority>().then([this] { events.push_back("Emitting Invalid Transient 5"); emit(std::make_unique("T5", false)); }); - on>, Priority::LOW>().then([this] { + on>, Priority>().then([this] { events.push_back("Emitting Message 4"); emit(std::make_unique("S4")); }); diff --git a/tests/tests/dsl/With.cpp b/tests/tests/dsl/With.cpp index fd389bcc3..35edac64f 100644 --- a/tests/tests/dsl/With.cpp +++ b/tests/tests/dsl/With.cpp @@ -43,27 +43,27 @@ class TestReactor : public test_util::TestBase { events.push_back("Message: " + m.data + " Data: " + d.data); }); - on>, Priority::LOW>().then([this] { + on>, Priority>().then([this] { events.push_back("Emitting Data 1"); emit(std::make_unique("D1")); }); - on>, Priority::LOW>().then([this] { + on>, Priority>().then([this] { events.push_back("Emitting Data 2"); emit(std::make_unique("D2")); }); - on>, Priority::LOW>().then([this] { + on>, Priority>().then([this] { events.push_back("Emitting Message 1"); emit(std::make_unique("M1")); }); - on>, Priority::LOW>().then([this] { + on>, Priority>().then([this] { events.push_back("Emitting Data 3"); emit(std::make_unique("D3")); }); - on>, Priority::LOW>().then([this] { + on>, Priority>().then([this] { events.push_back("Emitting Message 2"); emit(std::make_unique("M2")); }); diff --git a/tests/tests/threading/Group.cpp b/tests/tests/threading/Group.cpp index ea94b6834..ecbb52c89 100644 --- a/tests/tests/threading/Group.cpp +++ b/tests/tests/threading/Group.cpp @@ -42,14 +42,14 @@ namespace threading { NUClear::id_t task_id_source = 1; WHEN("Creating a lock") { - std::unique_ptr lock1 = group->lock(++task_id_source, 1, [] {}); + std::unique_ptr lock1 = group->lock(++task_id_source, util::Priority::LOW, [] {}); THEN("The lock should be true") { CHECK(lock1->lock() == true); } AND_WHEN("Creating a second lock") { - std::unique_ptr lock2 = group->lock(++task_id_source, 1, [] {}); + std::unique_ptr lock2 = group->lock(++task_id_source, util::Priority::LOW, [] {}); THEN("The lock should be false") { CHECK(lock1->lock() == true); @@ -67,7 +67,7 @@ namespace threading { WHEN("Creating a lock and locking it") { int notified1 = 0; - std::unique_ptr lock1 = group->lock(task_id_source++, 1, [&] { ++notified1; }); + std::unique_ptr lock1 = group->lock(task_id_source++, util::Priority::LOW, [&] { ++notified1; }); lock1->lock(); THEN("The lock should be true") { @@ -77,8 +77,8 @@ namespace threading { AND_WHEN("Creating two more locks") { int notified2 = 0; int notified3 = 0; - std::unique_ptr lock2 = group->lock(task_id_source++, 1, [&] { ++notified2; }); - std::unique_ptr lock3 = group->lock(task_id_source++, 1, [&] { ++notified3; }); + std::unique_ptr lock2 = group->lock(task_id_source++, util::Priority::LOW, [&] { ++notified2; }); + std::unique_ptr lock3 = group->lock(task_id_source++, util::Priority::LOW, [&] { ++notified3; }); THEN("The new locks should be false") { CHECK(lock1->lock() == true); @@ -116,11 +116,11 @@ namespace threading { WHEN("Creating a lock and locking it") { int notified1 = 0; - std::unique_ptr lock1 = group->lock(1, 1, [&] { ++notified1; }); + std::unique_ptr lock1 = group->lock(1, util::Priority::LOW, [&] { ++notified1; }); AND_WHEN("Locking the lock and creating a higher priority task") { lock1->lock(); - std::unique_ptr lock2 = group->lock(2, 2, [] {}); + std::unique_ptr lock2 = group->lock(2, util::Priority::NORMAL, [] {}); THEN("The new lock should be false") { CHECK(lock1->lock() == true); @@ -128,7 +128,7 @@ namespace threading { } } AND_WHEN("Not locking the lock and creating a higher priority task") { - std::unique_ptr lock2 = group->lock(2, 2, [] {}); + std::unique_ptr lock2 = group->lock(2, util::Priority::NORMAL, [] {}); THEN("The new lock should be true") { CHECK(lock1->lock() == false); @@ -151,11 +151,11 @@ namespace threading { std::array notified = {0, 0, 0, 0, 0}; std::array, n_locks> locks; - locks[3] = group->lock(3, 1, [&] { ++notified[3]; }); - locks[1] = group->lock(1, 1, [&] { ++notified[1]; }); - locks[4] = group->lock(4, 1, [&] { ++notified[4]; }); - locks[0] = group->lock(0, 1, [&] { ++notified[0]; }); - locks[2] = group->lock(2, 1, [&] { ++notified[2]; }); + locks[3] = group->lock(3, util::Priority::LOW, [&] { ++notified[3]; }); + locks[1] = group->lock(1, util::Priority::LOW, [&] { ++notified[1]; }); + locks[4] = group->lock(4, util::Priority::LOW, [&] { ++notified[4]; }); + locks[0] = group->lock(0, util::Priority::LOW, [&] { ++notified[0]; }); + locks[2] = group->lock(2, util::Priority::LOW, [&] { ++notified[2]; }); THEN("The locks should be lockable in the proper order") { CHECK(locks[0]->lock() == (0 < n_tokens)); @@ -198,11 +198,11 @@ namespace threading { WHEN("Creating a series of locks") { std::array notified = {0, 0, 0, 0, 0}; std::array, n_locks> locks = { - group->lock(0, 1, [&] { ++notified[0]; }), - group->lock(1, 1, [&] { ++notified[1]; }), - group->lock(2, 1, [&] { ++notified[2]; }), - group->lock(3, 1, [&] { ++notified[3]; }), - group->lock(4, 1, [&] { ++notified[4]; }), + group->lock(0, util::Priority::LOW, [&] { ++notified[0]; }), + group->lock(1, util::Priority::LOW, [&] { ++notified[1]; }), + group->lock(2, util::Priority::LOW, [&] { ++notified[2]; }), + group->lock(3, util::Priority::LOW, [&] { ++notified[3]; }), + group->lock(4, util::Priority::LOW, [&] { ++notified[4]; }), }; // Note that because this is in a scope, for the rest of the AND_WHEN calls, no locks have been @@ -291,9 +291,9 @@ namespace threading { WHEN("Creating a series of locks") { std::array notified = {0, 0, 0}; std::array, 3> locks = { - group->lock(0, 1, [&] { ++notified[0]; }), - group->lock(1, 1, [&] { ++notified[1]; }), - group->lock(2, 1, [&] { ++notified[2]; }), + group->lock(0, util::Priority::LOW, [&] { ++notified[0]; }), + group->lock(1, util::Priority::LOW, [&] { ++notified[1]; }), + group->lock(2, util::Priority::LOW, [&] { ++notified[2]; }), }; THEN("Locking and then unlocking the second lock") { @@ -316,7 +316,7 @@ namespace threading { WHEN("Creating a lock and locking it") { int notified1 = 0; - std::unique_ptr lock1 = group->lock(1, 1, [&] { ++notified1; }); + std::unique_ptr lock1 = group->lock(1, util::Priority::LOW, [&] { ++notified1; }); lock1->lock(); THEN("The lock should be true") { @@ -325,7 +325,7 @@ namespace threading { AND_WHEN("Creating a second lock with a higher priority") { int notified2 = 0; - std::unique_ptr lock2 = group->lock(2, 2, [&] { ++notified2; }); + std::unique_ptr lock2 = group->lock(2, util::Priority::NORMAL, [&] { ++notified2; }); THEN("The new lock should be false") { CHECK(lock1->lock() == true); @@ -352,7 +352,7 @@ namespace threading { WHEN("Creating a lock and locking it") { int notified1 = 0; - std::unique_ptr lock1 = group->lock(1, 1, [&] { ++notified1; }); + std::unique_ptr lock1 = group->lock(1, util::Priority::LOW, [&] { ++notified1; }); lock1->lock(); THEN("The lock should be true") { @@ -361,7 +361,7 @@ namespace threading { AND_WHEN("Adding a second lock") { int notified2 = 0; - std::unique_ptr lock2 = group->lock(2, 1, [&] { ++notified2; }); + std::unique_ptr lock2 = group->lock(2, util::Priority::LOW, [&] { ++notified2; }); THEN("The second lock should be false") { CHECK(lock2->lock() == false); @@ -378,7 +378,7 @@ namespace threading { AND_WHEN("Adding a third lock with higher priority") { int notified3 = 0; - std::unique_ptr lock3 = group->lock(3, 2, [&] { ++notified3; }); + std::unique_ptr lock3 = group->lock(3, util::Priority::NORMAL, [&] { ++notified3; }); THEN("The third lock should be lockable and second lock should not") { CHECK(lock3->lock() == true);