/** * @file tests/multithreading/simple/graph_manager.cpp * @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-2019 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 . */ #ifndef TESTS_MULTITHREADING_SIMPLE_GRAPH_MANAGER_HPP #define TESTS_MULTITHREADING_SIMPLE_GRAPH_MANAGER_HPP #include #include #include #include namespace artis { namespace tests { namespace multithreading { namespace simple { class LinksGraphManager : public artis::pdevs::GraphManager { public: enum submodels { LINK_1, LINK_2 }; struct inputs { enum values { IN_1, IN_2 }; }; struct outputs { enum values { OUT_1, OUT_2 }; }; LinksGraphManager( artis::common::Coordinator *coordinator, const GeneratorParameters ¶meters, const artis::common::NoParameters &graph_parameters) : artis::pdevs::GraphManager( coordinator, parameters, graph_parameters), _link_1("link_1", artis::common::NoParameters()), _link_2("link_2", artis::common::NoParameters()) { add_child(LINK_1, &_link_1); add_child(LINK_2, &_link_2); coordinator->input_ports({{inputs::IN_1, "in_1"}, {inputs::IN_2, "in_2"}}); coordinator->output_ports({{outputs::OUT_1, "out_1"}, {outputs::OUT_2, "out_2"}}); in({coordinator, inputs::IN_1}) >> out({&_link_1, Link::inputs::IN}); in({coordinator, inputs::IN_2}) >> out({&_link_2, Link::inputs::IN}); out({&_link_1, Link::outputs::OUT}) >> out({coordinator, outputs::OUT_1}); out({&_link_2, Link::outputs::OUT}) >> out({coordinator, outputs::OUT_2}); } ~LinksGraphManager() override = default; common::DoubleTime::type lookahead(const common::DoubleTime::type &t) const override { std::vector lookaheads = {_link_1.lookahead(t), _link_2.lookahead(t)}; return *std::min(lookaheads.begin(), lookaheads.end()); } void init() {} void start(common::DoubleTime::type /* t */) {} void transition(const common::Models & /* receivers */, artis::common::DoubleTime::type /* t */) {} private: artis::pdevs::Simulator _link_1; artis::pdevs::Simulator _link_2; }; class SimpleGraphManager : public artis::pdevs::GraphManager { public: enum submodels { GENERATOR, LINK_1_2, LINK_3_4, LINK_5_6, LINK_7_8, COUNTER }; SimpleGraphManager( artis::common::Coordinator *coordinator, const GeneratorParameters ¶meters, const artis::common::NoParameters &graph_parameters) : artis::pdevs::GraphManager( coordinator, parameters, graph_parameters), _generator("generator", parameters), _link_1_2("link_1_2", parameters, artis::common::NoParameters()), _link_3_4("link_3_4", parameters, artis::common::NoParameters()), _link_5_6("link_5_6", parameters, artis::common::NoParameters()), _link_7_8("link_7_8", parameters, artis::common::NoParameters()), _counter("counter", artis::common::NoParameters()) { add_child(GENERATOR, &_generator); add_child(LINK_1_2, &_link_1_2); add_child(LINK_3_4, &_link_3_4); add_child(LINK_5_6, &_link_5_6); add_child(LINK_7_8, &_link_7_8); add_child(COUNTER, &_counter); out({&_generator, Generator::outputs::OUT}) >> in({&_link_1_2, LinksGraphManager::inputs::IN_1}); out({&_generator, Generator::outputs::OUT + 1}) >> in({&_link_1_2, LinksGraphManager::inputs::IN_2}); out({&_generator, Generator::outputs::OUT + 2}) >> in({&_link_3_4, LinksGraphManager::inputs::IN_1}); out({&_generator, Generator::outputs::OUT + 3}) >> in({&_link_3_4, LinksGraphManager::inputs::IN_2}); out({&_generator, Generator::outputs::OUT + 4}) >> in({&_link_5_6, LinksGraphManager::inputs::IN_1}); out({&_generator, Generator::outputs::OUT + 5}) >> in({&_link_5_6, LinksGraphManager::inputs::IN_2}); out({&_generator, Generator::outputs::OUT + 6}) >> in({&_link_7_8, LinksGraphManager::inputs::IN_1}); out({&_generator, Generator::outputs::OUT + 7}) >> in({&_link_7_8, LinksGraphManager::inputs::IN_2}); out({&_link_1_2, LinksGraphManager::outputs::OUT_1}) >> in({&_counter, Counter::inputs::IN}); out({&_link_1_2, LinksGraphManager::outputs::OUT_2}) >> in({&_counter, Counter::inputs::IN}); out({&_link_3_4, LinksGraphManager::outputs::OUT_1}) >> in({&_counter, Counter::inputs::IN}); out({&_link_3_4, LinksGraphManager::outputs::OUT_2}) >> in({&_counter, Counter::inputs::IN}); out({&_link_5_6, LinksGraphManager::outputs::OUT_1}) >> in({&_counter, Counter::inputs::IN}); out({&_link_5_6, LinksGraphManager::outputs::OUT_2}) >> in({&_counter, Counter::inputs::IN}); out({&_link_7_8, LinksGraphManager::outputs::OUT_1}) >> in({&_counter, Counter::inputs::IN}); out({&_link_7_8, LinksGraphManager::outputs::OUT_2}) >> in({&_counter, Counter::inputs::IN}); } ~SimpleGraphManager() override = default; common::DoubleTime::type lookahead(const common::DoubleTime::type &t) const override { std::vector lookaheads = {_generator.lookahead(t), _link_1_2.lookahead(t), _link_3_4.lookahead(t), _link_5_6.lookahead(t), _link_7_8.lookahead(t), _counter.lookahead(t)}; return *std::min(lookaheads.begin(), lookaheads.end()); } void init() { _link_1_2.set_sender( (dynamic_cast< artis::pdevs::multithreading::Coordinator< artis::common::DoubleTime, SimpleGraphManager, GeneratorParameters, artis::common::NoParameters> *>(this->coordinator()))->get_sender()); _link_3_4.set_sender( (dynamic_cast< artis::pdevs::multithreading::Coordinator< artis::common::DoubleTime, SimpleGraphManager, GeneratorParameters, artis::common::NoParameters> *>(this->coordinator()))->get_sender()); _link_5_6.set_sender( (dynamic_cast< artis::pdevs::multithreading::Coordinator< artis::common::DoubleTime, SimpleGraphManager, GeneratorParameters, artis::common::NoParameters> *>(this->coordinator()))->get_sender()); _link_7_8.set_sender( (dynamic_cast< artis::pdevs::multithreading::Coordinator< artis::common::DoubleTime, SimpleGraphManager, GeneratorParameters, artis::common::NoParameters> *>(this->coordinator()))->get_sender()); } void start(common::DoubleTime::type t) { _link_1_2.get_sender().send( artis::pdevs::multithreading::start_message< artis::common::DoubleTime>(t)); _link_3_4.get_sender().send( artis::pdevs::multithreading::start_message< artis::common::DoubleTime>(t)); _link_5_6.get_sender().send( artis::pdevs::multithreading::start_message< artis::common::DoubleTime>(t)); _link_7_8.get_sender().send( artis::pdevs::multithreading::start_message< artis::common::DoubleTime>(t)); } void transition(const common::Models &receivers, artis::common::DoubleTime::type t) { std::for_each(receivers.begin(), receivers.end(), [this, t](const common::Model *model) { if (not model->is_atomic()) { if (model == &_link_1_2) { _link_1_2.get_sender().send( artis::pdevs::multithreading::transition_message< artis::common::DoubleTime>(t)); } else if (model == &_link_3_4) { _link_3_4.get_sender().send( artis::pdevs::multithreading::transition_message< artis::common::DoubleTime>(t)); } else if (model == &_link_5_6) { _link_5_6.get_sender().send( artis::pdevs::multithreading::transition_message< artis::common::DoubleTime>(t)); } else if (model == &_link_7_8) { _link_7_8.get_sender().send( artis::pdevs::multithreading::transition_message< artis::common::DoubleTime>(t)); } } }); } private: artis::pdevs::Simulator _generator; /* artis::pdevs::Coordinator _link_1_2; artis::pdevs::Coordinator _link_3_4; artis::pdevs::Coordinator _link_5_6; artis::pdevs::Coordinator _link_7_8; */ artis::pdevs::multithreading::Coordinator _link_1_2; artis::pdevs::multithreading::Coordinator _link_3_4; artis::pdevs::multithreading::Coordinator _link_5_6; artis::pdevs::multithreading::Coordinator _link_7_8; artis::pdevs::Simulator _counter; }; } } } } // namespace artis tests multithreading simple #endif