LCOV - code coverage report
Current view: top level - PTN_Engine - PTN_EngineImp.cpp (source / functions) Hit Total Coverage
Test: filtered_coverage.info Lines: 130 146 89.0 %
Date: 2024-05-26 15:41:39 Functions: 29 31 93.5 %

          Line data    Source code
       1             : /*
       2             :  * This file is part of PTN Engine
       3             :  *
       4             :  * Copyright (c) 2017 Eduardo Valgôde
       5             :  * Copyright (c) 2021 Kale Evans
       6             :  * Copyright (c) 2024 Eduardo Valgôde
       7             :  *
       8             :  * Licensed under the Apache License, Version 2.0 (the "License");
       9             :  * you may not use this file except in compliance with the License.
      10             :  * You may obtain a copy of the License at
      11             :  *
      12             :  * http://www.apache.org/licenses/LICENSE-2.0
      13             :  *
      14             :  * Unless required by applicable law or agreed to in writing, software
      15             :  * distributed under the License is distributed on an "AS IS" BASIS,
      16             :  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
      17             :  * See the License for the specific language governing permissions and
      18             :  * limitations under the License.
      19             :  */
      20             : 
      21             : #include "PTN_Engine/PTN_EngineImp.h"
      22             : #include "PTN_Engine/Executor/ActionsExecutorFactory.h"
      23             : #include "PTN_Engine/Utilities/LockWeakPtr.h"
      24             : #include <algorithm>
      25             : 
      26             : namespace ptne
      27             : {
      28             : using namespace std;
      29             : using enum PTN_Engine::ACTIONS_THREAD_OPTION;
      30             : 
      31          71 : PTN_EngineImp::PTN_EngineImp(PTN_Engine::ACTIONS_THREAD_OPTION actionsThreadOption)
      32          71 : : m_actionsThreadOption(actionsThreadOption)
      33          71 : , m_actionsExecutor(ActionsExecutorFactory::createExecutor(actionsThreadOption))
      34         142 : , m_eventLoop(*this)
      35             : {
      36          71 : }
      37             : 
      38          71 : PTN_EngineImp::~PTN_EngineImp()
      39             : {
      40          71 :         stop();
      41          71 : }
      42             : 
      43           1 : void PTN_EngineImp::clearInputPlaces()
      44             : {
      45           1 :         m_places.clearInputPlaces();
      46           1 :         m_newInputReceived = false;
      47           1 : }
      48             : 
      49           1 : void PTN_EngineImp::clearNet()
      50             : {
      51           1 :         if (isEventLoopRunning())
      52             :         {
      53           0 :                 throw PTN_Exception("Cannot clear net while the event loop is running.");
      54             :         }
      55           1 :         m_transitions.clear();
      56           1 :         m_places.clear();
      57           1 : }
      58             : 
      59         143 : void PTN_EngineImp::createTransition(const TransitionProperties &transitionProperties)
      60             : {
      61         285 :         createTransition(transitionProperties.name, transitionProperties.activationArcs,
      62         142 :                                          transitionProperties.destinationArcs, transitionProperties.inhibitorArcs,
      63         285 :                                          !transitionProperties.additionalConditionsNames.empty() ?
      64           8 :                                          m_conditions.getItems(transitionProperties.additionalConditionsNames) :
      65         135 :                                          createAnonymousConditions(transitionProperties.additionalConditions),
      66         143 :                                          transitionProperties.requireNoActionsInExecution);
      67         140 : }
      68             : 
      69         188 : void PTN_EngineImp::createPlace(PlaceProperties placeProperties)
      70             : {
      71         188 :         ActionFunction onEnterAction = placeProperties.onEnterAction;
      72         188 :         if (!placeProperties.onEnterActionFunctionName.empty())
      73             :         {
      74           8 :                 placeProperties.onEnterAction = m_actions.getItem(placeProperties.onEnterActionFunctionName);
      75             :         }
      76             : 
      77         187 :         ActionFunction onExitAction = placeProperties.onExitAction;
      78         187 :         if (!placeProperties.onExitActionFunctionName.empty())
      79             :         {
      80           0 :                 placeProperties.onExitAction = m_actions.getItem(placeProperties.onExitActionFunctionName);
      81             :         }
      82             : 
      83         187 :         auto place = make_shared<Place>(placeProperties, m_actionsExecutor);
      84         187 :         m_places.insert(place);
      85         192 : }
      86             : 
      87          98 : bool PTN_EngineImp::isEventLoopRunning() const
      88             : {
      89          98 :         return m_eventLoop.isRunning();
      90             : }
      91             : 
      92         168 : void PTN_EngineImp::stop() noexcept
      93             : {
      94         168 :         m_eventLoop.stop();
      95         168 : }
      96             : 
      97          11 : void PTN_EngineImp::registerAction(const string &name, const ActionFunction &action)
      98             : {
      99          11 :         m_actions.addItem(name, action);
     100           7 : }
     101             : 
     102          12 : void PTN_EngineImp::registerCondition(const string &name, const ConditionFunction &condition)
     103             : {
     104          12 :         m_conditions.addItem(name, condition);
     105          10 : }
     106             : 
     107         181 : size_t PTN_EngineImp::getNumberOfTokens(const string &place) const
     108             : {
     109         181 :         return m_places.getNumberOfTokens(place);
     110             : }
     111             : 
     112        2474 : void PTN_EngineImp::incrementInputPlace(const string &place)
     113             : {
     114        2474 :         m_places.incrementInputPlace(place);
     115        2473 :         m_newInputReceived = true;
     116        2473 :         m_eventLoop.notifyNewEvent();
     117        2473 : }
     118             : 
     119          63 : void PTN_EngineImp::setActionsThreadOption(const PTN_Engine::ACTIONS_THREAD_OPTION actionsThreadOption)
     120             : {
     121          63 :         if (isEventLoopRunning())
     122             :         {
     123           4 :                 throw PTN_Exception("Cannot change actions thread option while the event loop is running.");
     124             :         }
     125             : 
     126          59 :         unique_lock actionsThreadOptionGuard(m_actionsThreadOptionMutex);
     127             : 
     128          59 :         if (m_actionsThreadOption == actionsThreadOption)
     129             :         {
     130          56 :                 return;
     131             :         }
     132             : 
     133           3 :         m_actionsExecutor = ActionsExecutorFactory::createExecutor(actionsThreadOption);
     134           3 :         m_actionsThreadOption = actionsThreadOption;
     135             : 
     136           3 :         m_places.setActionsExecutor(m_actionsExecutor);
     137          59 : }
     138             : 
     139          46 : PTN_Engine::ACTIONS_THREAD_OPTION PTN_EngineImp::getActionsThreadOption() const
     140             : {
     141          46 :         shared_lock actionsThreadOptionGuard(m_actionsThreadOptionMutex);
     142          46 :         return m_actionsThreadOption;
     143          46 : }
     144             : 
     145           0 : void PTN_EngineImp::printState(ostream &o) const
     146             : {
     147           0 :         m_places.printState(o);
     148           0 : }
     149             : 
     150          39 : void PTN_EngineImp::execute(const bool log, ostream &o)
     151             : {
     152          39 :         m_eventLoop.start(log, o);
     153          39 : }
     154             : 
     155      806712 : bool PTN_EngineImp::executeInt(const bool log, ostream &o)
     156             : {
     157      806712 :         bool firedAtLeastOneTransition = false;
     158      806712 :         setNewInputReceived(false);
     159             : 
     160      806712 :         if (log)
     161             :         {
     162           0 :                 printState(o);
     163             :         }
     164             : 
     165     1633171 :         for (const auto &transition : enabledTransitions())
     166             :         {
     167     1652918 :                 if (auto enabledTransition = lockWeakPtr(transition))
     168             :                 {
     169      826459 :                         firedAtLeastOneTransition |= enabledTransition->execute();
     170      826459 :                 }
     171      806712 :         }
     172      806712 :         return firedAtLeastOneTransition;
     173             : }
     174             : 
     175        4510 : bool PTN_EngineImp::getNewInputReceived() const
     176             : {
     177        4510 :         return m_newInputReceived;
     178             : }
     179             : 
     180      806712 : void PTN_EngineImp::setNewInputReceived(const bool newInputReceived)
     181             : {
     182      806712 :         m_newInputReceived = newInputReceived;
     183      806712 : }
     184             : 
     185      807717 : vector<weak_ptr<Transition>> PTN_EngineImp::enabledTransitions() const
     186             : {
     187      807717 :         return m_transitions.collectEnabledTransitionsRandomly();
     188             : }
     189             : 
     190           1 : void PTN_EngineImp::setEventLoopSleepDuration(const PTN_Engine::EventLoopSleepDuration sleepDuration)
     191             : {
     192           1 :         m_eventLoop.setSleepDuration(sleepDuration);
     193           1 : }
     194             : 
     195           2 : PTN_Engine::EventLoopSleepDuration PTN_EngineImp::getEventLoopSleepDuration() const
     196             : {
     197           2 :         return m_eventLoop.getSleepDuration();
     198             : }
     199             : 
     200          19 : void PTN_EngineImp::addArc(const ArcProperties &arcProperties) const
     201             : {
     202          19 :         if (isEventLoopRunning())
     203             :         {
     204           0 :                 throw PTN_Exception("Cannot add arc while the event loop is running.");
     205             :         }
     206             : 
     207          19 :         if (!m_places.contains(arcProperties.placeName))
     208             :         {
     209           0 :                 throw PTN_Exception("The place " + arcProperties.placeName +
     210           0 :                                                         " must already exist in order to link to an arc.");
     211             :         }
     212          19 :         auto spPlace = m_places.getPlace(arcProperties.placeName);
     213             : 
     214          19 :         if (!m_transitions.contains(arcProperties.transitionName))
     215             :         {
     216           0 :                 throw PTN_Exception("The transition " + arcProperties.transitionName +
     217           0 :                                                         " must already exist in order to link to an arc.");
     218             :         }
     219             : 
     220          19 :         auto spTransition = m_transitions.getTransition(arcProperties.transitionName);
     221          19 :         spTransition->addArc(spPlace, arcProperties.type, arcProperties.weight);
     222          19 : }
     223             : 
     224           2 : void PTN_EngineImp::removeArc(const ArcProperties &arcProperties) const
     225             : {
     226           2 :         if (isEventLoopRunning())
     227             :         {
     228           0 :                 throw PTN_Exception("Cannot remove arc while the event loop is running.");
     229             :         }
     230             : 
     231           2 :         if (!m_places.contains(arcProperties.placeName))
     232             :         {
     233           1 :                 throw PTN_Exception("The place " + arcProperties.placeName +
     234           2 :                                                         " must already exist in order to unlink an arc.");
     235             :         }
     236           1 :         auto spPlace = m_places.getPlace(arcProperties.placeName);
     237             : 
     238           1 :         if (!m_transitions.contains(arcProperties.transitionName))
     239             :         {
     240           0 :                 throw PTN_Exception("The transition " + arcProperties.transitionName +
     241           0 :                                                         " must already exist in order to unlink an arc.");
     242             :         }
     243             : 
     244           1 :         auto spTransition = m_transitions.getTransition(arcProperties.transitionName);
     245           1 :         spTransition->removeArc(spPlace, arcProperties.type);
     246           1 : }
     247             : 
     248          12 : vector<PlaceProperties> PTN_EngineImp::getPlacesProperties() const
     249             : {
     250          12 :         return m_places.getPlacesProperties();
     251             : }
     252             : 
     253          13 : vector<TransitionProperties> PTN_EngineImp::getTransitionsProperties() const
     254             : {
     255          13 :         return m_transitions.getTransitionsProperties();
     256             : }
     257             : 
     258             : // Private
     259             : 
     260         142 : void PTN_EngineImp::createTransition(const string &name,
     261             :                                      const vector<ArcProperties> &activationArcs,
     262             :                                      const vector<ArcProperties> &destinationArcs,
     263             :                                      const vector<ArcProperties> &inhibitorArcs,
     264             :                                      const vector<pair<string, ConditionFunction>> &additionalConditions,
     265             :                                      const bool requireNoActionsInExecution)
     266             : {
     267             :         // if a transition with this name already exists in the net, throw an exception
     268         142 :         if (m_transitions.contains(name))
     269             :         {
     270           1 :                 throw PTN_Exception("Cannot create transition that already exists. Name: " + name);
     271             :         }
     272             : 
     273         800 :         auto getArcsFromArcsProperties = [this](const vector<ArcProperties> &arcProperties)
     274             :         {
     275         423 :                 vector<Arc> arcs;
     276         800 :                 for (const auto &arcProperty : arcProperties)
     277             :                 {
     278         377 :                         arcs.emplace_back(m_places.getPlace(arcProperty.placeName), arcProperty.weight);
     279             :                 }
     280         423 :                 return arcs;
     281           0 :         };
     282             : 
     283         143 :         m_transitions.insert(make_shared<Transition>(name, getArcsFromArcsProperties(activationArcs),
     284         283 :                                                                                                  getArcsFromArcsProperties(destinationArcs),
     285         283 :                                                                                                  getArcsFromArcsProperties(inhibitorArcs), additionalConditions,
     286             :                                                                                                  requireNoActionsInExecution));
     287         140 : }
     288             : 
     289             : vector<pair<string, ConditionFunction>>
     290         135 : PTN_EngineImp::createAnonymousConditions(const vector<ConditionFunction> &conditions) const
     291             : {
     292         135 :         vector<pair<string, ConditionFunction>> anonymousConditionsVector;
     293         135 :         ranges::transform(conditions, back_inserter(anonymousConditionsVector),
     294          22 :                                           [](const auto &condition) { return pair<string, ConditionFunction>("", condition); });
     295         135 :         return anonymousConditionsVector;
     296           0 : }
     297             : 
     298             : } // namespace ptne

Generated by: LCOV version 1.14