Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
280 changes: 150 additions & 130 deletions include/condy/async_operations.hpp

Large diffs are not rendered by default.

114 changes: 74 additions & 40 deletions include/condy/awaiter_operations.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,69 @@
namespace condy {

/**
* @brief This function creates a variant of OpAwaiter. OpAwaiter represents an
* asynchronous operation that can be awaited. It is basically a wrapper around
* an io_uring sqe preparation function.
* @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.
* @param func Preparation function that accepts `Ring*` and returns
* `io_uring_sqe*`.
* @param handler_args Arguments forwarded to CQE handler constructor.
* @return OpAwaiter The constructed awaiter.
*/
template <CQEHandlerLike CQEHandler, PrepFuncLike PrepFunc, typename... Args>
auto build_op_awaiter(PrepFunc &&func, Args &&...handler_args) {
return OpAwaiter<std::decay_t<PrepFunc>, CQEHandler>(
std::forward<PrepFunc>(func), std::forward<Args>(handler_args)...);
}
Comment thread
wokron marked this conversation as resolved.

/**
* @brief Build a multi-shot operation awaiter with custom CQE handler.
* @tparam CQEHandler Type of CQE handler.
* @tparam PrepFunc Type of preparation function.
* @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 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 <CQEHandlerLike CQEHandler, PrepFuncLike PrepFunc,
typename MultiShotFunc, typename... Args>
auto build_multishot_op_awaiter(PrepFunc &&func, MultiShotFunc &&multishot_func,
Args &&...handler_args) {
return MultiShotOpAwaiter<std::decay_t<PrepFunc>, CQEHandler,
std::decay_t<MultiShotFunc>>(
std::forward<PrepFunc>(func),
std::forward<MultiShotFunc>(multishot_func),
std::forward<Args>(handler_args)...);
}

/**
* @brief Build a zero-copy operation awaiter with custom CQE handler.
* @tparam CQEHandler Type of CQE handler.
* @tparam PrepFunc Type of preparation function.
* @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 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 <CQEHandlerLike CQEHandler, PrepFuncLike PrepFunc, typename FreeFunc,
typename... Args>
auto build_zero_copy_op_awaiter(PrepFunc &&func, FreeFunc &&free_func,
Args &&...handler_args) {
return ZeroCopyOpAwaiter<std::decay_t<PrepFunc>, CQEHandler,
std::decay_t<FreeFunc>>(
std::forward<PrepFunc>(func), std::forward<FreeFunc>(free_func),
std::forward<Args>(handler_args)...);
}

namespace detail {

template <typename Func, typename... Args>
auto make_op_awaiter(Func &&func, Args &&...args) {
auto prep_func = [func = std::forward<Func>(func),
Comment thread
wokron marked this conversation as resolved.
Expand All @@ -29,14 +88,10 @@ auto make_op_awaiter(Func &&func, Args &&...args) {
func(sqe, args...);
return sqe;
};
return OpAwaiter<decltype(prep_func), SimpleCQEHandler>(
std::move(prep_func));
return build_op_awaiter<SimpleCQEHandler>(std::move(prep_func));
}

#if !IO_URING_CHECK_VERSION(2, 13) // >= 2.13
/**
* @copydoc make_op_awaiter
*/
template <typename Func, typename... Args>
auto make_op_awaiter128(Func &&func, Args &&...args) {
auto prep_func = [func = std::forward<Func>(func),
Expand All @@ -45,14 +100,10 @@ auto make_op_awaiter128(Func &&func, Args &&...args) {
func(sqe, args...);
return sqe;
};
return OpAwaiter<decltype(prep_func), SimpleCQEHandler>(
std::move(prep_func));
return build_op_awaiter<SimpleCQEHandler>(std::move(prep_func));
}
#endif

/**
* @copydoc make_op_awaiter
*/
template <typename MultiShotFunc, typename Func, typename... Args>
auto make_multishot_op_awaiter(MultiShotFunc &&multishot_func, Func &&func,
Args &&...args) {
Expand All @@ -62,14 +113,10 @@ auto make_multishot_op_awaiter(MultiShotFunc &&multishot_func, Func &&func,
func(sqe, args...);
return sqe;
};
return MultiShotOpAwaiter<decltype(prep_func), SimpleCQEHandler,
std::decay_t<MultiShotFunc>>(
return build_multishot_op_awaiter<SimpleCQEHandler>(
std::move(prep_func), std::forward<MultiShotFunc>(multishot_func));
}

/**
* @copydoc make_op_awaiter
*/
template <BufferRingLike Br, typename Func, typename... Args>
auto make_select_buffer_op_awaiter(Br *buffers, Func &&func, Args &&...args) {
auto prep_func = [bgid = buffers->bgid(), func = std::forward<Func>(func),
Expand All @@ -80,13 +127,10 @@ auto make_select_buffer_op_awaiter(Br *buffers, Func &&func, Args &&...args) {
sqe->buf_group = bgid;
return sqe;
};
return OpAwaiter<decltype(prep_func), SelectBufferCQEHandler<Br>>(
std::move(prep_func), buffers);
return build_op_awaiter<SelectBufferCQEHandler<Br>>(std::move(prep_func),
buffers);
}

/**
* @copydoc make_op_awaiter
*/
template <typename MultiShotFunc, BufferRingLike Br, typename Func,
typename... Args>
auto make_multishot_select_buffer_op_awaiter(MultiShotFunc &&multishot_func,
Expand All @@ -100,16 +144,12 @@ auto make_multishot_select_buffer_op_awaiter(MultiShotFunc &&multishot_func,
sqe->buf_group = bgid;
return sqe;
};
return MultiShotOpAwaiter<decltype(prep_func), SelectBufferCQEHandler<Br>,
std::decay_t<MultiShotFunc>>(
return build_multishot_op_awaiter<SelectBufferCQEHandler<Br>>(
std::move(prep_func), std::forward<MultiShotFunc>(multishot_func),
buffers);
}

#if !IO_URING_CHECK_VERSION(2, 7) // >= 2.7
/**
* @copydoc make_op_awaiter
*/
template <BufferRingLike Br, typename Func, typename... Args>
auto make_bundle_select_buffer_op_awaiter(Br *buffers, Func &&func,
Args &&...args) {
Expand All @@ -122,15 +162,12 @@ auto make_bundle_select_buffer_op_awaiter(Br *buffers, Func &&func,
sqe->ioprio |= IORING_RECVSEND_BUNDLE;
return sqe;
};
return OpAwaiter<decltype(prep_func), SelectBufferCQEHandler<Br>>(
std::move(prep_func), buffers);
return build_op_awaiter<SelectBufferCQEHandler<Br>>(std::move(prep_func),
buffers);
}
#endif

#if !IO_URING_CHECK_VERSION(2, 7) // >= 2.7
/**
* @copydoc make_op_awaiter
*/
template <typename MultiShotFunc, BufferRingLike Br, typename Func,
typename... Args>
auto make_multishot_bundle_select_buffer_op_awaiter(
Expand All @@ -144,16 +181,12 @@ auto make_multishot_bundle_select_buffer_op_awaiter(
sqe->ioprio |= IORING_RECVSEND_BUNDLE;
return sqe;
};
return MultiShotOpAwaiter<decltype(prep_func), SelectBufferCQEHandler<Br>,
std::decay_t<MultiShotFunc>>(
return build_multishot_op_awaiter<SelectBufferCQEHandler<Br>>(
std::move(prep_func), std::forward<MultiShotFunc>(multishot_func),
buffers);
}
#endif

/**
* @copydoc make_op_awaiter
*/
template <typename FreeFunc, typename Func, typename... Args>
auto make_zero_copy_op_awaiter(FreeFunc &&free_func, Func &&func,
Args &&...args) {
Expand All @@ -163,11 +196,12 @@ auto make_zero_copy_op_awaiter(FreeFunc &&free_func, Func &&func,
func(sqe, args...);
return sqe;
};
return ZeroCopyOpAwaiter<decltype(prep_func), SimpleCQEHandler,
std::decay_t<FreeFunc>>(
return build_zero_copy_op_awaiter<SimpleCQEHandler>(
std::move(prep_func), std::forward<FreeFunc>(free_func));
}

} // namespace detail

/**
* @brief Decorates an awaiter with specific io_uring sqe flags.
* @tparam Flags The io_uring sqe flags to set.
Expand Down
9 changes: 9 additions & 0 deletions include/condy/cqe_handler.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,10 @@

namespace condy {

/**
* @brief A simple CQE handler that extracts the result from the CQE without any
* additional processing.
*/
class SimpleCQEHandler {
public:
using ReturnType = int32_t;
Expand All @@ -28,6 +32,11 @@ class SimpleCQEHandler {
int32_t res_ = -ENOTRECOVERABLE; // Internal error if not set
};

/**
* @brief A CQE handler that returns the selected buffers based on the result of
* the CQE.
* @tparam Br The buffer ring type
*/
template <BufferRingLike Br> class SelectBufferCQEHandler {
public:
using ReturnType = std::pair<int, typename Br::ReturnType>;
Expand Down
Loading
Loading