diff options
| author | Felix Morgner <felix.morgner@gmail.com> | 2026-06-17 11:17:59 +0200 |
|---|---|---|
| committer | Felix Morgner <felix.morgner@gmail.com> | 2026-06-17 17:52:24 +0200 |
| commit | e38520f3493a37d500adbca2704e1837bfdc488f (patch) | |
| tree | c815f9f8d0f29595bc66bf0693b1e053dbb610cd | |
| parent | 6e05501e8786f651fbf871c414c50573e5fecfb8 (diff) | |
| download | ttwhy-e38520f3493a37d500adbca2704e1837bfdc488f.tar.xz ttwhy-e38520f3493a37d500adbca2704e1837bfdc488f.zip | |
app: implement simple echo
| -rw-r--r-- | .clang-format | 10 | ||||
| -rw-r--r-- | .clang-tidy | 2 | ||||
| -rw-r--r-- | .lazy.lua | 1 | ||||
| -rw-r--r-- | CMakeLists.txt | 3 | ||||
| -rw-r--r-- | ttwhy/io.cppm | 84 | ||||
| -rw-r--r-- | ttwhy/lib.cppm | 1 | ||||
| -rw-r--r-- | ttwhy/main.cpp | 28 | ||||
| -rw-r--r-- | ttwhy/scoped_attributes.cppm | 5 |
8 files changed, 114 insertions, 20 deletions
diff --git a/.clang-format b/.clang-format index 48fb8b3..3bbbb4a 100644 --- a/.clang-format +++ b/.clang-format @@ -55,12 +55,14 @@ DerivePointerAlignment: "false" FixNamespaceComments: "true" IncludeBlocks: Regroup IncludeCategories: - # Project Headers - - Regex: 'ttwhy/[[:alnum:]._\/]+\.hpp' - Priority: 100 # Standard Headers - - Regex: '<[[:alnum:]._]+>' + - Regex: '(asio|asio/.*)\.hpp' + Priority: 500 + # Standard Headers + - Regex: '[[:alnum:]._]+.h' Priority: 900 + - Regex: '[[:alnum:]._]+' + Priority: 910 # Fallback - Regex: '.*' Priority: 800 diff --git a/.clang-tidy b/.clang-tidy index 0be16fb..6794ba6 100644 --- a/.clang-tidy +++ b/.clang-tidy @@ -87,7 +87,5 @@ CheckOptions: readability-magic-numbers.IgnoreTypeAliases: true FormatStyle: file -HeaderFilterRegex: "(.*/kstd/kstd/.*)|(arch|kernel|kapi)/.*\\.hpp" -SystemHeaders: true RemovedArgs: - -fcondition-coverage @@ -44,6 +44,7 @@ return { action = "copy", target = workspace_folder .. "/build", }, + cmake_use_presets = true, }, }, { diff --git a/CMakeLists.txt b/CMakeLists.txt index 3091b9e..316b655 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -23,7 +23,7 @@ find_package("Threads") add_library("asio" INTERFACE) add_library("ext::asio" ALIAS "asio") -target_include_directories("asio" INTERFACE +target_include_directories("asio" SYSTEM INTERFACE "${asio_SOURCE_DIR}/asio/include" ) @@ -40,6 +40,7 @@ target_sources("ttwhy-core" PUBLIC FILE_SET CXX_MODULES FILES + "ttwhy/io.cppm" "ttwhy/lib.cppm" "ttwhy/scoped_attributes.cppm" ) diff --git a/ttwhy/io.cppm b/ttwhy/io.cppm new file mode 100644 index 0000000..cbd3902 --- /dev/null +++ b/ttwhy/io.cppm @@ -0,0 +1,84 @@ +module; + +#include <asio.hpp> + +#include <expected> +#include <format> +#include <string> + +export module ttwhy:io; + +namespace ttwhy::io +{ + + export template<typename Stream> + auto handle_signals(Stream & stream) -> asio::awaitable<std::error_code> + { + auto executor = co_await asio::this_coro::executor; + auto signals = asio::signal_set{executor, SIGINT, SIGTERM}; + + auto [error, signal] = co_await signals.async_wait(asio::as_tuple(asio::use_awaitable)); + if (!error) + { + auto message = std::format("Received signal {}, exiting ...\n", signal); + co_await asio::async_write(stream, asio::buffer(message), asio::use_awaitable); + } + co_return error; + } + + export template<typename InputStream, typename ErrorStream> + auto read(InputStream & input_stream, ErrorStream & error_stream) + -> asio::awaitable<std::expected<std::string, asio::error_code>> + { + auto data = std::string{15, '\0'}; + + auto [error, read] = co_await input_stream.async_read_some(asio::buffer(data), asio::as_tuple(asio::use_awaitable)); + + if (error) + { + auto message = std::format("{}, exiting ...\n", error.message()); + co_await asio::async_write(error_stream, asio::buffer(message), asio::use_awaitable); + co_return std::unexpected{error}; + } + + data.resize(read); + co_return data; + } + + export template<typename OutputStream, typename ErrorStream> + auto write(std::string const & string, OutputStream & output_stream, ErrorStream & error_stream) + -> asio::awaitable<asio::error_code> + { + auto [error, written] = + co_await asio::async_write(output_stream, asio::buffer(string), asio::as_tuple(asio::use_awaitable)); + + if (error) + { + auto message = std::format("{}, exiting ...\n", error.message()); + co_await asio::async_write(error_stream, asio::buffer(message), asio::use_awaitable); + } + + co_return error; + } + + export template<typename InputStream, typename OutputStream, typename ErrorStream> + auto echo(InputStream & input_stream, OutputStream & output_stream, ErrorStream & error_stream) + -> asio::awaitable<asio::error_code> + { + while (true) + { + auto input = co_await read(input_stream, error_stream); + if (!input.has_value()) + { + co_return input.error(); + } + + auto write_error = co_await write(input.value(), output_stream, error_stream); + if (write_error) + { + co_return write_error; + } + } + } + +} // namespace ttwhy::io diff --git a/ttwhy/lib.cppm b/ttwhy/lib.cppm index fe7486f..14e0d5c 100644 --- a/ttwhy/lib.cppm +++ b/ttwhy/lib.cppm @@ -1,3 +1,4 @@ export module ttwhy; +export import :io; export import :scoped_attributes; diff --git a/ttwhy/main.cpp b/ttwhy/main.cpp index c210bee..649d01d 100644 --- a/ttwhy/main.cpp +++ b/ttwhy/main.cpp @@ -1,23 +1,30 @@ #include <asio.hpp> +#include <asio/experimental/awaitable_operators.hpp> + #include <stdio.h> +#include <format> + import ttwhy; -auto handle_signals(asio::cancellation_signal & cancellation_signal) -> asio::awaitable<void> +auto app(int in, int out, int error) -> asio::awaitable<void> { - co_await asio::this_coro::reset_cancellation_state(asio::disable_cancellation()); - co_await asio::this_coro::throw_if_cancelled(false); + using namespace asio::experimental::awaitable_operators; auto executor = co_await asio::this_coro::executor; - auto signals = asio::signal_set{executor, SIGINT, SIGTERM}; - auto log_stream = asio::posix::stream_descriptor{executor, fileno(stdout)}; - auto [error, signal] = co_await signals.async_wait(asio::as_tuple(asio::use_awaitable)); + auto input_stream = asio::posix::stream_descriptor{executor, in}; + auto output_stream = asio::posix::stream_descriptor{executor, out}; + auto error_stream = asio::posix::stream_descriptor{executor, error}; + + auto result = + co_await (ttwhy::io::handle_signals(error_stream) || ttwhy::io::echo(input_stream, output_stream, error_stream)); + auto final_error = result.index() == 0 ? std::get<0>(result) : std::get<1>(result); - if (!error) + if (final_error && final_error != asio::error::operation_aborted) { - co_await asio::async_write(log_stream, asio::buffer("shutting down...\n"), asio::as_tuple(asio::use_awaitable)); - cancellation_signal.emit(asio::cancellation_type::all); + auto message = std::format("Terminated with error: {}\n", final_error.message()); + co_await asio::async_write(error_stream, asio::buffer(message), asio::use_awaitable); } } @@ -27,9 +34,8 @@ auto main() -> int .canonical_mode(false) .echo(false); auto context = asio::io_context{}; - auto cancellation_signal = asio::cancellation_signal{}; - asio::co_spawn(context, handle_signals(cancellation_signal), asio::detached); + asio::co_spawn(context, app(fileno(stdin), fileno(stdout), fileno(stderr)), asio::detached); context.run(); } diff --git a/ttwhy/scoped_attributes.cppm b/ttwhy/scoped_attributes.cppm index 7c32ddf..b49dd18 100644 --- a/ttwhy/scoped_attributes.cppm +++ b/ttwhy/scoped_attributes.cppm @@ -1,9 +1,10 @@ module; -#include <cerrno> -#include <system_error> #include <termios.h> #include <unistd.h> + +#include <cerrno> +#include <system_error> #include <utility> export module ttwhy:scoped_attributes; |
