.. _program_listing_file_lib_port.cc: Program Listing for File port.cc ================================ |exhale_lsh| :ref:`Return to documentation for file ` (``lib/port.cc``) .. |exhale_lsh| unicode:: U+021B0 .. UPWARDS ARROW WITH TIP LEFTWARDS .. code-block:: cpp /* * Copyright (C) 2019 TU Dresden * All rights reserved. * * Authors: * Christian Menard */ #include "reactor-cpp/port.hh" #include "reactor-cpp/assert.hh" #include "reactor-cpp/environment.hh" #include "reactor-cpp/reaction.hh" namespace reactor { void BasePort::base_bind_to(BasePort* port) { reactor_assert(port != nullptr); reactor_assert(this->environment() == port->environment()); // NOLINT validate(!port->has_inward_binding(), "Ports may only be connected once"); validate(!port->has_anti_dependencies(), "Ports with anti dependencies may not be connected to other ports"); assert_phase(this, Environment::Phase::Assembly); if (this->is_input() && port->is_input()) { validate(this->container() == port->container()->container(), "An input port A may only be bound to another input port B if B is contained by a reactor that in turn is " "contained by the reactor of A"); } else if (this->is_input() && port->is_output()) { validate( this->container() == port->container(), "An input port A may only be bound directly to an output port B if A and B are contained by the same reactor."); } else if (this->is_output() && port->is_input()) { validate(this->container()->container() == port->container()->container(), "An output port can only be bound to an input port if both ports belong to reactors in the same " "hierarichal level"); } else if (this->is_output() && port->is_output()) { validate(this->container()->container() == port->container(), "An output port A may only be bound to another output port B if A is contained by a reactor that in turn " "is contained by the reactor of B"); } else { throw std::runtime_error("invalid connection"); } port->inward_binding_ = this; reactor_assert(this->outward_bindings_.insert(port).second); } void BasePort::register_dependency(Reaction* reaction, bool is_trigger) noexcept { reactor_assert(reaction != nullptr); reactor_assert(this->environment() == reaction->environment()); // NOLINT validate(!this->has_outward_bindings(), "Dependencies may no be declared on ports with an outward binding!"); assert_phase(this, Environment::Phase::Assembly); if (this->is_input()) { validate(this->container() == reaction->container(), "Dependent input ports must belong to the same reactor as the " "reaction"); } else { validate(this->container()->container() == reaction->container(), "Dependent output ports must belong to a contained reactor"); } reactor_assert(dependencies_.insert(reaction).second); if (is_trigger) { reactor_assert(triggers_.insert(reaction).second); } } void BasePort::register_antidependency(Reaction* reaction) noexcept { reactor_assert(reaction != nullptr); reactor_assert(this->environment() == reaction->environment()); // NOLINT validate(!this->has_inward_binding(), "Antidependencies may no be declared on ports with an inward binding!"); assert_phase(this, Environment::Phase::Assembly); if (this->is_output()) { validate(this->container() == reaction->container(), "Antidependent output ports must belong to the same reactor as " "the reaction"); } else { validate(this->container()->container() == reaction->container(), "Antidependent input ports must belong to a contained reactor"); } reactor_assert(anti_dependencies_.insert(reaction).second); } [[maybe_unused]] auto Port::typed_outward_bindings() const noexcept -> const std::set*>& { // this is undefined behavior and should be changed return reinterpret_cast*>&>(outward_bindings()); // NOLINT C++20 std::bit_cast } auto Port::typed_inward_binding() const noexcept -> Port* { // we can use a reinterpret cast here since we know that this port is always // connected with another Port. return reinterpret_cast*>(inward_binding()); // NOLINT } void Port::set() { validate(!has_inward_binding(), "set() may only be called on a ports that do not have an inward " "binding!"); auto* scheduler = environment()->scheduler(); scheduler->set_port(this); this->present_ = true; } } // namespace reactor