Line data Source code
1 : /* 2 : * This file is part of PTN Engine 3 : * 4 : * Copyright (c) 2017-2024 Eduardo ValgĂ´de 5 : * 6 : * Licensed under the Apache License, Version 2.0 (the "License"); 7 : * you may not use this file except in compliance with the License. 8 : * You may obtain a copy of the License at 9 : * 10 : * http://www.apache.org/licenses/LICENSE-2.0 11 : * 12 : * Unless required by applicable law or agreed to in writing, software 13 : * distributed under the License is distributed on an "AS IS" BASIS, 14 : * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 : * See the License for the specific language governing permissions and 16 : * limitations under the License. 17 : */ 18 : 19 : #include "PTN_Engine/Place.h" 20 : #include "PTN_Engine/Executor/IActionsExecutor.h" 21 : #include "PTN_Engine/PTN_EngineImp.h" 22 : #include "PTN_Engine/PTN_Exception.h" 23 : #include "PTN_Engine/Utilities/LockWeakPtr.h" 24 : #include <mutex> 25 : #include <string> 26 : #include <thread> 27 : 28 : 29 : namespace ptne 30 : { 31 : using namespace std; 32 : 33 282 : Place::~Place() = default; 34 : 35 284 : Place::Place(const PlaceProperties &placeProperties, const shared_ptr<IActionsExecutor> &executor) 36 284 : : m_name(placeProperties.name) 37 284 : , m_onEnterActionName(placeProperties.onEnterActionFunctionName) 38 286 : , m_onEnterAction(placeProperties.onEnterAction) 39 284 : , m_onExitActionName(placeProperties.onExitActionFunctionName) 40 284 : , m_onExitAction(placeProperties.onExitAction) 41 284 : , m_numberOfTokens(placeProperties.initialNumberOfTokens) 42 284 : , m_isInputPlace(placeProperties.input) 43 852 : , m_actionsExecutor(executor) 44 : { 45 284 : if (!m_onEnterActionName.empty() && m_onEnterAction == nullptr) 46 : { 47 1 : throw PTN_Exception("On enter action function must be specified."); 48 : } 49 : 50 283 : if (!m_onExitActionName.empty() && m_onExitAction == nullptr) 51 : { 52 1 : throw PTN_Exception("On exit action function must be specified."); 53 : } 54 294 : } 55 : 56 252 : string Place::getName() const 57 : { 58 252 : return m_name; 59 : } 60 : 61 811363 : void Place::enterPlace(const size_t tokens) 62 : { 63 811363 : unique_lock guard(m_mutex); 64 811363 : increaseNumberOfTokens(tokens); 65 811361 : if (m_onEnterAction == nullptr) 66 : { 67 6842 : return; 68 : } 69 804519 : while (m_blockStartingOnEnterActions) 70 : { 71 : // TO DO make this wait period configurable 72 : // add a max wait time after which an exception 73 : // is thrown. 74 0 : this_thread::sleep_for(100ms); 75 : } 76 804519 : lockWeakPtr(m_actionsExecutor)->executeAction(m_onEnterAction, m_onEnterActionsInExecution); 77 811363 : } 78 : 79 1206711 : void Place::exitPlace(const size_t tokens) 80 : { 81 1206711 : unique_lock guard(m_mutex); 82 1206711 : decreaseNumberOfTokens(tokens); 83 1206710 : if (m_onExitAction == nullptr) 84 : { 85 1202282 : return; 86 : } 87 4428 : lockWeakPtr(m_actionsExecutor)->executeAction(m_onExitAction, m_onExitActionsInExecution); 88 1206711 : } 89 : 90 811363 : void Place::increaseNumberOfTokens(const size_t tokens) 91 : { 92 811363 : if (tokens == 0) 93 : { 94 1 : throw NullTokensException(); 95 : } 96 : 97 811362 : if (tokens > ULLONG_MAX - m_numberOfTokens) 98 : { 99 1 : throw OverflowException(tokens); 100 : } 101 : 102 811361 : m_numberOfTokens += tokens; 103 811361 : } 104 : 105 1206711 : void Place::decreaseNumberOfTokens(const size_t tokens) 106 : { 107 1206711 : if (m_numberOfTokens < tokens) 108 : { 109 1 : throw NotEnoughTokensException(); 110 : } 111 1206710 : if (tokens == 0) // reset 112 : { 113 0 : m_numberOfTokens = 0; 114 : } 115 : else 116 : { 117 1206710 : m_numberOfTokens -= tokens; 118 : } 119 1206710 : } 120 : 121 13 : void Place::setNumberOfTokens(const size_t tokens) 122 : { 123 13 : unique_lock guard(m_mutex); 124 13 : m_numberOfTokens = tokens; 125 13 : } 126 : 127 3882132 : size_t Place::getNumberOfTokens() const 128 : { 129 3882132 : shared_lock guard(m_mutex); 130 3882132 : return m_numberOfTokens; 131 3882132 : } 132 : 133 2678 : bool Place::isInputPlace() const 134 : { 135 2678 : shared_lock guard(m_mutex); 136 2678 : return m_isInputPlace; 137 2678 : } 138 : 139 1 : string Place::getOnEnterActionName() const 140 : { 141 1 : shared_lock guard(m_mutex); 142 2 : return m_onEnterActionName; 143 1 : } 144 : 145 1 : string Place::getOnExitActionName() const 146 : { 147 1 : shared_lock guard(m_mutex); 148 2 : return m_onExitActionName; 149 1 : } 150 : 151 10 : bool Place::isOnEnterActionInExecution() const 152 : { 153 10 : return m_onEnterActionsInExecution > 0; 154 : } 155 : 156 8 : void Place::blockStartingOnEnterActions(const bool value) 157 : { 158 8 : m_blockStartingOnEnterActions = value; 159 8 : } 160 : 161 32 : PlaceProperties Place::placeProperties() const 162 : { 163 32 : PlaceProperties placeProperties; 164 32 : placeProperties.name = m_name; 165 32 : placeProperties.onEnterActionFunctionName = m_onEnterActionName; 166 32 : placeProperties.onExitActionFunctionName = m_onExitActionName; 167 32 : placeProperties.initialNumberOfTokens = m_numberOfTokens; 168 32 : placeProperties.onEnterAction = m_onEnterAction; 169 32 : placeProperties.onExitAction = m_onExitAction; 170 32 : placeProperties.input = m_isInputPlace; 171 32 : return placeProperties; 172 0 : } 173 : 174 0 : void Place::setActionsExecutor(shared_ptr<IActionsExecutor> &actionsExecutor) 175 : { 176 0 : unique_lock guard(m_mutex); 177 0 : m_actionsExecutor = actionsExecutor; 178 0 : } 179 : 180 : } // namespace ptne