From f47f40114b6122dd1a5296ec8dd44937682e3d74 Mon Sep 17 00:00:00 2001 From: wokron Date: Sun, 19 Jul 2026 18:38:09 +0800 Subject: [PATCH 1/5] add constexpr alternatives for const macros --- include/condy/helpers.hpp | 5 +++++ include/condy/version.hpp | 21 +++++++++++++++++++++ 2 files changed, 26 insertions(+) diff --git a/include/condy/helpers.hpp b/include/condy/helpers.hpp index 3401ecf8..4309d0f7 100644 --- a/include/condy/helpers.hpp +++ b/include/condy/helpers.hpp @@ -26,6 +26,11 @@ namespace condy { +/** + * @brief Placeholder to let io_uring allocate a direct file descriptor. + */ +inline constexpr unsigned file_index_alloc = CONDY_FILE_INDEX_ALLOC; + /** * @brief Helper to build an invocable that spawns a coroutine on invocation. * @tparam CoroFunc Type of the coroutine function. diff --git a/include/condy/version.hpp b/include/condy/version.hpp index ef211a13..01d135ef 100644 --- a/include/condy/version.hpp +++ b/include/condy/version.hpp @@ -4,5 +4,26 @@ #pragma once +/** + * @brief Condy major version. + */ #define CONDY_VERSION_MAJOR 1 + +/** + * @brief Condy minor version. + */ #define CONDY_VERSION_MINOR 8 + +namespace condy { + +/** + * @brief Condy major version. + */ +inline constexpr int version_major = CONDY_VERSION_MAJOR; + +/** + * @brief Condy minor version. + */ +inline constexpr int version_minor = CONDY_VERSION_MINOR; + +} // namespace condy From a25694ddf1a6c51451ab033cba5db2d5c8a9bb4e Mon Sep 17 00:00:00 2001 From: wokron Date: Sun, 19 Jul 2026 18:52:40 +0800 Subject: [PATCH 2/5] add condy.cppm module interface --- module/condy.cppm | 225 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 225 insertions(+) create mode 100644 module/condy.cppm diff --git a/module/condy.cppm b/module/condy.cppm new file mode 100644 index 00000000..cb167d00 --- /dev/null +++ b/module/condy.cppm @@ -0,0 +1,225 @@ +module; + +#define IOURINGINLINE inline +#include "condy.hpp" +#undef IOURINGINLINE + +export module condy; + +export namespace condy { + +// version.hpp +using condy::version_major; +using condy::version_minor; + +// coro.hpp +using condy::Coro; + +// runtime.hpp +using condy::current_runtime; +using condy::Runtime; + +// runtime_options.hpp +using condy::RuntimeOptions; + +// task.hpp +using condy::co_spawn; +using condy::Task; + +// sync_wait.hpp +using condy::default_runtime_options; +using condy::sync_wait; + +// buffers.hpp +using condy::buffer; +using condy::ConstBuffer; +using condy::MutableBuffer; + +// provided_buffers.hpp +using condy::BufferInfo; +using condy::bundled; +using condy::ProvidedBuffer; +using condy::ProvidedBufferPool; +using condy::ProvidedBufferQueue; + +// ring_settings.hpp +using condy::BufferTable; +using condy::FdTable; +using condy::RingSettings; + +// channel.hpp +using condy::Channel; + +// futex.hpp +using condy::Futex; + +// zcrx.hpp +#if CONDY_URING_VERSION_GE(2, 15) // >= 2.15 +using condy::ZeroCopyRxArea; +using condy::ZeroCopyRxBuffer; +using condy::ZeroCopyRxBufferPool; +using condy::ZeroCopyRxDMABufArea; +#endif + +// cqe_handler.hpp +using condy::NVMePassthruCQEHandler; +using condy::SelectBufferCQEHandler; +using condy::SimpleCQEHandler; +#if CONDY_URING_VERSION_GE(2, 12) // >= 2.12 +using condy::TxTimestampCQEHandler; +using condy::TxTimestampResult; +#endif + +// helpers.hpp +using condy::file_index_alloc; +using condy::fixed; +using condy::will_push; +using condy::will_spawn; + +// sender_operations.hpp +using condy::always_async; +using condy::build_multishot_op_sender; +using condy::build_op_sender; +using condy::build_zero_copy_op_sender; +using condy::drain; +using condy::flag; +using condy::hard_link; +using condy::link; +using condy::parallel; +using condy::when_all; +using condy::when_any; + +// awaiter_operations.hpp +using condy::build_multishot_op_awaiter; +using condy::build_op_awaiter; +using condy::build_zero_copy_op_awaiter; + +// awaiters.hpp +using condy::HardLinkAwaiter; +using condy::LinkAwaiter; +using condy::ParallelAllAwaiter; +using condy::ParallelAnyAwaiter; +using condy::RangedHardLinkAwaiter; +using condy::RangedLinkAwaiter; +using condy::RangedParallelAllAwaiter; +using condy::RangedParallelAnyAwaiter; +using condy::RangedWhenAllAwaiter; +using condy::RangedWhenAnyAwaiter; +using condy::WhenAllAwaiter; +using condy::WhenAnyAwaiter; + +// async_operations.hpp +using condy::async_accept; +using condy::async_accept_direct; +using condy::async_cancel_fd; +using condy::async_close; +using condy::async_connect; +using condy::async_epoll_ctl; +using condy::async_fadvise; +using condy::async_fallocate; +using condy::async_fgetxattr; +using condy::async_files_update; +using condy::async_fsetxattr; +using condy::async_fsync; +using condy::async_getxattr; +using condy::async_link; +using condy::async_link_timeout; +using condy::async_linkat; +using condy::async_madvise; +using condy::async_mkdir; +using condy::async_mkdirat; +using condy::async_multishot_accept; +using condy::async_multishot_accept_direct; +using condy::async_nop; +using condy::async_open; +using condy::async_open_direct; +using condy::async_openat; +using condy::async_openat2; +using condy::async_openat2_direct; +using condy::async_openat_direct; +using condy::async_read; +using condy::async_readv; +using condy::async_recv; +using condy::async_recv_multishot; +using condy::async_recvmsg; +using condy::async_recvmsg_multishot; +using condy::async_rename; +using condy::async_renameat; +using condy::async_send; +using condy::async_send_zc; +using condy::async_sendmsg; +using condy::async_sendmsg_zc; +using condy::async_sendto; +using condy::async_sendto_zc; +using condy::async_setxattr; +using condy::async_shutdown; +using condy::async_socket; +using condy::async_socket_direct; +using condy::async_splice; +using condy::async_statx; +using condy::async_symlink; +using condy::async_symlinkat; +using condy::async_sync_file_range; +using condy::async_tee; +using condy::async_timeout; +using condy::async_unlink; +using condy::async_unlinkat; +using condy::async_uring_cmd; +using condy::async_uring_cmd_multishot; +using condy::async_write; +using condy::async_writev; +#if CONDY_URING_VERSION_GE(2, 4) // >= 2.4 +using condy::async_timeout_multishot; +#endif +#if CONDY_URING_VERSION_GE(2, 5) // >= 2.5 +using condy::async_cmd_sock; +#endif +#if CONDY_URING_VERSION_GE(2, 6) // >= 2.6 +using condy::async_fixed_fd_install; +using condy::async_ftruncate; +using condy::async_futex_wait; +using condy::async_futex_waitv; +using condy::async_futex_wake; +using condy::async_read_multishot; +using condy::async_waitid; +#endif +#if CONDY_URING_VERSION_GE(2, 7) // >= 2.7 +using condy::async_bind; +using condy::async_fadvise64; +using condy::async_listen; +using condy::async_madvise64; +#endif +#if CONDY_URING_VERSION_GE(2, 8) // >= 2.8 +using condy::async_cmd_discard; +#endif +#if CONDY_URING_VERSION_GE(2, 10) // >= 2.10 +using condy::async_epoll_wait; +#endif +#if CONDY_URING_VERSION_GE(2, 12) // >= 2.12 +using condy::async_pipe; +using condy::async_pipe_direct; +#endif +#if CONDY_URING_VERSION_GE(2, 13) // >= 2.13 +using condy::async_cmd_getsockname; +using condy::async_nop128; +using condy::async_uring_cmd128; +#endif + +} // namespace condy + +export namespace condy::operators { + +// sender_operations.hpp +using condy::operators::operator&&; +using condy::operators::operator||; +using condy::operators::operator>>; + +} // namespace condy::operators + +export namespace condy::pmr { + +// pmr.hpp +using condy::pmr::Coro; +using condy::pmr::Task; + +} // namespace condy::pmr From 4dbba92ae2f577c560ea2c911cbf3998f554c08a Mon Sep 17 00:00:00 2001 From: wokron Date: Sun, 19 Jul 2026 19:14:47 +0800 Subject: [PATCH 3/5] add condy_module target and module-hello example --- CMakeLists.txt | 9 ++++++++- examples/CMakeLists.txt | 7 ++++++- examples/module-hello.cpp | 12 ++++++++++++ module/CMakeLists.txt | 9 +++++++++ 4 files changed, 35 insertions(+), 2 deletions(-) create mode 100644 examples/module-hello.cpp create mode 100644 module/CMakeLists.txt diff --git a/CMakeLists.txt b/CMakeLists.txt index 1939e4fa..28929efa 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -5,6 +5,7 @@ project(condy LANGUAGES CXX) option(BUILD_EXAMPLES "Build examples" OFF) option(BUILD_BENCHMARKS "Build benchmarks" OFF) option(BUILD_TESTS "Build tests" OFF) +option(BUILD_MODULE "Build C++ module interface" OFF) option(ENABLE_CLANG_TIDY "Enable clang-tidy static analysis" OFF) option(TESTS_STATIC_LINK "Use static linking for tests" OFF) option(TESTS_TSAN "Enable thread sanitizer for tests" OFF) @@ -25,7 +26,7 @@ add_library(condy INTERFACE) target_include_directories(condy INTERFACE include) target_compile_features(condy INTERFACE cxx_std_20) -if(BUILD_EXAMPLES OR BUILD_BENCHMARKS OR BUILD_TESTS OR LINK_LIBURING) +if(BUILD_EXAMPLES OR BUILD_BENCHMARKS OR BUILD_TESTS OR LINK_LIBURING OR BUILD_MODULE) enable_language(C) include(ExternalProject) @@ -60,6 +61,12 @@ if(LINK_LIBURING) target_link_libraries(condy INTERFACE uring) endif() +if(BUILD_MODULE) + set(CMAKE_CXX_SCAN_FOR_MODULES ON) + message(STATUS "Configuring C++ module interface in ${CMAKE_CURRENT_SOURCE_DIR}/module") + add_subdirectory(module) +endif() + # Warnings as errors add_compile_options(-Wall -Wextra -Werror) if(CMAKE_CXX_COMPILER_ID MATCHES "GNU") diff --git a/examples/CMakeLists.txt b/examples/CMakeLists.txt index 4560f444..e9e051b0 100644 --- a/examples/CMakeLists.txt +++ b/examples/CMakeLists.txt @@ -14,4 +14,9 @@ add_executable(queue-kernel-futex queue-kernel-futex.cpp) target_link_libraries(queue-kernel-futex PRIVATE condy uring) add_executable(queue-condy-futex queue-condy-futex.cpp) -target_link_libraries(queue-condy-futex PRIVATE condy uring) \ No newline at end of file +target_link_libraries(queue-condy-futex PRIVATE condy uring) + +if(BUILD_MODULE) + add_executable(module-hello module-hello.cpp) + target_link_libraries(module-hello PRIVATE condy_module uring) +endif() \ No newline at end of file diff --git a/examples/module-hello.cpp b/examples/module-hello.cpp new file mode 100644 index 00000000..719df1f2 --- /dev/null +++ b/examples/module-hello.cpp @@ -0,0 +1,12 @@ +#include +#include +#include + +import condy; + +condy::Coro<> co_main() { + std::string msg = "Hello, Condy (via module)!\n"; + co_await condy::async_write(STDOUT_FILENO, condy::buffer(msg), 0); +} + +int main() noexcept(false) { condy::sync_wait(co_main()); } diff --git a/module/CMakeLists.txt b/module/CMakeLists.txt new file mode 100644 index 00000000..746eaf7f --- /dev/null +++ b/module/CMakeLists.txt @@ -0,0 +1,9 @@ +cmake_minimum_required(VERSION 3.28) + +add_library(condy_module) +target_sources(condy_module + PUBLIC FILE_SET CXX_MODULES + FILES condy.cppm +) +target_compile_features(condy_module PUBLIC cxx_std_20) +target_link_libraries(condy_module PUBLIC condy) From a0659782b3fa328f6e40efdb88bf63df247f375d Mon Sep 17 00:00:00 2001 From: wokron Date: Sun, 19 Jul 2026 20:30:14 +0800 Subject: [PATCH 4/5] add docs for module support --- docs/build.md | 36 ++++++++++++++++++++++++++++++++++++ docs/examples.md | 3 +++ 2 files changed, 39 insertions(+) diff --git a/docs/build.md b/docs/build.md index 859602e5..d8ef3963 100644 --- a/docs/build.md +++ b/docs/build.md @@ -68,6 +68,42 @@ ctest --test-dir build ./build/examples/link-cp from.bin to.bin ``` +## C++20 Module Support + +Condy provides an optional C++20 module interface as an alternative to `#include `. + +```cpp +import condy; +``` + +### Requirements + +- **CMake 3.28+** with **Ninja** generator +- **GCC 14+** or **Clang 16+** + +### Building the Example + +```bash +cmake -B build -S . -G Ninja \ + -DBUILD_MODULE=ON \ + -DBUILD_EXAMPLES=ON +ninja -C build module-hello + +./build/examples/module-hello +# Hello, Condy (via module)! +``` + +### Using in Your Project + +The module target is `condy_module`: + +```cmake +set(BUILD_MODULE ON CACHE BOOL "") +add_subdirectory(third_party/condy) +add_executable(my_app src/main.cpp) +target_link_libraries(my_app PRIVATE condy_module) +``` + ## Version Compatibility Condy supports **liburing ≥ 2.3**. When building with a specific version of liburing, Condy assumes that all related interfaces provided by that version are already supported by your Linux kernel. diff --git a/docs/examples.md b/docs/examples.md index a35a4c85..be18326b 100644 --- a/docs/examples.md +++ b/docs/examples.md @@ -19,3 +19,6 @@ - [queue-kernel-futex.cpp](queue-kernel-futex_8cpp_source.html) Builds a producer-consumer queue through asynchronous futex syscalls (`condy::async_futex_wait()`), implementing an asynchronous semaphore for synchronization. + +- [module-hello.cpp](module-hello_8cpp_source.html) + Demonstrates using Condy as a C++20 module via `import condy;`. Requires CMake 3.28+, Ninja, and GCC 14+ or Clang 16+. Build with `-DBUILD_MODULE=ON`. From 880f430991ebe64396a121db4c56464dc76cb31b Mon Sep 17 00:00:00 2001 From: wokron Date: Mon, 20 Jul 2026 10:52:29 +0800 Subject: [PATCH 5/5] add module ci check --- .github/workflows/ci-toolchain.yml | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/.github/workflows/ci-toolchain.yml b/.github/workflows/ci-toolchain.yml index 691d4531..2e261af5 100644 --- a/.github/workflows/ci-toolchain.yml +++ b/.github/workflows/ci-toolchain.yml @@ -57,3 +57,23 @@ jobs: timeout-minutes: 5 working-directory: ${{github.workspace}}/build run: ctest --verbose + + - name: Build module-hello + # liburing < 2.13 exposes TU-local entities that break GCC modules + # https://github.com/axboe/liburing/issues/1457 + if: > + matrix.generator == 'Ninja' + && !(matrix.compiler.cc == 'gcc' && matrix.liburing-version == '2.3') + run: | + cmake -B ${{github.workspace}}/build_module -G Ninja \ + -DBUILD_MODULE=ON \ + -DBUILD_EXAMPLES=ON \ + -DCMAKE_C_COMPILER=${{ matrix.compiler.cc }} \ + -DCMAKE_CXX_COMPILER=${{ matrix.compiler.cxx }} + ninja -C ${{github.workspace}}/build_module module-hello + + - name: Run module-hello + if: > + matrix.generator == 'Ninja' + && !(matrix.compiler.cc == 'gcc' && matrix.liburing-version == '2.3') + run: ${{github.workspace}}/build_module/examples/module-hello