Skip to content

Commit

Permalink
Feature/adl experimenting (#46)
Browse files Browse the repository at this point in the history
* wip

* faster switching by allocating a new reducer queue

* make mermaid part of parsers

* recursive eventlogging

* wip adl

* wip 2

* formalizing direct mutation

* make getLog the only function

* rename some funcs

* simplify

* refactor with state

* nice refactor of fire loop

* remove html from ignore

* move to model

* remove remaining members

* thread id to class

* remove the class

* simpler reducer

* remove impl nullptr checks

* fail harder if the store is incomplete

* and undo the double queues

* small cleanup

* double checks

* cleaning cmake

* only trigger if net is still active

* getMarking

* cleaning
  • Loading branch information
thorstink authored Aug 11, 2023
1 parent b52d0a2 commit fc0414b
Show file tree
Hide file tree
Showing 24 changed files with 471 additions and 719 deletions.
13 changes: 9 additions & 4 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,23 +1,28 @@
cmake_minimum_required(VERSION 3.10)

# Read version from the package.xml file.
file(READ ${CMAKE_CURRENT_SOURCE_DIR}/package.xml package_xml_str)

if(NOT package_xml_str MATCHES "<version>([0-9]+.[0-9]+.[0-9]+)</version>")
message(FATAL_ERROR "Could not parse project version from package.xml. Aborting.")
endif()

project(symmetri VERSION ${CMAKE_MATCH_1})

set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_CXX_EXTENSIONS OFF)

set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-uninitialized -Wno-psabi -Wno-unused-parameter -Werror -Wall -Wextra -O3")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Werror -Wall -Wextra -pedantic")

if(BUILD_TESTING)
enable_testing()
if(ASAN_BUILD AND NOT TSAN_BUILD)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -g -fsanitize=address,undefined -fno-omit-frame-pointer -O0")
elseif(TSAN_BUILD AND NOT ASAN_BUILD)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -g -fsanitize=thread -fno-omit-frame-pointer -O0")
else()
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -flto -O3")
endif()
endif()

Expand All @@ -26,7 +31,7 @@ add_subdirectory(symmetri)

# some examples using the lib
if(BUILD_EXAMPLES)
add_subdirectory(examples/flight)
add_subdirectory(examples/hello_world)
add_subdirectory(examples/model_benchmark)
add_subdirectory(examples/flight)
add_subdirectory(examples/hello_world)
add_subdirectory(examples/model_benchmark)
endif()
46 changes: 17 additions & 29 deletions examples/flight/flight.cc
Original file line number Diff line number Diff line change
Expand Up @@ -5,45 +5,32 @@

#include "symmetri/parsers.h"
#include "symmetri/symmetri.h"
#include "symmetri/utilities.hpp"
#include "transition.hpp"

using namespace symmetri;
/**
* @brief We want to use the Foo class with Symmetri; Foo has nice
* functionalities such as Pause and Resume and it can also get
* preempted/cancelled. We need to define functions to let Symmetri use these
* functionalities. It is as simple by creating specialized version of the
* fire/cancel/isDirect/pause/resume functions. One does not need to implement
* fire/cancel/pause/resume functions. One does not need to implement
* all - if nothing is defined, a default version is used.
*
*/
namespace symmetri {

template <>
Result fire(const Foo &f) {
return f.fire() ? Result{{}, State::Error} : Result{{}, State::Completed};
}

template <>
Result cancel(const Foo &f) {
f.cancel();
return {{}, State::UserExit};
}

template <>
bool isDirect(const Foo &) {
return false;
}

template <>
void pause(const Foo &f) {
f.pause();
}
void pause(const Foo &f) { f.pause(); }

template <>
void resume(const Foo &f) {
f.resume();
}
} // namespace symmetri
void resume(const Foo &f) { f.resume(); }

/**
* @brief A simple printer for the eventlog
Expand Down Expand Up @@ -82,29 +69,29 @@ int main(int, char *argv[]) {
// Here we create the first PetriNet based on composing pnml1 and pnml2
// using flat composition. The associated transitions are two instance of
// the Foo-class.
symmetri::PetriNet subnet({pnml1, pnml2}, {{"P2", 1}},
{{"T0", Foo("SubFoo")}, {"T1", Foo("SubBar")}}, {},
"SubNet", pool);
PetriNet subnet({pnml1, pnml2}, {{"P2", 1}},
{{"T0", Foo("SubFoo")}, {"T1", Foo("SubBar")}}, {}, "SubNet",
pool);

// We create another PetriNet by flatly composing all three petri nets.
// Again we have 2 Foo-transitions, and the first transition (T0) is the
// subnet. This show how you can also nest PetriNets.
symmetri::PetriNet bignet(
{pnml1, pnml2, pnml3}, {{"P3", 5}},
{{"T0", subnet}, {"T1", Foo("Bar")}, {"T2", Foo("Foo")}}, {}, "RootNet",
pool);
PetriNet bignet({pnml1, pnml2, pnml3}, {{"P3", 5}},
{{"T0", subnet}, {"T1", Foo("Bar")}, {"T2", Foo("Foo")}}, {},
"RootNet", pool);

// a flag to check if we are running
std::atomic<bool> running(true);

// a thread that polls the eventlog and writes it to a file
auto gantt = std::thread([&] {
while (running) {
writeMermaidHtmlToFile(
symmetri::mermaidFromEventlog(bignet.getEventLog()));
std::this_thread::sleep_for(std::chrono::seconds(3));
if (!running) {
break;
}
writeMermaidHtmlToFile(symmetri::mermaidFromEventlog(getLog(bignet)));
}
writeMermaidHtmlToFile(symmetri::mermaidFromEventlog(bignet.getEventLog()));
});

// Parallel to the PetriNet execution, we run a thread through which we
Expand Down Expand Up @@ -141,7 +128,8 @@ int main(int, char *argv[]) {
// print the results and eventlog
spdlog::info("Result of this net: {0}", printState(result));
printLog(el);
t.join(); // clean up
gantt.join(); // clean up
t.join(); // clean up
writeMermaidHtmlToFile(symmetri::mermaidFromEventlog(el));
return 0;
}
Empty file removed examples/flight/mermaid.html
Empty file.
9 changes: 5 additions & 4 deletions examples/hello_world/main.cc
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
#include <thread>

#include "symmetri/symmetri.h"
#include "symmetri/utilities.hpp"

// Before main, we define a bunch of functions that can be bound to
// transitions in the petri net.
Expand Down Expand Up @@ -55,8 +56,8 @@ int main(int, char *argv[]) {
// store based on the petri net. You can specifiy a final marking, the amount
// of threads it can use (maximum amount of stuff it can do in parallel) and a
// name so the net is easy to identifiy in a log.
symmetri::PetriNet net({pnml_path_start, pnml_path_passive}, {}, store, {},
"CASE_X", pool);
PetriNet net({pnml_path_start, pnml_path_passive}, {}, store, {}, "CASE_X",
pool);

// We use a simple boolean flag to terminate the threads once the net
// finishes. Without it, these threads would prevent the program from cleanly
Expand Down Expand Up @@ -84,8 +85,8 @@ int main(int, char *argv[]) {
// becomes false.
});

auto [el, result] = symmetri::fire(net); // This function blocks until either
// the net completes, deadlocks
auto [el, result] = fire(net); // This function blocks until either
// the net completes, deadlocks
// or user requests exit (ctrl-c)
running.store(false); // We set this to false so the thread that we launched
// gets interrupted.
Expand Down
7 changes: 4 additions & 3 deletions examples/model_benchmark/model_benchmark.cc
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

#include "symmetri/parsers.h"
#include "symmetri/symmetri.h"
#include "symmetri/utilities.hpp"

int main(int, char *argv[]) {
spdlog::set_pattern("[%Y-%m-%d %H:%M:%S.%f] [%^%l%$] [thread %t] %v");
Expand All @@ -16,14 +17,14 @@ int main(int, char *argv[]) {
if (bolus) {
store.insert({t, []() {}});
} else {
store.insert({t, nullptr});
store.insert({t, DirectMutation{}});
}
}

symmetri::PetriNet bignet(net, m0, {}, store, {}, "pluto", pool);
PetriNet bignet(net, m0, {}, store, {}, "pluto", pool);
spdlog::info("start!");
const auto start_time = symmetri::Clock::now();
auto [el, result] = symmetri::fire(bignet); // infinite loop
auto [el, result] = fire(bignet); // infinite loop
const auto end_time = symmetri::Clock::now();
auto trans_count = el.size() / 2;
auto delta_t = (double((end_time - start_time).count()) / 1e9);
Expand Down
6 changes: 2 additions & 4 deletions symmetri/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
find_package(spdlog REQUIRED)

include(FetchContent)

FetchContent_Declare(
Expand All @@ -21,17 +19,17 @@ include_directories(include submodules)
#lib
add_library(${PROJECT_NAME} SHARED
tasks.cpp
symmetri.cc
model.cc
model_utilities.cc
pnml_parser.cc
grml_parser.cc
eventlog_parsers.cc
types.cpp
symmetri.cc
submodules/tinyxml2/tinyxml2.cpp
)
add_library(${PROJECT_NAME}::${PROJECT_NAME} ALIAS ${PROJECT_NAME})
target_link_libraries(${PROJECT_NAME} PUBLIC pthread PRIVATE concurrentqueue spdlog::spdlog)
target_link_libraries(${PROJECT_NAME} PUBLIC pthread PRIVATE concurrentqueue)

include(GenerateExportHeader)
generate_export_header(${PROJECT_NAME})
Expand Down
2 changes: 1 addition & 1 deletion symmetri/eventlog_parsers.cc
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ std::string mermaidFromEventlog(symmetri::Eventlog el) {

std::stringstream mermaid;
mermaid << "\n---\ndisplayMode : compact\n---\ngantt\ntitle A Gantt "
"Diagram\ndateFormat x\naxisFormat \%H:\%M:\%S\n";
"Diagram\ndateFormat x\naxisFormat %H:%M:%S\n";
std::string current_section("");
for (auto it = el.begin(); std::next(it) != el.end(); it = std::next(it)) {
const auto &start = *it;
Expand Down
27 changes: 16 additions & 11 deletions symmetri/include/symmetri/polytransition.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,8 @@
#include <memory>

#include "symmetri/types.h"
namespace symmetri {

struct DirectMutation {};

/**
* @brief Checks if the transition-function can be invoked.
Expand All @@ -15,7 +16,7 @@ namespace symmetri {
*/
template <typename T>
bool isDirect(const T &) {
return !std::is_invocable_v<T>;
return false;
}

/**
Expand All @@ -27,8 +28,8 @@ bool isDirect(const T &) {
* @return Result
*/
template <typename T>
Result cancel(const T &) {
return {{}, State::UserExit};
symmetri::Result cancel(const T &) {
return {{}, symmetri::State::UserExit};
}

/**
Expand Down Expand Up @@ -58,24 +59,28 @@ void resume(const T &) {}
* possible eventlog of the transition.
*/
template <typename T>
Result fire(const T &transition) {
if constexpr (!std::is_invocable_v<T>) {
return {{}, State::Completed};
} else if constexpr (std::is_same_v<State, decltype(transition())>) {
symmetri::Result fire(const T &transition) {
if constexpr (std::is_same_v<DirectMutation, T>) {
return {{}, symmetri::State::Completed};
} else if constexpr (std::is_same_v<symmetri::State,
decltype(transition())>) {
return {{}, transition()};
} else if constexpr (std::is_same_v<Result, decltype(transition())>) {
} else if constexpr (std::is_same_v<symmetri::Result,
decltype(transition())>) {
return transition();
} else {
transition();
return {{}, State::Completed};
return {{}, symmetri::State::Completed};
}
}

template <typename T>
Eventlog getLog(const T &) {
symmetri::Eventlog getLog(const T &) {
return {};
}

namespace symmetri {

/**
* @brief PolyTransition is a wrapper around any type that you want to tie to a
* transition. Typically this is an invokable object, such as a function, that
Expand Down
Loading

0 comments on commit fc0414b

Please sign in to comment.