22#include "Simo/compiler/BoostTypeIndexRuntimeCast.h"
23#include "Simo/compiler/Compiler.h"
30 virtual ~Port() =
default;
31 BOOST_TYPE_INDEX_REGISTER_RUNTIME_CLASS()
33 using TypeId = boost::typeindex::type_index;
36 template <
typename Self>
38 return boost::typeindex::type_id<Self>();
42 virtual bool connect(
Port* other) = 0;
44 [[nodiscard]] std::string_view name()
const {
return name_; }
45 void name(
const std::string_view name) { name_ = name; }
53template <
typename Payload>
60template <
typename Payload>
63 friend class InPort<Payload>;
65 enum struct PORT_STATE : std::uint8_t {
70 enum struct SEND_OUTCOME : std::uint8_t {
75 BOOST_TYPE_INDEX_REGISTER_RUNTIME_CLASS(
Port)
77 bool connect(
Port* other)
override;
79 SEND_OUTCOME send(Payload&& payload) {
80 storage = std::move(payload);
82 case PORT_STATE::EMPTY:
83 state_ = PORT_STATE::FILLED;
84 return SEND_OUTCOME::NEW;
85 case PORT_STATE::FILLED:
86 state_ = PORT_STATE::FILLED;
87 return SEND_OUTCOME::REPLACED;
92 void clear() { state_ = PORT_STATE::EMPTY; }
94 PORT_STATE state()
const {
return state_; }
98 PORT_STATE state_ = PORT_STATE::EMPTY;
105template <
typename Payload>
109 BOOST_TYPE_INDEX_REGISTER_RUNTIME_CLASS(
Port)
111 bool connect(
Port* other)
override;
113 Payload&& receive() {
114 SIMO_ASSERT(connecting_port !=
nullptr);
115 SIMO_ASSERT(connecting_port->state != OutPort<Payload>::PORT_STATE::EMPTY);
116 Payload out_p = std::move(connecting_port->storage);
117 connecting_port->clear();
118 return std::move(out_p);
122 if (connecting_port ==
nullptr ||
123 connecting_port->state() == OutPort<Payload>::PORT_STATE::EMPTY) {
126 return &connecting_port->storage;
129 void clear() { connecting_port->clear(); }
135template <
typename Payload>
136bool OutPort<Payload>::connect(
Port* other) {
140 auto* other_casted = boost::typeindex::runtime_cast<InPort<Payload>*>(other);
141 if (other_casted ==
nullptr) {
144 other_casted->connecting_port =
this;
148template <
typename Payload>
149bool InPort<Payload>::connect(Port* other) {
150 if (other->get_type_id() != get_type_id<Port>()) {
153 auto* other_casted = boost::typeindex::runtime_cast<OutPort<Payload>*>(other);
154 if (other_casted ==
nullptr) {
157 connecting_port = other_casted;
164template <
typename OutPayload,
typename InPayload>
167 BOOST_TYPE_INDEX_REGISTER_RUNTIME_CLASS(
Port)
168 bool connect(
Port* other)
override;
171 OutPort<OutPayload>::SEND_OUTCOME
send_out(OutPayload&& payload) {
172 return out_port.send(std::move(payload));
175 void clear_out() { out_port.clear(); }
177 void clear_in() { in_port.clear(); }
183 InPayload*
peek_in() {
return in_port.peek(); }
190template <
typename Payload>
191using BidirectionalPort = BidirectionalPortTyped<Payload, Payload>;
193template <
typename OutPayload,
typename InPayload>
194bool BidirectionalPortTyped<OutPayload, InPayload>::connect(
Port* other) {
195 auto* other_casted = boost::typeindex::runtime_cast<
196 BidirectionalPortTyped<InPayload, OutPayload>*>(other);
197 if (other_casted ==
nullptr) {
200 return out_port.connect(&other_casted->in_port) &&
201 in_port.connect(&other_casted->out_port);
Generic port. It offers the virtual method connect.
Definition Port.h:28
TypeId get_type_id(this Self &_)
Utility to the get type of class. Need the type at compile time.
Definition Port.h:37
InPayload && receive_in()
Extract the payload from the in port.
Definition Port.h:180
OutPort< OutPayload >::SEND_OUTCOME send_out(OutPayload &&payload)
Push a payload on the out port.
Definition Port.h:171
InPayload * peek_in()
Peek the payload from the in port.
Definition Port.h:183