SyDEVS  v0.7
Simulation-based analysis of complex systems involving people, devices, physical elements, and dynamic environments.
port.h
Go to the documentation of this file.
1 #pragma once
2 #ifndef SYDEVS_SYSTEMS_PORT_H_
3 #define SYDEVS_SYSTEMS_PORT_H_
4 
6 
7 namespace sydevs {
8 namespace systems {
9 
10 
17 template<data_mode dmode, data_goal dgoal, typename T>
18 class port_base
19 {
20 public:
21  port_base(const port_base&) = delete;
22  port_base& operator=(const port_base&) = delete;
23  port_base(port_base&&) = default;
24  port_base& operator=(port_base&&) = default;
25  virtual ~port_base() = default;
26 
27  const std::string& port_name() const;
28 
29  int64 port_index() const;
30  int64 node_index() const;
31 
33 
34 protected:
36 
37 private:
38  const std::string port_name_;
39  const int64 port_index_;
40  node_interface& external_interface_;
41 };
42 
43 
52 template<data_mode dmode, data_goal dgoal, typename T>
53 class port : public port_base<dmode, dgoal, T>
54 {
55 };
56 
57 
67 template<typename T>
68 class port<flow, input, T> : public port_base<flow, input, T>
69 {
70 public:
84  port(const std::string& port_name, const node_interface& external_interface);
85 
86  port(port&&) = default;
87  port& operator=(port&&) = default;
88  ~port() = default;
89 
90  const T& value() const;
91 
92  void print_on_use(bool flag = true) const;
93 };
94 
95 
105 template<typename T>
106 class port<message, input, T> : public port_base<message, input, T>
107 {
108 public:
122  port(const std::string& port_name, const node_interface& external_interface);
123 
124  port(port&&) = default;
125  port& operator=(port&&) = default;
126  ~port() = default;
127 
128  bool received() const;
129  const T& value() const;
130 
131  void print_on_use(bool flag = true) const;
132 };
133 
134 
144 template<typename T>
145 class port<message, output, T> : public port_base<message, output, T>
146 {
147 public:
161  port(const std::string& port_name, const node_interface& external_interface);
162 
163  port(port&&) = default;
164  port& operator=(port&&) = default;
165  ~port() = default;
166 
167  void send(const T& val);
168 
169  void print_on_use(bool flag = true) const;
170 };
171 
172 
182 template<typename T>
183 class port<flow, output, T> : public port_base<flow, output, T>
184 {
185 public:
199  port(const std::string& port_name, const node_interface& external_interface);
200 
201  port(port&&) = default;
202  port& operator=(port&&) = default;
203  ~port() = default;
204 
205  void assign(const T& val);
206 
207  void print_on_use(bool flag = true) const;
208 };
209 
210 
211 template<data_mode dmode, data_goal dgoal, typename T>
212 const std::string& port_base<dmode, dgoal, T>::port_name() const
213 {
214  return port_name_;
215 }
216 
217 
218 template<data_mode dmode, data_goal dgoal, typename T>
220 {
221  return port_index_;
222 }
223 
224 
225 template<data_mode dmode, data_goal dgoal, typename T>
227 {
228  return external_interface_.node_index();
229 }
230 
231 
232 template<data_mode dmode, data_goal dgoal, typename T>
234 {
235  return external_interface_;
236 }
237 
238 
239 template<data_mode dmode, data_goal dgoal, typename T>
240 port_base<dmode, dgoal, T>::port_base(const std::string& port_name, int64 port_index, node_interface& external_interface)
241  : port_name_(port_name)
242  , port_index_(port_index)
243  , external_interface_(external_interface)
244 {
246  const auto& full_node_name = const_cast<node_interface&>(this->external_interface()).full_name();
247  throw std::logic_error("Invalid data type for port (" + this->port_name() + ") " +
248  "of node (" + full_node_name + ")");
249  }
250 }
251 
252 
253 template<typename T>
254 port<flow, input, T>::port(const std::string& port_name, const node_interface& external_interface)
255  : port_base<flow, input, T>(
256  port_name,
257  const_cast<node_interface&>(external_interface).add_flow_input_port(port_name),
258  const_cast<node_interface&>(external_interface))
259 {
260 }
261 
262 
263 template<typename T>
265 {
266  if (!this->external_interface().active()) {
267  const auto& full_node_name = const_cast<node_interface&>(this->external_interface()).full_name();
268  throw std::logic_error("Attempt to get value on flow input port (" + this->port_name() + ") " +
269  "of inactive node (" + full_node_name + ")");
270  }
271  const auto& val = const_cast<node_interface&>(this->external_interface()).flow_input_port_value(this->port_index());
272  return const_cast<const T&>(val.template dereference<T>());
273 }
274 
275 
276 template<typename T>
278 {
279  auto tostring_func = flag ? tostring_converter<T>() : nullptr;
280  const_cast<node_interface&>(this->external_interface()).set_flow_input_printable(this->port_index(), tostring_func);
281 }
282 
283 
284 template<typename T>
285 port<message, input, T>::port(const std::string& port_name, const node_interface& external_interface)
286  : port_base<message, input, T>(
287  port_name,
288  const_cast<node_interface&>(external_interface).add_message_input_port(port_name),
289  const_cast<node_interface&>(external_interface))
290 {
291 }
292 
293 
294 template<typename T>
296 {
297  if (!this->external_interface().active()) {
298  const auto& full_node_name = const_cast<node_interface&>(this->external_interface()).full_name();
299  throw std::logic_error("Attempt to check message input port (" + this->port_name() + ") " +
300  "of inactive node (" + full_node_name + ")");
301  }
302  if (this->external_interface().dmode() != message || this->external_interface().dgoal() != input) {
303  const auto& full_node_name = const_cast<node_interface&>(this->external_interface()).full_name();
304  throw std::logic_error("Attempt to check message input port (" + this->port_name() + ") " +
305  "of node (" + full_node_name + ") outside of unplanned event");
306  }
307  return const_cast<node_interface&>(this->external_interface()).message_input_port_index() == this->port_index();
308 }
309 
310 
311 template<typename T>
313 {
314  if (!this->external_interface().active()) {
315  const auto& full_node_name = const_cast<node_interface&>(this->external_interface()).full_name();
316  throw std::logic_error("Attempt to get value on message input port (" + this->port_name() + ") " +
317  "of inactive node (" + full_node_name + ")");
318  }
319  if (this->external_interface().dmode() != message || this->external_interface().dgoal() != input) {
320  const auto& full_node_name = const_cast<node_interface&>(this->external_interface()).full_name();
321  throw std::logic_error("Attempt to get value on message input port (" + this->port_name() + ") " +
322  "of node (" + full_node_name + ") outside of unplanned event");
323  }
324  if (const_cast<node_interface&>(this->external_interface()).message_input_port_index() != this->port_index()) {
325  const auto& full_node_name = const_cast<node_interface&>(this->external_interface()).full_name();
326  throw std::logic_error("Attempt to get value on message input port (" + this->port_name() + ") " +
327  "of node (" + full_node_name + "), which was not the port that received the message.");
328  }
329  const auto& val = const_cast<node_interface&>(this->external_interface()).message_input_port_value(this->port_index());
330  return const_cast<const T&>(val.template dereference<T>());
331 }
332 
333 
334 template<typename T>
336 {
337  auto tostring_func = flag ? tostring_converter<T>() : nullptr;
338  const_cast<node_interface&>(this->external_interface()).set_message_input_printable(this->port_index(), tostring_func);
339 }
340 
341 
342 template<typename T>
343 port<message, output, T>::port(const std::string& port_name, const node_interface& external_interface)
344  : port_base<message, output, T>(
345  port_name,
346  const_cast<node_interface&>(external_interface).add_message_output_port(port_name),
347  const_cast<node_interface&>(external_interface))
348 {
349 }
350 
351 
352 template<typename T>
354 {
355  if (!this->external_interface().active()) {
356  const auto& full_node_name = const_cast<node_interface&>(this->external_interface()).full_name();
357  throw std::logic_error("Attempt to send value on message output port (" + this->port_name() + ") " +
358  "of inactive node (" + full_node_name + ")");
359  }
360  if (this->external_interface().dmode() != message || this->external_interface().dgoal() != output) {
361  const auto& full_node_name = const_cast<node_interface&>(this->external_interface()).full_name();
362  throw std::logic_error("Attempt to send value on message output port (" + this->port_name() + ") " +
363  "of node (" + full_node_name + ") outside of planned event");
364  }
365  const_cast<node_interface&>(this->external_interface()).append_message_output(this->port_index(), qualified_type<T>::copy(val));
366 }
367 
368 
369 template<typename T>
371 {
372  auto tostring_func = flag ? tostring_converter<T>() : nullptr;
373  const_cast<node_interface&>(this->external_interface()).set_message_output_printable(this->port_index(), tostring_func);
374 }
375 
376 
377 template<typename T>
378 port<flow, output, T>::port(const std::string& port_name, const node_interface& external_interface)
379  : port_base<flow, output, T>(
380  port_name,
381  const_cast<node_interface&>(external_interface).add_flow_output_port(port_name),
382  const_cast<node_interface&>(external_interface))
383 {
384 }
385 
386 
387 template<typename T>
389 {
390  if (!this->external_interface().active()) {
391  const auto& full_node_name = const_cast<node_interface&>(this->external_interface()).full_name();
392  throw std::logic_error("Attempt to assign value on flow output port (" + this->port_name() + ") " +
393  "of inactive node (" + full_node_name + ")");
394  }
395  if (this->external_interface().dmode() != flow) {
396  const auto& full_node_name = const_cast<node_interface&>(this->external_interface()).full_name();
397  throw std::logic_error("Attempt to assign value on flow output port (" + this->port_name() + ") " +
398  "of node (" + full_node_name + ") outside of initialization or finalization event");
399  }
400  const_cast<node_interface&>(this->external_interface()).assign_flow_output(this->port_index(), qualified_type<T>::copy(val));
401 }
402 
403 
404 template<typename T>
406 {
407  auto tostring_func = flag ? tostring_converter<T>() : nullptr;
408  const_cast<node_interface&>(this->external_interface()).set_flow_output_printable(this->port_index(), tostring_func);
409 }
410 
411 
412 } // namespace
413 } // namespace
414 
415 #endif
Definition: node_interface.h:17
port & operator=(port &&)=default
Move assignment.
port(port &&)=default
Move constructor.
port & operator=(port &&)=default
Move assignment.
port(port &&)=default
Move constructor.
port(port &&)=default
Move constructor.
port & operator=(port &&)=default
Move assignment.
port & operator=(port &&)=default
Move assignment.
port(port &&)=default
Move constructor.
A base class template for all port classes.
Definition: port.h:19
port_base(port_base &&)=default
Move constructor.
port_base & operator=(const port_base &)=delete
No copy assignment.
const node_interface & external_interface() const
Returns the encomassing node_interface object.
Definition: port.h:233
port_base & operator=(port_base &&)=default
Move assignment.
const std::string & port_name() const
Returns the name of the port.
Definition: port.h:212
int64 node_index() const
Returns the index of the node within the encompassing node_structure object.
Definition: port.h:226
int64 port_index() const
Returns the index of the port within the encompassing node_interface object.
Definition: port.h:219
port_base(const std::string &port_name, int64 port_index, node_interface &external_interface)
Definition: port.h:240
port_base(const port_base &)=delete
No copy constructor.
virtual ~port_base()=default
Destructor.
A generic port class template declaration.
Definition: port.h:54
const auto message
Equivalent to data_mode::message.
Definition: data_mode.h:23
const auto output
Equivalent to data_goal::output.
Definition: data_goal.h:22
const auto input
Equivalent to data_goal::input.
Definition: data_goal.h:21
const auto flow
Equivalent to data_mode::flow.
Definition: data_mode.h:22
Definition: arraynd.h:8
int64_t int64
Definition: number_types.h:15
Definition: qualified_type.h:24
static pointer copy(const T &X)
If T is a qualified type, returns a deep copy of X.
Definition: qualified_type.h:174