From 933e3b39d4b69b1f7259292a6d1c18984df4debd Mon Sep 17 00:00:00 2001 From: tanneberger Date: Thu, 31 Oct 2024 18:35:46 +0100 Subject: [PATCH 1/8] snapshot --- examples/ports/main.cc | 2 +- include/reactor-cpp/logging.hh | 1 - include/reactor-cpp/multiport.hh | 10 ++++-- include/reactor-cpp/reaction.hh | 3 +- include/reactor-cpp/reactor-cpp.hh | 1 + include/reactor-cpp/scops.hh | 54 +++++++++++++++++++++++++++++ include/reactor-cpp/transaction.hh | 55 ++++++++++++++++++++++++++++++ lib/CMakeLists.txt | 2 ++ lib/multiport.cc | 2 +- lib/reaction.cc | 6 ++-- lib/scops.cc | 13 +++++++ lib/transaction.cc | 25 ++++++++++++++ 12 files changed, 165 insertions(+), 9 deletions(-) create mode 100644 include/reactor-cpp/scops.hh create mode 100644 include/reactor-cpp/transaction.hh create mode 100644 lib/scops.cc create mode 100644 lib/transaction.cc diff --git a/examples/ports/main.cc b/examples/ports/main.cc index 671d89b7..b0a0eb4c 100644 --- a/examples/ports/main.cc +++ b/examples/ports/main.cc @@ -85,7 +85,7 @@ class Adder : public Reactor { r_add.declare_antidependency(&sum); } - void add() { + void add(Adder* self) { if (i1.is_present() && i2.is_present()) { sum.set(*i1.get() + *i2.get()); std::cout << "setting sum\n"; diff --git a/include/reactor-cpp/logging.hh b/include/reactor-cpp/logging.hh index 4ba08434..4f457309 100644 --- a/include/reactor-cpp/logging.hh +++ b/include/reactor-cpp/logging.hh @@ -30,7 +30,6 @@ private: // NOLINTNEXTLINE (cppcoreguidelines-avoid-non-const-global-variables) inline static std::mutex mutex_{}; - Lock lock_{}; public: diff --git a/include/reactor-cpp/multiport.hh b/include/reactor-cpp/multiport.hh index 3e66cee5..bbf4a48c 100644 --- a/include/reactor-cpp/multiport.hh +++ b/include/reactor-cpp/multiport.hh @@ -23,14 +23,14 @@ namespace reactor { class BaseMultiport { // NOLINT cppcoreguidelines-special-member-functions,-warnings-as-errors private: - std::atomic size_{0}; + std::atomic present_ports_size_{0}; std::vector present_ports_{}; // record that the port with the given index has been set void set_present(std::size_t index); // reset the list of set port indexes - void reset() noexcept { size_.store(0, std::memory_order_relaxed); } + void reset() noexcept { present_ports_size_.store(0, std::memory_order_relaxed); } [[nodiscard]] auto get_set_callback(std::size_t index) noexcept -> PortCallback; const PortCallback clean_callback_{[this]([[maybe_unused]] const BasePort& port) { this->reset(); }}; @@ -39,7 +39,7 @@ private: protected: [[nodiscard]] auto present_ports() const -> const auto& { return present_ports_; } - [[nodiscard]] auto present_ports_size() const -> auto { return size_.load(); } + [[nodiscard]] auto present_ports_size() const -> auto { return present_ports_size_.load(); } void present_ports_reserve(size_t n) { present_ports_.reserve(n); } @@ -50,11 +50,15 @@ public: ~BaseMultiport() = default; }; +template +class MutationChangeMultiportSize; + template > class Multiport : public BaseMultiport { // NOLINT cppcoreguidelines-special-member-functions protected: std::vector ports_{}; // NOLINT cppcoreguidelines-non-private-member-variables-in-classes + friend MutationChangeMultiportSize; public: using value_type = typename A::value_type; using size_type = typename A::size_type; diff --git a/include/reactor-cpp/reaction.hh b/include/reactor-cpp/reaction.hh index 84b8e539..c90bd017 100644 --- a/include/reactor-cpp/reaction.hh +++ b/include/reactor-cpp/reaction.hh @@ -27,6 +27,7 @@ private: std::set dependencies_; const int priority_; + const bool mutation_; unsigned int index_{}; std::function body_{nullptr}; @@ -37,7 +38,7 @@ private: void set_deadline_impl(Duration deadline, const std::function& handler); public: - Reaction(const std::string& name, int priority, Reactor* container, std::function body); + Reaction(const std::string& name, int priority, bool mutation, Reactor* container, std::function body); ~Reaction() override = default; diff --git a/include/reactor-cpp/reactor-cpp.hh b/include/reactor-cpp/reactor-cpp.hh index 420ed9e3..e4fc89db 100644 --- a/include/reactor-cpp/reactor-cpp.hh +++ b/include/reactor-cpp/reactor-cpp.hh @@ -21,5 +21,6 @@ #include "reaction.hh" #include "reactor.hh" #include "time.hh" +#include "scops.hh" #endif // REACTOR_CPP_REACTOR_CPP_HH diff --git a/include/reactor-cpp/scops.hh b/include/reactor-cpp/scops.hh new file mode 100644 index 00000000..cb046fd8 --- /dev/null +++ b/include/reactor-cpp/scops.hh @@ -0,0 +1,54 @@ +/* +* Copyright (C) 2024 TU Dresden +* All rights reserved. +* +* Authors: +* Tassilo Tanneberger +*/ + +#ifndef REACTOR_CPP_SCOPS_HH +#define REACTOR_CPP_SCOPS_HH + +#include "transaction.hh" +#include "time.hh" + +namespace reactor { +class Reactor; + +class Scope { +private: + reactor::Reactor* reactor; + +public: + Scope(reactor::Reactor* reactor) + : reactor(reactor) {} + + auto get_physical_time() const -> reactor::TimePoint { return reactor->get_physical_time(); } + auto get_tag() const -> reactor::Tag { return reactor->get_tag(); } + auto get_logical_time() const -> reactor::TimePoint { return reactor->get_logical_time(); } + auto get_microstep() const -> reactor::mstep_t { return reactor->get_microstep(); } + auto get_elapsed_logical_time() const -> reactor::Duration { return reactor->get_elapsed_logical_time(); } + auto get_elapsed_physical_time() const -> reactor::Duration { return reactor->get_elapsed_physical_time(); } + auto environment() const -> reactor::Environment* { return reactor->environment(); } + void request_stop() const { return environment()->sync_shutdown(); } +}; + +template +class MutableScope : public Scope { +public: + HostReactor* self_ = nullptr; + Environment* env_ = nullptr; + Transaction transaction_; + + explicit MutableScope(reactor::Reactor* reactor) : Scope(reactor), self_(reactor), env_(reactor->environment()) {} + ~MutableScope() = default; + + void begin_transaction(); + void end_transaction(); + void mutate(const std::unique_ptr&& mutation); + +}; + +} + +#endif // REACTOR_CPP_SCOPS_HH diff --git a/include/reactor-cpp/transaction.hh b/include/reactor-cpp/transaction.hh new file mode 100644 index 00000000..079aaf4f --- /dev/null +++ b/include/reactor-cpp/transaction.hh @@ -0,0 +1,55 @@ +/* +* Copyright (C) 2024 TU Dresden +* All rights reserved. +* +* Authors: +* Tassilo Tanneberger + */ + +#ifndef REACTOR_CPP_TRANSACTION_HH +#define REACTOR_CPP_TRANSACTION_HH + +#include + +#include "multiport.hh" + +namespace reactor { +class Reactor; +class Environment; + +enum MutationResult { + Success = 0, + NotMatchingBankSize = 1, +}; + +class Mutation { +public: + virtual auto run() -> MutationResult = 0 ; + +}; + +template +class MutationChangeMultiportSize : public Mutation { +private: + Multiport* multiport_ = nullptr; + std::size_t desired_size_ = 0; +public: + MutationChangeMultiportSize(Multiport* multiport, std::size_t size); + ~MutationChangeMultiportSize() = default; + void run() override; +}; + + +class Transaction { +private: + Reactor* parent = nullptr; + Environment* environment = nullptr; + std::vector mutations_{}; + +public: + void reset(); + auto execute() -> MutationResult; + +}; +} +#endif // REACTOR_CPP_TRANSACTION_HH diff --git a/lib/CMakeLists.txt b/lib/CMakeLists.txt index 6f2ffd7d..75ecf535 100644 --- a/lib/CMakeLists.txt +++ b/lib/CMakeLists.txt @@ -7,7 +7,9 @@ set(SOURCE_FILES reaction.cc reactor.cc scheduler.cc + scops.cc time.cc + transaction.cc multiport.cc reactor_element.cc ) diff --git a/lib/multiport.cc b/lib/multiport.cc index c6674cb1..ca9c5d82 100644 --- a/lib/multiport.cc +++ b/lib/multiport.cc @@ -21,7 +21,7 @@ auto reactor::BaseMultiport::get_set_callback(std::size_t index) noexcept -> rea } void reactor::BaseMultiport::set_present(std::size_t index) { - auto calculated_index = size_.fetch_add(1, std::memory_order_relaxed); + auto calculated_index = present_ports_size_.fetch_add(1, std::memory_order_relaxed); reactor_assert(calculated_index < present_ports_.size()); diff --git a/lib/reaction.cc b/lib/reaction.cc index 697ab52b..4e895da5 100644 --- a/lib/reaction.cc +++ b/lib/reaction.cc @@ -17,10 +17,12 @@ namespace reactor { -Reaction::Reaction(const std::string& name, int priority, Reactor* container, std::function body) +Reaction::Reaction(const std::string& name, int priority, bool mutation, Reactor* container, std::function body) : ReactorElement(name, ReactorElement::Type::Reaction, container) , priority_(priority) - , body_(std::move(std::move(body))) { + , mutation_(mutation) + , body_(std::move(std::move(body))) +{ reactor_assert(priority != 0); } diff --git a/lib/scops.cc b/lib/scops.cc new file mode 100644 index 00000000..d52f3ce0 --- /dev/null +++ b/lib/scops.cc @@ -0,0 +1,13 @@ + + +#include "reactor-cpp/scops.hh" + +template +void reactor::MutableScope::begin_transaction() { + transaction_.reset(); +} + +template +void reactor::MutableScope::end_transaction() { + transaction_.execute(); +} \ No newline at end of file diff --git a/lib/transaction.cc b/lib/transaction.cc new file mode 100644 index 00000000..91c256da --- /dev/null +++ b/lib/transaction.cc @@ -0,0 +1,25 @@ + + +#include "reactor-cpp/transaction.hh" + +template +reactor::MutationChangeMultiportSize::MutationChangeMultiportSize(Multiport* multiport, std::size_t size) + : multiport_(multiport), desired_size_(size){ +} + +template +void reactor::MutationChangeMultiportSize::run() { + multiport_->ports_.resize(desired_size_); +} + +auto reactor::Transaction::execute() -> MutationResult { + for (auto *mutation : mutations_) { + mutation->run(); + } + + return Success; +} + +void reactor::Transaction::reset() { + mutations_.clear(); +} \ No newline at end of file From 135797287740f0669ce687b01fc19118be03bd28 Mon Sep 17 00:00:00 2001 From: tanneberger Date: Mon, 11 Nov 2024 02:42:23 +0100 Subject: [PATCH 2/8] fixing --- examples/power_train/main.cc | 11 ++++++++++- include/reactor-cpp/scops.hh | 5 ++--- include/reactor-cpp/transaction.hh | 14 ++++++++------ lib/transaction.cc | 14 +++++++++++--- 4 files changed, 31 insertions(+), 13 deletions(-) diff --git a/examples/power_train/main.cc b/examples/power_train/main.cc index 05efe57f..155c3501 100644 --- a/examples/power_train/main.cc +++ b/examples/power_train/main.cc @@ -140,7 +140,7 @@ class Engine : public Reactor { public: // ports Input torque{"torque", this}; // NOLINT - + Multiport control_input; private: // reactions_ Reaction r1{"1", 1, this, [this]() { reaction_1(); }}; @@ -180,3 +180,12 @@ auto main() -> int { return 0; } + +class ReactionScope : public MutableScope { + void reaction_0() { + MutationChangeMultiportSize change_multiport_width{&this->self_->control_input, 6}; + this->add_to_transaction(&change_multiport_width); + + this->commit_transaction(); + } +}; diff --git a/include/reactor-cpp/scops.hh b/include/reactor-cpp/scops.hh index cb046fd8..430f8d8a 100644 --- a/include/reactor-cpp/scops.hh +++ b/include/reactor-cpp/scops.hh @@ -43,9 +43,8 @@ public: explicit MutableScope(reactor::Reactor* reactor) : Scope(reactor), self_(reactor), env_(reactor->environment()) {} ~MutableScope() = default; - void begin_transaction(); - void end_transaction(); - void mutate(const std::unique_ptr&& mutation); + void commit_transaction(); + void add_to_transaction(Mutation* mutation); }; diff --git a/include/reactor-cpp/transaction.hh b/include/reactor-cpp/transaction.hh index 079aaf4f..9da4e6a3 100644 --- a/include/reactor-cpp/transaction.hh +++ b/include/reactor-cpp/transaction.hh @@ -24,8 +24,9 @@ enum MutationResult { class Mutation { public: + virtual ~Mutation() = default; virtual auto run() -> MutationResult = 0 ; - + virtual auto rollback() -> MutationResult = 0; }; template @@ -33,12 +34,14 @@ class MutationChangeMultiportSize : public Mutation { private: Multiport* multiport_ = nullptr; std::size_t desired_size_ = 0; + std::size_t size_before_application_ = 0; public: MutationChangeMultiportSize(Multiport* multiport, std::size_t size); - ~MutationChangeMultiportSize() = default; - void run() override; -}; + ~MutationChangeMultiportSize() override = default; + auto run() -> MutationResult override; + auto rollback() -> MutationResult override; +}; class Transaction { private: @@ -47,9 +50,8 @@ private: std::vector mutations_{}; public: - void reset(); + void push_back(Mutation* mutation); auto execute() -> MutationResult; - }; } #endif // REACTOR_CPP_TRANSACTION_HH diff --git a/lib/transaction.cc b/lib/transaction.cc index 91c256da..17aba182 100644 --- a/lib/transaction.cc +++ b/lib/transaction.cc @@ -8,10 +8,18 @@ reactor::MutationChangeMultiportSize::MutationChangeMultiportSize(Multiport -void reactor::MutationChangeMultiportSize::run() { +auto reactor::MutationChangeMultiportSize::run() -> MutationResult { multiport_->ports_.resize(desired_size_); + + return Success; +} + +template +auto reactor::MutationChangeMultiportSize::rollback() -> MutationResult { + return Success; } + auto reactor::Transaction::execute() -> MutationResult { for (auto *mutation : mutations_) { mutation->run(); @@ -20,6 +28,6 @@ auto reactor::Transaction::execute() -> MutationResult { return Success; } -void reactor::Transaction::reset() { - mutations_.clear(); +void reactor::Transaction::push_back(reactor::Mutation* mutation) { + mutations_.push_back(mutation); } \ No newline at end of file From 2e4c112e85df6d5cd32d0a9ee5c2b80280d25e70 Mon Sep 17 00:00:00 2001 From: tanneberger Date: Mon, 9 Dec 2024 05:07:17 +0100 Subject: [PATCH 3/8] init mutations --- examples/CMakeLists.txt | 2 + examples/count/main.cc | 4 +- examples/multiport_mutation/CMakeLists.txt | 3 + examples/multiport_mutation/consumer.hh | 46 +++++++++ examples/multiport_mutation/load_balancer.hh | 82 +++++++++++++++ examples/multiport_mutation/main.cc | 100 +++++++++++++++++++ examples/multiport_mutation/producer.hh | 45 +++++++++ examples/ports/main.cc | 6 +- examples/unit_tests_mutations/CMakeLists.txt | 3 + examples/unit_tests_mutations/main.cc | 82 +++++++++++++++ include/reactor-cpp/environment.hh | 39 +++++++- include/reactor-cpp/graph.hh | 14 +++ include/reactor-cpp/impl/port_impl.hh | 5 +- include/reactor-cpp/logging.hh | 3 - include/reactor-cpp/multiport.hh | 22 +++- include/reactor-cpp/mutations.hh | 22 ++++ include/reactor-cpp/mutations/bank.hh | 39 ++++++++ include/reactor-cpp/mutations/connection.hh | 33 ++++++ include/reactor-cpp/mutations/multiport.hh | 43 ++++++++ include/reactor-cpp/port.hh | 31 +++++- include/reactor-cpp/reaction.hh | 6 +- include/reactor-cpp/reactor-cpp.hh | 2 +- include/reactor-cpp/reactor.hh | 9 +- include/reactor-cpp/reactor_element.hh | 6 +- include/reactor-cpp/{scops.hh => scopes.hh} | 16 +-- include/reactor-cpp/transaction.hh | 35 ++----- lib/CMakeLists.txt | 9 +- lib/environment.cc | 21 ++-- lib/logical_time.cc | 3 +- lib/mutation/bank.cc | 49 +++++++++ lib/mutation/connection.cc | 35 +++++++ lib/mutation/multiport.cc | 54 ++++++++++ lib/port.cc | 4 +- lib/reaction.cc | 8 +- lib/reactor.cc | 50 ++++++++-- lib/reactor_element.cc | 4 +- lib/scopes.cc | 11 ++ lib/scops.cc | 13 --- lib/transaction.cc | 33 +++--- 39 files changed, 862 insertions(+), 130 deletions(-) create mode 100644 examples/multiport_mutation/CMakeLists.txt create mode 100644 examples/multiport_mutation/consumer.hh create mode 100644 examples/multiport_mutation/load_balancer.hh create mode 100644 examples/multiport_mutation/main.cc create mode 100644 examples/multiport_mutation/producer.hh create mode 100644 examples/unit_tests_mutations/CMakeLists.txt create mode 100644 examples/unit_tests_mutations/main.cc create mode 100644 include/reactor-cpp/mutations.hh create mode 100644 include/reactor-cpp/mutations/bank.hh create mode 100644 include/reactor-cpp/mutations/connection.hh create mode 100644 include/reactor-cpp/mutations/multiport.hh rename include/reactor-cpp/{scops.hh => scopes.hh} (81%) create mode 100644 lib/mutation/bank.cc create mode 100644 lib/mutation/connection.cc create mode 100644 lib/mutation/multiport.cc create mode 100644 lib/scopes.cc delete mode 100644 lib/scops.cc diff --git a/examples/CMakeLists.txt b/examples/CMakeLists.txt index 5f05c960..3d40852e 100644 --- a/examples/CMakeLists.txt +++ b/examples/CMakeLists.txt @@ -7,3 +7,5 @@ add_subdirectory(count) add_subdirectory(ports) add_subdirectory(hello) add_subdirectory(power_train) +add_subdirectory(multiport_mutation) +add_subdirectory(unit_tests_mutations) diff --git a/examples/count/main.cc b/examples/count/main.cc index e0c6e92b..ca20df5d 100644 --- a/examples/count/main.cc +++ b/examples/count/main.cc @@ -12,8 +12,8 @@ class Count : public Reactor { LogicalAction counter{"counter", this}; // reactions_ - Reaction r_init{"r_init", 1, this, [this]() { init(); }}; - Reaction r_counter{"r_counter", 2, this, [this]() { print_count(); }}; + Reaction r_init{"r_init", 1, false, this, [this]() { this->init(); }}; + Reaction r_counter{"r_counter", 2, false, this, [this]() { this->print_count(); }}; public: explicit Count(Environment* env) diff --git a/examples/multiport_mutation/CMakeLists.txt b/examples/multiport_mutation/CMakeLists.txt new file mode 100644 index 00000000..b19dd98a --- /dev/null +++ b/examples/multiport_mutation/CMakeLists.txt @@ -0,0 +1,3 @@ +add_executable(mutation_multiports main.cc) +target_link_libraries(mutation_multiports reactor-cpp) +add_dependencies(examples mutation_multiports) diff --git a/examples/multiport_mutation/consumer.hh b/examples/multiport_mutation/consumer.hh new file mode 100644 index 00000000..2265b62b --- /dev/null +++ b/examples/multiport_mutation/consumer.hh @@ -0,0 +1,46 @@ +// +// Created by tanneberger on 11/17/24. +// + +#ifndef CONSUMER_HH +#define CONSUMER_HH + +#include + +using namespace reactor; +using namespace std::chrono_literals; + +class Consumer : public Reactor { +private: + class Inner: public Scope { + Inner(Reactor* reactor, std::size_t index) : Scope(reactor), index_(index) {} + std::size_t index_; + + [[maybe_unused]] const Inner& __lf_inner = *this; + + void reaction_1([[maybe_unused]] const Input& scale) { + std::cout << "consumer: " << index_ << " received value!" << std::endl; + } + + friend Consumer; + }; + + Inner __lf_inner; + Reaction handle{"handle", 1, this, [this]() { __lf_inner.reaction_1(this->in); }}; +public: + Consumer(const std::string& name, Environment* env, std::size_t index) : Reactor(name, env), __lf_inner(this, index) { + std::cout << "creating instance of consumer" << std::endl; + } + ~Consumer() override { + std::cout << "Consumer Object is deleted" << std::endl; + }; + + Input in{"in", this}; + + void assemble() override { + handle.declare_trigger(&in); + } +}; + + +#endif //CONSUMER_HH diff --git a/examples/multiport_mutation/load_balancer.hh b/examples/multiport_mutation/load_balancer.hh new file mode 100644 index 00000000..d701e33e --- /dev/null +++ b/examples/multiport_mutation/load_balancer.hh @@ -0,0 +1,82 @@ +// +// Created by tanneberger on 11/17/24. +// + +#ifndef LOAD_BALANCER_HH +#define LOAD_BALANCER_HH + +#include + +#include "../../lib/mutation/multiport.cc" +#include "reactor-cpp/mutations/multiport.hh" + +using namespace reactor; +using namespace std::chrono_literals; + +class LoadBalancer : public Reactor { +private: + class Inner: public MutableScope { + Inner(Reactor* reactor) : MutableScope(reactor) {} + [[maybe_unused]] const Inner& __lf_inner = *this; + + // reaction bodies + void reaction_1(const Input& inbound, LogicalAction& scale_action, Multiport>& outbound) { + if (rand() % 30 == 0) { + scale_action.schedule(rand() % 20 + 1); + } + + std::cout << "multiport size: " << outbound.size() << std::endl; + outbound[rand() % outbound.size()].set(inbound.get()); + } + + void reaction_2(ModifableMultiport>&outbound, [[maybe_unused]] const LogicalAction& scale, Output& scale_bank) { + ModifableMultiport>* temp = &outbound; + std::size_t new_size = *scale.get(); + + auto antideps = (outbound[0]).anti_dependencies(); + + MutationChangeOutputMultiportSize change_size{temp, this->reactor_, antideps, new_size}; + + add_to_transaction(&change_size); + + commit_transaction(); + + scale_bank.set(new_size); + } + + friend LoadBalancer; + }; + + Inner __lf_inner; + Reaction process{"process", 2, this, [this]() { __lf_inner.reaction_1(this->inbound, this->scale_action, this->out); }}; + Reaction scale{"scale", 1, this, [this]() { __lf_inner.reaction_2(this->out, this->scale_action, this->scale_bank); }}; + +public: + LoadBalancer(const std::string& name, Environment* env) + : Reactor(name, env), __lf_inner(this) { + std::cout << "creating instance of load balancer" << std::endl; + out.reserve(4); + for (size_t _lf_idx = 0; _lf_idx < 4; _lf_idx++) { + std::string _lf_port_name = out.name() + "_" + std::to_string(_lf_idx); + out.emplace_back(_lf_port_name, this); + } + } + + LogicalAction scale_action{"scale", this, 1us}; + ModifableMultiport> out{"out"}; + Input inbound{"inbound", this}; // NOLINT + Output scale_bank{"scale_bank", this}; + + void assemble() override { + std::cout << "assemble LoadBalancer\n"; + for (auto& __lf_port : out) { + process.declare_antidependency(&__lf_port); + } + process.declare_trigger(&inbound); + scale.declare_trigger(&scale_action); + } +}; + + + +#endif //LOAD_BALANCER_HH diff --git a/examples/multiport_mutation/main.cc b/examples/multiport_mutation/main.cc new file mode 100644 index 00000000..1f38f736 --- /dev/null +++ b/examples/multiport_mutation/main.cc @@ -0,0 +1,100 @@ +#include + +#include +#include + +#include "./consumer.hh" +#include "./load_balancer.hh" +#include "./producer.hh" +#include "../../lib/mutation/bank.cc" +#include "../../lib/mutation/connection.cc" +#include + +class Deployment : public Reactor { + std::unique_ptr producer_; + std::unique_ptr load_balancer_; + std::vector> consumers_; + + Reaction scale_bank{"scale_bank", 1, this, [this](){this->__inner.reaction_1(this->scale, this->consumers_, load_balancer_->out);}}; + +public: + +class Inner: public MutableScope { + int state = 0; + [[maybe_unused]] const Inner& __lf_inner = *this; +public: + + Inner(Reactor* reactor) : MutableScope(reactor) {} + void reaction_1(const Input& scale, std::vector>& reactor_bank, ModifableMultiport>& load_balancer) { + std::size_t new_size = *scale.get(); + std::size_t old_size = reactor_bank.size(); + + std::function(Reactor*, std::size_t)> lambda = [](Reactor* reactor, std::size_t index) { + std::string __lf_inst_name = "consumer_" + std::to_string(index); + return std::make_unique(__lf_inst_name, reactor->environment(), index); + }; + MutationChangeBankSize change_size{&reactor_bank, this->reactor_, new_size, lambda}; + + add_to_transaction(&change_size); + + // old topology + commit_transaction(); + // new topology + + if (old_size > new_size) { + + for (auto i = 0; i < old_size - new_size; i++) { + } + } else { + std::cout << "load_balancer size:" << load_balancer.size() << " bank size: " << reactor_bank.size() << std::endl; + for (auto i = 0; i < new_size - old_size; i++) { + std::cout << "add connection: " << i + old_size << std::endl; + MutationAddConnection, Input> add_conn{&load_balancer[i + old_size], &reactor_bank[i + old_size].get()->in, reactor_}; + add_to_transaction(&add_conn); + commit_transaction(); + } + } + + std::cout << "new bank size:" << reactor_bank.size() << std::endl; + } + + friend LoadBalancer; + }; + + Inner __inner; + + Deployment(const std::string& name, Environment* env) : Reactor(name, env), __inner(this), + producer_(std::make_unique("producer", environment())), + load_balancer_(std::make_unique("load_balancer", environment())) { + std::cout << "creating instance of deployment" << std::endl; + consumers_.reserve(4); + for (size_t __lf_idx = 0; __lf_idx < 4; __lf_idx++) { + std::string __lf_inst_name = "consumer_" + std::to_string(__lf_idx); + consumers_.push_back(std::make_unique(__lf_inst_name, environment(), __lf_idx)); + } + } + ~Deployment() override = default; + + Input scale{"scale", this}; + + void assemble() override { + for (size_t __lf_idx = 0; __lf_idx < 4; __lf_idx++) { + environment()->draw_connection(load_balancer_->out[__lf_idx], consumers_[__lf_idx]->in, ConnectionProperties{}); + environment()->draw_connection(producer_->value, load_balancer_->inbound, ConnectionProperties{}); + } + environment()->draw_connection(load_balancer_->scale_bank, scale, ConnectionProperties{}); + scale_bank.declare_trigger(&this->scale); + } +}; + + +auto main() -> int { + //srand(time(nullptr)); + Environment env{4}; + auto deployment = std::make_unique("c1", &env); + env.optimize(); + env.assemble(); + auto thread = env.startup(); + thread.join(); + return 0; +} diff --git a/examples/multiport_mutation/producer.hh b/examples/multiport_mutation/producer.hh new file mode 100644 index 00000000..9894412d --- /dev/null +++ b/examples/multiport_mutation/producer.hh @@ -0,0 +1,45 @@ +// +// Created by tanneberger on 11/17/24. +// + +#ifndef PRODUCER_HH +#define PRODUCER_HH + +#include + +using namespace reactor; +using namespace std::chrono_literals; + +class Producer : public Reactor { +private: + Timer timer{"timer", this, 1s, 1s}; + Reaction r_timer{"r_timer", 1, this, [this]() { __lf_inner.reaction_1(this->value);}}; + + class Inner: public Scope { + [[maybe_unused]] const Inner& __lf_inner = *this; + void reaction_1([[maybe_unused]] Output& out) { + std::cout << "producing value" << std::endl; + out.set(42); + } + explicit Inner(Reactor* reactor) : Scope(reactor) {} + + friend Producer; + }; + + Inner __lf_inner; +public: + Producer(const std::string& name, Environment* env) : Reactor(name, env), __lf_inner(this) { + std::cout << "creating instance of producer" << std::endl; + } + Producer() = delete; + ~Producer() override = default; + + Output value{"value", this}; + + void assemble() override { + r_timer.declare_trigger(&timer); + r_timer.declare_antidependency(&value); + } +}; + +#endif //PRODUCER_HH diff --git a/examples/ports/main.cc b/examples/ports/main.cc index b0a0eb4c..d1dda5d1 100644 --- a/examples/ports/main.cc +++ b/examples/ports/main.cc @@ -51,7 +51,7 @@ class Counter : public Reactor { class Printer : public Reactor { private: - Reaction r_value{"r_value", 1, this, [this]() { on_value(); }}; + Reaction r_value{"r_value", 1, this, [this]() { this->on_value(); }}; public: Input value{"value", this}; // NOLINT @@ -69,7 +69,7 @@ class Printer : public Reactor { class Adder : public Reactor { private: - Reaction r_add{"r_add", 1, this, [this]() { add(); }}; + Reaction r_add{"r_add", 1, this, [this]() { this->add(); }}; public: Input i1{"i1", this}; // NOLINT @@ -85,7 +85,7 @@ class Adder : public Reactor { r_add.declare_antidependency(&sum); } - void add(Adder* self) { + void add() { if (i1.is_present() && i2.is_present()) { sum.set(*i1.get() + *i2.get()); std::cout << "setting sum\n"; diff --git a/examples/unit_tests_mutations/CMakeLists.txt b/examples/unit_tests_mutations/CMakeLists.txt new file mode 100644 index 00000000..0843149f --- /dev/null +++ b/examples/unit_tests_mutations/CMakeLists.txt @@ -0,0 +1,3 @@ +add_executable(unit_tests_mutations main.cc) +target_link_libraries(unit_tests_mutations reactor-cpp) +add_dependencies(examples unit_tests_mutations) diff --git a/examples/unit_tests_mutations/main.cc b/examples/unit_tests_mutations/main.cc new file mode 100644 index 00000000..0066d705 --- /dev/null +++ b/examples/unit_tests_mutations/main.cc @@ -0,0 +1,82 @@ +#include + +#include "../../lib/mutation/multiport.cc" +#include +#include + +using namespace std::chrono_literals; + +class TestMultiport: public reactor::Reactor { + reactor::ModifableMultiport> test_multiport_{"modifable_multiports_"}; + reactor::Timer timer_{"timer", this, 1s}; + reactor::LogicalAction scale{"scale", this}; + reactor::Reaction trigger_reaction_{"trigger_reaction", 1, this, [this](){this->__inner.reaction_1(scale);}}; + reactor::Reaction test_reaction_{"test_reaction", 2, this, [this](){this->__inner.reaction_2(test_multiport_, scale);}}; + reactor::Reaction validate_reaction_{"validate_reaction", 3, this, [this](){this->__inner.reaction_3(test_multiport_);}}; +public: + +class Inner: public reactor::MutableScope { + int state = 0; + std::vector sizes = {4, 5, 6, 5, 4, 3}; + [[maybe_unused]] const Inner& __lf_inner = *this; +public: + + Inner(Reactor* reactor) : MutableScope(reactor) {} + + void reaction_1(reactor::LogicalAction& scale) { + int size = sizes[state]; + state = (state + 1) % sizes.size(); + std::cout << "set: " << size << std::endl; + scale.schedule(size); + } + + void reaction_2(reactor::ModifableMultiport>& test_multiport, reactor::LogicalAction& scale) { + reactor::ModifableMultiport>* temp = &test_multiport; + std::size_t new_size = *scale.get(); + + auto anti_dep = test_multiport[0].anti_dependencies(); + reactor::MutationChangeOutputMultiportSize change_size{temp, this->reactor_, anti_dep, new_size}; + add_to_transaction(&change_size); + + commit_transaction(); + } + + void reaction_3(reactor::ModifableMultiport>& test_multiport) { + for (auto i = 0; i < test_multiport.size(); i++) { + std::cout << test_multiport[i].fqn() << "/" << std::endl; + } + } + }; + + Inner __inner; + + TestMultiport(const std::string& name, reactor::Environment* env) : Reactor(name, env), __inner(this) { + std::cout << "creating instance of deployment" << std::endl; + + test_multiport_.reserve(4); + for (size_t _lf_idx = 0; _lf_idx < 4; _lf_idx++) { + std::string _lf_port_name = test_multiport_.name() + "_" + std::to_string(_lf_idx); + test_multiport_.emplace_back(_lf_port_name, this); + } + } + ~TestMultiport() override = default; + + void assemble() override { + trigger_reaction_.declare_trigger(&timer_); + trigger_reaction_.declare_schedulable_action(&scale); + test_reaction_.declare_trigger(&scale); + + } +}; + + +auto main() -> int { + // srand(time(nullptr)); + reactor::Environment env{4}; + auto test_multiport = std::make_unique("test_multiport", &env); + env.optimize(); + env.assemble(); + auto thread = env.startup(); + thread.join(); + return 0; +} diff --git a/include/reactor-cpp/environment.hh b/include/reactor-cpp/environment.hh index 825b3bba..82e28559 100644 --- a/include/reactor-cpp/environment.hh +++ b/include/reactor-cpp/environment.hh @@ -32,8 +32,9 @@ enum class Phase : std::uint8_t { Assembly = 1, Startup = 2, Execution = 3, - Shutdown = 4, - Deconstruction = 5 + Mutation = 4, + Shutdown = 5, + Deconstruction = 6, }; class Environment { @@ -74,25 +75,53 @@ private: Graph graph_{}; Graph optimized_graph_{}; - void build_dependency_graph(Reactor* reactor); - void calculate_indexes(); std::mutex shutdown_mutex_{}; auto startup(const TimePoint& start_time) -> std::thread; public: + //TODO: fix visebility + void calculate_indexes(); + void build_dependency_graph(Reactor* reactor); + + explicit Environment(unsigned int num_workers, bool fast_fwd_execution = default_fast_fwd_execution, const Duration& timeout = Duration::max()); explicit Environment(const std::string& name, Environment* containing_environment); auto name() -> const std::string& { return name_; } + void start_mutation() { + phase_ = Phase::Mutation; + } + + void stop_mutation() { + phase_ = Phase::Execution; + } + // this method draw a connection between two graph elements with some properties template void draw_connection(Port& source, Port& sink, ConnectionProperties properties) { this->draw_connection(&source, &sink, properties); } + template void remove_connection(Port* source, Port* sink) { + if (top_environment_ == nullptr || top_environment_ == this) { + log::Debug() << "remove connection: " << source->fqn() << " -/-> " << sink->fqn(); + auto properties = graph_.remove_edge(source, sink); + } else { + return top_environment_->remove_connection(source, sink); + + } + } + + void remove_top_level_reactor(Reactor* reactor) { + auto elements_erased = top_level_reactors_.erase(reactor); + if (elements_erased == 0) { + std::cout << "no elements erased" << std::endl; + } + } + template void draw_connection(Port* source, Port* sink, ConnectionProperties properties) { if (top_environment_ == nullptr || top_environment_ == this) { log::Debug() << "drawing connection: " << source->fqn() << " --> " << sink->fqn(); @@ -114,7 +143,7 @@ public: void export_dependency_graph(const std::string& path); - [[nodiscard]] auto top_level_reactors() const noexcept -> const auto& { return top_level_reactors_; } + [[nodiscard]] auto top_level_reactors() noexcept -> auto& { return top_level_reactors_; } [[nodiscard]] auto phase() const noexcept -> Phase { return phase_; } [[nodiscard]] auto scheduler() const noexcept -> const Scheduler* { return &scheduler_; } diff --git a/include/reactor-cpp/graph.hh b/include/reactor-cpp/graph.hh index 4009e169..8544306f 100644 --- a/include/reactor-cpp/graph.hh +++ b/include/reactor-cpp/graph.hh @@ -58,6 +58,20 @@ public: } } + auto remove_edge(E source, E destinations) noexcept -> std::optional

{ + if (graph_.find(source) == std::end(graph_)) { + return std::nullopt; + } else { + auto conns = std::find_if(std::begin(graph_[source]), std::end(graph_[source]), [destinations](auto val) { + return val.second == destinations; + }); + + if (conns != std::end(graph_[source])) { + graph_[source].erase(conns); + } + } + } + // this groups connections by same source and properties [[nodiscard]] auto get_edges() const noexcept -> std::map, map_key_compare> { std::map, map_key_compare> all_edges{}; diff --git a/include/reactor-cpp/impl/port_impl.hh b/include/reactor-cpp/impl/port_impl.hh index db596dbb..836384d4 100644 --- a/include/reactor-cpp/impl/port_impl.hh +++ b/include/reactor-cpp/impl/port_impl.hh @@ -9,10 +9,11 @@ #ifndef REACTOR_CPP_IMPL_PORT_IMPL_HH #define REACTOR_CPP_IMPL_PORT_IMPL_HH -#include "reactor-cpp/assert.hh" -#include "reactor-cpp/environment.hh" #include "reactor-cpp/port.hh" #include "reactor-cpp/reactor.hh" +#include "reactor-cpp/assert.hh" +#include "reactor-cpp/environment.hh" + namespace reactor { diff --git a/include/reactor-cpp/logging.hh b/include/reactor-cpp/logging.hh index 4f457309..43da8212 100644 --- a/include/reactor-cpp/logging.hh +++ b/include/reactor-cpp/logging.hh @@ -10,13 +10,10 @@ #define REACTOR_CPP_LOGGING_HH #include "reactor-cpp/config.hh" -#include "reactor-cpp/time.hh" -#include #include #include #include #include -#include namespace reactor::log { diff --git a/include/reactor-cpp/multiport.hh b/include/reactor-cpp/multiport.hh index bbf4a48c..a0d2e81e 100644 --- a/include/reactor-cpp/multiport.hh +++ b/include/reactor-cpp/multiport.hh @@ -25,6 +25,8 @@ class BaseMultiport { // NOLINT cppcoreguidelines-special-member-functions,-warn private: std::atomic present_ports_size_{0}; std::vector present_ports_{}; + std::string multiport_name_; + std::string fqn_; // record that the port with the given index has been set void set_present(std::size_t index); @@ -42,12 +44,17 @@ protected: [[nodiscard]] auto present_ports_size() const -> auto { return present_ports_size_.load(); } void present_ports_reserve(size_t n) { present_ports_.reserve(n); } + void present_ports_pop_back() { present_ports_.pop_back(); } void register_port(BasePort& port, size_t idx); + public: - BaseMultiport() = default; + explicit BaseMultiport(const std::string& name) : multiport_name_(name) {}; ~BaseMultiport() = default; + auto name() const -> std::string { + return multiport_name_; + } }; template @@ -66,7 +73,7 @@ public: using iterator = typename std::vector::iterator; using const_iterator = typename std::vector::const_iterator; - Multiport() noexcept = default; + explicit Multiport(const std::string& name) noexcept : BaseMultiport(name) {}; ~Multiport() noexcept = default; auto operator==(const Multiport& other) const noexcept -> bool { @@ -99,16 +106,23 @@ public: template > class ModifableMultiport : public Multiport { public: + ModifableMultiport(const std::string& name) : Multiport(name) {} + void reserve(std::size_t size) noexcept { this->ports_.reserve(size); this->present_ports_reserve(size); } - void push_back(const T& elem) noexcept { - this->ports_.push_back(elem); + void push_back(const T&& elem) noexcept { + this->ports_.push_back(std::move(elem)); this->register_port(this->ports_.back(), this->ports_.size() - 1); } + void pop_back() { + this->ports_.pop_back(); + this->present_ports_pop_back(); + } + template void emplace_back(Args&&... args) noexcept { this->ports_.emplace_back(std::forward(args)...); this->register_port(this->ports_.back(), this->ports_.size() - 1); diff --git a/include/reactor-cpp/mutations.hh b/include/reactor-cpp/mutations.hh new file mode 100644 index 00000000..d507f89f --- /dev/null +++ b/include/reactor-cpp/mutations.hh @@ -0,0 +1,22 @@ +#ifndef MUTATIONS_HH +#define MUTATIONS_HH + +namespace reactor { +class Reactor; +class Environment; + +enum MutationResult { + Success = 0, + NotMatchingBankSize = 1, +}; + +class Mutation { +public: + virtual ~Mutation() = default; + virtual auto run() -> MutationResult = 0 ; + virtual auto rollback() -> MutationResult = 0; +}; + +} + +#endif //MUTATIONS_HH diff --git a/include/reactor-cpp/mutations/bank.hh b/include/reactor-cpp/mutations/bank.hh new file mode 100644 index 00000000..8d52490f --- /dev/null +++ b/include/reactor-cpp/mutations/bank.hh @@ -0,0 +1,39 @@ +// +// Created by tanneberger on 11/18/24. +// + +#ifndef MUTATION_BANK_HH +#define MUTATION_BANK_HH + +#include + +#include "../reactor.hh" +#include "../mutations.hh" + +namespace reactor { +class Reactor; +class Environment; + +template +class MutationChangeBankSize : public reactor::Mutation { +private: + std::vector* bank_ = nullptr; + std::size_t desired_size_ = 0; + std::size_t size_before_application_ = 0; + Reactor* reactor_ = nullptr; + std::function create_lambda_; + + void change_size(std::size_t); + +public: + MutationChangeBankSize(std::vector* bank, Reactor* reactor, std::size_t size, std::function); + MutationChangeBankSize() = default; + explicit MutationChangeBankSize(const std::vector& other) : bank_(other.bank_), desired_size_(other.desired_size_), size_before_application_(other.size_before_application_) {} + ~MutationChangeBankSize() override = default; + + auto run() -> reactor::MutationResult override; + auto rollback() -> reactor::MutationResult override; +}; +} + +#endif //MUTATION_BANK_HH diff --git a/include/reactor-cpp/mutations/connection.hh b/include/reactor-cpp/mutations/connection.hh new file mode 100644 index 00000000..2e2b02ef --- /dev/null +++ b/include/reactor-cpp/mutations/connection.hh @@ -0,0 +1,33 @@ +// +// Created by tanneberger on 11/18/24. +// + +#ifndef MUTATION_CONNECTION_HH +#define MUTATION_CONNECTION_HH + +#include "../mutations.hh" + +namespace reactor { +class Reactor; +class Environment; + +template +class MutationAddConnection : public Mutation { +private: + A* source_; + B* sink_; + bool connection_ = false; + Reactor* reactor_{}; + +public: + MutationAddConnection(A* source, B* sink, Reactor* reactor); + MutationAddConnection(const MutationAddConnection& other) : source_(other.source_), sink_(other.sink_), connection_(other.connection_), reactor_(other.reactor_) {} + MutationAddConnection() = default; + ~MutationAddConnection() override = default; + + auto run() -> MutationResult override; + auto rollback() -> MutationResult override; +}; +} + +#endif //MUTATION_CONNECTION_HH diff --git a/include/reactor-cpp/mutations/multiport.hh b/include/reactor-cpp/mutations/multiport.hh new file mode 100644 index 00000000..e7a86aaa --- /dev/null +++ b/include/reactor-cpp/mutations/multiport.hh @@ -0,0 +1,43 @@ +// +// Created by tanneberger on 11/11/24. +// + +#ifndef MUTATION_MULTIPORT_HH +#define MUTATION_MULTIPORT_HH + +#include + +#include "../multiport.hh" +#include "../mutations.hh" +#include "../port.hh" + + +namespace reactor { +class Reactor; +class Environment; + +template +class MutationChangeOutputMultiportSize : public Mutation { +private: + ModifableMultiport>* multiport_ = nullptr; + std::set anti_dependencies_{}; + std::size_t desired_size_ = 0; + std::size_t size_before_application_ = 0; + Reactor* reactor_{}; + + void change_size(std::size_t); + +public: + MutationChangeOutputMultiportSize(ModifableMultiport>* multiport, Reactor* reactor, std::set& anti_dependencies, std::size_t size); + MutationChangeOutputMultiportSize() = default; + MutationChangeOutputMultiportSize(const MutationChangeOutputMultiportSize& other) : multiport_(other.multiport_), desired_size_(other.desired_size_), size_before_application_(other.size_before_application_) {} + ~MutationChangeOutputMultiportSize() override = default; + + + auto run() -> MutationResult override; + auto rollback() -> MutationResult override; +}; +} + + +#endif //MUTATION_MULTIPORT_HH diff --git a/include/reactor-cpp/port.hh b/include/reactor-cpp/port.hh index fd3048da..a8e74e07 100644 --- a/include/reactor-cpp/port.hh +++ b/include/reactor-cpp/port.hh @@ -22,6 +22,9 @@ namespace reactor { +template +class MutationChangeMultiportSize; + enum class PortType : std::uint8_t { Input, Output, Delay }; class BasePort : public ReactorElement { @@ -44,8 +47,6 @@ protected: : ReactorElement(name, match_port_enum(type), container) , type_(type) {} - void register_dependency(Reaction* reaction, bool is_trigger) noexcept; - void register_antidependency(Reaction* reaction) noexcept; virtual void cleanup() = 0; static auto match_port_enum(PortType type) noexcept -> ReactorElement::Type { @@ -72,7 +73,15 @@ protected: } public: - void set_inward_binding(BasePort* port) noexcept { inward_binding_ = port; } + void register_dependency(Reaction* reaction, bool is_trigger) noexcept; + void register_antidependency(Reaction* reaction) noexcept; + void set_inward_binding(BasePort* port) noexcept { + if (port != nullptr) { + std::cout << port->fqn() << "(" << port << ")" << " --> " << this->fqn() << "(" << this << ")" << std::endl; + } + + inward_binding_ = port; + } void add_outward_binding(BasePort* port) noexcept { outward_bindings_.insert(port); } virtual void instantiate_connection_to(const ConnectionProperties& properties, @@ -107,6 +116,12 @@ public: friend class Scheduler; }; + +inline auto operator==(const BasePort& a, const BasePort& b) -> bool { + bool equal = ((const ReactorElement&)a) == ((const ReactorElement&)b); + return equal; +} + template class Port : public BasePort { private: ImmutableValuePtr value_ptr_{nullptr}; @@ -173,7 +188,11 @@ public: Input(const std::string& name, Reactor* container) : Port(name, PortType::Input, container) {} - Input(Input&&) noexcept = default; + Input(Input&&) = default; + + ~Input() { + std::cout << "Input port gets deallocated:" << this->fqn() << std::endl; + } }; template class Output : public Port { // NOLINT(cppcoreguidelines-special-member-functions) @@ -182,6 +201,10 @@ public: : Port(name, PortType::Output, container) {} Output(Output&&) noexcept = default; + + ~Output() { + std::cout << "Output port gets deallocated: " << this->fqn() << std::endl; + } }; } // namespace reactor diff --git a/include/reactor-cpp/reaction.hh b/include/reactor-cpp/reaction.hh index c90bd017..3e34c6cb 100644 --- a/include/reactor-cpp/reaction.hh +++ b/include/reactor-cpp/reaction.hh @@ -26,9 +26,9 @@ private: std::set antidependencies_; std::set dependencies_; - const int priority_; + const int priority_ = -1; const bool mutation_; - unsigned int index_{}; + unsigned int index_ = -1; std::function body_{nullptr}; @@ -38,7 +38,7 @@ private: void set_deadline_impl(Duration deadline, const std::function& handler); public: - Reaction(const std::string& name, int priority, bool mutation, Reactor* container, std::function body); + Reaction(const std::string& name, int priority, Reactor* container, std::function body); ~Reaction() override = default; diff --git a/include/reactor-cpp/reactor-cpp.hh b/include/reactor-cpp/reactor-cpp.hh index e4fc89db..a4367c80 100644 --- a/include/reactor-cpp/reactor-cpp.hh +++ b/include/reactor-cpp/reactor-cpp.hh @@ -21,6 +21,6 @@ #include "reaction.hh" #include "reactor.hh" #include "time.hh" -#include "scops.hh" +#include "scopes.hh" #endif // REACTOR_CPP_REACTOR_CPP_HH diff --git a/include/reactor-cpp/reactor.hh b/include/reactor-cpp/reactor.hh index 02b698dd..11e861ac 100644 --- a/include/reactor-cpp/reactor.hh +++ b/include/reactor-cpp/reactor.hh @@ -14,7 +14,6 @@ #include #include "action.hh" -#include "environment.hh" #include "logical_time.hh" #include "reactor_element.hh" @@ -23,10 +22,10 @@ class Reactor : public ReactorElement { // NOLINT(cppcoreguidelines-special-memb private: std::set actions_{}; - std::set inputs_{}; + std::vector inputs_{}; std::set outputs_{}; std::set reactions_{}; - std::set reactors_{}; + std::vector reactors_{}; std::set> connections_{}; void register_action(BaseAction* action); @@ -38,6 +37,7 @@ private: public: Reactor(const std::string& name, Reactor* container); Reactor(const std::string& name, Environment* environment); + Reactor() = delete; ~Reactor() override = default; void register_connection(std::unique_ptr&& connection); @@ -60,6 +60,9 @@ public: [[nodiscard]] auto get_elapsed_logical_time() const noexcept -> Duration; [[nodiscard]] auto get_elapsed_physical_time() const noexcept -> Duration; + void remove_inputs(BasePort* base_port); + void remove_child_reactor(const Reactor* base_reactor); + friend ReactorElement; }; diff --git a/include/reactor-cpp/reactor_element.hh b/include/reactor-cpp/reactor_element.hh index d78bfeff..70965959 100644 --- a/include/reactor-cpp/reactor_element.hh +++ b/include/reactor-cpp/reactor_element.hh @@ -12,7 +12,6 @@ #include #include -#include #include #include @@ -52,6 +51,11 @@ public: virtual void startup() = 0; virtual void shutdown() = 0; + + auto operator==(const ReactorElement& other) const -> bool { + //std::cout << other.name() << "==" << name_ << std::endl; + return name_ == other.name(); // && container_ == other.container() && environment_ == other.environment(); // && fqn_ == other.fqn() + } }; } // namespace reactor diff --git a/include/reactor-cpp/scops.hh b/include/reactor-cpp/scopes.hh similarity index 81% rename from include/reactor-cpp/scops.hh rename to include/reactor-cpp/scopes.hh index 430f8d8a..9f4da694 100644 --- a/include/reactor-cpp/scops.hh +++ b/include/reactor-cpp/scopes.hh @@ -10,17 +10,18 @@ #define REACTOR_CPP_SCOPS_HH #include "transaction.hh" -#include "time.hh" +#include "logical_time.hh" +#include "reactor.hh" +#include "environment.hh" namespace reactor { -class Reactor; class Scope { private: - reactor::Reactor* reactor; + Reactor* reactor; public: - Scope(reactor::Reactor* reactor) + Scope(Reactor* reactor) : reactor(reactor) {} auto get_physical_time() const -> reactor::TimePoint { return reactor->get_physical_time(); } @@ -33,14 +34,13 @@ public: void request_stop() const { return environment()->sync_shutdown(); } }; -template class MutableScope : public Scope { public: - HostReactor* self_ = nullptr; - Environment* env_ = nullptr; Transaction transaction_; + Reactor* reactor_; + Environment* env_ = nullptr; - explicit MutableScope(reactor::Reactor* reactor) : Scope(reactor), self_(reactor), env_(reactor->environment()) {} + explicit MutableScope(Reactor* reactor) : Scope(reactor), transaction_(reactor), reactor_(reactor), env_(reactor->environment()) {} ~MutableScope() = default; void commit_transaction(); diff --git a/include/reactor-cpp/transaction.hh b/include/reactor-cpp/transaction.hh index 9da4e6a3..8316bd8c 100644 --- a/include/reactor-cpp/transaction.hh +++ b/include/reactor-cpp/transaction.hh @@ -11,45 +11,24 @@ #include -#include "multiport.hh" +#include "mutations.hh" +//#include "reactor.hh" namespace reactor { class Reactor; class Environment; -enum MutationResult { - Success = 0, - NotMatchingBankSize = 1, -}; - -class Mutation { -public: - virtual ~Mutation() = default; - virtual auto run() -> MutationResult = 0 ; - virtual auto rollback() -> MutationResult = 0; -}; - -template -class MutationChangeMultiportSize : public Mutation { -private: - Multiport* multiport_ = nullptr; - std::size_t desired_size_ = 0; - std::size_t size_before_application_ = 0; -public: - MutationChangeMultiportSize(Multiport* multiport, std::size_t size); - ~MutationChangeMultiportSize() override = default; - - auto run() -> MutationResult override; - auto rollback() -> MutationResult override; -}; class Transaction { private: - Reactor* parent = nullptr; - Environment* environment = nullptr; + Reactor* parent_ = nullptr; + Environment* environment_ = nullptr; std::vector mutations_{}; public: + explicit Transaction(Reactor* parent); + ~Transaction() = default; + void push_back(Mutation* mutation); auto execute() -> MutationResult; }; diff --git a/lib/CMakeLists.txt b/lib/CMakeLists.txt index 75ecf535..2ade6076 100644 --- a/lib/CMakeLists.txt +++ b/lib/CMakeLists.txt @@ -7,15 +7,18 @@ set(SOURCE_FILES reaction.cc reactor.cc scheduler.cc - scops.cc + scopes.cc time.cc transaction.cc multiport.cc reactor_element.cc + mutation/multiport.cc + mutation/bank.cc + mutation/connection.cc ) if(REACTOR_CPP_TRACE) - set(SOURCE_FILES ${SOURCE_FILES} trace.cc ) + set(SOURCE_FILES ${SOURCE_FILES} trace.cc) endif() if (DEFINED LF_REACTOR_CPP_SUFFIX) @@ -24,7 +27,7 @@ else() set(REACTOR_CPP_INCLUDE "include") endif() -add_library(${LIB_TARGET} SHARED ${SOURCE_FILES}) +add_library(${LIB_TARGET} STATIC ${SOURCE_FILES}) target_include_directories(${LIB_TARGET} PUBLIC "$" "$" diff --git a/lib/environment.cc b/lib/environment.cc index 52c0b6bf..b517146b 100644 --- a/lib/environment.cc +++ b/lib/environment.cc @@ -47,7 +47,7 @@ Environment::Environment(const std::string& name, Environment* containing_enviro void Environment::register_reactor(Reactor* reactor) { reactor_assert(reactor != nullptr); - validate(this->phase() == Phase::Construction, "Reactors may only be registered during construction phase!"); + validate(this->phase() == Phase::Construction || this->phase() == Phase::Mutation, "Reactors may only be registered during construction phase!"); validate(reactor->is_top_level(), "The environment may only contain top level reactors!"); [[maybe_unused]] bool result = top_level_reactors_.insert(reactor).second; reactor_assert(result); @@ -157,14 +157,23 @@ void Environment::build_dependency_graph(Reactor* reactor) { validate(result.second, "priorities must be unique for all reactions_ of the same reactor"); } + dependencies_.clear(); //TODO: fix + // connect all reactions_ this reaction depends on for (auto* reaction : reactor->reactions()) { - for (auto* dependency : reaction->dependencies()) { - auto* source = dependency; - while (source->has_inward_binding()) { - source = source->inward_binding(); + std::set dependencies = reaction->dependencies(); + for (auto* dependency : dependencies) { + if (dependency <= (BasePort*)0x100) { + std::cout << "FUCK" << std::endl; + } + while (dependency->has_inward_binding()) { + if (dependency <= (BasePort*)0x100) { + std::cout << "FUCK" << std::endl; + } + dependency = dependency->inward_binding(); } - for (auto* antidependency : source->anti_dependencies()) { + std::cout << "anti deps of: " << dependency->fqn() << "(" << dependency << ")" << std::endl; + for (auto* antidependency : dependency->anti_dependencies()) { dependencies_.emplace_back(reaction, antidependency); } } diff --git a/lib/logical_time.cc b/lib/logical_time.cc index c17ca2f4..56bd723e 100644 --- a/lib/logical_time.cc +++ b/lib/logical_time.cc @@ -45,7 +45,8 @@ auto Tag::subtract(Duration offset) const noexcept -> Tag { auto Tag::decrement() const noexcept -> Tag { if (micro_step_ == 0) { - return {time_point_ - Duration{1}, std::numeric_limits::max()}; + //FIXME: return {time_point_ - Duration{1}, std::numeric_limits::max()}; + return {time_point_ - Duration{1}, 0}; } return {time_point_, micro_step_ - 1}; } diff --git a/lib/mutation/bank.cc b/lib/mutation/bank.cc new file mode 100644 index 00000000..098c0de5 --- /dev/null +++ b/lib/mutation/bank.cc @@ -0,0 +1,49 @@ +// +// Created by tanneberger on 11/11/24. +// + +#include "reactor-cpp/mutations/bank.hh" +#include "reactor-cpp/action.hh" + +template +reactor::MutationChangeBankSize::MutationChangeBankSize(std::vector* bank, Reactor* reactor, std::size_t size, std::function create_lambda) + : bank_(bank), reactor_(reactor), desired_size_(size), create_lambda_(create_lambda){ +} + +template +void reactor::MutationChangeBankSize::change_size(std::size_t new_size) { + bank_->reserve(new_size); + auto current_size = bank_->size(); + std::cout << "scaling from: " << current_size << " to " << new_size << std::endl; + + if (current_size >= new_size) { + // downscale + + for (auto i = 0; i < current_size - new_size; i++) { + //TODO: consider saving the ports here here + Reactor* last = (*bank_->end()).get(); + reactor_->environment()->remove_top_level_reactor(last); + bank_->pop_back(); + } + } else { + // upscale + + for (auto i = 0; i < new_size - current_size; i++) { + bank_->push_back(create_lambda_(reactor_, current_size + i)); + (*bank_)[bank_->size() - 1]->assemble(); + } + std::cout << "created new reactors" << std::endl; + } +} +template +auto reactor::MutationChangeBankSize::run() -> MutationResult { + size_before_application_ = bank_->size(); + change_size(desired_size_); + return Success; +} + +template +auto reactor::MutationChangeBankSize::rollback() -> MutationResult { + change_size(size_before_application_); + return Success; +} diff --git a/lib/mutation/connection.cc b/lib/mutation/connection.cc new file mode 100644 index 00000000..38ceeb27 --- /dev/null +++ b/lib/mutation/connection.cc @@ -0,0 +1,35 @@ +// +// Created by tanneberger on 11/20/24. +// + +#include "reactor-cpp/mutations/connection.hh" +#include "reactor-cpp/reactor.hh" + +template +reactor::MutationAddConnection::MutationAddConnection(A* source, B* sink, Reactor* reactor) : source_(source), sink_(sink), reactor_(reactor) { + +} + + +template auto reactor::MutationAddConnection::run() -> MutationResult { + reactor_->environment()->draw_connection(source_, sink_, ConnectionProperties{}); + sink_->set_inward_binding(source_); + source_->add_outward_binding(sink_); + std::cout << "from: " << source_->fqn() << "(" << source_ << ")" + << " --> to: " << sink_->fqn() << "(" << sink_ << ")" << std::endl; + + for (const auto* reactor : reactor_->environment()->top_level_reactors()) { + reactor_->environment()->build_dependency_graph((Reactor*)reactor); + } + + reactor_->environment()->calculate_indexes(); + return Success; +} + +template auto reactor::MutationAddConnection::rollback() -> MutationResult { + reactor_->environment()->remove_connection(source_, sink_); + + return Success; +} + + diff --git a/lib/mutation/multiport.cc b/lib/mutation/multiport.cc new file mode 100644 index 00000000..ed950299 --- /dev/null +++ b/lib/mutation/multiport.cc @@ -0,0 +1,54 @@ +// +// Created by tanneberger on 11/11/24. +// + +#include "reactor-cpp/mutations/multiport.hh" +#include "reactor-cpp/reaction.hh" + +template +reactor::MutationChangeOutputMultiportSize::MutationChangeOutputMultiportSize(ModifableMultiport>* multiport, Reactor* reactor, std::set& anti_dependencies, std::size_t size) + : multiport_(multiport), reactor_(reactor), desired_size_(size), anti_dependencies_(anti_dependencies) { } + +template +void reactor::MutationChangeOutputMultiportSize::change_size(std::size_t new_size) { + multiport_->reserve(new_size); + auto current_size = multiport_->size(); + std::cout << "scaling from: " << current_size << " to " << new_size << std::endl; + + if (current_size >= new_size) { + // downscale + + for (auto i = 0; i < current_size - new_size; i++) { + //TODO: consider saving the ports here here + + std::string port_name_ = multiport_->name() + "_" + std::to_string(current_size + i - 1); + multiport_->pop_back(); + auto base_port = Output{port_name_, reactor_}; + reactor_->remove_inputs(&base_port); + } + } else { + // upscale + + for (auto i = 0; i < new_size - current_size; i++) { + std::string port_name_ = multiport_->name() + "_" + std::to_string(current_size + i); + multiport_->emplace_back(port_name_, reactor_); + BasePort* port = &(multiport_->operator[](current_size + i)); + for (auto* anti_dep : anti_dependencies_) { + anti_dep->declare_antidependency(port); + } + } + + } +} +template +auto reactor::MutationChangeOutputMultiportSize::run() -> MutationResult { + size_before_application_ = multiport_->size(); + change_size(desired_size_); + return Success; +} + +template +auto reactor::MutationChangeOutputMultiportSize::rollback() -> MutationResult { + change_size(size_before_application_); + return Success; +} diff --git a/lib/port.cc b/lib/port.cc index 7260c661..412e4cab 100644 --- a/lib/port.cc +++ b/lib/port.cc @@ -20,7 +20,7 @@ void BasePort::register_dependency(Reaction* reaction, bool is_trigger) noexcept reactor_assert(reaction != nullptr); reactor_assert(this->environment() == reaction->environment()); validate(!this->has_outward_bindings(), "Dependencies may no be declared on ports with an outward binding!"); - assert_phase(this, Phase::Assembly); + //assert_phase(this, Phase::Assembly); if (this->is_input()) { validate(this->container() == reaction->container(), "Dependent input ports must belong to the same reactor as the " @@ -42,7 +42,7 @@ void BasePort::register_antidependency(Reaction* reaction) noexcept { reactor_assert(reaction != nullptr); reactor_assert(this->environment() == reaction->environment()); validate(!this->has_inward_binding(), "Antidependencies may no be declared on ports with an inward binding!"); - assert_phase(this, Phase::Assembly); + //TODO: assert_phase(this, Phase::Assembly); if (this->is_output()) { validate(this->container() == reaction->container(), diff --git a/lib/reaction.cc b/lib/reaction.cc index 4e895da5..22ce0f21 100644 --- a/lib/reaction.cc +++ b/lib/reaction.cc @@ -17,10 +17,10 @@ namespace reactor { -Reaction::Reaction(const std::string& name, int priority, bool mutation, Reactor* container, std::function body) +Reaction::Reaction(const std::string& name, int priority, Reactor* container, std::function body) : ReactorElement(name, ReactorElement::Type::Reaction, container) , priority_(priority) - , mutation_(mutation) + , mutation_(false) , body_(std::move(std::move(body))) { reactor_assert(priority != 0); @@ -53,7 +53,7 @@ void Reaction::declare_schedulable_action(BaseAction* action) { void Reaction::declare_trigger(BasePort* port) { reactor_assert(port != nullptr); reactor_assert(this->environment() == port->environment()); - assert_phase(this, Phase::Assembly); + //assert_phase(this, Phase::Assembly); if (port->is_input()) { validate(this->container() == port->container(), @@ -128,7 +128,7 @@ void Reaction::set_deadline_impl(Duration deadline, const std::functionenvironment()->phase() == Phase::Assembly, "Reaction indexes may only be set during assembly phase!"); + validate(this->environment()->phase() == Phase::Assembly || this->environment()->phase() == Phase::Mutation, "Reaction indexes may only be set during assembly phase!"); this->index_ = index; } diff --git a/lib/reactor.cc b/lib/reactor.cc index f42488b0..eb9e5d26 100644 --- a/lib/reactor.cc +++ b/lib/reactor.cc @@ -18,7 +18,9 @@ namespace reactor { Reactor::Reactor(const std::string& name, Reactor* container) - : ReactorElement(name, ReactorElement::Type::Reactor, container) {} + : ReactorElement(name, ReactorElement::Type::Reactor, container) { + container->register_reactor(this); +} Reactor::Reactor(const std::string& name, Environment* environment) : ReactorElement(name, ReactorElement::Type::Reactor, environment) { environment->register_reactor(this); @@ -36,26 +38,28 @@ void Reactor::register_action([[maybe_unused]] BaseAction* action) { void Reactor::register_input(BasePort* port) { reactor_assert(port != nullptr); - reactor::validate(this->environment()->phase() == Phase::Construction, + reactor::validate(this->environment()->phase() == Phase::Construction || this->environment()->phase() == Phase::Mutation, "Ports can only be registered during construction phase!"); - [[maybe_unused]] bool result = inputs_.insert(port).second; - reactor_assert(result); + //[[maybe_unused]] bool result = inputs_.insert(port).second; + inputs_.push_back(port); + //reactor_assert(result); Statistics::increment_ports(); } void Reactor::register_output(BasePort* port) { reactor_assert(port != nullptr); - reactor::validate(this->environment()->phase() == Phase::Construction, + reactor::validate(this->environment()->phase() == Phase::Construction || this->environment()->phase() == Phase::Mutation, "Ports can only be registered during construction phase!"); - [[maybe_unused]] bool result = inputs_.insert(port).second; - reactor_assert(result); + //[[maybe_unused]] bool result = inputs_.insert(port).second; + //std::cout << "reactor port count:" << inputs_.size() << std::endl; + //TODO: reactor_assert(result); Statistics::increment_ports(); } void Reactor::register_reaction([[maybe_unused]] Reaction* reaction) { reactor_assert(reaction != nullptr); - validate(this->environment()->phase() == Phase::Construction, + validate(this->environment()->phase() == Phase::Construction || this->environment()->phase() == Phase::Mutation, "Reactions can only be registered during construction phase!"); [[maybe_unused]] bool result = reactions_.insert(reaction).second; reactor_assert(result); @@ -64,10 +68,16 @@ void Reactor::register_reaction([[maybe_unused]] Reaction* reaction) { void Reactor::register_reactor([[maybe_unused]] Reactor* reactor) { reactor_assert(reactor != nullptr); - validate(this->environment()->phase() == Phase::Construction, + validate(this->environment()->phase() == Phase::Construction || this->environment()->phase() == Phase::Mutation, "Reactions can only be registered during construction phase!"); - [[maybe_unused]] bool result = reactors_.insert(reactor).second; - reactor_assert(result); + if (std::find(std::begin(reactors_), std::end(reactors_), reactor) == std::end(reactors_)) { + reactors_.push_back(reactor); + } else { + std::cout << "duplicate insertion!" << std::endl; + } + + //[[maybe_unused]] bool result = reactors_.insert(reactor).second; + //reactor_assert(result); Statistics::increment_reactor_instances(); } @@ -141,4 +151,22 @@ auto Reactor::get_elapsed_physical_time() const noexcept -> Duration { return get_physical_time() - environment()->start_tag().time_point(); } +void Reactor::remove_inputs(BasePort* base_port) { + auto index = std::find_if(std::begin(inputs_), std::end(inputs_), [base_port](const BasePort* other) { return *other == *base_port;}); + + if (index != std::end(inputs_)) { + inputs_.erase(index); + } + }; + +void Reactor::remove_child_reactor(const Reactor* base_reactor) { + auto index = std::find_if(std::begin(reactors_), std::end(reactors_), [base_reactor](const Reactor* other) { + return base_reactor == other; + }); + + if (index != std::end(reactors_)) { + reactors_.erase(index); + } +} + } // namespace reactor diff --git a/lib/reactor_element.cc b/lib/reactor_element.cc index 32db319f..51eae68d 100644 --- a/lib/reactor_element.cc +++ b/lib/reactor_element.cc @@ -24,7 +24,7 @@ ReactorElement::ReactorElement(const std::string& name, ReactorElement::Type typ reactor_assert(container != nullptr); this->environment_ = container->environment(); reactor_assert(this->environment_ != nullptr); - validate(this->environment_->phase() == Phase::Construction || + validate(this->environment_->phase() == Phase::Construction ||this->environment_->phase() == Phase::Mutation || (type == Type::Action && this->environment_->phase() == Phase::Assembly), "Reactor elements can only be created during construction phase!"); // We need a reinterpret_cast here as the derived class is not yet created @@ -71,7 +71,7 @@ ReactorElement::ReactorElement(const std::string& name, ReactorElement::Type typ reactor_assert(environment != nullptr); validate(type == Type::Reactor || type == Type::Action, "Only reactors and actions can be owned by the environment!"); - validate(this->environment_->phase() == Phase::Construction || + validate(this->environment_->phase() == Phase::Construction || this->environment_->phase() == Phase::Mutation || (type == Type::Action && this->environment_->phase() == Phase::Assembly), "Reactor elements can only be created during construction phase!"); diff --git a/lib/scopes.cc b/lib/scopes.cc new file mode 100644 index 00000000..de65e5dd --- /dev/null +++ b/lib/scopes.cc @@ -0,0 +1,11 @@ + + +#include "reactor-cpp/scopes.hh" + +void reactor::MutableScope::add_to_transaction(Mutation* mutation) { + transaction_.push_back(mutation); +} + +void reactor::MutableScope::commit_transaction() { + transaction_.execute(); +} \ No newline at end of file diff --git a/lib/scops.cc b/lib/scops.cc deleted file mode 100644 index d52f3ce0..00000000 --- a/lib/scops.cc +++ /dev/null @@ -1,13 +0,0 @@ - - -#include "reactor-cpp/scops.hh" - -template -void reactor::MutableScope::begin_transaction() { - transaction_.reset(); -} - -template -void reactor::MutableScope::end_transaction() { - transaction_.execute(); -} \ No newline at end of file diff --git a/lib/transaction.cc b/lib/transaction.cc index 17aba182..2576c222 100644 --- a/lib/transaction.cc +++ b/lib/transaction.cc @@ -1,33 +1,24 @@ #include "reactor-cpp/transaction.hh" +#include "reactor-cpp/environment.hh" +#include "reactor-cpp/reactor.hh" -template -reactor::MutationChangeMultiportSize::MutationChangeMultiportSize(Multiport* multiport, std::size_t size) - : multiport_(multiport), desired_size_(size){ -} - -template -auto reactor::MutationChangeMultiportSize::run() -> MutationResult { - multiport_->ports_.resize(desired_size_); - - return Success; -} - -template -auto reactor::MutationChangeMultiportSize::rollback() -> MutationResult { - return Success; -} + reactor::Transaction::Transaction(Reactor* parent) : parent_(parent), environment_(parent->environment()) { } auto reactor::Transaction::execute() -> MutationResult { - for (auto *mutation : mutations_) { - mutation->run(); - } - return Success; + this->environment_->start_mutation(); + for (auto *mutation : mutations_) { + mutation->run(); + } + + this->environment_->stop_mutation(); + mutations_.clear(); + return Success; } void reactor::Transaction::push_back(reactor::Mutation* mutation) { - mutations_.push_back(mutation); + mutations_.push_back(mutation); } \ No newline at end of file From e088e960441d9d6e5f924eb2bee775ede534742c Mon Sep 17 00:00:00 2001 From: Omer Majeed Date: Thu, 12 Dec 2024 14:46:50 +0500 Subject: [PATCH 4/8] mutation fixes Signed-off-by: tanneberger --- examples/multiport_mutation/consumer.hh | 4 ++-- examples/multiport_mutation/load_balancer.hh | 7 +++--- examples/multiport_mutation/main.cc | 10 ++++---- examples/multiport_mutation/producer.hh | 5 ++-- include/reactor-cpp/environment.hh | 1 + include/reactor-cpp/graph.hh | 9 +++++++- include/reactor-cpp/reaction.hh | 2 +- include/reactor-cpp/scopes.hh | 2 +- include/reactor-cpp/transaction.hh | 3 +-- lib/environment.cc | 24 ++++++++------------ lib/mutation/bank.cc | 4 ++-- lib/mutation/connection.cc | 6 ----- lib/mutation/multiport.cc | 22 +++++++++++++----- lib/reaction.cc | 1 - lib/reactor.cc | 1 + lib/scopes.cc | 5 ++-- lib/transaction.cc | 13 +++++++++-- 17 files changed, 69 insertions(+), 50 deletions(-) diff --git a/examples/multiport_mutation/consumer.hh b/examples/multiport_mutation/consumer.hh index 2265b62b..b2ac7324 100644 --- a/examples/multiport_mutation/consumer.hh +++ b/examples/multiport_mutation/consumer.hh @@ -18,8 +18,8 @@ private: [[maybe_unused]] const Inner& __lf_inner = *this; - void reaction_1([[maybe_unused]] const Input& scale) { - std::cout << "consumer: " << index_ << " received value!" << std::endl; + void reaction_1([[maybe_unused]] const Input& in) { + std::cout << "consumer: " << index_ << " received value:" << *in.get() << std::endl; } friend Consumer; diff --git a/examples/multiport_mutation/load_balancer.hh b/examples/multiport_mutation/load_balancer.hh index d701e33e..085f35d8 100644 --- a/examples/multiport_mutation/load_balancer.hh +++ b/examples/multiport_mutation/load_balancer.hh @@ -24,9 +24,9 @@ private: if (rand() % 30 == 0) { scale_action.schedule(rand() % 20 + 1); } - - std::cout << "multiport size: " << outbound.size() << std::endl; - outbound[rand() % outbound.size()].set(inbound.get()); + unsigned sel = rand() % outbound.size(); + std::cout << "Sending out to:" << sel << std::endl; + outbound[sel].set(inbound.get()); } void reaction_2(ModifableMultiport>&outbound, [[maybe_unused]] const LogicalAction& scale, Output& scale_bank) { @@ -74,6 +74,7 @@ public: } process.declare_trigger(&inbound); scale.declare_trigger(&scale_action); + scale.declare_antidependency(&scale_bank); } }; diff --git a/examples/multiport_mutation/main.cc b/examples/multiport_mutation/main.cc index 1f38f736..7d85bf75 100644 --- a/examples/multiport_mutation/main.cc +++ b/examples/multiport_mutation/main.cc @@ -47,12 +47,12 @@ class Inner: public MutableScope { } } else { std::cout << "load_balancer size:" << load_balancer.size() << " bank size: " << reactor_bank.size() << std::endl; - for (auto i = 0; i < new_size - old_size; i++) { - std::cout << "add connection: " << i + old_size << std::endl; - MutationAddConnection, Input> add_conn{&load_balancer[i + old_size], &reactor_bank[i + old_size].get()->in, reactor_}; + for (auto i = 0; i < new_size; i++) { + std::cout << "add connection: " << i << std::endl; + MutationAddConnection, Input> add_conn{&load_balancer[i], &reactor_bank[i].get()->in, reactor_}; add_to_transaction(&add_conn); - commit_transaction(); } + commit_transaction(true); } std::cout << "new bank size:" << reactor_bank.size() << std::endl; @@ -90,7 +90,7 @@ class Inner: public MutableScope { auto main() -> int { //srand(time(nullptr)); - Environment env{4}; + Environment env{4, true}; auto deployment = std::make_unique("c1", &env); env.optimize(); env.assemble(); diff --git a/examples/multiport_mutation/producer.hh b/examples/multiport_mutation/producer.hh index 9894412d..7a998cbb 100644 --- a/examples/multiport_mutation/producer.hh +++ b/examples/multiport_mutation/producer.hh @@ -16,10 +16,11 @@ private: Reaction r_timer{"r_timer", 1, this, [this]() { __lf_inner.reaction_1(this->value);}}; class Inner: public Scope { + unsigned itr = 0; [[maybe_unused]] const Inner& __lf_inner = *this; void reaction_1([[maybe_unused]] Output& out) { - std::cout << "producing value" << std::endl; - out.set(42); + std::cout << "producing value:" << itr << std::endl; + out.set(itr++); } explicit Inner(Reactor* reactor) : Scope(reactor) {} diff --git a/include/reactor-cpp/environment.hh b/include/reactor-cpp/environment.hh index 82e28559..60e3db93 100644 --- a/include/reactor-cpp/environment.hh +++ b/include/reactor-cpp/environment.hh @@ -84,6 +84,7 @@ public: //TODO: fix visebility void calculate_indexes(); void build_dependency_graph(Reactor* reactor); + void clear_dependency_graph(); explicit Environment(unsigned int num_workers, bool fast_fwd_execution = default_fast_fwd_execution, diff --git a/include/reactor-cpp/graph.hh b/include/reactor-cpp/graph.hh index 8544306f..ac9b8e41 100644 --- a/include/reactor-cpp/graph.hh +++ b/include/reactor-cpp/graph.hh @@ -54,7 +54,14 @@ public: std::vector> edges{std::make_pair(properties, destination)}; graph_[source] = edges; } else { - graph_[source].emplace_back(properties, destination); + auto &edges = graph_[source]; + auto duplicate = std::find_if(edges.begin(), edges.end(), + [&](const std::pair& edge) { + return edge.first == properties && edge.second == destination; + }); + if (duplicate == edges.end()) { + graph_[source].emplace_back(properties, destination); + } } } diff --git a/include/reactor-cpp/reaction.hh b/include/reactor-cpp/reaction.hh index 3e34c6cb..80246a28 100644 --- a/include/reactor-cpp/reaction.hh +++ b/include/reactor-cpp/reaction.hh @@ -27,7 +27,6 @@ private: std::set dependencies_; const int priority_ = -1; - const bool mutation_; unsigned int index_ = -1; std::function body_{nullptr}; @@ -53,6 +52,7 @@ public: [[nodiscard]] auto port_triggers() const noexcept -> const auto& { return port_trigger_; } [[maybe_unused]] [[nodiscard]] auto antidependencies() const noexcept -> const auto& { return antidependencies_; } + [[maybe_unused]] void clear_antidependencies() noexcept { antidependencies_.clear(); } [[nodiscard]] auto dependencies() const noexcept -> const auto& { return dependencies_; } diff --git a/include/reactor-cpp/scopes.hh b/include/reactor-cpp/scopes.hh index 9f4da694..ae38c2fe 100644 --- a/include/reactor-cpp/scopes.hh +++ b/include/reactor-cpp/scopes.hh @@ -43,7 +43,7 @@ public: explicit MutableScope(Reactor* reactor) : Scope(reactor), transaction_(reactor), reactor_(reactor), env_(reactor->environment()) {} ~MutableScope() = default; - void commit_transaction(); + void commit_transaction(bool recalculate = false); void add_to_transaction(Mutation* mutation); }; diff --git a/include/reactor-cpp/transaction.hh b/include/reactor-cpp/transaction.hh index 8316bd8c..dfcb2f52 100644 --- a/include/reactor-cpp/transaction.hh +++ b/include/reactor-cpp/transaction.hh @@ -21,7 +21,6 @@ class Environment; class Transaction { private: - Reactor* parent_ = nullptr; Environment* environment_ = nullptr; std::vector mutations_{}; @@ -30,7 +29,7 @@ public: ~Transaction() = default; void push_back(Mutation* mutation); - auto execute() -> MutationResult; + auto execute(bool recalculate = false) -> MutationResult; }; } #endif // REACTOR_CPP_TRANSACTION_HH diff --git a/lib/environment.cc b/lib/environment.cc index b517146b..be84af16 100644 --- a/lib/environment.cc +++ b/lib/environment.cc @@ -144,6 +144,11 @@ void Environment::assemble() { // NOLINT(readability-function-cognitive-complexi } } +void Environment::clear_dependency_graph() { + dependencies_.clear(); + reactions_.clear(); +} + void Environment::build_dependency_graph(Reactor* reactor) { // obtain dependencies from each contained reactor for (auto* sub_reactor : reactor->reactors()) { @@ -157,23 +162,14 @@ void Environment::build_dependency_graph(Reactor* reactor) { validate(result.second, "priorities must be unique for all reactions_ of the same reactor"); } - dependencies_.clear(); //TODO: fix - // connect all reactions_ this reaction depends on for (auto* reaction : reactor->reactions()) { - std::set dependencies = reaction->dependencies(); - for (auto* dependency : dependencies) { - if (dependency <= (BasePort*)0x100) { - std::cout << "FUCK" << std::endl; - } - while (dependency->has_inward_binding()) { - if (dependency <= (BasePort*)0x100) { - std::cout << "FUCK" << std::endl; - } - dependency = dependency->inward_binding(); + for (auto* dependency : reaction->dependencies()) { + auto* source = dependency; + while (source->has_inward_binding()) { + source = source->inward_binding(); } - std::cout << "anti deps of: " << dependency->fqn() << "(" << dependency << ")" << std::endl; - for (auto* antidependency : dependency->anti_dependencies()) { + for (auto* antidependency : source->anti_dependencies()) { dependencies_.emplace_back(reaction, antidependency); } } diff --git a/lib/mutation/bank.cc b/lib/mutation/bank.cc index 098c0de5..4d8ee3b8 100644 --- a/lib/mutation/bank.cc +++ b/lib/mutation/bank.cc @@ -21,9 +21,9 @@ void reactor::MutationChangeBankSize::change_size(std::size_t new_size) { for (auto i = 0; i < current_size - new_size; i++) { //TODO: consider saving the ports here here - Reactor* last = (*bank_->end()).get(); - reactor_->environment()->remove_top_level_reactor(last); + std::unique_ptr lastElement = std::move(bank_->back()); bank_->pop_back(); + reactor_->environment()->remove_top_level_reactor(lastElement.get()); } } else { // upscale diff --git a/lib/mutation/connection.cc b/lib/mutation/connection.cc index 38ceeb27..260e500a 100644 --- a/lib/mutation/connection.cc +++ b/lib/mutation/connection.cc @@ -17,12 +17,6 @@ template auto reactor::MutationAddConnection::run() -> source_->add_outward_binding(sink_); std::cout << "from: " << source_->fqn() << "(" << source_ << ")" << " --> to: " << sink_->fqn() << "(" << sink_ << ")" << std::endl; - - for (const auto* reactor : reactor_->environment()->top_level_reactors()) { - reactor_->environment()->build_dependency_graph((Reactor*)reactor); - } - - reactor_->environment()->calculate_indexes(); return Success; } diff --git a/lib/mutation/multiport.cc b/lib/mutation/multiport.cc index ed950299..cf2887e3 100644 --- a/lib/mutation/multiport.cc +++ b/lib/mutation/multiport.cc @@ -11,7 +11,6 @@ reactor::MutationChangeOutputMultiportSize::MutationChangeOutputMultiportSize template void reactor::MutationChangeOutputMultiportSize::change_size(std::size_t new_size) { - multiport_->reserve(new_size); auto current_size = multiport_->size(); std::cout << "scaling from: " << current_size << " to " << new_size << std::endl; @@ -21,23 +20,34 @@ void reactor::MutationChangeOutputMultiportSize::change_size(std::size_t new_ for (auto i = 0; i < current_size - new_size; i++) { //TODO: consider saving the ports here here - std::string port_name_ = multiport_->name() + "_" + std::to_string(current_size + i - 1); + std::string port_name_ = multiport_->name() + "_" + std::to_string(current_size - i - 1); multiport_->pop_back(); auto base_port = Output{port_name_, reactor_}; reactor_->remove_inputs(&base_port); } + + for (auto* anti_dep : anti_dependencies_) { + anti_dep->clear_antidependencies(); + for (auto i = 0; i < new_size; i++) { + anti_dep->declare_antidependency(&multiport_->operator[](i)); + } + } } else { // upscale for (auto i = 0; i < new_size - current_size; i++) { std::string port_name_ = multiport_->name() + "_" + std::to_string(current_size + i); multiport_->emplace_back(port_name_, reactor_); - BasePort* port = &(multiport_->operator[](current_size + i)); - for (auto* anti_dep : anti_dependencies_) { - anti_dep->declare_antidependency(port); - } } + for (auto* anti_dep : anti_dependencies_) { + anti_dep->clear_antidependencies(); + for (auto i = 0; i < new_size; i++) { + anti_dep->declare_antidependency(&multiport_->operator[](i)); + } + } + + } } template diff --git a/lib/reaction.cc b/lib/reaction.cc index 22ce0f21..e160990b 100644 --- a/lib/reaction.cc +++ b/lib/reaction.cc @@ -20,7 +20,6 @@ namespace reactor { Reaction::Reaction(const std::string& name, int priority, Reactor* container, std::function body) : ReactorElement(name, ReactorElement::Type::Reaction, container) , priority_(priority) - , mutation_(false) , body_(std::move(std::move(body))) { reactor_assert(priority != 0); diff --git a/lib/reactor.cc b/lib/reactor.cc index eb9e5d26..76eadc25 100644 --- a/lib/reactor.cc +++ b/lib/reactor.cc @@ -47,6 +47,7 @@ void Reactor::register_input(BasePort* port) { } void Reactor::register_output(BasePort* port) { + (void)port; reactor_assert(port != nullptr); reactor::validate(this->environment()->phase() == Phase::Construction || this->environment()->phase() == Phase::Mutation, "Ports can only be registered during construction phase!"); diff --git a/lib/scopes.cc b/lib/scopes.cc index de65e5dd..49e714f3 100644 --- a/lib/scopes.cc +++ b/lib/scopes.cc @@ -6,6 +6,7 @@ void reactor::MutableScope::add_to_transaction(Mutation* mutation) { transaction_.push_back(mutation); } -void reactor::MutableScope::commit_transaction() { - transaction_.execute(); +void reactor::MutableScope::commit_transaction(bool recalculate) { + (void)recalculate; + transaction_.execute(recalculate); } \ No newline at end of file diff --git a/lib/transaction.cc b/lib/transaction.cc index 2576c222..07885f04 100644 --- a/lib/transaction.cc +++ b/lib/transaction.cc @@ -4,16 +4,25 @@ #include "reactor-cpp/environment.hh" #include "reactor-cpp/reactor.hh" - reactor::Transaction::Transaction(Reactor* parent) : parent_(parent), environment_(parent->environment()) { } + reactor::Transaction::Transaction(Reactor* parent) : environment_(parent->environment()) { } -auto reactor::Transaction::execute() -> MutationResult { +auto reactor::Transaction::execute(bool recalculate) -> MutationResult { this->environment_->start_mutation(); for (auto *mutation : mutations_) { mutation->run(); } + if (recalculate) { + this->environment_->clear_dependency_graph(); + for (const auto* reactor : this->environment_->top_level_reactors()) { + this->environment_->build_dependency_graph((Reactor*)reactor); + } + + this->environment_->calculate_indexes(); + } + this->environment_->stop_mutation(); mutations_.clear(); return Success; From 95c55bf2059c26214120160580b6e6f571af80c9 Mon Sep 17 00:00:00 2001 From: tanneberger Date: Fri, 13 Dec 2024 07:44:12 +0100 Subject: [PATCH 5/8] making it working --- examples/multiport_mutation/load_balancer.hh | 4 ++-- examples/multiport_mutation/main.cc | 9 ++++----- include/reactor-cpp/port.hh | 2 +- include/reactor-cpp/scopes.hh | 2 +- include/reactor-cpp/transaction.hh | 5 +++-- lib/mutation/connection.cc | 4 ++-- lib/mutation/multiport.cc | 8 ++++---- lib/reaction.cc | 2 +- lib/scopes.cc | 2 +- lib/transaction.cc | 7 ++++--- 10 files changed, 23 insertions(+), 22 deletions(-) diff --git a/examples/multiport_mutation/load_balancer.hh b/examples/multiport_mutation/load_balancer.hh index 085f35d8..8e744279 100644 --- a/examples/multiport_mutation/load_balancer.hh +++ b/examples/multiport_mutation/load_balancer.hh @@ -35,9 +35,9 @@ private: auto antideps = (outbound[0]).anti_dependencies(); - MutationChangeOutputMultiportSize change_size{temp, this->reactor_, antideps, new_size}; + auto change_size = std::make_shared>(temp, this->reactor_, antideps, new_size); - add_to_transaction(&change_size); + add_to_transaction(change_size); commit_transaction(); diff --git a/examples/multiport_mutation/main.cc b/examples/multiport_mutation/main.cc index 7d85bf75..3956b8e6 100644 --- a/examples/multiport_mutation/main.cc +++ b/examples/multiport_mutation/main.cc @@ -33,9 +33,9 @@ class Inner: public MutableScope { std::string __lf_inst_name = "consumer_" + std::to_string(index); return std::make_unique(__lf_inst_name, reactor->environment(), index); }; - MutationChangeBankSize change_size{&reactor_bank, this->reactor_, new_size, lambda}; + auto change_size = std::make_shared>>(&reactor_bank, this->reactor_, new_size, lambda); - add_to_transaction(&change_size); + add_to_transaction(change_size); // old topology commit_transaction(); @@ -48,9 +48,8 @@ class Inner: public MutableScope { } else { std::cout << "load_balancer size:" << load_balancer.size() << " bank size: " << reactor_bank.size() << std::endl; for (auto i = 0; i < new_size; i++) { - std::cout << "add connection: " << i << std::endl; - MutationAddConnection, Input> add_conn{&load_balancer[i], &reactor_bank[i].get()->in, reactor_}; - add_to_transaction(&add_conn); + auto add_conn = std::make_shared, Input>>(&load_balancer[i], &reactor_bank[i].get()->in, reactor_); + add_to_transaction(add_conn); } commit_transaction(true); } diff --git a/include/reactor-cpp/port.hh b/include/reactor-cpp/port.hh index a8e74e07..bcce4ea9 100644 --- a/include/reactor-cpp/port.hh +++ b/include/reactor-cpp/port.hh @@ -106,7 +106,7 @@ public: [[nodiscard]] auto triggers() const noexcept -> const auto& { return triggers_; } [[nodiscard]] auto dependencies() const noexcept -> const auto& { return dependencies_; } - [[nodiscard]] auto anti_dependencies() const noexcept -> const auto& { return anti_dependencies_; } + [[nodiscard]] auto anti_dependencies() noexcept -> auto& { return anti_dependencies_; } //TODO: make it const again [[nodiscard]] auto port_type() const noexcept -> PortType { return type_; } void register_set_callback(const PortCallback& callback); diff --git a/include/reactor-cpp/scopes.hh b/include/reactor-cpp/scopes.hh index ae38c2fe..f1f1352a 100644 --- a/include/reactor-cpp/scopes.hh +++ b/include/reactor-cpp/scopes.hh @@ -44,7 +44,7 @@ public: ~MutableScope() = default; void commit_transaction(bool recalculate = false); - void add_to_transaction(Mutation* mutation); + void add_to_transaction(const std::shared_ptr& mutation); }; diff --git a/include/reactor-cpp/transaction.hh b/include/reactor-cpp/transaction.hh index dfcb2f52..fb27ff19 100644 --- a/include/reactor-cpp/transaction.hh +++ b/include/reactor-cpp/transaction.hh @@ -10,6 +10,7 @@ #define REACTOR_CPP_TRANSACTION_HH #include +#include #include "mutations.hh" //#include "reactor.hh" @@ -22,13 +23,13 @@ class Environment; class Transaction { private: Environment* environment_ = nullptr; - std::vector mutations_{}; + std::vector> mutations_{}; public: explicit Transaction(Reactor* parent); ~Transaction() = default; - void push_back(Mutation* mutation); + void push_back(const std::shared_ptr& mutation); auto execute(bool recalculate = false) -> MutationResult; }; } diff --git a/lib/mutation/connection.cc b/lib/mutation/connection.cc index 260e500a..e66ebb83 100644 --- a/lib/mutation/connection.cc +++ b/lib/mutation/connection.cc @@ -15,8 +15,8 @@ template auto reactor::MutationAddConnection::run() -> reactor_->environment()->draw_connection(source_, sink_, ConnectionProperties{}); sink_->set_inward_binding(source_); source_->add_outward_binding(sink_); - std::cout << "from: " << source_->fqn() << "(" << source_ << ")" - << " --> to: " << sink_->fqn() << "(" << sink_ << ")" << std::endl; + //std::cout << "from: " << source_->fqn() << "(" << source_ << ")" + // << " --> to: " << sink_->fqn() << "(" << sink_ << ")" << std::endl; return Success; } diff --git a/lib/mutation/multiport.cc b/lib/mutation/multiport.cc index cf2887e3..279458c3 100644 --- a/lib/mutation/multiport.cc +++ b/lib/mutation/multiport.cc @@ -12,8 +12,6 @@ reactor::MutationChangeOutputMultiportSize::MutationChangeOutputMultiportSize template void reactor::MutationChangeOutputMultiportSize::change_size(std::size_t new_size) { auto current_size = multiport_->size(); - std::cout << "scaling from: " << current_size << " to " << new_size << std::endl; - if (current_size >= new_size) { // downscale @@ -29,6 +27,8 @@ void reactor::MutationChangeOutputMultiportSize::change_size(std::size_t new_ for (auto* anti_dep : anti_dependencies_) { anti_dep->clear_antidependencies(); for (auto i = 0; i < new_size; i++) { + + multiport_->operator[](i).anti_dependencies().clear(); anti_dep->declare_antidependency(&multiport_->operator[](i)); } } @@ -40,12 +40,12 @@ void reactor::MutationChangeOutputMultiportSize::change_size(std::size_t new_ multiport_->emplace_back(port_name_, reactor_); } - for (auto* anti_dep : anti_dependencies_) { + /*for (auto* anti_dep : anti_dependencies_) { anti_dep->clear_antidependencies(); for (auto i = 0; i < new_size; i++) { anti_dep->declare_antidependency(&multiport_->operator[](i)); } - } + }*/ } diff --git a/lib/reaction.cc b/lib/reaction.cc index e160990b..1647e68b 100644 --- a/lib/reaction.cc +++ b/lib/reaction.cc @@ -91,7 +91,7 @@ void Reaction::declare_dependency(BasePort* port) { void Reaction::declare_antidependency(BasePort* port) { reactor_assert(port != nullptr); reactor_assert(this->environment() == port->environment()); - assert_phase(this, Phase::Assembly); + //assert_phase(this, Phase::Assembly); if (port->is_output()) { validate(this->container() == port->container(), "Antidependent output ports must belong to the same reactor as " diff --git a/lib/scopes.cc b/lib/scopes.cc index 49e714f3..dee9ee79 100644 --- a/lib/scopes.cc +++ b/lib/scopes.cc @@ -2,7 +2,7 @@ #include "reactor-cpp/scopes.hh" -void reactor::MutableScope::add_to_transaction(Mutation* mutation) { +void reactor::MutableScope::add_to_transaction(const std::shared_ptr& mutation) { transaction_.push_back(mutation); } diff --git a/lib/transaction.cc b/lib/transaction.cc index 07885f04..2cf53855 100644 --- a/lib/transaction.cc +++ b/lib/transaction.cc @@ -10,7 +10,7 @@ auto reactor::Transaction::execute(bool recalculate) -> MutationResult { this->environment_->start_mutation(); - for (auto *mutation : mutations_) { + for (auto mutation : mutations_) { mutation->run(); } @@ -24,10 +24,11 @@ auto reactor::Transaction::execute(bool recalculate) -> MutationResult { } this->environment_->stop_mutation(); + mutations_.clear(); - return Success; + return Success; } -void reactor::Transaction::push_back(reactor::Mutation* mutation) { +void reactor::Transaction::push_back(const std::shared_ptr& mutation) { mutations_.push_back(mutation); } \ No newline at end of file From 9e1b6ed41186103895867535d75b123bc59f75ef Mon Sep 17 00:00:00 2001 From: tanneberger Date: Fri, 13 Dec 2024 20:41:00 +0100 Subject: [PATCH 6/8] clang-format --- Makefile | 52 +++++++++++++++++++++ include/reactor-cpp/connection.hh | 12 ++--- include/reactor-cpp/environment.hh | 13 ++---- include/reactor-cpp/graph.hh | 20 ++++---- include/reactor-cpp/impl/port_impl.hh | 5 +- include/reactor-cpp/multiport.hh | 18 +++---- include/reactor-cpp/mutations.hh | 6 +-- include/reactor-cpp/mutations/bank.hh | 22 +++++---- include/reactor-cpp/mutations/connection.hh | 13 ++++-- include/reactor-cpp/mutations/multiport.hh | 18 +++---- include/reactor-cpp/port.hh | 17 +++---- include/reactor-cpp/reactor-cpp.hh | 2 +- include/reactor-cpp/reactor_element.hh | 7 +-- include/reactor-cpp/scopes.hh | 25 +++++----- include/reactor-cpp/time_barrier.hh | 4 +- include/reactor-cpp/transaction.hh | 17 ++++--- include/reactor-cpp/value_ptr.hh | 20 ++++---- lib/environment.cc | 7 +-- lib/logical_time.cc | 4 +- lib/mutation/bank.cc | 22 ++++----- lib/mutation/connection.cc | 14 +++--- lib/mutation/multiport.cc | 34 +++++++------- lib/port.cc | 4 +- lib/reaction.cc | 10 ++-- lib/reactor.cc | 30 ++++++------ lib/reactor_element.cc | 2 +- lib/transaction.cc | 32 ++++++------- 27 files changed, 238 insertions(+), 192 deletions(-) create mode 100644 Makefile diff --git a/Makefile b/Makefile new file mode 100644 index 00000000..fcbcb7d6 --- /dev/null +++ b/Makefile @@ -0,0 +1,52 @@ +.PHONY: clean test coverage asan format format-check ci lf-test lib proto + +test: unit-test lf-test + +# Generate protobuf code +proto: + python3 external/nanopb/generator/nanopb_generator.py -Iexternal/nanopb/generator/proto/ -Iexternal/proto -L'#include "nanopb/%s"' -Dexternal/proto message.proto + +# Build reactor-uc as a static library +lib: + cmake -Bbuild + cmake --build build + make -C build + +# Build and run the unit tests +unit-test: + cmake -Bbuild -DBUILD_TESTS=ON + cmake --build build + make test -C build + +# Build and run lf tests +lf-test: + make -C test/lf + +# Get coverage data on unit tests +coverage: + cmake -Bbuild -DBUILD_TESTS=ON -DTEST_COVERAGE=ON + cmake --build build + make coverage -C build + +# Compile tests with AddressSanitizer and run them +asan: + cmake -Bbuild -DASAN=ON -DBUILD_TESTS=ON + cmake --build build + make test -C build + +# Format the code base +SRC_FILES := $(shell find ./lib -name '*.cc' -print) +HDR_FILES := $(shell find ./include -name '*.hh' -print) + +format: + clang-format -i -style=file $(SRC_FILES) $(HDR_FILES) + +# Check that the code base is formatted +format-check: + clang-format --dry-run --Werror -style=file $(SRC_FILES) $(HDR_FILES) + +# Run the entire CI flow +ci: clean test coverage format-check + +clean: + rm -rf build diff --git a/include/reactor-cpp/connection.hh b/include/reactor-cpp/connection.hh index 106738fc..07000a6c 100644 --- a/include/reactor-cpp/connection.hh +++ b/include/reactor-cpp/connection.hh @@ -143,8 +143,8 @@ public: }; } - auto acquire_tag(const Tag& tag, std::unique_lock& lock, - const std::function& abort_waiting) -> bool override { + auto acquire_tag(const Tag& tag, std::unique_lock& lock, const std::function& abort_waiting) + -> bool override { reactor_assert(lock.owns_lock()); log_.debug() << "downstream tries to acquire tag " << tag; @@ -210,8 +210,8 @@ public: }; } - auto acquire_tag(const Tag& tag, std::unique_lock& lock, - const std::function& abort_waiting) -> bool override { + auto acquire_tag(const Tag& tag, std::unique_lock& lock, const std::function& abort_waiting) + -> bool override { // Since this is a delayed connection, we can go back in time and need to // acquire the latest upstream tag that can create an event at the given // tag. We also need to consider that given a delay d and a tag g=(t, n), @@ -240,8 +240,8 @@ public: }; } - auto acquire_tag(const Tag& tag, std::unique_lock& lock, - const std::function& abort_waiting) -> bool override { + auto acquire_tag(const Tag& tag, std::unique_lock& lock, const std::function& abort_waiting) + -> bool override { this->log_.debug() << "downstream tries to acquire tag " << tag; return PhysicalTimeBarrier::acquire_tag(tag, lock, this->environment()->scheduler(), abort_waiting); } diff --git a/include/reactor-cpp/environment.hh b/include/reactor-cpp/environment.hh index 60e3db93..fdfb30b7 100644 --- a/include/reactor-cpp/environment.hh +++ b/include/reactor-cpp/environment.hh @@ -75,31 +75,25 @@ private: Graph graph_{}; Graph optimized_graph_{}; - std::mutex shutdown_mutex_{}; auto startup(const TimePoint& start_time) -> std::thread; public: - //TODO: fix visebility + // TODO: fix visebility void calculate_indexes(); void build_dependency_graph(Reactor* reactor); void clear_dependency_graph(); - explicit Environment(unsigned int num_workers, bool fast_fwd_execution = default_fast_fwd_execution, const Duration& timeout = Duration::max()); explicit Environment(const std::string& name, Environment* containing_environment); auto name() -> const std::string& { return name_; } - void start_mutation() { - phase_ = Phase::Mutation; - } + void start_mutation() { phase_ = Phase::Mutation; } - void stop_mutation() { - phase_ = Phase::Execution; - } + void stop_mutation() { phase_ = Phase::Execution; } // this method draw a connection between two graph elements with some properties template void draw_connection(Port& source, Port& sink, ConnectionProperties properties) { @@ -112,7 +106,6 @@ public: auto properties = graph_.remove_edge(source, sink); } else { return top_environment_->remove_connection(source, sink); - } } diff --git a/include/reactor-cpp/graph.hh b/include/reactor-cpp/graph.hh index ac9b8e41..08af8d65 100644 --- a/include/reactor-cpp/graph.hh +++ b/include/reactor-cpp/graph.hh @@ -54,14 +54,13 @@ public: std::vector> edges{std::make_pair(properties, destination)}; graph_[source] = edges; } else { - auto &edges = graph_[source]; - auto duplicate = std::find_if(edges.begin(), edges.end(), - [&](const std::pair& edge) { - return edge.first == properties && edge.second == destination; - }); - if (duplicate == edges.end()) { - graph_[source].emplace_back(properties, destination); - } + auto& edges = graph_[source]; + auto duplicate = std::find_if(edges.begin(), edges.end(), [&](const std::pair& edge) { + return edge.first == properties && edge.second == destination; + }); + if (duplicate == edges.end()) { + graph_[source].emplace_back(properties, destination); + } } } @@ -69,9 +68,8 @@ public: if (graph_.find(source) == std::end(graph_)) { return std::nullopt; } else { - auto conns = std::find_if(std::begin(graph_[source]), std::end(graph_[source]), [destinations](auto val) { - return val.second == destinations; - }); + auto conns = std::find_if(std::begin(graph_[source]), std::end(graph_[source]), + [destinations](auto val) { return val.second == destinations; }); if (conns != std::end(graph_[source])) { graph_[source].erase(conns); diff --git a/include/reactor-cpp/impl/port_impl.hh b/include/reactor-cpp/impl/port_impl.hh index 836384d4..db596dbb 100644 --- a/include/reactor-cpp/impl/port_impl.hh +++ b/include/reactor-cpp/impl/port_impl.hh @@ -9,11 +9,10 @@ #ifndef REACTOR_CPP_IMPL_PORT_IMPL_HH #define REACTOR_CPP_IMPL_PORT_IMPL_HH -#include "reactor-cpp/port.hh" -#include "reactor-cpp/reactor.hh" #include "reactor-cpp/assert.hh" #include "reactor-cpp/environment.hh" - +#include "reactor-cpp/port.hh" +#include "reactor-cpp/reactor.hh" namespace reactor { diff --git a/include/reactor-cpp/multiport.hh b/include/reactor-cpp/multiport.hh index a0d2e81e..d0aa4888 100644 --- a/include/reactor-cpp/multiport.hh +++ b/include/reactor-cpp/multiport.hh @@ -48,17 +48,14 @@ protected: void register_port(BasePort& port, size_t idx); - public: - explicit BaseMultiport(const std::string& name) : multiport_name_(name) {}; + explicit BaseMultiport(const std::string& name) + : multiport_name_(name){}; ~BaseMultiport() = default; - auto name() const -> std::string { - return multiport_name_; - } + auto name() const -> std::string { return multiport_name_; } }; -template -class MutationChangeMultiportSize; +template class MutationChangeMultiportSize; template > class Multiport : public BaseMultiport { // NOLINT cppcoreguidelines-special-member-functions @@ -66,6 +63,7 @@ protected: std::vector ports_{}; // NOLINT cppcoreguidelines-non-private-member-variables-in-classes friend MutationChangeMultiportSize; + public: using value_type = typename A::value_type; using size_type = typename A::size_type; @@ -73,7 +71,8 @@ public: using iterator = typename std::vector::iterator; using const_iterator = typename std::vector::const_iterator; - explicit Multiport(const std::string& name) noexcept : BaseMultiport(name) {}; + explicit Multiport(const std::string& name) noexcept + : BaseMultiport(name){}; ~Multiport() noexcept = default; auto operator==(const Multiport& other) const noexcept -> bool { @@ -106,7 +105,8 @@ public: template > class ModifableMultiport : public Multiport { public: - ModifableMultiport(const std::string& name) : Multiport(name) {} + ModifableMultiport(const std::string& name) + : Multiport(name) {} void reserve(std::size_t size) noexcept { this->ports_.reserve(size); diff --git a/include/reactor-cpp/mutations.hh b/include/reactor-cpp/mutations.hh index d507f89f..a7fab5df 100644 --- a/include/reactor-cpp/mutations.hh +++ b/include/reactor-cpp/mutations.hh @@ -13,10 +13,10 @@ enum MutationResult { class Mutation { public: virtual ~Mutation() = default; - virtual auto run() -> MutationResult = 0 ; + virtual auto run() -> MutationResult = 0; virtual auto rollback() -> MutationResult = 0; }; -} +} // namespace reactor -#endif //MUTATIONS_HH +#endif // MUTATIONS_HH diff --git a/include/reactor-cpp/mutations/bank.hh b/include/reactor-cpp/mutations/bank.hh index 8d52490f..f77fe040 100644 --- a/include/reactor-cpp/mutations/bank.hh +++ b/include/reactor-cpp/mutations/bank.hh @@ -7,16 +7,14 @@ #include -#include "../reactor.hh" #include "../mutations.hh" +#include "../reactor.hh" namespace reactor { class Reactor; class Environment; -template -class MutationChangeBankSize : public reactor::Mutation { -private: +template class MutationChangeBankSize : public reactor::Mutation { std::vector* bank_ = nullptr; std::size_t desired_size_ = 0; std::size_t size_before_application_ = 0; @@ -26,14 +24,18 @@ private: void change_size(std::size_t); public: - MutationChangeBankSize(std::vector* bank, Reactor* reactor, std::size_t size, std::function); + MutationChangeBankSize(std::vector* bank, Reactor* reactor, std::size_t size, + std::function); MutationChangeBankSize() = default; - explicit MutationChangeBankSize(const std::vector& other) : bank_(other.bank_), desired_size_(other.desired_size_), size_before_application_(other.size_before_application_) {} + explicit MutationChangeBankSize(const std::vector& other) + : bank_(other.bank_) + , desired_size_(other.desired_size_) + , size_before_application_(other.size_before_application_) {} ~MutationChangeBankSize() override = default; - auto run() -> reactor::MutationResult override; - auto rollback() -> reactor::MutationResult override; + auto run() -> MutationResult override; + auto rollback() -> MutationResult override; }; -} +} // namespace reactor -#endif //MUTATION_BANK_HH +#endif // MUTATION_BANK_HH diff --git a/include/reactor-cpp/mutations/connection.hh b/include/reactor-cpp/mutations/connection.hh index 2e2b02ef..72a78235 100644 --- a/include/reactor-cpp/mutations/connection.hh +++ b/include/reactor-cpp/mutations/connection.hh @@ -11,8 +11,7 @@ namespace reactor { class Reactor; class Environment; -template -class MutationAddConnection : public Mutation { +template class MutationAddConnection : public Mutation { private: A* source_; B* sink_; @@ -21,13 +20,17 @@ private: public: MutationAddConnection(A* source, B* sink, Reactor* reactor); - MutationAddConnection(const MutationAddConnection& other) : source_(other.source_), sink_(other.sink_), connection_(other.connection_), reactor_(other.reactor_) {} + MutationAddConnection(const MutationAddConnection& other) + : source_(other.source_) + , sink_(other.sink_) + , connection_(other.connection_) + , reactor_(other.reactor_) {} MutationAddConnection() = default; ~MutationAddConnection() override = default; auto run() -> MutationResult override; auto rollback() -> MutationResult override; }; -} +} // namespace reactor -#endif //MUTATION_CONNECTION_HH +#endif // MUTATION_CONNECTION_HH diff --git a/include/reactor-cpp/mutations/multiport.hh b/include/reactor-cpp/mutations/multiport.hh index e7a86aaa..da8e407e 100644 --- a/include/reactor-cpp/mutations/multiport.hh +++ b/include/reactor-cpp/mutations/multiport.hh @@ -11,13 +11,11 @@ #include "../mutations.hh" #include "../port.hh" - namespace reactor { class Reactor; class Environment; -template -class MutationChangeOutputMultiportSize : public Mutation { +template class MutationChangeOutputMultiportSize : public Mutation { private: ModifableMultiport>* multiport_ = nullptr; std::set anti_dependencies_{}; @@ -28,16 +26,18 @@ private: void change_size(std::size_t); public: - MutationChangeOutputMultiportSize(ModifableMultiport>* multiport, Reactor* reactor, std::set& anti_dependencies, std::size_t size); + MutationChangeOutputMultiportSize(ModifableMultiport>* multiport, Reactor* reactor, + std::set& anti_dependencies, std::size_t size); MutationChangeOutputMultiportSize() = default; - MutationChangeOutputMultiportSize(const MutationChangeOutputMultiportSize& other) : multiport_(other.multiport_), desired_size_(other.desired_size_), size_before_application_(other.size_before_application_) {} + MutationChangeOutputMultiportSize(const MutationChangeOutputMultiportSize& other) + : multiport_(other.multiport_) + , desired_size_(other.desired_size_) + , size_before_application_(other.size_before_application_) {} ~MutationChangeOutputMultiportSize() override = default; - auto run() -> MutationResult override; auto rollback() -> MutationResult override; }; -} - +} // namespace reactor -#endif //MUTATION_MULTIPORT_HH +#endif // MUTATION_MULTIPORT_HH diff --git a/include/reactor-cpp/port.hh b/include/reactor-cpp/port.hh index bcce4ea9..e5b3da56 100644 --- a/include/reactor-cpp/port.hh +++ b/include/reactor-cpp/port.hh @@ -22,8 +22,7 @@ namespace reactor { -template -class MutationChangeMultiportSize; +template class MutationChangeMultiportSize; enum class PortType : std::uint8_t { Input, Output, Delay }; @@ -77,7 +76,8 @@ public: void register_antidependency(Reaction* reaction) noexcept; void set_inward_binding(BasePort* port) noexcept { if (port != nullptr) { - std::cout << port->fqn() << "(" << port << ")" << " --> " << this->fqn() << "(" << this << ")" << std::endl; + std::cout << port->fqn() << "(" << port << ")" + << " --> " << this->fqn() << "(" << this << ")" << std::endl; } inward_binding_ = port; @@ -106,7 +106,7 @@ public: [[nodiscard]] auto triggers() const noexcept -> const auto& { return triggers_; } [[nodiscard]] auto dependencies() const noexcept -> const auto& { return dependencies_; } - [[nodiscard]] auto anti_dependencies() noexcept -> auto& { return anti_dependencies_; } //TODO: make it const again + [[nodiscard]] auto anti_dependencies() noexcept -> auto& { return anti_dependencies_; } // TODO: make it const again [[nodiscard]] auto port_type() const noexcept -> PortType { return type_; } void register_set_callback(const PortCallback& callback); @@ -116,7 +116,6 @@ public: friend class Scheduler; }; - inline auto operator==(const BasePort& a, const BasePort& b) -> bool { bool equal = ((const ReactorElement&)a) == ((const ReactorElement&)b); return equal; @@ -190,9 +189,7 @@ public: Input(Input&&) = default; - ~Input() { - std::cout << "Input port gets deallocated:" << this->fqn() << std::endl; - } + ~Input() { std::cout << "Input port gets deallocated:" << this->fqn() << std::endl; } }; template class Output : public Port { // NOLINT(cppcoreguidelines-special-member-functions) @@ -202,9 +199,7 @@ public: Output(Output&&) noexcept = default; - ~Output() { - std::cout << "Output port gets deallocated: " << this->fqn() << std::endl; - } + ~Output() { std::cout << "Output port gets deallocated: " << this->fqn() << std::endl; } }; } // namespace reactor diff --git a/include/reactor-cpp/reactor-cpp.hh b/include/reactor-cpp/reactor-cpp.hh index a4367c80..9f8ecf1c 100644 --- a/include/reactor-cpp/reactor-cpp.hh +++ b/include/reactor-cpp/reactor-cpp.hh @@ -20,7 +20,7 @@ #include "port.hh" #include "reaction.hh" #include "reactor.hh" -#include "time.hh" #include "scopes.hh" +#include "time.hh" #endif // REACTOR_CPP_REACTOR_CPP_HH diff --git a/include/reactor-cpp/reactor_element.hh b/include/reactor-cpp/reactor_element.hh index 70965959..d9f44013 100644 --- a/include/reactor-cpp/reactor_element.hh +++ b/include/reactor-cpp/reactor_element.hh @@ -52,9 +52,10 @@ public: virtual void startup() = 0; virtual void shutdown() = 0; - auto operator==(const ReactorElement& other) const -> bool { - //std::cout << other.name() << "==" << name_ << std::endl; - return name_ == other.name(); // && container_ == other.container() && environment_ == other.environment(); // && fqn_ == other.fqn() + auto operator==(const ReactorElement& other) const -> bool { + // std::cout << other.name() << "==" << name_ << std::endl; + return name_ == other.name(); // && container_ == other.container() && environment_ == other.environment(); // && + // fqn_ == other.fqn() } }; } // namespace reactor diff --git a/include/reactor-cpp/scopes.hh b/include/reactor-cpp/scopes.hh index f1f1352a..ff3712c6 100644 --- a/include/reactor-cpp/scopes.hh +++ b/include/reactor-cpp/scopes.hh @@ -1,18 +1,18 @@ /* -* Copyright (C) 2024 TU Dresden -* All rights reserved. -* -* Authors: -* Tassilo Tanneberger -*/ + * Copyright (C) 2024 TU Dresden + * All rights reserved. + * + * Authors: + * Tassilo Tanneberger + */ #ifndef REACTOR_CPP_SCOPS_HH #define REACTOR_CPP_SCOPS_HH -#include "transaction.hh" +#include "environment.hh" #include "logical_time.hh" #include "reactor.hh" -#include "environment.hh" +#include "transaction.hh" namespace reactor { @@ -40,14 +40,17 @@ public: Reactor* reactor_; Environment* env_ = nullptr; - explicit MutableScope(Reactor* reactor) : Scope(reactor), transaction_(reactor), reactor_(reactor), env_(reactor->environment()) {} + explicit MutableScope(Reactor* reactor) + : Scope(reactor) + , transaction_(reactor) + , reactor_(reactor) + , env_(reactor->environment()) {} ~MutableScope() = default; void commit_transaction(bool recalculate = false); void add_to_transaction(const std::shared_ptr& mutation); - }; -} +} // namespace reactor #endif // REACTOR_CPP_SCOPS_HH diff --git a/include/reactor-cpp/time_barrier.hh b/include/reactor-cpp/time_barrier.hh index a5874106..b69e2045 100644 --- a/include/reactor-cpp/time_barrier.hh +++ b/include/reactor-cpp/time_barrier.hh @@ -80,8 +80,8 @@ public: // The caller must hold a lock on the scheduler mutex auto try_acquire_tag(const Tag& tag) { return tag <= released_time_; } - auto acquire_tag(const Tag& tag, std::unique_lock& lock, - const std::function& abort_waiting) -> bool { + auto acquire_tag(const Tag& tag, std::unique_lock& lock, const std::function& abort_waiting) + -> bool { if (try_acquire_tag(tag)) { return true; } diff --git a/include/reactor-cpp/transaction.hh b/include/reactor-cpp/transaction.hh index fb27ff19..3b06496b 100644 --- a/include/reactor-cpp/transaction.hh +++ b/include/reactor-cpp/transaction.hh @@ -1,25 +1,24 @@ /* -* Copyright (C) 2024 TU Dresden -* All rights reserved. -* -* Authors: -* Tassilo Tanneberger + * Copyright (C) 2024 TU Dresden + * All rights reserved. + * + * Authors: + * Tassilo Tanneberger */ #ifndef REACTOR_CPP_TRANSACTION_HH #define REACTOR_CPP_TRANSACTION_HH -#include #include +#include #include "mutations.hh" -//#include "reactor.hh" +// #include "reactor.hh" namespace reactor { class Reactor; class Environment; - class Transaction { private: Environment* environment_ = nullptr; @@ -32,5 +31,5 @@ public: void push_back(const std::shared_ptr& mutation); auto execute(bool recalculate = false) -> MutationResult; }; -} +} // namespace reactor #endif // REACTOR_CPP_TRANSACTION_HH diff --git a/include/reactor-cpp/value_ptr.hh b/include/reactor-cpp/value_ptr.hh index a6d55089..7a8f6c75 100644 --- a/include/reactor-cpp/value_ptr.hh +++ b/include/reactor-cpp/value_ptr.hh @@ -517,23 +517,23 @@ public: // Comparison operators template -auto operator==(const MutableValuePtr& ptr1, - const MutableValuePtr& ptr2) noexcept -> bool { +auto operator==(const MutableValuePtr& ptr1, const MutableValuePtr& ptr2) noexcept + -> bool { return ptr1.get() == ptr2.get(); } template -auto operator==(const ImmutableValuePtr& ptr1, - const ImmutableValuePtr& ptr2) noexcept -> bool { +auto operator==(const ImmutableValuePtr& ptr1, const ImmutableValuePtr& ptr2) noexcept + -> bool { return ptr1.get() == ptr2.get(); } template -auto operator==(const ImmutableValuePtr& ptr1, - const MutableValuePtr& ptr2) noexcept -> bool { +auto operator==(const ImmutableValuePtr& ptr1, const MutableValuePtr& ptr2) noexcept + -> bool { return ptr1.get() == ptr2.get(); } template -auto operator==(const MutableValuePtr& ptr1, - const ImmutableValuePtr& ptr2) noexcept -> bool { +auto operator==(const MutableValuePtr& ptr1, const ImmutableValuePtr& ptr2) noexcept + -> bool { return ptr1.get() == ptr2.get(); } template @@ -554,8 +554,8 @@ auto operator==(std::nullptr_t, const ImmutableValuePtr& ptr1) no } template -auto operator!=(const MutableValuePtr& ptr1, - const MutableValuePtr& ptr2) noexcept -> bool { +auto operator!=(const MutableValuePtr& ptr1, const MutableValuePtr& ptr2) noexcept + -> bool { return ptr1.get() != ptr2.get(); } diff --git a/lib/environment.cc b/lib/environment.cc index be84af16..9b86fd7a 100644 --- a/lib/environment.cc +++ b/lib/environment.cc @@ -47,7 +47,8 @@ Environment::Environment(const std::string& name, Environment* containing_enviro void Environment::register_reactor(Reactor* reactor) { reactor_assert(reactor != nullptr); - validate(this->phase() == Phase::Construction || this->phase() == Phase::Mutation, "Reactors may only be registered during construction phase!"); + validate(this->phase() == Phase::Construction || this->phase() == Phase::Mutation, + "Reactors may only be registered during construction phase!"); validate(reactor->is_top_level(), "The environment may only contain top level reactors!"); [[maybe_unused]] bool result = top_level_reactors_.insert(reactor).second; reactor_assert(result); @@ -145,8 +146,8 @@ void Environment::assemble() { // NOLINT(readability-function-cognitive-complexi } void Environment::clear_dependency_graph() { - dependencies_.clear(); - reactions_.clear(); + dependencies_.clear(); + reactions_.clear(); } void Environment::build_dependency_graph(Reactor* reactor) { diff --git a/lib/logical_time.cc b/lib/logical_time.cc index 56bd723e..3e4ea73b 100644 --- a/lib/logical_time.cc +++ b/lib/logical_time.cc @@ -45,8 +45,8 @@ auto Tag::subtract(Duration offset) const noexcept -> Tag { auto Tag::decrement() const noexcept -> Tag { if (micro_step_ == 0) { - //FIXME: return {time_point_ - Duration{1}, std::numeric_limits::max()}; - return {time_point_ - Duration{1}, 0}; + // FIXME: return {time_point_ - Duration{1}, std::numeric_limits::max()}; + return {time_point_ - Duration{1}, 0}; } return {time_point_, micro_step_ - 1}; } diff --git a/lib/mutation/bank.cc b/lib/mutation/bank.cc index 4d8ee3b8..a358d88b 100644 --- a/lib/mutation/bank.cc +++ b/lib/mutation/bank.cc @@ -5,13 +5,15 @@ #include "reactor-cpp/mutations/bank.hh" #include "reactor-cpp/action.hh" -template -reactor::MutationChangeBankSize::MutationChangeBankSize(std::vector* bank, Reactor* reactor, std::size_t size, std::function create_lambda) - : bank_(bank), reactor_(reactor), desired_size_(size), create_lambda_(create_lambda){ -} +template +reactor::MutationChangeBankSize::MutationChangeBankSize(std::vector* bank, Reactor* reactor, std::size_t size, + std::function create_lambda) + : bank_(bank) + , reactor_(reactor) + , desired_size_(size) + , create_lambda_(create_lambda) {} -template -void reactor::MutationChangeBankSize::change_size(std::size_t new_size) { +template void reactor::MutationChangeBankSize::change_size(std::size_t new_size) { bank_->reserve(new_size); auto current_size = bank_->size(); std::cout << "scaling from: " << current_size << " to " << new_size << std::endl; @@ -20,7 +22,7 @@ void reactor::MutationChangeBankSize::change_size(std::size_t new_size) { // downscale for (auto i = 0; i < current_size - new_size; i++) { - //TODO: consider saving the ports here here + // TODO: consider saving the ports here here std::unique_ptr lastElement = std::move(bank_->back()); bank_->pop_back(); reactor_->environment()->remove_top_level_reactor(lastElement.get()); @@ -35,15 +37,13 @@ void reactor::MutationChangeBankSize::change_size(std::size_t new_size) { std::cout << "created new reactors" << std::endl; } } -template -auto reactor::MutationChangeBankSize::run() -> MutationResult { +template auto reactor::MutationChangeBankSize::run() -> MutationResult { size_before_application_ = bank_->size(); change_size(desired_size_); return Success; } -template -auto reactor::MutationChangeBankSize::rollback() -> MutationResult { +template auto reactor::MutationChangeBankSize::rollback() -> MutationResult { change_size(size_before_application_); return Success; } diff --git a/lib/mutation/connection.cc b/lib/mutation/connection.cc index e66ebb83..7bbbcd76 100644 --- a/lib/mutation/connection.cc +++ b/lib/mutation/connection.cc @@ -6,17 +6,17 @@ #include "reactor-cpp/reactor.hh" template -reactor::MutationAddConnection::MutationAddConnection(A* source, B* sink, Reactor* reactor) : source_(source), sink_(sink), reactor_(reactor) { - -} - +reactor::MutationAddConnection::MutationAddConnection(A* source, B* sink, Reactor* reactor) + : source_(source) + , sink_(sink) + , reactor_(reactor) {} template auto reactor::MutationAddConnection::run() -> MutationResult { reactor_->environment()->draw_connection(source_, sink_, ConnectionProperties{}); sink_->set_inward_binding(source_); source_->add_outward_binding(sink_); - //std::cout << "from: " << source_->fqn() << "(" << source_ << ")" - // << " --> to: " << sink_->fqn() << "(" << sink_ << ")" << std::endl; + // std::cout << "from: " << source_->fqn() << "(" << source_ << ")" + // << " --> to: " << sink_->fqn() << "(" << sink_ << ")" << std::endl; return Success; } @@ -25,5 +25,3 @@ template auto reactor::MutationAddConnection::rollback( return Success; } - - diff --git a/lib/mutation/multiport.cc b/lib/mutation/multiport.cc index 279458c3..486d6b6c 100644 --- a/lib/mutation/multiport.cc +++ b/lib/mutation/multiport.cc @@ -5,18 +5,22 @@ #include "reactor-cpp/mutations/multiport.hh" #include "reactor-cpp/reaction.hh" -template -reactor::MutationChangeOutputMultiportSize::MutationChangeOutputMultiportSize(ModifableMultiport>* multiport, Reactor* reactor, std::set& anti_dependencies, std::size_t size) - : multiport_(multiport), reactor_(reactor), desired_size_(size), anti_dependencies_(anti_dependencies) { } +template +reactor::MutationChangeOutputMultiportSize::MutationChangeOutputMultiportSize( + ModifableMultiport>* multiport, Reactor* reactor, std::set& anti_dependencies, + std::size_t size) + : multiport_(multiport) + , reactor_(reactor) + , desired_size_(size) + , anti_dependencies_(anti_dependencies) {} -template -void reactor::MutationChangeOutputMultiportSize::change_size(std::size_t new_size) { +template void reactor::MutationChangeOutputMultiportSize::change_size(std::size_t new_size) { auto current_size = multiport_->size(); if (current_size >= new_size) { // downscale for (auto i = 0; i < current_size - new_size; i++) { - //TODO: consider saving the ports here here + // TODO: consider saving the ports here here std::string port_name_ = multiport_->name() + "_" + std::to_string(current_size - i - 1); multiport_->pop_back(); @@ -25,12 +29,12 @@ void reactor::MutationChangeOutputMultiportSize::change_size(std::size_t new_ } for (auto* anti_dep : anti_dependencies_) { - anti_dep->clear_antidependencies(); - for (auto i = 0; i < new_size; i++) { + anti_dep->clear_antidependencies(); + for (auto i = 0; i < new_size; i++) { - multiport_->operator[](i).anti_dependencies().clear(); - anti_dep->declare_antidependency(&multiport_->operator[](i)); - } + multiport_->operator[](i).anti_dependencies().clear(); + anti_dep->declare_antidependency(&multiport_->operator[](i)); + } } } else { // upscale @@ -46,19 +50,15 @@ void reactor::MutationChangeOutputMultiportSize::change_size(std::size_t new_ anti_dep->declare_antidependency(&multiport_->operator[](i)); } }*/ - - } } -template -auto reactor::MutationChangeOutputMultiportSize::run() -> MutationResult { +template auto reactor::MutationChangeOutputMultiportSize::run() -> MutationResult { size_before_application_ = multiport_->size(); change_size(desired_size_); return Success; } -template -auto reactor::MutationChangeOutputMultiportSize::rollback() -> MutationResult { +template auto reactor::MutationChangeOutputMultiportSize::rollback() -> MutationResult { change_size(size_before_application_); return Success; } diff --git a/lib/port.cc b/lib/port.cc index 412e4cab..23af9ea3 100644 --- a/lib/port.cc +++ b/lib/port.cc @@ -20,7 +20,7 @@ void BasePort::register_dependency(Reaction* reaction, bool is_trigger) noexcept reactor_assert(reaction != nullptr); reactor_assert(this->environment() == reaction->environment()); validate(!this->has_outward_bindings(), "Dependencies may no be declared on ports with an outward binding!"); - //assert_phase(this, Phase::Assembly); + // assert_phase(this, Phase::Assembly); if (this->is_input()) { validate(this->container() == reaction->container(), "Dependent input ports must belong to the same reactor as the " @@ -42,7 +42,7 @@ void BasePort::register_antidependency(Reaction* reaction) noexcept { reactor_assert(reaction != nullptr); reactor_assert(this->environment() == reaction->environment()); validate(!this->has_inward_binding(), "Antidependencies may no be declared on ports with an inward binding!"); - //TODO: assert_phase(this, Phase::Assembly); + // TODO: assert_phase(this, Phase::Assembly); if (this->is_output()) { validate(this->container() == reaction->container(), diff --git a/lib/reaction.cc b/lib/reaction.cc index 1647e68b..6b373948 100644 --- a/lib/reaction.cc +++ b/lib/reaction.cc @@ -20,8 +20,7 @@ namespace reactor { Reaction::Reaction(const std::string& name, int priority, Reactor* container, std::function body) : ReactorElement(name, ReactorElement::Type::Reaction, container) , priority_(priority) - , body_(std::move(std::move(body))) -{ + , body_(std::move(std::move(body))) { reactor_assert(priority != 0); } @@ -52,7 +51,7 @@ void Reaction::declare_schedulable_action(BaseAction* action) { void Reaction::declare_trigger(BasePort* port) { reactor_assert(port != nullptr); reactor_assert(this->environment() == port->environment()); - //assert_phase(this, Phase::Assembly); + // assert_phase(this, Phase::Assembly); if (port->is_input()) { validate(this->container() == port->container(), @@ -91,7 +90,7 @@ void Reaction::declare_dependency(BasePort* port) { void Reaction::declare_antidependency(BasePort* port) { reactor_assert(port != nullptr); reactor_assert(this->environment() == port->environment()); - //assert_phase(this, Phase::Assembly); + // assert_phase(this, Phase::Assembly); if (port->is_output()) { validate(this->container() == port->container(), "Antidependent output ports must belong to the same reactor as " @@ -127,7 +126,8 @@ void Reaction::set_deadline_impl(Duration deadline, const std::functionenvironment()->phase() == Phase::Assembly || this->environment()->phase() == Phase::Mutation, "Reaction indexes may only be set during assembly phase!"); + validate(this->environment()->phase() == Phase::Assembly || this->environment()->phase() == Phase::Mutation, + "Reaction indexes may only be set during assembly phase!"); this->index_ = index; } diff --git a/lib/reactor.cc b/lib/reactor.cc index 76eadc25..08bc8863 100644 --- a/lib/reactor.cc +++ b/lib/reactor.cc @@ -38,22 +38,24 @@ void Reactor::register_action([[maybe_unused]] BaseAction* action) { void Reactor::register_input(BasePort* port) { reactor_assert(port != nullptr); - reactor::validate(this->environment()->phase() == Phase::Construction || this->environment()->phase() == Phase::Mutation, + reactor::validate(this->environment()->phase() == Phase::Construction || + this->environment()->phase() == Phase::Mutation, "Ports can only be registered during construction phase!"); //[[maybe_unused]] bool result = inputs_.insert(port).second; inputs_.push_back(port); - //reactor_assert(result); + // reactor_assert(result); Statistics::increment_ports(); } void Reactor::register_output(BasePort* port) { (void)port; reactor_assert(port != nullptr); - reactor::validate(this->environment()->phase() == Phase::Construction || this->environment()->phase() == Phase::Mutation, + reactor::validate(this->environment()->phase() == Phase::Construction || + this->environment()->phase() == Phase::Mutation, "Ports can only be registered during construction phase!"); //[[maybe_unused]] bool result = inputs_.insert(port).second; - //std::cout << "reactor port count:" << inputs_.size() << std::endl; - //TODO: reactor_assert(result); + // std::cout << "reactor port count:" << inputs_.size() << std::endl; + // TODO: reactor_assert(result); Statistics::increment_ports(); } @@ -78,7 +80,7 @@ void Reactor::register_reactor([[maybe_unused]] Reactor* reactor) { } //[[maybe_unused]] bool result = reactors_.insert(reactor).second; - //reactor_assert(result); + // reactor_assert(result); Statistics::increment_reactor_instances(); } @@ -153,17 +155,17 @@ auto Reactor::get_elapsed_physical_time() const noexcept -> Duration { } void Reactor::remove_inputs(BasePort* base_port) { - auto index = std::find_if(std::begin(inputs_), std::end(inputs_), [base_port](const BasePort* other) { return *other == *base_port;}); + auto index = std::find_if(std::begin(inputs_), std::end(inputs_), + [base_port](const BasePort* other) { return *other == *base_port; }); - if (index != std::end(inputs_)) { - inputs_.erase(index); - } - }; + if (index != std::end(inputs_)) { + inputs_.erase(index); + } +}; void Reactor::remove_child_reactor(const Reactor* base_reactor) { - auto index = std::find_if(std::begin(reactors_), std::end(reactors_), [base_reactor](const Reactor* other) { - return base_reactor == other; - }); + auto index = std::find_if(std::begin(reactors_), std::end(reactors_), + [base_reactor](const Reactor* other) { return base_reactor == other; }); if (index != std::end(reactors_)) { reactors_.erase(index); diff --git a/lib/reactor_element.cc b/lib/reactor_element.cc index 51eae68d..672fa5d7 100644 --- a/lib/reactor_element.cc +++ b/lib/reactor_element.cc @@ -24,7 +24,7 @@ ReactorElement::ReactorElement(const std::string& name, ReactorElement::Type typ reactor_assert(container != nullptr); this->environment_ = container->environment(); reactor_assert(this->environment_ != nullptr); - validate(this->environment_->phase() == Phase::Construction ||this->environment_->phase() == Phase::Mutation || + validate(this->environment_->phase() == Phase::Construction || this->environment_->phase() == Phase::Mutation || (type == Type::Action && this->environment_->phase() == Phase::Assembly), "Reactor elements can only be created during construction phase!"); // We need a reinterpret_cast here as the derived class is not yet created diff --git a/lib/transaction.cc b/lib/transaction.cc index 2cf53855..3092b937 100644 --- a/lib/transaction.cc +++ b/lib/transaction.cc @@ -4,31 +4,31 @@ #include "reactor-cpp/environment.hh" #include "reactor-cpp/reactor.hh" - reactor::Transaction::Transaction(Reactor* parent) : environment_(parent->environment()) { } - +reactor::Transaction::Transaction(Reactor* parent) + : environment_(parent->environment()) {} auto reactor::Transaction::execute(bool recalculate) -> MutationResult { - this->environment_->start_mutation(); - for (auto mutation : mutations_) { - mutation->run(); - } + this->environment_->start_mutation(); + for (auto mutation : mutations_) { + mutation->run(); + } - if (recalculate) { + if (recalculate) { this->environment_->clear_dependency_graph(); - for (const auto* reactor : this->environment_->top_level_reactors()) { - this->environment_->build_dependency_graph((Reactor*)reactor); - } + for (const auto* reactor : this->environment_->top_level_reactors()) { + this->environment_->build_dependency_graph((Reactor*)reactor); + } - this->environment_->calculate_indexes(); - } + this->environment_->calculate_indexes(); + } - this->environment_->stop_mutation(); + this->environment_->stop_mutation(); - mutations_.clear(); - return Success; + mutations_.clear(); + return Success; } void reactor::Transaction::push_back(const std::shared_ptr& mutation) { - mutations_.push_back(mutation); + mutations_.push_back(mutation); } \ No newline at end of file From a639c31ddca2f18c1ec2d2e0b07182cfa9e5bac9 Mon Sep 17 00:00:00 2001 From: tanneberger Date: Sat, 14 Dec 2024 08:22:58 +0100 Subject: [PATCH 7/8] code cleaning --- examples/CMakeLists.txt | 1 - examples/count/main.cc | 6 +- examples/hello/main.cc | 2 +- examples/multiport_mutation/consumer.hh | 49 +++++------ examples/multiport_mutation/load_balancer.hh | 64 +++++++-------- examples/multiport_mutation/main.cc | 86 ++++++++++---------- examples/multiport_mutation/producer.hh | 39 ++++----- examples/ports/main.cc | 8 +- examples/power_train/main.cc | 23 ++---- examples/unit_tests_mutations/CMakeLists.txt | 3 - examples/unit_tests_mutations/main.cc | 82 ------------------- include/reactor-cpp/environment.hh | 6 +- include/reactor-cpp/graph.hh | 16 ++-- include/reactor-cpp/multiport.hh | 21 ++--- include/reactor-cpp/mutations.hh | 16 +++- include/reactor-cpp/mutations/bank.hh | 30 ++++--- include/reactor-cpp/mutations/connection.hh | 15 +++- include/reactor-cpp/mutations/multiport.hh | 14 +++- include/reactor-cpp/port.hh | 11 +-- include/reactor-cpp/reaction.hh | 4 +- include/reactor-cpp/scopes.hh | 46 +++++++---- include/reactor-cpp/transaction.hh | 4 + lib/action.cc | 10 +-- lib/environment.cc | 8 +- lib/mutation/bank.cc | 9 +- lib/reaction.cc | 2 +- lib/reactor.cc | 6 +- lib/transaction.cc | 6 +- 28 files changed, 264 insertions(+), 323 deletions(-) delete mode 100644 examples/unit_tests_mutations/CMakeLists.txt delete mode 100644 examples/unit_tests_mutations/main.cc diff --git a/examples/CMakeLists.txt b/examples/CMakeLists.txt index 3d40852e..5b9bbf09 100644 --- a/examples/CMakeLists.txt +++ b/examples/CMakeLists.txt @@ -8,4 +8,3 @@ add_subdirectory(ports) add_subdirectory(hello) add_subdirectory(power_train) add_subdirectory(multiport_mutation) -add_subdirectory(unit_tests_mutations) diff --git a/examples/count/main.cc b/examples/count/main.cc index ca20df5d..08012a2b 100644 --- a/examples/count/main.cc +++ b/examples/count/main.cc @@ -5,15 +5,15 @@ using namespace reactor; using namespace std::chrono_literals; -class Count : public Reactor { +class Count final : public Reactor { private: // actions Timer timer{"timer", this}; LogicalAction counter{"counter", this}; // reactions_ - Reaction r_init{"r_init", 1, false, this, [this]() { this->init(); }}; - Reaction r_counter{"r_counter", 2, false, this, [this]() { this->print_count(); }}; + Reaction r_init{"r_init", 1, this, [this]() { this->init(); }}; + Reaction r_counter{"r_counter", 2, this, [this]() { this->print_count(); }}; public: explicit Count(Environment* env) diff --git a/examples/hello/main.cc b/examples/hello/main.cc index 3b02fd89..2f6c88f8 100644 --- a/examples/hello/main.cc +++ b/examples/hello/main.cc @@ -6,7 +6,7 @@ using namespace reactor; using namespace std::chrono_literals; -class Hello : public Reactor { +class Hello final : public Reactor { private: // actions Timer timer{"timer", this, 1s, 2s}; diff --git a/examples/multiport_mutation/consumer.hh b/examples/multiport_mutation/consumer.hh index b2ac7324..704d62f6 100644 --- a/examples/multiport_mutation/consumer.hh +++ b/examples/multiport_mutation/consumer.hh @@ -1,46 +1,39 @@ -// -// Created by tanneberger on 11/17/24. -// - -#ifndef CONSUMER_HH -#define CONSUMER_HH +#ifndef CONSUMER_HH // NOLINT +#define CONSUMER_HH // NOLINT #include using namespace reactor; using namespace std::chrono_literals; -class Consumer : public Reactor { -private: - class Inner: public Scope { - Inner(Reactor* reactor, std::size_t index) : Scope(reactor), index_(index) {} - std::size_t index_; - - [[maybe_unused]] const Inner& __lf_inner = *this; +class Consumer final : public Reactor { // NOLINT + class Inner : public Scope { + Inner(Reactor* reactor, std::size_t index) + : Scope(reactor) + , index_(index) {} + std::size_t index_ = 0; - void reaction_1([[maybe_unused]] const Input& in) { - std::cout << "consumer: " << index_ << " received value:" << *in.get() << std::endl; + void reaction_1(const Input& in) const { + std::cout << "consumer: " << index_ << " received value:" << *in.get() << '\n'; } friend Consumer; }; - Inner __lf_inner; - Reaction handle{"handle", 1, this, [this]() { __lf_inner.reaction_1(this->in); }}; + Inner _lf_inner; + Reaction handle{"handle", 1, this, [this]() { _lf_inner.reaction_1(this->in); }}; + public: - Consumer(const std::string& name, Environment* env, std::size_t index) : Reactor(name, env), __lf_inner(this, index) { - std::cout << "creating instance of consumer" << std::endl; + Consumer(const std::string& name, Environment* env, std::size_t index) + : Reactor(name, env) + , _lf_inner(this, index) { + std::cout << "creating instance of consumer" << '\n'; } - ~Consumer() override { - std::cout << "Consumer Object is deleted" << std::endl; - }; + ~Consumer() override { std::cout << "Consumer Object is deleted" << '\n'; }; - Input in{"in", this}; + Input in{"in", this}; // NOLINT - void assemble() override { - handle.declare_trigger(&in); - } + void assemble() override { handle.declare_trigger(&in); } }; - -#endif //CONSUMER_HH +#endif // CONSUMER_HH diff --git a/examples/multiport_mutation/load_balancer.hh b/examples/multiport_mutation/load_balancer.hh index 8e744279..db2e34ed 100644 --- a/examples/multiport_mutation/load_balancer.hh +++ b/examples/multiport_mutation/load_balancer.hh @@ -1,9 +1,5 @@ -// -// Created by tanneberger on 11/17/24. -// - -#ifndef LOAD_BALANCER_HH -#define LOAD_BALANCER_HH +#ifndef LOAD_BALANCER_HH // NOLINT +#define LOAD_BALANCER_HH // NOLINT #include @@ -13,29 +9,31 @@ using namespace reactor; using namespace std::chrono_literals; -class LoadBalancer : public Reactor { -private: - class Inner: public MutableScope { - Inner(Reactor* reactor) : MutableScope(reactor) {} - [[maybe_unused]] const Inner& __lf_inner = *this; +class LoadBalancer final : public Reactor { // NOLINT + class Inner : public MutableScope { + explicit Inner(Reactor* reactor) + : MutableScope(reactor) {} // reaction bodies - void reaction_1(const Input& inbound, LogicalAction& scale_action, Multiport>& outbound) { - if (rand() % 30 == 0) { - scale_action.schedule(rand() % 20 + 1); + static void reaction_1(const Input& inbound, LogicalAction& scale_action, + Multiport>& outbound) { + if (std::rand() % 30 == 0) { // NOLINT + scale_action.schedule(std::rand() % 20 + 1); // NOLINT } - unsigned sel = rand() % outbound.size(); - std::cout << "Sending out to:" << sel << std::endl; + const unsigned sel = std::rand() % outbound.size(); // NOLINT + std::cout << "Sending out to:" << sel << '\n'; outbound[sel].set(inbound.get()); } - void reaction_2(ModifableMultiport>&outbound, [[maybe_unused]] const LogicalAction& scale, Output& scale_bank) { + void reaction_2(ModifableMultiport>& outbound, + [[maybe_unused]] const LogicalAction& scale, Output& scale_bank) { ModifableMultiport>* temp = &outbound; std::size_t new_size = *scale.get(); auto antideps = (outbound[0]).anti_dependencies(); - auto change_size = std::make_shared>(temp, this->reactor_, antideps, new_size); + const auto change_size = + std::make_shared>(temp, this->reactor_, antideps, new_size); add_to_transaction(change_size); @@ -47,30 +45,32 @@ private: friend LoadBalancer; }; - Inner __lf_inner; - Reaction process{"process", 2, this, [this]() { __lf_inner.reaction_1(this->inbound, this->scale_action, this->out); }}; - Reaction scale{"scale", 1, this, [this]() { __lf_inner.reaction_2(this->out, this->scale_action, this->scale_bank); }}; + Inner _lf_inner; + Reaction process{"process", 2, this, [this]() { Inner::reaction_1(this->inbound, this->scale_action, this->out); }}; + Reaction scale{"scale", 1, this, [this]() { _lf_inner.reaction_2(this->out, this->scale_action, this->scale_bank); }}; public: LoadBalancer(const std::string& name, Environment* env) - : Reactor(name, env), __lf_inner(this) { - std::cout << "creating instance of load balancer" << std::endl; + : Reactor(name, env) + , _lf_inner(this) { + std::cout << "creating instance of load balancer" << '\n'; out.reserve(4); for (size_t _lf_idx = 0; _lf_idx < 4; _lf_idx++) { - std::string _lf_port_name = out.name() + "_" + std::to_string(_lf_idx); + std::string _lf_port_name = out.name() + "_" + std::to_string(_lf_idx); out.emplace_back(_lf_port_name, this); } } + ~LoadBalancer() override = default; - LogicalAction scale_action{"scale", this, 1us}; - ModifableMultiport> out{"out"}; - Input inbound{"inbound", this}; // NOLINT - Output scale_bank{"scale_bank", this}; + LogicalAction scale_action{"scale", this, 1us}; // NOLINT + ModifableMultiport> out{"out"}; // NOLINT + Input inbound{"inbound", this}; // NOLINT + Output scale_bank{"scale_bank", this}; // NOLINT void assemble() override { std::cout << "assemble LoadBalancer\n"; - for (auto& __lf_port : out) { - process.declare_antidependency(&__lf_port); + for (auto& _lf_port : out) { + process.declare_antidependency(&_lf_port); } process.declare_trigger(&inbound); scale.declare_trigger(&scale_action); @@ -78,6 +78,4 @@ public: } }; - - -#endif //LOAD_BALANCER_HH +#endif // LOAD_BALANCER_HH diff --git a/examples/multiport_mutation/main.cc b/examples/multiport_mutation/main.cc index 3956b8e6..cf59b29e 100644 --- a/examples/multiport_mutation/main.cc +++ b/examples/multiport_mutation/main.cc @@ -3,82 +3,80 @@ #include #include +#include "../../lib/mutation/bank.cc" +#include "../../lib/mutation/connection.cc" #include "./consumer.hh" #include "./load_balancer.hh" #include "./producer.hh" -#include "../../lib/mutation/bank.cc" -#include "../../lib/mutation/connection.cc" #include -class Deployment : public Reactor { - std::unique_ptr producer_; - std::unique_ptr load_balancer_; - std::vector> consumers_; - - Reaction scale_bank{"scale_bank", 1, this, [this](){this->__inner.reaction_1(this->scale, this->consumers_, load_balancer_->out);}}; - -public: - -class Inner: public MutableScope { +class Deployment final : public Reactor { // NOLINT + class Inner : public MutableScope { int state = 0; - [[maybe_unused]] const Inner& __lf_inner = *this; -public: - Inner(Reactor* reactor) : MutableScope(reactor) {} - void reaction_1(const Input& scale, std::vector>& reactor_bank, ModifableMultiport>& load_balancer) { + public: + Inner(Reactor* reactor) + : MutableScope(reactor) {} + void reaction_1(const Input& scale, std::vector>& reactor_bank, + ModifableMultiport>& load_balancer) { std::size_t new_size = *scale.get(); std::size_t old_size = reactor_bank.size(); - std::function(Reactor*, std::size_t)> lambda = [](Reactor* reactor, std::size_t index) { - std::string __lf_inst_name = "consumer_" + std::to_string(index); - return std::make_unique(__lf_inst_name, reactor->environment(), index); + std::function lambda = [](Reactor* reactor, std::size_t index) { + std::string _lf_inst_name = "consumer_" + std::to_string(index); + return std::make_unique(_lf_inst_name, reactor->environment(), index); }; - auto change_size = std::make_shared>>(&reactor_bank, this->reactor_, new_size, lambda); + + auto change_size = std::make_shared>>( + &reactor_bank, this->reactor_, new_size, lambda); add_to_transaction(change_size); - // old topology commit_transaction(); - // new topology - - if (old_size > new_size) { - for (auto i = 0; i < old_size - new_size; i++) { - } - } else { - std::cout << "load_balancer size:" << load_balancer.size() << " bank size: " << reactor_bank.size() << std::endl; + if (old_size < new_size) { for (auto i = 0; i < new_size; i++) { - auto add_conn = std::make_shared, Input>>(&load_balancer[i], &reactor_bank[i].get()->in, reactor_); - add_to_transaction(add_conn); + auto add_conn = std::make_shared, Input>>( + &load_balancer[i], &reactor_bank[i].get()->in, reactor_); + add_to_transaction(add_conn); } - commit_transaction(true); } - std::cout << "new bank size:" << reactor_bank.size() << std::endl; + commit_transaction(true); } friend LoadBalancer; }; - Inner __inner; + std::unique_ptr producer_; + std::unique_ptr load_balancer_; + std::vector> consumers_; + + Reaction scale_bank{"scale_bank", 1, this, + [this]() { this->_inner.reaction_1(this->scale, this->consumers_, load_balancer_->out); }}; + + Inner _inner; - Deployment(const std::string& name, Environment* env) : Reactor(name, env), __inner(this), - producer_(std::make_unique("producer", environment())), - load_balancer_(std::make_unique("load_balancer", environment())) { - std::cout << "creating instance of deployment" << std::endl; +public: + Deployment(const std::string& name, Environment* env) + : Reactor(name, env) + , _inner(this) + , producer_(std::make_unique("producer", environment())) + , load_balancer_(std::make_unique("load_balancer", environment())) { + std::cout << "creating instance of deployment" << '\n'; consumers_.reserve(4); - for (size_t __lf_idx = 0; __lf_idx < 4; __lf_idx++) { - std::string __lf_inst_name = "consumer_" + std::to_string(__lf_idx); - consumers_.push_back(std::make_unique(__lf_inst_name, environment(), __lf_idx)); + for (size_t _lf_idx = 0; _lf_idx < 4; _lf_idx++) { + std::string _lf_inst_name = "consumer_" + std::to_string(_lf_idx); + consumers_.push_back(std::make_unique(_lf_inst_name, environment(), _lf_idx)); } } ~Deployment() override = default; - Input scale{"scale", this}; + Input scale{"scale", this}; // NOLINT void assemble() override { - for (size_t __lf_idx = 0; __lf_idx < 4; __lf_idx++) { - environment()->draw_connection(load_balancer_->out[__lf_idx], consumers_[__lf_idx]->in, ConnectionProperties{}); + for (size_t _lf_idx = 0; _lf_idx < 4; _lf_idx++) { + environment()->draw_connection(load_balancer_->out[_lf_idx], consumers_[_lf_idx]->in, ConnectionProperties{}); environment()->draw_connection(producer_->value, load_balancer_->inbound, ConnectionProperties{}); } environment()->draw_connection(load_balancer_->scale_bank, scale, ConnectionProperties{}); @@ -86,9 +84,7 @@ class Inner: public MutableScope { } }; - auto main() -> int { - //srand(time(nullptr)); Environment env{4, true}; auto deployment = std::make_unique("c1", &env); env.optimize(); diff --git a/examples/multiport_mutation/producer.hh b/examples/multiport_mutation/producer.hh index 7a998cbb..d6416e9a 100644 --- a/examples/multiport_mutation/producer.hh +++ b/examples/multiport_mutation/producer.hh @@ -1,41 +1,42 @@ -// -// Created by tanneberger on 11/17/24. -// - -#ifndef PRODUCER_HH -#define PRODUCER_HH +#ifndef PRODUCER_HH // NOLINT +#define PRODUCER_HH // NOLINT #include using namespace reactor; using namespace std::chrono_literals; -class Producer : public Reactor { +class Producer final : public Reactor { // NOLINT private: Timer timer{"timer", this, 1s, 1s}; - Reaction r_timer{"r_timer", 1, this, [this]() { __lf_inner.reaction_1(this->value);}}; + Reaction r_timer{"r_timer", 1, this, [this]() { _lf_inner.reaction_1(this->value); }}; + + class Inner : public Scope { + unsigned int counter_ = 0; - class Inner: public Scope { - unsigned itr = 0; - [[maybe_unused]] const Inner& __lf_inner = *this; void reaction_1([[maybe_unused]] Output& out) { - std::cout << "producing value:" << itr << std::endl; - out.set(itr++); + std::cout << "producing value:" << counter_ << "\n"; + out.set(counter_++); } - explicit Inner(Reactor* reactor) : Scope(reactor) {} + + explicit Inner(Reactor* reactor) + : Scope(reactor) {} friend Producer; }; - Inner __lf_inner; + Inner _lf_inner; + public: - Producer(const std::string& name, Environment* env) : Reactor(name, env), __lf_inner(this) { - std::cout << "creating instance of producer" << std::endl; + Producer(const std::string& name, Environment* env) + : Reactor(name, env) + , _lf_inner(this) { + std::cout << "creating instance of producer\n"; } Producer() = delete; ~Producer() override = default; - Output value{"value", this}; + Output value{"value", this}; // NOLINT void assemble() override { r_timer.declare_trigger(&timer); @@ -43,4 +44,4 @@ public: } }; -#endif //PRODUCER_HH +#endif // PRODUCER_HH diff --git a/examples/ports/main.cc b/examples/ports/main.cc index d1dda5d1..cc164d85 100644 --- a/examples/ports/main.cc +++ b/examples/ports/main.cc @@ -5,7 +5,7 @@ using namespace reactor; using namespace std::chrono_literals; -class Trigger : public Reactor { +class Trigger final : public Reactor { private: Timer timer; Reaction r_timer{"r_timer", 1, this, [this]() { on_timer(); }}; @@ -25,7 +25,7 @@ class Trigger : public Reactor { void on_timer() { trigger.set(); } }; -class Counter : public Reactor { +class Counter final : public Reactor { private: int value_{0}; Reaction r_trigger{"r_trigger", 1, this, [this]() { on_trigger(); }}; @@ -49,7 +49,7 @@ class Counter : public Reactor { } }; -class Printer : public Reactor { +class Printer final : public Reactor { private: Reaction r_value{"r_value", 1, this, [this]() { this->on_value(); }}; @@ -67,7 +67,7 @@ class Printer : public Reactor { void on_value() { std::cout << this->name() << ": " << *value.get() << '\n'; } }; -class Adder : public Reactor { +class Adder final : public Reactor { private: Reaction r_add{"r_add", 1, this, [this]() { this->add(); }}; diff --git a/examples/power_train/main.cc b/examples/power_train/main.cc index 155c3501..7badae84 100644 --- a/examples/power_train/main.cc +++ b/examples/power_train/main.cc @@ -4,7 +4,7 @@ using namespace reactor; -class LeftPedal : public Reactor { +class LeftPedal final : public Reactor { public: // ports Output angle{"angle", this}; // NOLINT @@ -30,7 +30,7 @@ class LeftPedal : public Reactor { } }; -class RightPedal : public Reactor { +class RightPedal final : public Reactor { public: // ports Output angle{"angle", this}; // NOLINT @@ -60,7 +60,7 @@ class RightPedal : public Reactor { } }; -class BrakeControl : public Reactor { +class BrakeControl final : public Reactor { public: // ports Input angle{"angle", this}; // NOLINT @@ -81,7 +81,7 @@ class BrakeControl : public Reactor { } }; -class EngineControl : public Reactor { +class EngineControl final : public Reactor { public: // ports Input angle{"angle", this}; // NOLINT @@ -118,7 +118,7 @@ class EngineControl : public Reactor { } }; -class Brake : public Reactor { +class Brake final : public Reactor { public: // ports Input force{"force", this}; // NOLINT @@ -136,11 +136,11 @@ class Brake : public Reactor { void assemble() override { r1.declare_trigger(&force); } }; -class Engine : public Reactor { +class Engine final : public Reactor { public: // ports Input torque{"torque", this}; // NOLINT - Multiport control_input; + private: // reactions_ Reaction r1{"1", 1, this, [this]() { reaction_1(); }}; @@ -180,12 +180,3 @@ auto main() -> int { return 0; } - -class ReactionScope : public MutableScope { - void reaction_0() { - MutationChangeMultiportSize change_multiport_width{&this->self_->control_input, 6}; - this->add_to_transaction(&change_multiport_width); - - this->commit_transaction(); - } -}; diff --git a/examples/unit_tests_mutations/CMakeLists.txt b/examples/unit_tests_mutations/CMakeLists.txt deleted file mode 100644 index 0843149f..00000000 --- a/examples/unit_tests_mutations/CMakeLists.txt +++ /dev/null @@ -1,3 +0,0 @@ -add_executable(unit_tests_mutations main.cc) -target_link_libraries(unit_tests_mutations reactor-cpp) -add_dependencies(examples unit_tests_mutations) diff --git a/examples/unit_tests_mutations/main.cc b/examples/unit_tests_mutations/main.cc deleted file mode 100644 index 0066d705..00000000 --- a/examples/unit_tests_mutations/main.cc +++ /dev/null @@ -1,82 +0,0 @@ -#include - -#include "../../lib/mutation/multiport.cc" -#include -#include - -using namespace std::chrono_literals; - -class TestMultiport: public reactor::Reactor { - reactor::ModifableMultiport> test_multiport_{"modifable_multiports_"}; - reactor::Timer timer_{"timer", this, 1s}; - reactor::LogicalAction scale{"scale", this}; - reactor::Reaction trigger_reaction_{"trigger_reaction", 1, this, [this](){this->__inner.reaction_1(scale);}}; - reactor::Reaction test_reaction_{"test_reaction", 2, this, [this](){this->__inner.reaction_2(test_multiport_, scale);}}; - reactor::Reaction validate_reaction_{"validate_reaction", 3, this, [this](){this->__inner.reaction_3(test_multiport_);}}; -public: - -class Inner: public reactor::MutableScope { - int state = 0; - std::vector sizes = {4, 5, 6, 5, 4, 3}; - [[maybe_unused]] const Inner& __lf_inner = *this; -public: - - Inner(Reactor* reactor) : MutableScope(reactor) {} - - void reaction_1(reactor::LogicalAction& scale) { - int size = sizes[state]; - state = (state + 1) % sizes.size(); - std::cout << "set: " << size << std::endl; - scale.schedule(size); - } - - void reaction_2(reactor::ModifableMultiport>& test_multiport, reactor::LogicalAction& scale) { - reactor::ModifableMultiport>* temp = &test_multiport; - std::size_t new_size = *scale.get(); - - auto anti_dep = test_multiport[0].anti_dependencies(); - reactor::MutationChangeOutputMultiportSize change_size{temp, this->reactor_, anti_dep, new_size}; - add_to_transaction(&change_size); - - commit_transaction(); - } - - void reaction_3(reactor::ModifableMultiport>& test_multiport) { - for (auto i = 0; i < test_multiport.size(); i++) { - std::cout << test_multiport[i].fqn() << "/" << std::endl; - } - } - }; - - Inner __inner; - - TestMultiport(const std::string& name, reactor::Environment* env) : Reactor(name, env), __inner(this) { - std::cout << "creating instance of deployment" << std::endl; - - test_multiport_.reserve(4); - for (size_t _lf_idx = 0; _lf_idx < 4; _lf_idx++) { - std::string _lf_port_name = test_multiport_.name() + "_" + std::to_string(_lf_idx); - test_multiport_.emplace_back(_lf_port_name, this); - } - } - ~TestMultiport() override = default; - - void assemble() override { - trigger_reaction_.declare_trigger(&timer_); - trigger_reaction_.declare_schedulable_action(&scale); - test_reaction_.declare_trigger(&scale); - - } -}; - - -auto main() -> int { - // srand(time(nullptr)); - reactor::Environment env{4}; - auto test_multiport = std::make_unique("test_multiport", &env); - env.optimize(); - env.assemble(); - auto thread = env.startup(); - thread.join(); - return 0; -} diff --git a/include/reactor-cpp/environment.hh b/include/reactor-cpp/environment.hh index fdfb30b7..8e416ba1 100644 --- a/include/reactor-cpp/environment.hh +++ b/include/reactor-cpp/environment.hh @@ -103,16 +103,16 @@ public: template void remove_connection(Port* source, Port* sink) { if (top_environment_ == nullptr || top_environment_ == this) { log::Debug() << "remove connection: " << source->fqn() << " -/-> " << sink->fqn(); - auto properties = graph_.remove_edge(source, sink); + graph_.remove_edge(source, sink); } else { - return top_environment_->remove_connection(source, sink); + top_environment_->remove_connection(source, sink); } } void remove_top_level_reactor(Reactor* reactor) { auto elements_erased = top_level_reactors_.erase(reactor); if (elements_erased == 0) { - std::cout << "no elements erased" << std::endl; + std::cout << "no elements erased" << '\n'; } } diff --git a/include/reactor-cpp/graph.hh b/include/reactor-cpp/graph.hh index 08af8d65..739d8b33 100644 --- a/include/reactor-cpp/graph.hh +++ b/include/reactor-cpp/graph.hh @@ -9,6 +9,7 @@ #ifndef REACTOR_CPP_GRAPH_HH #define REACTOR_CPP_GRAPH_HH +#include #include #include #include @@ -64,16 +65,15 @@ public: } } - auto remove_edge(E source, E destinations) noexcept -> std::optional

{ + auto remove_edge(E source, E destinations) noexcept { if (graph_.find(source) == std::end(graph_)) { - return std::nullopt; - } else { - auto conns = std::find_if(std::begin(graph_[source]), std::end(graph_[source]), - [destinations](auto val) { return val.second == destinations; }); + return; + } + auto conns = std::find_if(std::begin(graph_[source]), std::end(graph_[source]), + [destinations](auto val) { return val.second == destinations; }); - if (conns != std::end(graph_[source])) { - graph_[source].erase(conns); - } + if (conns != std::end(graph_[source])) { + graph_[source].erase(conns); } } diff --git a/include/reactor-cpp/multiport.hh b/include/reactor-cpp/multiport.hh index d0aa4888..28d57bce 100644 --- a/include/reactor-cpp/multiport.hh +++ b/include/reactor-cpp/multiport.hh @@ -14,6 +14,7 @@ #include #include #include +#include #include #include "assert.hh" @@ -49,10 +50,10 @@ protected: void register_port(BasePort& port, size_t idx); public: - explicit BaseMultiport(const std::string& name) - : multiport_name_(name){}; + explicit BaseMultiport(std::string name) + : multiport_name_(std::move(name)){}; ~BaseMultiport() = default; - auto name() const -> std::string { return multiport_name_; } + [[nodiscard]] auto name() const -> std::string { return multiport_name_; } }; template class MutationChangeMultiportSize; @@ -82,14 +83,14 @@ public: auto operator[](std::size_t index) noexcept -> T& { return ports_[index]; } auto operator[](std::size_t index) const noexcept -> const T& { return ports_[index]; } - auto begin() noexcept -> iterator { return ports_.begin(); }; - auto begin() const noexcept -> const_iterator { return ports_.begin(); }; - auto cbegin() const noexcept -> const_iterator { return ports_.cbegin(); }; - auto end() noexcept -> iterator { return ports_.end(); }; - auto end() const noexcept -> const_iterator { return ports_.end(); }; - auto cend() const noexcept -> const_iterator { return ports_.cend(); }; + [[nodiscard]] auto begin() noexcept -> iterator { return ports_.begin(); }; + [[nodiscard]] auto begin() const noexcept -> const_iterator { return ports_.begin(); }; + [[nodiscard]] auto cbegin() const noexcept -> const_iterator { return ports_.cbegin(); }; + [[nodiscard]] auto end() noexcept -> iterator { return ports_.end(); }; + [[nodiscard]] auto end() const noexcept -> const_iterator { return ports_.end(); }; + [[nodiscard]] auto cend() const noexcept -> const_iterator { return ports_.cend(); }; - auto size() const noexcept -> size_type { return ports_.size(); }; + [[nodiscard]] auto size() const noexcept -> size_type { return ports_.size(); }; [[nodiscard]] auto empty() const noexcept -> bool { return ports_.empty(); }; [[nodiscard]] auto present_indices_unsorted() const noexcept -> std::vector { diff --git a/include/reactor-cpp/mutations.hh b/include/reactor-cpp/mutations.hh index a7fab5df..3aaa1eee 100644 --- a/include/reactor-cpp/mutations.hh +++ b/include/reactor-cpp/mutations.hh @@ -1,22 +1,30 @@ -#ifndef MUTATIONS_HH -#define MUTATIONS_HH +#ifndef REACTOR_CPP_MUTATIONS_HH +#define REACTOR_CPP_MUTATIONS_HH + +#include namespace reactor { class Reactor; class Environment; -enum MutationResult { +enum MutationResult : std::int8_t { Success = 0, NotMatchingBankSize = 1, }; class Mutation { public: + Mutation() = default; + Mutation(const Mutation& other) = default; + Mutation(Mutation&& other) = default; virtual ~Mutation() = default; + auto operator=(const Mutation& other) -> Mutation& = default; + auto operator=(Mutation&& other) -> Mutation& = default; + virtual auto run() -> MutationResult = 0; virtual auto rollback() -> MutationResult = 0; }; } // namespace reactor -#endif // MUTATIONS_HH +#endif // REACTOR_CPP_MUTATIONS_HH diff --git a/include/reactor-cpp/mutations/bank.hh b/include/reactor-cpp/mutations/bank.hh index f77fe040..4081b691 100644 --- a/include/reactor-cpp/mutations/bank.hh +++ b/include/reactor-cpp/mutations/bank.hh @@ -2,8 +2,8 @@ // Created by tanneberger on 11/18/24. // -#ifndef MUTATION_BANK_HH -#define MUTATION_BANK_HH +#ifndef REACTOR_CPP_MUTATIONS_BANK_HH +#define REACTOR_CPP_MUTATIONS_BANK_HH #include @@ -14,28 +14,38 @@ namespace reactor { class Reactor; class Environment; -template class MutationChangeBankSize : public reactor::Mutation { +template class MutationChangeBankSize final : public Mutation { std::vector* bank_ = nullptr; std::size_t desired_size_ = 0; std::size_t size_before_application_ = 0; Reactor* reactor_ = nullptr; - std::function create_lambda_; + std::function create_lambda_; - void change_size(std::size_t); + void change_size(std::size_t new_size); public: - MutationChangeBankSize(std::vector* bank, Reactor* reactor, std::size_t size, - std::function); MutationChangeBankSize() = default; - explicit MutationChangeBankSize(const std::vector& other) + MutationChangeBankSize(const MutationChangeBankSize& other) noexcept : bank_(other.bank_) , desired_size_(other.desired_size_) - , size_before_application_(other.size_before_application_) {} + , size_before_application_(other.size_before_application_) + , reactor_(other.reactor_) + , create_lambda_(other.create_lambda_){}; + MutationChangeBankSize(MutationChangeBankSize&& other) noexcept + : bank_(other.bank_) + , desired_size_(other.desired_size_) + , size_before_application_(other.size_before_application_) + , reactor_(other.reactor_) + , create_lambda_(other.create_lambda_){}; + explicit MutationChangeBankSize(std::vector* bank, Reactor* reactor, std::size_t size, + std::function create_lambda); ~MutationChangeBankSize() override = default; + auto operator=(const MutationChangeBankSize& other) -> MutationChangeBankSize& = default; + auto operator=(MutationChangeBankSize&& other) -> MutationChangeBankSize& = default; auto run() -> MutationResult override; auto rollback() -> MutationResult override; }; } // namespace reactor -#endif // MUTATION_BANK_HH +#endif // REACTOR_CPP_MUTATIONS_BANK_HH diff --git a/include/reactor-cpp/mutations/connection.hh b/include/reactor-cpp/mutations/connection.hh index 72a78235..25bb9b37 100644 --- a/include/reactor-cpp/mutations/connection.hh +++ b/include/reactor-cpp/mutations/connection.hh @@ -2,8 +2,8 @@ // Created by tanneberger on 11/18/24. // -#ifndef MUTATION_CONNECTION_HH -#define MUTATION_CONNECTION_HH +#ifndef REACTOR_CPP_MUTATIONS_CONNECTION_HH +#define REACTOR_CPP_MUTATIONS_CONNECTION_HH #include "../mutations.hh" @@ -19,18 +19,25 @@ private: Reactor* reactor_{}; public: - MutationAddConnection(A* source, B* sink, Reactor* reactor); + explicit MutationAddConnection(A* source, B* sink, Reactor* reactor); MutationAddConnection(const MutationAddConnection& other) : source_(other.source_) , sink_(other.sink_) , connection_(other.connection_) , reactor_(other.reactor_) {} + MutationAddConnection(MutationAddConnection&& other) noexcept + : source_(other.source_) + , sink_(other.sink_) + , connection_(other.connection_) + , reactor_(other.reactor_) {} MutationAddConnection() = default; ~MutationAddConnection() override = default; + auto operator=(const MutationAddConnection& other) -> MutationAddConnection& = default; + auto operator=(MutationAddConnection&& other) -> MutationAddConnection& = default; auto run() -> MutationResult override; auto rollback() -> MutationResult override; }; } // namespace reactor -#endif // MUTATION_CONNECTION_HH +#endif // REACTOR_CPP_MUTATIONS_CONNECTION_HH diff --git a/include/reactor-cpp/mutations/multiport.hh b/include/reactor-cpp/mutations/multiport.hh index da8e407e..268d6267 100644 --- a/include/reactor-cpp/mutations/multiport.hh +++ b/include/reactor-cpp/mutations/multiport.hh @@ -2,8 +2,8 @@ // Created by tanneberger on 11/11/24. // -#ifndef MUTATION_MULTIPORT_HH -#define MUTATION_MULTIPORT_HH +#ifndef REACTOR_CPP_MUTATIONS_MULTIPORT_HH +#define REACTOR_CPP_MUTATIONS_MULTIPORT_HH #include @@ -23,7 +23,7 @@ private: std::size_t size_before_application_ = 0; Reactor* reactor_{}; - void change_size(std::size_t); + void change_size(std::size_t new_size); public: MutationChangeOutputMultiportSize(ModifableMultiport>* multiport, Reactor* reactor, @@ -33,11 +33,17 @@ public: : multiport_(other.multiport_) , desired_size_(other.desired_size_) , size_before_application_(other.size_before_application_) {} + MutationChangeOutputMultiportSize(MutationChangeOutputMultiportSize&& other) noexcept + : multiport_(other.multiport_) + , desired_size_(other.desired_size_) + , size_before_application_(other.size_before_application_) {} ~MutationChangeOutputMultiportSize() override = default; + auto operator=(const MutationChangeOutputMultiportSize& other) -> MutationChangeOutputMultiportSize& = default; + auto operator=(MutationChangeOutputMultiportSize&& other) -> MutationChangeOutputMultiportSize& = default; auto run() -> MutationResult override; auto rollback() -> MutationResult override; }; } // namespace reactor -#endif // MUTATION_MULTIPORT_HH +#endif // REACTOR_CPP_MUTATIONS_MULTIPORT_HH diff --git a/include/reactor-cpp/port.hh b/include/reactor-cpp/port.hh index e5b3da56..ecb0b059 100644 --- a/include/reactor-cpp/port.hh +++ b/include/reactor-cpp/port.hh @@ -77,7 +77,7 @@ public: void set_inward_binding(BasePort* port) noexcept { if (port != nullptr) { std::cout << port->fqn() << "(" << port << ")" - << " --> " << this->fqn() << "(" << this << ")" << std::endl; + << " --> " << this->fqn() << "(" << this << ")" << '\n'; } inward_binding_ = port; @@ -116,11 +116,6 @@ public: friend class Scheduler; }; -inline auto operator==(const BasePort& a, const BasePort& b) -> bool { - bool equal = ((const ReactorElement&)a) == ((const ReactorElement&)b); - return equal; -} - template class Port : public BasePort { private: ImmutableValuePtr value_ptr_{nullptr}; @@ -189,7 +184,7 @@ public: Input(Input&&) = default; - ~Input() { std::cout << "Input port gets deallocated:" << this->fqn() << std::endl; } + ~Input() override { std::cout << "Input port gets deallocated:" << this->fqn() << "\n"; } }; template class Output : public Port { // NOLINT(cppcoreguidelines-special-member-functions) @@ -199,7 +194,7 @@ public: Output(Output&&) noexcept = default; - ~Output() { std::cout << "Output port gets deallocated: " << this->fqn() << std::endl; } + ~Output() override { std::cout << "Output port gets deallocated: " << this->fqn() << "\n"; } }; } // namespace reactor diff --git a/include/reactor-cpp/reaction.hh b/include/reactor-cpp/reaction.hh index 80246a28..e4cac716 100644 --- a/include/reactor-cpp/reaction.hh +++ b/include/reactor-cpp/reaction.hh @@ -27,7 +27,7 @@ private: std::set dependencies_; const int priority_ = -1; - unsigned int index_ = -1; + int index_ = -1; std::function body_{nullptr}; @@ -63,7 +63,7 @@ public: void startup() final {} void shutdown() final {} void trigger(); - void set_index(unsigned index); + void set_index(int index); template void set_deadline(Dur deadline, const std::function& handler) { set_deadline_impl(std::chrono::duration_cast(deadline), handler); diff --git a/include/reactor-cpp/scopes.hh b/include/reactor-cpp/scopes.hh index ff3712c6..fe1de9f4 100644 --- a/include/reactor-cpp/scopes.hh +++ b/include/reactor-cpp/scopes.hh @@ -6,8 +6,8 @@ * Tassilo Tanneberger */ -#ifndef REACTOR_CPP_SCOPS_HH -#define REACTOR_CPP_SCOPS_HH +#ifndef REACTOR_CPP_SCOPES_HH +#define REACTOR_CPP_SCOPES_HH #include "environment.hh" #include "logical_time.hh" @@ -18,20 +18,24 @@ namespace reactor { class Scope { private: - Reactor* reactor; + Reactor* reactor_; public: - Scope(Reactor* reactor) - : reactor(reactor) {} - - auto get_physical_time() const -> reactor::TimePoint { return reactor->get_physical_time(); } - auto get_tag() const -> reactor::Tag { return reactor->get_tag(); } - auto get_logical_time() const -> reactor::TimePoint { return reactor->get_logical_time(); } - auto get_microstep() const -> reactor::mstep_t { return reactor->get_microstep(); } - auto get_elapsed_logical_time() const -> reactor::Duration { return reactor->get_elapsed_logical_time(); } - auto get_elapsed_physical_time() const -> reactor::Duration { return reactor->get_elapsed_physical_time(); } - auto environment() const -> reactor::Environment* { return reactor->environment(); } - void request_stop() const { return environment()->sync_shutdown(); } + explicit Scope(Reactor* reactor) + : reactor_(reactor) {} + + [[nodiscard]] static auto get_physical_time() noexcept -> TimePoint { return Reactor::get_physical_time(); } + [[nodiscard]] auto get_tag() const noexcept -> Tag { return reactor_->get_tag(); } + [[nodiscard]] auto get_logical_time() const noexcept -> TimePoint { return reactor_->get_logical_time(); } + [[nodiscard]] auto get_microstep() const noexcept -> mstep_t { return reactor_->get_microstep(); } + [[nodiscard]] auto get_elapsed_logical_time() const noexcept -> Duration { + return reactor_->get_elapsed_logical_time(); + } + [[nodiscard]] auto get_elapsed_physical_time() const noexcept -> Duration { + return reactor_->get_elapsed_physical_time(); + } + [[nodiscard]] auto environment() const noexcept -> Environment* { return reactor_->environment(); } + void request_stop() const { environment()->sync_shutdown(); } }; class MutableScope : public Scope { @@ -45,7 +49,19 @@ public: , transaction_(reactor) , reactor_(reactor) , env_(reactor->environment()) {} + MutableScope(const MutableScope& other) + : Scope(other.reactor_) + , transaction_(other.transaction_) + , reactor_(other.reactor_) + , env_(other.env_) {} + MutableScope(MutableScope&& other) noexcept + : Scope(other.reactor_) + , transaction_(std::move(other.transaction_)) + , reactor_(other.reactor_) + , env_(other.env_) {} ~MutableScope() = default; + auto operator=(const MutableScope& other) -> MutableScope& = default; + auto operator=(MutableScope&& other) -> MutableScope& = default; void commit_transaction(bool recalculate = false); void add_to_transaction(const std::shared_ptr& mutation); @@ -53,4 +69,4 @@ public: } // namespace reactor -#endif // REACTOR_CPP_SCOPS_HH +#endif // REACTOR_CPP_SCOPES_HH diff --git a/include/reactor-cpp/transaction.hh b/include/reactor-cpp/transaction.hh index 3b06496b..b0ce287c 100644 --- a/include/reactor-cpp/transaction.hh +++ b/include/reactor-cpp/transaction.hh @@ -26,6 +26,10 @@ private: public: explicit Transaction(Reactor* parent); + Transaction(const Transaction& other) = default; + Transaction(Transaction&& other) = default; + auto operator=(const Transaction& other) -> Transaction& = default; + auto operator=(Transaction&& other) -> Transaction& = default; ~Transaction() = default; void push_back(const std::shared_ptr& mutation); diff --git a/lib/action.cc b/lib/action.cc index 04a52a41..ed8a43a7 100644 --- a/lib/action.cc +++ b/lib/action.cc @@ -29,7 +29,7 @@ void BaseAction::register_trigger(Reaction* reaction) { validate(this->container() == reaction->container(), "Action triggers must belong to the same reactor as the triggered " "reaction"); - [[maybe_unused]] bool result = triggers_.insert(reaction).second; + [[maybe_unused]] const bool result = triggers_.insert(reaction).second; reactor_assert(result); } @@ -40,7 +40,7 @@ void BaseAction::register_scheduler(Reaction* reaction) { // the reaction must belong to the same reactor as this action validate(this->container() == reaction->container(), "Scheduable actions must belong to the same reactor as the " "triggered reaction"); - [[maybe_unused]] bool result = schedulers_.insert(reaction).second; + [[maybe_unused]] const bool result = schedulers_.insert(reaction).second; reactor_assert(result); } @@ -62,8 +62,8 @@ void Timer::cleanup() noexcept { BaseAction::cleanup(); // schedule the timer again if (period_ != Duration::zero()) { - Tag now = Tag::from_logical_time(environment()->logical_time()); - Tag next = now.delay(period_); + const Tag now = Tag::from_logical_time(environment()->logical_time()); + const Tag next = now.delay(period_); environment()->scheduler()->schedule_sync(this, next); } } @@ -74,7 +74,7 @@ ShutdownTrigger::ShutdownTrigger(const std::string& name, Reactor* container) void ShutdownTrigger::setup() noexcept { BaseAction::setup(); } void ShutdownTrigger::shutdown() { - Tag tag = Tag::from_logical_time(environment()->logical_time()).delay(); + const Tag tag = Tag::from_logical_time(environment()->logical_time()).delay(); environment()->scheduler()->schedule_sync(this, tag); } diff --git a/lib/environment.cc b/lib/environment.cc index 9b86fd7a..ca08e670 100644 --- a/lib/environment.cc +++ b/lib/environment.cc @@ -41,7 +41,7 @@ Environment::Environment(const std::string& name, Environment* containing_enviro , top_environment_(containing_environment_->top_environment_) , scheduler_(this) , timeout_(containing_environment->timeout()) { - [[maybe_unused]] bool result = containing_environment->contained_environments_.insert(this).second; + [[maybe_unused]] const bool result = containing_environment->contained_environments_.insert(this).second; reactor_assert(result); } @@ -50,7 +50,7 @@ void Environment::register_reactor(Reactor* reactor) { validate(this->phase() == Phase::Construction || this->phase() == Phase::Mutation, "Reactors may only be registered during construction phase!"); validate(reactor->is_top_level(), "The environment may only contain top level reactors!"); - [[maybe_unused]] bool result = top_level_reactors_.insert(reactor).second; + [[maybe_unused]] const bool result = top_level_reactors_.insert(reactor).second; reactor_assert(result); } @@ -58,7 +58,7 @@ void Environment::register_input_action(BaseAction* action) { reactor_assert(action != nullptr); validate(this->phase() == Phase::Construction || this->phase() == Phase::Assembly, "Input actions may only be registered during construction or assembly phase!"); - [[maybe_unused]] bool result = input_actions_.insert(action).second; + [[maybe_unused]] const bool result = input_actions_.insert(action).second; reactor_assert(result); run_forever_ = true; } @@ -279,7 +279,7 @@ void Environment::calculate_indexes() { } log_.debug() << "Reactions sorted by index:"; - unsigned int index = 0; + int index = 0; while (!graph.empty()) { // find nodes with degree zero and assign index std::set degree_zero; diff --git a/lib/mutation/bank.cc b/lib/mutation/bank.cc index a358d88b..5ce7d635 100644 --- a/lib/mutation/bank.cc +++ b/lib/mutation/bank.cc @@ -6,12 +6,13 @@ #include "reactor-cpp/action.hh" template -reactor::MutationChangeBankSize::MutationChangeBankSize(std::vector* bank, Reactor* reactor, std::size_t size, - std::function create_lambda) +reactor::MutationChangeBankSize::MutationChangeBankSize( + std::vector* bank, Reactor* reactor, std::size_t size, + std::function create_lambda) : bank_(bank) , reactor_(reactor) , desired_size_(size) - , create_lambda_(create_lambda) {} + , create_lambda_(std::move(create_lambda)) {} template void reactor::MutationChangeBankSize::change_size(std::size_t new_size) { bank_->reserve(new_size); @@ -34,7 +35,7 @@ template void reactor::MutationChangeBankSize::change_size(std::siz bank_->push_back(create_lambda_(reactor_, current_size + i)); (*bank_)[bank_->size() - 1]->assemble(); } - std::cout << "created new reactors" << std::endl; + std::cout << "created new reactors" << '\n'; } } template auto reactor::MutationChangeBankSize::run() -> MutationResult { diff --git a/lib/reaction.cc b/lib/reaction.cc index 6b373948..20858170 100644 --- a/lib/reaction.cc +++ b/lib/reaction.cc @@ -125,7 +125,7 @@ void Reaction::set_deadline_impl(Duration deadline, const std::functiondeadline_handler_ = handler; } -void Reaction::set_index(unsigned index) { +void Reaction::set_index(int index) { validate(this->environment()->phase() == Phase::Assembly || this->environment()->phase() == Phase::Mutation, "Reaction indexes may only be set during assembly phase!"); this->index_ = index; diff --git a/lib/reactor.cc b/lib/reactor.cc index 08bc8863..b73263de 100644 --- a/lib/reactor.cc +++ b/lib/reactor.cc @@ -76,7 +76,7 @@ void Reactor::register_reactor([[maybe_unused]] Reactor* reactor) { if (std::find(std::begin(reactors_), std::end(reactors_), reactor) == std::end(reactors_)) { reactors_.push_back(reactor); } else { - std::cout << "duplicate insertion!" << std::endl; + std::cout << "duplicate insertion!" << '\n'; } //[[maybe_unused]] bool result = reactors_.insert(reactor).second; @@ -164,8 +164,8 @@ void Reactor::remove_inputs(BasePort* base_port) { }; void Reactor::remove_child_reactor(const Reactor* base_reactor) { - auto index = std::find_if(std::begin(reactors_), std::end(reactors_), - [base_reactor](const Reactor* other) { return base_reactor == other; }); + const auto index = std::find_if(std::begin(reactors_), std::end(reactors_), + [base_reactor](const Reactor* other) { return base_reactor == other; }); if (index != std::end(reactors_)) { reactors_.erase(index); diff --git a/lib/transaction.cc b/lib/transaction.cc index 3092b937..decb77b9 100644 --- a/lib/transaction.cc +++ b/lib/transaction.cc @@ -10,14 +10,14 @@ reactor::Transaction::Transaction(Reactor* parent) auto reactor::Transaction::execute(bool recalculate) -> MutationResult { this->environment_->start_mutation(); - for (auto mutation : mutations_) { + for (const auto& mutation : mutations_) { mutation->run(); } if (recalculate) { this->environment_->clear_dependency_graph(); - for (const auto* reactor : this->environment_->top_level_reactors()) { - this->environment_->build_dependency_graph((Reactor*)reactor); + for (auto* reactor : this->environment_->top_level_reactors()) { + this->environment_->build_dependency_graph(reactor); } this->environment_->calculate_indexes(); From e13f68cc1b6d5c3bc27947cb95ed26c300944c94 Mon Sep 17 00:00:00 2001 From: tanneberger Date: Wed, 18 Dec 2024 00:55:21 +0100 Subject: [PATCH 8/8] add clang-format version print --- .github/workflows/clang-format.yml | 1 + include/reactor-cpp/connection.hh | 12 ++++++------ include/reactor-cpp/multiport.hh | 4 ++-- include/reactor-cpp/mutations/bank.hh | 4 ++-- include/reactor-cpp/port.hh | 3 +-- include/reactor-cpp/time_barrier.hh | 4 ++-- include/reactor-cpp/value_ptr.hh | 20 ++++++++++---------- 7 files changed, 24 insertions(+), 24 deletions(-) diff --git a/.github/workflows/clang-format.yml b/.github/workflows/clang-format.yml index 9d9efd5e..a8c88927 100644 --- a/.github/workflows/clang-format.yml +++ b/.github/workflows/clang-format.yml @@ -10,5 +10,6 @@ jobs: - uses: actions/checkout@v4 - name: Analyze run: | + clang-format --version clang-format --dry-run --Werror -style=file $(find ./ -name '*.cc' -print) clang-format --dry-run --Werror -style=file $(find ./ -name '*.hh' -print) diff --git a/include/reactor-cpp/connection.hh b/include/reactor-cpp/connection.hh index 07000a6c..106738fc 100644 --- a/include/reactor-cpp/connection.hh +++ b/include/reactor-cpp/connection.hh @@ -143,8 +143,8 @@ public: }; } - auto acquire_tag(const Tag& tag, std::unique_lock& lock, const std::function& abort_waiting) - -> bool override { + auto acquire_tag(const Tag& tag, std::unique_lock& lock, + const std::function& abort_waiting) -> bool override { reactor_assert(lock.owns_lock()); log_.debug() << "downstream tries to acquire tag " << tag; @@ -210,8 +210,8 @@ public: }; } - auto acquire_tag(const Tag& tag, std::unique_lock& lock, const std::function& abort_waiting) - -> bool override { + auto acquire_tag(const Tag& tag, std::unique_lock& lock, + const std::function& abort_waiting) -> bool override { // Since this is a delayed connection, we can go back in time and need to // acquire the latest upstream tag that can create an event at the given // tag. We also need to consider that given a delay d and a tag g=(t, n), @@ -240,8 +240,8 @@ public: }; } - auto acquire_tag(const Tag& tag, std::unique_lock& lock, const std::function& abort_waiting) - -> bool override { + auto acquire_tag(const Tag& tag, std::unique_lock& lock, + const std::function& abort_waiting) -> bool override { this->log_.debug() << "downstream tries to acquire tag " << tag; return PhysicalTimeBarrier::acquire_tag(tag, lock, this->environment()->scheduler(), abort_waiting); } diff --git a/include/reactor-cpp/multiport.hh b/include/reactor-cpp/multiport.hh index 28d57bce..e2e42714 100644 --- a/include/reactor-cpp/multiport.hh +++ b/include/reactor-cpp/multiport.hh @@ -51,7 +51,7 @@ protected: public: explicit BaseMultiport(std::string name) - : multiport_name_(std::move(name)){}; + : multiport_name_(std::move(name)) {} ~BaseMultiport() = default; [[nodiscard]] auto name() const -> std::string { return multiport_name_; } }; @@ -73,7 +73,7 @@ public: using const_iterator = typename std::vector::const_iterator; explicit Multiport(const std::string& name) noexcept - : BaseMultiport(name){}; + : BaseMultiport(name) {} ~Multiport() noexcept = default; auto operator==(const Multiport& other) const noexcept -> bool { diff --git a/include/reactor-cpp/mutations/bank.hh b/include/reactor-cpp/mutations/bank.hh index 4081b691..f8cfc017 100644 --- a/include/reactor-cpp/mutations/bank.hh +++ b/include/reactor-cpp/mutations/bank.hh @@ -30,13 +30,13 @@ public: , desired_size_(other.desired_size_) , size_before_application_(other.size_before_application_) , reactor_(other.reactor_) - , create_lambda_(other.create_lambda_){}; + , create_lambda_(other.create_lambda_) {} MutationChangeBankSize(MutationChangeBankSize&& other) noexcept : bank_(other.bank_) , desired_size_(other.desired_size_) , size_before_application_(other.size_before_application_) , reactor_(other.reactor_) - , create_lambda_(other.create_lambda_){}; + , create_lambda_(other.create_lambda_) {} explicit MutationChangeBankSize(std::vector* bank, Reactor* reactor, std::size_t size, std::function create_lambda); ~MutationChangeBankSize() override = default; diff --git a/include/reactor-cpp/port.hh b/include/reactor-cpp/port.hh index ecb0b059..10627714 100644 --- a/include/reactor-cpp/port.hh +++ b/include/reactor-cpp/port.hh @@ -76,8 +76,7 @@ public: void register_antidependency(Reaction* reaction) noexcept; void set_inward_binding(BasePort* port) noexcept { if (port != nullptr) { - std::cout << port->fqn() << "(" << port << ")" - << " --> " << this->fqn() << "(" << this << ")" << '\n'; + std::cout << port->fqn() << "(" << port << ")" << " --> " << this->fqn() << "(" << this << ")" << '\n'; } inward_binding_ = port; diff --git a/include/reactor-cpp/time_barrier.hh b/include/reactor-cpp/time_barrier.hh index b69e2045..a5874106 100644 --- a/include/reactor-cpp/time_barrier.hh +++ b/include/reactor-cpp/time_barrier.hh @@ -80,8 +80,8 @@ public: // The caller must hold a lock on the scheduler mutex auto try_acquire_tag(const Tag& tag) { return tag <= released_time_; } - auto acquire_tag(const Tag& tag, std::unique_lock& lock, const std::function& abort_waiting) - -> bool { + auto acquire_tag(const Tag& tag, std::unique_lock& lock, + const std::function& abort_waiting) -> bool { if (try_acquire_tag(tag)) { return true; } diff --git a/include/reactor-cpp/value_ptr.hh b/include/reactor-cpp/value_ptr.hh index 7a8f6c75..a6d55089 100644 --- a/include/reactor-cpp/value_ptr.hh +++ b/include/reactor-cpp/value_ptr.hh @@ -517,23 +517,23 @@ public: // Comparison operators template -auto operator==(const MutableValuePtr& ptr1, const MutableValuePtr& ptr2) noexcept - -> bool { +auto operator==(const MutableValuePtr& ptr1, + const MutableValuePtr& ptr2) noexcept -> bool { return ptr1.get() == ptr2.get(); } template -auto operator==(const ImmutableValuePtr& ptr1, const ImmutableValuePtr& ptr2) noexcept - -> bool { +auto operator==(const ImmutableValuePtr& ptr1, + const ImmutableValuePtr& ptr2) noexcept -> bool { return ptr1.get() == ptr2.get(); } template -auto operator==(const ImmutableValuePtr& ptr1, const MutableValuePtr& ptr2) noexcept - -> bool { +auto operator==(const ImmutableValuePtr& ptr1, + const MutableValuePtr& ptr2) noexcept -> bool { return ptr1.get() == ptr2.get(); } template -auto operator==(const MutableValuePtr& ptr1, const ImmutableValuePtr& ptr2) noexcept - -> bool { +auto operator==(const MutableValuePtr& ptr1, + const ImmutableValuePtr& ptr2) noexcept -> bool { return ptr1.get() == ptr2.get(); } template @@ -554,8 +554,8 @@ auto operator==(std::nullptr_t, const ImmutableValuePtr& ptr1) no } template -auto operator!=(const MutableValuePtr& ptr1, const MutableValuePtr& ptr2) noexcept - -> bool { +auto operator!=(const MutableValuePtr& ptr1, + const MutableValuePtr& ptr2) noexcept -> bool { return ptr1.get() != ptr2.get(); }