2 #ifndef SYDEVS_SYSTEMS_COLLECTION_NODE_H_
3 #define SYDEVS_SYSTEMS_COLLECTION_NODE_H_
54 template<
typename AgentID,
typename Node>
126 template<
typename AgentNode>
192 timer& prototype_ET()
const;
196 template<data_mode dmode, data_goal dgoal,
typename T>
199 Node& handle_agent_planned_event(
int64 agent_index);
200 void erase_removed_agents();
203 std::string agent_name_from_id(
qualified_type<T> agent_id_type,
const AgentID& agent_id);
207 void adopt_component_print_flags(
const system_node& node)
const;
209 virtual duration macro_initialization_event() = 0;
211 virtual duration micro_planned_event(
const AgentID& agent_id,
duration elapsed_dt) = 0;
213 virtual void macro_finalization_event(
duration elapsed_dt) = 0;
216 std::map<AgentID, int64> agent_indices_;
217 std::map<int64, AgentID> agent_ids_;
218 std::map<int64, std::unique_ptr<Node>> agents_;
219 std::set<int64> removed_indices_;
229 template<
typename AgentID,
typename Node>
253 template<
typename AgentID,
typename Node>
277 template<
typename AgentID,
typename Node>
283 const AgentID* operator->()
const;
294 const_iterator(
const typename std::map<AgentID, int64>::const_iterator& iter);
296 typename std::map<AgentID, int64>::const_iterator iter_;
302 template<
typename AgentID,
typename Node>
305 , prototype(
"prototype", prototype_context())
306 , internal_context_(&const_cast<
node_interface&>(external_interface()),
314 , initialized_(false)
321 template<
typename AgentID,
typename Node>
324 external_IO().print_on_elapsed_duration(flag);
328 template<
typename AgentID,
typename Node>
331 external_IO().print_on_planned_duration(flag);
335 template<
typename AgentID,
typename Node>
338 if (initialized_)
throw std::logic_error(
"Attempt to initialize collection node (" + full_name() +
") more than once");
339 auto& current_t = event_time().t();
342 external_IO().print_event(
"macro-initialization");
344 auto dt = macro_initialization_event();
346 prototype_IO().clear_flow_inputs();
347 prototype_IO().clear_message_input();
348 prototype_IO().clear_flow_outputs();
349 auto macro_planned_dt = scale_planned_dt(dt);
350 if (macro_planned_dt.finite()) {
351 t_queue_.plan_event(macro_event_id, macro_planned_dt);
354 t_cache_.retain_event(macro_event_id, time_precision());
356 auto planned_dt = t_queue_.imminent_duration();
357 external_IO().print_planned_duration(planned_dt);
359 erase_removed_agents();
364 template<
typename AgentID,
typename Node>
367 auto& current_t = event_time().t();
368 t_queue_.advance_time(current_t);
369 t_cache_.advance_time(current_t);
370 external_IO().print_event(
"macro-unplanned");
371 external_IO().print_elapsed_duration(elapsed_dt);
373 auto dt = macro_unplanned_event(elapsed_dt);
375 prototype_IO().clear_flow_inputs();
376 prototype_IO().clear_message_input();
377 prototype_IO().clear_flow_outputs();
378 auto macro_planned_dt = scale_planned_dt(dt);
379 if (macro_planned_dt.finite()) {
380 t_queue_.plan_event(macro_event_id, macro_planned_dt);
383 t_queue_.cancel_event(macro_event_id);
386 t_cache_.retain_event(macro_event_id, time_precision());
388 auto planned_dt = t_queue_.imminent_duration();
389 external_IO().print_planned_duration(planned_dt);
390 erase_removed_agents();
395 template<
typename AgentID,
typename Node>
398 auto& current_t = event_time().t();
399 t_queue_.advance_time(current_t);
400 t_cache_.advance_time(current_t);
401 if (t_queue_.imminent_duration() != 0
_s)
throw std::logic_error(
"Unexpected error while advancing time to that of next planned event");
402 int64 agent_index = *std::begin(t_queue_.imminent_event_ids());
403 if (agent_index < macro_event_id) {
406 auto& agent = handle_agent_planned_event(agent_index);
407 int64 list_size = agent_IO(agent).message_output_list_size();
408 const auto& agent_id = agent_ids_[agent_index];
409 auto micro_elapsed_dt = elapsed_dt;
410 for (
int64 list_index = 0; list_index < list_size; ++list_index) {
411 event_time().advance();
412 int64 port_index = agent_IO(agent).message_output_index(list_index);
413 const auto& val = agent_IO(agent).message_output_value(list_index);
414 external_IO().print_event(
"micro-planned");
415 external_IO().print_elapsed_duration(micro_elapsed_dt);
416 prototype_IO().append_message_output(port_index, val);
418 auto dt = micro_planned_event(agent_id, micro_elapsed_dt);
420 prototype_IO().clear_flow_inputs();
421 prototype_IO().clear_message_input();
422 prototype_IO().clear_message_outputs();
423 prototype_IO().clear_flow_outputs();
424 auto macro_planned_dt = scale_planned_dt(dt);
425 external_IO().print_planned_duration(macro_planned_dt);
426 micro_elapsed_dt -= micro_elapsed_dt;
427 if (macro_planned_dt.finite()) {
428 t_queue_.plan_event(macro_event_id, macro_planned_dt);
431 t_queue_.cancel_event(macro_event_id);
434 t_cache_.retain_event(macro_event_id, time_precision());
437 agent_IO(agent).clear_message_outputs();
442 external_IO().print_event(
"macro-planned");
443 external_IO().print_elapsed_duration(elapsed_dt);
445 auto dt = macro_planned_event(elapsed_dt);
447 prototype_IO().clear_flow_inputs();
448 prototype_IO().clear_message_input();
449 prototype_IO().clear_flow_outputs();
450 auto macro_planned_dt = scale_planned_dt(dt);
451 external_IO().print_planned_duration(macro_planned_dt);
452 if (macro_planned_dt.finite()) {
453 t_queue_.plan_event(macro_event_id, macro_planned_dt);
456 t_queue_.pop_imminent_event(macro_event_id);
459 t_cache_.retain_event(macro_event_id, time_precision());
462 auto planned_dt = t_queue_.imminent_duration();
463 erase_removed_agents();
468 template<
typename AgentID,
typename Node>
471 if (finalized_)
throw std::logic_error(
"Attempt to finalize collection node (" + full_name() +
") more than once");
472 auto& current_t = event_time().t();
473 t_queue_.advance_time(current_t);
474 t_cache_.advance_time(current_t);
475 external_IO().print_event(
"macro-finalization");
476 external_IO().print_elapsed_duration(elapsed_dt);
478 macro_finalization_event(elapsed_dt);
479 while (agent_count() > 0) {
480 auto agent_id = *agent_begin();
481 remove_agent(agent_id);
484 erase_removed_agents();
489 template<
typename AgentID,
typename Node>
493 validate_prototype_port(prototype_port);
494 return prototype_port.
port_index() == prototype_IO().message_output_index(0);
498 template<
typename AgentID,
typename Node>
502 validate_prototype_port(prototype_port);
507 template<
typename AgentID,
typename Node>
511 validate_prototype_port(prototype_port);
512 if (prototype_IO().message_input_port_index() != -1) {
513 throw std::logic_error(
"Attempt to access message input port (" + prototype_port.
port_name() +
"), " +
514 "but another message input port of prototype agent (" + prototype.full_name() +
") " +
515 "has already been accessed");
524 template<
typename AgentID,
typename Node>
528 validate_prototype_port(prototype_port);
529 if (prototype_port.
port_index() != prototype_IO().message_output_index(0)) {
530 throw std::logic_error(
"Attempt to access message output port (" + prototype_port.
port_name() +
"), " +
531 "which is not the port of prototype agent (" + prototype.full_name() +
") " +
532 "on which the current message is being transmitted");
534 auto& val = prototype_IO().message_output_value(0);
535 return const_cast<const T&
>(val.template dereference<T>());
539 template<
typename AgentID,
typename Node>
543 validate_prototype_port(prototype_port);
544 auto& val = prototype_IO().flow_output_port_value(prototype_port.
port_index());
545 return const_cast<const T&
>(val.template dereference<T>());
549 template<
typename AgentID,
typename Node>
552 create_agent<Node>(agent_id);
556 template<
typename AgentID,
typename Node>
557 template<
typename AgentNode>
560 static_assert(std::is_base_of<Node, AgentNode>::value,
"AgentNode must inherit from Node");
561 if (prototype.node_dmode() ==
flow) {
562 throw std::logic_error(
"Attempt to use \"create_agent\" to create a flow node agent of a collection node (" + full_name() +
"); use \"invoke_agent\" instead");
564 event_time().advance();
566 std::unique_ptr<Node> agent_ptr(
new AgentNode(agent_name, internal_context_));
567 auto& agent = *agent_ptr;
568 agent.adopt_print_flags(prototype);
569 if (agent_exists(agent_id)) {
570 throw std::logic_error(
"Created agent (" + agent.full_name() +
") already exists.");
572 int64 agent_index = agent.node_index();
573 agent_indices_[agent_id] = agent_index;
574 agent_ids_[agent_index] = agent_id;
575 agents_[agent_index] = std::move(agent_ptr);
576 agent_IO(agent).print_event(
"initialization");
577 int64 missing_input = prototype_IO().missing_flow_input();
578 if (missing_input != -1) {
579 throw std::logic_error(
"Flow input port (" + agent_IO(agent).flow_input_port_name(missing_input) +
") " +
580 "of created agent (" + agent.full_name() +
") has no value");
582 auto input_port_count = prototype_IO().flow_input_port_count();
583 for (
int64 port_index = 0; port_index < input_port_count; ++port_index) {
584 const auto& flow_input_val = prototype_IO().flow_input_port_value(port_index);
585 agent_IO(agent).assign_flow_input(port_index, flow_input_val);
586 agent_IO(agent).print_flow_input(port_index);
591 planned_dt = agent.process_initialization_event();
593 catch (
const std::exception& e) {
594 prototype_ET() =
timer(prototype_ET().cumulative_duration() + agent.event_timer().cumulative_duration());
597 agent_IO(agent).deactivate();
598 if (planned_dt.finite()) {
599 t_queue_.plan_event(agent_index, planned_dt);
601 if (agent.time_precision() !=
no_scale) {
602 t_cache_.retain_event(agent_index, agent.time_precision());
607 template<
typename AgentID,
typename Node>
610 if (prototype.node_dmode() ==
flow) {
611 throw std::logic_error(
"Attempt to use \"affect_agent\" to affect a flow node agent of a collection node (" + full_name() +
"); use \"invoke_agent\" instead");
613 event_time().advance();
614 auto agent_iter = agent_indices_.find(agent_id);
615 if (agent_iter == std::end(agent_indices_)) {
616 throw std::logic_error(
"Attempt to affect agent (" + full_name() +
"." +
tostring(agent_id) +
") that does not exist");
618 int64 agent_index = agent_iter->second;
619 auto& agent = *
dynamic_cast<Node*
>(&internal_structure().node(agent_index));
620 int64 port_index = prototype_IO().message_input_port_index();
621 if (port_index == -1) {
622 throw std::logic_error(
"Attempt to affect agent (" + agent.full_name() +
"), " +
623 "but none of the prototype's message input ports have been accessed");
625 const auto& val = prototype_IO().message_input_port_value(port_index);
627 throw std::logic_error(
"Attempt to affect agent (" + agent.full_name() +
"), " +
628 "but none of the prototype's message input ports have been assigned a value");
630 agent_IO(agent).print_event(
"unplanned");
631 agent_IO(agent).set_message_input(port_index, val);
632 agent_IO(agent).print_message_input(port_index);
634 if (agent.time_precision() !=
no_scale) {
635 elapsed_dt = t_cache_.duration_since(agent_index).fixed_at(agent.time_precision());
640 planned_dt = agent.process_unplanned_event(elapsed_dt);
642 catch (
const std::exception& e) {
643 prototype_ET() =
timer(prototype_ET().cumulative_duration() + agent.event_timer().cumulative_duration());
646 agent_IO(agent).deactivate();
647 if (planned_dt.finite()) {
648 t_queue_.plan_event(agent_index, planned_dt);
651 t_queue_.cancel_event(agent_index);
653 if (agent.time_precision() !=
no_scale) {
654 t_cache_.retain_event(agent_index, agent.time_precision());
656 agent_IO(agent).clear_message_input();
657 prototype_IO().clear_message_input();
661 template<
typename AgentID,
typename Node>
664 if (prototype.node_dmode() ==
flow) {
665 throw std::logic_error(
"Attempt to use \"remove_agent\" to remove a flow node agent of a collection node (" + full_name() +
"); use \"invoke_agent\" instead");
667 event_time().advance();
668 auto agent_iter = agent_indices_.find(agent_id);
669 if (agent_iter == std::end(agent_indices_)) {
670 throw std::logic_error(
"Attempt to remove agent (" + full_name() +
"." +
tostring(agent_id) +
") that does not exist");
672 int64 agent_index = agent_iter->second;
673 auto& agent = *
dynamic_cast<Node*
>(&internal_structure().node(agent_index));
674 agent_IO(agent).print_event(
"finalization");
676 if (agent.time_precision() !=
no_scale) {
677 elapsed_dt = t_cache_.duration_since(agent_index).fixed_at(agent.time_precision());
681 agent.process_finalization_event(elapsed_dt);
683 catch (
const std::exception& e) {
684 prototype_ET() =
timer(prototype_ET().cumulative_duration() + agent.event_timer().cumulative_duration());
687 prototype_ET() =
timer(prototype_ET().cumulative_duration() + agent.event_timer().cumulative_duration());
688 agent_IO(agent).deactivate();
689 int64 missing_output = agent_IO(agent).missing_flow_output();
690 if (missing_output != -1) {
691 throw std::logic_error(
"Flow output port (" + agent_IO(agent).flow_output_port_name(missing_output) +
") " +
692 "of removed agent (" + agent.full_name() +
") not assigned");
694 int64 output_port_count = agent_IO(agent).flow_output_port_count();
695 for (
int64 port_index = 0; port_index < output_port_count; ++port_index) {
696 const auto& flow_output_val = agent_IO(agent).flow_output_port_value(port_index);
697 agent_IO(agent).print_flow_output(port_index);
698 prototype_IO().assign_flow_output(port_index, flow_output_val);
700 agent_indices_.erase(agent_iter);
701 removed_indices_.insert(agent_index);
702 t_queue_.cancel_event(agent_index);
703 t_cache_.release_event(agent_index);
707 template<
typename AgentID,
typename Node>
710 if (prototype.node_dmode() ==
message) {
711 throw std::logic_error(std::string(
"Attempt to use \"invoke_agent\" to invoke a message node agent of a collection node (" + full_name() +
"); ") +
712 "use \"create_agent\", \"affect_agent\", and \"remove_agent\" instead");
714 event_time().advance();
716 auto agent_ptr = std::make_unique<Node>(agent_name, internal_context_);
717 auto& agent = *agent_ptr;
718 int64 agent_index = agent.node_index();
719 agent.adopt_print_flags(prototype);
720 agent_IO(agent).print_event(
"flow");
721 int64 missing_input = prototype_IO().missing_flow_input();
722 if (missing_input != -1) {
723 throw std::logic_error(
"Flow input port (" + agent_IO(agent).flow_input_port_name(missing_input) +
") " +
724 "of invoked agent (" + agent.full_name() +
") has no value");
726 auto input_port_count = prototype_IO().flow_input_port_count();
727 for (
int64 port_index = 0; port_index < input_port_count; ++port_index) {
728 const auto& flow_input_val = prototype_IO().flow_input_port_value(port_index);
729 if (!flow_input_val)
throw std::logic_error(
"Flow input ports of created agent (" + agent.full_name() +
") not assigned");
730 agent_IO(agent).assign_flow_input(port_index, flow_input_val);
731 agent_IO(agent).print_flow_input(port_index);
735 agent.process_initialization_event();
737 catch (
const std::exception& e) {
738 prototype_ET() =
timer(prototype_ET().cumulative_duration() + agent.event_timer().cumulative_duration());
741 agent_IO(agent).deactivate();
742 int64 missing_output = agent_IO(agent).missing_flow_output();
743 if (missing_output != -1) {
744 throw std::logic_error(
"Flow output port (" + agent_IO(agent).flow_output_port_name(missing_output) +
") " +
745 "of invoked agent (" + agent.full_name() +
") not assigned");
747 int64 output_port_count = agent_IO(agent).flow_output_port_count();
748 for (
int64 port_index = 0; port_index < output_port_count; ++port_index) {
749 agent_IO(agent).print_flow_output(port_index);
750 const auto& flow_output_val = agent_IO(agent).flow_output_port_value(port_index);
751 prototype_IO().assign_flow_output(port_index, flow_output_val);
753 internal_structure().erase_node(agent_index);
757 template<
typename AgentID,
typename Node>
760 return agent_indices_.find(agent_id) != std::end(agent_indices_);
764 template<
typename AgentID,
typename Node>
767 return int64(agent_indices_.size());
771 template<
typename AgentID,
typename Node>
778 template<
typename AgentID,
typename Node>
785 template<
typename AgentID,
typename Node>
788 return internal_context_.internal_structure();
792 template<
typename AgentID,
typename Node>
793 inline node_interface& collection_node<AgentID, Node>::prototype_IO()
const
795 return const_cast<node_interface&
>(
const_cast<Node&
>(prototype).external_interface());
799 template<
typename AgentID,
typename Node>
800 inline timer& collection_node<AgentID, Node>::prototype_ET()
const
802 return const_cast<timer&
>(prototype.event_timer());
806 template<
typename AgentID,
typename Node>
807 inline node_interface& collection_node<AgentID, Node>::agent_IO(
const system_node& agent)
const
809 return const_cast<node_interface&
>(
const_cast<system_node&
>(agent).external_interface());
813 template<
typename AgentID,
typename Node>
814 inline discrete_event_time& collection_node<AgentID, Node>::event_time()
816 return external_IO().external_context().event_time();
820 template<
typename AgentID,
typename Node>
821 template<data_mode dmode, data_goal dgoal,
typename T>
822 inline void collection_node<AgentID, Node>::validate_prototype_port(
const port<dmode, dgoal, T>& prototype_port)
824 if (&prototype_port.external_interface() != &prototype_IO()) {
826 "port (" + prototype_port.port_name() +
"), " +
827 "which is not a port of the prototype agent (" + prototype.full_name() +
")");
829 if (!external_interface().active()) {
831 "port (" + prototype_port.port_name() +
"), " +
832 "which is a prototype port of inactive node (" + full_name() +
")");
837 template<
typename AgentID,
typename Node>
838 inline Node& collection_node<AgentID, Node>::handle_agent_planned_event(
int64 agent_index)
840 event_time().advance();
841 auto& agent = *
dynamic_cast<Node*
>(&internal_structure().node(agent_index));
842 agent_IO(agent).print_event(
"planned");
844 if (agent.time_precision() !=
no_scale) {
845 elapsed_dt = t_cache_.duration_since(agent_index).fixed_at(agent.time_precision());
851 planned_dt = agent.process_planned_event(elapsed_dt);
854 catch (
const std::exception& e) {
858 prototype_ET() = timer(prototype_ET().cumulative_duration() + agent.event_timer().cumulative_duration());
861 agent_IO(agent).deactivate();
862 if (planned_dt.finite()) {
863 t_queue_.plan_event(agent_index, planned_dt);
866 t_queue_.pop_imminent_event(agent_index);
868 if (agent.time_precision() !=
no_scale) {
869 t_cache_.retain_event(agent_index, agent.time_precision());
871 int64 list_size = agent_IO(agent).message_output_list_size();
872 for (
int64 list_index = 0; list_index < list_size; ++list_index) {
873 int64 port_index = agent_IO(agent).message_output_index(list_index);
874 agent_IO(agent).print_message_output(list_index, port_index);
880 template<
typename AgentID,
typename Node>
881 inline void collection_node<AgentID, Node>::erase_removed_agents()
883 for (
int64 agent_index : removed_indices_) {
884 internal_structure().erase_node(agent_index);
885 agent_ids_.erase(agent_index);
886 agents_.erase(agent_index);
888 removed_indices_.clear();
892 template<
typename AgentID,
typename Node>
894 inline std::string collection_node<AgentID, Node>::agent_name_from_id(qualified_type<T> agent_id_type,
const AgentID& agent_id)
900 template<
typename AgentID,
typename Node>
901 inline std::string collection_node<AgentID, Node>::agent_name_from_id(qualified_type<std::string> agent_id_type,
const AgentID& agent_id)
907 template<
typename AgentID,
typename Node>
908 inline void collection_node<AgentID, Node>::adopt_component_print_flags(
const system_node& node)
const
910 const auto node_ptr =
dynamic_cast<const collection_node*
>(&node);
912 throw std::logic_error(
"Attempt to transfer print flags from node (" + node.full_name() +
")" +
913 "to node (" + full_name() +
"), but the nodes are of different types");
915 auto& other_node =
const_cast<collection_node&
>(*node_ptr);
916 prototype.adopt_print_flags(other_node.prototype);
922 template<
typename AgentID,
typename Node>
931 template<
typename AgentID,
typename Node>
936 external_interface_.assign_flow_input(port_index_, val);
941 template<
typename AgentID,
typename Node>
944 : external_interface_(const_cast<
node_interface&>(input_port.external_interface()))
945 , port_index_(input_port.port_index())
952 template<
typename AgentID,
typename Node>
961 template<
typename AgentID,
typename Node>
966 external_interface_.set_message_input(port_index_, val);
971 template<
typename AgentID,
typename Node>
975 , port_index_(input_port.port_index())
982 template<
typename AgentID,
typename Node>
989 template<
typename AgentID,
typename Node>
992 return &iter_->first;
996 template<
typename AgentID,
typename Node>
1004 template<
typename AgentID,
typename Node>
1013 template<
typename AgentID,
typename Node>
1021 template<
typename AgentID,
typename Node>
1030 template<
typename AgentID,
typename Node>
1033 return iter_ == rhs.iter_;
1037 template<
typename AgentID,
typename Node>
1040 return iter_ != rhs.iter_;
1044 template<
typename AgentID,
typename Node>
A data type which represents a pointer to anything.
Definition: pointer.h:29
Definition: collection_node.h:279
const_iterator & operator++()
Definition: collection_node.h:997
const_iterator & operator--()
Definition: collection_node.h:1014
const AgentID * operator->() const
Definition: collection_node.h:990
const AgentID & operator*() const
Definition: collection_node.h:983
bool operator!=(const const_iterator &rhs) const
Definition: collection_node.h:1038
bool operator==(const const_iterator &rhs) const
Definition: collection_node.h:1031
Definition: collection_node.h:232
flow_port_proxy & operator=(flow_port_proxy &&)=default
Move assignment.
flow_port_proxy(flow_port_proxy &&)=default
Move constructor.
flow_port_proxy(const flow_port_proxy &)=delete
No copy constructor.
virtual ~flow_port_proxy()=default
Destructor.
Definition: collection_node.h:256
message_port_proxy & operator=(message_port_proxy &&)=default
Move assignment.
virtual ~message_port_proxy()=default
Destructor.
message_port_proxy(const message_port_proxy &)=delete
No copy constructor.
message_port_proxy(message_port_proxy &&)=default
Move constructor.
A base class for the collection node class template.
Definition: collection_node_base.h:22
A base class template for all collection nodes.
Definition: collection_node.h:56
void print_on_planned_duration(bool flag=true) const
If flag is true, all planned durations are printed for this node.
Definition: collection_node.h:329
bool transmitted(const port< message, output, T > &prototype_port)
Returns true if a message was transmitted by an agent on the port corresponding to prototype_port.
Definition: collection_node.h:491
duration handle_initialization_event()
Invoked at the beginning of a simulation; calls macro_initialization_event.
Definition: collection_node.h:336
static const int64 macro_event_id
The index used to schedule macro events; it must not conflict with any of the agent indices.
Definition: collection_node.h:94
const_iterator agent_begin()
Returns an iterator pointing to the oldest agent.
Definition: collection_node.h:772
collection_node(const std::string &node_name, const node_context &external_context)
Constructs a collection_node.
Definition: collection_node.h:303
void affect_agent(const AgentID &agent_id)
Sends a message to an agent.
Definition: collection_node.h:608
const Node prototype
A node that serves as a proxy for all agent nodes.
Definition: collection_node.h:86
bool agent_exists(const AgentID &agent_id)
Returns true if an agent with ID agent_id currently exists.
Definition: collection_node.h:758
void create_agent(const AgentID &agent_id)
Creates a new agent of type AgentNode.
Definition: collection_node.h:558
duration handle_unplanned_event(duration elapsed_dt)
Invoked whenever a message is received; calls macro_unplanned_event.
Definition: collection_node.h:365
void print_on_elapsed_duration(bool flag=true) const
If flag is true, all elapsed durations are printed for this node.
Definition: collection_node.h:322
int64 agent_count()
Returns the current number of agents.
Definition: collection_node.h:765
virtual ~collection_node()=default
Destructor.
const_iterator agent_end()
Returns an iterator pointing beyond the newest agent.
Definition: collection_node.h:779
flow_port_proxy< T > get(const port< flow, input, T > &prototype_port)
Returns a proxy of the flow input port prototype_port, allowing its value to be modified.
void handle_finalization_event(duration elapsed_dt)
Invoked at the end of a simulation; calls macro_finalization_event.
Definition: collection_node.h:469
void invoke_agent(const AgentID &agent_id)
Creates, invokes, and removes an agent.
Definition: collection_node.h:708
void remove_agent(const AgentID &agent_id)
Finalizes and removes an agent.
Definition: collection_node.h:662
duration handle_planned_event(duration elapsed_dt)
Invoked when the planned duration elapses for either an agent or the overall collection; calls micro_...
Definition: collection_node.h:396
message_port_proxy< T > get(const port< message, input, T > &prototype_port)
Returns a proxy of the message input port prototype_port, allowing its value to be modified.
A data structure which represents progress through a simulation, encapsulating both simulated time an...
Definition: discrete_event_time.h:37
Definition: node_context.h:17
Definition: node_interface.h:17
const pointer & flow_input_port_value(int64 port_index)
Definition: node_interface.cpp:62
const pointer & message_input_port_value(int64 port_index)
Definition: node_interface.cpp:113
Definition: node_structure.h:16
A class template for flow output ports.
Definition: port.h:184
A class template for message output ports.
Definition: port.h:146
const std::string & port_name() const
Returns the name of the port.
Definition: port.h:212
int64 port_index() const
Returns the index of the port within the encompassing node_interface object.
Definition: port.h:219
A generic port class template declaration.
Definition: port.h:54
A base class for all nodes from which systems models are constructed.
Definition: system_node.h:42
system_node & operator=(const system_node &)=delete
No copy assignment.
const std::string & node_name() const
Returns the name of the node.
Definition: system_node.h:135
const node_interface & external_interface() const
Returns the object responsible for exchanging information between the node and its surrounding contex...
Definition: system_node.h:153
A data structure which provides durations elapsed since past events.
Definition: time_cache.h:28
A data structure which supports the scheduling of future events.
Definition: time_queue.h:35
A class for measuring and accumulating intervals of wallclock time.
Definition: timer.h:25
const std::string & string_from_data_goal(data_goal dgoal)
Returns the std::string representation of the dgoal value.
Definition: data_goal.cpp:21
const auto message
Equivalent to data_mode::message.
Definition: data_mode.h:23
const std::string & string_from_data_mode(data_mode dmode)
Returns the std::string representation of the dmode value.
Definition: data_mode.cpp:21
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
constexpr auto _s
Definition: units.h:128
quantity< seconds > duration
Definition: quantity.h:1006
auto operator!=(const arraynd< T, ndims > &lhs, const arraynd< T, ndims > &rhs)
Definition: arraynd.h:904
auto operator==(const arraynd< T, ndims > &lhs, const arraynd< T, ndims > &rhs)
Definition: arraynd.h:894
int64_t int64
Definition: number_types.h:15
std::string tostring(const T &val)
Definition: qualified_type.h:35
constexpr scale no_scale
Definition: scale.h:153
auto operator*(const arraynd< T, ndims > &lhs, const arraynd< T, ndims > &rhs)
Definition: arraynd.h:762
Definition: qualified_type.h:76
Definition: qualified_type.h:24