RootStateMachine.hpp 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179
  1. /**
  2. * @file utils/RootStateMachine.hpp
  3. * @author The ARTIS Development Team
  4. * See the AUTHORS or Authors.txt file
  5. */
  6. /*
  7. * ARTIS - the multimodeling and simulation environment
  8. * This file is a part of the ARTIS environment
  9. *
  10. * Copyright (C) 2013-2023 ULCO http://www.univ-littoral.fr
  11. *
  12. * This program is free software: you can redistribute it and/or modify
  13. * it under the terms of the GNU General Public License as published by
  14. * the Free Software Foundation, either version 3 of the License, or
  15. * (at your option) any later version.
  16. *
  17. * This program is distributed in the hope that it will be useful,
  18. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  19. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  20. * GNU General Public License for more details.
  21. *
  22. * You should have received a copy of the GNU General Public License
  23. * along with this program. If not, see <http://www.gnu.org/licenses/>.
  24. */
  25. #ifndef ARTIS_STAR_ADDONS_UTILS_ROOT_STATE_MACHINE_HPP
  26. #define ARTIS_STAR_ADDONS_UTILS_ROOT_STATE_MACHINE_HPP
  27. #include <artis-star-addons/utils/StateMachine.hpp>
  28. #include <memory>
  29. #include <vector>
  30. namespace artis::addons::utils {
  31. template<class Time, class Types, class Parameters, class StateMachineTypes>
  32. class RootStateMachine {
  33. public:
  34. typedef std::vector<typename Types::state_machine_type::ExternalEvent> external_events_type;
  35. RootStateMachine() = default;
  36. virtual ~RootStateMachine() = default;
  37. virtual void build(const Parameters &parameters) = 0;
  38. template<class RootStateMachineType, size_t N>
  39. constexpr void build_machines(const Parameters &parameters) {
  40. if constexpr(N == 1)
  41. {
  42. this->template build_machine<RootStateMachineType, std::tuple_element_t < 0, StateMachineTypes>>
  43. (0, parameters);
  44. } else {
  45. this->template build_machine<RootStateMachineType, std::tuple_element_t < N - 1, StateMachineTypes>>
  46. (N - 1, parameters);
  47. build_machines<RootStateMachineType, N - 1>(parameters);
  48. }
  49. }
  50. int current_state(int machine_id) const {
  51. typename Types::state_machine_IDs_type::values key =
  52. static_cast<typename Types::state_machine_IDs_type::values>(machine_id);
  53. return _machines.find(key)->second->current_state()->_id;
  54. }
  55. const std::shared_ptr<typename Types::state_machine_type> &
  56. machine(const int machine_id) {
  57. typename Types::state_machine_IDs_type::values key =
  58. static_cast<typename Types::state_machine_IDs_type::values>(machine_id);
  59. return _machines.find(key)->second;
  60. }
  61. const external_events_type &outbox() const { return _outbox; }
  62. void start(const typename Time::type &t) {
  63. std::for_each(_machines.begin(), _machines.end(), [t](const auto &e) {
  64. e.second->start(t);
  65. });
  66. _last_time = t;
  67. }
  68. template<class StateType>
  69. const StateType &state_(int machine_id) const {
  70. typename Types::state_machine_IDs_type::values key =
  71. static_cast<typename Types::state_machine_IDs_type::values>(machine_id);
  72. return std::dynamic_pointer_cast < StateMachine < Time, Types, StateType >> (_machines.at(key))->state_();
  73. }
  74. typename Time::type ta(const typename Time::type &t) const {
  75. if (_outbox.empty()) {
  76. typename Time::type min = Time::infinity;
  77. std::for_each(_machines.cbegin(), _machines.cend(), [t, &min](const auto &e) {
  78. typename Time::type ta = e.second->ta(t);
  79. min = min < ta ? min : ta;
  80. });
  81. return min;
  82. } else return 0;
  83. }
  84. void transition(const typename Time::type &t) {
  85. if (_outbox.empty()) {
  86. std::for_each(_machines.cbegin(), _machines.cend(), [t, this](const auto &e) {
  87. if (e.second->is_ready(t)) {
  88. typename Types::state_machine_type::Events events = e.second->transition(t);
  89. dispatch(t, events.internals);
  90. appendEvents(events.externals);
  91. }
  92. });
  93. } else {
  94. _outbox.clear();
  95. }
  96. _last_time = t;
  97. std::for_each(_machines.cbegin(), _machines.cend(), [t](const auto &e) {
  98. e.second->update_sigma(t);
  99. });
  100. }
  101. void transition(const typename Time::type &t, int machine_id,
  102. const typename Types::state_machine_type::ExternalEvent &e) {
  103. typename Types::state_machine_IDs_type::values key =
  104. static_cast<typename Types::state_machine_IDs_type::values>(machine_id);
  105. typename Types::state_machine_type::Events events = _machines.at(key)->transition(t, e);
  106. dispatch(t, events.internals);
  107. appendEvents(events.externals);
  108. std::for_each(_machines.cbegin(), _machines.cend(), [t](const auto &e) {
  109. e.second->update_sigma(t);
  110. });
  111. }
  112. protected:
  113. template<class RootStateMachineType, class FinalStateMachine>
  114. void build_machine(int machine_id, const Parameters &parameters) {
  115. auto machine = std::make_shared<FinalStateMachine>(*dynamic_cast<RootStateMachineType *>(this), parameters);
  116. typename Types::state_machine_IDs_type::values key =
  117. static_cast<typename Types::state_machine_IDs_type::values>(machine_id);
  118. machine->build(machine);
  119. this->_machines[key] = std::dynamic_pointer_cast<typename Types::state_machine_type>(machine);
  120. }
  121. private:
  122. void appendEvents(const std::vector<typename Types::state_machine_type::ExternalEvent> &events) {
  123. _outbox.insert(_outbox.end(), events.cbegin(), events.cend());
  124. }
  125. void
  126. dispatch(const typename Time::type &t, const std::vector<typename Types::state_machine_type::InternalEvent> &events) {
  127. std::for_each(events.cbegin(), events.cend(),
  128. [t, this](const auto &e) {
  129. typename Types::state_machine_IDs_type::values key =
  130. static_cast<typename Types::state_machine_IDs_type::values>(e.machine_id);
  131. auto it = _machines.find(key);
  132. if (it != _machines.end()) {
  133. typename Types::state_machine_type::Events events = it->second->transition(t, e);
  134. dispatch(t, events.internals);
  135. appendEvents(events.externals);
  136. }
  137. });
  138. }
  139. std::map<typename Types::state_machine_IDs_type::values, std::shared_ptr<typename Types::state_machine_type>> _machines;
  140. external_events_type _outbox;
  141. typename Time::type _last_time{};
  142. };
  143. }
  144. #endif //ARTIS_STAR_ADDONS_UTILS_ROOT_STATE_MACHINE_HPP