123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179 |
- /**
- * @file utils/RootStateMachine.hpp
- * @author The ARTIS Development Team
- * See the AUTHORS or Authors.txt file
- */
- /*
- * ARTIS - the multimodeling and simulation environment
- * This file is a part of the ARTIS environment
- *
- * Copyright (C) 2013-2023 ULCO http://www.univ-littoral.fr
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
- #ifndef ARTIS_STAR_ADDONS_UTILS_ROOT_STATE_MACHINE_HPP
- #define ARTIS_STAR_ADDONS_UTILS_ROOT_STATE_MACHINE_HPP
- #include <artis-star-addons/utils/StateMachine.hpp>
- #include <memory>
- #include <vector>
- namespace artis::addons::utils {
- template<class Time, class Types, class Parameters, class StateMachineTypes>
- class RootStateMachine {
- public:
- typedef std::vector<typename Types::state_machine_type::ExternalEvent> external_events_type;
- RootStateMachine() = default;
- virtual ~RootStateMachine() = default;
- virtual void build(const Parameters ¶meters) = 0;
- template<class RootStateMachineType, size_t N>
- constexpr void build_machines(const Parameters ¶meters) {
- if constexpr(N == 1)
- {
- this->template build_machine<RootStateMachineType, std::tuple_element_t < 0, StateMachineTypes>>
- (0, parameters);
- } else {
- this->template build_machine<RootStateMachineType, std::tuple_element_t < N - 1, StateMachineTypes>>
- (N - 1, parameters);
- build_machines<RootStateMachineType, N - 1>(parameters);
- }
- }
- int current_state(int machine_id) const {
- typename Types::state_machine_IDs_type::values key =
- static_cast<typename Types::state_machine_IDs_type::values>(machine_id);
- return _machines.find(key)->second->current_state()->_id;
- }
- const std::shared_ptr<typename Types::state_machine_type> &
- machine(const int machine_id) {
- typename Types::state_machine_IDs_type::values key =
- static_cast<typename Types::state_machine_IDs_type::values>(machine_id);
- return _machines.find(key)->second;
- }
- const external_events_type &outbox() const { return _outbox; }
- void start(const typename Time::type &t) {
- std::for_each(_machines.begin(), _machines.end(), [t](const auto &e) {
- e.second->start(t);
- });
- _last_time = t;
- }
- template<class StateType>
- const StateType &state_(int machine_id) const {
- typename Types::state_machine_IDs_type::values key =
- static_cast<typename Types::state_machine_IDs_type::values>(machine_id);
- return std::dynamic_pointer_cast < StateMachine < Time, Types, StateType >> (_machines.at(key))->state_();
- }
- typename Time::type ta(const typename Time::type &t) const {
- if (_outbox.empty()) {
- typename Time::type min = Time::infinity;
- std::for_each(_machines.cbegin(), _machines.cend(), [t, &min](const auto &e) {
- typename Time::type ta = e.second->ta(t);
- min = min < ta ? min : ta;
- });
- return min;
- } else return 0;
- }
- void transition(const typename Time::type &t) {
- if (_outbox.empty()) {
- std::for_each(_machines.cbegin(), _machines.cend(), [t, this](const auto &e) {
- if (e.second->is_ready(t)) {
- typename Types::state_machine_type::Events events = e.second->transition(t);
- dispatch(t, events.internals);
- appendEvents(events.externals);
- }
- });
- } else {
- _outbox.clear();
- }
- _last_time = t;
- std::for_each(_machines.cbegin(), _machines.cend(), [t](const auto &e) {
- e.second->update_sigma(t);
- });
- }
- void transition(const typename Time::type &t, int machine_id,
- const typename Types::state_machine_type::ExternalEvent &e) {
- typename Types::state_machine_IDs_type::values key =
- static_cast<typename Types::state_machine_IDs_type::values>(machine_id);
- typename Types::state_machine_type::Events events = _machines.at(key)->transition(t, e);
- dispatch(t, events.internals);
- appendEvents(events.externals);
- std::for_each(_machines.cbegin(), _machines.cend(), [t](const auto &e) {
- e.second->update_sigma(t);
- });
- }
- protected:
- template<class RootStateMachineType, class FinalStateMachine>
- void build_machine(int machine_id, const Parameters ¶meters) {
- auto machine = std::make_shared<FinalStateMachine>(*dynamic_cast<RootStateMachineType *>(this), parameters);
- typename Types::state_machine_IDs_type::values key =
- static_cast<typename Types::state_machine_IDs_type::values>(machine_id);
- machine->build(machine);
- this->_machines[key] = std::dynamic_pointer_cast<typename Types::state_machine_type>(machine);
- }
- private:
- void appendEvents(const std::vector<typename Types::state_machine_type::ExternalEvent> &events) {
- _outbox.insert(_outbox.end(), events.cbegin(), events.cend());
- }
- void
- dispatch(const typename Time::type &t, const std::vector<typename Types::state_machine_type::InternalEvent> &events) {
- std::for_each(events.cbegin(), events.cend(),
- [t, this](const auto &e) {
- typename Types::state_machine_IDs_type::values key =
- static_cast<typename Types::state_machine_IDs_type::values>(e.machine_id);
- auto it = _machines.find(key);
- if (it != _machines.end()) {
- typename Types::state_machine_type::Events events = it->second->transition(t, e);
- dispatch(t, events.internals);
- appendEvents(events.externals);
- }
- });
- }
- std::map<typename Types::state_machine_IDs_type::values, std::shared_ptr<typename Types::state_machine_type>> _machines;
- external_events_type _outbox;
- typename Time::type _last_time{};
- };
- }
- #endif //ARTIS_STAR_ADDONS_UTILS_ROOT_STATE_MACHINE_HPP
|