/* * threads_actor.hpp * * Created on: Jun 11, 2021 * Author: erki */ #ifndef SKULLC_THREADS_ACTOR_HPP_ #define SKULLC_THREADS_ACTOR_HPP_ #include #include #include #include #include #include #include #include namespace Threads { template class Actor : public IActor { public: using value_type = std::variant; static_assert(std::is_default_constructible_v, "Ts must be default constructible."); static_assert(std::is_trivially_copyable_v, "Ts must be trivially copyable."); Actor() : IActor(sizeof(value_type)), signal_(this) {} ~Actor() override {} template struct Signal : Signallable { using parent = Actor; static_assert(std::is_convertible_v, "value_type cannot be constructed from T."); explicit Signal(parent* q) : q_(q) {} Signal(const Signal&) = default; Signal(Signal&&) = default; Signal& operator=(const Signal&) = default; Signal& operator=(Signal&&) = default; void emit(const T& data) override { parent::value_type to_send = data; q_->dispatchEvent(to_send); } BaseType_t emitFromIsr(const T& data) override { parent::value_type to_send = data; return q_->dispatchEventFromIsr(to_send); } private: parent* q_; }; template Signal getSignal() { static_assert(std::is_convertible_v, "value_type cannot be constructed from U."); return Signal(this); } template Signal* getAllocatedSignal() { static_assert(std::is_convertible_v, "value_type cannot be constructed from U."); return new Signal(this); } Signallable* getStaticSignal() { return &signal_; } void dispatchSignal(const char* data) final { dispatchImpl_(data); } private: struct Visitor_ { using parent = Actor; parent* q; Visitor_(parent* q) : q(q) {} template void operator()(const U& u) { CRTP* s = static_cast(q); s->onSignal(u); } }; void dispatchImpl_(const char* data) { const value_type* signal_data = reinterpret_cast(data); std::visit(Visitor_{this}, *signal_data); } Signal signal_; }; }// namespace Threads #endif /* SKULLC_THREADS_ACTOR_HPP_ */