diff --git a/conanfile.py b/conanfile.py index 0c5ef0f..5e18c81 100644 --- a/conanfile.py +++ b/conanfile.py @@ -54,7 +54,7 @@ def _min_cppstd(self): def _compilers_minimum_version(self): # We may reduce these in the future. return { - "gcc": ("14", "GCC 14+ required for async_context"), + "gcc": ("15", "GCC 15+ required for async_context"), "clang": ( "19", "Clang 19+ required for async_context" @@ -100,7 +100,7 @@ def validate(self): def build_requirements(self): self.tool_requires("cmake/[^4.0.0]") self.tool_requires("ninja/[^1.3.0]") - self.requires("libhal-cmake-util/[^5.0.3]") + self.requires("libhal-cmake-util/[^5.0.6]") if str(self.settings.os) != "baremetal": self.test_requires("boost-ext-ut/2.3.1", options={'disable_module': False}) diff --git a/cspell.json b/cspell.json index 11b0a86..6a42ffa 100644 --- a/cspell.json +++ b/cspell.json @@ -52,7 +52,8 @@ "doxygenenum", "alignof", "inplace", - "interruptible" + "interruptible", + "riscv" ], "ignorePaths": [ "build/", diff --git a/modules/coroutine.cppm b/modules/coroutine.cppm index 0424323..3d96666 100644 --- a/modules/coroutine.cppm +++ b/modules/coroutine.cppm @@ -1622,7 +1622,7 @@ public: requires std::is_constructible_v { m_state.template emplace(std::forward(p_value)); - }; + } /** * @brief Move constructor for future diff --git a/modules/sync.cppm b/modules/sync.cppm index ce2dee4..82343fd 100644 --- a/modules/sync.cppm +++ b/modules/sync.cppm @@ -18,6 +18,8 @@ module; #include #include +#include +#include export module async_context:sync; @@ -154,7 +156,6 @@ public: private: friend class mutex; - guard(mutex* p_access, context* p_context) : m_access(p_access) , m_context(p_context) diff --git a/test_package/main.cpp b/test_package/main.cpp index a7cdfbf..ece013c 100644 --- a/test_package/main.cpp +++ b/test_package/main.cpp @@ -29,22 +29,35 @@ import async_context; using namespace std::chrono_literals; +// linking println doesn't work on embedded systems generally +template +void test_package_print([[maybe_unused]] std::format_string p_fmt, + [[maybe_unused]] Args&&... p_args) +{ + // If we are on a system with a real OS (Linux, Windows, macOS), use println. + // If we are in an embedded toolchain (arm-none-eabi, riscv64-unknown-elf), + // the following macro will NOT be defined. +#if defined(__GLIBC__) || defined(_WIN32) || defined(__APPLE__) + std::println(stdout, p_fmt, p_args...); +#endif +} + // Simulates reading sensor data with I/O delay -async::future read_sensor(async::context& ctx, std::string_view p_name) +async::future read_sensor(async::context&, std::string_view p_name) { - std::println("['{}': Sensor] Read complete: 42", p_name); + test_package_print("['{}': Sensor] Read complete: 42", p_name); co_return 42; } // Processes data with computation delay -async::future process_data(async::context& p_ctx, +async::future process_data(async::context&, std::string_view p_name, int value) { - std::println("['{}': Process] Processing {}...", p_name, value); + test_package_print("['{}': Process] Processing {}...", p_name, value); co_await 10ms; // Simulate processing time int result = value * 2; - std::println("['{}': Process] Result: {}", p_name, result); + test_package_print("['{}': Process] Result: {}", p_name, result); co_return result; } @@ -52,22 +65,22 @@ async::future write_actuator(async::context& p_ctx, std::string_view p_name, int value) { - std::println("['{}': Actuator] Writing {}...", p_name, value); + test_package_print("['{}': Actuator] Writing {}...", p_name, value); co_await p_ctx.block_by_signal(); - std::println("['{}': Actuator] Write complete!", p_name); + test_package_print("['{}': Actuator] Write complete!", p_name); } // Coordinates the full pipeline async::future sensor_pipeline(async::context& ctx, std::string_view p_name) { - std::println("Pipeline '{}' starting...", p_name); + test_package_print("Pipeline '{}' starting...", p_name); int sensor_value = co_await read_sensor(ctx, p_name); int processed = co_await process_data(ctx, p_name, sensor_value); co_await write_actuator(ctx, p_name, processed); - std::println("Pipeline '{}' complete!\n", p_name); + test_package_print("Pipeline '{}' complete!\n", p_name); } // Stub implementation for ARM M Cortex targets without @@ -103,8 +116,8 @@ int main() auto pipeline2_future = sensor_pipeline(ctx1, "🔥 System 2"); // This is needed to simulate the context being unblocked by an external // callback. - auto unblock_function = - [&ctx0, &ctx1](async::context& p_ctx) -> async::future { + auto unblock_function = [&ctx0, + &ctx1](async::context&) -> async::future { while (true) { if (ctx0.done() and ctx1.done()) { break; @@ -132,6 +145,6 @@ int main() // Run ctx0, ctx1 and unblock_context to completion async::run_until_done(clk, stub_sleep_function, ctx0, ctx1, unblock_context); - std::println("Both pipelines completed successfully!"); + test_package_print("Both pipelines completed successfully!"); return 0; } diff --git a/tests/mutex.test.cpp b/tests/mutex.test.cpp index f98af67..b0171a2 100644 --- a/tests/mutex.test.cpp +++ b/tests/mutex.test.cpp @@ -43,7 +43,7 @@ void guards_tests() auto guard = co_await mutex.lock(p_context); // setup dma transaction... - std::println("Waiting on io complete flag, blocking by I/O"); + std::println("Waiting on io complete flag, blocking by signal"); // Would normally wrap this in a while loop to check if the resource is // fread.