From 02449a237c7ed4a349083523211c716966405f49 Mon Sep 17 00:00:00 2001 From: Mateusz Jakub Fila Date: Sun, 1 Mar 2026 21:12:35 +0100 Subject: [PATCH 1/5] rename exec_statuscode.hpp to statuscode.hpp --- examples/exec_reco.cpp | 2 +- examples/exec_task.cpp | 8 ++++---- examples/exec_tbb.cpp | 2 +- examples/{exec_statuscode.hpp => statuscode.hpp} | 0 4 files changed, 6 insertions(+), 6 deletions(-) rename examples/{exec_statuscode.hpp => statuscode.hpp} (100%) diff --git a/examples/exec_reco.cpp b/examples/exec_reco.cpp index 9219ae1..e1847eb 100644 --- a/examples/exec_reco.cpp +++ b/examples/exec_reco.cpp @@ -7,10 +7,10 @@ #include #include -#include "exec_statuscode.hpp" // StatusCodeImpl #include "exec_stream_await_sender.hpp" // stream_await_sender #include "exec_task_arena_scheduler.hpp" // TaskArenaScheduler #include "logging_utils.hpp" // log, format_name +#include "statuscode.hpp" // StatusCodeImpl namespace tools { struct Tag { diff --git a/examples/exec_task.cpp b/examples/exec_task.cpp index 7951cd2..40e4761 100644 --- a/examples/exec_task.cpp +++ b/examples/exec_task.cpp @@ -4,10 +4,10 @@ #include #include -#include "exec_backend.hpp" // std exec backend selection -#include "exec_statuscode.hpp" // exec StatusCodeImpl -#include "exec_timer.hpp" // TimerSender -#include "logging_utils.hpp" // log, format_name +#include "exec_backend.hpp" // std exec backend selection +#include "exec_timer.hpp" // TimerSender +#include "logging_utils.hpp" // log, format_name +#include "statuscode.hpp" // StatusCodeImpl namespace tools { struct Tag { diff --git a/examples/exec_tbb.cpp b/examples/exec_tbb.cpp index 191ec4e..0d2b760 100644 --- a/examples/exec_tbb.cpp +++ b/examples/exec_tbb.cpp @@ -7,10 +7,10 @@ #include #include "exec_backend.hpp" // std exec backend selection -#include "exec_statuscode.hpp" // exec StatusCodeImpl #include "exec_task_arena_scheduler.hpp" // TaskArenaScheduler/// TaskArenaSchduler #include "exec_timer.hpp" // TimerSender #include "logging_utils.hpp" // log, format_name +#include "statuscode.hpp" // StatusCodeImpl namespace tools { struct Tag { diff --git a/examples/exec_statuscode.hpp b/examples/statuscode.hpp similarity index 100% rename from examples/exec_statuscode.hpp rename to examples/statuscode.hpp From a5bfce99b928290e5531b11ea588b44a2fed11d5 Mon Sep 17 00:00:00 2001 From: Mateusz Jakub Fila Date: Sun, 1 Mar 2026 21:20:34 +0100 Subject: [PATCH 2/5] add task example with boost.capy --- CMakeLists.txt | 22 +++++ examples/CMakeLists.txt | 11 +++ examples/capy_task.cpp | 159 +++++++++++++++++++++++++++++++++++++ examples/capy_timer.hpp | 37 +++++++++ extern/capy/CMakeLists.txt | 22 +++++ 5 files changed, 251 insertions(+) create mode 100644 examples/capy_task.cpp create mode 100644 examples/capy_timer.hpp create mode 100644 extern/capy/CMakeLists.txt diff --git a/CMakeLists.txt b/CMakeLists.txt index a1aec6a..352a309 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -82,6 +82,28 @@ if(BUILD_TBB) endif() endif() +### capy options + +option(BUILD_CAPY "Build the capy sources included in CoroutineTests" TRUE) + +if (USE_SYSTEM_LIBS) + set(USE_SYSTEM_CAPY_DEFAULT ON) +else() + set(USE_SYSTEM_CAPY_DEFAULT OFF) +endif() +option(USE_SYSTEM_CAPY + "Pick up an existing installation of capy from the build environment" + ${USE_SYSTEM_CAPY_DEFAULT}) +unset(USE_SYSTEM_CAPY_DEFAULT) + +if(BUILD_CAPY) + if(USE_SYSTEM_CAPY) + find_package(capy REQUIRED) + else() + add_subdirectory(extern/capy) + endif() +endif() + ### CUDA options option(BUILD_CUDA "Build with CUDA support" OFF) diff --git a/examples/CMakeLists.txt b/examples/CMakeLists.txt index 788a397..7661745 100644 --- a/examples/CMakeLists.txt +++ b/examples/CMakeLists.txt @@ -56,6 +56,17 @@ if(BUILD_BEMAN_TASK) endif() endif() + +if(BUILD_CAPY) + add_executable(capy_task capy_task.cpp) + target_link_libraries(capy_task PRIVATE CoroutineTests Boost::capy) + # if (BUILD_TBB) + # add_executable(exec_tbb_capy exec_tbb.cpp) + # target_link_libraries(exec_tbb_capy PRIVATE CoroutineTests capy::capy TBB::tbb) + # target_compile_definitions(exec_tbb_capy PUBLIC "USE_CAPY") + # endif() +endif() + if(BUILD_CUDA AND BUILD_TBB) add_executable(alien_reco alien_reco.cpp) target_link_libraries(alien_reco PRIVATE CoroutineTests CUDA::cudart TBB::tbb) diff --git a/examples/capy_task.cpp b/examples/capy_task.cpp new file mode 100644 index 0000000..7e59bc8 --- /dev/null +++ b/examples/capy_task.cpp @@ -0,0 +1,159 @@ +#include +#include +#include +#include +#include +#include +#include + +#include "capy_timer.hpp" // TimerIoAwaitable +#include "logging_utils.hpp" // log, format_name +#include "statuscode.hpp" // StatusCodeImpl + +namespace tools { +struct Tag { + static constexpr const char* name = "tools"; +}; +using StatusCode = StatusCodeImpl; +} // namespace tools + +namespace algs { +struct Tag { + static constexpr const char* name = "algs"; +}; +using StatusCode = StatusCodeImpl; +} // namespace algs + +template +class VerboseExecutor { + + public: + VerboseExecutor(Ex& ex) : m_executor(&ex) { + static_assert(boost::capy::Executor>, + "VerboseExecutor should be a valid capy Executor"); + } + + auto post(std::coroutine_handle<> h) const { + log() << "executor posting new work item" << std::endl; + m_executor->post(h); + } + auto dispatch(std::coroutine_handle<> h) const { + log() << "executor dispatching new work item" << std::endl; + return m_executor->dispatch(h); + } + auto& context() const noexcept { return m_executor->context(); } + auto on_work_started() const noexcept { + log() << "executor work started" << std::endl; + m_executor->on_work_started(); + } + auto on_work_finished() const noexcept { + log() << "executor work finished" << std::endl; + m_executor->on_work_finished(); + } + bool operator==(const VerboseExecutor& other) const noexcept { + return (*m_executor) == (*other.m_executor); + } + + private: + Ex* m_executor; +}; + +boost::capy::task tool1_execute(std::string_view parent) { + const auto self = format_name(parent, "tool1"); + + log(self) << "Calling async API in tool1" << std::endl; + auto status = co_await TimerIoAwaitable{std::chrono::milliseconds(100), + timer::StatusCode::SUCCESS, self}; + log(self) << "Result from async API in tool1: " << status << std::endl; + + log(self) << "Finishing tool1" << std::endl; + co_return tools::StatusCode::FAILURE; +} + +boost::capy::task tool2_execute(std::string_view parent) { + const auto self = format_name(parent, "tool2"); + + log(self) << "Calling async API in tool2" << std::endl; + auto status1 = co_await TimerIoAwaitable{std::chrono::milliseconds(10), + timer::StatusCode::SUCCESS, self}; + log(self) << "Result from async API in tool2: " << status1 << std::endl; + + log(self) << "Launching tool1" << std::endl; + auto code = co_await tool1_execute(self); + log(self) << "Result from tool1: " << code << std::endl; + + log(self) << "Calling async API in tool2" << std::endl; + auto status2 = co_await TimerIoAwaitable{std::chrono::milliseconds(10), + timer::StatusCode::FAILURE, self}; + log(self) << "Result from async API in tool2: " << status2 << std::endl; + + log(self) << "Finishing tool2" << std::endl; + co_return tools::StatusCode::SUCCESS; +} + +boost::capy::task tool3_execute(std::string_view parent) { + const auto self = format_name(parent, "tool3"); + log(self) << "Finishing tool3" << std::endl; + co_return tools::StatusCode::FAILURE; +} + +boost::capy::task algorithm_execute(std::string_view parent) { + const auto self = format_name(parent, "algorithm"); + + log(self) << "Calling async API in algorithm" << std::endl; + auto status1 = co_await TimerIoAwaitable{std::chrono::milliseconds(42), + timer::StatusCode::SUCCESS, self}; + log(self) << "Result from async API in algorithm: " << status1 << std::endl; + + log(self) << "Launching tool1" << std::endl; + auto code1 = co_await tool1_execute(self); + log(self) << "Result from tool1: " << code1 << std::endl; + + log(self) << "Calling async API in algorithm" << std::endl; + auto status2 = co_await TimerIoAwaitable{std::chrono::milliseconds(17), + timer::StatusCode::FAILURE, self}; + log(self) << "Result from async API in algorithm: " << status2 << std::endl; + + log(self) << "Launching tool2" << std::endl; + auto code2 = co_await tool2_execute(self); + log(self) << "Result from tool2: " << code2 << std::endl; + + log(self) << "Launching tool3" << std::endl; + auto code3 = co_await tool3_execute(self); + log(self) << "Result from tool3: " << code3 << std::endl; + + log(self) << "Finishing algorithm" << std::endl; + co_return algs::StatusCode::SUCCESS; +} + +int main() { + log() << "main Starting" << std::endl; + + auto pool = boost::capy::thread_pool(4); + auto pool_executor = pool.get_executor(); + auto verbose_executor = VerboseExecutor(pool_executor); + + auto condition = std::condition_variable(); + auto mutex = std::mutex(); + auto final_result = algs::StatusCode{}; + auto result_handler = [&condition, &mutex, + &final_result](algs::StatusCode code) { + final_result = code; + std::lock_guard lock(mutex); + condition.notify_one(); + }; + + log() << "main launching algorithm" << std::endl; + boost::capy::run_async(verbose_executor, + result_handler)(algorithm_execute("main")); + + { + log() << "main waiting for algorithm to finish..." << std::endl; + std::unique_lock lock(mutex); + condition.wait(lock); + } + log() << "Final status of algorithm " << final_result << std::endl; + + log() << "main Done" << std::endl; + return EXIT_SUCCESS; +} diff --git a/examples/capy_timer.hpp b/examples/capy_timer.hpp new file mode 100644 index 0000000..d8a591a --- /dev/null +++ b/examples/capy_timer.hpp @@ -0,0 +1,37 @@ +#pragma once + +#include +#include +#include +#include + +#include "logging_utils.hpp" // log, format_name +#include "statuscode.hpp" // StatusCodeImpl + +namespace timer { +struct Tag { + static constexpr const char* name = "timer"; +}; +using StatusCode = StatusCodeImpl; +} // namespace timer + +struct TimerIoAwaitable { + std::chrono::milliseconds delay; + timer::StatusCode status_code; + std::string_view parent; + + bool await_ready() const noexcept { return false; } + + void await_suspend(std::coroutine_handle<> handle, + boost::capy::io_env const* env) noexcept { + std::thread([this, handle, env]() { + const auto self = format_name(parent, "TimerIoAwaitable"); + log(self) << "Async operation started, will take " << delay.count() + << " ms" << std::endl; + std::this_thread::sleep_for(delay); + log(self) << "Async operation finished" << std::endl; + env->executor.post(handle); + }).detach(); + } + timer::StatusCode await_resume() const noexcept { return status_code; } +}; diff --git a/extern/capy/CMakeLists.txt b/extern/capy/CMakeLists.txt new file mode 100644 index 0000000..7761a5a --- /dev/null +++ b/extern/capy/CMakeLists.txt @@ -0,0 +1,22 @@ +cmake_minimum_required(VERSION 3.25) +include(FetchContent) + +# Tell the user what's happening. +message(STATUS "Building capy as part of the CoroutineTests project") + +# Declare where to get stdexec from. +set(COROUTINETESTS_CAPY_SOURCE + "URL;https://github.com/cppalliance/capy/archive/df92ffbb0670c06ebf0f201da73f06d1385d5d9b.zip;URL_MD5;d6b6e1e25684986d17ae92c13f992cfc" + CACHE STRING "Source for capy, when built as part of this project") + +mark_as_advanced(COROUTINETESTS_CAPY_SOURCE) +FetchContent_Declare(capy SYSTEM ${COROUTINETESTS_CAPY_SOURCE}) + +# Turn off build tests, examples, and docs. +set(BOOST_CAPY_BUILD_TESTS FALSE) +set(BOOST_CAPY_BUILD_EXAMPLES FALSE) +set(BOOST_CAPY_BUILD_BENCH FALSE) +set(BOOST_CAPY_MRDOCS_BUILD FALSE) + +# Get it into the current directory. +FetchContent_MakeAvailable(capy) From 68912c08bac3e4862a0eeaf88c2132c20ac2f30f Mon Sep 17 00:00:00 2001 From: Mateusz Jakub Fila Date: Sun, 1 Mar 2026 22:25:48 +0100 Subject: [PATCH 3/5] add capy tbb example --- examples/CMakeLists.txt | 9 +- examples/capy_task_arena_executor.hpp | 46 +++++++++ examples/capy_tbb.cpp | 128 ++++++++++++++++++++++++++ 3 files changed, 178 insertions(+), 5 deletions(-) create mode 100644 examples/capy_task_arena_executor.hpp create mode 100644 examples/capy_tbb.cpp diff --git a/examples/CMakeLists.txt b/examples/CMakeLists.txt index 7661745..a349754 100644 --- a/examples/CMakeLists.txt +++ b/examples/CMakeLists.txt @@ -60,11 +60,10 @@ endif() if(BUILD_CAPY) add_executable(capy_task capy_task.cpp) target_link_libraries(capy_task PRIVATE CoroutineTests Boost::capy) - # if (BUILD_TBB) - # add_executable(exec_tbb_capy exec_tbb.cpp) - # target_link_libraries(exec_tbb_capy PRIVATE CoroutineTests capy::capy TBB::tbb) - # target_compile_definitions(exec_tbb_capy PUBLIC "USE_CAPY") - # endif() + if (BUILD_TBB) + add_executable(capy_tbb capy_tbb.cpp) + target_link_libraries(capy_tbb PRIVATE CoroutineTests Boost::capy TBB::tbb) + endif() endif() if(BUILD_CUDA AND BUILD_TBB) diff --git a/examples/capy_task_arena_executor.hpp b/examples/capy_task_arena_executor.hpp new file mode 100644 index 0000000..fd875dd --- /dev/null +++ b/examples/capy_task_arena_executor.hpp @@ -0,0 +1,46 @@ +#include + +#include +#include + +class TaskArenaContext : public boost::capy::execution_context { + public: + TaskArenaContext(tbb::task_arena& arena) : m_arena(&arena) {} + + void schedule(std::coroutine_handle<> h) const { + m_arena->enqueue([h]() { h.resume(); }); + } + bool operator==(const TaskArenaContext& other) const noexcept { + return m_arena == other.m_arena; + } + + private: + tbb::task_arena* m_arena; +}; + +class TaskArenaExecutor { + + public: + TaskArenaExecutor(TaskArenaContext& context) noexcept + : m_context(&context) { + static_assert(boost::capy::Executor, + "TaskArenaExecutor should be a valid capy Executor"); + } + + TaskArenaExecutor(TaskArenaExecutor const&) noexcept = default; + + std::coroutine_handle<> dispatch(std::coroutine_handle<> h) const { + m_context->schedule(h); + return std::noop_coroutine(); + } + void post(std::coroutine_handle<> h) const { m_context->schedule(h); } + TaskArenaContext& context() const noexcept { return *m_context; } + void on_work_started() const noexcept {} + void on_work_finished() const noexcept {} + bool operator==(const TaskArenaExecutor& other) const noexcept { + return m_context == other.m_context; + } + + private: + TaskArenaContext* m_context; +}; diff --git a/examples/capy_tbb.cpp b/examples/capy_tbb.cpp new file mode 100644 index 0000000..6baf745 --- /dev/null +++ b/examples/capy_tbb.cpp @@ -0,0 +1,128 @@ +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "capy_task_arena_executor.hpp" // TaskArenaExecutor +#include "capy_timer.hpp" // TimerIoAwaitable +#include "logging_utils.hpp" // log, format_name +#include "statuscode.hpp" // StatusCodeImpl + +namespace tools { +struct Tag { + static constexpr const char* name = "tools"; +}; +using StatusCode = StatusCodeImpl; +} // namespace tools + +namespace algs { +struct Tag { + static constexpr const char* name = "algs"; +}; +using StatusCode = StatusCodeImpl; +} // namespace algs + +boost::capy::task tool1_execute(std::string_view parent) { + const auto self = format_name(parent, "tool1"); + + log(self) << "Calling async API in tool1" << std::endl; + auto status = co_await TimerIoAwaitable{std::chrono::milliseconds(100), + timer::StatusCode::SUCCESS, self}; + log(self) << "Result from async API in tool1: " << status << std::endl; + + log(self) << "Finishing tool1" << std::endl; + co_return tools::StatusCode::FAILURE; +} + +boost::capy::task tool2_execute(std::string_view parent) { + const auto self = format_name(parent, "tool2"); + + log(self) << "Calling async API in tool2" << std::endl; + auto status1 = co_await TimerIoAwaitable{std::chrono::milliseconds(10), + timer::StatusCode::SUCCESS, self}; + log(self) << "Result from async API in tool2: " << status1 << std::endl; + + log(self) << "Launching tool1" << std::endl; + auto code = co_await tool1_execute(self); + log(self) << "Result from tool1: " << code << std::endl; + + log(self) << "Calling async API in tool2" << std::endl; + auto status2 = co_await TimerIoAwaitable{std::chrono::milliseconds(10), + timer::StatusCode::FAILURE, self}; + log(self) << "Result from async API in tool2: " << status2 << std::endl; + + log(self) << "Finishing tool2" << std::endl; + co_return tools::StatusCode::SUCCESS; +} + +boost::capy::task tool3_execute(std::string_view parent) { + const auto self = format_name(parent, "tool3"); + log(self) << "Finishing tool3" << std::endl; + co_return tools::StatusCode::FAILURE; +} + +boost::capy::task algorithm_execute(std::string_view parent) { + const auto self = format_name(parent, "algorithm"); + + log(self) << "Calling async API in algorithm" << std::endl; + auto status1 = co_await TimerIoAwaitable{std::chrono::milliseconds(42), + timer::StatusCode::SUCCESS, self}; + log(self) << "Result from async API in algorithm: " << status1 << std::endl; + + log(self) << "Launching tool1" << std::endl; + auto code1 = co_await tool1_execute(self); + log(self) << "Result from tool1: " << code1 << std::endl; + + log(self) << "Calling async API in algorithm" << std::endl; + auto status2 = co_await TimerIoAwaitable{std::chrono::milliseconds(17), + timer::StatusCode::FAILURE, self}; + log(self) << "Result from async API in algorithm: " << status2 << std::endl; + + log(self) << "Launching tool2" << std::endl; + auto code2 = co_await tool2_execute(self); + log(self) << "Result from tool2: " << code2 << std::endl; + + log(self) << "Launching tool3" << std::endl; + auto code3 = co_await tool3_execute(self); + log(self) << "Result from tool3: " << code3 << std::endl; + + log(self) << "Finishing algorithm" << std::endl; + co_return algs::StatusCode::SUCCESS; +} + +int main() { + log() << "main Starting" << std::endl; + + tbb::task_arena arena{2}; + auto context = TaskArenaContext(arena); + auto executor = TaskArenaExecutor(context); + + auto condition = std::condition_variable(); + auto mutex = std::mutex(); + auto final_result = algs::StatusCode{}; + auto result_handler = [&condition, &mutex, + &final_result](algs::StatusCode code) { + final_result = code; + std::lock_guard lock(mutex); + condition.notify_one(); + }; + + boost::capy::run_async(executor, result_handler)(algorithm_execute("main")); + + { + log() << "main waiting for algorithm to finish..." << std::endl; + std::unique_lock lock(mutex); + condition.wait(lock); + } + + log() << "Final status of algorithm " << final_result << std::endl; + // Block until all work items in the scope are done + log() << "main Done" << std::endl; + return EXIT_SUCCESS; +} From 696d9687a84dbab4afc8cfa88254284cb9f11314 Mon Sep 17 00:00:00 2001 From: Mateusz Jakub Fila Date: Sun, 1 Mar 2026 22:52:56 +0100 Subject: [PATCH 4/5] update readme --- examples/README.md | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/examples/README.md b/examples/README.md index b39b05c..6b6c685 100644 --- a/examples/README.md +++ b/examples/README.md @@ -102,7 +102,7 @@ This example shows usage of `task` coroutine return type from future C++26 stand Link: [exec_tbb.cpp](exec_tbb.cpp) -This is a variant of the "Exec task" example, but using a custom C++ senders/receivers scheduler to execute task coroutines on Intel TBB task arena. +This is a variant of the ["Exec task" example](#exec-task), but using a custom C++ senders/receivers scheduler to execute task coroutines on Intel TBB task arena. ## Alien @@ -144,6 +144,18 @@ Link: [alien_counting_scope.cpp](alien_counting_scope.cpp) This example demonstrates dynamic work submitting with `counting_scope` compatible with coroutine semantic as in ["Alien" example](#alien). `spawn` schedules execution of a coroutine that returns `void`. `join()` blocks the current thread until all submitted coroutines are finished (and rethrows the first exception captured from submitted work, if any). +## Capy task + +Link: [capy_task.cpp](capy_task.cpp) + +This is a variant of ["Exec task" example](#exec-task) using Boost.Capy and IoAwaitables protocol instead of C++26 execution. + +## Capy TBB + +Link: [capy_tbb.cpp](capy_tbb.cpp) + +This is a variant of ["Exec tbb" example](#exec-tbb) using Boost.Capy and IoAwaitables protocol instead of C++26 execution. This example shows implementation and usage of custom executor scheduling tasks on TBB task arena. + ## Reconstruction Link: [alien_reco.cpp](alien_reco.cpp) and [exec_reco.cpp](exec_reco.cpp) From 3a3037042c1d5b0038662f0ad52cc6bc6778e2d4 Mon Sep 17 00:00:00 2001 From: Mateusz Jakub Fila Date: Mon, 2 Mar 2026 00:11:50 +0100 Subject: [PATCH 5/5] check status in conditional variable wait --- examples/README.md | 4 ++-- examples/capy_task.cpp | 12 ++++++++---- examples/capy_tbb.cpp | 14 +++++++++----- examples/statuscode.hpp | 4 ++++ 4 files changed, 23 insertions(+), 11 deletions(-) diff --git a/examples/README.md b/examples/README.md index 6b6c685..a3886e5 100644 --- a/examples/README.md +++ b/examples/README.md @@ -148,13 +148,13 @@ This example demonstrates dynamic work submitting with `counting_scope` compatib Link: [capy_task.cpp](capy_task.cpp) -This is a variant of ["Exec task" example](#exec-task) using Boost.Capy and IoAwaitables protocol instead of C++26 execution. +This is a variant of ["Exec task" example](#exec-task) using Boost.Capy and IoAwaitables protocol ([p4003](https://www.open-std.org/JTC1/SC22/WG21/docs/papers/2026/p4003r0.pdf)) instead of C++26 execution. ## Capy TBB Link: [capy_tbb.cpp](capy_tbb.cpp) -This is a variant of ["Exec tbb" example](#exec-tbb) using Boost.Capy and IoAwaitables protocol instead of C++26 execution. This example shows implementation and usage of custom executor scheduling tasks on TBB task arena. +This is a variant of ["Exec tbb" example](#exec-tbb) using Boost.Capy and IoAwaitables protocol ([p4003](https://www.open-std.org/JTC1/SC22/WG21/docs/papers/2026/p4003r0.pdf)) instead of C++26 execution. This example shows implementation and usage of custom executor scheduling tasks on TBB task arena. ## Reconstruction diff --git a/examples/capy_task.cpp b/examples/capy_task.cpp index 7e59bc8..7466cdc 100644 --- a/examples/capy_task.cpp +++ b/examples/capy_task.cpp @@ -138,8 +138,10 @@ int main() { auto final_result = algs::StatusCode{}; auto result_handler = [&condition, &mutex, &final_result](algs::StatusCode code) { - final_result = code; - std::lock_guard lock(mutex); + { + std::lock_guard lock(mutex); + final_result = code; + } condition.notify_one(); }; @@ -149,8 +151,10 @@ int main() { { log() << "main waiting for algorithm to finish..." << std::endl; - std::unique_lock lock(mutex); - condition.wait(lock); + auto lock = std::unique_lock(mutex); + condition.wait(lock, [&final_result]() { + return final_result != algs::StatusCode::UNDEFINED; + }); } log() << "Final status of algorithm " << final_result << std::endl; diff --git a/examples/capy_tbb.cpp b/examples/capy_tbb.cpp index 6baf745..97e2d8a 100644 --- a/examples/capy_tbb.cpp +++ b/examples/capy_tbb.cpp @@ -99,7 +99,7 @@ boost::capy::task algorithm_execute(std::string_view parent) { int main() { log() << "main Starting" << std::endl; - tbb::task_arena arena{2}; + auto arena = tbb::task_arena(2); auto context = TaskArenaContext(arena); auto executor = TaskArenaExecutor(context); @@ -108,8 +108,10 @@ int main() { auto final_result = algs::StatusCode{}; auto result_handler = [&condition, &mutex, &final_result](algs::StatusCode code) { - final_result = code; - std::lock_guard lock(mutex); + { + std::lock_guard lock(mutex); + final_result = code; + } condition.notify_one(); }; @@ -117,8 +119,10 @@ int main() { { log() << "main waiting for algorithm to finish..." << std::endl; - std::unique_lock lock(mutex); - condition.wait(lock); + auto lock = std::unique_lock(mutex); + condition.wait(lock, [&final_result]() { + return final_result != algs::StatusCode::UNDEFINED; + }); } log() << "Final status of algorithm " << final_result << std::endl; diff --git a/examples/statuscode.hpp b/examples/statuscode.hpp index e144c0f..aa4c70f 100644 --- a/examples/statuscode.hpp +++ b/examples/statuscode.hpp @@ -7,8 +7,12 @@ class StatusCodeImpl { enum class Status { SUCCESS = 0, FAILURE = 1, UNDEFINED = 2 }; inline static const StatusCodeImpl SUCCESS{Status::SUCCESS}; inline static const StatusCodeImpl FAILURE{Status::FAILURE}; + inline static const StatusCodeImpl UNDEFINED{Status::UNDEFINED}; StatusCodeImpl(Status status = Status::UNDEFINED) : m_status(status) {} + bool operator==(const StatusCodeImpl& other) const { + return m_status == other.m_status; + } Status status() const { return m_status; } private: