Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature/adl experimenting #46

Merged
merged 27 commits into from
Aug 11, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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