diff --git a/Doc/Doxygen/FullDocumentation.doxy b/Doc/Doxygen/FullDocumentation.doxy index b2a4c86..9254e8a 100644 --- a/Doc/Doxygen/FullDocumentation.doxy +++ b/Doc/Doxygen/FullDocumentation.doxy @@ -114,7 +114,7 @@ CREATE_SUBDIRS_LEVEL = 8 # U+3044. # The default value is: NO. -ALLOW_UNICODE_NAMES = NO +ALLOW_UNICODE_NAMES = YES # The OUTPUT_LANGUAGE tag is used to specify the language in which all # documentation generated by doxygen is written. Doxygen will use this @@ -395,7 +395,7 @@ AUTOLINK_SUPPORT = YES # diagrams that involve STL classes more complete and accurate. # The default value is: NO. -BUILTIN_STL_SUPPORT = NO +BUILTIN_STL_SUPPORT = YES # If you use Microsoft's C++/CLI language, you should set this option to YES to # enable parsing support. diff --git a/Examples/CMakeLists.txt b/Examples/CMakeLists.txt index 247f24e..716411b 100644 --- a/Examples/CMakeLists.txt +++ b/Examples/CMakeLists.txt @@ -18,8 +18,7 @@ cmake_minimum_required (VERSION 3.8) add_subdirectory(Factorial) -add_subdirectory(PhoneMenu) add_subdirectory(Elevator) if(BUILD_IMPORT_EXPORT) - add_subdirectory(PhoneMenuXML) + add_subdirectory(PhoneMenu) endif(BUILD_IMPORT_EXPORT) diff --git a/Examples/Elevator/Controller/ElevatorController.cpp b/Examples/Elevator/Controller/ElevatorController.cpp old mode 100644 new mode 100755 index 5d7386d..2de3a74 --- a/Examples/Elevator/Controller/ElevatorController.cpp +++ b/Examples/Elevator/Controller/ElevatorController.cpp @@ -1,7 +1,7 @@ /* * This file is part of PTN Engine * - * Copyright (c) 2017-2023 Eduardo Valgôde + * Copyright (c) 2017-2024 Eduardo Valgôde * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -18,7 +18,6 @@ #include "Controller/ElevatorController.h" #include "Controller/ElevatorPetriNet.h" - #include #include #include @@ -43,30 +42,13 @@ void printFloorList(const unordered_set &floors) } // namespace ElevatorController::ElevatorController() -: m_pPetriNet(nullptr) -, m_currentFloor(s_bottomFloor) +: m_currentFloor(s_bottomFloor) , m_toAddToDestination(s_bottomFloor) -, m_destinations() -, m_nextTravelDestinations() -, m_floorsWaitingToGoUp() -, m_floorsWaitingToGoDown() { m_pPetriNet = make_unique(*this); m_pPetriNet->execute(false); } -ElevatorController::~ElevatorController() -{ -} - -void ElevatorController::checkPetriNetPointer() const -{ - if (m_pPetriNet == nullptr) - { - throw runtime_error("Petri net not available."); - } -} - void ElevatorController::openDoors() { m_pPetriNet->openDoors(); @@ -80,7 +62,7 @@ void ElevatorController::closeDoors() bool ElevatorController::callElevatorUp(const int floor) { { - unique_lock l(m_mutex); + unique_lock l(m_mutex); if (floor < s_bottomFloor || floor >= s_topFloor) { return false; @@ -94,7 +76,7 @@ bool ElevatorController::callElevatorUp(const int floor) bool ElevatorController::callElevatorDown(const int floor) { { - unique_lock l(m_mutex); + unique_lock l(m_mutex); if (floor <= s_bottomFloor || floor > s_topFloor) { return false; @@ -108,7 +90,7 @@ bool ElevatorController::callElevatorDown(const int floor) bool ElevatorController::setDestinationFloor(const int floor) { { - unique_lock l(m_mutex); + unique_lock l(m_mutex); if (floor < s_bottomFloor || floor > s_topFloor) { return false; @@ -127,7 +109,7 @@ void ElevatorController::stop() // Actions void ElevatorController::addDestination1() { - unique_lock l(m_mutex); + unique_lock l(m_mutex); m_nextTravelDestinations.erase(m_toAddToDestination); m_destinations.insert(m_toAddToDestination); printDestinations(); @@ -135,7 +117,7 @@ void ElevatorController::addDestination1() void ElevatorController::addDestination2() { - unique_lock l(m_mutex); + unique_lock l(m_mutex); if (m_destinations.contains(m_toAddToDestination)) { return; @@ -150,14 +132,14 @@ void ElevatorController::addDestination2() void ElevatorController::addWaitingToGoDown() { - unique_lock l(m_mutex); + unique_lock l(m_mutex); m_floorsWaitingToGoDown.insert(m_toAddToDestination); printWaitingGoDown(); } void ElevatorController::addWaitingToGoUp() { - unique_lock l(m_mutex); + unique_lock l(m_mutex); m_floorsWaitingToGoUp.insert(m_toAddToDestination); printWaitingGoUp(); } @@ -176,7 +158,7 @@ void ElevatorController::removeDestinationGD() void ElevatorController::removeDestination() { - unique_lock l(m_mutex); + unique_lock l(m_mutex); cout << "Removed " << m_currentFloor << " from destinations" << endl; auto it = m_destinations.find(m_currentFloor); if (it != m_destinations.end()) @@ -187,7 +169,7 @@ void ElevatorController::removeDestination() void ElevatorController::removeCurrentFromWaitingToGoDown() { - unique_lock l(m_mutex); + unique_lock l(m_mutex); size_t i = m_floorsWaitingToGoDown.erase(m_currentFloor); if (i > 0) { @@ -197,7 +179,7 @@ void ElevatorController::removeCurrentFromWaitingToGoDown() void ElevatorController::removeCurrentFromWaitingToGoUp() { - unique_lock l(m_mutex); + unique_lock l(m_mutex); size_t i = m_floorsWaitingToGoUp.erase(m_currentFloor); if (i > 0) { @@ -207,14 +189,14 @@ void ElevatorController::removeCurrentFromWaitingToGoUp() void ElevatorController::rotateLists() { - unique_lock l(m_mutex); + unique_lock l(m_mutex); swap(m_destinations, m_nextTravelDestinations); m_destinations.erase(m_currentFloor); } void ElevatorController::increaseFloor() { - unique_lock l(m_mutex); + unique_lock l(m_mutex); cout << "Ascending... " << endl; ++m_currentFloor; printCurrentFloor(); @@ -222,7 +204,7 @@ void ElevatorController::increaseFloor() void ElevatorController::decreaseFloor() { - unique_lock l(m_mutex); + unique_lock l(m_mutex); cout << "Descending... " << endl; --m_currentFloor; printCurrentFloor(); @@ -230,18 +212,18 @@ void ElevatorController::decreaseFloor() void ElevatorController::mergeGoingUpGTCurrent() { - unique_lock l(m_mutex); + unique_lock l(m_mutex); mergeToDestinations(m_floorsWaitingToGoDown, false); } void ElevatorController::mergeMinGoingUp() { - unique_lock l(m_mutex); + unique_lock l(m_mutex); if (m_floorsWaitingToGoUp.empty()) { return; } - const int minWaiting = *min_element(m_floorsWaitingToGoUp.begin(), m_floorsWaitingToGoUp.end()); + const int minWaiting = *ranges::min_element(m_floorsWaitingToGoUp.begin(), m_floorsWaitingToGoUp.end()); m_destinations.insert(minWaiting); m_floorsWaitingToGoUp.erase(minWaiting); @@ -251,12 +233,12 @@ void ElevatorController::mergeMinGoingUp() void ElevatorController::mergeMaxGoingDown() { - unique_lock l(m_mutex); + unique_lock l(m_mutex); if (m_floorsWaitingToGoDown.empty()) { return; } - const int maxWaiting = *max_element(m_floorsWaitingToGoDown.begin(), m_floorsWaitingToGoDown.end()); + const int maxWaiting = *ranges::max_element(m_floorsWaitingToGoDown.begin(), m_floorsWaitingToGoDown.end()); m_destinations.insert(maxWaiting); m_floorsWaitingToGoDown.erase(maxWaiting); @@ -266,7 +248,7 @@ void ElevatorController::mergeMaxGoingDown() void ElevatorController::mergePostponedToCurrent() { - unique_lock l(m_mutex); + unique_lock l(m_mutex); m_destinations.insert(m_nextTravelDestinations.begin(), m_nextTravelDestinations.end()); m_nextTravelDestinations.clear(); @@ -275,7 +257,7 @@ void ElevatorController::mergePostponedToCurrent() void ElevatorController::mergeGoingDownSTCurrent() { - unique_lock l(m_mutex); + unique_lock l(m_mutex); mergeToDestinations(m_floorsWaitingToGoDown, true); } @@ -286,7 +268,7 @@ void ElevatorController::mergeToDestinations(unordered_set &toAdd, const bo { deleted = false; auto floorIt = - std::find_if(toAdd.cbegin(), toAdd.cend(), + ranges::find_if(toAdd.cbegin(), toAdd.cend(), [this, &lessThan](const int floor) { return (lessThan && floor < m_currentFloor) || (!lessThan && floor > m_currentFloor); }); if (floorIt != toAdd.cend()) @@ -313,7 +295,7 @@ bool ElevatorController::isFloorNotInList() const bool ElevatorController::isFloorInList() const { - shared_lock l(m_mutex); + shared_lock l(m_mutex); return m_destinations.contains(m_currentFloor); } @@ -324,69 +306,69 @@ bool ElevatorController::isDestinationListNotEmpty() const bool ElevatorController::isDestinationListEmpty() const { - shared_lock l(m_mutex); + shared_lock l(m_mutex); return m_destinations.empty(); } bool ElevatorController::isMarkedFloorNotCurrentFloor() const { - shared_lock l(m_mutex); + shared_lock l(m_mutex); return m_toAddToDestination != m_currentFloor; } bool ElevatorController::isMarkedFloorGreaterThanCurrentFloor() const { - shared_lock l(m_mutex); + shared_lock l(m_mutex); return m_toAddToDestination > m_currentFloor; } bool ElevatorController::isMarkedFloorSmallerThanCurrentFloor() const { - shared_lock l(m_mutex); + shared_lock l(m_mutex); return m_toAddToDestination < m_currentFloor; } bool ElevatorController::isMinSmallerThanCurrent() const { - shared_lock l(m_mutex); + shared_lock l(m_mutex); if (m_destinations.empty()) { return false; } - int minFloor = *min_element(m_destinations.cbegin(), m_destinations.cend()); + int minFloor = *ranges::min_element(m_destinations.cbegin(), m_destinations.cend()); return minFloor < m_currentFloor; } bool ElevatorController::isMinGreaterThanCurrent() const { - shared_lock l(m_mutex); + shared_lock l(m_mutex); if (m_destinations.empty()) { return false; } - int minFloor = *min_element(m_destinations.cbegin(), m_destinations.cend()); + int minFloor = *ranges::min_element(m_destinations.cbegin(), m_destinations.cend()); return minFloor > m_currentFloor; } bool ElevatorController::isMaxSmallerThanCurrent() const { - shared_lock l(m_mutex); + shared_lock l(m_mutex); if (m_destinations.empty()) { return false; } - int maxFloor = *max_element(m_destinations.cbegin(), m_destinations.cend()); + int maxFloor = *ranges::max_element(m_destinations.cbegin(), m_destinations.cend()); return maxFloor < m_currentFloor; } bool ElevatorController::isMaxGreaterThanCurrent() const { - shared_lock l(m_mutex); + shared_lock l(m_mutex); if (m_destinations.empty()) { return false; } - int maxFloor = *max_element(m_destinations.cbegin(), m_destinations.cend()); + int maxFloor = *ranges::max_element(m_destinations.cbegin(), m_destinations.cend()); return maxFloor > m_currentFloor; } @@ -395,7 +377,7 @@ bool ElevatorController::isMaxGreaterThanCurrent() const void ElevatorController::elevatorStopped() const { - unique_lock l(m_mutex); + unique_lock l(m_mutex); cout << "Elevator stopped" << endl; } @@ -406,25 +388,25 @@ void ElevatorController::elevatorMoving() const void ElevatorController::doorsAreOpen() const { - unique_lock l(m_mutex); + unique_lock l(m_mutex); cout << "Elevator doors are open" << endl; } void ElevatorController::doorsAreClosed() const { - unique_lock l(m_mutex); + unique_lock l(m_mutex); cout << "Elevator doors are closed" << endl; } void ElevatorController::goingUp() const { - unique_lock l(m_mutex); + unique_lock l(m_mutex); cout << "Scheduled to go up." << endl; } void ElevatorController::goingDown() const { - unique_lock l(m_mutex); + unique_lock l(m_mutex); cout << "Scheduled to go down." << endl; } @@ -459,7 +441,7 @@ void ElevatorController::printWaitingGoUp() const void ElevatorController::printSchedule() const { - shared_lock l(m_mutex); + shared_lock l(m_mutex); cout << endl; cout << "Scheduled floors: " << endl; printDestinations(); diff --git a/Examples/Elevator/Controller/ElevatorController.h b/Examples/Elevator/Controller/ElevatorController.h old mode 100644 new mode 100755 index a13102d..2b6490a --- a/Examples/Elevator/Controller/ElevatorController.h +++ b/Examples/Elevator/Controller/ElevatorController.h @@ -18,12 +18,11 @@ #pragma once +#include "Controller/IElevatorPetriNet.h" #include #include #include -class IElevatorPetriNet; - //! Elevator controller class class ElevatorController { @@ -33,8 +32,6 @@ class ElevatorController //! Constructor. ElevatorController(); - ~ElevatorController(); - //! Command to open elevator doors. void openDoors(); @@ -68,7 +65,7 @@ class ElevatorController using PtrPetriNet = std::unique_ptr; //! The state machine of the controller. - PtrPetriNet m_pPetriNet; + PtrPetriNet m_pPetriNet = nullptr; //! Floor where the elevator currently is. int m_currentFloor = 0; @@ -97,9 +94,6 @@ class ElevatorController //! Remove current floor from m_floorsWaitingToGoUp void removeCurrentFromWaitingToGoUp(); - //! Check if pointer to PTN is valid. - void checkPetriNetPointer() const; - // Information void printCurrentFloor() const; void printDestinations() const; diff --git a/Examples/Elevator/Controller/ElevatorPetriNet.cpp b/Examples/Elevator/Controller/ElevatorPetriNet.cpp old mode 100644 new mode 100755 index 46f51c9..469e407 --- a/Examples/Elevator/Controller/ElevatorPetriNet.cpp +++ b/Examples/Elevator/Controller/ElevatorPetriNet.cpp @@ -1,7 +1,7 @@ /* * This file is part of PTN Engine * - * Copyright (c) 2017-2023 Eduardo Valgôde + * Copyright (c) 2017-2024 Eduardo Valgôde * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -41,6 +41,8 @@ ElevatorPetriNet::ElevatorPetriNet(ElevatorController &elevatorController) createCallingButtonTransitions(); } +ElevatorPetriNet::~ElevatorPetriNet() = default; + void ElevatorPetriNet::closeDoors() { incrementInput("CloseDoors"); @@ -83,300 +85,584 @@ void ElevatorPetriNet::stop() void ElevatorPetriNet::createInputPlaces() { - createPlace("CloseDoors", 0, true); - createPlace("OpenDoors", 0, true); - createPlace("CallButtonUp", 0, true); - createPlace("CallButtonDown", 0, true); - createPlace("DestinationButton", 0, true); + createPlace({ .name="CloseDoors", + .input=true }); + createPlace({ .name="OpenDoors", + .input=true }); + createPlace({ .name="CallButtonUp", + .input=true }); + createPlace({ .name="CallButtonDown", + .input=true }); + createPlace({ .name="DestinationButton", + .input=true }); } void ElevatorPetriNet::createCabinePlaces() { - createPlace("Stopped", 0, bind(&ElevatorController::elevatorStopped, &m_elevatorController)); - createPlace("Stopped_", 1); - createPlace("Moving", 0, bind(&ElevatorController::elevatorMoving, &m_elevatorController)); - createPlace("Moving_", 0); - createPlace("DoorsOpened", 1, bind(&ElevatorController::doorsAreOpen, &m_elevatorController)); - createPlace("DoorsClosed", 0, bind(&ElevatorController::doorsAreClosed, &m_elevatorController)); - createPlace("DoorsClosed_", 0); - - createPlace("RemoveFromListGU", 0, bind(&ElevatorController::removeDestinationGU, &m_elevatorController)); - createPlace("RemoveFromListGD", 0, bind(&ElevatorController::removeDestinationGD, &m_elevatorController)); - createPlace("ArrivedDestination", 0); - - createPlace("ProcessLists", 0); - createPlace("ProcessedLists", 1, bind(&ElevatorController::processedLists, &m_elevatorController)); - - createPlace("GoingUp", 0, bind(&ElevatorController::goingUp, &m_elevatorController)); - createPlace("GoingUp_", 0); - createPlace("GoingDown", 0, bind(&ElevatorController::goingDown, &m_elevatorController)); - createPlace("GoingDown_", 0); + createPlace({ .name = "Stopped", + .onEnterAction = bind_front(&ElevatorController::elevatorStopped, &m_elevatorController) }); + createPlace({ .name = "Stopped_", + .initialNumberOfTokens = 1 }); + createPlace({ .name="Moving", + .onEnterAction=bind_front(&ElevatorController::elevatorMoving, &m_elevatorController)}); + createPlace({ .name="Moving_"}); + createPlace({ .name="DoorsOpened", .initialNumberOfTokens=1, + .onEnterAction=bind_front(&ElevatorController::doorsAreOpen, &m_elevatorController)}); + createPlace({ .name="DoorsClosed", + .onEnterAction=bind_front(&ElevatorController::doorsAreClosed, &m_elevatorController)}); + createPlace({ .name="DoorsClosed_"}); + + createPlace({ .name="RemoveFromListGU", + .onEnterAction=bind_front(&ElevatorController::removeDestinationGU, &m_elevatorController) }); + createPlace({ .name="RemoveFromListGD", + .onEnterAction=bind_front(&ElevatorController::removeDestinationGD, &m_elevatorController) }); + createPlace({ .name="ArrivedDestination" }); + + createPlace({ .name="ProcessLists" }); + createPlace({ .name="ProcessedLists", + .initialNumberOfTokens=1, + .onEnterAction=bind_front(&ElevatorController::processedLists, &m_elevatorController) }); + + createPlace({ .name="GoingUp", + .onEnterAction=bind_front(&ElevatorController::goingUp, &m_elevatorController) }); + createPlace({ .name="GoingUp_" }); + createPlace({ .name="GoingDown", + .onExitAction=bind_front(&ElevatorController::goingDown, &m_elevatorController) }); + createPlace({ .name="GoingDown_" }); } void ElevatorPetriNet::createArrivalPlaces() { - createPlace("Ready", 1); - - createPlace("SwapGD", 0, bind(&ElevatorController::rotateLists, &m_elevatorController)); - createPlace("SwapGU", 0, bind(&ElevatorController::rotateLists, &m_elevatorController)); - - createPlace("MergeGoingUpGTCurrent", 0, - bind(&ElevatorController::mergeGoingUpGTCurrent, &m_elevatorController)); - createPlace("MergeMinGoingUp1", 0, bind(&ElevatorController::mergeMinGoingUp, &m_elevatorController)); - createPlace("MergeMaxGoingDown1", 0, bind(&ElevatorController::mergeMaxGoingDown, &m_elevatorController)); - createPlace("MergePostponedToCurrent11", 0, - bind(&ElevatorController::mergePostponedToCurrent, &m_elevatorController)); - createPlace("MergePostponedToCurrent12", 0, - bind(&ElevatorController::mergePostponedToCurrent, &m_elevatorController)); - - createPlace("MergeGoingDownSTCurrent", 0, - bind(&ElevatorController::mergeGoingDownSTCurrent, &m_elevatorController)); - createPlace("MergeMaxGoingDown2", 0, bind(&ElevatorController::mergeMaxGoingDown, &m_elevatorController)); - createPlace("MergeMinGoingUp2", 0, bind(&ElevatorController::mergeMinGoingUp, &m_elevatorController)); - createPlace("MergePostponedToCurrent21", 0, - bind(&ElevatorController::mergePostponedToCurrent, &m_elevatorController)); - createPlace("MergePostponedToCurrent22", 0, - bind(&ElevatorController::mergePostponedToCurrent, &m_elevatorController)); + createPlace({ .name = "Ready", + .initialNumberOfTokens=1 }); + + createPlace({ .name="SwapGD", + .onEnterAction=bind_front(&ElevatorController::rotateLists, &m_elevatorController)}); + createPlace({ .name="SwapGU", + .onEnterAction=bind_front(&ElevatorController::rotateLists, &m_elevatorController)}); + + createPlace({ .name="MergeGoingUpGTCurrent", + .onEnterAction=bind_front(&ElevatorController::mergeGoingUpGTCurrent, &m_elevatorController) }); + createPlace({ .name="MergeMinGoingUp1", + .onEnterAction=bind_front(&ElevatorController::mergeMinGoingUp, &m_elevatorController) }); + createPlace({ .name="MergeMaxGoingDown1", + .onEnterAction=bind_front(&ElevatorController::mergeMaxGoingDown, &m_elevatorController) }); + createPlace({ .name="MergePostponedToCurrent11", + .onEnterAction=bind_front(&ElevatorController::mergePostponedToCurrent, &m_elevatorController) }); + createPlace({ .name="MergePostponedToCurrent12", + .onEnterAction=bind_front(&ElevatorController::mergePostponedToCurrent, &m_elevatorController) }); + createPlace({ .name="MergeGoingDownSTCurrent", + .onEnterAction=bind_front(&ElevatorController::mergeGoingDownSTCurrent, &m_elevatorController) }); + createPlace({ .name="MergeMaxGoingDown2", + .onEnterAction=bind_front(&ElevatorController::mergeMaxGoingDown, &m_elevatorController) }); + createPlace({ .name="MergeMinGoingUp2", + .onEnterAction=bind_front(&ElevatorController::mergeMinGoingUp, &m_elevatorController) }); + createPlace({ .name="MergePostponedToCurrent21", + .onEnterAction=bind_front(&ElevatorController::mergePostponedToCurrent, &m_elevatorController) }); + createPlace({ .name="MergePostponedToCurrent22", + .onEnterAction=bind_front(&ElevatorController::mergePostponedToCurrent, &m_elevatorController) }); } void ElevatorPetriNet::createButtonPressPlaces() { - createPlace("AddToTravel", 0, bind(&ElevatorController::addDestination1, &m_elevatorController)); - createPlace("AddToNextTravel", 0, bind(&ElevatorController::addDestination2, &m_elevatorController)); - createPlace("WaitToGoUp", 0, bind(&ElevatorController::addWaitingToGoUp, &m_elevatorController)); - createPlace("WaitToGoDown", 0, bind(&ElevatorController::addWaitingToGoDown, &m_elevatorController)); - createPlace("D1", 0); - createPlace("D2", 0); - createPlace("D3", 0); - createPlace("D4", 0); - createPlace("D5", 0); + createPlace({ .name = "AddToTravel", + .onEnterAction=bind_front(&ElevatorController::addDestination1, &m_elevatorController) }); + createPlace({ .name = "AddToNextTravel", + .onEnterAction=bind_front(&ElevatorController::addDestination2, &m_elevatorController) }); + createPlace({ .name = "WaitToGoUp", + .onEnterAction=bind_front(&ElevatorController::addWaitingToGoUp, &m_elevatorController) }); + createPlace({ .name = "WaitToGoDown", + .onEnterAction=bind_front(&ElevatorController::addWaitingToGoDown, &m_elevatorController) }); + createPlace({ .name="D1"}); + createPlace({ .name="D2"}); + createPlace({ .name="D3"}); + createPlace({ .name="D4"}); + createPlace({ .name="D5"}); } void ElevatorPetriNet::createSimulationPlaces() { - createPlace("IncreaseFloor", 0, bind(&ElevatorController::increaseFloor, &m_elevatorController)); - createPlace("DecreaseFloor", 0, bind(&ElevatorController::decreaseFloor, &m_elevatorController)); + createPlace({ .name="IncreaseFloor", + .onEnterAction=bind_front(&ElevatorController::increaseFloor, &m_elevatorController)}); + createPlace({ .name="DecreaseFloor", + .onEnterAction=bind_front(&ElevatorController::decreaseFloor, &m_elevatorController)}); } void ElevatorPetriNet::createCabineTransitions() { - createTransition({ "CloseDoors", "Stopped_", "DoorsOpened" }, { "Stopped_", "DoorsClosed" }); - - createTransition({ "OpenDoors", "Stopped_", "DoorsClosed_" }, { "Stopped_", "DoorsOpened" }); - - createTransition({ "Stopped_", "DoorsClosed_", "ProcessedLists" }, { "DoorsClosed_", "Moving" }, - { "OpenDoors" }, - { bind(&ElevatorController::isDestinationListNotEmpty, &m_elevatorController) }, true); - - createTransition({ "ArrivedDestination", "Moving_" }, { "Stopped", "OpenDoors" }); + createTransition({ .name = "T1", + .activationArcs = { { .placeName = "CloseDoors" }, + { .placeName = "Stopped_" }, + { .placeName = "DoorsOpened" } }, + .destinationArcs = { { .placeName = "Stopped_" }, + { .placeName = "DoorsClosed" } } }); + + createTransition({ .name = "T2", + .activationArcs = { { .placeName = "OpenDoors" }, + { .placeName = "Stopped_" }, + { .placeName = "DoorsClosed_" } }, + .destinationArcs = { { .placeName = "Stopped_" }, + { .placeName = "DoorsOpened" } } }); + + createTransition({ .name = "T3", + .activationArcs = { { .placeName = "Stopped_" }, + { .placeName = "DoorsClosed_" }, + { .placeName = "ProcessedLists" } }, + .destinationArcs = { { .placeName = "DoorsClosed_" }, + { .placeName = "Moving" } }, + .inhibitorArcs = { { .placeName = "OpenDoors" } }, + .additionalConditions{ bind_front(&ElevatorController::isDestinationListNotEmpty, &m_elevatorController) }, + .requireNoActionsInExecution=true }); + + createTransition({ .name = "T4", + .activationArcs = { { .placeName = "ArrivedDestination" }, + { .placeName = "Moving_" } }, + .destinationArcs = { { .placeName = "Stopped" }, + { .placeName = "OpenDoors" } } }); // Trick to prevent read arcs from executing multiple times one place - createTransition({ "DoorsClosed" }, { "DoorsClosed_" }); - createTransition({ "Moving" }, { "Moving_" }); - createTransition({ "Stopped" }, { "Stopped_" }); - createTransition({ "GoingUp" }, { "GoingUp_" }); - createTransition({ "GoingDown" }, { "GoingDown_" }); + createTransition({ .name = "T5", + .activationArcs = { { .placeName = "DoorsClosed" } }, + .destinationArcs = { { .placeName = "DoorsClosed_" } } }); + createTransition({ .name = "T6", + .activationArcs = { { .placeName = "Moving" } }, + .destinationArcs = { { .placeName = "Moving_" } } }); + createTransition({ .name = "T7", + .activationArcs = { { .placeName = "Stopped" } }, + .destinationArcs = { { .placeName = "Stopped_" } } }); + createTransition({ .name = "T8", + .activationArcs = { { .placeName = "GoingUp" } }, + .destinationArcs = { { .placeName = "GoingUp_" } } }); + createTransition({ .name = "T9", + .activationArcs = { { .placeName = "GoingDown" } }, + .destinationArcs = { { .placeName = "GoingDown_" } } }); } void ElevatorPetriNet::createSimulationTransitions() { - createTransition({ "GoingUp_", "Ready", "Moving_" }, { "Moving_", "GoingUp_", "IncreaseFloor" }, - vector{ "ArrivedDestination" }); - - createTransition({ "GoingDown_", "Ready", "Moving_" }, { "Moving_", "GoingDown_", "DecreaseFloor" }, - vector{ "ArrivedDestination" }); - - createTransition({ "IncreaseFloor" }, { "Ready" }, - { bind(&ElevatorController::isFloorNotInList, &m_elevatorController) }, true); - - createTransition({ "DecreaseFloor" }, { "Ready" }, - { bind(&ElevatorController::isFloorNotInList, &m_elevatorController) }, true); - - createTransition({ "IncreaseFloor" }, { "RemoveFromListGU" }, - { bind(&ElevatorController::isFloorInList, &m_elevatorController) }, true); - - createTransition({ "RemoveFromListGU" }, { "ProcessLists", "ArrivedDestination", "Ready" }); - - createTransition({ "DecreaseFloor" }, { "RemoveFromListGD" }, - { bind(&ElevatorController::isFloorInList, &m_elevatorController) }, true); - - createTransition({ "RemoveFromListGD" }, { "ProcessLists", "ArrivedDestination", "Ready" }); + createTransition({ .name = "T10", + .activationArcs = { { .placeName = "GoingUp_" }, + { .placeName = "Ready" }, + { .placeName = "Moving_" } }, + .destinationArcs = { { .placeName = "Moving_" }, + { .placeName = "GoingUp_" }, + { .placeName = "IncreaseFloor" } }, + .inhibitorArcs = { { .placeName = "ArrivedDestination" } } }); + + createTransition({ .name = "T11", + .activationArcs = { { .placeName = "GoingDown_" }, + { .placeName = "Ready" }, + { .placeName = "Moving_" } }, + .destinationArcs = { { .placeName = "Moving_" }, + { .placeName = "GoingDown_" }, + { .placeName = "DecreaseFloor" } }, + .inhibitorArcs = { { .placeName = "ArrivedDestination" } } }); + + createTransition({ .name = "T12", + .activationArcs = { { .placeName = "IncreaseFloor" } }, + .destinationArcs = { { .placeName = "Ready" } }, + .additionalConditions={ bind_front(&ElevatorController::isFloorNotInList, &m_elevatorController) }, + .requireNoActionsInExecution=true }); + + createTransition({ .name = "T13", + .activationArcs = { { .placeName = "DecreaseFloor" } }, + .destinationArcs = { { .placeName = "Ready" } }, + .additionalConditions={ bind_front(&ElevatorController::isFloorNotInList, &m_elevatorController) }, + .requireNoActionsInExecution=true }); + + createTransition({ .name = "T14", + .activationArcs = { { .placeName = "IncreaseFloor" } }, + .destinationArcs = { { .placeName = "RemoveFromListGU" } }, + .additionalConditions={ bind_front(&ElevatorController::isFloorInList, &m_elevatorController) }, + .requireNoActionsInExecution=true }); + + createTransition({ .name = "T15", + .activationArcs = { { .placeName = "RemoveFromListGU" } }, + .destinationArcs = { { .placeName = "ProcessLists" }, + { .placeName = "ArrivedDestination" }, + { .placeName = "Ready" } } }); + + createTransition({ .name = "T16", + .activationArcs = { { .placeName = "DecreaseFloor" } }, + .destinationArcs = { { .placeName = "RemoveFromListGD" } }, + .additionalConditions={ bind_front(&ElevatorController::isFloorInList, &m_elevatorController) }, + .requireNoActionsInExecution=true }); + + createTransition({ .name = "T17", + .activationArcs = { { .placeName = "RemoveFromListGD" } }, + .destinationArcs = { { .placeName = "ProcessLists" }, + { .placeName = "ArrivedDestination" }, + { .placeName = "Ready" } } }); } void ElevatorPetriNet::createArrivingFloorTransitions() { // Arriving a floor going down. - createTransition({ "Ready", "ProcessLists", "GoingDown_", "DoorsClosed_" }, - { "Ready", "GoingDown_", "DoorsClosed_", "ProcessedLists" }, - { "OpenDoors", "ArrivedDestination" }, - { bind(&ElevatorController::isDestinationListNotEmpty, &m_elevatorController) }, true); - - createTransition({ "Ready", "ProcessLists", "GoingDown_", "DoorsClosed_" }, { "DoorsClosed_", "SwapGD" }, - { "OpenDoors", "ArrivedDestination" }, - { bind(&ElevatorController::isDestinationListEmpty, &m_elevatorController) }, true); - - createTransition({ "SwapGD" }, { "MergeGoingUpGTCurrent" }, - { bind(&ElevatorController::isDestinationListNotEmpty, &m_elevatorController) }, true); - - createTransition({ "SwapGD" }, { "MergeMinGoingUp1" }, - { bind(&ElevatorController::isDestinationListEmpty, &m_elevatorController) }, true); - - createTransition({ "MergeGoingUpGTCurrent" }, { "Ready", "ProcessedLists", "GoingUp" }); - - createTransition({ "MergeMinGoingUp1" }, { "MergeMaxGoingDown1" }, - { bind(&ElevatorController::isDestinationListEmpty, &m_elevatorController) }, true); - - createTransition({ "MergeMinGoingUp1" }, { "GoingDown", "Ready", "ProcessedLists" }, - { bind(&ElevatorController::isMinSmallerThanCurrent, &m_elevatorController) }, true); - - createTransition({ "MergeMinGoingUp1" }, { "MergePostponedToCurrent11" }, - { bind(&ElevatorController::isMinGreaterThanCurrent, &m_elevatorController) }, true); - - createTransition({ "MergeMaxGoingDown1" }, { "Ready", "ProcessedLists" }, - { bind(&ElevatorController::isDestinationListEmpty, &m_elevatorController) }, true); - - createTransition({ "MergeMaxGoingDown1" }, { "MergePostponedToCurrent12" }, - { bind(&ElevatorController::isDestinationListNotEmpty, &m_elevatorController), - bind(&ElevatorController::isMaxSmallerThanCurrent, &m_elevatorController) }, - true); - - createTransition({ "MergeMaxGoingDown1" }, { "Ready", "ProcessedLists", "GoingUp" }, - { bind(&ElevatorController::isDestinationListNotEmpty, &m_elevatorController), - bind(&ElevatorController::isMaxGreaterThanCurrent, &m_elevatorController) }, - true); - - createTransition({ "MergePostponedToCurrent11" }, { "Ready", "ProcessedLists", "GoingUp" }); - - createTransition({ "MergePostponedToCurrent12" }, { "Ready", "ProcessedLists", "GoingDown" }); + createTransition({ .name = "T18", + .activationArcs = { { .placeName = "Ready" }, + { .placeName = "ProcessLists" }, + { .placeName = "GoingDown_" }, + { .placeName = "DoorsClosed_" } }, + .destinationArcs = { { .placeName = "Ready" }, + { .placeName = "GoingDown_" }, + { .placeName = "DoorsClosed_" }, + { .placeName = "ProcessedLists" } }, + .inhibitorArcs = { { .placeName = "OpenDoors" }, + { .placeName = "ArrivedDestination" } }, + .additionalConditions={ bind_front(&ElevatorController::isDestinationListNotEmpty, &m_elevatorController) }, + .requireNoActionsInExecution=true }); + + createTransition({ .name = "T19", + .activationArcs = { { .placeName = "Ready" }, + { .placeName = "ProcessLists" }, + { .placeName = "GoingDown_" }, + { .placeName = "DoorsClosed_" } }, + .destinationArcs = { { .placeName = "DoorsClosed_" }, + { .placeName = "SwapGD" } }, + .inhibitorArcs = { { .placeName = "OpenDoors" }, + { .placeName = "ArrivedDestination" } }, + .additionalConditions={ bind_front(&ElevatorController::isDestinationListEmpty, &m_elevatorController) }, + .requireNoActionsInExecution=true }); + + createTransition({ .name = "T20", + .activationArcs = { { .placeName = "SwapGD" } }, + .destinationArcs = { { .placeName = "MergeGoingUpGTCurrent" } }, + .additionalConditions={ bind_front(&ElevatorController::isDestinationListNotEmpty, &m_elevatorController) }, + .requireNoActionsInExecution=true }); + + createTransition({ .name = "T21", + .activationArcs = { { .placeName = "SwapGD" } }, + .destinationArcs = { { .placeName = "MergeMinGoingUp1" } }, + .additionalConditions={ bind_front(&ElevatorController::isDestinationListEmpty, &m_elevatorController) }, + .requireNoActionsInExecution=true }); + + createTransition({ .name = "T22", + .activationArcs = { { .placeName = "MergeGoingUpGTCurrent" } }, + .destinationArcs = { { .placeName = "Ready" }, + { .placeName = "ProcessedLists" }, + { .placeName = "GoingUp" } } }); + + createTransition({ .name = "T23", + .activationArcs = { { .placeName = "MergeMinGoingUp1" } }, + .destinationArcs = { { .placeName = "MergeMaxGoingDown1" } }, + .additionalConditions={ bind_front(&ElevatorController::isDestinationListEmpty, &m_elevatorController) }, + .requireNoActionsInExecution=true }); + + createTransition({ .name = "T24", + .activationArcs = { { .placeName = "MergeMinGoingUp1" } }, + .destinationArcs = { { .placeName = "GoingDown" }, + { .placeName = "Ready" }, + { .placeName = "ProcessedLists" } }, + .additionalConditions={ bind_front(&ElevatorController::isMinSmallerThanCurrent, &m_elevatorController) }, + .requireNoActionsInExecution=true }); + + createTransition({ .name = "T25", + .activationArcs = { { .placeName = "MergeMinGoingUp1" } }, + .destinationArcs = { { .placeName = "MergePostponedToCurrent11" } }, + .additionalConditions={ bind_front(&ElevatorController::isMinGreaterThanCurrent, &m_elevatorController) }, + .requireNoActionsInExecution=true }); + + createTransition({ .name = "T26", + .activationArcs = { { .placeName = "MergeMaxGoingDown1" } }, + .destinationArcs = { { .placeName = "Ready" }, + { .placeName = "ProcessedLists" } }, + .additionalConditions={ bind_front(&ElevatorController::isDestinationListEmpty, &m_elevatorController) }, + .requireNoActionsInExecution=true }); + + createTransition({ .name = "T27", + .activationArcs = { { .placeName = "MergeMaxGoingDown1" } }, + .destinationArcs = { { .placeName = "MergePostponedToCurrent12" } }, + .additionalConditions={ bind_front(&ElevatorController::isDestinationListNotEmpty, &m_elevatorController), + bind_front(&ElevatorController::isMaxSmallerThanCurrent, &m_elevatorController) }, + .requireNoActionsInExecution=true }); + + createTransition({ .name = "T28", + .activationArcs = { { .placeName = "MergeMaxGoingDown1" } }, + .destinationArcs = { { .placeName = "Ready" }, + { .placeName = "ProcessedLists" }, + { .placeName = "GoingUp" } }, + .additionalConditions={ bind_front(&ElevatorController::isDestinationListNotEmpty, &m_elevatorController), + bind_front(&ElevatorController::isMaxGreaterThanCurrent, &m_elevatorController) }, + .requireNoActionsInExecution=true }); + + createTransition({ .name = "T29", + .activationArcs = { { .placeName = "MergePostponedToCurrent11" } }, + .destinationArcs = { { .placeName = "Ready" }, + { .placeName = "ProcessedLists" }, + { .placeName = "GoingUp" } } }); + + createTransition({ .name = "T30", + .activationArcs = { { .placeName = "MergePostponedToCurrent12" } }, + .destinationArcs = { { .placeName = "Ready" }, + { .placeName = "ProcessedLists" }, + { .placeName = "GoingDown" } } }); // Arriving a floor going up. - createTransition({ "Ready", "ProcessLists", "GoingUp_", "DoorsClosed_" }, - { "Ready", "GoingUp_", "DoorsClosed_", "ProcessedLists" }, - { "OpenDoors", "ArrivedDestination" }, - { bind(&ElevatorController::isDestinationListNotEmpty, &m_elevatorController) }, true); - - createTransition({ "Ready", "ProcessLists", "GoingUp_", "DoorsClosed_" }, { "DoorsClosed_", "SwapGU" }, - { "OpenDoors", "ArrivedDestination" }, - { bind(&ElevatorController::isDestinationListEmpty, &m_elevatorController) }, true); - - createTransition({ "SwapGU" }, { "MergeGoingDownSTCurrent" }, - { bind(&ElevatorController::isDestinationListNotEmpty, &m_elevatorController) }, true); - - createTransition({ "SwapGU" }, { "MergeMaxGoingDown2" }, - { bind(&ElevatorController::isDestinationListEmpty, &m_elevatorController) }, true); - - createTransition({ "MergeGoingDownSTCurrent" }, { "Ready", "ProcessedLists", "GoingDown" }); - - createTransition({ "MergeMaxGoingDown2" }, { "MergeMinGoingUp2" }, - { bind(&ElevatorController::isDestinationListEmpty, &m_elevatorController) }, true); - - createTransition({ "MergeMaxGoingDown2" }, { "GoingUp", "Ready", "ProcessedLists" }, - { bind(&ElevatorController::isMaxGreaterThanCurrent, &m_elevatorController) }, true); - - createTransition({ "MergeMaxGoingDown2" }, { "MergePostponedToCurrent21" }, - { bind(&ElevatorController::isMaxSmallerThanCurrent, &m_elevatorController) }, true); - - createTransition({ "MergeMinGoingUp2" }, { "Ready", "ProcessedLists" }, - { bind(&ElevatorController::isDestinationListEmpty, &m_elevatorController) }, true); - - createTransition({ "MergeMinGoingUp2" }, { "MergePostponedToCurrent22" }, - { bind(&ElevatorController::isDestinationListNotEmpty, &m_elevatorController), - bind(&ElevatorController::isMinGreaterThanCurrent, &m_elevatorController) }, - true); - - createTransition({ "MergeMinGoingUp2" }, { "Ready", "ProcessedLists", "GoingDown" }, - { bind(&ElevatorController::isDestinationListNotEmpty, &m_elevatorController), - bind(&ElevatorController::isMinSmallerThanCurrent, &m_elevatorController) }, - true); - - createTransition({ "MergePostponedToCurrent21" }, { "Ready", "ProcessedLists", "GoingDown" }); - - createTransition({ "MergePostponedToCurrent22" }, { "Ready", "ProcessedLists", "GoingUp" }); + createTransition({ .name = "T31", + .activationArcs = { { .placeName = "Ready" }, + { .placeName = "ProcessLists" }, + { .placeName = "GoingUp_" }, + { .placeName = "DoorsClosed_" } }, + .destinationArcs = { { .placeName = "Ready" }, + { .placeName = "GoingUp_" }, + { .placeName = "DoorsClosed_" }, + { .placeName = "ProcessedLists" } }, + .inhibitorArcs = { { .placeName = "OpenDoors" }, + { .placeName = "ArrivedDestination" } }, + .additionalConditions={ bind_front(&ElevatorController::isDestinationListNotEmpty, &m_elevatorController) }, + .requireNoActionsInExecution=true }); + + createTransition({ .name = "T32", + .activationArcs = { { .placeName = "Ready" }, + { .placeName = "ProcessLists" }, + { .placeName = "GoingUp_" }, + { .placeName = "DoorsClosed_" } }, + .destinationArcs = { { .placeName = "DoorsClosed_" }, + { .placeName = "SwapGU" } }, + .inhibitorArcs = { { .placeName = "OpenDoors" }, + { .placeName = "ArrivedDestination" } }, + .additionalConditions={ bind_front(&ElevatorController::isDestinationListEmpty, &m_elevatorController) }, + .requireNoActionsInExecution=true }); + + createTransition({ .name = "T33", + .activationArcs = { { .placeName = "SwapGU" } }, + .destinationArcs = { { .placeName = "MergeGoingDownSTCurrent" } }, + .additionalConditions={ bind_front(&ElevatorController::isDestinationListNotEmpty, &m_elevatorController) }, + .requireNoActionsInExecution=true }); + + createTransition({ .name = "T34", + .activationArcs = { { .placeName = "SwapGU" } }, + .destinationArcs = { { .placeName = "MergeMaxGoingDown2" } }, + .additionalConditions={ bind_front(&ElevatorController::isDestinationListEmpty, &m_elevatorController) }, + .requireNoActionsInExecution=true }); + + createTransition({ .name = "T35", + .activationArcs = { { .placeName = "MergeGoingDownSTCurrent" } }, + .destinationArcs = { { .placeName = "Ready" }, + { .placeName = "ProcessedLists" }, + { .placeName = "GoingDown" } } }); + + createTransition({ .name = "T36", + .activationArcs = { { .placeName = "MergeMaxGoingDown2" } }, + .destinationArcs = { { .placeName = "MergeMinGoingUp2" } }, + .additionalConditions={ bind_front(&ElevatorController::isDestinationListEmpty, &m_elevatorController) }, + .requireNoActionsInExecution=true }); + + createTransition({ .name = "T37", + .activationArcs = { { .placeName = "MergeMaxGoingDown2" } }, + .destinationArcs = { { .placeName = "GoingUp" }, + { .placeName = "Ready" }, + { .placeName = "ProcessedLists" } }, + .additionalConditions={ bind_front(&ElevatorController::isMaxGreaterThanCurrent, &m_elevatorController) }, + .requireNoActionsInExecution=true }); + + createTransition({ .name = "T38", + .activationArcs = { { .placeName = "MergeMaxGoingDown2" } }, + .destinationArcs = { { .placeName = "MergePostponedToCurrent21" } }, + .additionalConditions={ bind_front(&ElevatorController::isMaxSmallerThanCurrent, &m_elevatorController) }, + .requireNoActionsInExecution=true }); + + createTransition({ .name = "T39", + .activationArcs = { { .placeName = "MergeMinGoingUp2" } }, + .destinationArcs = { { .placeName = "Ready" }, + { .placeName = "ProcessedLists" } }, + .additionalConditions={ bind_front(&ElevatorController::isDestinationListEmpty, &m_elevatorController) }, + .requireNoActionsInExecution=true }); + + createTransition({ .name = "T40", + .activationArcs = { { .placeName = "MergeMinGoingUp2" } }, + .destinationArcs = { { .placeName = "MergePostponedToCurrent22" } }, + .additionalConditions={ bind_front(&ElevatorController::isDestinationListNotEmpty, &m_elevatorController), + bind_front(&ElevatorController::isMinGreaterThanCurrent, &m_elevatorController) }, + .requireNoActionsInExecution=true }); + + createTransition({ .name = "T41", + .activationArcs = { { .placeName = "MergeMinGoingUp2" } }, + .destinationArcs = { { .placeName = "Ready" }, + { .placeName = "ProcessedLists" }, + { .placeName = "GoingDown" } }, + .additionalConditions={ bind_front(&ElevatorController::isDestinationListNotEmpty, &m_elevatorController), + bind_front(&ElevatorController::isMinSmallerThanCurrent, &m_elevatorController) }, + .requireNoActionsInExecution=true }); + + createTransition({ .name = "T42", + .activationArcs = { { .placeName = "MergePostponedToCurrent21" } }, + .destinationArcs = { { .placeName = "Ready" }, + { .placeName = "ProcessedLists" }, + { .placeName = "GoingDown" } } }); + + createTransition({ .name = "T43", + .activationArcs = { { .placeName = "MergePostponedToCurrent22" } }, + .destinationArcs = { { .placeName = "Ready" }, + { .placeName = "ProcessedLists" }, + { .placeName = "GoingUp" } } }); } void ElevatorPetriNet::createButtonPressingTransitions() { - createTransition({ "DestinationButton", "Ready" }, { "D3" }, vector{ "GoingUp_", "GoingDown_" }, - { bind(&ElevatorController::isMarkedFloorNotCurrentFloor, &m_elevatorController) }, true); - - createTransition({ "DestinationButton", "GoingUp_", "Ready" }, { "D1", "GoingUp_" }, - { bind(&ElevatorController::isMarkedFloorNotCurrentFloor, &m_elevatorController) }, true); - - createTransition({ "DestinationButton", "GoingDown_", "Ready" }, { "D2", "GoingDown_" }, - { bind(&ElevatorController::isMarkedFloorNotCurrentFloor, &m_elevatorController) }, true); - - createTransition({ "D1" }, { "AddToTravel" }, - { bind(&ElevatorController::isMarkedFloorGreaterThanCurrentFloor, &m_elevatorController) }, - true); - - createTransition({ "D1" }, { "AddToNextTravel" }, - { bind(&ElevatorController::isMarkedFloorSmallerThanCurrentFloor, &m_elevatorController) }, - true); - - createTransition({ "D2" }, { "AddToNextTravel" }, - { bind(&ElevatorController::isMarkedFloorGreaterThanCurrentFloor, &m_elevatorController) }, - true); - - createTransition({ "D2" }, { "AddToTravel" }, - { bind(&ElevatorController::isMarkedFloorSmallerThanCurrentFloor, &m_elevatorController) }, - true); - - createTransition({ "D3" }, { "GoingUp", "AddToTravel" }, - { bind(&ElevatorController::isMarkedFloorGreaterThanCurrentFloor, &m_elevatorController) }, - true); - - createTransition({ "D3" }, { "GoingDown", "AddToTravel" }, - { bind(&ElevatorController::isMarkedFloorSmallerThanCurrentFloor, &m_elevatorController) }, - true); - - createTransition({ "AddToNextTravel" }, { "Ready" }); - - createTransition({ "AddToTravel" }, { "Ready" }); + createTransition({ .name = "T44", + .activationArcs = { { .placeName = "DestinationButton" }, + { .placeName = "Ready" } }, + .destinationArcs = { { .placeName = "D3" } }, + .inhibitorArcs = { { .placeName = "GoingUp_" }, + { .placeName = "GoingDown_" } }, + .additionalConditions={ bind_front(&ElevatorController::isMarkedFloorNotCurrentFloor, &m_elevatorController) }, + .requireNoActionsInExecution=true }); + + createTransition({ .name = "T45", + .activationArcs = { { .placeName = "DestinationButton" }, + { .placeName = "GoingUp_" }, + { .placeName = "Ready" } }, + .destinationArcs = { { .placeName = "D1" }, + { .placeName = "GoingUp_" } }, + .additionalConditions={ bind_front(&ElevatorController::isMarkedFloorNotCurrentFloor, &m_elevatorController) }, + .requireNoActionsInExecution=true }); + + createTransition({ .name = "T46", + .activationArcs = { { .placeName = "DestinationButton" }, + { .placeName = "GoingDown_" }, + { .placeName = "Ready" } }, + .destinationArcs = { { .placeName = "D2" }, + { .placeName = "GoingDown_" } }, + .additionalConditions={ bind_front(&ElevatorController::isMarkedFloorNotCurrentFloor, &m_elevatorController) }, + .requireNoActionsInExecution=true }); + + createTransition({ .name = "T47", + .activationArcs = { { .placeName = "D1" } }, + .destinationArcs = { { .placeName = "AddToTravel" } }, + .additionalConditions={ bind_front(&ElevatorController::isMarkedFloorGreaterThanCurrentFloor, &m_elevatorController) }, + .requireNoActionsInExecution=true }); + + createTransition({ .name = "T48", + .activationArcs = { { .placeName = "D1" } }, + .destinationArcs = { { .placeName = "AddToNextTravel" } }, + .additionalConditions={ bind_front(&ElevatorController::isMarkedFloorSmallerThanCurrentFloor, &m_elevatorController) }, + .requireNoActionsInExecution=true }); + + createTransition({ .name = "T49", + .activationArcs = { { .placeName = "D2" } }, + .destinationArcs = { { .placeName = "AddToNextTravel" } }, + .additionalConditions={ bind_front(&ElevatorController::isMarkedFloorGreaterThanCurrentFloor, &m_elevatorController) }, + .requireNoActionsInExecution=true }); + + createTransition({ .name = "T50", + .activationArcs = { { .placeName = "D2" } }, + .destinationArcs = { { .placeName = "AddToTravel" } }, + .additionalConditions={ bind_front(&ElevatorController::isMarkedFloorSmallerThanCurrentFloor, &m_elevatorController) }, + .requireNoActionsInExecution=true }); + + createTransition({ .name = "T51", + .activationArcs = { { .placeName = "D3" } }, + .destinationArcs = { { .placeName = "GoingUp" }, + { .placeName = "AddToTravel" } }, + .additionalConditions={ bind_front(&ElevatorController::isMarkedFloorGreaterThanCurrentFloor, &m_elevatorController) }, + .requireNoActionsInExecution=true }); + + createTransition({ .name = "T52", + .activationArcs = { { .placeName = "D3" } }, + .destinationArcs = { { .placeName = "GoingDown" }, + { .placeName = "AddToTravel" } }, + .additionalConditions={ bind_front(&ElevatorController::isMarkedFloorSmallerThanCurrentFloor, &m_elevatorController) }, + .requireNoActionsInExecution=true }); + + createTransition({ .name = "T53", + .activationArcs = { { .placeName = "AddToNextTravel" } }, + .destinationArcs = { { .placeName = "Ready" } } }); + + createTransition({ .name = "T54", + .activationArcs = { { .placeName = "AddToTravel" } }, + .destinationArcs = { { .placeName = "Ready" } } }); } void ElevatorPetriNet::createCallingButtonTransitions() { // Calling the elevator to go up. - createTransition({ "CallButtonUp", "Ready" }, { "D3" }, vector{ "GoingUp_", "GoingDown_" }, - { bind(&ElevatorController::isMarkedFloorNotCurrentFloor, &m_elevatorController) }, true); - - createTransition({ "CallButtonUp", "GoingUp_", "Ready" }, { "D4", "GoingUp_" }, - { bind(&ElevatorController::isMarkedFloorNotCurrentFloor, &m_elevatorController) }, true); - - createTransition({ "CallButtonUp", "GoingDown_", "Ready" }, { "WaitToGoUp", "GoingDown_" }); - - createTransition({ "D4" }, { "WaitToGoUp" }, - { bind(&ElevatorController::isMarkedFloorSmallerThanCurrentFloor, &m_elevatorController) }, - true); - - createTransition({ "D4" }, { "AddToTravel" }, - { bind(&ElevatorController::isMarkedFloorGreaterThanCurrentFloor, &m_elevatorController) }, - true); - - createTransition({ "WaitToGoUp" }, { "Ready" }); + createTransition({ .name = "T55", + .activationArcs = { { .placeName = "CallButtonUp" }, + { .placeName = "Ready" } }, + .destinationArcs = { { .placeName = "D3" } }, + .inhibitorArcs = { { .placeName = "GoingUp_" }, + { .placeName = "GoingDown_" } }, + .additionalConditions={ bind_front(&ElevatorController::isMarkedFloorNotCurrentFloor, &m_elevatorController) }, + .requireNoActionsInExecution=true }); + + createTransition({ .name = "T56", + .activationArcs = { { .placeName = "CallButtonUp" }, + { .placeName = "GoingUp_" }, + { .placeName = "Ready" } }, + .destinationArcs = { { .placeName = "D4" }, + { .placeName = "GoingUp_" } }, + .additionalConditions={ bind_front(&ElevatorController::isMarkedFloorNotCurrentFloor, &m_elevatorController) }, + .requireNoActionsInExecution=true }); + + createTransition({ .name = "T57", + .activationArcs = { { .placeName = "CallButtonUp" }, + { .placeName = "GoingDown_" }, + { .placeName = "Ready" } }, + .destinationArcs = { { .placeName = "WaitToGoUp" }, + { .placeName = "GoingDown_" } } }); + + createTransition({ .name = "T58", + .activationArcs = { { .placeName = "D4" } }, + .destinationArcs = { { .placeName = "WaitToGoUp" } }, + .additionalConditions={ bind_front(&ElevatorController::isMarkedFloorSmallerThanCurrentFloor, &m_elevatorController) }, + .requireNoActionsInExecution=true }); + + createTransition({ .name = "T59", + .activationArcs = { { .placeName = "D4" } }, + .destinationArcs = { { .placeName = "AddToTravel" } }, + .additionalConditions={ bind_front(&ElevatorController::isMarkedFloorGreaterThanCurrentFloor, &m_elevatorController) }, + .requireNoActionsInExecution=true }); + + createTransition({ .name = "T60", + .activationArcs = { { .placeName = "WaitToGoUp" } }, + .destinationArcs = { { .placeName = "Ready" } } }); // Calling the elevator to go down. - createTransition({ "CallButtonDown", "Ready" }, { "D3" }, vector{ "GoingUp_", "GoingDown_" }, - { bind(&ElevatorController::isMarkedFloorNotCurrentFloor, &m_elevatorController) }, true); - - createTransition({ "CallButtonDown", "GoingDown_", "Ready" }, { "D5", "GoingDown_" }, - { bind(&ElevatorController::isMarkedFloorNotCurrentFloor, &m_elevatorController) }, true); - - createTransition({ "CallButtonDown", "GoingUp_", "Ready" }, { "WaitToGoDown", "GoingUp_" }); - - createTransition({ "D5" }, { "AddToTravel" }, - { bind(&ElevatorController::isMarkedFloorSmallerThanCurrentFloor, &m_elevatorController) }, - true); - - createTransition({ "D5" }, { "WaitToGoDown" }, - { bind(&ElevatorController::isMarkedFloorGreaterThanCurrentFloor, &m_elevatorController) }, - true); - - createTransition({ "WaitToGoDown" }, { "Ready" }); + createTransition({ .name = "T61", + .activationArcs = { { .placeName = "CallButtonDown" }, + { .placeName = "Ready" } }, + .destinationArcs = { { .placeName = "D3" } }, + .inhibitorArcs = { { .placeName = "GoingUp_" }, + { .placeName = "GoingDown_" } }, + .additionalConditions={ bind_front(&ElevatorController::isMarkedFloorNotCurrentFloor, &m_elevatorController) }, + .requireNoActionsInExecution=true }); + + createTransition({ .name = "T62", + .activationArcs = { { .placeName = "CallButtonDown" }, + { .placeName = "GoingDown_" }, + { .placeName = "Ready" } }, + .destinationArcs = { { .placeName = "D5" }, + { .placeName = "GoingDown_" } }, + .additionalConditions={ bind_front(&ElevatorController::isMarkedFloorNotCurrentFloor, &m_elevatorController) }, + .requireNoActionsInExecution=true }); + + createTransition({ .name = "T63", + .activationArcs = { { .placeName = "CallButtonDown" }, + { .placeName = "GoingUp_" }, + { .placeName = "Ready" } }, + .destinationArcs = { { .placeName = "WaitToGoDown" }, + { .placeName = "GoingUp_" } } }); + + createTransition({ .name = "T64", + .activationArcs = { { .placeName = "D5" } }, + .destinationArcs = { { .placeName = "AddToTravel" } }, + .additionalConditions={ bind_front(&ElevatorController::isMarkedFloorSmallerThanCurrentFloor, &m_elevatorController) }, + .requireNoActionsInExecution=true }); + + createTransition({ .name = "T65", + .activationArcs = { { .placeName = "D5" } }, + .destinationArcs = { { .placeName = "WaitToGoDown" } }, + .additionalConditions={ bind_front(&ElevatorController::isMarkedFloorGreaterThanCurrentFloor, &m_elevatorController) }, + .requireNoActionsInExecution=true }); + + createTransition({ .name = "T66", + .activationArcs = { { .placeName = "WaitToGoDown" } }, + .destinationArcs = { { .placeName = "Ready" } } }); } diff --git a/Examples/Elevator/Controller/ElevatorPetriNet.h b/Examples/Elevator/Controller/ElevatorPetriNet.h old mode 100644 new mode 100755 index b650a96..4b7e84b --- a/Examples/Elevator/Controller/ElevatorPetriNet.h +++ b/Examples/Elevator/Controller/ElevatorPetriNet.h @@ -1,7 +1,7 @@ /* * This file is part of PTN Engine * - * Copyright (c) 2017-2023 Eduardo Valgôde + * Copyright (c) 2017-2024 Eduardo Valgôde * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -25,18 +25,17 @@ class ElevatorController; //! Implements PTN Engine net defining the phone menu behaviour. -/*! - * The behaviour is defined in the constructor. - */ class ElevatorPetriNet : public IElevatorPetriNet, private ptne::PTN_Engine { public: - /*! - * Constructor. - * \param ptrDispatcher Shared pointer to the controller. - */ + //! + //! Constructor. + //! \param ptrDispatcher Shared pointer to the controller. + //! explicit ElevatorPetriNet(ElevatorController &elevatorController); + ~ElevatorPetriNet() override; + // Events void closeDoors() override; diff --git a/Examples/Elevator/Controller/IElevatorPetriNet.h b/Examples/Elevator/Controller/IElevatorPetriNet.h old mode 100644 new mode 100755 index 2f4624c..11b56be --- a/Examples/Elevator/Controller/IElevatorPetriNet.h +++ b/Examples/Elevator/Controller/IElevatorPetriNet.h @@ -1,7 +1,7 @@ /* * This file is part of PTN Engine * - * Copyright (c) 2017-2023 Eduardo Valgôde + * Copyright (c) 2017-2024 Eduardo Valgôde * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -18,14 +18,11 @@ #pragma once - //! Base class for a PTN Engine net that controls the ElevatorController. class IElevatorPetriNet { public: - virtual ~IElevatorPetriNet() - { - } + virtual ~IElevatorPetriNet() = default; virtual void closeDoors() = 0; diff --git a/Examples/Elevator/main.cpp b/Examples/Elevator/main.cpp old mode 100644 new mode 100755 diff --git a/Examples/Factorial/main.cpp b/Examples/Factorial/main.cpp old mode 100644 new mode 100755 index 7813719..38beab1 --- a/Examples/Factorial/main.cpp +++ b/Examples/Factorial/main.cpp @@ -1,7 +1,7 @@ /* * This file is part of PTN Engine * - * Copyright (c) 2023 Eduardo Valgôde + * Copyright (c) 2023-2024 Eduardo Valgôde * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -17,7 +17,6 @@ */ #include - #include "PTN_Engine/PTN_Engine.h" using namespace std; @@ -42,10 +41,19 @@ int main(int, char **) ConditionFunction finished = [&x]() { return x <= 1; }; ConditionFunction notFinished = [&finished]() { return !finished(); }; - pn.createPlace("Compute", 0, compute, true); - pn.createPlace("Finished", 0); - pn.createTransition({ "Compute" }, { "Compute" }, { notFinished }); - pn.createTransition({ "Compute" }, { "Finished" }, { finished }); + pn.createPlace({ .name="Compute", + .onEnterAction=compute, + .input=true}); + pn.createPlace({.name="Finished"}); + + pn.createTransition({ .name = "T1", + .activationArcs = { { .placeName = "Compute" } }, + .destinationArcs = { { .placeName = "Compute" } }, + .additionalConditions={ notFinished } }); + pn.createTransition({ .name = "T2", + .activationArcs= { { .placeName = "Compute" } }, + .destinationArcs = { { .placeName = "Finished" } }, + .additionalConditions={ finished } }); for (size_t i : { 0, 1, 2, 3, 6, 10 }) { diff --git a/Examples/PhoneMenu/CMakeLists.txt b/Examples/PhoneMenu/CMakeLists.txt index f6c1a6e..b26d550 100644 --- a/Examples/PhoneMenu/CMakeLists.txt +++ b/Examples/PhoneMenu/CMakeLists.txt @@ -1,13 +1,13 @@ # This file is part of PTN Engine -# +# # Copyright (c) 2017 Eduardo Valgôde -# +# # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at -# +# # http://www.apache.org/licenses/LICENSE-2.0 -# +# # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -20,8 +20,9 @@ set(PROJECT_TEST_NAME PhoneMenu) include_directories( ${INCLUDE_DIR} - ${PROJECT_SOURCE_DIR}/Examples/PhoneMenu - ) + ${PROJECT_SOURCE_DIR}/PTN_Engine/ImportExport/include + ${PROJECT_SOURCE_DIR}/Examples/PhoneMenu + ) file( GLOB_RECURSE PhoneMenu_SRC "*.h" @@ -29,18 +30,21 @@ file( GLOB_RECURSE PhoneMenu_SRC ) add_executable (PhoneMenu ${PhoneMenu_SRC}) -target_link_libraries(PhoneMenu PUBLIC PTN_Engine) +target_link_libraries(PhoneMenu PUBLIC + PTN_Engine + ImportExport) if(NOT BUILD_SHARED_LIBS) set_target_properties(PhoneMenu PROPERTIES SUFFIX ${EXECUTABLE_STATIC_POSTFIX}${CMAKE_EXECUTABLE_SUFFIX}) endif() set_target_properties(PhoneMenu PROPERTIES DEBUG_POSTFIX ${CMAKE_DEBUG_POSTFIX}) +file(COPY ${CMAKE_CURRENT_SOURCE_DIR}/assets/PhoneMenu.xml DESTINATION ${CMAKE_BINARY_DIR}/bin) # Install rules if(INSTALL_EXAMPLES) install(TARGETS PhoneMenu - RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}) + RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}) endif() diff --git a/Examples/PhoneMenu/Controller/Controller.cpp b/Examples/PhoneMenu/Controller/Controller.cpp old mode 100644 new mode 100755 index af2a135..4350840 --- a/Examples/PhoneMenu/Controller/Controller.cpp +++ b/Examples/PhoneMenu/Controller/Controller.cpp @@ -1,7 +1,7 @@ /* * This file is part of PTN Engine * - * Copyright (c) 2017-2023 Eduardo Valgôde + * Copyright (c) 2017-2024 Eduardo Valgôde * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -17,68 +17,62 @@ */ #include "Controller/Controller.h" -#include using namespace std; -Controller::Controller() -: m_petriNet(*this) -, m_messageSelected(0) +Controller::Controller(MainMenuView &mainMenuView, + MessagesMenuView &messagesMenuView, + CallLogView &callLogView, + MessageList &messageList, + CallList &callLog) +: m_mainMenuView(mainMenuView) +, m_messagesMenuView(messagesMenuView) +, m_callLogView(callLogView) +, m_messageList(messageList) +, m_callLog(callLog) { } -Controller::~Controller() -{ -} +Controller::~Controller() = default; void Controller::pressA() { - m_petriNet.pressA(); + m_menuStateMachine->pressA(); } void Controller::pressB() { - m_petriNet.pressB(); + m_menuStateMachine->pressB(); } void Controller::pressC() { - m_petriNet.pressC(); -} - -Controller::MessageList &Controller::messageList() -{ - return m_messageList; -} - -Controller::CallList &Controller::callLog() -{ - return m_callLog; + m_menuStateMachine->pressC(); } void Controller::showMainMenu() const { - m_mainMenu.showMenu(); + m_mainMenuView.showMenu(); } void Controller::selectCallsOption() { - m_mainMenu.select(0); + m_mainMenuView.select(0); } void Controller::selectMessagesOption() { - m_mainMenu.select(1); + m_mainMenuView.select(1); } -void Controller::showCallsMenu() +void Controller::showCallsMenu() const { - m_callLogView.viewCallLog(m_callLog); + m_callLogView.viewCallLog(); } -void Controller::showMessageMenu() +void Controller::showMessageMenu() const { - m_messagesMenu.showMessagesList(m_messageList, m_messageSelected); + m_messagesMenuView.showMessagesList(m_messageSelected); } void Controller::selectNextMessage() @@ -90,17 +84,37 @@ void Controller::selectNextMessage() } } -void Controller::showMessage() +void Controller::showMessage() const { - m_messagesMenu.displayMessage(m_messageList.getItem(m_messageSelected)); + m_messagesMenuView.displayMessage(m_messageList.getItem(m_messageSelected)); } void Controller::execute() { - m_petriNet.execute(); + if (m_menuStateMachine == nullptr) + { + return; + } + m_menuStateMachine->execute(); } void Controller::stop() { - m_petriNet.stop(); + m_menuStateMachine->stop(); +} + +void Controller::setStateMachine(shared_ptr stateMachine) +{ + if (m_menuStateMachine != nullptr) + { + m_menuStateMachine->stop(); + } + stateMachine->setControllerFunctions(*this); + m_menuStateMachine = stateMachine; +} + + +bool Controller::justReturnTrue() const +{ + return true; } diff --git a/Examples/PhoneMenu/Controller/Controller.h b/Examples/PhoneMenu/Controller/Controller.h old mode 100644 new mode 100755 index 52a4e81..de2d15c --- a/Examples/PhoneMenu/Controller/Controller.h +++ b/Examples/PhoneMenu/Controller/Controller.h @@ -1,7 +1,7 @@ /* * This file is part of PTN Engine * - * Copyright (c) 2017-2023 Eduardo Valgôde + * Copyright (c) 2017-2024 Eduardo Valgôde * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -18,28 +18,31 @@ #pragma once -#include "Controller/MenuStateMachine.h" +#include "Controller/IMenuStateMachine.h" #include "Model/Call.h" #include "Model/List.h" #include "Model/Message.h" #include "View/CallLogView.h" #include "View/MainMenuView.h" #include "View/MessagesMenuView.h" +#include -//! Example of a controller class -/*! - * Controls the display of a simplified hypothetical phone's menus, - * using only three keys. - */ +//! +//! \brief Example of a controller class +//! +//! \details Controls the display of a simplified hypothetical phone's menus, using only three keys. +//! class Controller { public: using MessageList = List; - using CallList = List; - //! Constructor. - Controller(); + Controller(MainMenuView &mainMenuView, + MessagesMenuView &messagesMenu, + CallLogView &callLogView, + MessageList &m_messageList, + CallList &m_callLog); ~Controller(); @@ -47,6 +50,8 @@ class Controller void stop(); + void setStateMachine(std::shared_ptr stateMachine); + // Actions //! Triggers an event indicating key "A" was pressed. @@ -58,10 +63,6 @@ class Controller //! Triggers an event indicating key "C" was pressed. void pressC(); - MessageList &messageList(); - - CallList &callLog(); - //! Show the main menu on screen. void showMainMenu() const; @@ -72,44 +73,45 @@ class Controller void selectMessagesOption(); //! Show the calls menu or log. - void showCallsMenu(); + void showCallsMenu() const; //! Show the messages menu. - void showMessageMenu(); + void showMessageMenu() const; //! Select the next message. void selectNextMessage(); //! Show the selected message. - void showMessage(); + void showMessage() const; + + //! Dummy function for showing in import export from files + bool justReturnTrue() const; private: //! The state machine of the controller. - MenuStateMachine m_petriNet; + std::shared_ptr m_menuStateMachine = nullptr; // Views //! A view of the main menu. - MainMenuView m_mainMenu; + MainMenuView &m_mainMenuView; //! A view of the messages. - MessagesMenuView m_messagesMenu; + MessagesMenuView &m_messagesMenuView; //! A view of the call logs. - CallLogView m_callLogView; - + CallLogView &m_callLogView; // Data sources //! The message data. - MessageList m_messageList; + MessageList &m_messageList; //! The call log data. - CallList m_callLog; - + CallList &m_callLog; // Internals //! Index of the selected message. - size_t m_messageSelected; + size_t m_messageSelected = 0; }; diff --git a/Examples/PhoneMenuXML/View/MainMenuView.h b/Examples/PhoneMenu/Controller/IMenuStateMachine.h old mode 100644 new mode 100755 similarity index 63% rename from Examples/PhoneMenuXML/View/MainMenuView.h rename to Examples/PhoneMenu/Controller/IMenuStateMachine.h index 79e85a8..5a4a571 --- a/Examples/PhoneMenuXML/View/MainMenuView.h +++ b/Examples/PhoneMenu/Controller/IMenuStateMachine.h @@ -1,7 +1,7 @@ /* * This file is part of PTN Engine * - * Copyright (c) 2017-2019 Eduardo Valgôde + * Copyright (c) 2024 Eduardo Valgôde * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -18,25 +18,21 @@ #pragma once -//! View the main menu on screen. -class MainMenuView +#include "PTN_Engine/PTN_Engine.h" + +class Controller; + +class IMenuStateMachine : public ptne::PTN_Engine { public: - //! - MainMenuView(); - - ~MainMenuView(); + virtual void setControllerFunctions(Controller &menuController) = 0; - //! Print the menu on screen. - void showMenu() const; + //! Press A key event. + virtual void pressA() = 0; - /*! - * Select an option. - * \param option Number of the option. - */ - void select(const int option); + //! Press B key event. + virtual void pressB() = 0; -private: - //! Selected option. - int m_selection; + //! Press C key event. + virtual void pressC() = 0; }; diff --git a/Examples/PhoneMenu/Controller/MenuStateMachine.cpp b/Examples/PhoneMenu/Controller/MenuStateMachine.cpp old mode 100644 new mode 100755 index e1070fa..61ee32a --- a/Examples/PhoneMenu/Controller/MenuStateMachine.cpp +++ b/Examples/PhoneMenu/Controller/MenuStateMachine.cpp @@ -1,7 +1,7 @@ /* * This file is part of PTN Engine * - * Copyright (c) 2017-2023 Eduardo Valgôde + * Copyright (c) 2017-2024 Eduardo Valgôde * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -21,58 +21,102 @@ using namespace ptne; -MenuStateMachine::MenuStateMachine(Controller &menuController) -: PTN_Engine() +void MenuStateMachine::setControllerFunctions(Controller &menuController) { using namespace std; // Places - createPlace("InputA", 0, true); - createPlace("InputB", 0, true); - createPlace("InputC", 0, true); - createPlace("CallsMenuSelected", 1, bind(&Controller::showMainMenu, &menuController)); - createPlace("MessagesMenuSelected", 0, bind(&Controller::showMainMenu, &menuController)); - createPlace("SelectMessagesOption", 0, bind(&Controller::selectMessagesOption, &menuController)); - createPlace("SelectCallsOption", 0, bind(&Controller::selectCallsOption, &menuController)); - createPlace("CallsLog", 0, bind(&Controller::showCallsMenu, &menuController)); - createPlace("MessagesMenu", 0, bind(&Controller::showMessageMenu, &menuController)); - createPlace("NextMessage", 0, bind(&Controller::selectNextMessage, &menuController)); - createPlace("ShowMessage", 0, bind(&Controller::showMessage, &menuController)); + createPlace({ .name="InputA", + .input=true }); + createPlace({ .name="InputB", + .input=true }); + createPlace({ .name="InputC", + .input=true }); + createPlace({ .name="CallsMenuSelected", + .initialNumberOfTokens=1, + .onEnterAction=bind_front(&Controller::showMainMenu, &menuController) }); + createPlace({ .name="MessagesMenuSelected", + .onEnterAction=bind_front(&Controller::showMainMenu, &menuController) }); + createPlace({ .name="SelectMessagesOption", + .onEnterAction=bind_front(&Controller::selectMessagesOption, &menuController) }); + createPlace({ .name="SelectCallsOption", + .onEnterAction=bind_front(&Controller::selectCallsOption, &menuController) }); + createPlace({ .name="CallsLog", + .onEnterAction=bind_front(&Controller::showCallsMenu, &menuController) }); + createPlace({ .name="MessagesMenu", + .onEnterAction=bind_front(&Controller::showMessageMenu, &menuController) }); + createPlace({ .name="NextMessage", + .onEnterAction=bind_front(&Controller::selectNextMessage, &menuController) }); + createPlace({ .name="ShowMessage", + .onEnterAction=bind_front(&Controller::showMessage, &menuController) }); // Transitions // Switch menu - createTransition({ "InputA", "CallsMenuSelected" }, { "SelectMessagesOption" }); + createTransition({ .name = "T1", + .activationArcs = { {.placeName = "InputA" }, + {.placeName = "CallsMenuSelected" } }, + .destinationArcs = { {.placeName = "SelectMessagesOption" } } }); - createTransition({ "SelectMessagesOption" }, { "MessagesMenuSelected" }); + createTransition({ .name = "T2", + .activationArcs = { { .placeName = "SelectMessagesOption" } }, + .destinationArcs = { { .placeName = "MessagesMenuSelected" } } }); // Switch menu - createTransition({ "InputA", "MessagesMenuSelected" }, { "SelectCallsOption" }); + createTransition({ .name = "T3", + .activationArcs = { { .placeName = "InputA" }, + { .placeName = "MessagesMenuSelected" } }, + .destinationArcs = { { .placeName = "SelectCallsOption" } } }); - createTransition({ "SelectCallsOption" }, { "CallsMenuSelected" }); + createTransition({ .name = "T4", + .activationArcs = { { .placeName = "SelectCallsOption" } }, + .destinationArcs = { { .placeName = "CallsMenuSelected" } } }); // Select calls log - createTransition({ "InputB", "CallsMenuSelected" }, { "CallsLog" }); + createTransition({ .name = "T5", + .activationArcs = { { .placeName = "InputB" }, + { .placeName = "CallsMenuSelected" } }, + .destinationArcs = { { .placeName = "CallsLog" } } }); // Leave calls log - createTransition({ "InputC", "CallsLog" }, { "CallsMenuSelected" }); + createTransition({ .name = "T6", + .activationArcs = { { .placeName = "InputC" }, + { .placeName = "CallsLog" } }, + .destinationArcs = { { .placeName = "CallsMenuSelected" } } }); // Select messages menu - createTransition({ "InputB", "MessagesMenuSelected" }, { "MessagesMenu" }); + createTransition({ .name = "T7", + .activationArcs = { { .placeName = "InputB" }, + { .placeName = "MessagesMenuSelected" } }, + .destinationArcs = { { .placeName = "MessagesMenu" } } }); // Leave messages menu - createTransition({ "InputC", "MessagesMenu" }, { "MessagesMenuSelected" }); + createTransition({ .name = "T8", + .activationArcs = { { .placeName = "InputC" }, + { .placeName = "MessagesMenu" } }, + .destinationArcs = { { .placeName = "MessagesMenuSelected" } } }); // Select next message - createTransition({ "InputA", "MessagesMenu" }, { "NextMessage" }); + createTransition({ .name = "T9", + .activationArcs = { { .placeName = "InputA" }, + { .placeName = "MessagesMenu" } }, + .destinationArcs = { { .placeName = "NextMessage" } } }); - createTransition({ "NextMessage" }, { "MessagesMenu" }); + createTransition({ .name = "T10", + .activationArcs = { { .placeName = "NextMessage" } }, + .destinationArcs = { { .placeName = "MessagesMenu" } } }); // Show message - createTransition({ "InputB", "MessagesMenu" }, { "ShowMessage" }); + createTransition({ .name = "T11", + .activationArcs = { { .placeName = "InputB" }, + { .placeName = "MessagesMenu" } }, + .destinationArcs = { { .placeName = "ShowMessage" } }}); // Leave show message - createTransition({ "InputC", "ShowMessage" }, { "MessagesMenu" }); + createTransition({ .name = "T12", + .activationArcs = { { .placeName = "InputC" }, + { .placeName = "ShowMessage" } }, + .destinationArcs = { { .placeName = "MessagesMenu" } } }); } void MenuStateMachine::pressA() diff --git a/Examples/PhoneMenu/Controller/MenuStateMachine.h b/Examples/PhoneMenu/Controller/MenuStateMachine.h old mode 100644 new mode 100755 index a981e68..af80354 --- a/Examples/PhoneMenu/Controller/MenuStateMachine.h +++ b/Examples/PhoneMenu/Controller/MenuStateMachine.h @@ -1,7 +1,7 @@ /* * This file is part of PTN Engine * - * Copyright (c) 2017-2023 Eduardo Valgôde + * Copyright (c) 2017-2024 Eduardo Valgôde * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -18,29 +18,24 @@ #pragma once -#include "PTN_Engine/PTN_Engine.h" +#include "Controller/IMenuStateMachine.h" class Controller; -//! Implements PTN Engine net defining the phone menu behaviour. -/*! - * The behaviour is defined in the constructor. - */ -class MenuStateMachine : public ptne::PTN_Engine +//! +//! \brief Implements PTN Engine net defining the phone menu behaviour. +//! +class MenuStateMachine : public IMenuStateMachine { public: - /*! - * Constructor. - * \param ptrDispatcher Shared pointer to the controller. - */ - explicit MenuStateMachine(Controller &menuController); + void setControllerFunctions(Controller &menuController) override; //! Press A key event. - void pressA(); + void pressA() override; //! Press B key event. - void pressB(); + void pressB() override; //! Press C key event. - void pressC(); + void pressC() override; }; diff --git a/Examples/PhoneMenu/Controller/XMLMenuStateMachine.cpp b/Examples/PhoneMenu/Controller/XMLMenuStateMachine.cpp new file mode 100755 index 0000000..d6472f2 --- /dev/null +++ b/Examples/PhoneMenu/Controller/XMLMenuStateMachine.cpp @@ -0,0 +1,67 @@ +/* + * This file is part of PTN Engine + * + * Copyright (c) 2017-2024 Eduardo Valgôde + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "Controller/XMLMenuStateMachine.h" +#include "Controller/Controller.h" +#include "PTN_Engine/ImportExport/IFileExporter.h" +#include "PTN_Engine/ImportExport/IFileImporter.h" +#include "PTN_Engine/ImportExport/ExporterFactory.h" +#include "PTN_Engine/ImportExport/ImporterFactory.h" + +using namespace ptne; +using namespace std; + +void XMLMenuStateMachine::setControllerFunctions(Controller &menuController) +{ + registerAction("showMainMenu", bind_front(&Controller::showMainMenu, &menuController)); + registerAction("selectMessagesOption", bind_front(&Controller::selectMessagesOption, &menuController)); + registerAction("selectCallsOption", bind_front(&Controller::selectCallsOption, &menuController)); + registerAction("showCallsMenu", bind_front(&Controller::showCallsMenu, &menuController)); + registerAction("showMessageMenu", bind_front(&Controller::showMessageMenu, &menuController)); + registerAction("selectNextMessage", bind_front(&Controller::selectNextMessage, &menuController)); + registerAction("showMessage", bind_front(&Controller::showMessage, &menuController)); + registerCondition("DummyFunction", bind_front(&Controller::justReturnTrue, &menuController)); +} + +void XMLMenuStateMachine::pressA() +{ + incrementInputPlace("InputA"); +} + +void XMLMenuStateMachine::pressB() +{ + incrementInputPlace("InputB"); +} + +void XMLMenuStateMachine::pressC() +{ + incrementInputPlace("InputC"); +} + +void XMLMenuStateMachine::exportStateMachine(const string &filePath) const +{ + unique_ptr xmlExporter = ExporterFactory::createXMLFileExporter(); + xmlExporter->_export(*this, filePath); +} + +void XMLMenuStateMachine::importStateMachine(const string &filePath) +{ + unique_ptr xmlImporter = ImporterFactory::createXMLFileImporter(); + clearNet(); + xmlImporter->_import(filePath, *this); +} diff --git a/Examples/PhoneMenuXML/Model/Call.h b/Examples/PhoneMenu/Controller/XMLMenuStateMachine.h old mode 100644 new mode 100755 similarity index 56% rename from Examples/PhoneMenuXML/Model/Call.h rename to Examples/PhoneMenu/Controller/XMLMenuStateMachine.h index dc68d32..d2e9327 --- a/Examples/PhoneMenuXML/Model/Call.h +++ b/Examples/PhoneMenu/Controller/XMLMenuStateMachine.h @@ -1,7 +1,7 @@ /* * This file is part of PTN Engine * - * Copyright (c) 2017-2019 Eduardo Valgôde + * Copyright (c) 2017-2024 Eduardo Valgôde * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -17,22 +17,22 @@ */ #pragma once -#include + +#include "Controller/IMenuStateMachine.h" + +class Controller; //! -class Call +//! \brief Implements PTN Engine net defining the phone menu behaviour. +//! +class XMLMenuStateMachine : public IMenuStateMachine { public: - //! - Call(const std::string &date, const std::string &number) - : m_date(date) - , m_number(number) - { - } - - //! - std::string m_date; + void setControllerFunctions(Controller &menuController) override; + void pressA() override; + void pressB() override; + void pressC() override; - //! - std::string m_number; + void exportStateMachine(const std::string &filePath) const; + void importStateMachine(const std::string &filePath); }; diff --git a/Examples/PhoneMenu/Model/Call.h b/Examples/PhoneMenu/Model/Call.h old mode 100644 new mode 100755 index 9d5cbc4..91af0f1 --- a/Examples/PhoneMenu/Model/Call.h +++ b/Examples/PhoneMenu/Model/Call.h @@ -1,7 +1,7 @@ /* * This file is part of PTN Engine * - * Copyright (c) 2017 Eduardo Valgôde + * Copyright (c) 2017-2024 Eduardo Valgôde * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -17,22 +17,12 @@ */ #pragma once + #include -//! class Call { public: - //! - Call(const std::string &date, const std::string &number) - : m_date(date) - , m_number(number) - { - } - - //! std::string m_date; - - //! std::string m_number; }; diff --git a/Examples/PhoneMenu/Model/List.h b/Examples/PhoneMenu/Model/List.h old mode 100644 new mode 100755 index 3d52b50..7e1e9ef --- a/Examples/PhoneMenu/Model/List.h +++ b/Examples/PhoneMenu/Model/List.h @@ -1,7 +1,7 @@ /* * This file is part of PTN Engine * - * Copyright (c) 2017 Eduardo Valgôde + * Copyright (c) 2017-2024 Eduardo Valgôde * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -17,6 +17,7 @@ */ #pragma once + #include #include @@ -27,29 +28,29 @@ class List public: List() = default; - /*! - * Add an item to the list. - * \param item Item. - */ + //! + //! \brief Add an item to the list. + //! \param item Item. + //! void addItem(const T &item) { m_items.push_back(item); } - /*! - * The number of elements. - * \return Number of elements. - */ + //! + //! \brief The number of elements. + //! \return Number of elements. + //! size_t size() const { return m_items.size(); } - /*! - * Get an item from the list. - * \param i Index of the selected item. - * \return A copy of the item. - */ + //! + //! \brief Get an item from the list. + //! \param i Index of the selected item. + //! \return A copy of the item. + //! T getItem(const size_t i) const { if (i < m_items.size()) diff --git a/Examples/PhoneMenu/Model/Message.h b/Examples/PhoneMenu/Model/Message.h old mode 100644 new mode 100755 index e4a8f99..36a4068 --- a/Examples/PhoneMenu/Model/Message.h +++ b/Examples/PhoneMenu/Model/Message.h @@ -1,7 +1,7 @@ /* * This file is part of PTN Engine * - * Copyright (c) 2017 Eduardo Valgôde + * Copyright (c) 2017-2024 Eduardo Valgôde * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -17,26 +17,13 @@ */ #pragma once + #include //! A very simple message model. class Message { public: - /*! - * Message constructor. - * \param title Title of the message. - * \param message Body of the message. - */ - Message(const std::string &title, const std::string &message) - : m_title(title) - , m_body(message) - { - } - - //! Message title. std::string m_title; - - //! Message body. std::string m_body; }; diff --git a/Examples/PhoneMenu/View/CallLogView.cpp b/Examples/PhoneMenu/View/CallLogView.cpp old mode 100644 new mode 100755 index a8a1841..c86ff27 --- a/Examples/PhoneMenu/View/CallLogView.cpp +++ b/Examples/PhoneMenu/View/CallLogView.cpp @@ -17,16 +17,20 @@ */ #include "View/CallLogView.h" - #include using namespace std; -void CallLogView::viewCallLog(const List &callLog) +CallLogView::CallLogView(List &callLog) +: m_callLog(callLog) +{ +} + +void CallLogView::viewCallLog() const { - for (size_t i = 0; i < callLog.size(); ++i) + for (size_t i = 0; i < m_callLog.size(); ++i) { - const Call &call = callLog.getItem(i); + const Call &call = m_callLog.getItem(i); cout << call.m_date << " - " << call.m_number << endl; } } diff --git a/Examples/PhoneMenu/View/CallLogView.h b/Examples/PhoneMenu/View/CallLogView.h old mode 100644 new mode 100755 index 17d8e09..dac3d1c --- a/Examples/PhoneMenu/View/CallLogView.h +++ b/Examples/PhoneMenu/View/CallLogView.h @@ -25,11 +25,14 @@ class CallLogView { public: - CallLogView() = default; + CallLogView(List &callLog); - /*! - * Print the call logs on screen. - * \param callLog List of calls. - */ - void viewCallLog(const List &callLog); + //! + //! Print the call logs on screen. + //! \param callLog List of calls. + //! + void viewCallLog() const; + +private: + List &m_callLog; }; diff --git a/Examples/PhoneMenu/View/MainMenuView.cpp b/Examples/PhoneMenu/View/MainMenuView.cpp old mode 100644 new mode 100755 index 3a3bbc1..377d19c --- a/Examples/PhoneMenu/View/MainMenuView.cpp +++ b/Examples/PhoneMenu/View/MainMenuView.cpp @@ -1,7 +1,7 @@ /* * This file is part of PTN Engine * - * Copyright (c) 2017 Eduardo Valgôde + * Copyright (c) 2017-2024 Eduardo Valgôde * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -17,21 +17,11 @@ */ #include "View/MainMenuView.h" - #include #include using namespace std; -MainMenuView::MainMenuView() -: m_selection(0) -{ -} - -MainMenuView::~MainMenuView() -{ -} - void MainMenuView::showMenu() const { cout << "OPTIONS:" << endl; diff --git a/Examples/PhoneMenu/View/MainMenuView.h b/Examples/PhoneMenu/View/MainMenuView.h old mode 100644 new mode 100755 index 5976afe..fbe2f3e --- a/Examples/PhoneMenu/View/MainMenuView.h +++ b/Examples/PhoneMenu/View/MainMenuView.h @@ -22,21 +22,16 @@ class MainMenuView { public: - //! - MainMenuView(); - - ~MainMenuView(); - //! Print the menu on screen. void showMenu() const; - /*! - * Select an option. - * \param option Number of the option. - */ + //! + //! Select an option. + //! \param option Number of the option. + //! void select(const int option); private: //! Selected option. - int m_selection; + int m_selection = 0; }; diff --git a/Examples/PhoneMenu/View/MessagesMenuView.cpp b/Examples/PhoneMenu/View/MessagesMenuView.cpp old mode 100644 new mode 100755 index ed21722..d70080f --- a/Examples/PhoneMenu/View/MessagesMenuView.cpp +++ b/Examples/PhoneMenu/View/MessagesMenuView.cpp @@ -1,7 +1,7 @@ /* * This file is part of PTN Engine * - * Copyright (c) 2017-2018 Eduardo Valgôde + * Copyright (c) 2017-2024 Eduardo Valgôde * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -17,14 +17,18 @@ */ #include "View/MessagesMenuView.h" - #include using namespace std; -void MessagesMenuView::showMessagesList(const MessageList &messageList, const size_t selectedMessage) +MessagesMenuView::MessagesMenuView(MessageList& messagesList): +m_messageList(messagesList) +{ +} + +void MessagesMenuView::showMessagesList(const size_t selectedMessage) const { - for (size_t i = 0; i < messageList.size(); ++i) + for (size_t i = 0; i < m_messageList.size(); ++i) { if (i == selectedMessage) { @@ -34,11 +38,11 @@ void MessagesMenuView::showMessagesList(const MessageList &messageList, const si { cout << " "; } - cout << i << " - " << messageList.getItem(i).m_title << endl; + cout << i << " - " << m_messageList.getItem(i).m_title << endl; } } -void MessagesMenuView::displayMessage(const Message &message) +void MessagesMenuView::displayMessage(const Message &message) const { cout << "TITLE:" << endl; cout << message.m_title << endl << endl; diff --git a/Examples/PhoneMenu/View/MessagesMenuView.h b/Examples/PhoneMenu/View/MessagesMenuView.h old mode 100644 new mode 100755 index 260b0dc..fdbfa11 --- a/Examples/PhoneMenu/View/MessagesMenuView.h +++ b/Examples/PhoneMenu/View/MessagesMenuView.h @@ -1,7 +1,7 @@ /* * This file is part of PTN Engine * - * Copyright (c) 2017-2018 Eduardo Valgôde + * Copyright (c) 2017-2024 Eduardo Valgôde * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -18,8 +18,6 @@ #pragma once -#include - #include "Model/List.h" #include "Model/Message.h" @@ -29,18 +27,21 @@ class MessagesMenuView public: using MessageList = List; - MessagesMenuView() = default; + MessagesMenuView(MessageList& messagesList); + + //! + //! Show the message list on screen. + //! \param messageList List of messages. + //! \param selectedMessage Selected message from the list. + //! + void showMessagesList(const size_t selectedMessage) const; - /*! - * Show the message list on screen. - * \param messageList List of messages. - * \param selectedMessage Selected message from the list. - */ - void showMessagesList(const MessageList &messageList, const size_t selectedMessage); + //! + //! Print the selected message on screen. + //! \param message Message to be displayed. + //! + void displayMessage(const Message &message) const; - /*! - * Print the selected message on screen. - * \param message Message to be displayed. - */ - void displayMessage(const Message &message); +private: + MessageList &m_messageList; }; diff --git a/Examples/PhoneMenu/assets/PhoneMenu.xml b/Examples/PhoneMenu/assets/PhoneMenu.xml new file mode 100644 index 0000000..bfbfec7 --- /dev/null +++ b/Examples/PhoneMenu/assets/PhoneMenu.xml @@ -0,0 +1,279 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Examples/PhoneMenu/main.cpp b/Examples/PhoneMenu/main.cpp old mode 100644 new mode 100755 index cc99d1d..ca19f0e --- a/Examples/PhoneMenu/main.cpp +++ b/Examples/PhoneMenu/main.cpp @@ -1,7 +1,7 @@ /* * This file is part of PTN Engine * - * Copyright (c) 2017-2023 Eduardo Valgôde + * Copyright (c) 2017-2024 Eduardo Valgôde * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -16,13 +16,21 @@ * limitations under the License. */ -#include - #include "Controller/Controller.h" +#include "Controller/MenuStateMachine.h" +#include "Controller/XMLMenuStateMachine.h" +#include "Model/Call.h" +#include "Model/List.h" +#include "Model/Message.h" +#include "View/CallLogView.h" +#include "View/MainMenuView.h" +#include "View/MessagesMenuView.h" +#include +#include using namespace std; -void programLoop(Controller &controller) +static void programLoop(Controller &controller) { bool exit = false; do @@ -57,26 +65,63 @@ void programLoop(Controller &controller) } while (!exit); } +void populateMessageList(List &messageList) +{ + messageList.addItem(Message("Hi...", "Hi John, don't forget to water the plants.")); + messageList.addItem(Message("Is...", "Is this thing working?")); + messageList.addItem(Message("Please...", "Please top up your phone.")); +} + +void populateCallLog(List &callLog) +{ + callLog.addItem(Call("10:05:03 29-JUN-2018", "John Doe")); + callLog.addItem(Call("09:35:50 29-JUN-2018", "Sally Smith")); + callLog.addItem(Call("09:12:01 29-JUN-2018", "Dick Jones")); + callLog.addItem(Call("08:59:47 29-JUN-2018", "Harry Brown")); +} + +void runLoop(Controller &controller) +{ + controller.execute(); + controller.pressA(); + programLoop(controller); + controller.stop(); +} + int main(int, char **) { - // Set up controller - Controller controller; + // Create data + List messageList; + populateMessageList(messageList); + List callLog; + populateCallLog(callLog); - // Set up data - controller.messageList().addItem(Message("Hi...", "Hi John, don't forget to water the plants.")); - controller.messageList().addItem(Message("Is...", "Is this thing working?")); - controller.messageList().addItem(Message("Please...", "Please top up your phone.")); + // Create views + MainMenuView mainMenuView; + MessagesMenuView messagesMenuView(messageList); + CallLogView callLogView(callLog); - controller.callLog().addItem(Call("10:05:03 29-JUN-2018", "John Doe")); - controller.callLog().addItem(Call("09:35:50 29-JUN-2018", "Sally Smith")); - controller.callLog().addItem(Call("09:12:01 29-JUN-2018", "Dick Jones")); - controller.callLog().addItem(Call("08:59:47 29-JUN-2018", "Harry Brown")); + // Create the controller + Controller controller(mainMenuView, messagesMenuView, callLogView, messageList, callLog); - controller.execute(); + // Set a state machine in the controller + controller.setStateMachine(make_shared()); - controller.pressA(); + runLoop(controller); - programLoop(controller); + cout << "Switching state machine" << endl; + + auto xmlMenuStateMachine = make_shared(); + controller.setStateMachine(xmlMenuStateMachine); +#ifdef WIN32 + xmlMenuStateMachine->importStateMachine("../PhoneMenu.xml"); +#else + xmlMenuStateMachine->importStateMachine("./PhoneMenu.xml"); +#endif + // export the state machine just as an example + xmlMenuStateMachine->exportStateMachine("./PhoneMenuExport.xml"); + + runLoop(controller); cout << "Successfully terminated" << endl; return 0; diff --git a/Examples/PhoneMenuXML/.clang-format b/Examples/PhoneMenuXML/.clang-format deleted file mode 100644 index c447e67..0000000 --- a/Examples/PhoneMenuXML/.clang-format +++ /dev/null @@ -1,47 +0,0 @@ -AccessModifierOffset: -4 -AlignEscapedNewlinesLeft: true -AlignTrailingComments: false -AllowAllParametersOfDeclarationOnNextLine: false -AllowShortFunctionsOnASingleLine: false -AllowShortIfStatementsOnASingleLine: true -AllowShortLoopsOnASingleLine: false -AlwaysBreakBeforeMultilineStrings: false -AlwaysBreakTemplateDeclarations: true -BinPackParameters: false -BreakBeforeBinaryOperators: false -BreakBeforeBraces: Allman -BreakBeforeTernaryOperators: false -BreakConstructorInitializersBeforeComma: true -ColumnLimit: 115 -CommentPragmas: '' -ConstructorInitializerAllOnOneLineOrOnePerLine: false -ConstructorInitializerIndentWidth: 0 -ContinuationIndentWidth: 0 -Cpp11BracedListStyle: false -DerivePointerBinding: false -IndentCaseLabels: false -IndentFunctionDeclarationAfterType: false -IndentWidth: 4 -Language: Cpp -MaxEmptyLinesToKeep: 2 -NamespaceIndentation: Inner -ObjCSpaceAfterProperty: true -ObjCSpaceBeforeProtocolList: true -PenaltyBreakBeforeFirstCallParameter: 115 -PenaltyBreakComment: 115 -PenaltyBreakFirstLessLess: 0 -PenaltyBreakString: 115 -PenaltyExcessCharacter: 115 -PenaltyReturnTypeOnItsOwnLine: 20 -SpaceBeforeAssignmentOperators: true -SpaceBeforeParens: ControlStatements -SpaceInEmptyParentheses: false -SpacesBeforeTrailingComments: 1 -SpacesInAngles: false -SpacesInCStyleCastParentheses: false -SpacesInContainerLiterals: false -SpacesInParentheses: false -Standard: Cpp11 -TabWidth: 4 -UseTab: ForIndentation - diff --git a/Examples/PhoneMenuXML/CMakeLists.txt b/Examples/PhoneMenuXML/CMakeLists.txt deleted file mode 100644 index ecc2f47..0000000 --- a/Examples/PhoneMenuXML/CMakeLists.txt +++ /dev/null @@ -1,49 +0,0 @@ -# This file is part of PTN Engine -# -# Copyright (c) 2019-2023 Eduardo Valgôde -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -cmake_minimum_required (VERSION 3.8) - -set(PROJECT_TEST_NAME PhoneMenuXML) - -include_directories( - ${INCLUDE_DIR} - ${PROJECT_SOURCE_DIR}/PTN_Engine/ImportExport/include - ${PROJECT_SOURCE_DIR}/Examples/PhoneMenuXML - ) - -file( GLOB_RECURSE PhoneMenuXML_SRC - "*.h" - "*.cpp" - ) - -add_executable (PhoneMenuXML ${PhoneMenuXML_SRC}) -target_link_libraries(PhoneMenuXML PUBLIC - PTN_Engine - ImportExport) - -if(NOT BUILD_SHARED_LIBS) - set_target_properties(PhoneMenuXML PROPERTIES SUFFIX ${EXECUTABLE_STATIC_POSTFIX}${CMAKE_EXECUTABLE_SUFFIX}) -endif() -set_target_properties(PhoneMenuXML PROPERTIES DEBUG_POSTFIX ${CMAKE_DEBUG_POSTFIX}) - -file(COPY ${CMAKE_CURRENT_SOURCE_DIR}/assets/PhoneMenu.xml DESTINATION ${CMAKE_BINARY_DIR}/bin) - - -# Install rules -if(INSTALL_EXAMPLES) - install(TARGETS PhoneMenuXML - RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}) -endif() diff --git a/Examples/PhoneMenuXML/Controller/Controller.cpp b/Examples/PhoneMenuXML/Controller/Controller.cpp deleted file mode 100644 index dbabcc5..0000000 --- a/Examples/PhoneMenuXML/Controller/Controller.cpp +++ /dev/null @@ -1,136 +0,0 @@ -/* - * This file is part of PTN Engine - * - * Copyright (c) 2017-2023 Eduardo Valgôde - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "Controller/Controller.h" -#include "PTN_Engine/IExporter.h" -#include "PTN_Engine/IImporter.h" -#include "PTN_Engine/ImportExport/ExportFactory.h" -#include "PTN_Engine/ImportExport/ImportFactory.h" -#include - -using namespace std; - -Controller::Controller() -: m_petriNet(ptne::PTN_Engine::ACTIONS_THREAD_OPTION::EVENT_LOOP) -, m_messageSelected(0) -{ - m_petriNet.registerAction("showMainMenu", bind(&Controller::showMainMenu, this)); - m_petriNet.registerAction("selectMessagesOption", bind(&Controller::selectMessagesOption, this)); - m_petriNet.registerAction("selectCallsOption", bind(&Controller::selectCallsOption, this)); - m_petriNet.registerAction("showCallsMenu", bind(&Controller::showCallsMenu, this)); - m_petriNet.registerAction("showMessageMenu", bind(&Controller::showMessageMenu, this)); - m_petriNet.registerAction("selectNextMessage", bind(&Controller::selectNextMessage, this)); - m_petriNet.registerAction("showMessage", bind(&Controller::showMessage, this)); - m_petriNet.registerCondition("DummyFunction", bind(&Controller::justReturnTrue, this)); -} - -Controller::~Controller() -{ -} - -void Controller::pressA() -{ - m_petriNet.incrementInputPlace("InputA"); -} - -void Controller::pressB() -{ - m_petriNet.incrementInputPlace("InputB"); -} - -void Controller::pressC() -{ - m_petriNet.incrementInputPlace("InputC"); -} - -Controller::MessageList &Controller::messageList() -{ - return m_messageList; -} - -Controller::CallList &Controller::callLog() -{ - return m_callLog; -} - -void Controller::execute() -{ - m_petriNet.execute(); -} - -void Controller::stop() -{ - m_petriNet.stop(); -} - -void Controller::exportStateMachine(const string &filePath) const -{ - unique_ptr xmlExporter = ptne::ExportFactory::createXMLExporter(); - m_petriNet.export_(*xmlExporter); - xmlExporter->saveFile(filePath); -} - -void Controller::importStateMachine(const string &filePath) -{ - unique_ptr xmlImporter = ptne::ImportFactory::createXMLImporter(filePath); - m_petriNet.import(*xmlImporter); -} - -void Controller::showMainMenu() const -{ - m_mainMenu.showMenu(); -} - -void Controller::selectCallsOption() -{ - m_mainMenu.select(0); -} - -void Controller::selectMessagesOption() -{ - m_mainMenu.select(1); -} - -void Controller::showCallsMenu() -{ - m_callLogView.viewCallLog(m_callLog); -} - -void Controller::showMessageMenu() -{ - m_messagesMenu.showMessagesList(m_messageList, m_messageSelected); -} - -void Controller::selectNextMessage() -{ - ++m_messageSelected; - if (m_messageSelected == m_messageList.size()) - { - m_messageSelected = 0; - } -} - -void Controller::showMessage() -{ - m_messagesMenu.displayMessage(m_messageList.getItem(m_messageSelected)); -} - -bool Controller::justReturnTrue() -{ - return true; -} diff --git a/Examples/PhoneMenuXML/Controller/Controller.h b/Examples/PhoneMenuXML/Controller/Controller.h deleted file mode 100644 index 93b6566..0000000 --- a/Examples/PhoneMenuXML/Controller/Controller.h +++ /dev/null @@ -1,119 +0,0 @@ -/* - * This file is part of PTN Engine - * - * Copyright (c) 2017-2023 Eduardo Valgôde - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#pragma once - -#include "Model/Call.h" -#include "Model/List.h" -#include "Model/Message.h" -#include "PTN_Engine/PTN_Engine.h" -#include "View/CallLogView.h" -#include "View/MainMenuView.h" -#include "View/MessagesMenuView.h" - -//! Example of a controller class -/*! - * Controls the display of a simplified hypothetical phone's menus, - * using only three keys. - */ -class Controller -{ -public: - using MessageList = List; - - using CallList = List; - - Controller(); - - ~Controller(); - - void execute(); - - void stop(); - - // Actions - - //! Triggers an event indicating key "A" was pressed. - void pressA(); - - //! Triggers an event indicating key "B" was pressed. - void pressB(); - - //! Triggers an event indicating key "C" was pressed. - void pressC(); - - MessageList &messageList(); - - CallList &callLog(); - - void exportStateMachine(const std::string &filePath) const; - - void importStateMachine(const std::string &filePath); - -private: - //! The state machine of the controller. - ptne::PTN_Engine m_petriNet; - - //! Show the main menu on screen. - void showMainMenu() const; - - //! Select the calls option. - void selectCallsOption(); - - //! Select the messages option. - void selectMessagesOption(); - - //! Show the calls menu or log. - void showCallsMenu(); - - //! Show the messages menu. - void showMessageMenu(); - - //! Select the next message. - void selectNextMessage(); - - //! Show the selected message. - void showMessage(); - - //! Dummy function for showing in import export from files - bool justReturnTrue(); - - // Views - - //! A view of the main menu. - MainMenuView m_mainMenu; - - //! A view of the messages. - MessagesMenuView m_messagesMenu; - - //! A view of the call logs. - CallLogView m_callLogView; - - // Data sources - - //! The message data. - MessageList m_messageList; - - //! The call log data. - CallList m_callLog; - - // Internals - - //! Index of the selected message. - size_t m_messageSelected; -}; diff --git a/Examples/PhoneMenuXML/Model/List.h b/Examples/PhoneMenuXML/Model/List.h deleted file mode 100644 index 110afdb..0000000 --- a/Examples/PhoneMenuXML/Model/List.h +++ /dev/null @@ -1,65 +0,0 @@ -/* - * This file is part of PTN Engine - * - * Copyright (c) 2017-2019 Eduardo Valgôde - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#pragma once -#include -#include - -//! A very simple list based on std::vector -template -class List -{ -public: - List() = default; - - /*! - * Add an item to the list. - * \param item Item. - */ - void addItem(const T &item) - { - m_items.push_back(item); - } - - /*! - * The number of elements. - * \return Number of elements. - */ - size_t size() const - { - return m_items.size(); - } - - /*! - * Get an item from the list. - * \param i Index of the selected item. - * \return A copy of the item. - */ - T getItem(const size_t i) const - { - if (i < m_items.size()) - { - return m_items.at(i); - } - throw std::runtime_error("Out of bounds"); - } - -private: - //! Collection of items. - std::vector m_items; -}; diff --git a/Examples/PhoneMenuXML/Model/Message.h b/Examples/PhoneMenuXML/Model/Message.h deleted file mode 100644 index 2506700..0000000 --- a/Examples/PhoneMenuXML/Model/Message.h +++ /dev/null @@ -1,42 +0,0 @@ -/* - * This file is part of PTN Engine - * - * Copyright (c) 2017-2019 Eduardo Valgôde - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#pragma once -#include - -//! A very simple message model. -class Message -{ -public: - /*! - * Message constructor. - * \param title Title of the message. - * \param message Body of the message. - */ - Message(const std::string &title, const std::string &message) - : m_title(title) - , m_body(message) - { - } - - //! Message title. - std::string m_title; - - //! Message body. - std::string m_body; -}; diff --git a/Examples/PhoneMenuXML/View/CallLogView.cpp b/Examples/PhoneMenuXML/View/CallLogView.cpp deleted file mode 100644 index 4cde17e..0000000 --- a/Examples/PhoneMenuXML/View/CallLogView.cpp +++ /dev/null @@ -1,32 +0,0 @@ -/* - * This file is part of PTN Engine - * - * Copyright (c) 2017-2019 Eduardo Valgôde - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "View/CallLogView.h" - -#include - -using namespace std; - -void CallLogView::viewCallLog(const List &callLog) -{ - for (size_t i = 0; i < callLog.size(); ++i) - { - const Call &call = callLog.getItem(i); - cout << call.m_date << " - " << call.m_number << endl; - } -} diff --git a/Examples/PhoneMenuXML/View/CallLogView.h b/Examples/PhoneMenuXML/View/CallLogView.h deleted file mode 100644 index 579e95a..0000000 --- a/Examples/PhoneMenuXML/View/CallLogView.h +++ /dev/null @@ -1,35 +0,0 @@ -/* - * This file is part of PTN Engine - * - * Copyright (c) 2017-2019 Eduardo Valgôde - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#pragma once - -#include "Model/Call.h" -#include "Model/List.h" - -//! View the call logs -class CallLogView -{ -public: - CallLogView() = default; - - /*! - * Print the call logs on screen. - * \param callLog List of calls. - */ - void viewCallLog(const List &callLog); -}; diff --git a/Examples/PhoneMenuXML/View/MainMenuView.cpp b/Examples/PhoneMenuXML/View/MainMenuView.cpp deleted file mode 100644 index 8b6fb37..0000000 --- a/Examples/PhoneMenuXML/View/MainMenuView.cpp +++ /dev/null @@ -1,67 +0,0 @@ -/* - * This file is part of PTN Engine - * - * Copyright (c) 2017-2019 Eduardo Valgôde - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "View/MainMenuView.h" - -#include -#include - -using namespace std; - -MainMenuView::MainMenuView() -: m_selection(0) -{ -} - -MainMenuView::~MainMenuView() -{ -} - -void MainMenuView::showMenu() const -{ - cout << "OPTIONS:" << endl; - cout << "\tCall Log" << endl; - cout << "\tMessages" << endl << endl; - cout << "SELECTED: "; - switch (m_selection) - { - default: - throw runtime_error("Undefined"); - case 0: - cout << "Call Log" << endl; - break; - case 1: - cout << "Messages" << endl; - break; - } -} - -void MainMenuView::select(const int option) -{ - switch (option) - { - default: - throw runtime_error("Invalid option"); - case 0: - m_selection = 0; - break; - case 1: - m_selection = 1; - break; - } -} diff --git a/Examples/PhoneMenuXML/View/MessagesMenuView.cpp b/Examples/PhoneMenuXML/View/MessagesMenuView.cpp deleted file mode 100644 index 19c0dc7..0000000 --- a/Examples/PhoneMenuXML/View/MessagesMenuView.cpp +++ /dev/null @@ -1,48 +0,0 @@ -/* - * This file is part of PTN Engine - * - * Copyright (c) 2017-2019 Eduardo Valgôde - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "View/MessagesMenuView.h" - -#include - -using namespace std; - -void MessagesMenuView::showMessagesList(const MessageList &messageList, const size_t selectedMessage) -{ - for (size_t i = 0; i < messageList.size(); ++i) - { - if (i == selectedMessage) - { - cout << "=>"; - } - else - { - cout << " "; - } - cout << i << " - " << messageList.getItem(i).m_title << endl; - } -} - -void MessagesMenuView::displayMessage(const Message &message) -{ - cout << "TITLE:" << endl; - cout << message.m_title << endl << endl; - - cout << "MESSAGE:" << endl; - cout << message.m_body << endl << endl; -} diff --git a/Examples/PhoneMenuXML/View/MessagesMenuView.h b/Examples/PhoneMenuXML/View/MessagesMenuView.h deleted file mode 100644 index 72aa886..0000000 --- a/Examples/PhoneMenuXML/View/MessagesMenuView.h +++ /dev/null @@ -1,46 +0,0 @@ -/* - * This file is part of PTN Engine - * - * Copyright (c) 2017-2019 Eduardo Valgôde - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#pragma once - -#include - -#include "Model/List.h" -#include "Model/Message.h" - -//! View of the messages menu. -class MessagesMenuView -{ -public: - using MessageList = List; - - MessagesMenuView() = default; - - /*! - * Show the message list on screen. - * \param messageList List of messages. - * \param selectedMessage Selected message from the list. - */ - void showMessagesList(const MessageList &messageList, const size_t selectedMessage); - - /*! - * Print the selected message on screen. - * \param message Message to be displayed. - */ - void displayMessage(const Message &message); -}; diff --git a/Examples/PhoneMenuXML/assets/PhoneMenu.xml b/Examples/PhoneMenuXML/assets/PhoneMenu.xml deleted file mode 100644 index e0c27e7..0000000 --- a/Examples/PhoneMenuXML/assets/PhoneMenu.xml +++ /dev/null @@ -1,139 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/Examples/PhoneMenuXML/main.cpp b/Examples/PhoneMenuXML/main.cpp deleted file mode 100644 index f475284..0000000 --- a/Examples/PhoneMenuXML/main.cpp +++ /dev/null @@ -1,91 +0,0 @@ -/* - * This file is part of PTN Engine - * - * Copyright (c) 2017-2023 Eduardo Valgôde - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include - -#include "Controller/Controller.h" - -using namespace std; - -void programLoop(Controller &controller) -{ - bool exit = false; - do - { - cout << "a - switch option, b - Select, c - escape, q - quit" << endl; - - string userInput; - cin >> userInput; - - if (userInput == "a" || userInput == "A") - { - controller.pressA(); - } - else if (userInput == "b" || userInput == "B") - { - controller.pressB(); - } - else if (userInput == "c" || userInput == "C") - { - controller.pressC(); - } - else if (userInput == "q" || userInput == "Q") - { - cout << "Quitting..." << endl; - controller.stop(); - exit = true; - } - else - { - cout << "Invalid input" << endl; - } - } while (!exit); -} - -int main(int, char **) -{ - // Set up controller - Controller controller; -#ifdef WIN32 - controller.importStateMachine("../PhoneMenu.xml"); -#else - controller.importStateMachine("./PhoneMenu.xml"); -#endif - - // Set up data - controller.messageList().addItem(Message("Hi...", "Hi John, don't forget to water the plants.")); - controller.messageList().addItem(Message("Is...", "Is this thing working?")); - controller.messageList().addItem(Message("Please...", "Please top up your phone.")); - - controller.callLog().addItem(Call("10:05:03 29-JUN-2018", "John Doe")); - controller.callLog().addItem(Call("09:35:50 29-JUN-2018", "Sally Smith")); - controller.callLog().addItem(Call("09:12:01 29-JUN-2018", "Dick Jones")); - controller.callLog().addItem(Call("08:59:47 29-JUN-2018", "Harry Brown")); - - controller.execute(); - - controller.pressA(); - - programLoop(controller); - - cout << "Successfully terminated" << endl; - - controller.exportStateMachine("PhoneMenuExport.xml"); - - return 0; -} diff --git a/PTN_Engine/CMakeLists.txt b/PTN_Engine/CMakeLists.txt index 27f60ba..98108b4 100644 --- a/PTN_Engine/CMakeLists.txt +++ b/PTN_Engine/CMakeLists.txt @@ -1,13 +1,13 @@ # This file is part of PTN Engine -# +# # Copyright (c) 2017-2023 Eduardo Valgôde -# +# # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at -# +# # http://www.apache.org/licenses/LICENSE-2.0 -# +# # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -16,7 +16,7 @@ cmake_minimum_required (VERSION 3.8) -#Two variants of the PTN_Engine library are created. +#Two variants of the PTN_Engine library are created. include_directories ( ../ ${INCLUDE_DIR}) @@ -48,7 +48,7 @@ file (GLOB ${PTN_Engine_SRC_4} ${PTN_Engine_SRC_5}) -add_library (PTN_Engine +add_library (PTN_Engine ${PTN_Engine_SRC}) target_compile_definitions (PTN_Engine PUBLIC diff --git a/PTN_Engine/EventLoop.cpp b/PTN_Engine/EventLoop.cpp old mode 100644 new mode 100755 index a1c0e39..f1b7028 --- a/PTN_Engine/EventLoop.cpp +++ b/PTN_Engine/EventLoop.cpp @@ -1,7 +1,7 @@ /* * This file is part of PTN Engine * - * Copyright (c) 2023 Eduardo Valgôde + * Copyright (c) 2023-2024 Eduardo Valgôde * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -27,13 +27,10 @@ using namespace std; EventLoop::EventLoop(IPTN_EngineEL &ptnEngineInternal) : m_ptnEngine(ptnEngineInternal) -, m_sleepDuration(100ms) { } -EventLoop::~EventLoop() -{ -} +EventLoop::~EventLoop() = default; bool EventLoop::isRunning() const { @@ -75,31 +72,31 @@ void EventLoop::start(const bool log, ostream &o) void EventLoop::notifyNewEvent() { - unique_lock eventNotifierGuard(m_eventNotifierMutex); + unique_lock eventNotifierGuard(m_eventNotifierMutex); m_eventNotifier.notify_all(); } void EventLoop::setSleepDuration(const SleepDuration sleepDuration) { - unique_lock lock(m_sleepDurationMutex); + unique_lock lock(m_sleepDurationMutex); // TODO validate input m_sleepDuration = sleepDuration; } EventLoop::SleepDuration EventLoop::getSleepDuration() const { - shared_lock lock(m_sleepDurationMutex); + shared_lock lock(m_sleepDurationMutex); return m_sleepDuration; } -void EventLoop::run(std::stop_token stopToken, const bool log, ostream &o) +void EventLoop::run(stop_token stopToken, const bool log, ostream &o) { while (!stopToken.stop_requested()) { if (!m_ptnEngine.executeInt(log, o)) { - shared_lock lock(m_sleepDurationMutex); - unique_lock eventNotifierGuard(m_eventNotifierMutex); + shared_lock lock(m_sleepDurationMutex); + unique_lock eventNotifierGuard(m_eventNotifierMutex); m_eventNotifier.wait_for(eventNotifierGuard, m_sleepDuration, [this] { return m_ptnEngine.getNewInputReceived(); }); } diff --git a/PTN_Engine/EventLoop.h b/PTN_Engine/EventLoop.h old mode 100644 new mode 100755 index a39db82..284bb44 --- a/PTN_Engine/EventLoop.h +++ b/PTN_Engine/EventLoop.h @@ -32,19 +32,19 @@ namespace ptne class IPTN_EngineEL; class Transition; -/*! - * \brief The EventLoop class manages an event loop thread, where all the events are passed to the petri net - * engine. - */ +//! +//! \brief The EventLoop class manages an event loop thread, where all the events are passed to the petri net +//! engine. +//! class EventLoop { public: using SleepDuration = std::chrono::duration>; - /*! - * \brief EventLoop - * \param ptnEngineInternal - */ + //! + //! \brief EventLoop + //! \param ptnEngineInternal + //! explicit EventLoop(IPTN_EngineEL &ptnEngineInternal); ~EventLoop(); @@ -54,47 +54,47 @@ class EventLoop EventLoop &operator=(const EventLoop &) = delete; EventLoop &operator=(EventLoop &&) = delete; - /*! - * \brief Inform if the event loop is running. - * \return True if the event loop thread is running. - */ + //! + //! \brief Inform if the event loop is running. + //! \return True if the event loop thread is running. + //! bool isRunning() const; - /*! - * \brief Order the event loop to stop. - */ + //! + //! \brief Order the event loop to stop. + //! void stop() noexcept; - /*! - * \brief Start the event loop thread. - * \param log Whether to log or not. - * \param o The output stream to write the log messages to. - */ + //! + //! \brief Start the event loop thread. + //! \param log Whether to log or not. + //! \param o The output stream to write the log messages to. + //! void start(const bool log, std::ostream &o); - /*! - * \brief Notify the event loop thread of a new event. - */ + //! + //! \brief Notify the event loop thread of a new event. + //! void notifyNewEvent(); - /*! - * \brief Set the event loop watchdog timer period. - * \param sleepTime The event loop watchdog timer period. - */ + //! + //! \brief Set the event loop watchdog timer period. + //! \param sleepTime The event loop watchdog timer period. + //! void setSleepDuration(const SleepDuration sleepDuration); - /*! - * \brief Get the event loop watchdog timer period. - * \return The event loop watchdog timer period. - */ + //! + //! \brief Get the event loop watchdog timer period. + //! \return The event loop watchdog timer period. + //! SleepDuration getSleepDuration() const; private: - /*! - * \brief Event loop function. - * \param log Flag to turn on logging on or off. - * \param o Log where to write log messages. - */ + //! + //! \brief Event loop function. + //! \param log Flag to turn on logging on or off. + //! \param o Log where to write log messages. + //! void run(std::stop_token stopToken, const bool log, std::ostream &o); //! Reference to the petri net engine. @@ -113,7 +113,7 @@ class EventLoop mutable std::shared_mutex m_sleepDurationMutex; //! While idle, watchdog timer period. - SleepDuration m_sleepDuration; + SleepDuration m_sleepDuration = std::chrono::milliseconds(100); //! Event loop thread. std::jthread m_eventLoopThread; diff --git a/PTN_Engine/IPTN_EngineEL.h b/PTN_Engine/IPTN_EngineEL.h old mode 100644 new mode 100755 index 1ec0d39..cd624dd --- a/PTN_Engine/IPTN_EngineEL.h +++ b/PTN_Engine/IPTN_EngineEL.h @@ -24,12 +24,13 @@ namespace ptne { -/*! - * \brief The IPTN_EngineEL class - */ +//! +//! \brief The IPTN_EngineEL class +//! class IPTN_EngineEL { public: + virtual ~IPTN_EngineEL() = default; virtual bool executeInt(const bool log = false, std::ostream &o = std::cout) = 0; virtual bool getNewInputReceived() const = 0; virtual PTN_Engine::ACTIONS_THREAD_OPTION getActionsThreadOption() const = 0; diff --git a/PTN_Engine/IPTN_EnginePlace.h b/PTN_Engine/IPTN_EnginePlace.h old mode 100644 new mode 100755 index 4c1a0fe..c1404cf --- a/PTN_Engine/IPTN_EnginePlace.h +++ b/PTN_Engine/IPTN_EnginePlace.h @@ -23,12 +23,13 @@ namespace ptne { -/*! - * \brief The IPTN_EnginePlace class - */ +//! +//! \brief The IPTN_EnginePlace class +//! class IPTN_EnginePlace { public: + virtual ~IPTN_EnginePlace() = default; virtual PTN_Engine::ACTIONS_THREAD_OPTION getActionsThreadOption() const = 0; virtual void addJob(const ActionFunction &actionFunction) = 0; }; diff --git a/PTN_Engine/ImportExport/CMakeLists.txt b/PTN_Engine/ImportExport/CMakeLists.txt index 436e09a..8919127 100644 --- a/PTN_Engine/ImportExport/CMakeLists.txt +++ b/PTN_Engine/ImportExport/CMakeLists.txt @@ -1,13 +1,13 @@ # This file is part of PTN Engine -# +# # Copyright (c) 2019-2023 Eduardo Valgôde -# +# # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at -# +# # http://www.apache.org/licenses/LICENSE-2.0 -# +# # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. diff --git a/PTN_Engine/ImportExport/ImportFactory.cpp b/PTN_Engine/ImportExport/ExporterFactory.cpp old mode 100644 new mode 100755 similarity index 72% rename from PTN_Engine/ImportExport/ImportFactory.cpp rename to PTN_Engine/ImportExport/ExporterFactory.cpp index a436257..ca95a8c --- a/PTN_Engine/ImportExport/ImportFactory.cpp +++ b/PTN_Engine/ImportExport/ExporterFactory.cpp @@ -1,7 +1,7 @@ /* * This file is part of PTN Engine * - * Copyright (c) 2019-2023 Eduardo Valgôde + * Copyright (c) 2019-2024 Eduardo Valgôde * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -16,16 +16,16 @@ * limitations under the License. */ -#include "XML/XML_Importer.h" -#include +#include "PTN_Engine/ImportExport/ExporterFactory.h" +#include "XML/XML_FileExporter.h" namespace ptne { using namespace std; -unique_ptr ImportFactory::createXMLImporter(const string &filePath) +unique_ptr ExporterFactory::createXMLFileExporter() { - return make_unique(filePath); + return make_unique(); } } // namespace ptne diff --git a/PTN_Engine/ImportExport/IExporter.cpp b/PTN_Engine/ImportExport/IExporter.cpp new file mode 100755 index 0000000..c6b1a27 --- /dev/null +++ b/PTN_Engine/ImportExport/IExporter.cpp @@ -0,0 +1,51 @@ +/* + * This file is part of PTN Engine + * + * Copyright (c) 2024 Eduardo Valgôde + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "PTN_Engine/ImportExport/IFileExporter.h" +#include "PTN_Engine/PTN_Exception.h" + +namespace ptne +{ +using namespace std; + +void IFileExporter::_export(const PTN_Engine &ptnEngine) +{ + if (ptnEngine.isEventLoopRunning()) + { + throw PTN_Exception("Cannot change actions thread option while the event loop is running."); + } + + exportActionsThreadOption(PTN_Engine::toString(ptnEngine.getActionsThreadOption())); + + for (const auto &placeProperties : ptnEngine.getPlacesProperties()) + { + exportPlace(placeProperties); + } + + for (const auto &transitionProperties : ptnEngine.getTransitionsProperties()) + { + exportTransition(transitionProperties); + } + + for (const auto &arcProperties : ptnEngine.getArcsProperties()) + { + exportArc(arcProperties); + } +} + +} // namespace ptne diff --git a/PTN_Engine/ImportExport/IImporter.cpp b/PTN_Engine/ImportExport/IImporter.cpp new file mode 100755 index 0000000..a510437 --- /dev/null +++ b/PTN_Engine/ImportExport/IImporter.cpp @@ -0,0 +1,51 @@ +/* + * This file is part of PTN Engine + * + * Copyright (c) 2024 Eduardo Valgôde + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "PTN_Engine/ImportExport/IFileImporter.h" + +namespace ptne +{ +using namespace std; + +void IFileImporter::_import(PTN_Engine &ptnEngine) const +{ + if (ptnEngine.isEventLoopRunning()) + { + ptnEngine.stop(); + } + + string actionsThreadOptionStr = importActionsThreadOption(); + ptnEngine.setActionsThreadOption(std::move(PTN_Engine::toACTIONS_THREAD_OPTION(actionsThreadOptionStr))); + + for (const auto &placeProperties : importPlaces()) + { + ptnEngine.createPlace(placeProperties); + } + + for (const auto &transitionProperties : importTransitions()) + { + ptnEngine.createTransition(transitionProperties); + } + + for (const auto &arcsProperties : importArcs()) + { + ptnEngine.addArc(arcsProperties); + } +} + +} // namespace ptne diff --git a/PTN_Engine/ImportExport/ExportFactory.cpp b/PTN_Engine/ImportExport/ImporterFactory.cpp old mode 100644 new mode 100755 similarity index 78% rename from PTN_Engine/ImportExport/ExportFactory.cpp rename to PTN_Engine/ImportExport/ImporterFactory.cpp index d08ba3e..b99888d --- a/PTN_Engine/ImportExport/ExportFactory.cpp +++ b/PTN_Engine/ImportExport/ImporterFactory.cpp @@ -16,16 +16,16 @@ * limitations under the License. */ -#include "XML/XML_Exporter.h" -#include +#include "PTN_Engine/ImportExport/ImporterFactory.h" +#include "XML/XML_FileImporter.h" namespace ptne { using namespace std; -unique_ptr ExportFactory::createXMLExporter() +unique_ptr ImporterFactory::createXMLFileImporter() { - return make_unique(); + return make_unique(); } } // namespace ptne diff --git a/PTN_Engine/ImportExport/XML/assets/PetriNet.xml b/PTN_Engine/ImportExport/XML/assets/PetriNet.xml index 3be6f50..69cc125 100644 --- a/PTN_Engine/ImportExport/XML/assets/PetriNet.xml +++ b/PTN_Engine/ImportExport/XML/assets/PetriNet.xml @@ -30,7 +30,8 @@ - + + @@ -48,7 +49,8 @@ - + + diff --git a/PTN_Engine/ImportExport/XML/src/XML/XML_Exporter.cpp b/PTN_Engine/ImportExport/XML/src/XML/XML_Exporter.cpp deleted file mode 100644 index cf2c5db..0000000 --- a/PTN_Engine/ImportExport/XML/src/XML/XML_Exporter.cpp +++ /dev/null @@ -1,111 +0,0 @@ -/* - * This file is part of PTN Engine - * - * Copyright (c) 2019 Eduardo Valgôde - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "XML/XML_Exporter.h" -#include -#include -#include - -namespace ptne -{ -using namespace pugi; -using namespace std; - -XML_Exporter::XML_Exporter() -{ - m_rootNode = m_document.append_child("PTN-Engine"); - m_rootNode.append_attribute("version").set_value("2.0"); - m_rootNode.append_attribute("format").set_value("1"); - m_rootNode.append_attribute("name").set_value("blah"); - m_placesNode = m_rootNode.append_child("Places"); - m_transitionsNode = m_rootNode.append_child("Transitions"); -} - -XML_Exporter::~XML_Exporter() -{ -} - -void XML_Exporter::exportActionsThreadOption(const std::string &actionsThreadOption) -{ - m_rootNode.append_attribute("actionsThreadOption").set_value(actionsThreadOption.c_str()); -} - -void XML_Exporter::exportPlace(const string &name, - const string &tokens, - const string &isInput, - const string &onEnterAction, - const string &onExitAction) -{ - xml_node placeNode = m_placesNode.append_child("Place"); - placeNode.append_attribute("name").set_value(name.c_str()); - placeNode.append_attribute("tokens").set_value(tokens.c_str()); - placeNode.append_attribute("input").set_value(isInput.c_str()); - placeNode.append_attribute("onEnterAction").set_value(onEnterAction.c_str()); - placeNode.append_attribute("onExitAction").set_value(onExitAction.c_str()); -} - -void XML_Exporter::exportTransition(const vector> &activationPlaces, - const vector> &destinationPlaces, - const vector &activationConditions, - const vector &inhibitorPlaces, - const bool requireNoActionInExecution) -{ - xml_node transitionNode = m_transitionsNode.append_child("Transition"); - - xml_node activationPlacesNode = transitionNode.append_child("ActivationPlaces"); - for (const auto &activationPlace : activationPlaces) - { - xml_node activationPlaceNode = activationPlacesNode.append_child("ActivationPlace"); - activationPlaceNode.append_attribute("name").set_value(get<0>(activationPlace).c_str()); - size_t weight = get<1>(activationPlace); - activationPlaceNode.append_attribute("weight").set_value(to_string(weight).c_str()); - } - - xml_node destinationPlacesNode = transitionNode.append_child("DestinationPlaces"); - for (const auto &destinationPlace : destinationPlaces) - { - xml_node destinationPlaceNode = destinationPlacesNode.append_child("DestinationPlace"); - destinationPlaceNode.append_attribute("name").set_value(get<0>(destinationPlace).c_str()); - size_t weight = get<1>(destinationPlace); - destinationPlaceNode.append_attribute("weight").set_value(to_string(weight).c_str()); - } - - xml_node activationConditionsNode = transitionNode.append_child("ActivationConditions"); - for (const auto &activationCondition : activationConditions) - { - xml_node activationConditionNode = activationConditionsNode.append_child("ActivationCondition"); - activationConditionNode.append_attribute("name").set_value(activationCondition.c_str()); - } - - xml_node inhibitorPlacesNode = transitionNode.append_child("InhibitorPlaces"); - for (const auto &inhibitorPlace : inhibitorPlaces) - { - xml_node inhibitorPlaceNode = inhibitorPlacesNode.append_child("InhibitorPlace"); - inhibitorPlaceNode.append_attribute("name").set_value(inhibitorPlace.c_str()); - } - - xml_node requireNoActionsInExecution = transitionNode.append_child("RequireNoActionsInExecution"); - requireNoActionsInExecution.append_attribute("value").set_value(requireNoActionInExecution); -} - -void XML_Exporter::saveFile(const string &filePath) const -{ - m_document.save_file(filePath.c_str()); -} - -} // namespace ptne diff --git a/PTN_Engine/ImportExport/XML/src/XML/XML_Exporter.h b/PTN_Engine/ImportExport/XML/src/XML/XML_Exporter.h deleted file mode 100644 index a3dd4a3..0000000 --- a/PTN_Engine/ImportExport/XML/src/XML/XML_Exporter.h +++ /dev/null @@ -1,85 +0,0 @@ -/* - * This file is part of PTN Engine - * - * Copyright (c) 2019-2022 Eduardo Valgôde - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#pragma once - -#include -#include -#include -#include - -namespace ptne -{ - -/*! - * \brief The XML_Exporter class - */ -class XML_Exporter : public IExporter -{ -public: - XML_Exporter(); - - ~XML_Exporter(); - - /*! - * \brief exportActionsThreadOption - * \param actionsThreadOption - */ - void exportActionsThreadOption(const std::string &actionsThreadOption) override; - - /*! - * \brief exportPlace - * \param name - * \param tokens - * \param isInput - * \param onEnterAction - * \param onExitAction - */ - void exportPlace(const std::string &name, - const std::string &tokens, - const std::string &isInput, - const std::string &onEnterAction, - const std::string &onExitAction) override; - - /*! - * \brief exportTransition - * \param activationPlaces - * \param destinationPlaces - * \param activationConditions - * \param inhibitorPlaces - * \param requireNoActionInExecution - */ - void exportTransition(const std::vector> &activationPlaces, - const std::vector> &destinationPlaces, - const std::vector &activationConditions, - const std::vector &inhibitorPlaces, - const bool requireNoActionInExecution) override; - - /*! - * \brief saveFile - * \param filePath - */ - void saveFile(const std::string &filePath) const override; - -private: - pugi::xml_node m_rootNode; - pugi::xml_document m_document; - pugi::xml_node m_placesNode; - pugi::xml_node m_transitionsNode; -}; -} // namespace ptne diff --git a/PTN_Engine/ImportExport/XML/src/XML/XML_FileExporter.cpp b/PTN_Engine/ImportExport/XML/src/XML/XML_FileExporter.cpp new file mode 100755 index 0000000..4b92958 --- /dev/null +++ b/PTN_Engine/ImportExport/XML/src/XML/XML_FileExporter.cpp @@ -0,0 +1,122 @@ +/* + * This file is part of PTN Engine + * + * Copyright (c) 2019-2024 Eduardo Valgôde + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "PTN_Engine/PTN_Engine.h" +#include "PTN_Engine/PTN_Exception.h" +#include "XML/XML_FileExporter.h" +#include +#include + +namespace ptne +{ +using namespace pugi; +using namespace std; + +void XML_FileExporter::_export(const PTN_Engine &ptnEngine, const string& filePath) +{ + m_filePath = filePath; + m_rootNode = m_document.append_child("PTN-Engine"); + m_rootNode.append_attribute("version").set_value("3.0"); + m_rootNode.append_attribute("format").set_value("1"); + m_rootNode.append_attribute("name").set_value("blah"); + m_placesNode = m_rootNode.append_child("Places"); + m_transitionsNode = m_rootNode.append_child("Transitions"); + m_arcsNode = m_rootNode.append_child("Arcs"); + IFileExporter::_export(ptnEngine); + saveFile(); +} + +void XML_FileExporter::exportActionsThreadOption(const string &actionsThreadOption) +{ + m_rootNode.append_attribute("actionsThreadOption").set_value(actionsThreadOption.c_str()); +} + +void XML_FileExporter::exportPlace(const PlaceProperties &placeProperties) +{ + xml_node placeNode = m_placesNode.append_child("Place"); + placeNode.append_attribute("name").set_value(placeProperties.name.c_str()); + placeNode.append_attribute("tokens").set_value(placeProperties.initialNumberOfTokens); + placeNode.append_attribute("input").set_value(placeProperties.input ? true : false); + placeNode.append_attribute("onEnterAction").set_value(placeProperties.onEnterActionFunctionName.c_str()); + placeNode.append_attribute("onExitAction").set_value(placeProperties.onExitActionFunctionName.c_str()); +} + +void XML_FileExporter::exportTransition(const TransitionProperties &transitionProperties) +{ + xml_node transitionNode = m_transitionsNode.append_child("Transition"); + + xml_node name = transitionNode.append_child("Name"); + name.append_attribute("value").set_value(transitionProperties.name.c_str()); + + xml_node activationConditionsNode = transitionNode.append_child("ActivationConditions"); + for (const auto &activationCondition : transitionProperties.additionalConditionsNames) + { + xml_node activationConditionNode = activationConditionsNode.append_child("ActivationCondition"); + activationConditionNode.append_attribute("name").set_value(activationCondition.c_str()); + } + + xml_node requireNoActionsInExecution = transitionNode.append_child("RequireNoActionsInExecution"); + requireNoActionsInExecution.append_attribute("value").set_value(transitionProperties.requireNoActionsInExecution? "true" : "false"); +} + +void XML_FileExporter::exportArc(const vector &arcsPropereties) +{ + for (const auto &arcProperties : arcsPropereties) + { + xml_node arcNode = m_arcsNode.append_child("Arc"); + xml_node place = arcNode.append_child("Place"); + place.append_attribute("value").set_value(arcProperties.placeName.c_str()); + + xml_node transition = arcNode.append_child("Transition"); + transition.append_attribute("value").set_value(arcProperties.transitionName.c_str()); + + xml_node weight = arcNode.append_child("Weight"); + weight.append_attribute("value").set_value(to_string(arcProperties.weight).c_str()); + + xml_node type = arcNode.append_child("Type"); + + using enum ArcProperties::Type; + string typeStr; + switch (arcProperties.type) + { + default: + throw PTN_Exception("Unsupported enum"); + break; + case ACTIVATION: + typeStr = "Activation"; + break; + case BIDIRECTIONAL: + typeStr = "Bidirectional"; + break; + case DESTINATION: + typeStr = "Destination"; + break; + case INHIBITOR: + typeStr = "Inhibitor"; + break; + } + type.append_attribute("value").set_value(typeStr.c_str()); + } +} + +void XML_FileExporter::saveFile() const +{ + m_document.save_file(m_filePath.c_str()); +} + +} // namespace ptne diff --git a/PTN_Engine/ImportExport/XML/src/XML/XML_FileExporter.h b/PTN_Engine/ImportExport/XML/src/XML/XML_FileExporter.h new file mode 100755 index 0000000..784e4ea --- /dev/null +++ b/PTN_Engine/ImportExport/XML/src/XML/XML_FileExporter.h @@ -0,0 +1,76 @@ +/* + * This file is part of PTN Engine + * + * Copyright (c) 2019-2024 Eduardo Valgôde + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#pragma once + +#include "PTN_Engine/ImportExport/IFileExporter.h" +#include + +namespace ptne +{ + +//! +//! \brief The XML_Exporter class +//! +class XML_FileExporter : public IFileExporter +{ +public: + ~XML_FileExporter() override = default; + + void _export(const PTN_Engine &ptnEngine, const std::string &filePath) override; + +private: + + //! + //! \brief exportActionsThreadOption + //! \param actionsThreadOption + //! + void exportActionsThreadOption(const std::string &actionsThreadOption) override; + + //! + //! \brief exportPlace + //! \param placeProperties + //! + void exportPlace(const PlaceProperties &placeProperties) override; + + //! + //! \brief exportTransition + //! \param transitionProperties + //! + void exportTransition(const TransitionProperties &transitionProperties) override; + + //! + //! \brief exportArc + //! \param arcPropereties + //! + void exportArc(const std::vector &arcPropereties) override; + + //! + //! \brief saveFile + //! \param filePath + //! + void saveFile() const; + + pugi::xml_node m_rootNode; + pugi::xml_document m_document; + pugi::xml_node m_placesNode; + pugi::xml_node m_transitionsNode; + pugi::xml_node m_arcsNode; + std::string m_filePath; +}; +} // namespace ptne diff --git a/PTN_Engine/ImportExport/XML/src/XML/XML_FileImporter.cpp b/PTN_Engine/ImportExport/XML/src/XML/XML_FileImporter.cpp new file mode 100755 index 0000000..2f7b2b0 --- /dev/null +++ b/PTN_Engine/ImportExport/XML/src/XML/XML_FileImporter.cpp @@ -0,0 +1,220 @@ +/* + * This file is part of PTN Engine + * + * Copyright (c) 2019-2024 Eduardo Valgôde + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "PTN_Engine/PTN_Engine.h" +#include "PTN_Engine/PTN_Exception.h" +#include "XML/XML_FileImporter.h" +#include +#include +#include + +using namespace pugi; +using namespace std; +using namespace ptne; + +namespace +{ +string getAttributeValue(const xml_node &node, const string &attrName) +{ + return node.attribute(attrName.c_str()).value(); +} + +vector collectTransitionAttributes(const xml_node &transition, const string &attribute) +{ + vector activationConditions; + const auto &childAttributes = transition.child(attribute.c_str()); + ranges::transform(begin(childAttributes), end(childAttributes), back_inserter(activationConditions), + [](const auto &activationCondition) { return activationCondition.attribute("name").value(); }); + return activationConditions; +} + +vector collectArcAttributes(const xml_node &transition, const string &attribute, const ArcProperties::Type type) +{ + vector arcsProperties; + for (xml_node activationCondition : transition.child(attribute.c_str())) + { + const string activationConditionName(activationCondition.attribute("name").value()); + size_t weight = 1; + const string weightStr(activationCondition.attribute("weight").value()); + if (!string(activationCondition.attribute("weight").value()).empty()) + { + weight = static_cast(atol(weightStr.c_str())); + } + + arcsProperties.emplace_back(weight, + activationCondition.attribute("name").value(), + activationConditionName, + type); + } + return arcsProperties; +} + +template +T getNodeValue(const string &nodeName, const xml_node &xmlNode) +{ + return xmlNode.child(nodeName.c_str()).attribute("value").value(); +} + +template <> +bool getNodeValue(const string &nodeName, const xml_node &xmlNode) +{ + const string v = xmlNode.child(nodeName.c_str()).attribute("value").value(); + if (v == "true") + { + return true; + } + else if (v == "false") + { + return false; + } + else + { + throw PTN_Exception("Invalid value for " + nodeName + ": " + v); + } +} + +template <> +size_t getNodeValue(const string &nodeName, const xml_node &xmlNode) +{ + const string v = xmlNode.child(nodeName.c_str()).attribute("value").value(); + + size_t result{}; + auto [ptr, ec] = from_chars(v.data(), v.data() + v.size(), result); + + if (ec != errc()) + { + throw PTN_Exception("Could not convert from string to int"); + } + + return result; +} + +} // namespace + +namespace ptne +{ +void XML_FileImporter::_import(const string &filePath, PTN_Engine &ptnEngine) +{ + xml_parse_result result = m_document.load_file(filePath.c_str()); + + if (!result) + { + throw PTN_Exception(result.description()); + } + + IFileImporter::_import(ptnEngine); +} + +string XML_FileImporter::importActionsThreadOption() const +{ + return m_document.child("PTN-Engine").attribute("actionsThreadOption").as_string(); +} + +vector XML_FileImporter::importPlaces() const +{ + vector placesInfoCollection; + for (const xml_node &place : m_document.child("PTN-Engine").child("Places")) + { + PlaceProperties placeProperties; + bool isInput = false; + const string isInputStr = getAttributeValue(place, "input"); + if (!isInputStr.empty()) + { + isInput = getAttributeValue(place, "input") == "true" ? true : false; + } + + size_t numberOfTokens = 0; + const string numberOfTokensStr = getAttributeValue(place, "tokens"); + if (!numberOfTokensStr.empty()) + { + numberOfTokens = static_cast(atol(numberOfTokensStr.c_str())); + } + + placeProperties.name = getAttributeValue(place, "name"); + placeProperties.initialNumberOfTokens = numberOfTokens; + placeProperties.onEnterActionFunctionName = getAttributeValue(place, "onEnterAction"); + placeProperties.onExitActionFunctionName = getAttributeValue(place, "onExitAction"); + placeProperties.input = isInput; + + placesInfoCollection.emplace_back(placeProperties); + } + return placesInfoCollection; +} + +vector XML_FileImporter::importTransitions() const +{ + vector transitionInfoCollection; + for (xml_node transition : m_document.child("PTN-Engine").child("Transitions")) + { + TransitionProperties transitionProperties; + + const auto activationConditions = collectTransitionAttributes(transition, "ActivationConditions"); + transitionProperties.name = getNodeValue("Name", transition); + transitionProperties.activationArcs = collectArcAttributes(transition, "ActivationPlaces", + ArcProperties::Type::ACTIVATION); + transitionProperties.destinationArcs = collectArcAttributes(transition, "DestinationPlaces", + ArcProperties::Type::DESTINATION); + transitionProperties.inhibitorArcs = collectArcAttributes(transition, "InhibitorPlaces", + ArcProperties::Type::INHIBITOR);; + transitionProperties.additionalConditionsNames = activationConditions; + transitionProperties.requireNoActionsInExecution = getNodeValue("RequireNoActionsInExecution", transition); + transitionInfoCollection.emplace_back(transitionProperties); + } + return transitionInfoCollection; +} + +vector XML_FileImporter::importArcs() const +{ + vector arcInfoCollection; + for (xml_node arc : m_document.child("PTN-Engine").child("Arcs")) + { + ArcProperties arcProperties; + + arcProperties.placeName = getNodeValue("Place", arc); + arcProperties.transitionName = getNodeValue("Transition", arc); + arcProperties.weight = getNodeValue("Weight", arc); + + using enum ArcProperties::Type; + auto typeStr = getNodeValue("Type", arc); + if (typeStr == "Activation") + { + arcProperties.type = ACTIVATION; + } + else if (typeStr == "Bidirectional") + { + arcProperties.type = BIDIRECTIONAL; + } + else if (typeStr == "Destination") + { + arcProperties.type = DESTINATION; + } + else if (typeStr == "Inhibitor") + { + arcProperties.type = INHIBITOR; + } + else + { + throw PTN_Exception("Type string not supported"); + } + + arcInfoCollection.emplace_back(arcProperties); + } + return arcInfoCollection; +} + +} // namespace ptne diff --git a/PTN_Engine/ImportExport/XML/src/XML/XML_FileImporter.h b/PTN_Engine/ImportExport/XML/src/XML/XML_FileImporter.h new file mode 100755 index 0000000..2344729 --- /dev/null +++ b/PTN_Engine/ImportExport/XML/src/XML/XML_FileImporter.h @@ -0,0 +1,70 @@ +/* + * This file is part of PTN Engine + * + * Copyright (c) 2019-2024 Eduardo Valgôde + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#pragma once + +#include "PTN_Engine/ImportExport/IFileImporter.h" +#include +#include + +namespace ptne +{ +class PTN_Engine; + +//! +//! \brief The XML_Importer class +//! +class XML_FileImporter : public IFileImporter//, public IFileImporter +{ +public: + ~XML_FileImporter() override = default; + + void _import(const std::string& filePath, PTN_Engine &ptnEngine) override; + +private: + + //! + //! \brief importActionsThreadOption + //! \return + //! + std::string importActionsThreadOption() const override; + + //! + //! \brief importPlaces + //! \return + //! + std::vector importPlaces() const override; + + //! + //! \brief importTransitions + //! \return + //! + std::vector importTransitions() const override; + + //! + //! \brief importArcs + //! \return + //! + std::vector importArcs() const override; + + //! + //! \brief m_document + //! + pugi::xml_document m_document; +}; +} // namespace ptne diff --git a/PTN_Engine/ImportExport/XML/src/XML/XML_Importer.cpp b/PTN_Engine/ImportExport/XML/src/XML/XML_Importer.cpp deleted file mode 100644 index fbe7081..0000000 --- a/PTN_Engine/ImportExport/XML/src/XML/XML_Importer.cpp +++ /dev/null @@ -1,171 +0,0 @@ -/* - * This file is part of PTN Engine - * - * Copyright (c) 2019 Eduardo Valgôde - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "XML/XML_Importer.h" -#include -#include - -using namespace pugi; -using namespace std; - -namespace -{ -string getAttributeValue(const xml_node &node, const string &attrName) -{ - return node.attribute(attrName.c_str()).value(); -} - -vector collectTransitionAttributes(const xml_node &transition, const string &attribute) -{ - vector activationConditions; - const auto &childAttributes = transition.child(attribute.c_str()); - transform(begin(childAttributes), end(childAttributes), back_inserter(activationConditions), - [](const auto &activationCondition) { return activationCondition.attribute("name").value(); }); - return activationConditions; -} - -pair, vector> collectArcAttributes(const xml_node &transition, const string &attribute) -{ - vector places; - vector weights; - for (xml_node activationCondition : transition.child(attribute.c_str())) - { - places.emplace_back(activationCondition.attribute("name").value()); - - size_t weight = 1; - string weightStr = activationCondition.attribute("weight").value(); - if (!weightStr.empty()) - { - weight = static_cast(std::atol(weightStr.c_str())); - } - - weights.emplace_back(weight); - } - - return pair, vector>{ places, weights }; -} - -bool getRequireNoActionsInExecution(const xml_node &transition) -{ - const string v = transition.child("RequireNoActionsInExecution").attribute("value").value(); - if (v == "true") - { - return true; - } - else if (v == "false") - { - return false; - } - else - { - throw runtime_error("Invalid value for RequireNoActionsInExecution: " + v); - } -} -} // namespace - -namespace ptne -{ -XML_Importer::XML_Importer(const string &filePath) -{ - xml_parse_result result = m_document.load_file(filePath.c_str()); - - if (!result) - { - throw runtime_error(result.description()); - } - - // collectDocumentInformation(petriNet, doc); -} - -// void XML_Importer::collectDocumentInformation(PTN_Engine &petriNet, const xml_document &doc) const -//{ -// const xml_node root_node = doc.child("PTN-Engine"); -// // cout << "version: " << getAttributeValue(root_node, "version") << endl; -// // cout << "format: " << getAttributeValue(root_node, "format") << endl; -// //// PTN verify compatibility -// // cout << "name: " << getAttributeValue(root_node, "name") << endl; -// // PTN - set name? -//} - -XML_Importer::~XML_Importer() -{ -} - -std::string XML_Importer::getActionsThreadOption() const -{ - return m_document.child("PTN-Engine").attribute("actionsThreadOption").as_string(); -} - -vector XML_Importer::getPlaces() const -{ - vector placesInfoCollection; - for (const xml_node &place : m_document.child("PTN-Engine").child("Places")) - { - PlaceInfo placeInfo; - bool isInput = false; - const string isInputStr = getAttributeValue(place, "isInput"); - if (!isInputStr.empty()) - { - isInput = getAttributeValue(place, "isInput") == "true" ? true : false; - } - - size_t numberOfTokens = 0; - const string numberOfTokensStr = getAttributeValue(place, "tokens"); - if (!numberOfTokensStr.empty()) - { - numberOfTokens = static_cast(std::atol(numberOfTokensStr.c_str())); - } - - get<0>(placeInfo) = getAttributeValue(place, "name"); - get<1>(placeInfo) = numberOfTokens; - get<2>(placeInfo) = getAttributeValue(place, "onEnterAction"); - get<3>(placeInfo) = getAttributeValue(place, "onExitAction"); - get<4>(placeInfo) = isInput; - - placesInfoCollection.emplace_back(placeInfo); - } - return placesInfoCollection; -} - -vector XML_Importer::getTransitions() const -{ - vector transitionInfoCollection; - for (xml_node transition : m_document.child("PTN-Engine").child("Transitions")) - { - TransitionInfo transitionInfo; - const vector activationConditions = - collectTransitionAttributes(transition, "ActivationConditions"); - const vector inhibitorPlaces = collectTransitionAttributes(transition, "InhibitorPlaces"); - const auto activationArcs = collectArcAttributes(transition, "ActivationPlaces"); - const auto destinationArcs = collectArcAttributes(transition, "DestinationPlaces"); - - get<0>(transitionInfo) = activationArcs.first; - get<1>(transitionInfo) = activationArcs.second; - get<2>(transitionInfo) = destinationArcs.first; - get<3>(transitionInfo) = destinationArcs.second; - get<4>(transitionInfo) = inhibitorPlaces; - get<5>(transitionInfo) = activationConditions; - get<6>(transitionInfo) = getRequireNoActionsInExecution(transition); - - transitionInfoCollection.emplace_back(transitionInfo); - } - return transitionInfoCollection; -} - - -} // namespace ptne diff --git a/PTN_Engine/ImportExport/XML/src/XML/XML_Importer.h b/PTN_Engine/ImportExport/XML/src/XML/XML_Importer.h deleted file mode 100644 index 93a4999..0000000 --- a/PTN_Engine/ImportExport/XML/src/XML/XML_Importer.h +++ /dev/null @@ -1,68 +0,0 @@ -/* - * This file is part of PTN Engine - * - * Copyright (c) 2019 Eduardo Valgôde - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#pragma once - -#include -#include -#include -#include - -namespace ptne -{ -class PTN_Engine; - -/*! - * \brief The XML_Importer class - */ -class XML_Importer : public IImporter -{ -public: - /*! - * \brief XML_Importer - * \param filePath - */ - explicit XML_Importer(const std::string &filePath); - - ~XML_Importer() override; - - /*! - * \brief getActionsThreadOption - * \return - */ - std::string getActionsThreadOption() const override; - - /*! - * \brief getPlaces - * \return - */ - std::vector getPlaces() const override; - - /*! - * \brief getTransitions - * \return - */ - std::vector getTransitions() const override; - -private: - /*! - * \brief m_document - */ - pugi::xml_document m_document; -}; -} // namespace ptne diff --git a/PTN_Engine/ImportExport/include/PTN_Engine/ImportExport/ImportFactory.h b/PTN_Engine/ImportExport/include/PTN_Engine/ImportExport/ExporterFactory.h old mode 100644 new mode 100755 similarity index 79% rename from PTN_Engine/ImportExport/include/PTN_Engine/ImportExport/ImportFactory.h rename to PTN_Engine/ImportExport/include/PTN_Engine/ImportExport/ExporterFactory.h index 215692c..2335613 --- a/PTN_Engine/ImportExport/include/PTN_Engine/ImportExport/ImportFactory.h +++ b/PTN_Engine/ImportExport/include/PTN_Engine/ImportExport/ExporterFactory.h @@ -1,7 +1,7 @@ /* * This file is part of PTN Engine * - * Copyright (c) 2019 Eduardo Valgôde + * Copyright (c) 2019-2024 Eduardo Valgôde * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -20,17 +20,15 @@ #include "PTN_Engine/Utilities/Explicit.h" #include -#include - namespace ptne { -class IImporter; +class IFileExporter; -class DLL_PUBLIC ImportFactory +class DLL_PUBLIC ExporterFactory { public: - static std::unique_ptr createXMLImporter(const std::string &filePath); + static std::unique_ptr createXMLFileExporter(); }; } // namespace ptne diff --git a/PTN_Engine/ImportExport/include/PTN_Engine/ImportExport/IFileExporter.h b/PTN_Engine/ImportExport/include/PTN_Engine/ImportExport/IFileExporter.h new file mode 100755 index 0000000..8039aab --- /dev/null +++ b/PTN_Engine/ImportExport/include/PTN_Engine/ImportExport/IFileExporter.h @@ -0,0 +1,72 @@ +/* + * This file is part of PTN Engine + * + * Copyright (c) 2019-2024 Eduardo Valgôde + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#pragma once + +#include "PTN_Engine/Utilities/Explicit.h" +#include "PTN_Engine/PTN_Engine.h" +#include + +namespace ptne +{ +class PTN_Engine; + +//! +//! \brief The IExporter class +//! +class DLL_PUBLIC IFileExporter +{ +public: + virtual ~IFileExporter() = default; + + //! + //! \brief _export + //! \param ptnEngine + //! + virtual void _export(const PTN_Engine &ptnEngine, const std::string &filePath) = 0; + +protected: + void _export(const PTN_Engine &ptnEngine); + +private: + //! + //! \brief exportActionsThreadOption + //! \param actionsThreadOption + //! + virtual void exportActionsThreadOption(const std::string &actionsThreadOption) = 0; + + //! + //! \brief exportPlace + //! \param placeProperties + //! + virtual void exportPlace(const PlaceProperties &placeProperties) = 0; + + //! + //!\brief exportTransition + //!\param transitionPropereties + //! + virtual void exportTransition(const TransitionProperties &transitionPropereties) = 0; + + //! + //! \brief exportArc + //! \param arcPropereties + //! + virtual void exportArc(const std::vector &arcPropereties) = 0; +}; + +} // namespace ptne diff --git a/PTN_Engine/ImportExport/include/PTN_Engine/ImportExport/IFileImporter.h b/PTN_Engine/ImportExport/include/PTN_Engine/ImportExport/IFileImporter.h new file mode 100755 index 0000000..7b3723a --- /dev/null +++ b/PTN_Engine/ImportExport/include/PTN_Engine/ImportExport/IFileImporter.h @@ -0,0 +1,73 @@ +/* + * This file is part of PTN Engine + * + * Copyright (c) 2019-2024 Eduardo Valgôde + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#pragma once + +#include "PTN_Engine/Utilities/Explicit.h" +#include "PTN_Engine/PTN_Engine.h" +#include + +namespace ptne +{ +class PTN_Engine; + +//! +//! \brief The IImporter class +//! +class DLL_PUBLIC IFileImporter +{ +public: + virtual ~IFileImporter() = default; + + //! + //! \brief import + //! \param ptnEngine + //! + virtual void _import(const std::string &filePath, PTN_Engine &ptnEngine) = 0; + +protected: + + void _import(PTN_Engine &ptnEngine) const; + +private: + //! + //! \brief importActionsThreadOption + //! \return + //! + virtual std::string importActionsThreadOption() const = 0; + + //! + //! \brief importPlaces + //! \return + //! + virtual std::vector importPlaces() const = 0; + + //! + //! \brief importTransitions + //! \return + //! + virtual std::vector importTransitions() const = 0; + + //! + //! \brief importArcs + //! \return + //! + virtual std::vector importArcs() const = 0; +}; + +} // namespace ptne diff --git a/PTN_Engine/ImportExport/include/PTN_Engine/ImportExport/ExportFactory.h b/PTN_Engine/ImportExport/include/PTN_Engine/ImportExport/ImporterFactory.h old mode 100644 new mode 100755 similarity index 85% rename from PTN_Engine/ImportExport/include/PTN_Engine/ImportExport/ExportFactory.h rename to PTN_Engine/ImportExport/include/PTN_Engine/ImportExport/ImporterFactory.h index 96e9c7c..b0dcda5 --- a/PTN_Engine/ImportExport/include/PTN_Engine/ImportExport/ExportFactory.h +++ b/PTN_Engine/ImportExport/include/PTN_Engine/ImportExport/ImporterFactory.h @@ -20,17 +20,15 @@ #include "PTN_Engine/Utilities/Explicit.h" #include -#include - namespace ptne { -class IExporter; +class IFileImporter; -class DLL_PUBLIC ExportFactory +class DLL_PUBLIC ImporterFactory { public: - static std::unique_ptr createXMLExporter(); + static std::unique_ptr createXMLFileImporter(); }; } // namespace ptne diff --git a/PTN_Engine/JobQueue/JobQueue.cpp b/PTN_Engine/JobQueue/JobQueue.cpp old mode 100644 new mode 100755 index 4fd1f12..dde7cf1 --- a/PTN_Engine/JobQueue/JobQueue.cpp +++ b/PTN_Engine/JobQueue/JobQueue.cpp @@ -1,7 +1,7 @@ /* * This file is part of PTN Engine * - * Copyright (c) 2023 Eduardo Valgôde + * Copyright (c) 2023-2024 Eduardo Valgôde * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -33,7 +33,7 @@ void JobQueue::activate() launch(); } -void JobQueue::inactivate() +void JobQueue::deactivate() { if (!m_isJobQueueActive) { @@ -53,7 +53,7 @@ bool JobQueue::isActive() const void JobQueue::launch() { - lock_guard l(m_jobQueueMutex); + lock_guard l(m_jobQueueMutex); if (!m_isJobQueueRunning && !m_jobQueue.empty() && m_isJobQueueActive) { m_isJobQueueRunning = true; @@ -63,7 +63,7 @@ void JobQueue::launch() void JobQueue::run(stop_token stopToken) { - unique_lock l(m_jobQueueMutex); + unique_lock l(m_jobQueueMutex); while (!m_jobQueue.empty() && !stopToken.stop_requested()) { ActionFunction job = m_jobQueue.back(); @@ -78,7 +78,7 @@ void JobQueue::run(stop_token stopToken) void JobQueue::addJob(const ActionFunction &actionFunction) { { - lock_guard l(m_jobQueueMutex); + lock_guard l(m_jobQueueMutex); m_jobQueue.push_front(actionFunction); } launch(); diff --git a/PTN_Engine/JobQueue/JobQueue.h b/PTN_Engine/JobQueue/JobQueue.h old mode 100644 new mode 100755 index ee301a4..3c64199 --- a/PTN_Engine/JobQueue/JobQueue.h +++ b/PTN_Engine/JobQueue/JobQueue.h @@ -21,15 +21,14 @@ #include "PTN_Engine/PTN_Engine.h" #include #include -#include #include #include namespace ptne { -/*! - * \brief Manages a thread that accepts tasks to be executed in sequence. - */ +//! +//! \brief Manages a thread that accepts tasks to be executed in sequence. +//! class JobQueue { public: @@ -44,29 +43,29 @@ class JobQueue void activate(); //! Deactivate the job queue. - void inactivate(); + void deactivate(); - /*! - * \brief Informs on whether the job queue is running or not. - * \return True if the job queue is active. - */ + //! + //! \brief Informs on whether the job queue is running or not. + //! \return True if the job queue is active. + //! bool isActive() const; - /*! - * \brief Adds a job to the job queue. - * \param Function/job to be executed. - */ + //! + //! \brief Adds a job to the job queue. + //! \param Function/job to be executed. + //! void addJob(const ActionFunction &actionFunction); - /*! - * \brief Run the job queue. Should be executed in its own thread. - */ + //! + //! \brief Run the job queue. Should be executed in its own thread. + //! void run(std::stop_token stopToken); private: - /*! - * \brief Launch the job queue. - */ + //! + //! \brief Launch the job queue. + //! void launch(); //! Whether the job queue is active or not. diff --git a/PTN_Engine/ManagedContainer.h b/PTN_Engine/ManagedContainer.h old mode 100644 new mode 100755 index 9c1658e..bc0d595 --- a/PTN_Engine/ManagedContainer.h +++ b/PTN_Engine/ManagedContainer.h @@ -1,6 +1,6 @@ /* * This file is part of PTN Engine - * Copyright (c) 2023 Eduardo Valgôde + * Copyright (c) 2023-2024 Eduardo Valgôde * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -17,18 +17,17 @@ #pragma once #include "PTN_Engine/PTN_Engine.h" -#include - #include "PTN_Engine/PTN_Engine.h" #include "PTN_Engine/PTN_Exception.h" #include #include +#include namespace ptne { -/*! - * \brief The ManagedContainer class - */ +//! +//! \brief The ManagedContainer class +//! template class ManagedContainer { @@ -40,33 +39,34 @@ class ManagedContainer ManagedContainer &operator=(const ManagedContainer &) = delete; ManagedContainer &operator=(const ManagedContainer &&) = delete; - /*! - * \brief Add item to container. - * \param name - Name of the item used as key. - * \param item - The item itself. - */ + //! + //! \brief Add item to container. + //! \throws InvalidFunctionNameException, RepeatedFunctionException + //! \param name - Name of the item used as key. + //! \param item - The item itself. + //! void addItem(const std::string &name, T item) { - std::unique_lock lock(m_mutex); + std::unique_lock lock(m_mutex); if (name.empty()) { throw InvalidFunctionNameException(name); } - if (m_items.find(name) != m_items.end()) + if (m_items.contains(name)) { - throw RepeatedActionException(name); + throw RepeatedFunctionException(name); } m_items[name] = item; } - /*! - * \brief Retrieve a copy of the item. - * \param name - Identifier of the item. - * \throws InvalidFunctionNameException - * \return Copy of the item identified by name. - */ + //! + //! \brief Retrieve a copy of the item. + //! \param name - Identifier of the item. + //! \throws InvalidFunctionNameException + //! \return Copy of the item identified by name. + //! T getItem(const std::string &name) const { if (name.empty()) @@ -74,36 +74,36 @@ class ManagedContainer throw InvalidFunctionNameException(name); } - std::shared_lock lock(m_mutex); - if (m_items.find(name) == m_items.end()) + std::shared_lock lock(m_mutex); + if (!m_items.contains(name)) { throw InvalidFunctionNameException(name); } return m_items.at(name); } - /*! - * \brief getItems gets copies of the items based on their identifying names. - * Invalid names result in a InvalidFunctionNameException. - * \throws InvalidFunctionNameException - * \param names of the items - * \return vector with the names and copies of the items found in the container. - */ + //! + //! \brief getItems gets copies of the items based on their identifying names. + //! Invalid names result in a InvalidFunctionNameException. + //! \throws InvalidFunctionNameException + //! \param names of the items + //! \return vector with the names and copies of the items found in the container. + //! std::vector> getItems(const std::vector &names) const { - std::shared_lock lock(m_mutex); + std::shared_lock lock(m_mutex); std::vector> items; - for_each(names.cbegin(), names.cend(), + std::ranges::for_each(names.cbegin(), names.cend(), [&](const std::string &name) { if (name.empty()) { - throw InvalidFunctionNameException(name); + throw InvalidFunctionNameException(name); } - if (m_items.find(name) == m_items.end()) + if (!m_items.contains(name)) { - throw InvalidFunctionNameException(name); + throw InvalidFunctionNameException(name); } items.push_back(std::pair(name, m_items.at(name))); }); diff --git a/PTN_Engine/ManagerBase.h b/PTN_Engine/ManagerBase.h new file mode 100755 index 0000000..13ed19d --- /dev/null +++ b/PTN_Engine/ManagerBase.h @@ -0,0 +1,91 @@ +/* + * This file is part of PTN Engine + * + * Copyright (c) 2024 Eduardo Valgôde + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#pragma once + +#include "PTN_Engine/PTN_Exception.h" +#include +#include + +namespace ptne +{ + +template +class ManagerBase +{ +protected: + ManagerBase() = default; + ~ManagerBase() = default; + ManagerBase(const ManagerBase &) = delete; + ManagerBase(ManagerBase &&) = delete; + ManagerBase &operator=(const ManagerBase &) = delete; + ManagerBase &operator=(const ManagerBase &&) = delete; + + //! + //! \brief contains + //! \param name + //! \return + //! + bool contains(const std::string &itemName) const + { + return m_items.contains(itemName); + } + + //! + //! \brief insert + //! \param item + //! + void insert(const std::shared_ptr &item) + { + const auto &itemName = item->getName(); + if (m_items.contains(itemName)) + { + throw RepeatedPlaceException(itemName); + } + m_items[itemName] = item; + } + + //! + //! \brief Removes all places from the container. + //! + void clear() + { + m_items.clear(); + } + + //! + //! \brief getPlace + //! \param itemName + //! \return + //! + std::shared_ptr getItem(const std::string &itemName) const + { + if (!m_items.contains(itemName)) + { + throw PTN_Exception("Cannot get:" + itemName); + } + return m_items.at(itemName); + } + + //! + //! \brief Vector with the items. + //! + std::unordered_map> m_items; +}; + +} // namespace ptne diff --git a/PTN_Engine/PTN_Engine.cpp b/PTN_Engine/PTN_Engine.cpp old mode 100644 new mode 100755 index 48d0789..1de0c6b --- a/PTN_Engine/PTN_Engine.cpp +++ b/PTN_Engine/PTN_Engine.cpp @@ -1,7 +1,7 @@ /* * This file is part of PTN Engine * - * Copyright (c) 2017-2023 Eduardo Valgôde + * Copyright (c) 2017-2024 Eduardo Valgôde * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -23,16 +23,13 @@ namespace ptne { using namespace std; -PTN_Engine::~PTN_Engine() -{ -} +PTN_Engine::~PTN_Engine() = default; PTN_Engine::PTN_Engine(ACTIONS_THREAD_OPTION actionsRuntimeThread) -: m_impProxy(new PTN_EngineImpProxy(actionsRuntimeThread)) +: m_impProxy(make_unique(actionsRuntimeThread)) { } - void PTN_Engine::setEventLoopSleepDuration(const EventLoopSleepDuration sleepDuration) { m_impProxy->setEventLoopSleepDuration(sleepDuration); @@ -40,208 +37,159 @@ void PTN_Engine::setEventLoopSleepDuration(const EventLoopSleepDuration sleepDur PTN_Engine::EventLoopSleepDuration PTN_Engine::getEventLoopSleepDuration() const { - return m_impProxy->getEventLoopSleepDuration(); -} - -void PTN_Engine::createTransition(const vector &activationPlaces, - const vector &activationWeights, - const vector &destinationPlaces, - const vector &destinationWeights, - const vector &inhibitorPlaces, - const vector &additionalConditions, - const bool requireNoActionsInExecution) -{ - m_impProxy->createTransition(activationPlaces, activationWeights, destinationPlaces, destinationWeights, - inhibitorPlaces, additionalConditions, requireNoActionsInExecution); -} - -void PTN_Engine::createTransition(const vector &activationPlaces, - const vector &activationWeights, - const vector &destinationPlaces, - const vector &destinationWeights, - const vector &inhibitorPlaces, - const vector &additionalConditions, - const bool requireNoActionsInExecution) -{ - m_impProxy->createTransition(activationPlaces, activationWeights, destinationPlaces, destinationWeights, - inhibitorPlaces, additionalConditions, requireNoActionsInExecution); -} - -void PTN_Engine::createTransition(const vector &activationPlaces, - const vector &activationWeights, - const vector &destinationPlaces, - const vector &destinationWeights, - const bool requireNoActionsInExecution) -{ - m_impProxy->createTransition(activationPlaces, activationWeights, destinationPlaces, destinationWeights, - vector{}, vector{}, requireNoActionsInExecution); -} - -void PTN_Engine::createTransition(const vector &activationPlaces, - const vector &activationWeights, - const vector &destinationPlaces, - const vector &destinationWeights, - const vector &inhibitorPlaces, - const bool requireNoActionsInExecution) -{ - m_impProxy->createTransition(activationPlaces, activationWeights, destinationPlaces, destinationWeights, - inhibitorPlaces, vector{}, requireNoActionsInExecution); + return m_impProxy->getEventLoopSleepDuration(); } -void PTN_Engine::createTransition(const vector &activationPlaces, - const vector &activationWeights, - const vector &destinationPlaces, - const vector &destinationWeights, - const vector &additionalConditions, - const bool requireNoActionsInExecution) +void PTN_Engine::addArc(const ArcProperties &arcProperties) { - m_impProxy->createTransition(activationPlaces, activationWeights, destinationPlaces, destinationWeights, - vector{}, additionalConditions, requireNoActionsInExecution); + m_impProxy->addArc(arcProperties); } -void PTN_Engine::createTransition(const vector &activationPlaces, - const vector &destinationPlaces, - const bool requireNoActionsInExecution) +void PTN_Engine::removeArc(const ArcProperties &arcProperties) { - m_impProxy->createTransition(activationPlaces, vector{}, destinationPlaces, vector{}, - vector{}, vector{}, requireNoActionsInExecution); + m_impProxy->removeArc(arcProperties); } -void PTN_Engine::createTransition(const vector &activationPlaces, - const vector &destinationPlaces, - const vector &inhibitorPlaces, - const bool requireNoActionsInExecution) +void PTN_Engine::clearNet() { - m_impProxy->createTransition(activationPlaces, vector{}, destinationPlaces, vector{}, - inhibitorPlaces, vector{}, requireNoActionsInExecution); + m_impProxy->clearNet(); } -void PTN_Engine::createTransition(const vector &activationPlaces, - const vector &destinationPlaces, - const vector &additionalConditions, - const bool requireNoActionsInExecution) +vector PTN_Engine::getPlacesProperties() const { - m_impProxy->createTransition(activationPlaces, vector{}, destinationPlaces, vector{}, - vector{}, additionalConditions, requireNoActionsInExecution); + return m_impProxy->getPlacesProperties(); } -void PTN_Engine::createTransition(const vector &activationPlaces, - const vector &destinationPlaces, - const vector &inhibitorPlaces, - const vector &additionalConditions, - const bool requireNoActionsInExecution) +vector PTN_Engine::getTransitionsProperties() const { - m_impProxy->createTransition(activationPlaces, vector{}, destinationPlaces, vector{}, - inhibitorPlaces, additionalConditions, requireNoActionsInExecution); + return m_impProxy->getTransitionsProperties(); } -void PTN_Engine::createTransition(const std::vector &activationPlaces, - const std::vector &destinationPlaces, - const std::vector &inhibitorPlaces, - const std::vector &additionalConditions, - const bool requireNoActionsInExecution) +vector> PTN_Engine::getArcsProperties() const { - m_impProxy->createTransition(activationPlaces, vector{}, destinationPlaces, vector{}, - inhibitorPlaces, additionalConditions, requireNoActionsInExecution); + return m_impProxy->getArcsProperties(); } -void PTN_Engine::createPlace(const string &name, - const size_t initialNumberOfTokens, - ActionFunction onEnterAction, - ActionFunction onExitAction, - const bool input) +void PTN_Engine::createTransition(const TransitionProperties &transitionProperties) { - m_impProxy->createPlace(name, initialNumberOfTokens, onEnterAction, onExitAction, input); + m_impProxy->createTransition(transitionProperties); } -void PTN_Engine::createPlace(const string &name, - const size_t initialNumberOfTokens, - const string &onEnterAction, - const string &onExitAction, - const bool input) +void PTN_Engine::createPlace(const PlaceProperties &placeProperties) { - m_impProxy->createPlaceStr(name, initialNumberOfTokens, onEnterAction, onExitAction, input); + m_impProxy->createPlace(placeProperties); } -void PTN_Engine::createPlace(const string &name, const size_t initialNumberOfTokens, const bool input) +void PTN_Engine::registerAction(const string &name, const ActionFunction &action) const { - m_impProxy->createPlace(name, initialNumberOfTokens, nullptr, nullptr, input); + m_impProxy->registerAction(name, action); } -void PTN_Engine::createPlace(const string &name, - const size_t initialNumberOfTokens, - ActionFunction onEnterAction, - const bool input) +void PTN_Engine::registerCondition(const string &name, const ConditionFunction &condition) const { - m_impProxy->createPlace(name, initialNumberOfTokens, onEnterAction, nullptr, input); -} - -void PTN_Engine::createPlace(const string &name, - const size_t initialNumberOfTokens, - const string &onEnterAction, - const bool input) -{ - m_impProxy->createPlaceStr(name, initialNumberOfTokens, onEnterAction, "", input); -} - -void PTN_Engine::registerAction(const string &name, ActionFunction action) -{ - m_impProxy->registerAction(name, action); -} - -void PTN_Engine::registerCondition(const string &name, ConditionFunction condition) -{ - m_impProxy->registerCondition(name, condition); + m_impProxy->registerCondition(name, condition); } void PTN_Engine::execute(const bool log, ostream &o) { - m_impProxy->execute(log, o); + m_impProxy->execute(log, o); } size_t PTN_Engine::getNumberOfTokens(const string &place) const { - return m_impProxy->getNumberOfTokens(place); + return m_impProxy->getNumberOfTokens(place); } void PTN_Engine::incrementInputPlace(const string &place) { - m_impProxy->incrementInputPlace(place); + m_impProxy->incrementInputPlace(place); } void PTN_Engine::printState(ostream &o) const { - m_impProxy->printState(o); -} - -void PTN_Engine::export_(IExporter &exporter) const -{ - m_impProxy->export_(exporter); -} - -void PTN_Engine::import(const IImporter &importer) -{ - m_impProxy->import(importer); + m_impProxy->printState(o); } void PTN_Engine::setActionsThreadOption(const ACTIONS_THREAD_OPTION actionsThreadOption) { - m_impProxy->setActionsThreadOption(actionsThreadOption); + m_impProxy->setActionsThreadOption(actionsThreadOption); } PTN_Engine::ACTIONS_THREAD_OPTION PTN_Engine::getActionsThreadOption() const { - return m_impProxy->getActionsThreadOption(); + return m_impProxy->getActionsThreadOption(); } bool PTN_Engine::isEventLoopRunning() const { - return m_impProxy->isEventLoopRunning(); + return m_impProxy->isEventLoopRunning(); } void PTN_Engine::stop() { - m_impProxy->stop(); + m_impProxy->stop(); +} + +namespace +{ + const string ACTIONS_THREAD_OPTION_SINGLE_THREAD{ "SINGLE_THREAD" }; + const string ACTIONS_THREAD_OPTION_EVENT_LOOP{ "EVENT_LOOP" }; + const string ACTIONS_THREAD_OPTION_DETACHED{ "DETACHED" }; + const string ACTIONS_THREAD_OPTION_JOB_QUEUE{ "JOB_QUEUE" }; +} + +PTN_Engine::ACTIONS_THREAD_OPTION +PTN_Engine::toACTIONS_THREAD_OPTION(const string &actionsThreadOptionStr) +{ + using enum ACTIONS_THREAD_OPTION; + if (actionsThreadOptionStr == ACTIONS_THREAD_OPTION_SINGLE_THREAD) + { + return SINGLE_THREAD; + } + else if (actionsThreadOptionStr == ACTIONS_THREAD_OPTION_EVENT_LOOP) + { + return EVENT_LOOP; + } + else if (actionsThreadOptionStr == ACTIONS_THREAD_OPTION_DETACHED) + { + return DETACHED; + } + else if (actionsThreadOptionStr == ACTIONS_THREAD_OPTION_JOB_QUEUE) + { + return JOB_QUEUE; + } + else + { + throw PTN_Exception("Could not convert " + actionsThreadOptionStr + " to ACTIONS_THREAD_OPTION"); + } +} + +string PTN_Engine::toString(ACTIONS_THREAD_OPTION actionsThreadOption) +{ + using enum ACTIONS_THREAD_OPTION; + switch (actionsThreadOption) + { + default: + { + throw PTN_Exception("Could not convert to string"); + } + case DETACHED: + { + return ACTIONS_THREAD_OPTION_DETACHED; + } + case SINGLE_THREAD: + { + return ACTIONS_THREAD_OPTION_SINGLE_THREAD; + } + case EVENT_LOOP: + { + return ACTIONS_THREAD_OPTION_EVENT_LOOP; + } + case JOB_QUEUE: + { + return ACTIONS_THREAD_OPTION_JOB_QUEUE; + } + } } } // namespace ptne diff --git a/PTN_Engine/PTN_EngineImp.cpp b/PTN_Engine/PTN_EngineImp.cpp old mode 100644 new mode 100755 index f80fa12..08faf2c --- a/PTN_Engine/PTN_EngineImp.cpp +++ b/PTN_Engine/PTN_EngineImp.cpp @@ -3,7 +3,7 @@ * * Copyright (c) 2017 Eduardo Valgôde * Copyright (c) 2021 Kale Evans - * Copyright (c) 2023 Eduardo Valgôde + * Copyright (c) 2024 Eduardo Valgôde * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -19,9 +19,9 @@ */ #include "PTN_Engine/PTN_EngineImp.h" -#include "PTN_Engine/IExporter.h" -#include "PTN_Engine/IImporter.h" #include "PTN_Engine/JobQueue/JobQueue.h" +#include "PTN_Engine/Utilities/LockWeakPtr.h" +#include namespace ptne { @@ -58,63 +58,43 @@ void PTN_EngineImp::clearNet() m_places.clear(); } -void PTN_EngineImp::createPlace(const string &name, - const size_t initialNumberOfTokens, - ActionFunction onEnterAction, - ActionFunction onExitAction, - const bool input) +void PTN_EngineImp::createTransition(const TransitionProperties &transitionProperties) { - auto place = make_shared(*this, name, initialNumberOfTokens, onEnterAction, onExitAction, input); - m_places.insert(place); + createTransition(transitionProperties.name, + transitionProperties.activationArcs, + transitionProperties.destinationArcs, + transitionProperties.inhibitorArcs, + !transitionProperties.additionalConditionsNames.empty() ? + m_conditions.getItems(transitionProperties.additionalConditionsNames) : + createAnonymousConditions(transitionProperties.additionalConditions), + transitionProperties.requireNoActionsInExecution); } -void PTN_EngineImp::createPlaceStr(const string &name, - const size_t initialNumberOfTokens, - const string &onEnterActionName, - const string &onExitActionName, - const bool input) +void PTN_EngineImp::createPlace(const PlaceProperties &placeProperties) { - ActionFunction onEnterAction; - if (!onEnterActionName.empty()) + ActionFunction onEnterAction = placeProperties.onEnterAction; + if (!placeProperties.onEnterActionFunctionName.empty()) { - onEnterAction = m_actions.getItem(onEnterActionName); + onEnterAction = m_actions.getItem(placeProperties.onEnterActionFunctionName); } - ActionFunction onExitAction; - if (!onExitActionName.empty()) + ActionFunction onExitAction = placeProperties.onExitAction; + if (!placeProperties.onExitActionFunctionName.empty()) { - onExitAction = m_actions.getItem(onExitActionName); + onExitAction = m_actions.getItem(placeProperties.onExitActionFunctionName); } - auto place = make_shared(*this, name, initialNumberOfTokens, onEnterActionName, onEnterAction, - onExitActionName, onExitAction, input); + auto place = make_shared(*this, + placeProperties.name, + placeProperties.initialNumberOfTokens, + placeProperties.onEnterActionFunctionName, + onEnterAction, + placeProperties.onExitActionFunctionName, + onExitAction, + placeProperties.input); m_places.insert(place); } -void PTN_EngineImp::createTransition(const vector &activationPlaces, - const vector &activationWeights, - const vector &destinationPlaces, - const vector &destinationWeights, - const vector &inhibitorPlaces, - const vector &additionalConditions, - const bool requireNoActionsInExecution) -{ - createTransition(activationPlaces, activationWeights, destinationPlaces, destinationWeights, inhibitorPlaces, - m_conditions.getItems(additionalConditions), requireNoActionsInExecution); -} - -void PTN_EngineImp::createTransition(const vector &activationPlaces, - const vector &activationWeights, - const vector &destinationPlaces, - const vector &destinationWeights, - const vector &inhibitorPlaces, - const vector &additionalConditions, - const bool requireNoActionsInExecution) -{ - createTransition(activationPlaces, activationWeights, destinationPlaces, destinationWeights, inhibitorPlaces, - createAnonymousConditions(additionalConditions), requireNoActionsInExecution); -} - bool PTN_EngineImp::isEventLoopRunning() const { return m_eventLoop.isRunning(); @@ -125,12 +105,12 @@ void PTN_EngineImp::stop() noexcept m_eventLoop.stop(); } -void PTN_EngineImp::registerAction(const string &name, ActionFunction action) +void PTN_EngineImp::registerAction(const string &name, const ActionFunction &action) { m_actions.addItem(name, action); } -void PTN_EngineImp::registerCondition(const string &name, ConditionFunction condition) +void PTN_EngineImp::registerCondition(const string &name, const ConditionFunction &condition) { m_conditions.addItem(name, condition); } @@ -147,61 +127,6 @@ void PTN_EngineImp::incrementInputPlace(const string &place) m_eventLoop.notifyNewEvent(); } -void PTN_EngineImp::export_(IExporter &exporter) const -{ - if (isEventLoopRunning()) - { - throw PTN_Exception("Cannot change actions thread option while the event loop is running."); - } - - string actionsThreadOptionStr; - if (!ACTIONS_THREAD_OPTION_toString(m_actionsThreadOption, actionsThreadOptionStr)) - { - throw PTN_Exception("Invalid ACTIONS_THREAD_OPTION"); - } - exporter.exportActionsThreadOption(actionsThreadOptionStr); - - m_places.export_(exporter); - m_transitions.export_(exporter); -} - -void PTN_EngineImp::import(const IImporter &importer) -{ - if (isEventLoopRunning()) - { - throw PTN_Exception("Cannot import while the event loop is running."); - } - - // TODO: Not exception safe, maybe this should go to a constructor instead. - clearNet(); - - PTN_Engine::ACTIONS_THREAD_OPTION actionThreadOption = m_actionsThreadOption; - string actionsThreadOptionStr = importer.getActionsThreadOption(); - if (ACTIONS_THREAD_OPTION_fromString(actionsThreadOptionStr, actionThreadOption)) - { - setActionsThreadOption(actionThreadOption); - } - else - { - throw PTN_Exception("Invalid input ACTIONS_THREAD_OPTION string"); - } - - // create places - for (const IImporter::PlaceInfo &placeInfo : importer.getPlaces()) - { - createPlaceStr(get<0>(placeInfo), get<1>(placeInfo), get<2>(placeInfo), get<3>(placeInfo), - get<4>(placeInfo)); - } - - // create transitions - for (const IImporter::TransitionInfo &transitionInfo : importer.getTransitions()) - { - createTransition(get<0>(transitionInfo), get<1>(transitionInfo), get<2>(transitionInfo), - get<3>(transitionInfo), get<4>(transitionInfo), get<5>(transitionInfo), - get<6>(transitionInfo)); - } -} - void PTN_EngineImp::setActionsThreadOption(const PTN_Engine::ACTIONS_THREAD_OPTION actionsThreadOption) { if (isEventLoopRunning()) @@ -209,7 +134,7 @@ void PTN_EngineImp::setActionsThreadOption(const PTN_Engine::ACTIONS_THREAD_OPTI throw PTN_Exception("Cannot change actions thread option while the event loop is running."); } - unique_lock actionsThreadOptionGuard(m_actionsThreadOptionMutex); + unique_lock actionsThreadOptionGuard(m_actionsThreadOptionMutex); if (m_actionsThreadOption == actionsThreadOption) { @@ -228,11 +153,11 @@ void PTN_EngineImp::setActionsThreadOption(const PTN_Engine::ACTIONS_THREAD_OPTI PTN_Engine::ACTIONS_THREAD_OPTION PTN_EngineImp::getActionsThreadOption() const { - shared_lock actionsThreadOptionGuard(m_actionsThreadOptionMutex); + shared_lock actionsThreadOptionGuard(m_actionsThreadOptionMutex); return m_actionsThreadOption; } -void PTN_EngineImp::printState(std::ostream &o) const +void PTN_EngineImp::printState(ostream &o) const { m_places.printState(o); } @@ -251,10 +176,10 @@ bool PTN_EngineImp::executeInt(const bool log, ostream &o) { printState(o); } - vector> _enabledTransitions = enabledTransitions(); - for (auto &transition : _enabledTransitions) + + for (const auto &transition : enabledTransitions()) { - if (auto enabledTransition = transition.lock()) + if (auto enabledTransition = lockWeakPtr(transition)) { firedAtLeastOneTransition |= enabledTransition->execute(); } @@ -287,30 +212,105 @@ PTN_Engine::EventLoopSleepDuration PTN_EngineImp::getEventLoopSleepDuration() co return m_eventLoop.getSleepDuration(); } +void PTN_EngineImp::addArc(const ArcProperties &arcProperties) +{ + if (isEventLoopRunning()) + { + throw PTN_Exception("Cannot add arc while the event loop is running."); + } + + if (!m_places.contains(arcProperties.placeName)) + { + throw PTN_Exception("The place" + arcProperties.placeName + " must already exist in order to link to an arc."); + } + auto spPlace = m_places.getPlace(arcProperties.placeName); + + if (!m_transitions.contains(arcProperties.transitionName)) + { + throw PTN_Exception("The transition " + arcProperties.transitionName +" must already exist in order to link to an arc."); + } + + auto spTransition = m_transitions.getTransition(arcProperties.transitionName); + spTransition->addPlace(spPlace, arcProperties.type, arcProperties.weight); +} + +void PTN_EngineImp::removeArc(const ArcProperties &arcProperties) const +{ + if (isEventLoopRunning()) + { + throw PTN_Exception("Cannot remove arc while the event loop is running."); + } + + if (!m_places.contains(arcProperties.placeName)) + { + throw PTN_Exception("The place" + arcProperties.placeName + " must already exist in order to unlink an arc."); + } + auto spPlace = m_places.getPlace(arcProperties.placeName); + + if (m_transitions.contains(arcProperties.transitionName)) + { + throw PTN_Exception("The transition " + arcProperties.transitionName +" must already exist in order to unlink an arc."); + } + + auto spTransition = m_transitions.getTransition(arcProperties.transitionName); + spTransition->removePlace(spPlace, arcProperties.type); +} + +vector PTN_EngineImp::getPlacesProperties() const +{ + return m_places.getPlacesProperties(); +} + +vector PTN_EngineImp::getTransitionsProperties() const +{ + return m_transitions.getTransitionsProperties(); +} + +vector> PTN_EngineImp::getArcsProperties() const +{ + return m_transitions.getArcsProperties(); +} + // Private -void PTN_EngineImp::createTransition(const vector &activationPlaces, - const vector &activationWeights, - const vector &destinationPlaces, - const vector &destinationWeights, - const vector &inhibitorPlaces, +void PTN_EngineImp::createTransition(const string &name, + const vector &activationArcs, + const vector &destinationArcs, + const vector &inhibitorArcs, const vector> &additionalConditions, const bool requireNoActionsInExecution) { - vector activationPlacesVector = m_places.getPlacesFromNames(activationPlaces); - vector destinationPlacesVector = m_places.getPlacesFromNames(destinationPlaces); - vector inhibitorPlacesVector = m_places.getPlacesFromNames(inhibitorPlaces); + // if a transition with this name already exists in the net, throw an exception + if (m_transitions.hasTransition(name)) + { + throw PTN_Exception("Cannot create transition that already exists. Name: " + name); + } + + auto getArcsFromArcsProperties = [this](const vector &arcProperties) + { + vector arcs; + for (const auto &arcProperty : arcProperties) + { + arcs.emplace_back(m_places.getPlace(arcProperty.placeName), arcProperty.weight); + } + return arcs; + }; m_transitions.insert( - make_shared(activationPlacesVector, activationWeights, destinationPlacesVector, destinationWeights, - inhibitorPlacesVector, additionalConditions, requireNoActionsInExecution)); + make_shared(name, + getArcsFromArcsProperties(activationArcs), + getArcsFromArcsProperties(destinationArcs), + getArcsFromArcsProperties(inhibitorArcs), + additionalConditions, + requireNoActionsInExecution)); + } -const vector> +vector> PTN_EngineImp::createAnonymousConditions(const vector &conditions) const { vector> anonymousConditionsVector; - transform(conditions.cbegin(), conditions.cend(), back_inserter(anonymousConditionsVector), + ranges::transform(conditions.cbegin(), conditions.cend(), back_inserter(anonymousConditionsVector), [](const auto &condition) { return pair("", condition); }); return anonymousConditionsVector; } @@ -326,47 +326,4 @@ void PTN_EngineImp::addJob(const ActionFunction &actionFunction) m_jobQueue->addJob(actionFunction); } -bool PTN_EngineImp::ACTIONS_THREAD_OPTION_fromString(const string &actionsThreadOptionStr, - PTN_Engine::ACTIONS_THREAD_OPTION &out) -{ - if (actionsThreadOptionStr == "DETACHED") - { - out = PTN_Engine::ACTIONS_THREAD_OPTION::DETACHED; - } - else if (actionsThreadOptionStr == "EVENT_LOOP") - { - out = PTN_Engine::ACTIONS_THREAD_OPTION::EVENT_LOOP; - } - else if (actionsThreadOptionStr == "JOB_QUEUE") - { - out = PTN_Engine::ACTIONS_THREAD_OPTION::JOB_QUEUE; - } - else - { - return false; - } - return true; -} - -bool PTN_EngineImp::ACTIONS_THREAD_OPTION_toString(const PTN_Engine::ACTIONS_THREAD_OPTION actionsThreadOption, - string &out) -{ - switch (actionsThreadOption) - { - case PTN_Engine::ACTIONS_THREAD_OPTION::DETACHED: - out = "DETACHED"; - break; - case PTN_Engine::ACTIONS_THREAD_OPTION::EVENT_LOOP: - out = "EVENT_LOOP"; - break; - case PTN_Engine::ACTIONS_THREAD_OPTION::JOB_QUEUE: - out = "JOB_QUEUE"; - break; - default: - return false; - break; - } - return true; -} - } // namespace ptne diff --git a/PTN_Engine/PTN_EngineImp.h b/PTN_Engine/PTN_EngineImp.h old mode 100644 new mode 100755 index 3574c4d..26efd95 --- a/PTN_Engine/PTN_EngineImp.h +++ b/PTN_Engine/PTN_EngineImp.h @@ -3,7 +3,7 @@ * * Copyright (c) 2017 Eduardo Valgôde * Copyright (c) 2021 Kale Evans - * Copyright (c) 2023 Eduardo Valgôde + * Copyright (c) 2024 Eduardo Valgôde * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -26,18 +26,15 @@ #include "PTN_Engine/ManagedContainer.h" #include "PTN_Engine/PTN_Engine.h" #include "PTN_Engine/Place.h" -#include "PTN_Engine/PlacesManagedContainer.h" -#include "PTN_Engine/TransitionsManagedContainer.h" +#include "PTN_Engine/PlacesManager.h" +#include "PTN_Engine/TransitionsManager.h" #include #include -#include namespace ptne { class IConditionFunctor; class IActionFunctor; -class IExporter; -class IImporter; class JobQueue; class Place; class Transition; @@ -47,15 +44,14 @@ using WeakPtrPlace = std::weak_ptr; //! Implements the Petri net logic. -/*! - * Implements the Petri net logic. - * Used by the PTN_Engine class. - * \sa PTN_Engine - */ +//! +//! Implements the Petri net logic. +//! Used by the PTN_Engine class. +//! \sa PTN_Engine +//! class PTN_EngineImp final : public IPTN_EngineEL, public IPTN_EnginePlace { public: - //! Constructor. explicit PTN_EngineImp(PTN_Engine::ACTIONS_THREAD_OPTION actionsThreadOption); ~PTN_EngineImp(); @@ -64,249 +60,193 @@ class PTN_EngineImp final : public IPTN_EngineEL, public IPTN_EnginePlace PTN_EngineImp &operator=(const PTN_EngineImp &) = delete; PTN_EngineImp &operator=(PTN_EngineImp &&) = delete; - /*! - * Clear the token counter from all input places. - */ + //! + //! Clear the token counter from all input places. + //! void clearInputPlaces(); - /*! - * \brief clearNet - */ + //! + //! \brief clearNet + //! void clearNet(); - /*! - * Create a new place in the net. - * \param name The name of the place. - * \param initialNumberOfTokens The number of tokens to be initialized with. - * \param onEnterAction The function to be called once a token enters the place. - * \param onExitAction The function to be called once a token leaves the place. - * \param input A flag determining if this place can have tokens added manually. - */ - void createPlace(const std::string &name, - const size_t initialNumberOfTokens, - ActionFunction onEnterAction, - ActionFunction onExitAction, - const bool input = false); - - /*! - * Create a new place in the net. - * \param name The name of the place. - * \param initialNumberOfTokens The number of tokens to be initialized with. - * \param onEnterActionName Name of the function to be called once a token enters the place. - * \param onExitActionName Name of the function to be called once a token leaves the place. - * \param input A flag determining if this place can have tokens added manually. - */ - void createPlaceStr(const std::string &name, - const size_t initialNumberOfTokens, - const std::string &onEnterActionName, - const std::string &onExitActionName, - const bool input = false); - - /*! - * Create a new transition - * \param activationPlaces A vector with the names of the activation places. - * \param activationWeights A vector with the weights of each activation place. - * \param destinationPlaces A vector with the names of the destination places. - * \param destinationWeights A vector with the weights of each destination place. - * \param inhibitorPlaces Places that cannot have tokens to fire the transition. - * \param additionalConditions A vector with additionalConditions. - */ - void createTransition(const std::vector &activationPlaces, - const std::vector &activationWeights, - const std::vector &destinationPlaces, - const std::vector &destinationWeights, - const std::vector &inhibitorPlaces, - const std::vector &additionalConditions, - const bool requireNoActionsInExecution); - - /*! - * Create a new transition - * \param activationPlaces A vector with the names of the activation places. - * \param activationWeights A vector with the weights of each activation place. - * \param destinationPlaces A vector with the names of the destination places. - * \param destinationWeights A vector with the weights of each destination place. - * \param inhibitorPlaces Places that cannot have tokens to fire the transition. - * \param additionalConditions A vector with a pairs of a name and a function that returns bool. - */ - void createTransition(const std::vector &activationPlaces, - const std::vector &activationWeights, - const std::vector &destinationPlaces, - const std::vector &destinationWeights, - const std::vector &inhibitorPlaces, - const std::vector &additionalConditions, - const bool requireNoActionsInExecution); - - /*! - * \brief Imports the Petri net using the provided importer. - * \param importer Object containing all necessary information to create a new Petri net. - */ + //! + //! \brief createTransition + //! \param transitionProperties + //! + void createTransition(const TransitionProperties &transitionProperties); + + //! + //! \brief createPlace + //! \param placeProperties + //! + void createPlace(const PlaceProperties &placeProperties); + + //! + //! \brief isEventLoopRunning + //! \return + //! bool isEventLoopRunning() const; - /*! - * \brief Stop the execution loop. - */ + //! + //! \brief Stop the execution loop. + //! void stop() noexcept; - /*! - * Register an action to be called by the Petri net. - * \param name The name of the place. - * \param action The function to be called once a token enters the place. - */ - void registerAction(const std::string &name, ActionFunction action); - - /*! - * Register a condition - * \param name The name of the condition - * \param conditions A function pointer to a condition. - */ - void registerCondition(const std::string &name, ConditionFunction condition); - - /*! - * Return the number of tokens in a given place. - * \param place The name of the place to get the number of tokens from. - * \return The number of tokens present in the place. - */ + //! + //! Register an action to be called by the Petri net. + //! \param name The name of the place. + //! \param action The function to be called once a token enters the place. + //! + void registerAction(const std::string &name, const ActionFunction &action); + + //! + //! Register a condition + //! \param name The name of the condition + //! \param conditions A function pointer to a condition. + //! + void registerCondition(const std::string &name, const ConditionFunction &condition); + + //! + //! Return the number of tokens in a given place. + //! \param place The name of the place to get the number of tokens from. + //! \return The number of tokens present in the place. + //! size_t getNumberOfTokens(const std::string &place) const; - /*! - * Add a token in an input place. - * \param place Name of the place to be incremented. - */ + //! + //! Add a token in an input place. + //! \param place Name of the place to be incremented. + //! void incrementInputPlace(const std::string &place); - /*! - * \brief export_ - * \param exporter - */ - void export_(IExporter &exporter) const; - - /*! - * \brief import - * \param importer - */ - void import(const IImporter &importer); - //! Specify the thread where the actions should be run. void setActionsThreadOption(const PTN_Engine::ACTIONS_THREAD_OPTION actionsThreadOption); - /*! - * \brief getActionsThreadOption - * \return - */ + //! + //! \brief getActionsThreadOption + //! \return + //! PTN_Engine::ACTIONS_THREAD_OPTION getActionsThreadOption() const override; - /*! - * Start the petri net event loop. - * \param log Flag logging the state of the net on or off. - * \param o Log output stream. - */ + //! + //! Start the petri net event loop. + //! \param log Flag logging the state of the net on or off. + //! \param o Log output stream. + //! void execute(const bool log = false, std::ostream &o = std::cout); - /*! - * \brief executeInt - * \param log - * \param o - * \return - */ + //! + //! \brief executeInt + //! \param log + //! \param o + //! \return + //! bool executeInt(const bool log = false, std::ostream &o = std::cout) override; - /*! - * \brief Add job to job queue. - * \param Function to be executed in the job queue. - */ + //! + //! \brief Add job to job queue. + //! \param Function to be executed in the job queue. + //! void addJob(const ActionFunction &actionFunction) override; - /*! - * \brief Indicates if there are new tokens in any input places. - * \return True of there is a new token in an input place. - */ + //! + //! \brief Indicates if there are new tokens in any input places. + //! \return True of there is a new token in an input place. + //! bool getNewInputReceived() const override; - /*! - * \brief Flags or clears flag of new tokens in input places. - * \param newInputReceived - The new value for the new input received flag. - */ + //! + //! \brief Flags or clears flag of new tokens in input places. + //! \param newInputReceived - The new value for the new input received flag. + //! void setNewInputReceived(const bool newInputReceived); - /*! - * \brief Gets the transitions that are currently enabled. - * \return Weak pointers to the transitions that are enabled. - */ + //! + //! \brief Gets the transitions that are currently enabled. + //! \return Weak pointers to the transitions that are enabled. + //! std::vector> enabledTransitions() const; - /*! - * Print the petri net places and number of tokens. - * \param o Output stream. - */ + //! + //! Print the petri net places and number of tokens. + //! \param o Output stream. + //! void printState(std::ostream &o) const; - /*! - * \brief Set the sleep duration of the event loop. - * \param sleepDuration - Time the event loop takes until it checks for new inputs. - */ + //! + //! \brief Set the sleep duration of the event loop. + //! \param sleepDuration - Time the event loop takes until it checks for new inputs. + //! void setEventLoopSleepDuration(const PTN_Engine::EventLoopSleepDuration sleepDuration); - /*! - * \brief Gets the current sleep time set in the event loop. - * \return The sleep time of the event loop. - */ + //! + //! \brief Gets the current sleep time set in the event loop. + //! \return The sleep time of the event loop. + //! PTN_Engine::EventLoopSleepDuration getEventLoopSleepDuration() const; + //! + //! \brief addArc + //! \param arcProperties + //! + void addArc(const ArcProperties &arcProperties); + + //! + //! \brief addArc + //! \param arcProperties + //! + void removeArc(const ArcProperties &arcProperties) const; + + //! + //! \brief getPlacesProperties + //! \return + //! + std::vector getPlacesProperties() const; + + //! + //! \brief getTransitionsProperties + //! \return + //! + std::vector getTransitionsProperties() const; + + //! + //! \brief getArcsProperties + //! \return + //! + std::vector> getArcsProperties() const; + private: - /*! - * Create a new transition - * \param activationPlaces A vector with the names of the activation places. - * \param activationWeights A vector with the weights of each activation place. - * \param destinationPlaces A vector with the names of the destination places. - * \param destinationWeights A vector with the weights of each destination place. - * \param inhibitorPlaces Places that cannot have tokens to fire the transition. - * \param additionalConditions A vector with names to additional conditions. - */ - void createTransition(const std::vector &activationPlaces, - const std::vector &activationWeights, - const std::vector &destinationPlaces, - const std::vector &destinationWeights, - const std::vector &inhibitorPlaces, + //! + //! Create a new transition + //! \param name Name and identifier of the transition + //! \param activationPlaces A vector with the names of the activation places. + //! \param activationWeights A vector with the weights of each activation place. + //! \param destinationPlaces A vector with the names of the destination places. + //! \param destinationWeights A vector with the weights of each destination place. + //! \param inhibitorPlaces Places that cannot have tokens to fire the transition. + //! \param additionalConditions A vector with names to additional conditions. + //! + void createTransition(const std::string &name, + const std::vector &activationArcs, + const std::vector &destinationArcs, + const std::vector &inhibitorArcs, const std::vector> &additionalConditions, const bool requireNoActionsInExecution); - /*! - * \brief exportPlaces - * \param exporter - */ - void exportPlaces(IExporter &exporter) const; - - /*! - * \brief createAnonymousConditions - * \param conditions - * \return - */ - const std::vector> + //! + //! \brief createAnonymousConditions + //! \param conditions + //! \return + //! + std::vector> createAnonymousConditions(const std::vector &conditions) const; - /*! - * \brief ACTIONS_THREAD_OPTION_fromString - * \param actionsThreadOptionStr - * \param out - Output value - * \return true if successful. - */ - static bool ACTIONS_THREAD_OPTION_fromString(const std::string &actionsThreadOptionStr, - PTN_Engine::ACTIONS_THREAD_OPTION &out); - - /*! - * \brief ACTIONS_THREAD_OPTION_toString - * \param actionsThreadOption - * \param out - Output value - * \return true if successful - */ - static bool - ACTIONS_THREAD_OPTION_toString(const PTN_Engine::ACTIONS_THREAD_OPTION actionsThreadOption, std::string &out); - //! Container with all the transitions in the Petri net. - TransitionsManagedContainer m_transitions; + TransitionsManager m_transitions; //! Container with all the places in the Petri net. - PlacesManagedContainer m_places; + PlacesManager m_places; //! Container with all the actions available to this Petri net. ManagedContainer m_actions; diff --git a/PTN_Engine/PTN_EngineImpProxy.cpp b/PTN_Engine/PTN_EngineImpProxy.cpp old mode 100644 new mode 100755 index 673a3cf..c5c1701 --- a/PTN_Engine/PTN_EngineImpProxy.cpp +++ b/PTN_Engine/PTN_EngineImpProxy.cpp @@ -3,7 +3,7 @@ * * Copyright (c) 2017 Eduardo Valgôde * Copyright (c) 2021 Kale Evans - * Copyright (c) 2023 Eduardo Valgôde + * Copyright (c) 2023-2024 Eduardo Valgôde * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -37,131 +37,121 @@ PTN_Engine::PTN_EngineImpProxy::~PTN_EngineImpProxy() void PTN_Engine::PTN_EngineImpProxy::setEventLoopSleepDuration(const EventLoopSleepDuration sleepDuration) { - unique_lock guard(m_mutex); + unique_lock guard(m_mutex); m_ptnEngineImp.setEventLoopSleepDuration(sleepDuration); } PTN_Engine::EventLoopSleepDuration PTN_Engine::PTN_EngineImpProxy::getEventLoopSleepDuration() const { - shared_lock guard(m_mutex); + shared_lock guard(m_mutex); return m_ptnEngineImp.getEventLoopSleepDuration(); } -void PTN_Engine::PTN_EngineImpProxy::createTransition(const vector &activationPlaces, - const vector &activationWeights, - const vector &destinationPlaces, - const vector &destinationWeights, - const vector &inhibitorPlaces, - const vector &additionalConditions, - const bool requireNoActionsInExecution) +void PTN_Engine::PTN_EngineImpProxy::addArc(const ArcProperties &arcProperties) { - unique_lock guard(m_mutex); - m_ptnEngineImp.createTransition(activationPlaces, activationWeights, destinationPlaces, destinationWeights, - inhibitorPlaces, additionalConditions, requireNoActionsInExecution); + unique_lock guard(m_mutex); + m_ptnEngineImp.addArc(arcProperties); } -void PTN_Engine::PTN_EngineImpProxy::createTransition(const vector &activationPlaces, - const vector &activationWeights, - const vector &destinationPlaces, - const vector &destinationWeights, - const vector &inhibitorPlaces, - const vector &additionalConditions, - const bool requireNoActionsInExecution) +void PTN_Engine::PTN_EngineImpProxy::removeArc(const ArcProperties &arcProperties) { - unique_lock guard(m_mutex); - m_ptnEngineImp.createTransition(activationPlaces, activationWeights, destinationPlaces, destinationWeights, - inhibitorPlaces, additionalConditions, requireNoActionsInExecution); + unique_lock guard(m_mutex); + m_ptnEngineImp.removeArc(arcProperties); } -void PTN_Engine::PTN_EngineImpProxy::createPlace(const string &name, - const size_t initialNumberOfTokens, - ActionFunction onEnterAction, - ActionFunction onExitAction, - const bool input) +void PTN_Engine::PTN_EngineImpProxy::clearNet() { - unique_lock guard(m_mutex); - m_ptnEngineImp.createPlace(name, initialNumberOfTokens, onEnterAction, onExitAction, input); + unique_lock guard(m_mutex); + m_ptnEngineImp.clearNet(); } -void PTN_Engine::PTN_EngineImpProxy::createPlaceStr(const string &name, - const size_t initialNumberOfTokens, - const string &onEnterAction, - const string &onExitAction, - const bool input) +vector PTN_Engine::PTN_EngineImpProxy::getPlacesProperties() const { - unique_lock guard(m_mutex); - m_ptnEngineImp.createPlaceStr(name, initialNumberOfTokens, onEnterAction, onExitAction, input); + shared_lock guard(m_mutex); + return m_ptnEngineImp.getPlacesProperties(); } -void PTN_Engine::PTN_EngineImpProxy::registerAction(const string &name, ActionFunction action) +vector PTN_Engine::PTN_EngineImpProxy::getTransitionsProperties() const { - unique_lock guard(m_mutex); + shared_lock guard(m_mutex); + return m_ptnEngineImp.getTransitionsProperties(); +} + +vector> PTN_Engine::PTN_EngineImpProxy::getArcsProperties() const +{ + shared_lock guard(m_mutex); + return m_ptnEngineImp.getArcsProperties(); +} + +void PTN_Engine::PTN_EngineImpProxy::createTransition(const TransitionProperties &transitionProperties) +{ + unique_lock guard(m_mutex); + m_ptnEngineImp.createTransition(transitionProperties); +} + +void PTN_Engine::PTN_EngineImpProxy::createPlace(const PlaceProperties &placeProperties) +{ + unique_lock guard(m_mutex); + m_ptnEngineImp.createPlace(placeProperties); +} + +void PTN_Engine::PTN_EngineImpProxy::registerAction(const string &name, const ActionFunction &action) +{ + unique_lock guard(m_mutex); m_ptnEngineImp.registerAction(name, action); } -void PTN_Engine::PTN_EngineImpProxy::registerCondition(const string &name, ConditionFunction condition) +void PTN_Engine::PTN_EngineImpProxy::registerCondition(const string &name, const ConditionFunction &condition) { - unique_lock guard(m_mutex); + unique_lock guard(m_mutex); m_ptnEngineImp.registerCondition(name, condition); } void PTN_Engine::PTN_EngineImpProxy::execute(const bool log, ostream &o) { - unique_lock guard(m_mutex); + unique_lock guard(m_mutex); m_ptnEngineImp.execute(log, o); } void PTN_Engine::PTN_EngineImpProxy::stop() { - unique_lock guard(m_mutex); + unique_lock guard(m_mutex); m_ptnEngineImp.stop(); } size_t PTN_Engine::PTN_EngineImpProxy::getNumberOfTokens(const string &place) const { - shared_lock guard(m_mutex); + shared_lock guard(m_mutex); return m_ptnEngineImp.getNumberOfTokens(place); } void PTN_Engine::PTN_EngineImpProxy::incrementInputPlace(const string &place) { - unique_lock guard(m_mutex); + unique_lock guard(m_mutex); m_ptnEngineImp.incrementInputPlace(place); } void PTN_Engine::PTN_EngineImpProxy::printState(ostream &o) const { - shared_lock guard(m_mutex); + shared_lock guard(m_mutex); m_ptnEngineImp.printState(o); } -void PTN_Engine::PTN_EngineImpProxy::export_(IExporter &exporter) const -{ - shared_lock guard(m_mutex); - m_ptnEngineImp.export_(exporter); -} - -void PTN_Engine::PTN_EngineImpProxy::import(const IImporter &importer) -{ - unique_lock guard(m_mutex); - m_ptnEngineImp.import(importer); -} - bool PTN_Engine::PTN_EngineImpProxy::isEventLoopRunning() const { - shared_lock guard(m_mutex); + shared_lock guard(m_mutex); return m_ptnEngineImp.isEventLoopRunning(); } void PTN_Engine::PTN_EngineImpProxy::setActionsThreadOption(const ACTIONS_THREAD_OPTION actionsThreadOption) { - unique_lock guard(m_mutex); + unique_lock guard(m_mutex); m_ptnEngineImp.setActionsThreadOption(actionsThreadOption); } PTN_Engine::ACTIONS_THREAD_OPTION PTN_Engine::PTN_EngineImpProxy::getActionsThreadOption() const { - shared_lock guard(m_mutex); + shared_lock guard(m_mutex); return m_ptnEngineImp.getActionsThreadOption(); } diff --git a/PTN_Engine/PTN_EngineImpProxy.h b/PTN_Engine/PTN_EngineImpProxy.h old mode 100644 new mode 100755 index 4de2559..ad3eefb --- a/PTN_Engine/PTN_EngineImpProxy.h +++ b/PTN_Engine/PTN_EngineImpProxy.h @@ -3,7 +3,7 @@ * * Copyright (c) 2017 Eduardo Valgôde * Copyright (c) 2021 Kale Evans - * Copyright (c) 2023 Eduardo Valgôde + * Copyright (c) 2023-2024 Eduardo Valgôde * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -26,11 +26,11 @@ namespace ptne { -/*! - * \brief The PTN_Engine::PTN_EngineImpProxy class is a proxy class to the PTN_EngineImp, which implements the - * PTN_Engine logic. This proxy, implements the necessary synchronization for multi-threaded usage of the - * PTN_Engine. - */ +//! +//! \brief The PTN_Engine::PTN_EngineImpProxy class is a proxy class to the PTN_EngineImp, which implements the +//! PTN_Engine logic. This proxy, implements the necessary synchronization for multi-threaded usage of the +//! PTN_Engine. +//! class PTN_Engine::PTN_EngineImpProxy final { public: @@ -44,129 +44,67 @@ class PTN_Engine::PTN_EngineImpProxy final PTN_EngineImpProxy &operator=(const PTN_EngineImpProxy &) = delete; PTN_EngineImpProxy &operator=(PTN_EngineImpProxy &&) = delete; - /*! - * Create a new transition - * \param activationPlaces A vector with the names of the activation places. - * \param activationWeights A vector with the weights of each activation place. - * \param destinationPlaces A vector with the names of the destination places. - * \param destinationWeights A vector with the weights of each destination place. - * \param inhibitorPlaces Places that cannot have tokens to fire the transition. - * \param additionalConditions A vector with functions that return bool. - */ - void createTransition(const std::vector &activationPlaces, - const std::vector &activationWeights, - const std::vector &destinationPlaces, - const std::vector &destinationWeights, - const std::vector &inhibitorPlaces, - const std::vector &additionalConditions, - const bool requireNoActionsInExecution); - - /*! - * Create a new transition - * \param activationPlaces A vector with the names of the activation places. - * \param activationWeights A vector with the weights of each activation place. - * \param destinationPlaces A vector with the names of the destination places. - * \param destinationWeights A vector with the weights of each destination place. - * \param inhibitorPlaces Places that cannot have tokens to fire the transition. - * \param additionalConditions A vector with names to additional conditions. - */ - void createTransition(const std::vector &activationPlaces, - const std::vector &activationWeights, - const std::vector &destinationPlaces, - const std::vector &destinationWeights, - const std::vector &inhibitorPlaces, - const std::vector &additionalConditions, - const bool requireNoActionsInExecution); - - /*! - * Create a new place in the net. - * \param name The name of the place. - * \param initialNumberOfTokens The number of tokens to be initialized with. - * \param onEnterAction The function to be called once a token enters the place. - * \param onExitAction The function to be called once a token leaves the place. - * \param input A flag determining if this place can have tokens added manually. - */ - void createPlace(const std::string &name, - const size_t initialNumberOfTokens, - ActionFunction onEnterAction, - ActionFunction onExitAction, - const bool input = false); - - /*! - * Create a new place in the net. - * \param name The name of the place. - * \param initialNumberOfTokens The number of tokens to be initialized with. - * \param onEnterAction Name of the function to be called once a token enters the place. - * \param onExitAction Name of the function to be called once a token leaves the place. - * \param input A flag determining if this place can have tokens added manually. - */ - void createPlaceStr(const std::string &name, - const size_t initialNumberOfTokens, - const std::string &onEnterAction, - const std::string &onExitAction, - const bool input = false); - - /*! - * Register an action to be called by the Petri net. - * \param name The name of the place. - * \param action The function to be called once a token enters the place. - */ - void registerAction(const std::string &name, ActionFunction action); - - /*! - * Register a condition - * \param name The name of the condition - * \param conditions A function pointer to a condition. - */ - void registerCondition(const std::string &name, ConditionFunction condition); - - /*! - * Start the petri net event loop. - * \param log Flag logging the state of the net on or off. - * \param o Log output stream. - */ + //! + //! \brief createTransition + //! \param transitionProperties + //! + void createTransition(const TransitionProperties &transitionProperties); + + //! + //! \brief createPlace + //! \param placeProperties + //! + void createPlace(const PlaceProperties &placeProperties); + + //! + //! Register an action to be called by the Petri net. + //! \param name The name of the place. + //! \param action The function to be called once a token enters the place. + //! + void registerAction(const std::string &name, const ActionFunction &action); + + //! + //! Register a condition + //! \param name The name of the condition + //! \param conditions A function pointer to a condition. + //! + void registerCondition(const std::string &name, const ConditionFunction &condition); + + //! + //! Start the petri net event loop. + //! \param log Flag logging the state of the net on or off. + //! \param o Log output stream. + //! void execute(const bool log = false, std::ostream &o = std::cout); - /*! - * \brief Stop the execution loop. - */ + //! + //! \brief Stop the execution loop. + //! void stop(); - /*! - * Return the number of tokens in a given place. - * \param place The name of the place to get the number of tokens from. - * \return The number of tokens present in the place. - */ + //! + //! Return the number of tokens in a given place. + //! \param place The name of the place to get the number of tokens from. + //! \return The number of tokens present in the place. + //! size_t getNumberOfTokens(const std::string &place) const; - /*! - * Add a token in an input place. - * \param place Name of the place to be incremented. - */ + //! + //! Add a token in an input place. + //! \param place Name of the place to be incremented. + //! void incrementInputPlace(const std::string &place); - /*! - * Print the petri net places and number of tokens. - * \param o Output stream. - */ + //! + //! Print the petri net places and number of tokens. + //! \param o Output stream. + //! void printState(std::ostream &o) const; - /*! - * \brief export_ - * \param exporter - */ - void export_(IExporter &exporter) const; - - /*! - * \brief import - * \param importer - */ - void import(const IImporter &importer); - - /*! - * \brief Imports the Petri net using the provided importer. - * \param importer Object containing all necessary information to create a new Petri net. - */ + //! + //! \brief isEventLoopRunning + //! \return + //! bool isEventLoopRunning() const; //! Specify the thread where the actions should be run. @@ -175,18 +113,53 @@ class PTN_Engine::PTN_EngineImpProxy final //! Get the information on which thread the actions are run. ACTIONS_THREAD_OPTION getActionsThreadOption() const; - /*! - * \brief setEventLoopSleepDuration - * \param sleepDuration - */ + //! + //! \brief setEventLoopSleepDuration + //! \param sleepDuration + //! void setEventLoopSleepDuration(const EventLoopSleepDuration sleepDuration); - /*! - * \brief getEventLoopSleepDuration - * \return - */ + //! + //! \brief getEventLoopSleepDuration + //! \return + //! EventLoopSleepDuration getEventLoopSleepDuration() const; + //! + //! \brief addArc + //! \param arcProperties + //! + void addArc(const ArcProperties& arcProperties); + + //! + //! \brief addArc + //! \param arcProperties + //! + void removeArc(const ArcProperties& arcProperties); + + //! + //! \brief clearNet + //! + void clearNet(); + + //! + //! \brief getPlacesProperties + //! \return + //! + std::vector getPlacesProperties() const; + + //! + //! \brief getTransitionsProperties + //! \return + //! + std::vector getTransitionsProperties() const; + + //! + //! \brief getArcsProperties + //! \return + //! + std::vector> getArcsProperties() const; + private: //! Synchronizes calls to m_ptnEngineImp mutable std::shared_mutex m_mutex; diff --git a/PTN_Engine/Place.cpp b/PTN_Engine/Place.cpp old mode 100644 new mode 100755 index 6de6a61..52d7017 --- a/PTN_Engine/Place.cpp +++ b/PTN_Engine/Place.cpp @@ -1,7 +1,7 @@ /* * This file is part of PTN Engine * - * Copyright (c) 2017-2023 Eduardo Valgôde + * Copyright (c) 2017-2024 Eduardo Valgôde * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -17,22 +17,21 @@ */ #include "PTN_Engine/Place.h" -#include "PTN_Engine/IExporter.h" #include "PTN_Engine/IPTN_EnginePlace.h" #include "PTN_Engine/PTN_Exception.h" -#include "limits.h" -#include #include +#include +#include namespace ptne { using namespace std; Place::Place(IPTN_EnginePlace &parent, - const std::string &name, + const string &name, const size_t initialNumberOfTokens, - ActionFunction onEnterAction, - ActionFunction onExitAction, + const ActionFunction &onEnterAction, + const ActionFunction &onExitAction, const bool input) : m_ptnEngine(parent) , m_name(name) @@ -44,12 +43,12 @@ Place::Place(IPTN_EnginePlace &parent, } Place::Place(IPTN_EnginePlace &parent, - const std::string &name, + const string &name, const size_t initialNumberOfTokens, const string &onEnterActionName, - ActionFunction onEnterAction, + const ActionFunction &onEnterAction, const string &onExitActionName, - ActionFunction onExitAction, + const ActionFunction &onExitAction, const bool input) : m_ptnEngine(parent) , m_name(name) @@ -69,7 +68,7 @@ string Place::getName() const void Place::enterPlace(const size_t tokens) { - unique_lock guard(m_mutex); + unique_lock guard(m_mutex); increaseNumberOfTokens(tokens); if (m_onEnterAction == nullptr) { @@ -80,14 +79,14 @@ void Place::enterPlace(const size_t tokens) // TODO make this wait period configurable // add a max wait time after which an exception // is thrown. - std::this_thread::sleep_for(100ms); + this_thread::sleep_for(100ms); } executeAction(m_onEnterAction, m_onEnterActionsInExecution); } void Place::exitPlace(const size_t tokens) { - unique_lock guard(m_mutex); + unique_lock guard(m_mutex); decreaseNumberOfTokens(tokens); if (m_onExitAction == nullptr) { @@ -129,41 +128,41 @@ void Place::decreaseNumberOfTokens(const size_t tokens) void Place::setNumberOfTokens(const size_t tokens) { - unique_lock guard(m_mutex); + unique_lock guard(m_mutex); m_numberOfTokens = tokens; } size_t Place::getNumberOfTokens() const { - shared_lock guard(m_mutex); + shared_lock guard(m_mutex); return m_numberOfTokens; } bool Place::isInputPlace() const { - shared_lock guard(m_mutex); + shared_lock guard(m_mutex); return m_isInputPlace; } -const string Place::getOnEnterActionName() const +string Place::getOnEnterActionName() const { - shared_lock guard(m_mutex); + shared_lock guard(m_mutex); return m_onEnterActionName; } -const string Place::getOnExitActionName() const +string Place::getOnExitActionName() const { - shared_lock guard(m_mutex); + shared_lock guard(m_mutex); return m_onExitActionName; } -void Place::executeAction(const ActionFunction &action, std::atomic &actionsInExecution) +void Place::executeAction(const ActionFunction &action, atomic &actionsInExecution) { switch (m_ptnEngine.getActionsThreadOption()) { default: { - throw std::runtime_error("Invalid configuration"); + throw PTN_Exception("Invalid configuration"); } case PTN_Engine::ACTIONS_THREAD_OPTION::SINGLE_THREAD: case PTN_Engine::ACTIONS_THREAD_OPTION::EVENT_LOOP: @@ -192,7 +191,7 @@ void Place::executeAction(const ActionFunction &action, std::atomic &act action(); --actionsInExecution; }; - auto t = std::thread(job); + auto t = thread(job); t.detach(); break; } @@ -209,10 +208,15 @@ void Place::blockStartingOnEnterActions(const bool value) m_blockStartingOnEnterActions = value; } -void Place::export_(IExporter &exporter) const +PlaceProperties Place::placeProperties() const { - exporter.exportPlace(m_name, to_string(m_numberOfTokens), m_isInputPlace ? "true" : "false", - m_onEnterActionName, m_onExitActionName); + PlaceProperties placeProperties; + placeProperties.name = m_name; + placeProperties.onEnterActionFunctionName = m_onEnterActionName; + placeProperties.onExitActionFunctionName = m_onExitActionName; + placeProperties.initialNumberOfTokens = m_numberOfTokens; + placeProperties.input = m_isInputPlace; + return placeProperties; } } // namespace ptne diff --git a/PTN_Engine/Place.h b/PTN_Engine/Place.h old mode 100644 new mode 100755 index b046c52..142fdd9 --- a/PTN_Engine/Place.h +++ b/PTN_Engine/Place.h @@ -1,7 +1,7 @@ /* * This file is part of PTN Engine * - * Copyright (c) 2017-2023 Eduardo Valgôde + * Copyright (c) 2017-2024 Eduardo Valgôde * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -18,57 +18,55 @@ #pragma once +#include "PTN_Engine/PTN_Engine.h" #include #include -#include #include namespace ptne { - -class IExporter; class IPTN_EnginePlace; -/*! - * \brief Implements a place of a Petri net. - */ +//! +//! \brief Implements a place of a Petri net. +//! class Place final { public: using ActionFunction = std::function; - /*! - * Place constructor. - * \param initialNumberOfTokens The number of tokens the place contains originally. - * \param onEnterAction The action to be performed when a token enters the place. - * \param onExitAction The action to be performed when a token leaves the place. - * \param input Flag that marks the place as an input place. - */ + //! + //! Place constructor. + //! \param initialNumberOfTokens The number of tokens the place contains originally. + //! \param onEnterAction The action to be performed when a token enters the place. + //! \param onExitAction The action to be performed when a token leaves the place. + //! \param input Flag that marks the place as an input place. + //! Place(IPTN_EnginePlace &parent, const std::string &name, const size_t initialNumberOfTokens, - ActionFunction onEnterAction, - ActionFunction onExitAction, + const ActionFunction &onEnterAction, + const ActionFunction &onExitAction, const bool input = false); - /*! - * \brief Place - * \param parent - * \param name - * \param initialNumberOfTokens - * \param onEnterActionName - * \param onEnterAction - * \param onExitActionName - * \param onExitAction - * \param input - */ + //! + //! \brief Place + //! \param parent + //! \param name + //! \param initialNumberOfTokens + //! \param onEnterActionName + //! \param onEnterAction + //! \param onExitActionName + //! \param onExitAction + //! \param input + //! Place(IPTN_EnginePlace &parent, const std::string &name, const size_t initialNumberOfTokens, const std::string &onEnterActionName, - ActionFunction onEnterAction, + const ActionFunction &onEnterAction, const std::string &onExitActionName, - ActionFunction onExitAction, + const ActionFunction &onExitAction, const bool input = false); ~Place() = default; @@ -77,89 +75,89 @@ class Place final Place &operator=(Place &) = delete; Place &operator=(Place &&) = delete; - /*! - * \brief getName - * \return place name - */ + //! + //! \brief getName + //! \return place name + //! std::string getName() const; - /*! - * \brief Increase number of tokens and call on enter action. - * \param tokens - number of tokens to increase. - */ + //! + //! \brief Increase number of tokens and call on enter action. + //! \param tokens - number of tokens to increase. + //! void enterPlace(const size_t tokens = 1); - /*! - * \brief Decrease number of tokens and call on exit action. - * \param tokens - number of tokens to decrease. - */ + //! + //! \brief Decrease number of tokens and call on exit action. + //! \param tokens - number of tokens to decrease. + //! void exitPlace(const size_t tokens = 1); - /*! - * Set the number of tokens in the place. - * \param tokens Number of tokens to be set. - */ + //! + //! Set the number of tokens in the place. + //! \param tokens Number of tokens to be set. + //! void setNumberOfTokens(const size_t tokens); - /*! - * Return the number of tokens. - * \return The number of tokens in the place. - */ + //! + //! Return the number of tokens. + //! \return The number of tokens in the place. + //! size_t getNumberOfTokens() const; - /*! - * If the place is flagged as input. - * \return If the place is an input place. - */ + //! + //! If the place is flagged as input. + //! \return If the place is an input place. + //! bool isInputPlace() const; - /*! - * \brief getOnEnterActionName - * \return The label name of the on enter action. - */ - const std::string getOnEnterActionName() const; - - /*! - * \brief getOnExitActionName - * \return the label name of the on exit action. - */ - const std::string getOnExitActionName() const; - - /*! - * \brief Tells if an "onEnter" action, belonging to the place, is being executed. - * \return true if an "onEnter" action being executed. - */ + //! + //! \brief getOnEnterActionName + //! \return The label name of the on enter action. + //! + std::string getOnEnterActionName() const; + + //! + //! \brief getOnExitActionName + //! \return the label name of the on exit action. + //! + std::string getOnExitActionName() const; + + //! + //! \brief Tells if an "onEnter" action, belonging to the place, is being executed. + //! \return true if an "onEnter" action being executed. + //! bool isOnEnterActionInExecution() const; - /*! - * \brief Whether an on enter action can be triggered or not. - * \param value - */ + //! + //! \brief Whether an on enter action can be triggered or not. + //! \param value + //! void blockStartingOnEnterActions(const bool value); - /*! - * \brief Export a place. - * \param exporter - Object that can export a place. - */ - void export_(IExporter &exporter) const; + //! + //! \brief placeProperties + //! \return + //! + PlaceProperties placeProperties() const; private: - /*! - * Increase number of tokens in the place. - * \param tokens Number of tokens to be added. Must be at least 1. - */ + //! + //! Increase number of tokens in the place. + //! \param tokens Number of tokens to be added. Must be at least 1. + //! void increaseNumberOfTokens(const size_t tokens = 1); - /*! - * Decrease number of tokens in the place. - * \param tokens Number of tokens to be removed. Must be at least 1. - */ + //! + //! Decrease number of tokens in the place. + //! \param tokens Number of tokens to be removed. Must be at least 1. + //! void decreaseNumberOfTokens(const size_t tokens = 1); - /*! - * \brief Execute the action according to the configuration. - * \param action to be executed - */ + //! + //! \brief Execute the action according to the configuration. + //! \param action to be executed + //! void executeAction(const ActionFunction &action, std::atomic &); //! Reference to the PTN Engine instance, to which the place belongs. diff --git a/PTN_Engine/PlacesManagedContainer.cpp b/PTN_Engine/PlacesManagedContainer.cpp deleted file mode 100644 index 628c4ac..0000000 --- a/PTN_Engine/PlacesManagedContainer.cpp +++ /dev/null @@ -1,124 +0,0 @@ -/* - * This file is part of PTN Engine - * - * Copyright (c) 2023 Eduardo Valgôde - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "PTN_Engine/PlacesManagedContainer.h" -#include "PTN_Engine/IExporter.h" -#include "PTN_Engine/PTN_Exception.h" -#include "PTN_Engine/Utilities/DetectRepeated.h" -#include "PTN_Engine/Utilities/LockWeakPtr.h" -#include - -namespace ptne -{ -using namespace std; - -void PlacesManagedContainer::clearInputPlaces() const -{ - unique_lock transitionsGuard(m_placesMutex); - for (const WeakPtrPlace &place : m_inputPlaces) - { - SharedPtrPlace spPlace = lockWeakPtr(place); - spPlace->setNumberOfTokens(0); - } -} - -void PlacesManagedContainer::insert(shared_ptr place) -{ - unique_lock transitionsGuard(m_placesMutex); - const auto &placeName = place->getName(); - if (m_places.find(placeName) != m_places.end()) - { - throw RepeatedPlaceException(placeName); - } - - m_places[placeName] = place; - if (place->isInputPlace()) - { - m_inputPlaces.push_back(place); - } -} - -void PlacesManagedContainer::clear() -{ - unique_lock transitionsGuard(m_placesMutex); - m_inputPlaces.clear(); - m_places.clear(); -} - -void PlacesManagedContainer::printState(ostream &o) const -{ - shared_lock transitionsGuard(m_placesMutex); - o << "Place; Tokens" << endl; - for (const auto &p : m_places) - { - o << p.first.c_str() << ": " << p.second->getNumberOfTokens() << endl; - } - o << endl << endl; -} - -size_t PlacesManagedContainer::getNumberOfTokens(const string &place) const -{ - shared_lock transitionsGuard(m_placesMutex); - if (m_places.find(place) == m_places.end()) - { - throw InvalidNameException(place); - } - return m_places.at(place)->getNumberOfTokens(); -} - -void PlacesManagedContainer::incrementInputPlace(const string &place) -{ - unique_lock transitionsGuard(m_placesMutex); - if (m_places.find(place) == m_places.end()) - { - throw InvalidNameException(place); - } - if (!m_places.at(place)->isInputPlace()) - { - throw NotInputPlaceException(place); - } - m_places.at(place)->enterPlace(1); -} - -void PlacesManagedContainer::export_(IExporter &exporter) const -{ - shared_lock transitionsGuard(m_placesMutex); - for (const auto &place : m_places) - { - place.second->export_(exporter); - } -} - -vector PlacesManagedContainer::getPlacesFromNames(const vector &placesNames) const -{ - shared_lock transitionsGuard(m_placesMutex); - - utility::detectRepeatedNames(placesNames); - - vector placesVector; - for (const auto &placeName : placesNames) - { - if (m_places.find(placeName) == m_places.end()) - { - throw InvalidNameException(placeName); - } - placesVector.push_back(m_places.at(placeName)); - } - return placesVector; -} -} // namespace ptne diff --git a/PTN_Engine/PlacesManagedContainer.h b/PTN_Engine/PlacesManagedContainer.h deleted file mode 100644 index d6a1792..0000000 --- a/PTN_Engine/PlacesManagedContainer.h +++ /dev/null @@ -1,111 +0,0 @@ -/* - * This file is part of PTN Engine - * - * Copyright (c) 2023 Eduardo Valgôde - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#pragma once - -#include "PTN_Engine/PTN_Engine.h" -#include "PTN_Engine/Place.h" -#include - -namespace ptne -{ -using SharedPtrPlace = std::shared_ptr; -using WeakPtrPlace = std::weak_ptr; - -/*! - * \brief Holds and manages a collection of places. - */ -class PlacesManagedContainer -{ -public: - PlacesManagedContainer() = default; - ~PlacesManagedContainer() = default; - PlacesManagedContainer(const PlacesManagedContainer &) = delete; - PlacesManagedContainer(PlacesManagedContainer &&) = delete; - PlacesManagedContainer &operator=(const PlacesManagedContainer &) = delete; - PlacesManagedContainer &operator=(const PlacesManagedContainer &&) = delete; - - /*! - * \brief clearInputPlaces - */ - void clearInputPlaces() const; - - /*! - * \brief Inserts a shared pointer of a place in the container. - * \param name - Indetifier of the place - * \param place - Shared pointer to a place. - */ - void insert(std::shared_ptr place); - - /*! - * \brief Removes all places from the container. - */ - void clear(); - - /*! - * Print the petri net places and number of tokens. - * \param o Output stream. - */ - void printState(std::ostream &o) const; - - /*! - * \brief Gets the number of tokens in a given place. - * \param place - identifier of a place. - * \return Number of tokens inside place. - */ - size_t getNumberOfTokens(const std::string &place) const; - - /*! - * \brief Increment the number of tokens in an input place. - * \param place - Identifier of the input place to increment. - */ - void incrementInputPlace(const std::string &place); - - /*! - * \brief Exports the collection of places. - * \param exporter - Exporter. - */ - void export_(IExporter &exporter) const; - - /*! - * \brief Translates a vector of names of places to a vector of weak pointers to those places. - * \param names Names of the places. - * \return Vector of weakt_ptr for each place given in "names". - */ - std::vector getPlacesFromNames(const std::vector &placesNames) const; - -private: - /*! - * Shared mutex to synchronize the access to the transitions(readers-writer lock). - */ - mutable std::shared_mutex m_placesMutex; - - /*! - * \brief Map of places. - * Insertion is only performed on construction and there are no removals during the lifetime of the net. - * On the other hand many access operations are expected. - */ - std::unordered_map m_places; - - /*! - * \brief Vector with the input places. - * Insertions on construction. Otherwise (should remain) unchanged. - */ - std::vector m_inputPlaces; -}; -} // namespace ptne diff --git a/PTN_Engine/PlacesManager.cpp b/PTN_Engine/PlacesManager.cpp new file mode 100755 index 0000000..3bd859a --- /dev/null +++ b/PTN_Engine/PlacesManager.cpp @@ -0,0 +1,132 @@ +/* + * This file is part of PTN Engine + * + * Copyright (c) 2023-2024 Eduardo Valgôde + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "PTN_Engine/PlacesManager.h" +#include "PTN_Engine/PTN_Exception.h" +#include "PTN_Engine/Utilities/DetectRepeated.h" +#include "PTN_Engine/Utilities/LockWeakPtr.h" +#include + +namespace ptne +{ +using namespace std; + +bool PlacesManager::contains(const string &itemName) const +{ + shared_lock itemsGuard(m_itemsMutex); + return ManagerBase::contains(itemName); +} + +void PlacesManager::insert(const shared_ptr &spPlace) +{ + unique_lock itemsGuard(m_itemsMutex); + ManagerBase::insert(spPlace); + if (spPlace->isInputPlace()) + { + m_inputPlaces.push_back(spPlace); + } +} + +void PlacesManager::clear() +{ + unique_lock itemsGuard(m_itemsMutex); + ManagerBase::clear(); + m_inputPlaces.clear(); +} + +shared_ptr PlacesManager::getPlace(const string &placeName) const +{ + shared_lock itemsGuard(m_itemsMutex); + return ManagerBase::getItem(placeName); +} + +void PlacesManager::clearInputPlaces() const +{ + unique_lock placesGuard(m_itemsMutex); + for (const WeakPtrPlace &place : m_inputPlaces) + { + SharedPtrPlace spPlace = lockWeakPtr(place); + spPlace->setNumberOfTokens(0); + } +} + +void PlacesManager::printState(ostream &o) const +{ + shared_lock placesGuard(m_itemsMutex); + o << "Place; Tokens" << endl; + for (const auto &[placeName, place] : m_items) + { + o << placeName.c_str() << ": " << place->getNumberOfTokens() << endl; + } + o << endl << endl; +} + +size_t PlacesManager::getNumberOfTokens(const string &place) const +{ + shared_lock placesGuard(m_itemsMutex); + if (!m_items.contains(place)) + { + throw InvalidNameException(place); + } + return m_items.at(place)->getNumberOfTokens(); +} + +void PlacesManager::incrementInputPlace(const string &place) +{ + unique_lock placesGuard(m_itemsMutex); + if (!m_items.contains(place)) + { + throw InvalidNameException(place); + } + if (!m_items.at(place)->isInputPlace()) + { + throw NotInputPlaceException(place); + } + m_items.at(place)->enterPlace(1); +} + +vector PlacesManager::getPlacesProperties() const +{ + shared_lock placesGuard(m_itemsMutex); + + vector placesProperties; + for (const auto &[_, place] : m_items) + { + placesProperties.push_back(place->placeProperties()); + } + return placesProperties; +} + +vector PlacesManager::getPlacesFromNames(const vector &placesNames) const +{ + shared_lock placesGuard(m_itemsMutex); + + utility::detectRepeatedNames(placesNames); + + vector placesVector; + for (const auto &placeName : placesNames) + { + if (!m_items.contains(placeName)) + { + throw InvalidNameException(placeName); + } + placesVector.push_back(m_items.at(placeName)); + } + return placesVector; +} +} // namespace ptne diff --git a/PTN_Engine/PlacesManager.h b/PTN_Engine/PlacesManager.h new file mode 100755 index 0000000..4c87843 --- /dev/null +++ b/PTN_Engine/PlacesManager.h @@ -0,0 +1,112 @@ +/* + * This file is part of PTN Engine + * + * Copyright (c) 2023-2024 Eduardo Valgôde + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#pragma once + +#include "PTN_Engine/PTN_Engine.h" +#include "PTN_Engine/Place.h" +#include "PTN_Engine/ManagerBase.h" +#include + +namespace ptne +{ +using SharedPtrPlace = std::shared_ptr; +using WeakPtrPlace = std::weak_ptr; + +//! +//! \brief Holds and manages a collection of places. +//! +class PlacesManager : private ManagerBase +{ +public: + //! + //! \brief contains + //! \param itemName + //! \return + //! + bool contains(const std::string &itemName) const; + + //! + //! \brief Insert a new transition. + //! \param place + //! + void insert(const std::shared_ptr &place); + + //! + //! \brief clear + //! + void clear(); + + //! + //! \brief getPlace + //! \param placeName + //! \return + //! + std::shared_ptr getPlace(const std::string &placeName) const; + + //! + //! \brief clearInputPlaces + //! + void clearInputPlaces() const; + + //! + //! \brief Translates a vector of names of places to a vector of weak pointers to those places. + //! \param names Names of the places. + //! \return Vector of weakt_ptr for each place given in "names". + //! + std::vector getPlacesFromNames(const std::vector &placesNames) const; + + //! + //! Print the petri net places and number of tokens. + //! \param o Output stream. + //! + void printState(std::ostream &o) const; + + //! + //! \brief Gets the number of tokens in a given place. + //! \param place - identifier of a place. + //! \return Number of tokens inside place. + //! + size_t getNumberOfTokens(const std::string &place) const; + + //! + //! \brief Increment the number of tokens in an input place. + //! \param place - Identifier of the input place to increment. + //! + void incrementInputPlace(const std::string &place); + + //! + //! \brief getPlacesProperties + //! \return + //! + std::vector getPlacesProperties() const; + +private: + //! + //! Shared mutex to synchronize the access to the items(readers-writer lock). + //! + mutable std::shared_mutex m_itemsMutex; + + //! + //! \brief Vector with the input places. + //! Insertions on construction. Otherwise (should remain) unchanged. + //! + std::vector m_inputPlaces; +}; + +} // namespace ptne diff --git a/PTN_Engine/Transition.cpp b/PTN_Engine/Transition.cpp old mode 100644 new mode 100755 index 12637a7..8556cd8 --- a/PTN_Engine/Transition.cpp +++ b/PTN_Engine/Transition.cpp @@ -3,7 +3,7 @@ * * Copyright (c) 2017 Eduardo Valgôde * Copyright (c) 2021 Kale Evans - * Copyright (c) 2023 Eduardo Valgôde + * Copyright (c) 2024 Eduardo Valgôde * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -19,85 +19,73 @@ */ #include "PTN_Engine/Transition.h" -#include "PTN_Engine/IExporter.h" #include "PTN_Engine/PTN_Exception.h" #include "PTN_Engine/Place.h" #include "PTN_Engine/Utilities/DetectRepeated.h" #include "PTN_Engine/Utilities/LockWeakPtr.h" +#include +#include #include -#include -#include +#include namespace ptne { using namespace std; -Transition::Transition(const vector &activationPlaces, - const vector &activationWeights, - const vector &destinationPlaces, - const vector &destinationWeights, - const vector &inhibitorPlaces, +Transition::Transition(const string &name, + const vector &activationArcs, + const vector &destinationArcs, + const vector &inhibitorArcs, const vector> &additionalActivationConditions, const bool requireNoActionsInExecution) -: m_additionalActivationConditions{ additionalActivationConditions } -, m_inhibitorPlaces(inhibitorPlaces) +: m_name(name) +, m_activationArcs(activationArcs) +, m_destinationArcs(destinationArcs) +, m_additionalActivationConditions(additionalActivationConditions) +, m_inhibitorArcs(inhibitorArcs) , m_requireNoActionsInExecution(requireNoActionsInExecution) { - if (activationPlaces.size() != activationWeights.size() && !activationWeights.empty()) + auto getPlacesFromArcs = [](const vector &arcs) { - throw ActivationWeightDimensionException(); - } - - if (destinationPlaces.size() != destinationWeights.size() && !destinationWeights.empty()) - { - throw DestinationWeightDimensionException(); - } - - utility::detectRepeated(activationPlaces); + vector places; + ranges::transform(arcs.cbegin(), arcs.cend(), back_inserter(places), [](const auto &arc) { + return arc.place; }); + return places; + }; - utility::detectRepeated(destinationPlaces); + utility::detectRepeated(getPlacesFromArcs(activationArcs)); + utility::detectRepeated(getPlacesFromArcs(destinationArcs)); - if (!activationWeights.empty()) + auto validateWeights = [](const vector &arcs) { - for (size_t i = 0; i < activationPlaces.size(); ++i) + if (ranges::find_if(arcs.cbegin(), arcs.cend(), [](const auto &arc) { + return arc.weight == 0; + }) != arcs.cend()) { - m_activationPlaces.push_back(tuple(activationPlaces[i], activationWeights[i])); + throw ZeroValueWeightException(); } - } - else - { - transform(activationPlaces.cbegin(), activationPlaces.cend(), back_inserter(m_activationPlaces), - [](const auto &ap) { return tuple(ap, 1); }); - } + }; - if (!destinationWeights.empty()) - { - for (size_t i = 0; i < destinationPlaces.size(); ++i) - { - if (destinationWeights[i] == 0) - { - throw ZeroValueWeightException(); - } - m_destinationPlaces.push_back( - tuple(destinationPlaces[i], destinationWeights[i])); - } - } - else - { - transform(destinationPlaces.cbegin(), destinationPlaces.cend(), back_inserter(m_destinationPlaces), - [](const auto &dp) { return tuple(dp, 1); }); - } + validateWeights(activationArcs); + validateWeights(destinationArcs); + validateWeights(inhibitorArcs); } Transition::Transition(Transition &&transition) noexcept { - unique_lock guard(m_mutex); + unique_lock guard(m_mutex); moveMembers(transition); } +string Transition::getName() const +{ + shared_lock guard(m_mutex); + return m_name; +} + bool Transition::execute() { - unique_lock guard(m_mutex); + unique_lock guard(m_mutex); bool result = false; blockStartingOnEnterActions(true); @@ -119,7 +107,7 @@ bool Transition::execute() bool Transition::isEnabled() const { - shared_lock guard(m_mutex); + shared_lock guard(m_mutex); return isEnabledInternal(); } @@ -144,114 +132,192 @@ bool Transition::isActive() const checkAdditionalConditions(); } -vector> Transition::getActivationPlaces() const +vector Transition::getActivationPlaces() const { - shared_lock guard(m_mutex); - return m_activationPlaces; + shared_lock guard(m_mutex); + return m_activationArcs; } -vector> Transition::getDestinationPlaces() const +vector Transition::getDestinationPlaces() const { - shared_lock guard(m_mutex); - return m_destinationPlaces; + shared_lock guard(m_mutex); + return m_destinationArcs; } -vector> Transition::getAdditionalActivationConditions() const +vector> Transition::getAdditionalActivationConditions() const { - shared_lock guard(m_mutex); + shared_lock guard(m_mutex); return m_additionalActivationConditions; } -std::vector Transition::getInhibitorPlaces() const +vector Transition::getInhibitorArcs() const { - shared_lock guard(m_mutex); - return m_inhibitorPlaces; -} - -void Transition::export_(IExporter &exporter) const -{ - vector> activationPlacesExport; - transform(m_activationPlaces.cbegin(), m_activationPlaces.cend(), back_inserter(activationPlacesExport), - [](const auto &activationPlace) - { - tuple activationPlaceExport; - if (auto activationPlaceShPtr = get<0>(activationPlace).lock()) - { - get<0>(activationPlaceExport) = activationPlaceShPtr->getName(); - get<1>(activationPlaceExport) = get<1>(activationPlace); - return activationPlaceExport; - } - else - { - throw PTN_Exception("Could not lock activation place weak pointer"); - } - }); - - vector> destinationPlacesExport; - transform(m_destinationPlaces.cbegin(), m_destinationPlaces.cend(), back_inserter(destinationPlacesExport), - [](const auto &destinationPlace) - { - tuple destinationPlaceExport; - if (auto destinationPlaceShPtr = get<0>(destinationPlace).lock()) - { - get<0>(destinationPlaceExport) = destinationPlaceShPtr->getName(); - get<1>(destinationPlaceExport) = get<1>(destinationPlace); - return destinationPlaceExport; - } - else - { - throw PTN_Exception("Could not lock destination place weak pointer"); - } - }); - - vector activationConditionsNames; - transform(m_additionalActivationConditions.cbegin(), m_additionalActivationConditions.cend(), - back_inserter(activationConditionsNames), - [](const auto &activationCondition) { return activationCondition.first; }); - - vector inhibitorPlacesNames; - transform(m_inhibitorPlaces.cbegin(), m_inhibitorPlaces.cend(), back_inserter(inhibitorPlacesNames), - [](const auto &inhibitorPlace) - { - if (auto inhibitorPlaceShPtr = inhibitorPlace.lock()) - { - return inhibitorPlaceShPtr->getName(); - } - else - { - throw PTN_Exception("Could not lock inhibitor place weak pointer"); - } - }); - - exporter.exportTransition(activationPlacesExport, destinationPlacesExport, activationConditionsNames, - inhibitorPlacesNames, requireNoActionsInExecution()); + shared_lock guard(m_mutex); + return m_inhibitorArcs; } bool Transition::requireNoActionsInExecution() const { + shared_lock guard(m_mutex); return m_requireNoActionsInExecution; } bool Transition::checkInhibitorPlaces() const { - for (const WeakPtrPlace &inhibitorPlace : m_inhibitorPlaces) + auto numberOfTokensGreaterThan0 = [](const auto &inhibitorArc) { - SharedPtrPlace spInhibitorPlace = lockWeakPtr(inhibitorPlace); + SharedPtrPlace spInhibitorArc = lockWeakPtr(inhibitorArc.place); + return spInhibitorArc->getNumberOfTokens() > 0; + }; - if (spInhibitorPlace->getNumberOfTokens() > 0) + if (ranges::find_if(m_inhibitorArcs.cbegin(), m_inhibitorArcs.cend(), numberOfTokensGreaterThan0) != m_inhibitorArcs.end()) + { + return false; + } + return true; +} + +TransitionProperties Transition::getTransitionProperties() const +{ + TransitionProperties transitionProperties; + + auto getAdditionalConditionsNames = [this]() + { + vector additionalActivationConditionNames; + for (const auto &[additionalActivationConditionName,_] : m_additionalActivationConditions) { - return false; + additionalActivationConditionNames.push_back(additionalActivationConditionName); + } + return additionalActivationConditionNames; + }; + + transitionProperties.additionalConditionsNames = getAdditionalConditionsNames(); + transitionProperties.name = getName(); + transitionProperties.requireNoActionsInExecution = m_requireNoActionsInExecution; + + return transitionProperties; +} + +array,3> Transition::getArcsProperties() const +{ + array, 3> arcsProperties; + auto arcPropertiesFromArcs = + [this](const vector &arcs, ArcProperties::Type type) + { + vector arcProperties; + for (const auto &arc : arcs) + { + auto spPlace = lockWeakPtr(arc.place); + arcProperties.emplace_back(arc.weight, spPlace->getName(), getName(), type); + } + return arcProperties; + }; + + arcsProperties[0] = arcPropertiesFromArcs(m_activationArcs, ArcProperties::Type::ACTIVATION); + arcsProperties[1] = arcPropertiesFromArcs(m_destinationArcs, ArcProperties::Type::DESTINATION); + arcsProperties[2] = arcPropertiesFromArcs(m_inhibitorArcs, ArcProperties::Type::INHIBITOR); + + return arcsProperties; +} + +void Transition::addPlace(const shared_ptr &place, const ArcProperties::Type type, const size_t weight) +{ + unique_lock guard(m_mutex); + + auto addArcTo = [&place, weight] (auto &placesContainer) + { + auto sameNameAs = [&place] (const auto &arc) { + return lockWeakPtr(arc.place)->getName() == place->getName(); + }; + + if (ranges::find_if(placesContainer.cbegin(), placesContainer.cend(), sameNameAs) == placesContainer.cend()) + { + placesContainer.push_back({ place, weight }); } + }; + + switch (type) + { + default: + { + throw PTN_Exception("Unexpected type"); + } + case ArcProperties::Type::ACTIVATION: + { + addArcTo(m_activationArcs); + break; + } + case ArcProperties::Type::BIDIRECTIONAL: + { + addArcTo(m_activationArcs); + addArcTo(m_destinationArcs); + break; + } + case ArcProperties::Type::DESTINATION: + { + addArcTo(m_destinationArcs); + break; + } + case ArcProperties::Type::INHIBITOR: + { + addArcTo(m_inhibitorArcs); + break; + } + } +} + +void Transition::removePlace(const shared_ptr &place, const ArcProperties::Type type) +{ + unique_lock guard(m_mutex); + + auto removePlaceFrom = [&place](auto &placesContainer) + { + auto sameNameAs = [&place](const auto &arc) + { return lockWeakPtr(arc.place)->getName() == place->getName(); }; + + auto it = ranges::find_if(placesContainer.cbegin(), placesContainer.cend(), sameNameAs); + if (it != placesContainer.cend()) + { + placesContainer.erase(it); + } + }; + + switch (type) + { + default: + { + throw PTN_Exception("Unexpected type"); + } + case ArcProperties::Type::ACTIVATION: + { + removePlaceFrom(m_activationArcs); + break; + } + case ArcProperties::Type::BIDIRECTIONAL: + { + removePlaceFrom(m_activationArcs); + removePlaceFrom(m_destinationArcs); + break; + } + case ArcProperties::Type::DESTINATION: + { + removePlaceFrom(m_destinationArcs); + break; + } + case ArcProperties::Type::INHIBITOR: + { + removePlaceFrom(m_inhibitorArcs); + break; + } } - return true; } bool Transition::checkActivationPlaces() const { - for (const tuple &tupleActivationPlace : m_activationPlaces) + for (const Arc &activationArc : m_activationArcs) { - const WeakPtrPlace &activationPlace = get<0>(tupleActivationPlace); - const size_t activationWeight = get<1>(tupleActivationPlace); + const WeakPtrPlace &activationPlace = activationArc.place; + const size_t activationWeight = activationArc.weight; SharedPtrPlace spPlace = lockWeakPtr(activationPlace); @@ -265,12 +331,11 @@ bool Transition::checkActivationPlaces() const bool Transition::checkAdditionalConditions() const { - for (const auto &p : m_additionalActivationConditions) + for (const auto&[name, activationCondition] : m_additionalActivationConditions) { - const ConditionFunction &activationCondition = p.second; if (!activationCondition) { - throw PTN_Exception("Invalid activation condition " + p.first); + throw PTN_Exception("Invalid activation condition " + name); } else { @@ -285,9 +350,9 @@ bool Transition::checkAdditionalConditions() const bool Transition::noActionsInExecution() const { - for (const tuple &tupleActivationPlace : m_activationPlaces) + for (const Arc &activationArc : m_activationArcs) { - const WeakPtrPlace &activationPlace = get<0>(tupleActivationPlace); + const WeakPtrPlace &activationPlace = activationArc.place; SharedPtrPlace spPlace = lockWeakPtr(activationPlace); @@ -299,18 +364,18 @@ bool Transition::noActionsInExecution() const return true; } -void Transition::performTransit() +void Transition::performTransit() const { exitActivationPlaces(); enterDestinationPlaces(); } -void Transition::exitActivationPlaces() +void Transition::exitActivationPlaces() const { - for (tuple &tupleActivationPlace : m_activationPlaces) + for (const Arc &activationArc : m_activationArcs) { - const WeakPtrPlace &activationPlace = get<0>(tupleActivationPlace); - const size_t activationWeight = get<1>(tupleActivationPlace); + const WeakPtrPlace &activationPlace = activationArc.place; + const size_t activationWeight = activationArc.weight; if (SharedPtrPlace spPlace = lockWeakPtr(activationPlace)) { @@ -319,12 +384,12 @@ void Transition::exitActivationPlaces() } } -void Transition::enterDestinationPlaces() +void Transition::enterDestinationPlaces() const { - for (tuple &tupleDestinationPlace : m_destinationPlaces) + for (const Arc &destinationArc : m_destinationArcs) { - const WeakPtrPlace &destinationPlace = get<0>(tupleDestinationPlace); - const size_t destinationWeight = get<1>(tupleDestinationPlace); + const WeakPtrPlace &destinationPlace = destinationArc.place; + const size_t destinationWeight = destinationArc.weight; if (SharedPtrPlace spPlace = lockWeakPtr(destinationPlace)) { @@ -335,22 +400,22 @@ void Transition::enterDestinationPlaces() void Transition::moveMembers(Transition &transition) { - m_activationPlaces = std::move(transition.m_activationPlaces); - m_destinationPlaces = std::move(transition.m_destinationPlaces); + m_activationArcs = std::move(transition.m_activationArcs); + m_destinationArcs = std::move(transition.m_destinationArcs); + m_inhibitorArcs = std::move(transition.m_inhibitorArcs); m_additionalActivationConditions = std::move(transition.m_additionalActivationConditions); - m_inhibitorPlaces = std::move(transition.m_inhibitorPlaces); } -void Transition::blockStartingOnEnterActions(const bool value) +void Transition::blockStartingOnEnterActions(const bool value) const { if (!m_requireNoActionsInExecution) { return; } - for (tuple &tupleActivationPlace : m_activationPlaces) + for (const Arc &activationArc : m_activationArcs) { - const WeakPtrPlace &activationPlace = get<0>(tupleActivationPlace); + const WeakPtrPlace &activationPlace = activationArc.place; if (SharedPtrPlace spPlace = lockWeakPtr(activationPlace)) { spPlace->blockStartingOnEnterActions(value); diff --git a/PTN_Engine/Transition.h b/PTN_Engine/Transition.h old mode 100644 new mode 100755 index db666a8..0f4e2a9 --- a/PTN_Engine/Transition.h +++ b/PTN_Engine/Transition.h @@ -3,7 +3,7 @@ * * Copyright (c) 2017 Eduardo Valgôde * Copyright (c) 2021 Kale Evans - * Copyright (c) 2023 Eduardo Valgôde + * Copyright (c) 2024 Eduardo Valgôde * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -20,49 +20,62 @@ #pragma once +#include "PTN_Engine/PTN_Engine.h" #include #include #include -#include #include namespace ptne { -class IExporter; class Place; //! Shared pointer to member functions of the controller. using ConditionFunction = std::function; -/*! - * \brief Implements a Petri net transition. - */ +//! Shared pointer type to a place in the net. +using SharedPtrPlace = std::shared_ptr; + +//! Weak pointer type to a place in the net. +using WeakPtrPlace = std::weak_ptr; + +//! +//! \brief The Arc class +//! +struct Arc +{ + //! + //! \brief place + //! + WeakPtrPlace place; + + //! + //! \brief weight + //! + size_t weight = 1; +}; + +//! +//! \brief Implements a Petri net transition. +//! class Transition final { public: - //! Shared pointer type to a place in the net. - using SharedPtrPlace = std::shared_ptr; - - //! Weak pointer type to a place in the net. - using WeakPtrPlace = std::weak_ptr; - - //! Constructor. - /*! - * Constructor. - * \param activationPlaces Collection of incoming places. - * \param activationWeights Weights of each activation place. - * \param destinationPlaces Collection of outgoing places. - * \param destinationWeights Weights of each destination place. - * \param additionalActivationConditions Boolean function from the controller that can block firing. - * \param inhibitorPlaces Places that must be empty for the transition to fire. - */ - Transition(const std::vector &activationPlaces, - const std::vector &activationWeights, - const std::vector &destinationPlaces, - const std::vector &destinationWeights, - const std::vector &inhibitorPlaces, - const std::vector> &additionalActivationConditions, - const bool requireNoActionsInExecution); + //! \brief Constructor. + //! \param name Name and identifier of the transition. + //! \param activationPlaces Collection of incoming places. + //! \param activationWeights Weights of each activation place. + //! \param destinationPlaces Collection of outgoing places. + //! \param destinationWeights Weights of each destination place. + //! \param additionalActivationConditions Boolean function from the controller that can block firing. + //! \param inhibitorPlaces Places that must be empty for the transition to fire. + //! + Transition( const std::string& name, + const std::vector &activationArcs, + const std::vector &destinationArcs, + const std::vector &inhibitorArcs, + const std::vector> &additionalActivationConditions, + const bool requireNoActionsInExecution); ~Transition() = default; Transition(const Transition &) = delete; @@ -70,117 +83,151 @@ class Transition final Transition &operator=(Transition &) = delete; Transition &operator=(Transition &&) = delete; - /*! - * Evaluate the activation places and transit the tokens if possible. - * \return true if token transit was performed, false if not. - */ + //! + //! \brief getName + //! \return + //! + std::string getName() const; + + //! + //! Evaluate the activation places and transit the tokens if possible. + //! \return true if token transit was performed, false if not. + //! bool execute(); - /*! - * Evaluates if the transition can attempt to be fired. - * \return true if can attepmted to be fired, false if it cannot. - */ + //! + //! Evaluates if the transition can attempt to be fired. + //! \return true if can attepmted to be fired, false if it cannot. + //! bool isEnabled() const; - /*! - * \brief getActivationPlaces Gets the activation places of the transition. - * \return A vector of tuples with the activation places and their weights. - */ - std::vector> getActivationPlaces() const; - - /*! - * \brief getDestinationPlaces - * \return A vector of tuples with the destination places and their weights. - */ - std::vector> getDestinationPlaces() const; - - /*! - * \brief getAdditionalActivationConditions - * \return - */ + //! + //! \brief getActivationPlaces Gets the activation places of the transition. + //! \return A vector of Arcs with the activation places and their weights. + //! + std::vector getActivationPlaces() const; + + //! + //! \brief getDestinationPlaces + //! \return A vector of Arcs with the destination places and their weights. + //! + std::vector getDestinationPlaces() const; + + //! + //! \brief getAdditionalActivationConditions + //! \return + //! std::vector> getAdditionalActivationConditions() const; - /*! - * \brief getInhibitorPlaces - * \return - */ - std::vector getInhibitorPlaces() const; - - /*! - * \brief Export a transition. - * \param exporter - Object that can export a transition. - */ - void export_(IExporter &exporter) const; - - /*! - * \brief requireNoActionsInExecution - * \return true if it is required that the activation places have no ongoing on enter actions. - */ + //! + //! \brief getInhibitorArcs + //! \return + //! + std::vector getInhibitorArcs() const; + + //! + //! \brief requireNoActionsInExecution + //! \return true if it is required that the activation places have no ongoing on enter actions. + //! bool requireNoActionsInExecution() const; + //! + //! \brief getTransitionProperties + //! \return + //! + TransitionProperties getTransitionProperties() const; + + //! + //! \brief getArcsProperties + //! \return + //! + std::array,3> getArcsProperties() const; + + //! + //! \brief addPlace + //! \param place + //! \param activation + //! \param isInhibitor + //! \param weight + //! + void addPlace(const std::shared_ptr &place, const ArcProperties::Type type, const size_t weight = 0); + + //! + //! \brief removePlace + //! \param place + //! \param activation + //! \param isInhibitor + //! + void removePlace(const std::shared_ptr &place, const ArcProperties::Type type); + private: - /*! - * \brief Checks if all inhibitor places are empty. - * \return True if yes, false if not. - */ + //! + //! \brief Name and identifier of the transition. + //! + std::string m_name; + + //! + //! \brief Checks if all inhibitor places are empty. + //! \return True if yes, false if not. + //! bool checkInhibitorPlaces() const; - /*! - * \brief Checks if all activation places have enough tokens. - * \return True if yes, false if not. - */ + //! + //! \brief Checks if all activation places have enough tokens. + //! \return True if yes, false if not. + //! bool checkActivationPlaces() const; - /*! - * \brief Checks if all additional conditions allow firing. - * \return True if yes, false if not. - */ + //! + //! \brief Checks if all additional conditions allow firing. + //! \return True if yes, false if not. + //! bool checkAdditionalConditions() const; - /*! - * \brief If there are no actions being currently executed in the activation places. - * \return true if there are no actions being currently executed in the activation places. - */ + //! + //! \brief If there are no actions being currently executed in the activation places. + //! \return true if there are no actions being currently executed in the activation places. + //! bool noActionsInExecution() const; - /*! - * \brief Evaluates if the transition can be fired. - * \return true if can be fired, false if it cannot. - */ + //! + //! \brief Evaluates if the transition can be fired. + //! \return true if can be fired, false if it cannot. + //! bool isActive() const; - /*! - * \brief Evaluates if the transition can attempt to be fired. - * \return True if can attepmted to be fired, false if it cannot. - */ + //! + //! \brief Evaluates if the transition can attempt to be fired. + //! \return True if can attepmted to be fired, false if it cannot. + //! bool isEnabledInternal() const; //! Moves the tokens from the inputs to the outputs. - void performTransit(); + void performTransit() const; //! Removes the tokens from the activation places. - void exitActivationPlaces(); + void exitActivationPlaces() const; //! Inserts tokens in the destination places. - void enterDestinationPlaces(); + void enterDestinationPlaces() const; //! Move members of the class into the transition passed as argument. void moveMembers(Transition &transition); //! Block/unblock activation places from starting any on enter actions. - void blockStartingOnEnterActions(const bool value); + void blockStartingOnEnterActions(const bool value) const; //! Pointers to the activations places from the net. - std::vector> m_activationPlaces; + std::vector m_activationArcs; //! Pointers to the destination places from the net. - std::vector> m_destinationPlaces; + std::vector m_destinationArcs; //! Pointers to the controller's functions that evaluate if the transition can be fired. std::vector> m_additionalActivationConditions; //! Inhibitor arcs - std::vector m_inhibitorPlaces; + std::vector m_inhibitorArcs; //! Shared mutex to synchronize calls, allowing simultaneous reads (readers-writer lock). mutable std::shared_mutex m_mutex; diff --git a/PTN_Engine/TransitionsManagedContainer.cpp b/PTN_Engine/TransitionsManagedContainer.cpp deleted file mode 100644 index 543e398..0000000 --- a/PTN_Engine/TransitionsManagedContainer.cpp +++ /dev/null @@ -1,67 +0,0 @@ -/* - * This file is part of PTN Engine - * - * Copyright (c) 2017 Eduardo Valgôde - * Copyright (c) 2021 Kale Evans - * Copyright (c) 2023 Eduardo Valgôde - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "PTN_Engine/TransitionsManagedContainer.h" -#include "PTN_Engine/IExporter.h" -#include "PTN_Engine/Transition.h" -#include -#include - -namespace ptne -{ -using namespace std; - -vector> TransitionsManagedContainer::collectEnabledTransitionsRandomly() const -{ - shared_lock transitionsGuard(m_transitionsMutex); - - vector> enabledTransitions; - copy_if(m_transitions.cbegin(), m_transitions.cend(), back_inserter(enabledTransitions), - [](const auto &transition) { return transition->isEnabled(); }); - - // TODO check performance - random_device randomDevice; - mt19937_64 seed(randomDevice()); - shuffle(enabledTransitions.begin(), enabledTransitions.end(), seed); - return enabledTransitions; -} - -void TransitionsManagedContainer::export_(IExporter &exporter) const -{ - shared_lock transitionsGuard(m_transitionsMutex); - for (const auto &transition : m_transitions) - { - transition->export_(exporter); - } -} - -void TransitionsManagedContainer::insert(shared_ptr transition) -{ - unique_lock transitionsGuard(m_transitionsMutex); - m_transitions.emplace_back(transition); -} - -void TransitionsManagedContainer::clear() -{ - unique_lock transitionsGuard(m_transitionsMutex); - m_transitions.clear(); -} - -} // namespace ptne diff --git a/PTN_Engine/TransitionsManagedContainer.h b/PTN_Engine/TransitionsManagedContainer.h deleted file mode 100644 index 04c3c2b..0000000 --- a/PTN_Engine/TransitionsManagedContainer.h +++ /dev/null @@ -1,80 +0,0 @@ -/* - * This file is part of PTN Engine - * - * Copyright (c) 2017 Eduardo Valgôde - * Copyright (c) 2021 Kale Evans - * Copyright (c) 2023 Eduardo Valgôde - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#pragma once - -#include "PTN_Engine/Transition.h" -#include - -namespace ptne -{ -class IExporter; - -/*! - * \brief The TransitionsManagedContainer class - */ -class TransitionsManagedContainer -{ -public: - TransitionsManagedContainer() = default; - ~TransitionsManagedContainer() = default; - TransitionsManagedContainer(const TransitionsManagedContainer &) = delete; - TransitionsManagedContainer(TransitionsManagedContainer &&) = delete; - TransitionsManagedContainer &operator=(const TransitionsManagedContainer &) = delete; - TransitionsManagedContainer &operator=(const TransitionsManagedContainer &&) = delete; - - /*! - * \brief Insert a new transition. - * \param transition - */ - void insert(std::shared_ptr transition); - - /*! - * \brief collectEnabledTransitionsRandomly - * \return A vector of weak pointers to the enabled transitions. - */ - std::vector> collectEnabledTransitionsRandomly() const; - - /*! - * \brief clear - */ - void clear(); - - /*! - * \brief export_ - * \param exporter - * \param places - * \param conditions - */ - void export_(IExporter &exporter) const; - -private: - /*! - * Shared mutex to synchronize the access to the transitions(readers-writer lock). - */ - mutable std::shared_mutex m_transitionsMutex; - - /*! - * \brief Vector with the transitions. - */ - std::vector> m_transitions; -}; - -} // namespace ptne diff --git a/PTN_Engine/TransitionsManager.cpp b/PTN_Engine/TransitionsManager.cpp new file mode 100755 index 0000000..a056647 --- /dev/null +++ b/PTN_Engine/TransitionsManager.cpp @@ -0,0 +1,111 @@ +/* + * This file is part of PTN Engine + * + * Copyright (c) 2017 Eduardo Valgôde + * Copyright (c) 2021 Kale Evans + * Copyright (c) 2024 Eduardo Valgôde + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "PTN_Engine/TransitionsManager.h" +#include "PTN_Engine/Transition.h" +#include +#include +#include +#include + +namespace ptne +{ +using namespace std; + +bool TransitionsManager::contains(const string &itemName) const +{ + shared_lock itemsGuard(m_itemsMutex); + return ManagerBase::contains(itemName); +} + +void TransitionsManager::insert(shared_ptr transition) +{ + unique_lock itemsGuard(m_itemsMutex); + ManagerBase::insert(transition); +} + +void TransitionsManager::clear() +{ + unique_lock itemsGuard(m_itemsMutex); + ManagerBase::clear(); +} + +vector> TransitionsManager::collectEnabledTransitionsRandomly() const +{ + shared_lock transitionsGuard(m_itemsMutex); + + // vector> enabledTransitions; + // copy_if(m_transitions.cbegin(), m_transitions.cend(), back_inserter(enabledTransitions), + // [](const auto &item) { return item.second->isEnabled(); }); + + vector> enabledTransitions; + for (const auto &[_, transition] : m_items) + { + if (transition->isEnabled()) + { + enabledTransitions.push_back(transition); + } + } + + // TODO check performance + random_device randomDevice; + mt19937_64 seed(randomDevice()); + ranges::shuffle(enabledTransitions.begin(), enabledTransitions.end(), seed); + return enabledTransitions; +} + +bool TransitionsManager::hasTransition(const string &name) const +{ + shared_lock itemsGuard(m_itemsMutex); + return ManagerBase::contains(name); +} + +SharedPtrTransition TransitionsManager::getTransition(const string &transitionName) const +{ + shared_lock itemsGuard(m_itemsMutex); + return ManagerBase::getItem(transitionName); +} + +vector TransitionsManager::getTransitionsProperties() const +{ + shared_lock itemsGuard(m_itemsMutex); + vector transitionsProperties; + for (const auto &[_, transition] : m_items) + { + transitionsProperties.push_back(transition->getTransitionProperties()); + } + return transitionsProperties; +} + +vector> TransitionsManager::getArcsProperties() const +{ + shared_lock itemsGuard(m_itemsMutex); + vector> arcsProperties; + for (const auto &[_, transition] : m_items) + { + auto arcsPropertiesExport = transition->getArcsProperties(); + arcsProperties.push_back(arcsPropertiesExport[0]); + arcsProperties.push_back(arcsPropertiesExport[1]); + arcsProperties.push_back(arcsPropertiesExport[2]); + } + return arcsProperties; +} + +} // namespace ptne diff --git a/PTN_Engine/TransitionsManager.h b/PTN_Engine/TransitionsManager.h new file mode 100755 index 0000000..ae8d5d3 --- /dev/null +++ b/PTN_Engine/TransitionsManager.h @@ -0,0 +1,94 @@ +/* + * This file is part of PTN Engine + * + * Copyright (c) 2017 Eduardo Valgôde + * Copyright (c) 2021 Kale Evans + * Copyright (c) 2024 Eduardo Valgôde + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#pragma once + +#include "PTN_Engine/Transition.h" +#include "PTN_Engine/ManagerBase.h" +#include + +namespace ptne +{ +using SharedPtrTransition = std::shared_ptr; + +//! +//! \brief The TransitionsManager class +//! +class TransitionsManager : private ManagerBase +{ +public: + //! + //! \brief contains + //! \param itemName + //! \return + //! + bool contains(const std::string &itemName) const; + + //! + //! \brief Insert a new transition. + //! \param transition + //! + void insert(std::shared_ptr transition); + + //! + //! \brief clear + //! + void clear(); + + //! + //! \brief collectEnabledTransitionsRandomly + //! \return A vector of weak pointers to the enabled transitions. + //! + std::vector> collectEnabledTransitionsRandomly() const; + + //! + //! \brief hasTransition + //! \param name + //! \return + //! + bool hasTransition(const std::string &name) const; + + //! + //! \brief getTransition + //! \param transitionName + //! \return + //! + SharedPtrTransition getTransition(const std::string &transitionName) const; + + //! + //! \brief getTransitionsProperties + //! \return + //! + std::vector getTransitionsProperties() const; + + //! + //! \brief getArcsProperties + //! \return + //! + std::vector> getArcsProperties() const; + +private: + //! + //! Shared mutex to synchronize the access to the items(readers-writer lock). + //! + mutable std::shared_mutex m_itemsMutex; +}; + +} // namespace ptne diff --git a/PTN_Engine/Utilities/DetectRepeated.h b/PTN_Engine/Utilities/DetectRepeated.h old mode 100644 new mode 100755 index a4e15b4..03b4568 --- a/PTN_Engine/Utilities/DetectRepeated.h +++ b/PTN_Engine/Utilities/DetectRepeated.h @@ -18,40 +18,33 @@ #include #include -#include #include -namespace ptne +namespace ptne::utility { -namespace utility +template +void detectRepeated(std::vector> items) { - namespace + auto equals = [](const std::weak_ptr &t, const std::weak_ptr &u) { - template - bool equals(const std::weak_ptr &t, const std::weak_ptr &u) - { - return !t.owner_before(u) && !u.owner_before(t); - } - } // namespace + return !t.owner_before(u) && !u.owner_before(t); + }; - template - void detectRepeated(std::vector> items) + std::ranges::sort(items.begin(), items.end(), std::owner_less>()); + + if (items.end() - std::unique(items.begin(), items.end(), equals) > 0) { - std::sort(items.begin(), items.end(), std::owner_less>()); - if (items.end() - std::unique(items.begin(), items.end(), equals) > 0) - { - throw E(); - } + throw E(); } +} - template - void detectRepeatedNames(std::vector items) +template +void detectRepeatedNames(std::vector items) +{ + std::ranges::sort(items.begin(), items.end()); + if (items.end() - std::unique(items.begin(), items.end()) > 0) { - std::sort(items.begin(), items.end()); - if (items.end() - std::unique(items.begin(), items.end()) > 0) - { - throw E(); - } + throw E(); } -} // namespace utility -} // namespace ptne +} +} // namespace ptne::utility diff --git a/PTN_Engine/include/PTN_Engine/IExporter.h b/PTN_Engine/include/PTN_Engine/IExporter.h deleted file mode 100644 index ead3329..0000000 --- a/PTN_Engine/include/PTN_Engine/IExporter.h +++ /dev/null @@ -1,51 +0,0 @@ -/* - * This file is part of PTN Engine - * - * Copyright (c) 2019-2023 Eduardo Valgôde - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#pragma once - -#include "PTN_Engine/Utilities/Explicit.h" -#include -#include - -namespace ptne -{ -class PTN_Engine; - -class DLL_PUBLIC IExporter -{ -public: - virtual ~IExporter() = default; - - virtual void exportActionsThreadOption(const std::string &actionsThreadOption) = 0; - - virtual void exportPlace(const std::string &name, - const std::string &tokens, - const std::string &isInput, - const std::string &onEnterAction, - const std::string &onExitAction) = 0; - - virtual void exportTransition(const std::vector> &activationPlaces, - const std::vector> &destinationPlaces, - const std::vector &activationConditions, - const std::vector &inhibitorPlaces, - const bool requireNoActionsInExecution) = 0; - - virtual void saveFile(const std::string &filePath) const = 0; -}; - -} // namespace ptne diff --git a/PTN_Engine/include/PTN_Engine/IImporter.h b/PTN_Engine/include/PTN_Engine/IImporter.h deleted file mode 100644 index 9ac58db..0000000 --- a/PTN_Engine/include/PTN_Engine/IImporter.h +++ /dev/null @@ -1,66 +0,0 @@ -/* - * This file is part of PTN Engine - * - * Copyright (c) 2019-2023 Eduardo Valgôde - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#pragma once - -#include "PTN_Engine/Utilities/Explicit.h" -#include -#include - -namespace ptne -{ -class PTN_Engine; - -class DLL_PUBLIC IImporter -{ -public: - virtual ~IImporter() = default; - - virtual std::string getActionsThreadOption() const = 0; - - using PlaceInfo = std::tuple; - - /*! - * \brief getPlaces - * \return - */ - virtual std::vector getPlaces() const = 0; - - - using TransitionInfo = std::tuple, // activation places - std::vector, // activation weights - std::vector, // destination places - std::vector, // destination weights - std::vector, // inhibitor places - std::vector, // activation conditions - bool // require no action in execution - >; - - /*! - * \brief getTransitions - * \return - */ - virtual std::vector getTransitions() const = 0; -}; - -} // namespace ptne diff --git a/PTN_Engine/include/PTN_Engine/PTN_Engine.h b/PTN_Engine/include/PTN_Engine/PTN_Engine.h old mode 100644 new mode 100755 index d312dd7..2b7c1c1 --- a/PTN_Engine/include/PTN_Engine/PTN_Engine.h +++ b/PTN_Engine/include/PTN_Engine/PTN_Engine.h @@ -1,7 +1,7 @@ /* * This file is part of PTN Engine * - * Copyright (c) 2017-2023 Eduardo Valgôde + * Copyright (c) 2017-2024 Eduardo Valgôde * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -28,245 +28,190 @@ namespace ptne { -class IExporter; -class IImporter; - using ConditionFunction = std::function; using ActionFunction = std::function; -//! Base class that implements the Petri net logic. /*! - * Base class that implements the Petri net logic. - * Using the pimpl idiom. - * \sa PTN_EngineImp + * \brief The PlaceProperties class */ -class DLL_PUBLIC PTN_Engine +struct DLL_PUBLIC ArcProperties final { -public: - enum class ACTIONS_THREAD_OPTION - { - SINGLE_THREAD, - EVENT_LOOP, - DETACHED, - JOB_QUEUE + enum class Type { + ACTIVATION, + DESTINATION, + BIDIRECTIONAL, + INHIBITOR, + //RESET, }; - using EventLoopSleepDuration = std::chrono::duration>; - - virtual ~PTN_Engine(); - - PTN_Engine(const PTN_Engine &) = delete; - PTN_Engine(PTN_Engine &&) = delete; - PTN_Engine &operator=(const PTN_Engine &) = delete; - PTN_Engine &operator=(PTN_Engine &&) = delete; - - /*! - * Create a new transition - * \param activationPlaces A vector with the names of the activation places. - * \param activationWeights A vector with the weights of each activation place. - * \param destinationPlaces A vector with the names of the destination places. - * \param destinationWeights A vector with the weights of each destination place. - * \param inhibitorPlaces Places that cannot have tokens to fire the transition. - * \param additionalConditions A vector with functors that return bool. - */ - void createTransition(const std::vector &activationPlaces, - const std::vector &activationWeights, - const std::vector &destinationPlaces, - const std::vector &destinationWeights, - const std::vector &inhibitorPlaces, - const std::vector &additionalConditions, - const bool requireNoActionsInExecution = false); - /*! - * Create a new transition - * \param activationPlaces A vector with the names of the activation places. - * \param activationWeights A vector with the weights of each activation place. - * \param destinationPlaces A vector with the names of the destination places. - * \param destinationWeights A vector with the weights of each destination place. - * \param inhibitorPlaces Places that cannot have tokens to fire the transition. - * \param additionalConditions A vector with names to additional conditions. + * \brief weight */ - void createTransition(const std::vector &activationPlaces, - const std::vector &activationWeights, - const std::vector &destinationPlaces, - const std::vector &destinationWeights, - const std::vector &inhibitorPlaces, - const std::vector &additionalConditions, - const bool requireNoActionsInExecution = false); + size_t weight = 1; /*! - * Create a new transition - * \param activationPlaces A vector with the names of the activation places. - * \param activationWeights A vector with the weights of each activation place. - * \param destinationPlaces A vector with the names of the destination places. - * \param destinationWeights A vector with the weights of each destination place. + * \brief placeName */ - void createTransition(const std::vector &activationPlaces, - const std::vector &activationWeights, - const std::vector &destinationPlaces, - const std::vector &destinationWeights, - const bool requireNoActionsInExecution = false); + std::string placeName; /*! - * Create a new transition - * \param activationPlaces A vector with the names of the activation places. - * \param activationWeights A vector with the weights of each activation place. - * \param destinationPlaces A vector with the names of the destination places. - * \param destinationWeights A vector with the weights of each destination place. - * \param inhibitorPlaces Places that cannot have tokens to fire the transition. + * \brief transitionName */ - void createTransition(const std::vector &activationPlaces, - const std::vector &activationWeights, - const std::vector &destinationPlaces, - const std::vector &destinationWeights, - const std::vector &inhibitorPlaces, - const bool requireNoActionsInExecution = false); + std::string transitionName; /*! - * Create a new transition - * \param activationPlaces A vector with the names of the activation places. - * \param activationWeights A vector with the weights of each activation place. - * \param destinationPlaces A vector with the names of the destination places. - * \param destinationWeights A vector with the weights of each destination place. - * \param additionalConditions A vector with functors that return bool. + * \brief type */ - void createTransition(const std::vector &activationPlaces, - const std::vector &activationWeights, - const std::vector &destinationPlaces, - const std::vector &destinationWeights, - const std::vector &additionalConditions, - const bool requireNoActionsInExecution = false); + Type type = { Type::ACTIVATION }; +}; +/*! + * \brief The TransitionProperties class + */ +struct DLL_PUBLIC TransitionProperties final +{ /*! - * Create a new transition - * \param activationPlaces A vector with the names of the activation places. - * \param destinationPlaces A vector with the names of the destination places. + * \brief Name and identifier of the transition */ - void createTransition(const std::vector &activationPlaces, - const std::vector &destinationPlaces, - const bool requireNoActionsInExecution = false); + std::string name; + + //! + //! \brief activationArcs + //! + std::vector activationArcs; + + //! + //! \brief destinationArcs + //! + std::vector destinationArcs; + + //! + //! \brief inhibitorArcs + //! + std::vector inhibitorArcs; + + //! + //! \brief additional conditions function names + //! + std::vector additionalConditionsNames; + + //! + //! \brief A vector with functions that return bool. + //! + std::vector additionalConditions; + + //! + //! \brief requireNoActionsInExecution + //! + bool requireNoActionsInExecution = false; +}; - /*! - * Create a new transition - * \param activationPlaces A vector with the names of the activation places. - * \param destinationPlaces A vector with the names of the destination places. - * \param inhibitorPlaces Places that cannot have tokens to fire the transition. - */ - void createTransition(const std::vector &activationPlaces, - const std::vector &destinationPlaces, - const std::vector &inhibitorPlaces, - const bool requireNoActionsInExecution = false); +/*! + * \brief The PlaceProperties class + */ +struct DLL_PUBLIC PlaceProperties final +{ + //! + //! \brief The name of the place. + //! + std::string name; + + //! + //! \brief The number of tokens to be initialized with. + //! + size_t initialNumberOfTokens = 0; + + //! + //! \brief The function to be called once a token enters the place. + //! + std::string onEnterActionFunctionName; + + //! + //! \brief The function to be called once a token leaves the place. + //! + std::string onExitActionFunctionName; + + //! + //! \brief onEnterAction + //! + ActionFunction onEnterAction = nullptr; + + //! + //! \brief onExitAction + //! + ActionFunction onExitAction = nullptr; + + //! + //! \brief A flag determining if this place can have tokens added manually. + //! + bool input = false; +}; - /*! - * Create a new transition - * \param activationPlaces A vector with the names of the activation places. - * \param destinationPlaces A vector with the names of the destination places. - * \param additionalConditions A vector with functors that return bool. - */ - void createTransition(const std::vector &activationPlaces, - const std::vector &destinationPlaces, - const std::vector &additionalConditions, - const bool requireNoActionsInExecution = false); +//! Base class that implements the Petri net logic. +/*! + * Base class that implements the Petri net logic. + * Using the pimpl idiom. + * \sa PTN_EngineImp + */ +class DLL_PUBLIC PTN_Engine +{ +public: + enum class ACTIONS_THREAD_OPTION + { + SINGLE_THREAD, + EVENT_LOOP, + DETACHED, + JOB_QUEUE + }; /*! - * Create a new transition - * \param activationPlaces A vector with the names of the activation places. - * \param destinationPlaces A vector with the names of the destination places. - * \param inhibitorPlaces Places that cannot have tokens to fire the transition. - * \param additionalConditions A vector with functors that return bool. + * \brief toACTIONS_THREAD_OPTION + * \param actionsThreadOptionStr + * \return */ - void createTransition(const std::vector &activationPlaces, - const std::vector &destinationPlaces, - const std::vector &inhibitorPlaces, - const std::vector &additionalConditions, - const bool requireNoActionsInExecution = false); + static ACTIONS_THREAD_OPTION toACTIONS_THREAD_OPTION(const std::string &actionsThreadOptionStr); /*! - * Create a new transition - * \param activationPlaces A vector with the names of the activation places. - * \param destinationPlaces A vector with the names of the destination places. - * \param inhibitorPlaces Places that cannot have tokens to fire the transition. - * \param additionalConditions A vector with names to additional conditions. + * \brief toString + * \param actionsThreadOption + * \return */ - void createTransition(const std::vector &activationPlaces, - const std::vector &destinationPlaces, - const std::vector &inhibitorPlaces, - const std::vector &additionalConditions, - const bool requireNoActionsInExecution = false); + static std::string toString(ACTIONS_THREAD_OPTION actionsThreadOption); - /*! - * Create a new place in the net. - * \param name The name of the place. - * \param initialNumberOfTokens The number of tokens to be initialized with. - * \param onEnterAction The function to be called once a token enters the place. - * \param onExitAction The function to be called once a token leaves the place. - * \param input A flag determining if this place can have tokens added manually. - */ - void createPlace(const std::string &name, - const size_t initialNumberOfTokens, - ActionFunction onEnterAction, - ActionFunction onExitAction, - const bool input = false); + using EventLoopSleepDuration = std::chrono::duration>; - /*! - * Create a new place in the net. - * \param name The name of the place. - * \param initialNumberOfTokens The number of tokens to be initialized with. - * \param onEnterAction Name of the function to be called once a token enters the place. - * \param onExitAction Name of the function functor to be called once a token leaves the place. - * \param input A flag determining if this place can have tokens added manually. - */ - void createPlace(const std::string &name, - const size_t initialNumberOfTokens, - const std::string &onEnterAction, - const std::string &onExitAction, - const bool input = false); + virtual ~PTN_Engine(); - /*! - * Create a new place in the net. - * \param name The name of the place. - * \param initialNumberOfTokens The number of tokens to be initialized with. - * \param input A flag determining if this place can have tokens added manually. - */ - void createPlace(const std::string &name, const size_t initialNumberOfTokens, const bool input = false); + PTN_Engine(const PTN_Engine &) = delete; + PTN_Engine(PTN_Engine &&) = delete; + PTN_Engine &operator=(const PTN_Engine &) = delete; + PTN_Engine &operator=(PTN_Engine &&) = delete; /*! - * Create a new place in the net. - * \param name The name of the place. - * \param initialNumberOfTokens The number of tokens to be initialized with. - * \param onEnterAction The function to be called once a token enters the place. - * \param input A flag determining if this place can have tokens added manually. + * \brief createTransition + * \param transitionProperties */ - void createPlace(const std::string &name, - const size_t initialNumberOfTokens, - ActionFunction onEnterAction, - const bool input = false); + void createTransition(const TransitionProperties &transitionProperties); /*! - * Create a new place in the net. - * \param name The name of the place. - * \param initialNumberOfTokens The number of tokens to be initialized with. - * \param onEnterAction Name of the function to be called once a token enters the place. - * \param input A flag determining if this place can have tokens added manually. + * \brief createPlace + * \param placeProperties */ - void createPlace(const std::string &name, - const size_t initialNumberOfTokens, - const std::string &onEnterAction, - const bool input = false); + void createPlace(const PlaceProperties &placeProperties); /*! * Register an action to be called by the Petri net. * \param name The name of the place. * \param action The function to be called once a token enters the place. */ - void registerAction(const std::string &name, ActionFunction action); + void registerAction(const std::string &name, const ActionFunction &action) const; /*! * Register a condition * \param name The name of the condition * \param conditions A function pointer to a condition. */ - void registerCondition(const std::string &name, ConditionFunction condition); + void registerCondition(const std::string &name, const ConditionFunction &condition) const; /*! * Start the petri net event loop. @@ -295,19 +240,6 @@ class DLL_PUBLIC PTN_Engine */ void printState(std::ostream &o) const; - /*! - * \brief Exports the Petri net using the provided exporter. - * \param exporter Object capable of exporting all important information about the Petri net's structure to - * some other format. - */ - void export_(IExporter &exporter) const; - - /*! - * \brief Imports the Petri net using the provided importer. - * \param importer Object containing all necessary information to create a new Petri net. - */ - void import(const IImporter &importer); - //! Constructor explicit PTN_Engine(ACTIONS_THREAD_OPTION actionsRuntimeThread = ACTIONS_THREAD_OPTION::JOB_QUEUE); @@ -340,6 +272,41 @@ class DLL_PUBLIC PTN_Engine */ EventLoopSleepDuration getEventLoopSleepDuration() const; + /*! + * \brief addArc + * \param arcProperties + */ + void addArc(const ArcProperties& arcProperties); + + /*! + * \brief addArc + * \param arcProperties + */ + void removeArc(const ArcProperties& arcProperties); + + /*! + * \brief clearNet + */ + void clearNet(); + + /*! + * \brief getPlacesProperties + * \return + */ + std::vector getPlacesProperties() const; + + /*! + * \brief getTransitionsProperties + * \return + */ + std::vector getTransitionsProperties() const; + + /*! + * \brief getArcsProperties + * \return + */ + std::vector> getArcsProperties() const; + private: class PTN_EngineImpProxy; diff --git a/PTN_Engine/include/PTN_Engine/PTN_Exception.h b/PTN_Engine/include/PTN_Engine/PTN_Exception.h old mode 100644 new mode 100755 index 44f1ed7..4091925 --- a/PTN_Engine/include/PTN_Engine/PTN_Exception.h +++ b/PTN_Engine/include/PTN_Engine/PTN_Exception.h @@ -94,24 +94,11 @@ class DLL_PUBLIC RepeatedPlaceException : public PTN_Exception * Exception to be thrown if the user tries to add a Condition to the net that with the name of an already * existing one. */ -class DLL_PUBLIC RepeatedActionException : public PTN_Exception +class DLL_PUBLIC RepeatedFunctionException : public PTN_Exception { public: - explicit RepeatedActionException(const std::string &name) - : PTN_Exception("Trying to add an already existing action: " + name + ".") - { - } -}; - -/*! - * Exception to be thrown if the user tries to add an Action to the net that with the name of an already - * existing one. - */ -class DLL_PUBLIC RepeatedConditionException : public PTN_Exception -{ -public: - explicit RepeatedConditionException(const std::string &name) - : PTN_Exception("Trying to add an already existing condition: " + name + ".") + explicit RepeatedFunctionException(const std::string &name) + : PTN_Exception("Trying to add an already existing function: " + name + ".") { } }; @@ -158,35 +145,11 @@ class DLL_PUBLIC OverflowException : public PTN_Exception } }; -/*! - * Exception to be thrown when the dimension of the vector containing the activation weights does not match - * the dimension of the vector containing the names of the activation places. - */ -class DLL_PUBLIC ActivationWeightDimensionException : public PTN_Exception -{ -public: - ActivationWeightDimensionException() - : PTN_Exception("The number of activation weights must be the same as the number of activation places.") - {} -}; - -/*! - * Exception to be thrown when the dimension of the vector containing the destination weights does not match - * the dimension of the vector containing the names of the destination places. - */ -class DLL_PUBLIC DestinationWeightDimensionException : public PTN_Exception -{ -public: - DestinationWeightDimensionException() - : PTN_Exception("The number of destination weights must be the same as the number of destination places.") - {} -}; - //! Exception to be thrown when the weight value is 0. class DLL_PUBLIC ZeroValueWeightException : public PTN_Exception { public: - ZeroValueWeightException() + ZeroValueWeightException() : PTN_Exception("Weights cannot be 0.") { } diff --git a/PTN_Engine/include/PTN_Engine/Utilities/Explicit.h b/PTN_Engine/include/PTN_Engine/Utilities/Explicit.h old mode 100644 new mode 100755 diff --git a/PTN_Engine/include/PTN_Engine/Utilities/LockWeakPtr.h b/PTN_Engine/include/PTN_Engine/Utilities/LockWeakPtr.h old mode 100644 new mode 100755 index 558ed6e..7713b69 --- a/PTN_Engine/include/PTN_Engine/Utilities/LockWeakPtr.h +++ b/PTN_Engine/include/PTN_Engine/Utilities/LockWeakPtr.h @@ -13,19 +13,19 @@ #pragma warning(disable : 4275) #endif +#include "PTN_Engine/PTN_Exception.h" #include "PTN_Engine/Utilities/Explicit.h" #include -#include -namespace +namespace ptne { //! Exception to be thrown if attempting to lock an expired pointer. -class DLL_PUBLIC ExpiredSharedPtrException : public std::runtime_error +class DLL_PUBLIC ExpiredSharedPtrException : public PTN_Exception { public: ExpiredSharedPtrException() - : runtime_error("Expired shared pointer.") + : PTN_Exception("Expired shared pointer.") { } }; diff --git a/Tests/BlackBoxTests/Fixtures/FixturePetriNet.cpp b/Tests/BlackBoxTests/Fixtures/FixturePetriNet.cpp old mode 100644 new mode 100755 index df007fd..4c7b9e8 --- a/Tests/BlackBoxTests/Fixtures/FixturePetriNet.cpp +++ b/Tests/BlackBoxTests/Fixtures/FixturePetriNet.cpp @@ -1,7 +1,7 @@ /* * This file is part of PTN Engine * - * Copyright (c) 2017-2023 Eduardo Valgôde + * Copyright (c) 2017-2024 Eduardo Valgôde * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -22,25 +22,23 @@ #include "Mocks/Dispatcher/RoundRobinPetriNet.h" #include "Mocks/Dispatcher/WeightedPetriNet.h" #include -#include using namespace std; using namespace std::chrono; -FixturePetriNet::FixturePetriNet() -{ -} +FixturePetriNet::FixturePetriNet() = default; -void FixturePetriNet::testRoundRobinState(const size_t expectedTokens[s_numberOfRoundRobinPlaces]) +void FixturePetriNet::testRoundRobinState( +const array &expectedTokens) const { - size_t tokens[s_numberOfRoundRobinPlaces]; + array tokens; // TODO // Dangerous(ugly) cast necessary only for testing. This does not need to exist within a normal use case. // Nonetheless it would be nice to fix it. IDispatcherPetriNet *dispatcherPetriNet = m_dispatcher.m_pPetriNet.get(); - if (RoundRobinPetriNet *roundRobinPetriNet = dynamic_cast(dispatcherPetriNet)) + if (const auto *roundRobinPetriNet = dynamic_cast(dispatcherPetriNet)) { tokens[0] = roundRobinPetriNet->getNumberOfTokens("InputWaitPackage"); tokens[1] = roundRobinPetriNet->getNumberOfTokens("WaitPackage"); @@ -58,16 +56,16 @@ void FixturePetriNet::testRoundRobinState(const size_t expectedTokens[s_numberOf } } -void FixturePetriNet::testFreeChoiceState(const size_t expectedTokens[s_numberOfFreeChoicePlaces]) +void FixturePetriNet::testFreeChoiceState(const array &expectedTokens) const { - size_t tokens[s_numberOfFreeChoicePlaces]; + array tokens; // TODO // Dangerous(ugly) cast necessary only for testing. This does not need to exist within a normal use case. // Nonetheless it would be nice to fix it. IDispatcherPetriNet *dispatcherPetriNet = m_dispatcher.m_pPetriNet.get(); - if (FreeChoicePetriNet *freeChoicePetriNet = dynamic_cast(dispatcherPetriNet)) + if (const auto *freeChoicePetriNet = dynamic_cast(dispatcherPetriNet)) { tokens[0] = freeChoicePetriNet->getNumberOfTokens("InputWaitPackage"); tokens[1] = freeChoicePetriNet->getNumberOfTokens("WaitPackage"); @@ -92,24 +90,24 @@ void FixturePetriNet::testFreeChoiceState(const size_t expectedTokens[s_numberOf EXPECT_TRUE(tokens[3] > 0 || tokens[5] > 0) << tokens[3] << " " << tokens[5]; - float bucket1 = tokens[3]; - float bucket2 = tokens[5]; + auto bucket1 = static_cast(tokens[3]); + auto bucket2 = static_cast(tokens[5]); float metric = abs(bucket1 - bucket2) / (bucket1 + bucket2); EXPECT_TRUE(metric < 0.1f) << metric; } -void FixturePetriNet::testWeightedState(const size_t expectedTokens[s_numberOfWeightedPlaces]) +void FixturePetriNet::testWeightedState(const array &expectedTokens) const { - size_t tokens[s_numberOfWeightedPlaces]; + array tokens; // TODO // Dangerous(ugly) cast necessary only for testing. This does not need to exist within a normal use case. // Nonetheless it would be nice to fix it. IDispatcherPetriNet *dispatcherPetriNet = m_dispatcher.m_pPetriNet.get(); - if (WeightedPetriNet *weightedPetriNet = dynamic_cast(dispatcherPetriNet)) + if (const auto *weightedPetriNet = dynamic_cast(dispatcherPetriNet)) { tokens[0] = weightedPetriNet->getNumberOfTokens("InputWaitPackage"); tokens[1] = weightedPetriNet->getNumberOfTokens("WaitPackage"); @@ -124,16 +122,16 @@ void FixturePetriNet::testWeightedState(const size_t expectedTokens[s_numberOfWe } } -void FixturePetriNet::testInhibitedState(const size_t expectedTokens[s_numberOfInhibitedNetPlaces]) +void FixturePetriNet::testInhibitedState(const array< size_t, s_numberOfInhibitedNetPlaces> &expectedTokens) const { - size_t tokens[s_numberOfInhibitedNetPlaces]; + array < size_t, s_numberOfInhibitedNetPlaces> tokens; // TODO // Dangerous(ugly) cast necessary only for testing. This does not need to exist within a normal use case. // Nonetheless it would be nice to fix it. IDispatcherPetriNet *dispatcherPetriNet = m_dispatcher.m_pPetriNet.get(); - if (InhibitedPetriNet *weightedPetriNet = dynamic_cast(dispatcherPetriNet)) + if (const auto *weightedPetriNet = dynamic_cast(dispatcherPetriNet)) { tokens[0] = weightedPetriNet->getNumberOfTokens("InputWaitPackage"); tokens[1] = weightedPetriNet->getNumberOfTokens("P1"); diff --git a/Tests/BlackBoxTests/Fixtures/FixturePetriNet.h b/Tests/BlackBoxTests/Fixtures/FixturePetriNet.h old mode 100644 new mode 100755 index 30c2015..5856323 --- a/Tests/BlackBoxTests/Fixtures/FixturePetriNet.h +++ b/Tests/BlackBoxTests/Fixtures/FixturePetriNet.h @@ -18,15 +18,15 @@ #pragma once -#include "Mocks/Dispatcher/Dispatcher.h" #include "gtest/gtest.h" -#include +#include "Mocks/Dispatcher/Dispatcher.h" +#include //! Fixture for testing a complete PTN net. -/*! - * To test a complete PTN Engine net from the users point of view. - * It only uses the public interface. - */ +//! +//! To test a complete PTN Engine net from the users point of view. +//! It only uses the public interface. +//! class FixturePetriNet : public ::testing::Test { public: @@ -45,29 +45,29 @@ class FixturePetriNet : public ::testing::Test //! Constructor. FixturePetriNet(); - /*! - * Tests the number of tokens in all places of the net. - * \param expectedTokens Expected number of tokens in each place. - */ - void testRoundRobinState(const size_t expectedTokens[s_numberOfRoundRobinPlaces]); + //! + //! Tests the number of tokens in all places of the net. + //! \param expectedTokens Expected number of tokens in each place. + //! + void testRoundRobinState(const std::array < size_t, s_numberOfRoundRobinPlaces> &expectedTokens) const; - /*! - * Tests the number of tokens in all places of the net. - * \param expectedTokens Expected number of tokens in each place. - */ - void testFreeChoiceState(const size_t expectedTokens[s_numberOfFreeChoicePlaces]); + //! + //! Tests the number of tokens in all places of the net. + //! \param expectedTokens Expected number of tokens in each place. + //! + void testFreeChoiceState(const std::array &expectedTokens) const; - /*! - * Tests the number of tokens in all places of the net. - * \param expectedTokens Expected number of tokens in each place. - */ - void testWeightedState(const size_t expectedTokens[s_numberOfWeightedPlaces]); + //! + //! Tests the number of tokens in all places of the net. + //! \param expectedTokens Expected number of tokens in each place. + //! + void testWeightedState(const std::array &expectedTokens) const; - /*! - * Tests the number of tokens in all places of the net. - * \param expectedTokens Expected number of tokens in each place. - */ - void testInhibitedState(const size_t expectedTokens[s_numberOfInhibitedNetPlaces]); + //! + //! Tests the number of tokens in all places of the net. + //! \param expectedTokens Expected number of tokens in each place. + //! + void testInhibitedState(const std::array &expectedTokens) const; //! Controller containing the PTN Engine net. Dispatcher m_dispatcher; diff --git a/Tests/BlackBoxTests/Mocks/Dispatcher/Dispatcher.cpp b/Tests/BlackBoxTests/Mocks/Dispatcher/Dispatcher.cpp old mode 100644 new mode 100755 index 285a214..1e332dd --- a/Tests/BlackBoxTests/Mocks/Dispatcher/Dispatcher.cpp +++ b/Tests/BlackBoxTests/Mocks/Dispatcher/Dispatcher.cpp @@ -1,7 +1,7 @@ /* * This file is part of PTN Engine * - * Copyright (c) 2017-2023 Eduardo Valgôde + * Copyright (c) 2017-2024 Eduardo Valgôde * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -22,26 +22,15 @@ #include "Mocks/Dispatcher/RoundRobinPetriNet.h" #include "Mocks/Dispatcher/WeightedPetriNet.h" -#include - using namespace std; Dispatcher::Dispatcher() -: m_pPetriNet(nullptr) -, m_resetCounter(false) -, m_isWaitingPackage(true) -, m_isUsingChannelA(false) -, m_isUsingChannelB(false) -, m_isChannelASelected(true) -, m_isChannelBSelected(false) { setRoundRobinMode(ptne::PTN_Engine::ACTIONS_THREAD_OPTION::EVENT_LOOP); } -Dispatcher::~Dispatcher() -{ -} +Dispatcher::~Dispatcher() = default; void Dispatcher::actionWaitPackage() { @@ -98,15 +87,6 @@ bool Dispatcher::resetCounter() const return m_resetCounter; } -bool Dispatcher::stillRunning() const -{ - if (m_pPetriNet) - { - return m_pPetriNet->stillRunning(); - } - return false; -} - void Dispatcher::setResetCounter(const bool resetCounter) { m_resetCounter = resetCounter; diff --git a/Tests/BlackBoxTests/Mocks/Dispatcher/Dispatcher.h b/Tests/BlackBoxTests/Mocks/Dispatcher/Dispatcher.h old mode 100644 new mode 100755 index 4eb65b1..7c31d60 --- a/Tests/BlackBoxTests/Mocks/Dispatcher/Dispatcher.h +++ b/Tests/BlackBoxTests/Mocks/Dispatcher/Dispatcher.h @@ -18,12 +18,10 @@ #pragma once +#include "Mocks/Dispatcher/IDispatcherPetriNet.h" #include "PTN_Engine/PTN_Engine.h" #include -//! Interface for Petri nets controlling the logic of this dispatcher -class IDispatcherPetriNet; - //! Alternately uses channel a and b to dispatch packages. class RoundRobinPetriNet; @@ -37,31 +35,21 @@ class WeightedPetriNet; class InhibitedPetriNet; //! Mock/fake controller class -/*! - * This is the controller of a package dispatcher that has two channels available: A and B. - * When a package arrives it can either use one or the other. - */ +//! +//! This is the controller of a package dispatcher that has two channels available: A and B. +//! When a package arrives it can either use one or the other. +//! class Dispatcher { -private: - //! For testing purposes only - friend class FixturePetriNet; - - //! Petri net that defines and controls the dispatcher business logic. - std::unique_ptr m_pPetriNet; - - //! If the counter can be reset. - bool m_resetCounter; - public: Dispatcher(); ~Dispatcher(); - /*! - * Set the flag to reset the counter. - * \param resetCounter Reset counter on or off. - */ + //! + //! Set the flag to reset the counter. + //! \param resetCounter Reset counter on or off. + //! void setResetCounter(const bool resetCounter); //! Puts a token in the input place and triggers the net to perform one dispatch operation. @@ -97,26 +85,26 @@ class Dispatcher //! Action to be performed when channel B is no longer selected. void onLeaveSelectChannelB(); - /*! - * If the counter can be reset. - * \return if the counter can be reset. - */ + //! + //! If the counter can be reset. + //! \return if the counter can be reset. + //! bool resetCounter() const; //! Flag that indicates it is waiting for a package. - bool m_isWaitingPackage; + bool m_isWaitingPackage = true; //! Flag that indicates it is using channel A. - bool m_isUsingChannelA; + bool m_isUsingChannelA = false; //! Flag that indicates it is using channel B. - bool m_isUsingChannelB; + bool m_isUsingChannelB = false; //! Flag that indicates channel A is selected. - bool m_isChannelASelected; + bool m_isChannelASelected = true; //! Flag that indicates channel B is selected. - bool m_isChannelBSelected; + bool m_isChannelBSelected = false; //! Select round robin Petri net. void setRoundRobinMode(ptne::PTN_Engine::ACTIONS_THREAD_OPTION); @@ -132,7 +120,15 @@ class Dispatcher void execute(); - bool stillRunning() const; - void stop(); + +private: + //! For testing purposes only + friend class FixturePetriNet; + + //! Petri net that defines and controls the dispatcher business logic. + std::unique_ptr m_pPetriNet = nullptr; + + //! If the counter can be reset. + bool m_resetCounter = false; }; diff --git a/Tests/BlackBoxTests/Mocks/Dispatcher/FreeChoicePetriNet.cpp b/Tests/BlackBoxTests/Mocks/Dispatcher/FreeChoicePetriNet.cpp old mode 100644 new mode 100755 index 2b50cf2..3aa7342 --- a/Tests/BlackBoxTests/Mocks/Dispatcher/FreeChoicePetriNet.cpp +++ b/Tests/BlackBoxTests/Mocks/Dispatcher/FreeChoicePetriNet.cpp @@ -1,7 +1,7 @@ /* * This file is part of PTN Engine * - * Copyright (c) 2017-2023 Eduardo Valgôde + * Copyright (c) 2017-2024 Eduardo Valgôde * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -26,61 +26,73 @@ FreeChoicePetriNet::FreeChoicePetriNet(Dispatcher &dispatcher, : PTN_Engine(actionsThreadOption) { // Places - createPlace("InputWaitPackage", 0, true); + PlaceProperties placeProperties; + placeProperties.name = "InputWaitPackage"; + placeProperties.input = true; - createPlace("WaitPackage", 1, bind(&Dispatcher::actionWaitPackage, &dispatcher), - bind(&Dispatcher::onLeaveWaitPackage, &dispatcher)); + createPlace({ .name="InputWaitPackage", + .input=true }); - createPlace("ChannelA", 0, bind(&Dispatcher::actionChannelA, &dispatcher), - bind(&Dispatcher::onLeaveChannelA, &dispatcher)); + createPlace({ .name="WaitPackage", + .initialNumberOfTokens=1, + .onEnterAction=bind(&Dispatcher::actionWaitPackage, &dispatcher), + .onExitAction=bind(&Dispatcher::onLeaveWaitPackage, &dispatcher) }); - createPlace("CounterA", 0); + createPlace({ .name="ChannelA", + .onEnterAction=bind(&Dispatcher::actionChannelA, &dispatcher), + .onExitAction=bind(&Dispatcher::onLeaveChannelA, &dispatcher) }); - createPlace("ChannelB", 0, bind(&Dispatcher::actionChannelB, &dispatcher), - bind(&Dispatcher::onLeaveChannelB, &dispatcher)); + createPlace({ .name="CounterA"}); - createPlace("CounterB", 0); + createPlace({ .name="ChannelB", + .onEnterAction=bind(&Dispatcher::actionChannelB, &dispatcher), + .onExitAction=bind(&Dispatcher::onLeaveChannelB, &dispatcher) }); - createPlace("PackageCounter", 0); + createPlace({ .name="CounterB" }); + + createPlace({ .name="PackageCounter" }); // Transitions // Use A - createTransition({ "InputWaitPackage", "WaitPackage" }, // activation - { "ChannelA", "PackageCounter" } // destination - ); + createTransition({ .name = "T1", + .activationArcs = { ArcProperties{ .placeName = "InputWaitPackage" }, + ArcProperties{ .placeName = "WaitPackage" } }, + .destinationArcs = { ArcProperties{ .placeName = "ChannelA" }, + ArcProperties{ .placeName = "PackageCounter" } } }); // Use B - createTransition({ "InputWaitPackage", "WaitPackage" }, // activation - { "ChannelB", "PackageCounter" } // destination - ); + createTransition({ .name = "T2", + .activationArcs = { ArcProperties{ .placeName = "InputWaitPackage" }, + ArcProperties{ .placeName = "WaitPackage" } }, + .destinationArcs = { ArcProperties{ .placeName = "ChannelB" }, + ArcProperties{ .placeName = "PackageCounter" } } }); // From A back to waiting a package - createTransition({ "ChannelA" }, // activation - { "WaitPackage", "CounterA" } // destination - ); + createTransition({ .name = "T3", + .activationArcs = { ArcProperties{ .placeName = "ChannelA" } }, + .destinationArcs = { ArcProperties{ .placeName = "WaitPackage" }, + ArcProperties{ .placeName = "CounterA" } } }); // From B back to waiting a package - createTransition({ "ChannelB" }, // activation - { "WaitPackage", "CounterB" } // destination - ); + createTransition({ .name = "T4", + .activationArcs = { ArcProperties{ .placeName = "ChannelB" } }, + .destinationArcs = { ArcProperties{ .placeName = "WaitPackage" }, + ArcProperties{ .placeName = "CounterB" } } }); // Reset Counters - createTransition({ "PackageCounter" }, // activation - {}, // destination - // additional conditions - { bind(&Dispatcher::resetCounter, &dispatcher) }); - - createTransition({ "CounterA" }, // activation - {}, // destination - // additional conditions - { bind(&Dispatcher::resetCounter, &dispatcher) }); - - createTransition({ "CounterB" }, // activation - {}, // destination - // additional conditions - { bind(&Dispatcher::resetCounter, &dispatcher) }); + createTransition({ .name = "T5", + .activationArcs = { ArcProperties{ .placeName = "PackageCounter" } }, + .additionalConditions={ bind(&Dispatcher::resetCounter, &dispatcher) } }); + + createTransition({ .name = "T6", + .activationArcs = { ArcProperties{ .placeName = "CounterA" } }, + .additionalConditions={ bind(&Dispatcher::resetCounter, &dispatcher) } }); + + createTransition({ .name = "T7", + .activationArcs = { ArcProperties{ .placeName = "CounterB" } }, + .additionalConditions={ bind(&Dispatcher::resetCounter, &dispatcher) } }); } void FreeChoicePetriNet::dispatch() diff --git a/Tests/BlackBoxTests/Mocks/Dispatcher/FreeChoicePetriNet.h b/Tests/BlackBoxTests/Mocks/Dispatcher/FreeChoicePetriNet.h old mode 100644 new mode 100755 index f7ea2bb..98136a5 --- a/Tests/BlackBoxTests/Mocks/Dispatcher/FreeChoicePetriNet.h +++ b/Tests/BlackBoxTests/Mocks/Dispatcher/FreeChoicePetriNet.h @@ -1,7 +1,7 @@ /* * This file is part of PTN Engine * - * Copyright (c) 2017-2023 Eduardo Valgôde + * Copyright (c) 2017-2024 Eduardo Valgôde * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -23,16 +23,16 @@ #include "PTN_Engine/PTN_Engine.h" //! Implements PTN Engine net defining a free choice behaviour. -/*! - * The behaviour is defined in the constructor. - */ +//! +//! The behaviour is defined in the constructor. +//! class FreeChoicePetriNet : public IDispatcherPetriNet, private ptne::PTN_Engine { // For testing purposes. friend class FixturePetriNet; public: - explicit FreeChoicePetriNet( + FreeChoicePetriNet( Dispatcher &dispatcher, PTN_Engine::ACTIONS_THREAD_OPTION actionsThreadOption = PTN_Engine::ACTIONS_THREAD_OPTION::EVENT_LOOP); diff --git a/Tests/BlackBoxTests/Mocks/Dispatcher/IDispatcherPetriNet.h b/Tests/BlackBoxTests/Mocks/Dispatcher/IDispatcherPetriNet.h old mode 100644 new mode 100755 index 5b094d1..ed43a10 --- a/Tests/BlackBoxTests/Mocks/Dispatcher/IDispatcherPetriNet.h +++ b/Tests/BlackBoxTests/Mocks/Dispatcher/IDispatcherPetriNet.h @@ -1,7 +1,7 @@ /* * This file is part of PTN Engine * - * Copyright (c) 2017-2023 Eduardo Valgôde + * Copyright (c) 2017-2024 Eduardo Valgôde * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -18,8 +18,6 @@ #pragma once -#include "Mocks/Dispatcher/Dispatcher.h" - //! Base class for a PTN Engine net that controls the dispatcher. class IDispatcherPetriNet { diff --git a/Tests/BlackBoxTests/Mocks/Dispatcher/InhibitedPetriNet.cpp b/Tests/BlackBoxTests/Mocks/Dispatcher/InhibitedPetriNet.cpp old mode 100644 new mode 100755 index d5771d7..a3d5d9d --- a/Tests/BlackBoxTests/Mocks/Dispatcher/InhibitedPetriNet.cpp +++ b/Tests/BlackBoxTests/Mocks/Dispatcher/InhibitedPetriNet.cpp @@ -1,7 +1,7 @@ /* * This file is part of PTN Engine * - * Copyright (c) 2017-2023 Eduardo Valgôde + * Copyright (c) 2017-2024 Eduardo Valgôde * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -25,40 +25,42 @@ InhibitedPetriNet::InhibitedPetriNet(PTN_Engine::ACTIONS_THREAD_OPTION actionsTh : PTN_Engine(actionsThreadOption) { // Places - createPlace("InputWaitPackage", 0, true); - - createPlace("P1", 1); - createPlace("P2", 1); - createPlace("P3", 1); - createPlace("P4", 0); - createPlace("P5", 0); + createPlace({ .name="InputWaitPackage", + .input=true }); + + createPlace({ .name="P1", + .initialNumberOfTokens=1}); + createPlace({ .name="P2", + .initialNumberOfTokens=1}); + createPlace({ .name="P3", + .initialNumberOfTokens=1}); + createPlace({ .name="P4", + .initialNumberOfTokens=0}); + createPlace({ .name="P5", + .initialNumberOfTokens=0}); // Transitions - - - createTransition({ "InputWaitPackage", "P1", "P3" }, // activation - { "P4" } // destination - ); - - - createTransition({ "P2" }, // activation - { "P5" }, // destination - { "P3" }, // inhibitor arc - false // require no actions in execution - ); - - - createTransition({ "InputWaitPackage", "P4" }, // activation - { "P1", "P3" }, // destination - false // require no actions in execution - ); - - - createTransition({ "P5" }, // activation - { "P2" }, // destination - { "P4" }, // inhibitor arc - false // require no actions in execution - ); + createTransition( {.name = "T1", + .activationArcs = { ArcProperties{ .placeName = "InputWaitPackage" }, + ArcProperties{ .placeName = "P1" }, + ArcProperties{ .placeName = "P3" } }, + .destinationArcs = {ArcProperties{ .placeName = "P4" } } }); + + createTransition({ .name = "T2", + .activationArcs = { ArcProperties{ .placeName = "P2" } }, + .destinationArcs = { ArcProperties{ .placeName = "P5" } }, + .inhibitorArcs = { ArcProperties{ .placeName = "P3" } } }); + + createTransition({ .name = "T3", + .activationArcs = { ArcProperties{ .placeName = "InputWaitPackage" }, + ArcProperties{ .placeName = "P4" } }, + .destinationArcs = { ArcProperties{ .placeName = "P1" }, + ArcProperties{ .placeName = "P3" } } }); + + createTransition({ .name = "T4", + .activationArcs = { ArcProperties{ .placeName = "P5" } }, + .destinationArcs = { ArcProperties{ .placeName = "P2" } }, + .inhibitorArcs = { ArcProperties{ .placeName = "P4" } } }); } void InhibitedPetriNet::dispatch() diff --git a/Tests/BlackBoxTests/Mocks/Dispatcher/InhibitedPetriNet.h b/Tests/BlackBoxTests/Mocks/Dispatcher/InhibitedPetriNet.h old mode 100644 new mode 100755 index 9374ef5..10a0e60 --- a/Tests/BlackBoxTests/Mocks/Dispatcher/InhibitedPetriNet.h +++ b/Tests/BlackBoxTests/Mocks/Dispatcher/InhibitedPetriNet.h @@ -18,14 +18,13 @@ #pragma once -#include "Mocks/Dispatcher/Dispatcher.h" #include "Mocks/Dispatcher/IDispatcherPetriNet.h" #include "PTN_Engine/PTN_Engine.h" //! Implements PTN Engine net with a Petri net that uses the inhibitor arc. -/*! - * The behaviour is defined in the constructor. - */ +//! +//! The behaviour is defined in the constructor. +//! class InhibitedPetriNet : public IDispatcherPetriNet, private ptne::PTN_Engine { // For testing purposes. diff --git a/Tests/BlackBoxTests/Mocks/Dispatcher/RoundRobinPetriNet.cpp b/Tests/BlackBoxTests/Mocks/Dispatcher/RoundRobinPetriNet.cpp old mode 100644 new mode 100755 index de7296d..cb80cac --- a/Tests/BlackBoxTests/Mocks/Dispatcher/RoundRobinPetriNet.cpp +++ b/Tests/BlackBoxTests/Mocks/Dispatcher/RoundRobinPetriNet.cpp @@ -1,7 +1,7 @@ /* * This file is part of PTN Engine * - * Copyright (c) 2017-2023 Eduardo Valgôde + * Copyright (c) 2017-2024 Eduardo Valgôde * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -26,52 +26,68 @@ RoundRobinPetriNet::RoundRobinPetriNet(Dispatcher &dispatcher, : PTN_Engine(actionsThreadOption) { // Places - createPlace("InputWaitPackage", 0, true); + createPlace({ .name="InputWaitPackage", + .input=true }); - createPlace("WaitPackage", 1, bind(&Dispatcher::actionWaitPackage, &dispatcher), - bind(&Dispatcher::onLeaveWaitPackage, &dispatcher)); + createPlace({ .name="WaitPackage", + .initialNumberOfTokens=1, + .onEnterAction=bind_front(&Dispatcher::actionWaitPackage, &dispatcher), + .onExitAction=bind_front(&Dispatcher::onLeaveWaitPackage, &dispatcher) }); - createPlace("ChannelA", 0, bind(&Dispatcher::actionChannelA, &dispatcher), - bind(&Dispatcher::onLeaveChannelA, &dispatcher)); + createPlace({ .name="ChannelA", + .onEnterAction=bind_front(&Dispatcher::actionChannelA, &dispatcher), + .onExitAction=bind_front(&Dispatcher::onLeaveChannelA, &dispatcher) }); - createPlace("ChannelB", 0, bind(&Dispatcher::actionChannelB, &dispatcher), - bind(&Dispatcher::onLeaveChannelB, &dispatcher)); + createPlace({ .name="ChannelB", + .onEnterAction=bind_front(&Dispatcher::actionChannelB, &dispatcher), + .onExitAction=bind_front(&Dispatcher::onLeaveChannelB, &dispatcher) }); - createPlace("SelectA", 1, bind(&Dispatcher::actionSelectA, &dispatcher), - bind(&Dispatcher::onLeaveSelectChannelA, &dispatcher)); + createPlace({ .name="SelectA", + .initialNumberOfTokens=1, + .onEnterAction=bind_front(&Dispatcher::actionSelectA, &dispatcher), + .onExitAction=bind_front(&Dispatcher::onLeaveSelectChannelA, &dispatcher) }); - createPlace("SelectB", 0, bind(&Dispatcher::actionSelectB, &dispatcher), - bind(&Dispatcher::onLeaveSelectChannelB, &dispatcher)); + createPlace({ .name="SelectB", + .onEnterAction=bind_front(&Dispatcher::actionSelectB, &dispatcher), + .onExitAction=bind_front(&Dispatcher::onLeaveSelectChannelB, &dispatcher) }); - createPlace("PackageCounter", 0); + createPlace({ .name="PackageCounter" }); // Transitions // Use A - createTransition({ "InputWaitPackage", "WaitPackage", "SelectA" }, // activation - { "ChannelA", "PackageCounter" } // destination - ); + createTransition({ .name = "T1", + .activationArcs = { ArcProperties{ .placeName = "InputWaitPackage" }, + ArcProperties{ .placeName = "WaitPackage" }, + ArcProperties{ .placeName = "SelectA" } }, + .destinationArcs = { ArcProperties{ .placeName = "ChannelA" }, + ArcProperties{ .placeName = "PackageCounter" } } }); // Use B - createTransition({ "InputWaitPackage", "WaitPackage", "SelectB" }, // activation - { "ChannelB", "PackageCounter" } // destination - ); + createTransition({ .name = "T2", + .activationArcs = { ArcProperties{ .placeName = "InputWaitPackage" }, + ArcProperties{ .placeName = "WaitPackage" }, + ArcProperties{ .placeName = "SelectB" } }, + .destinationArcs = { ArcProperties{ .placeName = "ChannelB" }, + ArcProperties{ .placeName = "PackageCounter" } } }); // Switch to A - createTransition({ "ChannelA" }, // activation - { "SelectB", "WaitPackage" } // destination - ); + createTransition({ .name = "T3", + .activationArcs = { ArcProperties{ .placeName = "ChannelA" } }, + .destinationArcs = { ArcProperties{ .placeName = "SelectB" }, + ArcProperties{ .placeName = "WaitPackage" } } }); // Switch to B - createTransition({ "ChannelB" }, // activation - { "SelectA", "WaitPackage" } // destination - ); + createTransition({ .name = "T4", + .activationArcs = { ArcProperties{ .placeName = "ChannelB" } }, + .destinationArcs = { ArcProperties{ .placeName = "SelectA" }, + ArcProperties{ .placeName = "WaitPackage" } } }); // Reset Counter - createTransition({ "PackageCounter" }, // activation - {}, // destination - { bind(&Dispatcher::resetCounter, &dispatcher) }); + createTransition({ .name = "T5", + .activationArcs = { ArcProperties{ .placeName = "PackageCounter" } }, + .additionalConditions={ bind_front(&Dispatcher::resetCounter, &dispatcher) } }); } void RoundRobinPetriNet::dispatch() diff --git a/Tests/BlackBoxTests/Mocks/Dispatcher/RoundRobinPetriNet.h b/Tests/BlackBoxTests/Mocks/Dispatcher/RoundRobinPetriNet.h old mode 100644 new mode 100755 index d853904..e45838b --- a/Tests/BlackBoxTests/Mocks/Dispatcher/RoundRobinPetriNet.h +++ b/Tests/BlackBoxTests/Mocks/Dispatcher/RoundRobinPetriNet.h @@ -23,9 +23,9 @@ #include "PTN_Engine/PTN_Engine.h" //! Implements PTN Engine net defining a round robin behaviour. -/*! - * The behaviour is defined in the constructor. - */ +//! +//! The behaviour is defined in the constructor. +//! class RoundRobinPetriNet : public IDispatcherPetriNet, public ptne::PTN_Engine { // For testing purposes. diff --git a/Tests/BlackBoxTests/Mocks/Dispatcher/WeightedPetriNet.cpp b/Tests/BlackBoxTests/Mocks/Dispatcher/WeightedPetriNet.cpp old mode 100644 new mode 100755 index ae6b76a..0d27b95 --- a/Tests/BlackBoxTests/Mocks/Dispatcher/WeightedPetriNet.cpp +++ b/Tests/BlackBoxTests/Mocks/Dispatcher/WeightedPetriNet.cpp @@ -1,7 +1,7 @@ /* * This file is part of PTN Engine * - * Copyright (c) 2017-2023 Eduardo Valgôde + * Copyright (c) 2017-2024 Eduardo Valgôde * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -17,6 +17,7 @@ */ #include "Mocks/Dispatcher/WeightedPetriNet.h" +#include "PTN_Engine/PTN_Engine.h" using namespace ptne; using namespace std; @@ -25,21 +26,20 @@ WeightedPetriNet::WeightedPetriNet(PTN_Engine::ACTIONS_THREAD_OPTION actionsThre : PTN_Engine(actionsThreadOption) { // Places - createPlace("InputWaitPackage", 0, true); - createPlace("WaitPackage", 0); - createPlace("ChannelA", 0); - createPlace("ChannelB", 0); - + createPlace({.name="InputWaitPackage", .input=true}); + createPlace({.name="WaitPackage"}); + createPlace({.name="ChannelA"}); + createPlace({.name="ChannelB"}); // Transitions - - createTransition({ "InputWaitPackage" }, // activation - vector{ 1 }, { "WaitPackage" }, // destination - vector{ 1 }); - - createTransition({ "WaitPackage" }, // activation - vector{ 3 }, { "ChannelA", "ChannelB" }, // destination - vector{ 4, 10 }); + createTransition({ .name = "T1", + .activationArcs = { ArcProperties{ .weight = 1, .placeName = "InputWaitPackage" } }, + .destinationArcs = { ArcProperties{ .weight = 1 , .placeName = "WaitPackage"} } }); + + createTransition({ .name = "T2", + .activationArcs = { ArcProperties{ .weight = 3, .placeName = "WaitPackage" } }, + .destinationArcs = { ArcProperties{ .weight = 4, .placeName = "ChannelA" }, + ArcProperties{ .weight = 10, .placeName = "ChannelB" } } }); } void WeightedPetriNet::dispatch() diff --git a/Tests/BlackBoxTests/Mocks/Dispatcher/WeightedPetriNet.h b/Tests/BlackBoxTests/Mocks/Dispatcher/WeightedPetriNet.h old mode 100644 new mode 100755 index b76b2a8..3d0549a --- a/Tests/BlackBoxTests/Mocks/Dispatcher/WeightedPetriNet.h +++ b/Tests/BlackBoxTests/Mocks/Dispatcher/WeightedPetriNet.h @@ -18,14 +18,13 @@ #pragma once -#include "Mocks/Dispatcher/Dispatcher.h" #include "Mocks/Dispatcher/IDispatcherPetriNet.h" #include "PTN_Engine/PTN_Engine.h" //! Implements PTN Engine net with a Petri net with different weights. -/*! - * The behaviour is defined in the constructor. - */ +//! +//! The behaviour is defined in the constructor. +//! class WeightedPetriNet : public IDispatcherPetriNet, public ptne::PTN_Engine { // For testing purposes. diff --git a/Tests/BlackBoxTests/Mocks/RegisteredFunctions/Controller.cpp b/Tests/BlackBoxTests/Mocks/RegisteredFunctions/Controller.cpp old mode 100644 new mode 100755 index 2fc3dd1..2e9150d --- a/Tests/BlackBoxTests/Mocks/RegisteredFunctions/Controller.cpp +++ b/Tests/BlackBoxTests/Mocks/RegisteredFunctions/Controller.cpp @@ -1,7 +1,7 @@ /* * This file is part of PTN Engine * - * Copyright (c) 2018-2023 Eduardo Valgôde + * Copyright (c) 2018-2024 Eduardo Valgôde * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -17,14 +17,13 @@ */ #include "Mocks/RegisteredFunctions/Controller.h" -#include using namespace std; -std::mutex Controller::s_mut; +mutex Controller::s_mut; Controller::Controller() -: m_petriNet(*this) +: m_menuStateMachine(*this) { } @@ -34,30 +33,30 @@ Controller::~Controller() void Controller::initialize() { - m_petriNet.registerCallbacks(); - m_petriNet.createPetriNetStructure(); + m_menuStateMachine.registerCallbacks(); + m_menuStateMachine.createPetriNetStructure(); } void Controller::startExecution() { - m_petriNet.addExecuteP0(); + m_menuStateMachine.addExecuteP0(); } string Controller::getSomeString() const { - std::lock_guard g(s_mut); + lock_guard g(s_mut); return m_someString; } void Controller::actionPlace1() { - std::lock_guard g(s_mut); + lock_guard g(s_mut); m_someString = "actionPlace1"; } void Controller::actionPlace2() { - std::lock_guard g(s_mut); + lock_guard g(s_mut); m_someString = "actionPlace2"; } @@ -76,17 +75,12 @@ bool Controller::externalCondition3() const return false; } -bool Controller::isEventLoopRunning() const +size_t Controller::getNumberOfTokens(const string &placeName) const { - return m_petriNet.isEventLoopRunning(); -} - -size_t Controller::getNumberOfTokens(const std::string &placeName) const -{ - return m_petriNet.getNumberOfTokens(placeName); + return m_menuStateMachine.getNumberOfTokens(placeName); } void Controller::stop() { - m_petriNet.stop(); + m_menuStateMachine.stop(); } diff --git a/Tests/BlackBoxTests/Mocks/RegisteredFunctions/Controller.h b/Tests/BlackBoxTests/Mocks/RegisteredFunctions/Controller.h old mode 100644 new mode 100755 index 7109979..37a2291 --- a/Tests/BlackBoxTests/Mocks/RegisteredFunctions/Controller.h +++ b/Tests/BlackBoxTests/Mocks/RegisteredFunctions/Controller.h @@ -42,14 +42,12 @@ class Controller std::string getSomeString() const; - bool isEventLoopRunning() const; - size_t getNumberOfTokens(const std::string &placeName) const; void stop(); private: - RegisteredFunctionsPN m_petriNet; + RegisteredFunctionsPN m_menuStateMachine; void actionPlace1(); diff --git a/Tests/BlackBoxTests/Mocks/RegisteredFunctions/RegisteredFunctionsPN.cpp b/Tests/BlackBoxTests/Mocks/RegisteredFunctions/RegisteredFunctionsPN.cpp old mode 100644 new mode 100755 index 2adeeff..b29a3d8 --- a/Tests/BlackBoxTests/Mocks/RegisteredFunctions/RegisteredFunctionsPN.cpp +++ b/Tests/BlackBoxTests/Mocks/RegisteredFunctions/RegisteredFunctionsPN.cpp @@ -1,7 +1,7 @@ /* * This file is part of PTN Engine * - * Copyright (c) 2018-2023 Eduardo Valgôde + * Copyright (c) 2018-2024 Eduardo Valgôde * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -18,12 +18,14 @@ #include "Mocks/RegisteredFunctions/RegisteredFunctionsPN.h" #include "Mocks/RegisteredFunctions/Controller.h" +#include "PTN_Engine/PTN_Engine.h" using namespace std; +using namespace ptne; RegisteredFunctionsPN::RegisteredFunctionsPN(Controller &controller, - PTN_Engine::ACTIONS_THREAD_OPTION actionsThreadOption) -: ptne::PTN_Engine(actionsThreadOption) + PTN_Engine::ACTIONS_THREAD_OPTION actionsThreadOption) +: PTN_Engine(actionsThreadOption) , m_controller(controller) { } @@ -39,12 +41,21 @@ void RegisteredFunctionsPN::registerCallbacks() void RegisteredFunctionsPN::createPetriNetStructure() { - createPlace("P0", 0, true); - createPlace("P1", 0, "actionPlace1", false); - createPlace("P2", 0, "actionPlace2", false); + createPlace({ .name="P0", + .input=true }); + createPlace({ .name="P1", + .onEnterActionFunctionName="actionPlace1" }); + createPlace({ .name="P2", + .onEnterActionFunctionName="actionPlace2" }); - createTransition({ "P0" }, { "P1" }, {}, vector{ "externalCondition1", "externalCondition2" }); - createTransition({ "P0" }, { "P2" }, {}, vector{ "externalCondition3" }); + createTransition({ .name = "T1", + .activationArcs = { ArcProperties{ .placeName = "P0" } }, + .destinationArcs = { ArcProperties{ .placeName = "P1" } }, + .additionalConditionsNames = { "externalCondition1", "externalCondition2" } }); + createTransition({ .name = "T2", + .activationArcs = { ArcProperties{ .placeName = "P0" } }, + .destinationArcs = { ArcProperties{ .placeName = "P2" } }, + .additionalConditionsNames = { "externalCondition3" } }); } void RegisteredFunctionsPN::addExecuteP0() @@ -53,12 +64,7 @@ void RegisteredFunctionsPN::addExecuteP0() execute(); } -bool RegisteredFunctionsPN::isEventLoopRunning() const -{ - return PTN_Engine::isEventLoopRunning(); -} - -size_t RegisteredFunctionsPN::getNumberOfTokens(const std::string &placeName) const +size_t RegisteredFunctionsPN::getNumberOfTokens(const string &placeName) const { return PTN_Engine::getNumberOfTokens(placeName); } diff --git a/Tests/BlackBoxTests/Mocks/RegisteredFunctions/RegisteredFunctionsPN.h b/Tests/BlackBoxTests/Mocks/RegisteredFunctions/RegisteredFunctionsPN.h old mode 100644 new mode 100755 index f2ecfb6..abd3e2f --- a/Tests/BlackBoxTests/Mocks/RegisteredFunctions/RegisteredFunctionsPN.h +++ b/Tests/BlackBoxTests/Mocks/RegisteredFunctions/RegisteredFunctionsPN.h @@ -39,7 +39,5 @@ class RegisteredFunctionsPN : public ptne::PTN_Engine Controller &m_controller; - bool isEventLoopRunning() const; - size_t getNumberOfTokens(const std::string &placeName) const; }; diff --git a/Tests/BlackBoxTests/Mocks/Simple/SimpleController.cpp b/Tests/BlackBoxTests/Mocks/Simple/SimpleController.cpp old mode 100644 new mode 100755 index e73d745..a6263b1 --- a/Tests/BlackBoxTests/Mocks/Simple/SimpleController.cpp +++ b/Tests/BlackBoxTests/Mocks/Simple/SimpleController.cpp @@ -26,14 +26,12 @@ SimpleController::SimpleController() { } -SimpleController::~SimpleController() -{ -} +SimpleController::~SimpleController() = default; void SimpleController::doSomethingConcurrently(const size_t numberOfThreads) { m_collectedThreadIds.clear(); - auto f = [&]() -> void + auto f = [this]() { this_thread::sleep_for(chrono::milliseconds(5)); for (int i = 0; i < 10; ++i) @@ -42,15 +40,10 @@ void SimpleController::doSomethingConcurrently(const size_t numberOfThreads) } }; - vector threads; + vector threads; for (size_t i = 0; i < numberOfThreads; ++i) { - threads.emplace_back(thread(f)); - } - - for (auto &t : threads) - { - t.join(); + threads.emplace_back(f); } } @@ -64,7 +57,7 @@ void SimpleController::collectThreadId() m_collectedThreadIds.insert(this_thread::get_id()); } -size_t SimpleController::getNumberOfTokens(const std::string &placeName) const +size_t SimpleController::getNumberOfTokens(const string &placeName) const { return m_petriNet.getNumberOfTokens(placeName); } diff --git a/Tests/BlackBoxTests/Mocks/Simple/SimpleController.h b/Tests/BlackBoxTests/Mocks/Simple/SimpleController.h old mode 100644 new mode 100755 index c94a289..130df8a --- a/Tests/BlackBoxTests/Mocks/Simple/SimpleController.h +++ b/Tests/BlackBoxTests/Mocks/Simple/SimpleController.h @@ -18,10 +18,9 @@ #pragma once -#include -#include -#include #include "Mocks/Simple/SimplePetriNet.h" +#include +#include //! A very simple controller with a very simple petri net. class SimpleController diff --git a/Tests/BlackBoxTests/Mocks/Simple/SimplePetriNet.cpp b/Tests/BlackBoxTests/Mocks/Simple/SimplePetriNet.cpp old mode 100644 new mode 100755 index 04e1bfe..8987325 --- a/Tests/BlackBoxTests/Mocks/Simple/SimplePetriNet.cpp +++ b/Tests/BlackBoxTests/Mocks/Simple/SimplePetriNet.cpp @@ -1,7 +1,7 @@ /* * This file is part of PTN Engine * - * Copyright (c) 2018-2023 Eduardo Valgôde + * Copyright (c) 2018-2024 Eduardo Valgôde * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -20,15 +20,20 @@ #include "Mocks/Simple/SimpleController.h" using namespace std; +using namespace ptne; SimplePetriNet::SimplePetriNet(SimpleController &controller) -: PTN_Engine(ptne::PTN_Engine::ACTIONS_THREAD_OPTION::EVENT_LOOP) +: PTN_Engine(PTN_Engine::ACTIONS_THREAD_OPTION::EVENT_LOOP) { - createPlace("P1", 0, bind(&SimpleController::collectThreadId, &controller), true); - createPlace("P2", 0); + createPlace({ .name="P1", + .onEnterAction=bind(&SimpleController::collectThreadId, &controller), + .input=true }); + createPlace({ .name="P2" }); - createTransition({ "P1" }, { "P2" }); - createTransition({ "P2" }, {}); + createTransition({ .name = "T1", + .activationArcs = { ArcProperties{ .placeName = "P1" } }, + .destinationArcs = { ArcProperties{ .placeName = "P2" } } }); + createTransition({ .name = "T2", .activationArcs = { ArcProperties{ .placeName = "P2" } } }); } void SimplePetriNet::addExecuteP1() @@ -36,7 +41,7 @@ void SimplePetriNet::addExecuteP1() incrementInputPlace("P1"); } -size_t SimplePetriNet::getNumberOfTokens(const std::string &placeName) const +size_t SimplePetriNet::getNumberOfTokens(const string &placeName) const { return ptne::PTN_Engine::getNumberOfTokens(placeName); } diff --git a/Tests/BlackBoxTests/Mocks/Simple/SimplePetriNet.h b/Tests/BlackBoxTests/Mocks/Simple/SimplePetriNet.h old mode 100644 new mode 100755 index 1f330bf..994d2cf --- a/Tests/BlackBoxTests/Mocks/Simple/SimplePetriNet.h +++ b/Tests/BlackBoxTests/Mocks/Simple/SimplePetriNet.h @@ -20,7 +20,6 @@ #include "PTN_Engine/PTN_Engine.h" - class SimpleController; class SimplePetriNet : public ptne::PTN_Engine diff --git a/Tests/BlackBoxTests/Tests/TestPetriNet.cpp b/Tests/BlackBoxTests/Tests/TestPetriNet.cpp old mode 100644 new mode 100755 index 33c1690..7086980 --- a/Tests/BlackBoxTests/Tests/TestPetriNet.cpp +++ b/Tests/BlackBoxTests/Tests/TestPetriNet.cpp @@ -1,7 +1,7 @@ /* * This file is part of PTN Engine * - * Copyright (c) 2017-2023 Eduardo Valgôde + * Copyright (c) 2017-2024 Eduardo Valgôde * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -17,16 +17,18 @@ */ #include "Fixtures/FixturePetriNet.h" +#include "gtest/gtest.h" #include "Mocks/RegisteredFunctions/Controller.h" #include "Mocks/Simple/SimpleController.h" +#include "PTN_Engine/PTN_Engine.h" #include "PTN_Engine/PTN_Exception.h" -#include "gtest/gtest.h" -#include -#include +#include #include +#include - +using namespace std; using namespace std::chrono; +using namespace ptne; TEST_F(FixturePetriNet, RoundRobin_1) { @@ -41,12 +43,12 @@ TEST_F(FixturePetriNet, RoundRobin_1) // m_plSelectA; // m_plSelectB; // m_plPackageCounter; - size_t expectedState[7] = { 0, 1, 0, 0, 1, 0, 0 }; + array expectedState{ 0, 1, 0, 0, 1, 0, 0 }; testRoundRobinState(expectedState); m_dispatcher.dispatch(); - std::this_thread::sleep_for(10ms); + this_thread::sleep_for(10ms); EXPECT_TRUE(m_dispatcher.m_isWaitingPackage && m_dispatcher.m_isChannelBSelected && (!m_dispatcher.m_isChannelASelected)); @@ -56,7 +58,7 @@ TEST_F(FixturePetriNet, RoundRobin_1) testRoundRobinState(expectedState); m_dispatcher.dispatch(); - std::this_thread::sleep_for(10ms); + this_thread::sleep_for(10ms); EXPECT_TRUE(m_dispatcher.m_isWaitingPackage && m_dispatcher.m_isChannelASelected && (!m_dispatcher.m_isChannelBSelected)); @@ -67,7 +69,7 @@ TEST_F(FixturePetriNet, RoundRobin_1) m_dispatcher.setResetCounter(true); m_dispatcher.dispatch(); - std::this_thread::sleep_for(10ms); + this_thread::sleep_for(10ms); expectedState[4] = 0; // m_plSelectA; expectedState[5] = 1; // m_plSelectB; expectedState[6] = 0; // m_plPackageCounter; @@ -81,19 +83,12 @@ TEST_F(FixturePetriNet, RoundRobin_1_detached) EXPECT_EQ(true, m_dispatcher.m_isWaitingPackage && m_dispatcher.m_isChannelASelected && (!m_dispatcher.m_isChannelBSelected)); - // m_plInputWaitPackage; - // m_plWaitPackage; - // m_plChannelA; - // m_plChannelB; - // m_plSelectA; - // m_plSelectB; - // m_plPackageCounter; - size_t expectedState[7] = { 0, 1, 0, 0, 1, 0, 0 }; + array expectedState { 0, 1, 0, 0, 1, 0, 0 }; testRoundRobinState(expectedState); m_dispatcher.dispatch(); - std::this_thread::sleep_for(10ms); + this_thread::sleep_for(10ms); EXPECT_TRUE(m_dispatcher.m_isWaitingPackage && m_dispatcher.m_isChannelBSelected && (!m_dispatcher.m_isChannelASelected)); @@ -103,7 +98,7 @@ TEST_F(FixturePetriNet, RoundRobin_1_detached) testRoundRobinState(expectedState); m_dispatcher.dispatch(); - std::this_thread::sleep_for(10ms); + this_thread::sleep_for(10ms); EXPECT_TRUE(m_dispatcher.m_isWaitingPackage && m_dispatcher.m_isChannelASelected && (!m_dispatcher.m_isChannelBSelected)); @@ -114,7 +109,7 @@ TEST_F(FixturePetriNet, RoundRobin_1_detached) m_dispatcher.setResetCounter(true); m_dispatcher.dispatch(); - std::this_thread::sleep_for(10ms); + this_thread::sleep_for(10ms); expectedState[4] = 0; // m_plSelectA; expectedState[5] = 1; // m_plSelectB; expectedState[6] = 0; // m_plPackageCounter; @@ -135,12 +130,12 @@ TEST_F(FixturePetriNet, RoundRobin_1_continuous2) // m_plSelectA; // m_plSelectB; // m_plPackageCounter; - size_t expectedState[7] = { 0, 1, 0, 0, 1, 0, 0 }; + array expectedState { 0, 1, 0, 0, 1, 0, 0 }; testRoundRobinState(expectedState); m_dispatcher.dispatch(); - std::this_thread::sleep_for(10ms); + this_thread::sleep_for(10ms); EXPECT_TRUE(m_dispatcher.m_isWaitingPackage && m_dispatcher.m_isChannelBSelected && (!m_dispatcher.m_isChannelASelected)); @@ -150,7 +145,7 @@ TEST_F(FixturePetriNet, RoundRobin_1_continuous2) testRoundRobinState(expectedState); m_dispatcher.dispatch(); - std::this_thread::sleep_for(10ms); + this_thread::sleep_for(10ms); EXPECT_TRUE(m_dispatcher.m_isWaitingPackage && m_dispatcher.m_isChannelASelected && (!m_dispatcher.m_isChannelBSelected)); @@ -161,7 +156,7 @@ TEST_F(FixturePetriNet, RoundRobin_1_continuous2) m_dispatcher.setResetCounter(true); m_dispatcher.dispatch(); - std::this_thread::sleep_for(10ms); + this_thread::sleep_for(10ms); expectedState[4] = 0; // m_plSelectA; expectedState[5] = 1; // m_plSelectB; expectedState[6] = 0; // m_plPackageCounter; @@ -172,13 +167,13 @@ TEST_F(FixturePetriNet, RoundRobin_1_continuous2) TEST_F(FixturePetriNet, FreeChoice_1) { size_t numberOfIterations = 1100; - size_t expectedState[7] = { 0, 1, 0, 0, 0, 0, numberOfIterations }; + array expectedState = { 0, 1, 0, 0, 0, 0, numberOfIterations }; m_dispatcher.setResetCounter(false); m_dispatcher.setFreeChoiceMode(ptne::PTN_Engine::ACTIONS_THREAD_OPTION::EVENT_LOOP); for (size_t i = 0; i < numberOfIterations; ++i) { m_dispatcher.dispatch(); - std::this_thread::sleep_for(10ms); + this_thread::sleep_for(10ms); } testFreeChoiceState(expectedState); m_dispatcher.stop(); @@ -187,13 +182,13 @@ TEST_F(FixturePetriNet, FreeChoice_1) TEST_F(FixturePetriNet, FreeChoice_1_detached) { size_t numberOfIterations = 1100; - size_t expectedState[7] = { 0, 1, 0, 0, 0, 0, numberOfIterations }; + array expectedState = { 0, 1, 0, 0, 0, 0, numberOfIterations }; m_dispatcher.setResetCounter(false); m_dispatcher.setFreeChoiceMode(ptne::PTN_Engine::ACTIONS_THREAD_OPTION::DETACHED); for (size_t i = 0; i < numberOfIterations; ++i) { m_dispatcher.dispatch(); - std::this_thread::sleep_for(10ms); + this_thread::sleep_for(10ms); } testFreeChoiceState(expectedState); m_dispatcher.stop(); @@ -205,19 +200,19 @@ TEST_F(FixturePetriNet, Weights_1) m_dispatcher.setWeightedPN(ptne::PTN_Engine::ACTIONS_THREAD_OPTION::EVENT_LOOP); m_dispatcher.dispatch(); - std::this_thread::sleep_for(10ms); + this_thread::sleep_for(10ms); - size_t expectedState[4] = { 0, 1, 0, 0 }; + array expectedState = { 0, 1, 0, 0 }; testWeightedState(expectedState); m_dispatcher.dispatch(); - std::this_thread::sleep_for(10ms); + this_thread::sleep_for(10ms); expectedState[1] = 2; testWeightedState(expectedState); m_dispatcher.dispatch(); - std::this_thread::sleep_for(10ms); + this_thread::sleep_for(10ms); expectedState[1] = 0; expectedState[2] = 4; @@ -232,19 +227,19 @@ TEST_F(FixturePetriNet, Weights_1_detached) m_dispatcher.setWeightedPN(ptne::PTN_Engine::ACTIONS_THREAD_OPTION::DETACHED); m_dispatcher.dispatch(); - std::this_thread::sleep_for(10ms); + this_thread::sleep_for(10ms); - size_t expectedState[4] = { 0, 1, 0, 0 }; + array expectedState = { 0, 1, 0, 0 }; testWeightedState(expectedState); m_dispatcher.dispatch(); - std::this_thread::sleep_for(10ms); + this_thread::sleep_for(10ms); expectedState[1] = 2; testWeightedState(expectedState); m_dispatcher.dispatch(); - std::this_thread::sleep_for(10ms); + this_thread::sleep_for(10ms); expectedState[1] = 0; expectedState[2] = 4; @@ -260,12 +255,12 @@ TEST_F(FixturePetriNet, Inhibited_SingleThread) m_dispatcher.dispatch(); m_dispatcher.execute(); - size_t expectedState[6] = { 0, 0, 0, 0, 1, 1 }; + array expectedState = { 0, 0, 0, 0, 1, 1 }; testInhibitedState(expectedState); m_dispatcher.dispatch(); m_dispatcher.execute(); - size_t expectedState_[6] = { 0, 1, 1, 1, 0, 0 }; + array expectedState_ = { 0, 1, 1, 1, 0, 0 }; testInhibitedState(expectedState_); m_dispatcher.stop(); } @@ -276,15 +271,15 @@ TEST_F(FixturePetriNet, Inhibited_1) m_dispatcher.setInhibitedPN(ptne::PTN_Engine::ACTIONS_THREAD_OPTION::EVENT_LOOP); m_dispatcher.dispatch(); - std::this_thread::sleep_for(10ms); + this_thread::sleep_for(10ms); - size_t expectedState[6] = { 0, 0, 0, 0, 1, 1 }; + array expectedState = { 0, 0, 0, 0, 1, 1 }; testInhibitedState(expectedState); m_dispatcher.dispatch(); - std::this_thread::sleep_for(10ms); + this_thread::sleep_for(10ms); - size_t expectedState_[6] = { 0, 1, 1, 1, 0, 0 }; + array expectedState_ = { 0, 1, 1, 1, 0, 0 }; testInhibitedState(expectedState_); m_dispatcher.stop(); } @@ -295,15 +290,15 @@ TEST_F(FixturePetriNet, Inhibited_1_detached) m_dispatcher.setInhibitedPN(ptne::PTN_Engine::ACTIONS_THREAD_OPTION::DETACHED); m_dispatcher.dispatch(); - std::this_thread::sleep_for(10ms); + this_thread::sleep_for(10ms); - size_t expectedState[6] = { 0, 0, 0, 0, 1, 1 }; + array expectedState = { 0, 0, 0, 0, 1, 1 }; testInhibitedState(expectedState); m_dispatcher.dispatch(); - std::this_thread::sleep_for(10ms); + this_thread::sleep_for(10ms); - size_t expectedState_[6] = { 0, 1, 1, 1, 0, 0 }; + array expectedState_ = { 0, 1, 1, 1, 0, 0 }; testInhibitedState(expectedState_); m_dispatcher.stop(); } @@ -314,7 +309,7 @@ TEST_F(FixturePetriNet, ThreadSafety) const size_t numberOfThreads = 8; simpleController.doSomethingConcurrently(numberOfThreads); - std::this_thread::sleep_for(10ms); + this_thread::sleep_for(10ms); EXPECT_EQ(numberOfThreads, simpleController.getNumberOfDifferentThreads()); @@ -329,7 +324,7 @@ TEST(Registered, RegisteredMethods) controller.initialize(); controller.startExecution(); - std::this_thread::sleep_for(10ms); + this_thread::sleep_for(10ms); // TODO get a better way to test EXPECT_EQ(1, controller.getNumberOfTokens("P1")); @@ -355,21 +350,24 @@ TEST(Conditions, AdditionalActivationConditions) bool m_hasConnectionToServer = true; ptne::PTN_Engine pn; - pn.createPlace("P1", 0, true); - pn.createPlace("P2", 0); + pn.createPlace({ .name = "P1", + .input = true }); + pn.createPlace({ .name="P2"}); - pn.createTransition({ "P1" }, { "P2" }, - vector{ [&m_callCount, &m_hasConnectionToServer]() - { - ++m_callCount; - return m_hasConnectionToServer; - } }); + pn.createTransition({ .name = "T1", + .activationArcs = { ArcProperties{ .placeName = "P1" } }, + .destinationArcs = { ArcProperties{ .placeName = "P2" } }, + .additionalConditions={ [&m_callCount, &m_hasConnectionToServer]() + { + ++m_callCount; + return m_hasConnectionToServer; + } } }); EXPECT_EQ(0, m_callCount); pn.execute(); pn.incrementInputPlace("P1"); - std::this_thread::sleep_for(10ms); + this_thread::sleep_for(10ms); pn.stop(); EXPECT_EQ(1, m_callCount); vector numberOfTokens; @@ -383,107 +381,155 @@ TEST(ActionsThreadOption, Ordering) using std::vector; using namespace ptne; - std::string str; - std::mutex mut; + string str; + mutex mut; ActionFunction action1 = [&str, &mut]() { - std::lock_guard lg(mut); + lock_guard lg(mut); str.append("a"); }; ActionFunction action2 = [&str, &mut]() { - std::lock_guard lg(mut); + lock_guard lg(mut); str.append("b"); }; PTN_Engine pn_singleThread(PTN_Engine::ACTIONS_THREAD_OPTION::SINGLE_THREAD); - pn_singleThread.createPlace("P1", 0, action1, true); - pn_singleThread.createPlace("Counter", 100000); - pn_singleThread.createPlace("P2", 0, action2); - pn_singleThread.createTransition({ "P1", "Counter" }, { "P2" }); - pn_singleThread.createTransition({ "P2" }, { "P1" }); + pn_singleThread.createPlace({ .name = "P1", + .onEnterAction = action1, + .input = true }); + pn_singleThread.createPlace({ .name = "Counter", + .initialNumberOfTokens = 100000 }); + pn_singleThread.createPlace({ .name = "P2", + .onEnterAction = action2 }); + pn_singleThread.createTransition({ .name = "T1", + .activationArcs = { ArcProperties{ .placeName = "P1" }, + ArcProperties{ .placeName = "Counter" } }, + .destinationArcs = { ArcProperties{ .placeName = "P2" } } }); + pn_singleThread.createTransition({ .name = "T2", + .activationArcs = { ArcProperties{ .placeName = "P2" } }, + .destinationArcs = { ArcProperties{ .placeName = "P1" } } }); pn_singleThread.incrementInputPlace("P1"); pn_singleThread.execute(); EXPECT_EQ(0, pn_singleThread.getNumberOfTokens("P2")); - EXPECT_FALSE(str.find("aa") != std::string::npos); - EXPECT_FALSE(str.find("bb") != std::string::npos); + EXPECT_FALSE(str.find("aa") != string::npos); + EXPECT_FALSE(str.find("bb") != string::npos); str.clear(); - std::atomic finished = false; - ActionFunction action3 = [&finished]() { - finished = true; + atomic finished = false; + ActionFunction action3 = [&finished]() { + finished = true; }; PTN_Engine pn_jobQueue(PTN_Engine::ACTIONS_THREAD_OPTION::JOB_QUEUE); - pn_jobQueue.createPlace("P1", 0, action1, true); - pn_jobQueue.createPlace("Counter", 100000); - pn_jobQueue.createPlace("P2", 0, action2); - pn_jobQueue.createPlace("P3", 0, action3); - pn_jobQueue.createTransition({ "P1", "Counter" }, { "P2" }); - pn_jobQueue.createTransition({ "P2" }, { "P1" }); - pn_jobQueue.createTransition({ "P1" }, { "P3" }, vector{ "Counter" }); + pn_jobQueue.createPlace( + { .name = "P1", .initialNumberOfTokens = 0, .onEnterAction = action1, .input = true }); + pn_jobQueue.createPlace({ .name = "Counter", + .initialNumberOfTokens = 100000 }); + pn_jobQueue.createPlace({ .name = "P2", + .onEnterAction = action2 }); + pn_jobQueue.createPlace({ .name="P3", + .onEnterAction=action3 }); + pn_jobQueue.createTransition({ .name = "T1", + .activationArcs = { ArcProperties{ .placeName = "P1" }, + ArcProperties{ .placeName = "Counter" } }, + .destinationArcs = { ArcProperties{ .placeName = "P2" } } }); + pn_jobQueue.createTransition({ .name = "T2", + .activationArcs = { ArcProperties{ .placeName = "P2" } }, + .destinationArcs = { ArcProperties{ .placeName = "P1" } } }); + pn_jobQueue.createTransition({ .name = "T3", + .activationArcs = { ArcProperties{ .placeName = "P1" } }, + .destinationArcs = { ArcProperties{ .placeName = "P3" } }, + .inhibitorArcs = { ArcProperties{ .placeName = "Counter" } } }); pn_jobQueue.execute(); pn_jobQueue.incrementInputPlace("P1"); while (!finished) { - std::this_thread::sleep_for(100ms); + this_thread::sleep_for(100ms); } pn_jobQueue.stop(); EXPECT_EQ(0, pn_jobQueue.getNumberOfTokens("P2")); { - std::lock_guard lg(mut); - EXPECT_FALSE(str.find("aa") != std::string::npos); - EXPECT_FALSE(str.find("bb") != std::string::npos); + lock_guard lg(mut); + EXPECT_FALSE(str.find("aa") != string::npos); + EXPECT_FALSE(str.find("bb") != string::npos); str.clear(); } finished = false; PTN_Engine pn_eventloop(PTN_Engine::ACTIONS_THREAD_OPTION::EVENT_LOOP); - pn_eventloop.createPlace("P1", 0, action1, true); - pn_eventloop.createPlace("Counter", 100000); - pn_eventloop.createPlace("P2", 0, action2); - pn_eventloop.createPlace("P3", 0, action3); - pn_eventloop.createTransition({ "P1", "Counter" }, { "P2" }); - pn_eventloop.createTransition({ "P2" }, { "P1" }); - pn_eventloop.createTransition({ "P1" }, { "P3" }, vector{ "Counter" }); + pn_eventloop.createPlace({ .name = "P1", + .onEnterAction = action1, + .input = true }); + pn_eventloop.createPlace({ .name="Counter", + .initialNumberOfTokens=100000 }); + pn_eventloop.createPlace({ .name="P2", + .onEnterAction=action2 }); + pn_eventloop.createPlace({ .name="P3", + .onEnterAction=action3 }); + pn_eventloop.createTransition({ .name = "T1", + .activationArcs = { ArcProperties{ .placeName = "P1" }, + ArcProperties{ .placeName = "Counter" } }, + .destinationArcs = { ArcProperties{ .placeName = "P2" } } }); + pn_eventloop.createTransition({ .name = "T2", + .activationArcs = { ArcProperties{ .placeName = "P2" } }, + .destinationArcs = { ArcProperties{ .placeName = "P1" } } }); + pn_eventloop.createTransition({ .name = "T3", + .activationArcs = { ArcProperties{ .placeName = "P1" } }, + .destinationArcs = { ArcProperties{ .placeName = "P3" } }, + .inhibitorArcs = { ArcProperties{ .placeName = "Counter" } } }); pn_eventloop.execute(); pn_eventloop.incrementInputPlace("P1"); while (!finished) { - std::this_thread::sleep_for(100ms); + this_thread::sleep_for(100ms); } pn_eventloop.stop(); EXPECT_EQ(0, pn_eventloop.getNumberOfTokens("P2")); { - std::lock_guard lg(mut); - EXPECT_FALSE(str.find("aa") != std::string::npos); - EXPECT_FALSE(str.find("bb") != std::string::npos); + lock_guard lg(mut); + EXPECT_FALSE(str.find("aa") != string::npos); + EXPECT_FALSE(str.find("bb") != string::npos); str.clear(); } finished = false; PTN_Engine pn_detached(PTN_Engine::ACTIONS_THREAD_OPTION::DETACHED); - pn_detached.createPlace("P1", 0, action1, true); - pn_detached.createPlace("Counter", 100000); - pn_detached.createPlace("P2", 0, action2); - pn_detached.createPlace("P3", 0, action3); - pn_detached.createTransition({ "P1", "Counter" }, { "P2" }); - pn_detached.createTransition({ "P2" }, { "P1" }); - pn_detached.createTransition({ "P1" }, { "P3" }, vector{ "Counter" }); + pn_detached.createPlace({ .name="P1", + .onEnterAction=action1, + .input=true }); + pn_detached.createPlace({ .name="Counter", + .initialNumberOfTokens=100000 }); + pn_detached.createPlace({ .name="P2", + .onEnterAction=action2 }); + pn_detached.createPlace({ .name="P3", + .onEnterAction=action3 }); + pn_detached.createTransition({ .name = "T1", + .activationArcs = { ArcProperties{ .placeName = "P1" }, + ArcProperties{ .placeName = "Counter" } }, + .destinationArcs = { ArcProperties{ .placeName = "P2" } } }); + pn_detached.createTransition({ .name = "T2", + .activationArcs = { ArcProperties{ .placeName = "P2" } }, + .destinationArcs = { ArcProperties{ .placeName = "P1" } } }); + pn_detached.createTransition({ .name = "T3", + .activationArcs = { ArcProperties{ .placeName = "P1" } }, + .destinationArcs = { ArcProperties{ .placeName = "P3" } }, + .inhibitorArcs = { ArcProperties{ .placeName = "Counter" } } }); pn_detached.execute(); pn_detached.incrementInputPlace("P1"); while (!finished) { - std::this_thread::sleep_for(100ms); + this_thread::sleep_for(100ms); } pn_detached.stop(); EXPECT_EQ(0, pn_detached.getNumberOfTokens("P2")); { - std::lock_guard lg(mut); - EXPECT_TRUE(str.find("aa") != std::string::npos); - EXPECT_TRUE(str.find("bb") != std::string::npos); + lock_guard lg(mut); + EXPECT_TRUE(str.find("aa") != string::npos); + EXPECT_TRUE(str.find("bb") != string::npos); } + this_thread::sleep_for(5000ms); } TEST(Concurrency, ThreadSafety_1) @@ -491,18 +537,28 @@ TEST(Concurrency, ThreadSafety_1) using namespace ptne; PTN_Engine pn; - pn.createPlace("P1", 0, true); - pn.createPlace("Counter", 5); - pn.createPlace("P2", 0); - std::atomic finished = false; + pn.createPlace({ .name="P1", + .input=true }); + pn.createPlace({ .name="Counter", + .initialNumberOfTokens=5 }); + pn.createPlace({ .name="P2"}); + atomic finished = false; ActionFunction flagFinish = [&finished]() { finished = true; }; - pn.createPlace("P3", 0, flagFinish); - pn.createTransition({ "P1", "Counter" }, { "P2" }); - pn.createTransition({}, { "P3" }, std::vector{ "Counter", "P3" }); + pn.createPlace({ .name = "P3", + .onEnterAction = flagFinish }); + + pn.createTransition({ .name = "T1", + .activationArcs = { ArcProperties{ .placeName = "P1" }, + ArcProperties{ .placeName = "Counter" } }, + .destinationArcs = { ArcProperties{ .placeName = "P2" } } }); + pn.createTransition({ .name = "T2", + .destinationArcs = { ArcProperties{ .placeName = "P3" } }, + .inhibitorArcs = { ArcProperties{ .placeName = "Counter" }, + ArcProperties{ .placeName = "P3" } } }); pn.execute(); const size_t totalThreads = 16; - std::latch _latch(totalThreads); + latch _latch(totalThreads); auto f = [&pn, &_latch, &finished]() { _latch.wait(); @@ -513,16 +569,16 @@ TEST(Concurrency, ThreadSafety_1) while (!finished) { - std::this_thread::sleep_for(10ms); + this_thread::sleep_for(10ms); } pn.stop(); }; - std::vector threads; + vector threads; for (size_t i = 0; i < totalThreads; ++i) { - threads.emplace_back(std::thread(f)); + threads.emplace_back(f); _latch.count_down(); } @@ -530,9 +586,9 @@ TEST(Concurrency, ThreadSafety_1) { t.join(); } - + EXPECT_EQ(0, pn.getNumberOfTokens("Counter")); EXPECT_EQ(155, pn.getNumberOfTokens("P1")); EXPECT_EQ(5, pn.getNumberOfTokens("P2")); - EXPECT_EQ(1, pn.getNumberOfTokens("P3")); + EXPECT_EQ(1, pn.getNumberOfTokens("P3")); } diff --git a/Tests/BlackBoxTests/main.cpp b/Tests/BlackBoxTests/main.cpp old mode 100644 new mode 100755 diff --git a/Tests/WhiteBoxTests/Fixtures/FixtureTestPlace.cpp b/Tests/WhiteBoxTests/Fixtures/FixtureTestPlace.cpp old mode 100644 new mode 100755 index a8bd07a..8ab8416 --- a/Tests/WhiteBoxTests/Fixtures/FixtureTestPlace.cpp +++ b/Tests/WhiteBoxTests/Fixtures/FixtureTestPlace.cpp @@ -17,18 +17,16 @@ */ #include "Fixtures/FixtureTestPlace.h" -#include "PTN_Engine/PTN_Engine.h" using namespace ptne; -using std::bind; +using std::bind_front; FixtureTestPlace::FixtureTestPlace() -: m_ptnEngine(PTN_Engine::ACTIONS_THREAD_OPTION::EVENT_LOOP) -, m_place(m_ptnEngine, +: m_place(m_ptnEngine, "", size_t(0), - bind(&Controller::onEnter, &m_controller), - bind(&Controller::onExit, &m_controller)) + bind_front(&Controller::onEnter, &m_controller), + bind_front(&Controller::onExit, &m_controller)) { m_ptnEngine.setActionsThreadOption(PTN_Engine::ACTIONS_THREAD_OPTION::EVENT_LOOP); } @@ -70,8 +68,8 @@ void FixtureTestPlace::exitPlace() void FixtureTestPlace::inputPlace() { - ptne::Place inputPlace(m_ptnEngine, "", size_t(0), bind(&Controller::onEnter, m_controller), - bind(&Controller::onExit, m_controller)); + ptne::Place inputPlace(m_ptnEngine, "", size_t(0), bind_front(&Controller::onEnter, m_controller), + bind_front(&Controller::onExit, m_controller)); EXPECT_EQ(false, inputPlace.isInputPlace()); } diff --git a/Tests/WhiteBoxTests/Fixtures/FixtureTestPlace.h b/Tests/WhiteBoxTests/Fixtures/FixtureTestPlace.h old mode 100644 new mode 100755 index 1513e1b..a428817 --- a/Tests/WhiteBoxTests/Fixtures/FixtureTestPlace.h +++ b/Tests/WhiteBoxTests/Fixtures/FixtureTestPlace.h @@ -19,12 +19,10 @@ #pragma once #include "gtest/gtest.h" - #include "Mocks/Controller.h" #include "PTN_Engine/PTN_EngineImp.h" #include "PTN_Engine/Place.h" - //! Fixture to test places. class FixtureTestPlace : public ::testing::Test { @@ -41,22 +39,22 @@ class FixtureTestPlace : public ::testing::Test //! Test input places specifics. void inputPlace(); - /*! - * Test entering a place with a specific number of tokens. - * \param tokens Number of tokens. - */ + //! + //! Test entering a place with a specific number of tokens. + //! \param tokens Number of tokens. + //! void enterPlace(const size_t tokens); - /*! - * Test exiting a place with a specific number of tokens. - * \param tokens Number of tokens. - */ + //! + //! Test exiting a place with a specific number of tokens. + //! \param tokens Number of tokens. + //! void exitPlace(const size_t tokens); protected: Controller m_controller; - ptne::PTN_EngineImp m_ptnEngine; + ptne::PTN_EngineImp m_ptnEngine{ ptne::PTN_Engine::ACTIONS_THREAD_OPTION::EVENT_LOOP }; //! A PTN Engine place. ptne::Place m_place; diff --git a/Tests/WhiteBoxTests/Fixtures/FixtureTestTransition.cpp b/Tests/WhiteBoxTests/Fixtures/FixtureTestTransition.cpp old mode 100644 new mode 100755 index 673f123..3448b05 --- a/Tests/WhiteBoxTests/Fixtures/FixtureTestTransition.cpp +++ b/Tests/WhiteBoxTests/Fixtures/FixtureTestTransition.cpp @@ -3,7 +3,7 @@ * * Copyright (c) 2017 Eduardo Valgôde * Copyright (c) 2021 Kale Evans - * Copyright (c) 2023 Eduardo Valgôde + * Copyright (c) 2024 Eduardo Valgôde * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -23,11 +23,6 @@ using namespace ptne; using namespace std; -FixtureTestTransition::FixtureTestTransition() -: m_ptnEngine(PTN_Engine::ACTIONS_THREAD_OPTION::EVENT_LOOP) -{ -} - void FixtureTestTransition::createTransition(const vector &inputTokens, const vector &outputTokens, const vector &expectedInputTokens, @@ -35,20 +30,35 @@ void FixtureTestTransition::createTransition(const vector &inputTokens, const VectorOfConditions &conditions, const bool expectedFireResult) { - vector> inputPlaces = createPlaces(inputTokens); - vector> wInputPlaces = createPlaceWPtrs(inputPlaces); + vector inputPlaces = createPlaces(inputTokens); + vector wInputPlaces = createPlaceWPtrs(inputPlaces); - vector> outputPlaces = createPlaces(outputTokens); - vector> wOutputPlaces = createPlaceWPtrs(outputPlaces); + vector outputPlaces = createPlaces(outputTokens); + vector wOutputPlaces = createPlaceWPtrs(outputPlaces); for (size_t i : outputTokens) { - shared_ptr newPlace(new Place(m_ptnEngine, "", i, nullptr, nullptr)); + auto newPlace = make_shared(m_ptnEngine, "", i, nullptr, nullptr); outputPlaces.push_back(newPlace); wOutputPlaces.push_back(newPlace); } - Transition transition(wInputPlaces, {}, wOutputPlaces, {}, {}, conditions, false); + auto createArcs = [] (const vector &places) + { + vector arcs; + for (const auto &place : places) + { + arcs.emplace_back(place); + } + return arcs; + }; + + Transition transition("T1", + createArcs(inputPlaces), + createArcs(outputPlaces), + {}, + conditions, + false); EXPECT_EQ(expectedFireResult, transition.execute()); @@ -83,15 +93,30 @@ void FixtureTestTransition::createTransitionWithWeights(const vector &in // Create input places - vector> inputPlaces = createPlaces(inputTokens); - vector> wPtrInputPlaces = createPlaceWPtrs(inputPlaces); + vector inputPlaces = createPlaces(inputTokens); + vector wPtrInputPlaces = createPlaceWPtrs(inputPlaces); // Create output places - vector> outputPlaces = createPlaces(outputTokens); - vector> wOutputPlaces = createPlaceWPtrs(outputPlaces); + vector outputPlaces = createPlaces(outputTokens); + vector wOutputPlaces = createPlaceWPtrs(outputPlaces); + + auto createArcs = [] (const vector &places, const vector &weights) + { + vector arcs; + for (size_t i = 0; i < places.size(); ++i) + { + arcs.emplace_back(places[i], weights[i]); + } + return arcs; + }; // Create transition - Transition transition(wPtrInputPlaces, inputWeights, wOutputPlaces, outputWeights, {}, conditions, false); + Transition transition("T1", + createArcs(inputPlaces, inputWeights), + createArcs(outputPlaces, outputWeights), + {}, + conditions, + false); // Test transition EXPECT_EQ(expectedFireResult, transition.execute()); @@ -111,25 +136,25 @@ void FixtureTestTransition::createTransitionWithWeights(const vector &in } } -vector> FixtureTestTransition::createPlaces(const vector &inputTokens) +vector FixtureTestTransition::createPlaces(const vector &inputTokens) { // Create input places - vector> inputPlaces; + vector inputPlaces; for (size_t i : inputTokens) { - shared_ptr newPlace(new Place(m_ptnEngine, "", i, nullptr, nullptr)); + auto newPlace = make_shared(m_ptnEngine, "", i, nullptr, nullptr); inputPlaces.push_back(newPlace); } return inputPlaces; } -vector> FixtureTestTransition::createPlaceWPtrs(const vector> &places) +vector FixtureTestTransition::createPlaceWPtrs(const vector &places) const { // Create input places - vector> wPtrPlaces; - for (const shared_ptr &spPlace : places) + vector wPtrPlaces; + for (const SharedPtrPlace &spPlace : places) { - wPtrPlaces.push_back(weak_ptr(spPlace)); + wPtrPlaces.push_back(WeakPtrPlace(spPlace)); } return wPtrPlaces; } diff --git a/Tests/WhiteBoxTests/Fixtures/FixtureTestTransition.h b/Tests/WhiteBoxTests/Fixtures/FixtureTestTransition.h old mode 100644 new mode 100755 index 5900845..a249587 --- a/Tests/WhiteBoxTests/Fixtures/FixtureTestTransition.h +++ b/Tests/WhiteBoxTests/Fixtures/FixtureTestTransition.h @@ -18,33 +18,33 @@ #pragma once +#include "gtest/gtest.h" #include "Mocks/Controller.h" #include "PTN_Engine/PTN_Engine.h" #include "PTN_Engine/PTN_EngineImp.h" #include "PTN_Engine/Place.h" #include "PTN_Engine/Transition.h" -#include "gtest/gtest.h" //! Fixture to test transitions. class FixtureTestTransition : public ::testing::Test { public: //! Constructor. - FixtureTestTransition(); + FixtureTestTransition() = default; using VectorOfPlaces = std::vector>; using VectorOfConditions = std::vector>; - /*! - * Test creating a transition and makes it available for further testing. - * \param inputTokens Tokens to put in each activation place. - * \param outputTokens Tokens to put in the destination places before firing. - * \param expectedInputTokens Expected number of tokens on the inputs after executing the transition. - * \param expectedOutputTokens Expected tokens after trying to fire the transition. - * \param conditions Additional conditions from the controller. - * \param expectedFireResult If it is expected that the condition fires. - */ + //! + //! Test creating a transition and makes it available for further testing. + //! \param inputTokens Tokens to put in each activation place. + //! \param outputTokens Tokens to put in the destination places before firing. + //! \param expectedInputTokens Expected number of tokens on the inputs after executing the transition. + //! \param expectedOutputTokens Expected tokens after trying to fire the transition. + //! \param conditions Additional conditions from the controller. + //! \param expectedFireResult If it is expected that the condition fires. + //! void createTransition(const std::vector &inputTokens, const std::vector &outputTokens, const std::vector &expectedInputTokens, @@ -53,17 +53,16 @@ class FixtureTestTransition : public ::testing::Test const bool expectedFireResult); - /*! - * - * \param inputTokens Tokens to put in each activation place. - * \param inputWeights Input weights. - * \param outputTokens Tokens to put in the destination places before firing. - * \param outputWeights Output weights. - * \param expectedInputTokens Expected number of tokens on the inputs after executing the transition. - * \param expectedOutputTokens Expected tokens after trying to fire the transition. - * \param conditions Additional conditions from the controller. - * \param expectedFireResult If it is expected that the condition fires. - */ + //! + //! \param inputTokens Tokens to put in each activation place. + //! \param inputWeights Input weights. + //! \param outputTokens Tokens to put in the destination places before firing. + //! \param outputWeights Output weights. + //! \param expectedInputTokens Expected number of tokens on the inputs after executing the transition. + //! \param expectedOutputTokens Expected tokens after trying to fire the transition. + //! \param conditions Additional conditions from the controller. + //! \param expectedFireResult If it is expected that the condition fires. + //! void createTransitionWithWeights(const std::vector &inputTokens, const std::vector &inputWeights, const std::vector &outputTokens, @@ -73,25 +72,25 @@ class FixtureTestTransition : public ::testing::Test const VectorOfConditions &conditions, const bool expectedFireResult); - /*! - * Utility function. Creates vector of shared pointers to places from a vector of - * initial tokens. - * \param tokens Vector with initial tokens. - * \return Vector of shared pointers to places with the tokens given in the input. - */ - std::vector> createPlaces(const std::vector &inputTokens); + //! + //! Utility function. Creates vector of shared pointers to places from a vector of + //! initial tokens. + //! \param tokens Vector with initial tokens. + //! \return Vector of shared pointers to places with the tokens given in the input. + //! + std::vector createPlaces(const std::vector &inputTokens); - /*! - * Utility function. Create a vector with weak pointers of the shared pointers of the - * input vector. - * \param Vector of shared pointers to places. - * \return Vector of weak pointers to vector of shared pointers. - */ - std::vector> - createPlaceWPtrs(const std::vector> &places); + //! + //! Utility function. Create a vector with weak pointers of the shared pointers of the + //! input vector. + //! \param Vector of shared pointers to places. + //! \return Vector of weak pointers to vector of shared pointers. + //! + std::vector + createPlaceWPtrs(const std::vector> &places) const; protected: Controller m_controller; - ptne::PTN_EngineImp m_ptnEngine; + ptne::PTN_EngineImp m_ptnEngine{ ptne::PTN_Engine::ACTIONS_THREAD_OPTION::EVENT_LOOP }; }; diff --git a/Tests/WhiteBoxTests/Mocks/Controller.cpp b/Tests/WhiteBoxTests/Mocks/Controller.cpp old mode 100644 new mode 100755 index 6dad761..84fe2dd --- a/Tests/WhiteBoxTests/Mocks/Controller.cpp +++ b/Tests/WhiteBoxTests/Mocks/Controller.cpp @@ -18,14 +18,6 @@ #include "Mocks/Controller.h" -Controller::Controller() -: m_activationConditionCallCounter(0) -, m_enterCounter(0) -, m_exitCounter(0) -, m_canFire(true) -{ -} - void Controller::onEnter() { ++m_enterCounter; diff --git a/Tests/WhiteBoxTests/Mocks/Controller.h b/Tests/WhiteBoxTests/Mocks/Controller.h old mode 100644 new mode 100755 index ea4f599..62f4271 --- a/Tests/WhiteBoxTests/Mocks/Controller.h +++ b/Tests/WhiteBoxTests/Mocks/Controller.h @@ -18,17 +18,17 @@ */ #pragma once + #include +//! //! Sample controller. -/*! - * Sample controller. - */ +//! class Controller final { public: //! Constructor. - Controller(); + Controller() = default; //! On enter action. void onEnter(); @@ -53,14 +53,14 @@ class Controller final private: //! Activation condition call counter - mutable size_t m_activationConditionCallCounter; + mutable size_t m_activationConditionCallCounter = 0; //! Counter of times entered. - size_t m_enterCounter; + size_t m_enterCounter = 0; //! Counter of times exited. - size_t m_exitCounter; + size_t m_exitCounter = 0; //! Activation condition. - bool m_canFire; + bool m_canFire = true; }; diff --git a/Tests/WhiteBoxTests/Tests/TestPlace.cpp b/Tests/WhiteBoxTests/Tests/TestPlace.cpp old mode 100644 new mode 100755 index 4619e94..72c367a --- a/Tests/WhiteBoxTests/Tests/TestPlace.cpp +++ b/Tests/WhiteBoxTests/Tests/TestPlace.cpp @@ -16,11 +16,8 @@ * limitations under the License. */ -#include "gtest/gtest.h" - #include "Fixtures/FixtureTestPlace.h" -#include "limits.h" - +#include "gtest/gtest.h" TEST_F(FixtureTestPlace, InputPlace) { diff --git a/Tests/WhiteBoxTests/Tests/TestTransition.cpp b/Tests/WhiteBoxTests/Tests/TestTransition.cpp old mode 100644 new mode 100755 index c4daeee..2ee2096 --- a/Tests/WhiteBoxTests/Tests/TestTransition.cpp +++ b/Tests/WhiteBoxTests/Tests/TestTransition.cpp @@ -1,7 +1,7 @@ /* * This file is part of PTN Engine * - * Copyright (c) 2017-2023 Eduardo Valgôde + * Copyright (c) 2017-2024 Eduardo Valgôde * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -28,7 +28,7 @@ TEST_F(FixtureTestTransition, T1) vector expectedInputTokens{ 0, 0, 0 }; vector outputTokens{ 0, 0, 0 }; vector expectedOutputTokens{ 1, 1, 1 }; - VectorOfConditions conditions{ { "", bind(&Controller::activationCondition, &m_controller) } }; + VectorOfConditions conditions{ { "", bind_front(&Controller::activationCondition, &m_controller) } }; bool expectedFireResult = true; createTransition(inputTokens, outputTokens, expectedInputTokens, expectedOutputTokens, conditions, @@ -42,7 +42,7 @@ TEST_F(FixtureTestTransition, T2) vector expectedInputTokens{ 1, 0, 1 }; vector outputTokens{ 0, 0, 0 }; vector expectedOutputTokens{ 0, 0, 0 }; - VectorOfConditions conditions{ { "", bind(&Controller::activationCondition, &m_controller) } }; + VectorOfConditions conditions{ { "", bind_front(&Controller::activationCondition, &m_controller) } }; bool expectedFireResult = false; createTransition(inputTokens, outputTokens, expectedInputTokens, expectedOutputTokens, conditions, @@ -57,7 +57,7 @@ TEST_F(FixtureTestTransition, T3) vector expectedInputTokens{ 1, 1, 1 }; vector outputTokens{ 0, 0, 0 }; vector expectedOutputTokens{ 0, 0, 0 }; - VectorOfConditions conditions{ { "", bind(&Controller::activationCondition, &m_controller) } }; + VectorOfConditions conditions{ { "", bind_front(&Controller::activationCondition, &m_controller) } }; bool expectedFireResult = false; m_controller.setFireCondition(false); @@ -82,48 +82,29 @@ TEST_F(FixtureTestTransition, T_Weights) expectedOutputTokens, conditions, expectedFireResult); } -TEST_F(FixtureTestTransition, T_ZeroValueWeightException) +namespace { - vector inputTokens{ 2, 2 }; - vector inputWeights{ 2, 1 }; - vector outputTokens{ 0 }; - vector outputWeights{ 0 }; - VectorOfConditions conditions{}; - - vector> inputPlaces = createPlaces(inputTokens); - vector> wInputPlaces = createPlaceWPtrs(inputPlaces); - - vector> outputPlaces = createPlaces(outputTokens); - vector> wOutputPlaces = createPlaceWPtrs(outputPlaces); - - ASSERT_THROW(Transition(wInputPlaces, inputWeights, wOutputPlaces, outputWeights, {}, conditions, false), - ZeroValueWeightException); -} - -TEST_F(FixtureTestTransition, T_ActivationWeightDimensionException) +vector createArcs(const vector> &places, const vector &weights) { - vector inputTokens{ 2, 2 }; - vector inputWeights{ 2 }; - vector outputTokens{ 0 }; - vector outputWeights{ 1 }; - VectorOfConditions conditions{}; - - vector> inputPlaces = createPlaces(inputTokens); - vector> wInputPlaces = createPlaceWPtrs(inputPlaces); - - vector> outputPlaces = createPlaces(outputTokens); - vector> wOutputPlaces = createPlaceWPtrs(outputPlaces); - - ASSERT_THROW(Transition(wInputPlaces, inputWeights, wOutputPlaces, outputWeights, {}, conditions, false), - ActivationWeightDimensionException); + vector arcs; + for (size_t i = 0; i < places.size(); ++i) + { + arcs.emplace_back(places[i], weights[i]); + } + for (size_t i = 0; i < weights.size(); ++i) + { + arcs[i].weight = weights[i]; + } + return arcs; +} } -TEST_F(FixtureTestTransition, T_DestinationWeightDimensionException) +TEST_F(FixtureTestTransition, T_ZeroValueWeightException) { vector inputTokens{ 2, 2 }; - vector inputWeights{ 2, 3 }; + vector inputWeights{ 2, 1 }; vector outputTokens{ 0 }; - vector outputWeights{ 1, 5 }; + vector outputWeights{ 0 }; VectorOfConditions conditions{}; vector> inputPlaces = createPlaces(inputTokens); @@ -132,26 +113,39 @@ TEST_F(FixtureTestTransition, T_DestinationWeightDimensionException) vector> outputPlaces = createPlaces(outputTokens); vector> wOutputPlaces = createPlaceWPtrs(outputPlaces); - ASSERT_THROW(Transition(wInputPlaces, inputWeights, wOutputPlaces, outputWeights, {}, conditions, false), - DestinationWeightDimensionException); + ASSERT_THROW(Transition("T1", + createArcs(inputPlaces, inputWeights), + createArcs(outputPlaces, outputWeights), + {}, + conditions, + false), + ZeroValueWeightException); } TEST_F(FixtureTestTransition, T_ActivationPlaceRepetitionException) { vector inputTokens{ 2, 2 }; - vector inputWeights{ 2, 3, 1 }; + vector inputWeights{ 2, 3 }; vector outputTokens{ 1, 2 }; vector outputWeights{ 1, 5 }; VectorOfConditions conditions{}; vector> inputPlaces = createPlaces(inputTokens); vector> wInputPlaces = createPlaceWPtrs(inputPlaces); - wInputPlaces.push_back(inputPlaces.at(0)); + vector> outputPlaces = createPlaces(outputTokens); vector> wOutputPlaces = createPlaceWPtrs(outputPlaces); - ASSERT_THROW(Transition(wInputPlaces, inputWeights, wOutputPlaces, outputWeights, {}, conditions, false), + auto inputArcs = createArcs(inputPlaces, inputWeights); + inputArcs.emplace_back(inputPlaces.at(0)); + + ASSERT_THROW(Transition("T1", + inputArcs, + createArcs(outputPlaces, outputWeights), + {}, + conditions, + false), ActivationPlaceRepetitionException); } @@ -160,7 +154,7 @@ TEST_F(FixtureTestTransition, T_DestinationPlaceRepetitionException) vector inputTokens{ 2, 2 }; vector inputWeights{ 2, 3 }; vector outputTokens{ 1, 2 }; - vector outputWeights{ 1, 5, 3 }; + vector outputWeights{ 1, 5 }; VectorOfConditions conditions{}; vector> inputPlaces = createPlaces(inputTokens); @@ -168,8 +162,15 @@ TEST_F(FixtureTestTransition, T_DestinationPlaceRepetitionException) vector> outputPlaces = createPlaces(outputTokens); vector> wOutputPlaces = createPlaceWPtrs(outputPlaces); - wOutputPlaces.push_back(outputPlaces.at(0)); - ASSERT_THROW(Transition(wInputPlaces, inputWeights, wOutputPlaces, outputWeights, {}, conditions, false), + auto outputArcs = createArcs(outputPlaces, outputWeights); + outputArcs.emplace_back(outputPlaces.at(0)); + + ASSERT_THROW(Transition("T1", + createArcs(inputPlaces, inputWeights), + outputArcs, + {}, + conditions, + false), DestinationPlaceRepetitionException); } diff --git a/Tests/WhiteBoxTests/main.cpp b/Tests/WhiteBoxTests/main.cpp old mode 100644 new mode 100755