From dfac66f41eee4453c39132df1a3600be95e4c512 Mon Sep 17 00:00:00 2001 From: Stefano Lusardi Date: Thu, 16 Mar 2023 00:39:26 +0100 Subject: [PATCH] Apply update_interval as soon as it is called. --- .gitignore | 2 ++ CMakeLists.txt | 2 +- examples/CMakeLists.txt | 6 ++-- examples/src/example_every.cpp | 9 ++---- examples/src/example_remove.cpp | 32 +++++++++++++++++++++ examples/src/example_update_interval.cpp | 36 ++++++++++++++---------- include/ssts/task_scheduler.hpp | 27 ++++++++++++------ scripts/valgrind/install.sh | 20 +++++++++++++ scripts/valgrind/run_callgrind.sh | 17 +++++++++++ scripts/valgrind/run_memcheck.sh | 19 +++++++++++++ 10 files changed, 136 insertions(+), 34 deletions(-) create mode 100644 examples/src/example_remove.cpp create mode 100755 scripts/valgrind/install.sh create mode 100755 scripts/valgrind/run_callgrind.sh create mode 100755 scripts/valgrind/run_memcheck.sh diff --git a/.gitignore b/.gitignore index 096a217..0132417 100644 --- a/.gitignore +++ b/.gitignore @@ -5,6 +5,8 @@ **/results **/unit_tests **/profiles +**/memcheck +**/callgrind **/logs **/.cache **/.clangd diff --git a/CMakeLists.txt b/CMakeLists.txt index 3632c61..bbdb051 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -25,7 +25,7 @@ option(SSTS_BUILD_TESTS "Build library tests" True) option(SSTS_BUILD_EXAMPLES "Build library examples" True) option(SSTS_INSTALL_LIBRARY "Install library" False) option(SSTS_INSTALL_EXAMPLES "Install examples (requires installing library and building examples)" False) -option(SSTS_ENABLE_SANITIZERS "Run unit tests with Thread Sanitizer support" True) +option(SSTS_ENABLE_SANITIZERS "Run unit tests with Thread Sanitizer support" False) if(${SSTS_ENABLE_SANITIZERS}) message(STATUS "::ssTs:: Sanitizers enabled") diff --git a/examples/CMakeLists.txt b/examples/CMakeLists.txt index 0d4e156..1dc27a7 100644 --- a/examples/CMakeLists.txt +++ b/examples/CMakeLists.txt @@ -6,9 +6,6 @@ function(add_example EXAMPLE_TARGET) add_executable(${EXAMPLE_TARGET} src/${EXAMPLE_TARGET}.cpp) target_link_libraries(${EXAMPLE_TARGET} PRIVATE ssts::ssts PRIVATE spdlog::spdlog) target_compile_features(${EXAMPLE_TARGET} PRIVATE cxx_std_17) - # if(UNIX) - # target_link_libraries(${EXAMPLE_TARGET} PRIVATE pthread) - # endif() if(${SSTS_INSTALL_EXAMPLES}) install(TARGETS ${EXAMPLE_TARGET} RUNTIME DESTINATION "${CMAKE_INSTALL_BINDIR}") @@ -24,4 +21,5 @@ add_example(example_nested) add_example(example_bind) add_example(example_update_interval) add_example(example_every) -add_example(example_unordered) \ No newline at end of file +add_example(example_unordered) +add_example(example_remove) \ No newline at end of file diff --git a/examples/src/example_every.cpp b/examples/src/example_every.cpp index 2d2983b..86fa400 100644 --- a/examples/src/example_every.cpp +++ b/examples/src/example_every.cpp @@ -1,14 +1,11 @@ #include -#include - #include - #include "utils/utils.hpp" int main() { - ssts::utils::log(ssts::version()); spdlog::set_pattern("[%H:%M:%S.%e] %v"); + spdlog::info(ssts::version()); ssts::task_scheduler s(8); s.set_duplicate_allowed(false); @@ -36,9 +33,9 @@ int main() std::this_thread::sleep_for(10s); - ssts::utils::log("Task Scheduler shutdown"); + spdlog::info("Task Scheduler shutdown"); s.stop(); - ssts::utils::log("Task Scheduler finished"); + spdlog::info("Task Scheduler finished"); return 0; } diff --git a/examples/src/example_remove.cpp b/examples/src/example_remove.cpp new file mode 100644 index 0000000..8cffb5a --- /dev/null +++ b/examples/src/example_remove.cpp @@ -0,0 +1,32 @@ +#include +#include +#include "utils/utils.hpp" + +int main() +{ + spdlog::set_pattern("[%H:%M:%S.%e] %v"); + spdlog::info(ssts::version()); + + ssts::task_scheduler s(8); + s.start(); + + ssts::utils::timer t; + + s.in("Foo"s, 2s, []{ spdlog::info("Foo"); }); + s.in("Bar"s, 3s, []{ spdlog::info("Bar"); }); + + spdlog::info("before remove"); + std::this_thread::sleep_for(2s); + + s.remove_task("foo"s); // Wrong task ID + s.remove_task("Bar"s); + + spdlog::info("after remove"); + std::this_thread::sleep_for(2s); + + spdlog::info("Task Scheduler shutdown"); + s.stop(); + + spdlog::info("Task Scheduler finished"); + return 0; +} diff --git a/examples/src/example_update_interval.cpp b/examples/src/example_update_interval.cpp index 6d1be06..6c28d86 100644 --- a/examples/src/example_update_interval.cpp +++ b/examples/src/example_update_interval.cpp @@ -1,29 +1,35 @@ #include - +#include #include "utils/utils.hpp" -void t_update_interval() +int main() { - ssts::utils::log_test("Update Interval"); - ssts::task_scheduler s(2); + spdlog::set_pattern("[%H:%M:%S.%e] %v"); + spdlog::info(ssts::version()); + + ssts::task_scheduler s(8); + s.start(); + ssts::utils::timer t; + + s.every("Foo"s, 2s, []{ spdlog::info("Foo"); }); + + s.every("Bar"s, 2s, []{ spdlog::info("Bar"); }); - s.every("task_id"s, 250ms, []{ std::cout << "Hi!" << std::endl; }); + s.in(1ms, []{ spdlog::info("one millis!"); }); - ssts::utils::log("before update"); + spdlog::info("before update"); std::this_thread::sleep_for(3s); - s.update_interval("task_id"s, 1s); - ssts::utils::log("after update"); - std::this_thread::sleep_for(4s); -} + s.update_interval("foo"s, 100ms); // Wrong task ID + s.update_interval("Bar"s, 100ms); -int main() -{ - ssts::utils::log(ssts::version()); + spdlog::info("after update"); + std::this_thread::sleep_for(2s); - t_update_interval(); + spdlog::info("Task Scheduler shutdown"); + s.stop(); - ssts::utils::log("Task Scheduler finished"); + spdlog::info("Task Scheduler finished"); return 0; } diff --git a/include/ssts/task_scheduler.hpp b/include/ssts/task_scheduler.hpp index 9cc17ba..ddd1bad 100644 --- a/include/ssts/task_scheduler.hpp +++ b/include/ssts/task_scheduler.hpp @@ -9,6 +9,7 @@ #include #include #include +#include #include #include #include @@ -351,15 +352,26 @@ class task_scheduler */ bool update_interval(const std::string& task_id, ssts::clock::duration interval) { - std::scoped_lock lock(_update_tasks_mtx); + std::unique_lock lock(_update_tasks_mtx); - if (auto task = get_task_iterator(task_id); task != _tasks.end() - && task->second.interval().has_value()) + if (auto task_iterator = get_task_iterator(task_id); task_iterator != _tasks.end() && task_iterator->second.interval().has_value()) { - task->second.set_interval(interval); + const auto task_interval = task_iterator->second.interval().value(); + auto task_next_start_time = task_iterator->first - task_interval; + + const auto now = ssts::clock::now(); + while(now > task_next_start_time) + task_next_start_time += interval; + + task_iterator->second.set_interval(interval); + _tasks.emplace(std::move(task_next_start_time), std::move(task_iterator->second)); + _tasks.erase(task_iterator); + lock.unlock(); + + _update_tasks_cv.notify_one(); return true; } - + return false; } @@ -493,11 +505,10 @@ class task_scheduler { std::scoped_lock lock(_update_tasks_mtx); - // if (!_is_duplicate_allowed && already_exists(st.hash())) - // return; + if (already_exists(st.hash())) + return; _tasks.emplace(std::move(timepoint), std::move(st)); - _next_task_timepoint = _tasks.begin()->first; } _update_tasks_cv.notify_one(); diff --git a/scripts/valgrind/install.sh b/scripts/valgrind/install.sh new file mode 100755 index 0000000..65b1a89 --- /dev/null +++ b/scripts/valgrind/install.sh @@ -0,0 +1,20 @@ +cd ~/Downloads + +sudo apt remove --purge valgrind -y + +wget https://sourceware.org/pub/valgrind/valgrind-3.20.0.tar.bz2 +tar xvf valgrind-3.20.0.tar.bz2 + +export CC=gcc-12 + +cd valgrind-3.20.0 +./configure +make +sudo make install + +cd .. +rm -r valgrind-3.20.0 +rm -r valgrind-3.20.0.tar.bz2 + +echo "" +valgrind --version diff --git a/scripts/valgrind/run_callgrind.sh b/scripts/valgrind/run_callgrind.sh new file mode 100755 index 0000000..2283c3c --- /dev/null +++ b/scripts/valgrind/run_callgrind.sh @@ -0,0 +1,17 @@ +mkdir -p callgrind + +valgrind --tool=callgrind \ + --callgrind-out-file=callgrind/callgrind.out \ + --verbose \ + --log-file=callgrind/callgrind.log \ + --error-exitcode=1 \ + ./build/Debug/examples/example_remove + + # --exit-on-first-error=yes \ + +# callgrind_annotate --auto=yes callgrind.out + +ret=$? +echo "" +echo "callgrind exit code: " $ret +exit $ret \ No newline at end of file diff --git a/scripts/valgrind/run_memcheck.sh b/scripts/valgrind/run_memcheck.sh new file mode 100755 index 0000000..0f63ed7 --- /dev/null +++ b/scripts/valgrind/run_memcheck.sh @@ -0,0 +1,19 @@ +mkdir -p memcheck + +valgrind --tool=memcheck \ + --leak-check=full \ + --show-leak-kinds=all \ + --track-origins=yes \ + --verbose \ + --xml=yes \ + --xml-file=memcheck/memcheck.xml \ + --log-file=memcheck/memcheck.log \ + --error-exitcode=1 \ + ./build/Debug/examples/example_remove + + # --exit-on-first-error=yes \ + +ret=$? +echo "" +echo "memcheck exit code: " $ret +exit $ret \ No newline at end of file