From d3129d332a51d4d9a7ea7bf304a0831e4dba66dd Mon Sep 17 00:00:00 2001 From: wokron Date: Mon, 31 Aug 2026 00:01:06 +0800 Subject: [PATCH 1/4] remove internal check_cqe32() --- include/condy/cqe_handler.hpp | 12 ------------ include/condy/detail/ring.hpp | 13 ------------- include/condy/zcrx.hpp | 2 -- 3 files changed, 27 deletions(-) diff --git a/include/condy/cqe_handler.hpp b/include/condy/cqe_handler.hpp index 8679c69d..95056bf8 100644 --- a/include/condy/cqe_handler.hpp +++ b/include/condy/cqe_handler.hpp @@ -57,10 +57,6 @@ class SelectBufferCQEHandler { */ struct NVMePassthruCQEHandler { std::pair operator()(io_uring_cqe *cqe) noexcept { - assert( - detail::Context::current().runtime()->ring_internal().check_cqe32( - cqe) && - "Expected big CQE for NVMe passthrough"); return {cqe->res, cqe->big_cqe[0]}; } }; @@ -98,10 +94,6 @@ struct SCSIBsgResult { */ struct SCSIBsgPassthruCQEHandler { std::pair operator()(io_uring_cqe *cqe) noexcept { - assert( - detail::Context::current().runtime()->ring_internal().check_cqe32( - cqe) && - "Expected big CQE for SCSI BSG passthrough"); return {cqe->res, SCSIBsgResult{cqe->big_cqe[0]}}; } }; @@ -138,10 +130,6 @@ struct TxTimestampResult { struct TxTimestampCQEHandler { std::pair operator()(io_uring_cqe *cqe) noexcept { - assert( - detail::Context::current().runtime()->ring_internal().check_cqe32( - cqe) && - "Expected big CQE for TX timestamp operations"); TxTimestampResult result; result.tstype = static_cast(cqe->flags >> IORING_TIMESTAMP_TYPE_SHIFT); diff --git a/include/condy/detail/ring.hpp b/include/condy/detail/ring.hpp index 871957e6..3158d204 100644 --- a/include/condy/detail/ring.hpp +++ b/include/condy/detail/ring.hpp @@ -133,19 +133,6 @@ class Ring { } #endif - bool check_cqe32([[maybe_unused]] io_uring_cqe *cqe) const noexcept { - auto ring_flags = ring_.flags; - if (ring_flags & IORING_SETUP_CQE32) { - return true; - } -#if CONDY_URING_VERSION_GE(2, 13) // >= 2.13 - if (ring_flags & IORING_SETUP_CQE_MIXED) { - return cqe->flags & IORING_CQE_F_32; - } -#endif - return false; - } - private: template io_uring_sqe *get_sqe_() noexcept { diff --git a/include/condy/zcrx.hpp b/include/condy/zcrx.hpp index a9d8ca22..2a39288e 100644 --- a/include/condy/zcrx.hpp +++ b/include/condy/zcrx.hpp @@ -203,8 +203,6 @@ class ZeroCopyRxBufferPool { uint32_t zcrx_id() const noexcept { return zcrx_id_; } ZeroCopyRxBuffer handle_finish(io_uring_cqe *cqe) noexcept { - assert(ring_->check_cqe32(cqe) && "Expected big CQE for ZeroCopyRx"); - if (cqe->res < 0) { return ZeroCopyRxBuffer(); } From 4a734f9f13df25c463ca0e37df74ecd883ff8135 Mon Sep 17 00:00:00 2001 From: wokron Date: Sat, 29 Aug 2026 16:50:10 +0800 Subject: [PATCH 2/4] check if runtime exist --- include/condy/detail/op_states.hpp | 24 +++++++++++++++++------- 1 file changed, 17 insertions(+), 7 deletions(-) diff --git a/include/condy/detail/op_states.hpp b/include/condy/detail/op_states.hpp index f3a68252..5fcdbd6e 100644 --- a/include/condy/detail/op_states.hpp +++ b/include/condy/detail/op_states.hpp @@ -31,22 +31,32 @@ template class OpSenderOperationState { public: void start(unsigned int flags) noexcept { - auto &context = Context::current(); - auto &ring = context.runtime()->ring_internal(); + auto *runtime = Context::current().runtime(); + if (runtime == nullptr) { + fail_(-EINVAL); + return; + } + auto &ring = runtime->ring_internal(); io_uring_sqe *sqe = prep_func_(&ring); if (sqe == nullptr) { - io_uring_cqe cqe = {}; - cqe.res = -EINVAL; - finish_handle_.get().handle(&cqe); + fail_(-EINVAL); return; } - context.runtime()->pend_work_internal(); + runtime->pend_work_internal(); io_uring_sqe_set_flags(sqe, sqe->flags | flags); auto work = encode_work(&finish_handle_.get(), WorkType::Common); io_uring_sqe_set_data64(sqe, work); ring.maybe_submit(); - finish_handle_.get().maybe_set_cancel(context.runtime()); + finish_handle_.get().maybe_set_cancel(runtime); + } + +private: + void fail_(int32_t res) noexcept { + assert(res < 0); + io_uring_cqe cqe[2] = {}; + cqe[0].res = res; + finish_handle_.get().handle(cqe); } private: From 2e593358fe151fc3fbc4183bdf29eea0cc67338d Mon Sep 17 00:00:00 2001 From: wokron Date: Sun, 30 Aug 2026 19:16:07 +0800 Subject: [PATCH 3/4] check if already canceled --- include/condy/detail/finish_handles.hpp | 5 +++++ include/condy/detail/op_states.hpp | 4 ++++ 2 files changed, 9 insertions(+) diff --git a/include/condy/detail/finish_handles.hpp b/include/condy/detail/finish_handles.hpp index d334fd5e..bf6843c3 100644 --- a/include/condy/detail/finish_handles.hpp +++ b/include/condy/detail/finish_handles.hpp @@ -32,6 +32,11 @@ class OpFinishHandle : public OpFinishHandleBase { CONDY_DELETE_COPY_MOVE(OpFinishHandle); public: + bool stop_requested() noexcept { + auto stop_token = receiver_.get_stop_token(); + return stop_token.stop_requested(); + } + void maybe_set_cancel(Runtime *runtime) noexcept { auto stop_token = receiver_.get_stop_token(); if (stop_token.stop_possible()) { diff --git a/include/condy/detail/op_states.hpp b/include/condy/detail/op_states.hpp index 5fcdbd6e..e93e0518 100644 --- a/include/condy/detail/op_states.hpp +++ b/include/condy/detail/op_states.hpp @@ -36,6 +36,10 @@ template class OpSenderOperationState { fail_(-EINVAL); return; } + if (finish_handle_.get().stop_requested()) { + fail_(-ECANCELED); + return; + } auto &ring = runtime->ring_internal(); io_uring_sqe *sqe = prep_func_(&ring); if (sqe == nullptr) { From ea30c36f966396da90270d1c28857b12c18746c3 Mon Sep 17 00:00:00 2001 From: wokron Date: Sat, 29 Aug 2026 17:17:46 +0800 Subject: [PATCH 4/4] add tests --- tests/test_senders.cpp | 47 +++++++++++++++++++++++++++++++++++++++++- 1 file changed, 46 insertions(+), 1 deletion(-) diff --git a/tests/test_senders.cpp b/tests/test_senders.cpp index d966c41d..716260e2 100644 --- a/tests/test_senders.cpp +++ b/tests/test_senders.cpp @@ -1,3 +1,4 @@ +#include "condy/async_operations.hpp" #include "condy/awaiter_operations.hpp" #include "condy/channel.hpp" #include "condy/detail/async_operations.hpp" @@ -6,7 +7,9 @@ #include "condy/sync_wait.hpp" #include #include +#include #include +#include #include #include #include @@ -557,4 +560,46 @@ TEST_CASE("test senders - cancel from other runtime thread") { condy::sync_wait(cancel_task()); t1.join(); -} \ No newline at end of file +} + +TEST_CASE("test senders - start without runtime") { + auto coro = []() -> condy::Coro { + int r = co_await condy::async_nop(); + REQUIRE(r == -EINVAL); + co_return r; + }(); + auto handle = coro.release(); + + REQUIRE(!handle.done()); + handle.resume(); + REQUIRE(handle.done()); + REQUIRE(handle.promise().value() == -EINVAL); + + handle.destroy(); +} + +#if CONDY_URING_VERSION_GE(2, 13) // >= 2.13 +TEST_CASE("test senders - start without sqe128 support") { + auto func = []() -> condy::Coro { + int r = co_await condy::async_nop128(); + REQUIRE(r == -EINVAL); + }; + condy::sync_wait(func()); +} +#endif + +TEST_CASE("test senders - start with stopped token") { + using condy::operators::operator||; + + auto func = []() -> condy::Coro { + condy::Channel ch(1); + REQUIRE(ch.try_push(42) == 0); + + auto res = co_await (ch.pop() || condy::async_nop()); + REQUIRE(res.index() == 0); + auto [r, item] = std::get<0>(res); + REQUIRE(r == 0); + REQUIRE(item == 42); + }; + condy::sync_wait(func()); +}