Skip to content

Commit

Permalink
Issue #31 - Fix thread safety.
Browse files Browse the repository at this point in the history
  • Loading branch information
vldtecno committed Apr 23, 2023
1 parent 85a2c09 commit 4acd770
Show file tree
Hide file tree
Showing 58 changed files with 3,551 additions and 1,714 deletions.
2 changes: 1 addition & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ set(CMAKE_STATIC_LIBRARY_PREFIX lib)
set(EXECUTABLE_STATIC_POSTFIX _s)


set (CMAKE_CXX_STANDARD 17)
set (CMAKE_CXX_STANDARD 20)
if(CMAKE_COMPILER_IS_GNUCXX)
#set(MULTITHREADED_BUILD 8 CACHE STRING "How many threads are used to build the project")
#set(CMAKE_MAKE_PROGRAM "${CMAKE_MAKE_PROGRAM} -j${MULTITHREADED_BUILD}")
Expand Down
1,196 changes: 789 additions & 407 deletions Doc/Doxygen/FullDocumentation.doxy

Large diffs are not rendered by default.

108 changes: 54 additions & 54 deletions Doc/Specification/Specification.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,29 +4,30 @@

This document specifies the *PTN Engine* library version x.x.x .

**Responsibility for the usage or integration of the *PTN Engine* belongs to its
users alone.**
**THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.**

## The **PTN Engine** Concept

The *PTN Engine* is a C++ 11 library that implements the rules of Petri nets.
The *PTN Engine* is a C++ library that implements the rules of Petri nets.

Its purpose is to be integrated in other programs and to enable the
integrating program to have its logic defined by a Petri net.

The engine can be integrated by deriving from its classes. It provides a PTN
base class and Petri nets can be defined in the constructor of its children.
Third party code can be invoked as tokens enter and leave each place in the net,
thus being controlled by the net.
Third party code can be invoked as tokens enter and leave each place in the net.

The *PTN Engine* aims to:
* control the software that integrates it so that its business logic conforms
to a specified Petri net;
* be easy to integrate with third party code.

Quality is a concern in the development of the *PTN Engine*. For this reason
unit tests and documentation accompany its delivery. There is much to be
improved concerning this topic, which hopefully will be performed in each new
unit tests and documentation are also part of this project. There is still much to
be improved concerning this topic, which hopefully will be addressed in each new
release.

### Implemented Petri net features
Expand All @@ -46,6 +47,39 @@ a way to implement events influencing the firing of a transition.
token leaves a place. In other words: control or simulation actions can be
triggered by tokens entering and leaving a place.

### Runtime options

The PTN-Engine offers 4 different modes of operation, by selecting a
ACTIONS_THREAD_OPTION on construction.

These modes are:

SINGLE_THREAD
In single thread mode, as the name says, the PTN-Engine will only use one thread.
This means all the business logic of the net executes in the same thread. If an
action is triggered by a token reaching a place, this action will be executed
synchronously, and the net will be on hold until the execution of the action is
concluded.

EVENT_LOOP
In this mode, the Petri net is executed in a different thread. This allows for
events to be processed asynchronously. However, running actions triggered by a
token entering or leaving a place will be done in the same thread that is running
the Petri net.

DETACHED
This mode is similar to the EVENT_LOOP mode, but any actions triggered by the
tokens entering or leaving a place, will be executed in their own separate thread.
There is no guarantee of order of execution of actions that are triggered almost
at the same time in this mode. The order will depend on the system's scheduling.

JOB_QUEUE
This mode is again similar to the EVENT_LOOP mode. As hinted by the name, a Job
Queue thread will be created. Actions will be added to the Job Queue as a job to be
executed. This mode of operation guarantees that the order of execution of the
actions is the same as the order in which they were triggered.


### Licenses and Related 3rd Party Software

The *PTN Engine* is licensed under the Apache License, Version 2.0 .
Expand All @@ -65,9 +99,6 @@ This version supports only a subset of Petri nets.

It can nonetheless be used to implement finite-state machines and marked graphs.

The CMake build scripts support the compilers GCC 4.9 and Visual C++ 2015.


## Alternatives
If the *PTN Engine* does not meet your requirements, here are some alternative
suggestions:
Expand All @@ -85,7 +116,7 @@ clients.

### Dependencies

This library is implemented in C++ 11.
This library is implemented in C++ 20.

C++11 specific:
- standard smart pointers
Expand All @@ -98,51 +129,21 @@ C++11 specific:
- tuple
- to_string

The *PTN Engine* relies on [Google Test](https://github.com/google/googletest)
for unit testing.
The *PTN Engine* relies on:
-[Google Test](https://github.com/google/googletest) for unit testing.
-[pugixml](https://pugixml.org/) to import and export Petri nets.

### Structure

#### PTN Engine

The *PTN Engine* is implemented within the namespace ptne.

##### Class Diagram
The class structure is as follows:

TODO - For the time being generate the Doxygen documentation.

##### PTN_Engine
This is the base class that implements the Petri net logic. The integrator
should create a class that inherits from this one. Inside its constructor Places
should be created as shared pointers and passed to the engine (addPlace).

Transitions should be created also in the constructor of the class inheriting
from PTN_Engine.

For more information on how to do this please read the code of the examples.

##### Place
This class defines a place in a Petri net. Additionally function pointers can be
passed a Place so that they are called when a token enters or leaves the place.

Places can be defined as entry places, which are places that simulate the
happening of an event and which can be manipulated by the outside code.

##### IActionFunctor
Base class for methods to be called by the Place when a token enters or leaves.

##### IConditionFunctor
Base class for additional conditions that can disable or enable a transition in
the net.
TODO - include Doxygen documentation

##### Action
Template class that facilitates the creation of function pointers to a
particular class, to be used in the net's places.
#### ImportExport

##### ActivationCondition
Template class that facilitates the creation of function pointers to a
particular class, to be used in the net's places.
Implements the import and export of Petri nets.

#### White Box Tests
Collection of tests that access the internals of the *PTN Engine*.
Expand Down Expand Up @@ -189,8 +190,7 @@ Behaviour of the program in an environment with not enough memory available is
not yet specified nor tested. This is a point for future developments. (TODO)

### Thread Safety
This library was in its latest release only tested and considered for single
threaded operation. TODO
The *PTN Engine* is thread safe.

### Code Coverage
No analysis or compilation metrics at this point.
Expand Down Expand Up @@ -235,8 +235,8 @@ another only for the *PTN Engine* itself.
Doxygen can be used to generate this part of the documentation.

### User Guide
This document, or collection of documents, explains how the user can integrate
the *PTN Engine* in his own program and how to use all features of the engine.
Explains how the user can integrate the *PTN Engine* in his own program and
how to use all features of the engine.
The user guide is available at ```/Doc/User Guide```.

### Test Reports
Expand Down
153 changes: 35 additions & 118 deletions Doc/User Guide/UserGuide.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,143 +26,60 @@ include the directory "PTN_Engine/include".
**Note**: You should use the same compiler and compiler settings for the
*PTN Engine* and for your application to guarantee binary compatibility.

### 2. Create a class you wish to control with a Petri net.
### 2. Create your own *PTN Engine* instance.

The intention behind the engine is to control some process with a Petri net.
The object to be controlled should have its own class.

For this example let's assume the class to be controlled is called Controller.
Create a PTN_Engine and select on of the ACTIONS_THREAD_OPTION options available.
object. Example:

```c++

class Controller
{
public:

// Contains public methods that can be invoked by PTN Engine
// These are of two types:
// void Action();
// and
// bool Condition() const;

//Example of some action methods

void onEnterAction2();
void onExitAction2();

//Example of some additional activation condition methods

bool isCondition1() const;
bool isCondition2() const;

. . .
};
using namespace ptne;
PTN_Engine pn(PTN_Engine::ACTIONS_THREAD_OPTION::SINGLE_THREAD);

```
### 3. Create your own *PTN Engine* derived class.

Create a class that inherits privately from PTN_Engine and that accepts a shared
pointer to a class whose methods are to be invoked by the net.
### 3. Create the action functions
These are the functions you want to invoke when a token enters or exits a given
place.
Example:
```c++

#include "PTN_Engine/PTN_Engine.h"

class MyPetriNet: private ptne::PTN_Engine
{
public:
MyPetriNet(std::shared_ptr<Controller> ptrController);

. . .

ActionFunction compute = [&x, &result](){
result *= x;
if (x > 0)
{
--x;
}
};
```

### 4. Implement the Petri net
In the constructor of the class that inherits from PTN_Engine (MyPetriNet in
this example) is where the Petri net is defined.
#### 4.1 Create the Petri net places
These can be any kind of functions as long as they return void, take no arguments
and are accessible to the PTN_Engine object.

The first step is to create *all* the places in the net.
### 4. Create the condition functions

This is optional. If you want to add some additional conditions to the
transition's activation, now is the moment to do it.
Example:
```c++
MyPetriNet::MyPetriNet(std::shared_ptr<Controller> ptrMenuController):
PTN_Engine()
{
//Example of an input place without actions associated
addPlace(
"Place1", //Place name
0, //Initial number of tokens
nullptr, //No on enter actions
nullptr, //No on exit actions
true //Marked as input place
);
//Example of a place with on enter and on exit actions
addPlace(
"Place2", //Place name
1, //Initial number of tokens
std::bind(&Controller::onEnterAction2, ptrController), //on enter action
std::bind(&Controller::onExitAction2, ptrController), //on exit action
);
ConditionFunction finished = [&x](){return x <= 1;};
```
These can be any kind of functions as long as they return bool, take no arguments
and are accessible to the PTN_Engine object.
#### 4.2 Create the Petri net transitions

The last step is to create *all* transitions in the net.
#### 5 Create the Petri net's places
Create *all* places in the Petri net.
Example:
```c++

//Example of a transition without additional conditions
createTransition(
{"Place1", "Place2"}, //Activation places
{"Place3"}, //Destination places
{} //Additional conditions
);

//Example of a transition with additional conditions
createTransition(
{"InputC", "ShowMessage"}, //Activation places
{"MessagesMenu"}, //Destination places
//Vector of addditional conditions
{
std::bind(&Controller::isCondition1, ptrController),
std::bind(&Controller::isCondition2, ptrController),
}
);

. . .

pn.createPlace("Compute", 0, compute, true);
pn.createPlace("Finished", 0);
```

### 5 - Create access to input places
To control the PTN Engine net, you need to provide access to it via public
methods in your new class.
#### 7 Create the Petri net's transitions

The last step is to create *all* transitions in the net.
Example:
```c++
#include "PTN_Engine/PTN_Engine.h"
class MyPetriNet: private ptne::PTN_Engine
{
public:
MyPetriNet(std::shared_ptr<Controller> ptrController);
. . .
void someTrigger()
{
incrementInputPlace("someInputPlace");
execute();
}
. . .
pn.createTransition({"Compute"}, {"Finished"}, {finished});
pn.createTransition({"Compute"}, {"Compute"}, {notFinished});
```
3 changes: 2 additions & 1 deletion Examples/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# This file is part of PTN Engine
#
# Copyright (c) 2017 Eduardo Valgôde
# 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.
Expand All @@ -17,6 +17,7 @@

cmake_minimum_required (VERSION 3.8)

add_subdirectory(Factorial)
add_subdirectory(PhoneMenu)
add_subdirectory(Elevator)
if(BUILD_IMPORT_EXPORT)
Expand Down
Loading

0 comments on commit 4acd770

Please sign in to comment.