/* * threads_actor_output.hpp * * Created on: Oct 24, 2021 * Author: erki */ #ifndef SKULLC_THREADS_ACTOR_OUTPUT_HPP_ #define SKULLC_THREADS_ACTOR_OUTPUT_HPP_ #include #include #include #include namespace Threads { template class ActorOutput { private: using signal_variant = std::variant*...>; std::array stored_signals_; public: ActorOutput() = default; ActorOutput(const ActorOutput&) = delete; ActorOutput(ActorOutput&&) = delete; ActorOutput& operator=(const ActorOutput&) = delete; ActorOutput& operator=(ActorOutput&&) = delete; using connection_type = std::optional; template connection_type addConnection(Signallable* signal) { static_assert(std::disjunction_v...>, "T is not a member of Ts."); for (auto it = stored_signals_.begin(); it != stored_signals_.end(); ++it) { auto& storage = *it; if (std::get_if(&storage)) { storage = signal_variant{signal}; return it; } } return std::nullopt; } bool removeConnection(connection_type& connection) { if (!connection) return true; for (auto it = stored_signals_.begin(); it != stored_signals_.end(); ++it) { if (it == *connection) { delete *it; *it = std::monostate{}; return true; } } return false; } protected: template void emitOutput(const T& data) { static_assert(std::disjunction_v...>, "T is not a member of Ts."); for (auto& s : stored_signals_) { if (auto** signal = std::get_if*>(&s)) (*signal)->emit(data); } } template void emitOutputFromIsr(const T& data) { static_assert(std::disjunction_v...>, "T is not a member of Ts."); for (auto& s : stored_signals_) { if (auto** signal = std::get_if*>(&s)) (*signal)->emitFromIsr(data); } } }; template auto connectActors(Sender* sender, Receiver* receiver) { auto* signal = receiver->template getAllocatedSignal(); return sender->addConnection(signal); } template auto connectActors(Sender& sender, Receiver& receiver) { auto* signal = receiver.template getAllocatedSignal(); return sender.addConnection(signal); } }// namespace Threads #endif// SKULLC_THREADS_ACTOR_OUTPUT_HPP_