/** * @file PoolRouter.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-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 . */ #include "PoolRouter.hpp" namespace artis::factory { void PoolRouter::dint(const Time & /* t */) { switch (_phase) { case Phase::INIT: { _phase = Phase::WAIT; break; } case Phase::WAIT: { break; } case Phase::SEND: { auto it = next_po(); assert(it != _pending_po.cend()); if (not (*it)->is_finish() and (*it)->current_operation().get_type() != CHANGE_POOL_TYPE) { _available_machines[(*it)->current_operation().get_loc_index()]--; } _pending_po.erase(it); if (std::find_if(_pending_po.cbegin(), _pending_po.cend(), [this](const auto &e) { return e->is_finish() or e->current_operation().get_type() == CHANGE_POOL_TYPE or _available_machines[e->current_operation().get_loc_index()] > 0; }) != _pending_po.cend()) { _phase = Phase::SEND; } else { _phase = Phase::WAIT; } break; } } } void PoolRouter::dext(const Time &t, const Time & /* e */, const Bag &bag) { std::for_each(bag.begin(), bag.end(), [t, this](const common::event::ExternalEvent &event) { if (event.port_index() == inputs::IN) { uint8_t *data = nullptr; event.data()(data); _pending_po.push_back(std::make_unique(data, event.data().size())); _pending_po.back()->next(); } else if (event.port_index() == inputs::FINISH) { unsigned int index; event.data()(index); _available_machines[index]++; } else if (event.port_index() >= inputs::IN_M) { uint8_t *data = nullptr; event.data()(data); _pending_po.push_back(std::make_unique(data, event.data().size())); _available_machines[event.port_index() - inputs::IN_M]++; _pending_po.back()->next(); } } ); if (std::find_if(_pending_po.cbegin(), _pending_po.cend(), [this](const auto &e) { return e->is_finish() or e->current_operation().get_type() == CHANGE_POOL_TYPE or _available_machines[e->current_operation().get_loc_index()] > 0; }) != _pending_po.cend()) { _phase = Phase::SEND; } else { _phase = Phase::WAIT; } } void PoolRouter::start(const Time & /* t */) { _phase = Phase::INIT; for (const auto &e: _parameters.capacities) { _available_machines[e.first] = e.second; } } Time PoolRouter::ta(const Time & /* t */) const { switch (_phase) { case Phase::INIT: return 0; case Phase::WAIT: return artis::common::DoubleTime::infinity; case Phase::SEND: return 0; } return artis::common::DoubleTime::infinity; } Bag PoolRouter::lambda(const Time & /* t */) const { Bag bag; if (_phase == Phase::SEND) { if (not _pending_po.empty()) { auto it = next_po(); assert(it != _pending_po.cend()); auto po = it->get(); if (po->is_finish() or po->current_operation().get_type() == CHANGE_POOL_TYPE) { bag.push_back(ExternalEvent(outputs::OUT, common::event::Value(po->_buffer, po->_size))); } else if (po->current_operation().get_type() == CHANGE_MACHINE_TYPE) { bag.push_back(ExternalEvent(outputs::OUT_M + po->current_operation().get_loc_index(), common::event::Value(po->_buffer, po->_size))); } } } return bag; } artis::common::event::Value PoolRouter::observe(const Time & /* t */, unsigned int index) const { switch (index) { case vars::WAITING_PO_NUMBER: return (unsigned int) _pending_po.size(); } return {}; } PoolRouter::ProductionOrders::const_iterator PoolRouter::next_po() const { auto it = std::find_if(_pending_po.cbegin(), _pending_po.cend(), [](const auto &e) { return e->is_finish() or e->current_operation().get_type() == CHANGE_POOL_TYPE; }); if (it != _pending_po.cend()) { return it; } else { return std::find_if(_pending_po.cbegin(), _pending_po.cend(), [this](const auto &e) { return _available_machines.at(e->current_operation().get_loc_index()) > 0; }); } } } // namespace artis::factory