From 3f78d0978d3464f4a6115588811e89f0f3adfcb1 Mon Sep 17 00:00:00 2001 From: portersky <24420859+portersky@users.noreply.github.com> Date: Tue, 5 May 2026 23:43:33 +0200 Subject: [PATCH] feat: add CLI argument parser with ASIO duration timer Adds support for `--duration ` (and `--help`) to automatically terminate after a set time. Useful for testing, CI, and agent runs where the default infinite loop is problematic. Uses `asio::steady_timer` + `async_wait` for the timeout (unified with the existing signal handling under one io_context). The `process_signals` lambda was restored as it looks nicer. Combines what were 4 incremental commits into one (the separate window refactor from earlier remains). Updated cuber.cpp and includes. --- cuber.cpp | 37 ++++++++++++++++++++++++++++++++++--- 1 file changed, 34 insertions(+), 3 deletions(-) diff --git a/cuber.cpp b/cuber.cpp index 706579a..950938a 100644 --- a/cuber.cpp +++ b/cuber.cpp @@ -1,15 +1,35 @@ #define GLFW_INCLUDE_NONE #include +#include +#include +#include #include "GLFW/glfw3.h" #include "asio.hpp" +#include "asio/steady_timer.hpp" +#include "fmt/std.h" #include "cbt/window.hpp" #include "cbt/opengl/context.hpp" #include "scenes/cube.hpp" -auto main(int, char const*[]) -> int { +auto main(int argc, char const* argv[]) -> int { + float max_duration_seconds = 0.0f; + + for (int i = 1; i < argc; ++i) { + std::string_view arg = argv[i]; + if (arg == "--help" || arg == "-h") { + fmt::print("Usage: {} [--duration ] [--help|-h]\n", argv[0]); + fmt::print(" --duration Auto-terminate after N seconds (for testing/CI)\n"); + return 0; + } + if (arg == "--duration" && i + 1 < argc) { + max_duration_seconds = std::stof(std::string(argv[++i])); + continue; + } + } + auto win = cbt::window("cuber", 1280, 720); if (!win.valid()) { @@ -27,7 +47,7 @@ auto main(int, char const*[]) -> int { return 1; } - // signal handling + // signal handling + optional duration timer (via ASIO) asio::io_context io; asio::signal_set signals(io, SIGINT, SIGTERM); bool quit = false; @@ -37,6 +57,17 @@ auto main(int, char const*[]) -> int { io.stop(); }); + asio::steady_timer duration_timer(io); + if (max_duration_seconds > 0.0f) { + duration_timer.expires_after(std::chrono::milliseconds( + static_cast(max_duration_seconds * 1000.0f))); + duration_timer.async_wait([&](auto ec) { + if (!ec) { + quit = true; + } + }); + } + auto process_signals = [&]() -> void { while (io.poll()) {} }; @@ -47,11 +78,11 @@ auto main(int, char const*[]) -> int { while (!win.should_close()) { process_signals(); + auto now = std::chrono::steady_clock::now(); if (quit || glfwGetKey(win.raw(), GLFW_KEY_Q) == GLFW_PRESS) { break; } - auto now = std::chrono::steady_clock::now(); auto dt = std::chrono::duration(now - prev).count(); prev = now;