/** * @file tests/multithreading/lifegame/models.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-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_LIFEGAME_MODELS_HPP #define TESTS_MULTITHREADING_LIFEGAME_MODELS_HPP #include #include namespace artis { namespace tests { namespace multithreading { namespace lifegame { struct CellParameters { std::map neighbour_numbers; std::map initial_states; }; class Cell : public artis::pdevs::Dynamics { public: enum inputs { IN }; enum outputs { OUT }; enum states { STATE }; Cell(const std::string &name, const artis::pdevs::Context &context) : artis::pdevs::Dynamics(name, context), _neighbour_number( context.parameters().neighbour_numbers.find(name)->second), _initial_state(context.parameters().initial_states.find(name)->second) { input_ports({{IN, "in"}}); output_ports({{OUT, "out"}}); observables({{STATE, "state"}}); } ~Cell() override = default; void dint(const typename common::DoubleTime::type & /* t */) override { if (_phase == SEND) { _phase = WAIT; _sigma = common::DoubleTime::infinity; } else if (_phase == NEW_STATE) { if (_state and (_true_neighbour_number < 2 or _true_neighbour_number > 3)) { _state = false; } else if (not _state and (_true_neighbour_number == 3)) { _state = true; } _phase = SEND; _sigma = 1; _true_neighbour_number = 0; _received = 0; } } void dext(const typename common::DoubleTime::type & /* t */, const typename common::DoubleTime::type & /* e */, const common::Bag &bag) override { std::for_each(bag.begin(), bag.end(), [this](const common::ExternalEvent &e) { if (e.on_port(IN)) { bool data; e.data()(data); if (data) { ++_true_neighbour_number; } ++_received; } }); if (_received == _neighbour_number) { _phase = NEW_STATE; _sigma = 0; } else { _phase = WAIT; _sigma = common::DoubleTime::infinity; } } void dconf(const typename common::DoubleTime::type &t, const typename common::DoubleTime::type &e, const common::Bag &bag) override { dext(t, e, bag); } void start(const typename common::DoubleTime::type &t) override { (void) t; _phase = SEND; _sigma = 0; _state = _initial_state; _true_neighbour_number = 0; _received = 0; } typename common::DoubleTime::type ta(const typename common::DoubleTime::type & /* t */) const override { return _sigma; } common::Bag lambda(const typename common::DoubleTime::type & /* t */) const override { common::Bag bag; if (_phase == SEND) { bag.push_back( artis::common::ExternalEvent(OUT, _state)); } return bag; } common::Value observe(const common::DoubleTime::type & /* t */, unsigned int index) const override { if (index == STATE) { return _state; } return common::Value(); } private: enum Phase { SEND, WAIT, NEW_STATE }; // parameters unsigned int _neighbour_number; bool _initial_state; // state Phase _phase; common::DoubleTime::type _sigma; bool _state; unsigned int _received; unsigned int _true_neighbour_number; }; } } } } // namespace artis tests multithreading lifegame #endif