diff --git a/examples/fuse-prime-fs.cpp b/examples/fuse-prime-fs.cpp index 2fbdf420..b58e1a9f 100644 --- a/examples/fuse-prime-fs.cpp +++ b/examples/fuse-prime-fs.cpp @@ -200,7 +200,8 @@ auto fuse_register_cmd(iovec iov[2], uint16_t qid) { auto *cmd = reinterpret_cast(sqe->cmd); *cmd = {}; cmd->qid = qid; - }); + }, + condy::SimpleCQEHandler{}); } auto fuse_commit_and_fetch_cmd(uint16_t qid, uint64_t commit_id) { @@ -211,7 +212,8 @@ auto fuse_commit_and_fetch_cmd(uint16_t qid, uint64_t commit_id) { *cmd = {}; cmd->qid = qid; cmd->commit_id = commit_id; - }); + }, + condy::SimpleCQEHandler{}); } class FuseServer { diff --git a/examples/ublk-loop.cpp b/examples/ublk-loop.cpp index 68f9208d..bc428177 100644 --- a/examples/ublk-loop.cpp +++ b/examples/ublk-loop.cpp @@ -50,15 +50,17 @@ off_t io_desc_offset(size_t q_id) { } auto ublk_ctrl_cmd(int fd, int cmd_op, const ublksrv_ctrl_cmd &ctrl) { - return condy::async_uring_cmd(cmd_op, fd, [&](io_uring_sqe *sqe) { - std::memcpy(sqe->cmd, &ctrl, sizeof(ctrl)); - }); + return condy::async_uring_cmd( + cmd_op, fd, + [&](io_uring_sqe *sqe) { std::memcpy(sqe->cmd, &ctrl, sizeof(ctrl)); }, + condy::SimpleCQEHandler{}); } auto ublk_io_cmd(int cmd_op, const ublksrv_io_cmd &cmd) { return condy::async_uring_cmd( cmd_op, condy::fixed(FIXED_FD), - [&](io_uring_sqe *sqe) { std::memcpy(sqe->cmd, &cmd, sizeof(cmd)); }); + [&](io_uring_sqe *sqe) { std::memcpy(sqe->cmd, &cmd, sizeof(cmd)); }, + condy::SimpleCQEHandler{}); } condy::Coro setup_device() { diff --git a/include/condy/async_operations.hpp b/include/condy/async_operations.hpp index 58341cf6..dfe9f0ad 100644 --- a/include/condy/async_operations.hpp +++ b/include/condy/async_operations.hpp @@ -696,9 +696,10 @@ inline auto async_recv_multishot(Fd sockfd, ZeroCopyRxBufferPool &pool, detail::prep_recv_zc_multishot(sqe, sockfd, zcrx_id); return sqe; }; - auto op = build_multishot_op_awaiter< - SelectBufferCQEHandler>( - std::move(prep_func), std::forward(func), &pool); + auto op = build_multishot_op_awaiter( + std::move(prep_func), + SelectBufferCQEHandler(&pool), + std::forward(func)); return detail::maybe_flag_fixed_fd(std::move(op), sockfd); } #endif @@ -870,6 +871,7 @@ inline auto async_socket_direct(int domain, int type, int protocol, /** * @brief See io_uring_prep_uring_cmd + * @deprecated Use the overload accepting a CQEHandler instance instead. * @tparam CQEHandler Custom CQE handler for specific result processing. * @param cmd_func Function to configure sqe for specific command. Signature: * void(io_uring_sqe *sqe). @@ -877,8 +879,21 @@ inline auto async_socket_direct(int domain, int type, int protocol, */ template +[[deprecated]] inline auto +async_uring_cmd(int cmd_op, Fd fd, CmdFunc &&cmd_func, Args &&...handler_args) { + return async_uring_cmd(cmd_op, fd, std::forward(cmd_func), + CQEHandler(std::forward(handler_args)...)); +} + +/** + * @brief See io_uring_prep_uring_cmd + * @param cmd_func Function to configure sqe for specific command. Signature: + * void(io_uring_sqe *sqe). + * @param cqe_handler CQE handler for specific result processing. + */ +template inline auto async_uring_cmd(int cmd_op, Fd fd, CmdFunc &&cmd_func, - Args &&...handler_args) { + CQEHandler &&cqe_handler) { auto prep_func = [cmd_op, fd = detail::unwrap_fixed(fd), cmd_func = std::forward(cmd_func)](detail::Ring *ring) { @@ -887,19 +902,43 @@ inline auto async_uring_cmd(int cmd_op, Fd fd, CmdFunc &&cmd_func, cmd_func(sqe); return sqe; }; - auto op = build_op_awaiter(std::move(prep_func), - std::forward(handler_args)...); + auto op = build_op_awaiter(std::move(prep_func), + std::forward(cqe_handler)); return detail::maybe_flag_fixed_fd(std::move(op), fd); } /** - * @copydoc async_uring_cmd + * @brief See io_uring_prep_uring_cmd + * @deprecated Use the overload accepting a CQEHandler instance instead. + * @tparam CQEHandler Custom CQE handler for specific result processing. + * @param cmd_func Function to configure sqe for specific command. Signature: + * void(io_uring_sqe *sqe). + * @param func Callback invoked on each completion except the last one. + * @param handler_args Arguments forwarded to CQEHandler constructor. */ template +[[deprecated]] inline auto +async_uring_cmd_multishot(int cmd_op, Fd fd, CmdFunc &&cmd_func, + MultiShotFunc &&func, Args &&...handler_args) { + return async_uring_cmd_multishot( + cmd_op, fd, std::forward(cmd_func), + CQEHandler(std::forward(handler_args)...), + std::forward(func)); +} + +/** + * @brief See io_uring_prep_uring_cmd (multi-shot variant) + * @param cmd_func Function to configure sqe for specific command. Signature: + * void(io_uring_sqe *sqe). + * @param cqe_handler CQE handler for specific result processing. + * @param func Callback invoked on each completion except the last one. + */ +template inline auto async_uring_cmd_multishot(int cmd_op, Fd fd, CmdFunc &&cmd_func, - MultiShotFunc &&func, - Args &&...handler_args) { + CQEHandler &&cqe_handler, + MultiShotFunc &&func) { auto prep_func = [cmd_op, fd = detail::unwrap_fixed(fd), cmd_func = std::forward(cmd_func)](detail::Ring *ring) { @@ -908,15 +947,16 @@ inline auto async_uring_cmd_multishot(int cmd_op, Fd fd, CmdFunc &&cmd_func, cmd_func(sqe); return sqe; }; - auto op = build_multishot_op_awaiter( - std::move(prep_func), std::forward(func), - std::forward(handler_args)...); + auto op = build_multishot_op_awaiter(std::move(prep_func), + std::forward(cqe_handler), + std::forward(func)); return detail::maybe_flag_fixed_fd(std::move(op), fd); } #if CONDY_URING_VERSION_GE(2, 13) // >= 2.13 /** * @brief See io_uring_prep_uring_cmd128 + * @deprecated Use the overload accepting a CQEHandler instance instead. * @tparam CQEHandler Custom CQE handler for specific result processing. * @param cmd_func Function to configure sqe for specific command. Signature: * void(io_uring_sqe *sqe). @@ -924,8 +964,22 @@ inline auto async_uring_cmd_multishot(int cmd_op, Fd fd, CmdFunc &&cmd_func, */ template +[[deprecated]] inline auto async_uring_cmd128(int cmd_op, Fd fd, + CmdFunc &&cmd_func, + Args &&...handler_args) { + return async_uring_cmd128(cmd_op, fd, std::forward(cmd_func), + CQEHandler(std::forward(handler_args)...)); +} + +/** + * @brief See io_uring_prep_uring_cmd128 + * @param cmd_func Function to configure sqe for specific command. Signature: + * void(io_uring_sqe *sqe). + * @param cqe_handler CQE handler for specific result processing. + */ +template inline auto async_uring_cmd128(int cmd_op, Fd fd, CmdFunc &&cmd_func, - Args &&...handler_args) { + CQEHandler &&cqe_handler) { auto prep_func = [cmd_op, fd = detail::unwrap_fixed(fd), cmd_func = std::forward(cmd_func)](detail::Ring *ring) { @@ -937,8 +991,8 @@ inline auto async_uring_cmd128(int cmd_op, Fd fd, CmdFunc &&cmd_func, cmd_func(sqe); return sqe; }; - auto op = build_op_awaiter(std::move(prep_func), - std::forward(handler_args)...); + auto op = build_op_awaiter(std::move(prep_func), + std::forward(cqe_handler)); return detail::maybe_flag_fixed_fd(std::move(op), fd); } #endif diff --git a/include/condy/awaiter_operations.hpp b/include/condy/awaiter_operations.hpp index 8f7bc642..60bfe2d0 100644 --- a/include/condy/awaiter_operations.hpp +++ b/include/condy/awaiter_operations.hpp @@ -16,62 +16,57 @@ namespace condy { /** * @brief Build a single-shot operation awaiter with custom CQE handler. - * @tparam CQEHandler Type of CQE handler. * @tparam PrepFunc Type of preparation function. - * @tparam Args Additional arguments for CQE handler construction. + * @tparam CQEHandler Type of CQE handler. * @param func Preparation function that accepts `Ring*` and returns * `io_uring_sqe*`. - * @param handler_args Arguments forwarded to CQE handler constructor. + * @param cqe_handler CQE handler instance. * @return OpAwaiter The constructed awaiter. */ -template -auto build_op_awaiter(PrepFunc &&func, Args &&...handler_args) { - return build_op_sender(std::forward(func), - std::forward(handler_args)...); +template +auto build_op_awaiter(PrepFunc &&func, CQEHandler &&cqe_handler) { + return build_op_sender(std::forward(func), + std::forward(cqe_handler)); } /** * @brief Build a multi-shot operation awaiter with custom CQE handler. - * @tparam CQEHandler Type of CQE handler. * @tparam PrepFunc Type of preparation function. + * @tparam CQEHandler Type of CQE handler. * @tparam MultiShotFunc Type of callback function for multi-shot operations. - * @tparam Args Additional arguments for CQE handler construction. * @param func Preparation function that accepts `Ring*` and returns * `io_uring_sqe*`. + * @param cqe_handler CQE handler instance. * @param multishot_func Callback invoked on each completion except the last * one. - * @param handler_args Arguments forwarded to CQE handler constructor. * @return MultiShotOpAwaiter The constructed awaiter. */ -template -auto build_multishot_op_awaiter(PrepFunc &&func, MultiShotFunc &&multishot_func, - Args &&...handler_args) { - return build_multishot_op_sender( - std::forward(func), - std::forward(multishot_func), - std::forward(handler_args)...); +template +auto build_multishot_op_awaiter(PrepFunc &&func, CQEHandler &&cqe_handler, + MultiShotFunc &&multishot_func) { + return build_multishot_op_sender( + std::forward(func), std::forward(cqe_handler), + std::forward(multishot_func)); } /** * @brief Build a zero-copy operation awaiter with custom CQE handler. - * @tparam CQEHandler Type of CQE handler. * @tparam PrepFunc Type of preparation function. + * @tparam CQEHandler Type of CQE handler. * @tparam FreeFunc Type of resource cleanup function. - * @tparam Args Additional arguments for CQE handler construction. * @param func Preparation function that accepts `Ring*` and returns * `io_uring_sqe*`. + * @param cqe_handler CQE handler instance. * @param free_func Cleanup function invoked when resource no longer needed. - * @param handler_args Arguments forwarded to CQE handler constructor. * @return ZeroCopyOpAwaiter The constructed awaiter. */ -template -auto build_zero_copy_op_awaiter(PrepFunc &&func, FreeFunc &&free_func, - Args &&...handler_args) { - return build_zero_copy_op_sender( - std::forward(func), std::forward(free_func), - std::forward(handler_args)...); +template +auto build_zero_copy_op_awaiter(PrepFunc &&func, CQEHandler &&cqe_handler, + FreeFunc &&free_func) { + return build_zero_copy_op_sender(std::forward(func), + std::forward(cqe_handler), + std::forward(free_func)); } -} // namespace condy \ No newline at end of file +} // namespace condy diff --git a/include/condy/detail/async_operations.hpp b/include/condy/detail/async_operations.hpp index 4151939b..85fe7bf0 100644 --- a/include/condy/detail/async_operations.hpp +++ b/include/condy/detail/async_operations.hpp @@ -32,7 +32,7 @@ auto make_op_awaiter(Func &&func, Args &&...args) { func(sqe, args...); return sqe; }; - return build_op_awaiter(std::move(prep_func)); + return build_op_awaiter(std::move(prep_func), SimpleCQEHandler{}); } #if CONDY_URING_VERSION_GE(2, 13) // >= 2.13 @@ -48,7 +48,7 @@ auto make_op_awaiter128(Func &&func, Args &&...args) { func(sqe, args...); return sqe; }; - return build_op_awaiter(std::move(prep_func)); + return build_op_awaiter(std::move(prep_func), SimpleCQEHandler{}); } #endif @@ -62,8 +62,9 @@ auto make_multishot_op_awaiter(MultiShotFunc &&multishot_func, Func &&func, func(sqe, args...); return sqe; }; - return build_multishot_op_awaiter( - std::move(prep_func), std::forward(multishot_func)); + return build_multishot_op_awaiter( + std::move(prep_func), SimpleCQEHandler{}, + std::forward(multishot_func)); } template @@ -77,8 +78,8 @@ auto make_select_buffer_op_awaiter(Br *buffers, Func &&func, Args &&...args) { sqe->buf_group = bgid; return sqe; }; - return build_op_awaiter>(std::move(prep_func), - buffers); + return build_op_awaiter(std::move(prep_func), + SelectBufferCQEHandler
(buffers)); } template buf_group = bgid; return sqe; }; - return build_multishot_op_awaiter>( - std::move(prep_func), std::forward(multishot_func), - buffers); + return build_multishot_op_awaiter( + std::move(prep_func), SelectBufferCQEHandler
(buffers), + std::forward(multishot_func)); } #if CONDY_URING_VERSION_GE(2, 7) // >= 2.7 @@ -114,8 +115,8 @@ auto make_bundle_select_buffer_op_awaiter(Br *buffers, Func &&func, sqe->ioprio |= IORING_RECVSEND_BUNDLE; return sqe; }; - return build_op_awaiter>(std::move(prep_func), - buffers); + return build_op_awaiter(std::move(prep_func), + SelectBufferCQEHandler
(buffers)); } #endif @@ -134,9 +135,9 @@ auto make_multishot_bundle_select_buffer_op_awaiter( sqe->ioprio |= IORING_RECVSEND_BUNDLE; return sqe; }; - return build_multishot_op_awaiter>( - std::move(prep_func), std::forward(multishot_func), - buffers); + return build_multishot_op_awaiter( + std::move(prep_func), SelectBufferCQEHandler
(buffers), + std::forward(multishot_func)); } #endif @@ -150,8 +151,8 @@ auto make_zero_copy_op_awaiter(FreeFunc &&free_func, Func &&func, func(sqe, args...); return sqe; }; - return build_zero_copy_op_awaiter( - std::move(prep_func), std::forward(free_func)); + return build_zero_copy_op_awaiter(std::move(prep_func), SimpleCQEHandler{}, + std::forward(free_func)); } template diff --git a/include/condy/sender_operations.hpp b/include/condy/sender_operations.hpp index ea82ace3..766dda19 100644 --- a/include/condy/sender_operations.hpp +++ b/include/condy/sender_operations.hpp @@ -11,32 +11,29 @@ namespace condy { -template -auto build_op_sender(PrepFunc &&prep_func, Args &&...args) { - return OpSender, CQEHandler>( +template +auto build_op_sender(PrepFunc &&prep_func, CQEHandler &&cqe_handler) { + return OpSender, std::decay_t>( std::forward(prep_func), - CQEHandler(std::forward(args)...)); + std::forward(cqe_handler)); } -template -auto build_multishot_op_sender(PrepFunc &&func, MultiShotFunc &&multishot_func, - Args &&...handler_args) { - return MultiShotOpSender, CQEHandler, +template +auto build_multishot_op_sender(PrepFunc &&func, CQEHandler &&cqe_handler, + MultiShotFunc &&multishot_func) { + return MultiShotOpSender, std::decay_t, std::decay_t>( - std::forward(func), - CQEHandler(std::forward(handler_args)...), + std::forward(func), std::forward(cqe_handler), std::forward(multishot_func)); } -template -auto build_zero_copy_op_sender(PrepFunc &&func, FreeFunc &&free_func, - Args &&...handler_args) { - return ZeroCopyOpSender, CQEHandler, +template +auto build_zero_copy_op_sender(PrepFunc &&func, CQEHandler &&cqe_handler, + FreeFunc &&free_func) { + return ZeroCopyOpSender, std::decay_t, std::decay_t>( - std::forward(func), - CQEHandler(std::forward(handler_args)...), + std::forward(func), std::forward(cqe_handler), std::forward(free_func)); } diff --git a/tests/helpers.hpp b/tests/helpers.hpp index 035c12c5..334192f5 100644 --- a/tests/helpers.hpp +++ b/tests/helpers.hpp @@ -152,12 +152,15 @@ inline auto my_async_cmd_sock(int cmd_op, Fd fd, int level, int optname, }; #if CONDY_URING_VERSION_GE(2, 13) // >= 2.13 if constexpr (SQE128) { - return condy::async_uring_cmd128(cmd_op, fd, cmd_func); + return condy::async_uring_cmd128(cmd_op, fd, cmd_func, + condy::SimpleCQEHandler{}); } else { - return condy::async_uring_cmd(cmd_op, fd, cmd_func); + return condy::async_uring_cmd(cmd_op, fd, cmd_func, + condy::SimpleCQEHandler{}); } #else - return condy::async_uring_cmd(cmd_op, fd, cmd_func); + return condy::async_uring_cmd(cmd_op, fd, cmd_func, + condy::SimpleCQEHandler{}); #endif } #endif @@ -187,15 +190,15 @@ inline auto my_cmd_nvme_read(Fd fd, void *buf, size_t buf_size, }; #if CONDY_URING_VERSION_GE(2, 13) // >= 2.13 if constexpr (SQE128) { - return condy::async_uring_cmd128( - NVME_URING_CMD_IO, fd, cmd_func); + return condy::async_uring_cmd128(NVME_URING_CMD_IO, fd, cmd_func, + condy::NVMePassthruCQEHandler{}); } else { - return condy::async_uring_cmd( - NVME_URING_CMD_IO, fd, cmd_func); + return condy::async_uring_cmd(NVME_URING_CMD_IO, fd, cmd_func, + condy::NVMePassthruCQEHandler{}); } #else - return condy::async_uring_cmd( - NVME_URING_CMD_IO, fd, cmd_func); + return condy::async_uring_cmd(NVME_URING_CMD_IO, fd, cmd_func, + condy::NVMePassthruCQEHandler{}); #endif } @@ -219,15 +222,15 @@ inline auto my_cmd_nvme_write(Fd fd, const void *buf, size_t buf_size, }; #if CONDY_URING_VERSION_GE(2, 13) // >= 2.13 if constexpr (SQE128) { - return condy::async_uring_cmd128( - NVME_URING_CMD_IO, fd, cmd_func); + return condy::async_uring_cmd128(NVME_URING_CMD_IO, fd, cmd_func, + condy::NVMePassthruCQEHandler{}); } else { - return condy::async_uring_cmd( - NVME_URING_CMD_IO, fd, cmd_func); + return condy::async_uring_cmd(NVME_URING_CMD_IO, fd, cmd_func, + condy::NVMePassthruCQEHandler{}); } #else - return condy::async_uring_cmd( - NVME_URING_CMD_IO, fd, cmd_func); + return condy::async_uring_cmd(NVME_URING_CMD_IO, fd, cmd_func, + condy::NVMePassthruCQEHandler{}); #endif } @@ -268,15 +271,15 @@ inline auto my_cmd_scsi_test_unit_ready(Fd fd) { }; #if CONDY_URING_VERSION_GE(2, 13) // >= 2.13 if constexpr (SQE128) { - return condy::async_uring_cmd128( - 0, fd, cmd_func); + return condy::async_uring_cmd128(0, fd, cmd_func, + condy::SCSIBsgPassthruCQEHandler{}); } else { - return condy::async_uring_cmd( - 0, fd, cmd_func); + return condy::async_uring_cmd(0, fd, cmd_func, + condy::SCSIBsgPassthruCQEHandler{}); } #else - return condy::async_uring_cmd(0, fd, - cmd_func); + return condy::async_uring_cmd(0, fd, cmd_func, + condy::SCSIBsgPassthruCQEHandler{}); #endif } diff --git a/tests/test_async_operations.4.cpp b/tests/test_async_operations.4.cpp index 062b016e..ba215199 100644 --- a/tests/test_async_operations.4.cpp +++ b/tests/test_async_operations.4.cpp @@ -470,16 +470,16 @@ TEST_CASE("test async_operations - test uring_cmd_multishot - tx timestamp") { REQUIRE(r == static_cast(msg.size())); std::vector> results; - co_await ( - condy::async_uring_cmd_multishot( - SOCKET_URING_OP_TX_TIMESTAMP, fd, [](auto) { /* no-op */ }, - [&](auto r) { - results.push_back(r); - if (results.size() == 3) { - chan.force_push(std::monostate{}); - } - }) || - chan.pop()); + co_await (condy::async_uring_cmd_multishot( + SOCKET_URING_OP_TX_TIMESTAMP, fd, + [](auto) { /* no-op */ }, condy::TxTimestampCQEHandler{}, + [&](auto r) { + results.push_back(r); + if (results.size() == 3) { + chan.force_push(std::monostate{}); + } + }) || + chan.pop()); REQUIRE(results.size() == 3); REQUIRE(results[0].second.tstype == SCM_TSTAMP_SCHED); REQUIRE(results[1].second.tstype == SCM_TSTAMP_SND);