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
45 changes: 23 additions & 22 deletions include/condy/awaiter_operations.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@

#include "condy/awaiters.hpp"
#include "condy/concepts.hpp"
#include "condy/cqe_handler.hpp"

namespace condy {

Expand All @@ -25,7 +26,8 @@ auto make_op_awaiter(Func &&func, Args &&...args) {
... args = std::forward<Args>(args)](auto sqe) {
func(sqe, args...);
};
return OpAwaiter<decltype(prep_func)>(std::move(prep_func));
return OpAwaiter<decltype(prep_func), SimpleCQEHandler>(
std::move(prep_func));
}

#if !IO_URING_CHECK_VERSION(2, 13) // >= 2.13
Expand All @@ -38,7 +40,8 @@ auto make_op_awaiter128(Func &&func, Args &&...args) {
... args = std::forward<Args>(args)](auto sqe) {
func(sqe, args...);
};
return OpAwaiter128<decltype(prep_func)>(std::move(prep_func));
return OpAwaiter<decltype(prep_func), SimpleCQEHandler, true>(
std::move(prep_func));
}
#endif

Expand All @@ -52,8 +55,9 @@ auto make_multishot_op_awaiter(MultiShotFunc &&multishot_func, Func &&func,
... args = std::forward<Args>(args)](auto sqe) {
func(sqe, args...);
};
return MultiShotOpAwaiter<std::decay_t<MultiShotFunc>, decltype(prep_func)>(
std::forward<MultiShotFunc>(multishot_func), std::move(prep_func));
return MultiShotOpAwaiter<decltype(prep_func), SimpleCQEHandler,
std::decay_t<MultiShotFunc>>(
std::move(prep_func), std::forward<MultiShotFunc>(multishot_func));
}

/**
Expand All @@ -67,9 +71,8 @@ auto make_select_buffer_op_awaiter(Br *buffers, Func &&func, Args &&...args) {
sqe->flags |= IOSQE_BUFFER_SELECT;
sqe->buf_group = bgid;
};
auto op = SelectBufferOpAwaiter<Br, decltype(prep_func)>(
buffers, std::move(prep_func));
return op;
return OpAwaiter<decltype(prep_func), SelectBufferCQEHandler<Br>>(
std::move(prep_func), buffers);
}

/**
Expand All @@ -86,11 +89,10 @@ auto make_multishot_select_buffer_op_awaiter(MultiShotFunc &&multishot_func,
sqe->flags |= IOSQE_BUFFER_SELECT;
sqe->buf_group = bgid;
};
auto op = MultiShotSelectBufferOpAwaiter<std::decay_t<MultiShotFunc>, Br,
decltype(prep_func)>(
std::forward<MultiShotFunc>(multishot_func), buffers,
std::move(prep_func));
return op;
return MultiShotOpAwaiter<decltype(prep_func), SelectBufferCQEHandler<Br>,
std::decay_t<MultiShotFunc>>(
std::move(prep_func), std::forward<MultiShotFunc>(multishot_func),
buffers);
}

#if !IO_URING_CHECK_VERSION(2, 7) // >= 2.7
Expand All @@ -107,9 +109,8 @@ auto make_bundle_select_buffer_op_awaiter(Br *buffers, Func &&func,
sqe->buf_group = bgid;
sqe->ioprio |= IORING_RECVSEND_BUNDLE;
};
auto op = SelectBufferOpAwaiter<Br, decltype(prep_func)>(
buffers, std::move(prep_func));
return op;
return OpAwaiter<decltype(prep_func), SelectBufferCQEHandler<Br>>(
std::move(prep_func), buffers);
}
#endif

Expand All @@ -128,11 +129,10 @@ auto make_multishot_bundle_select_buffer_op_awaiter(
sqe->buf_group = bgid;
sqe->ioprio |= IORING_RECVSEND_BUNDLE;
};
auto op = MultiShotSelectBufferOpAwaiter<std::decay_t<MultiShotFunc>, Br,
decltype(prep_func)>(
std::forward<MultiShotFunc>(multishot_func), buffers,
std::move(prep_func));
return op;
return MultiShotOpAwaiter<decltype(prep_func), SelectBufferCQEHandler<Br>,
std::decay_t<MultiShotFunc>>(
std::move(prep_func), std::forward<MultiShotFunc>(multishot_func),
buffers);
}
#endif

Expand All @@ -146,8 +146,9 @@ auto make_zero_copy_op_awaiter(FreeFunc &&free_func, Func &&func,
... args = std::forward<Args>(args)](auto sqe) {
func(sqe, args...);
};
return ZeroCopyOpAwaiter<std::decay_t<FreeFunc>, decltype(prep_func)>(
std::forward<FreeFunc>(free_func), std::move(prep_func));
return ZeroCopyOpAwaiter<decltype(prep_func), SimpleCQEHandler,
std::decay_t<FreeFunc>>(
std::move(prep_func), std::forward<FreeFunc>(free_func));
}

/**
Expand Down
81 changes: 32 additions & 49 deletions include/condy/awaiters.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -108,64 +108,47 @@ class OpAwaiterBase {
HandleBox<Handle> finish_handle_;
};

template <typename Func>
class [[nodiscard]] OpAwaiter : public OpAwaiterBase<OpFinishHandle, Func> {
template <typename PrepFunc, CQEHandlerLike CQEHandler, bool SQE128 = false>
class [[nodiscard]] OpAwaiter
: public OpAwaiterBase<OpFinishHandle<CQEHandler>, PrepFunc, SQE128> {
public:
using Base = OpAwaiterBase<OpFinishHandle, Func>;
OpAwaiter(Func func) : Base(OpFinishHandle(), func) {}
};

#if !IO_URING_CHECK_VERSION(2, 13) // >= 2.13
template <typename Func>
class [[nodiscard]] OpAwaiter128
: public OpAwaiterBase<OpFinishHandle, Func, true> {
public:
using Base = OpAwaiterBase<OpFinishHandle, Func, true>;
OpAwaiter128(Func func) : Base(OpFinishHandle(), func) {}
using Base = OpAwaiterBase<OpFinishHandle<CQEHandler>, PrepFunc, SQE128>;
template <typename... Args>
OpAwaiter(PrepFunc func, Args &&...args)
: Base(HandleBox(
OpFinishHandle<CQEHandler>(std::forward<Args>(args)...)),
func) {}
};
#endif

template <typename MultiShotFunc, typename Func>
template <typename PrepFunc, CQEHandlerLike CQEHandler, typename MultiShotFunc,
bool SQE128 = false>
class [[nodiscard]] MultiShotOpAwaiter
: public OpAwaiterBase<MultiShotOpFinishHandle<MultiShotFunc>, Func> {
: public OpAwaiterBase<MultiShotOpFinishHandle<CQEHandler, MultiShotFunc>,
PrepFunc, SQE128> {
public:
using Base = OpAwaiterBase<MultiShotOpFinishHandle<MultiShotFunc>, Func>;
MultiShotOpAwaiter(MultiShotFunc multishot_func, Func func)
: Base(
MultiShotOpFinishHandle<MultiShotFunc>(std::move(multishot_func)),
func) {}
using Base =
OpAwaiterBase<MultiShotOpFinishHandle<CQEHandler, MultiShotFunc>,
PrepFunc, SQE128>;
template <typename... Args>
MultiShotOpAwaiter(PrepFunc func, MultiShotFunc multishot_func,
Args &&...args)
: Base(HandleBox(MultiShotOpFinishHandle<CQEHandler, MultiShotFunc>(
std::move(multishot_func), std::forward<Args>(args)...)),
func) {}
};

template <typename FreeFunc, typename Func>
template <typename PrepFunc, CQEHandlerLike CQEHandler, typename FreeFunc,
bool SQE128 = false>
class [[nodiscard]] ZeroCopyOpAwaiter
: public OpAwaiterBase<ZeroCopyOpFinishHandle<FreeFunc>, Func> {
: public OpAwaiterBase<ZeroCopyOpFinishHandle<CQEHandler, FreeFunc>,
PrepFunc, SQE128> {
public:
using Base = OpAwaiterBase<ZeroCopyOpFinishHandle<FreeFunc>, Func>;
ZeroCopyOpAwaiter(FreeFunc free_func, Func func)
: Base(ZeroCopyOpFinishHandle<FreeFunc>(std::move(free_func)), func) {}
};

template <BufferRingLike Br, typename Func>
class [[nodiscard]] SelectBufferOpAwaiter
: public OpAwaiterBase<SelectBufferOpFinishHandle<Br>, Func> {
public:
using Base = OpAwaiterBase<SelectBufferOpFinishHandle<Br>, Func>;
SelectBufferOpAwaiter(Br *buffers, Func func)
: Base(SelectBufferOpFinishHandle<Br>(buffers), func) {}
};

template <typename MultiShotFunc, BufferRingLike Br, typename Func>
class [[nodiscard]] MultiShotSelectBufferOpAwaiter
: public OpAwaiterBase<
MultiShotSelectBufferOpFinishHandle<MultiShotFunc, Br>, Func> {
public:
using Base =
OpAwaiterBase<MultiShotSelectBufferOpFinishHandle<MultiShotFunc, Br>,
Func>;
MultiShotSelectBufferOpAwaiter(MultiShotFunc multishot_func, Br *buffers,
Func func)
: Base(MultiShotSelectBufferOpFinishHandle<MultiShotFunc, Br>(
std::move(multishot_func), buffers),
using Base = OpAwaiterBase<ZeroCopyOpFinishHandle<CQEHandler, FreeFunc>,
PrepFunc, SQE128>;
template <typename... Args>
ZeroCopyOpAwaiter(PrepFunc func, FreeFunc free_func, Args &&...args)
: Base(HandleBox(ZeroCopyOpFinishHandle<CQEHandler, FreeFunc>(
std::move(free_func), std::forward<Args>(args)...)),
func) {}
};

Expand Down
12 changes: 10 additions & 2 deletions include/condy/concepts.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,9 @@ namespace condy {
namespace detail {

struct FixedFd;
struct Action;

}
} // namespace detail

template <typename T>
concept HandleLike = requires(T handle, Invoker *invoker) {
Expand All @@ -29,9 +30,16 @@ template <typename T>
concept OpFinishHandleLike =
HandleLike<T> && requires(T handle, io_uring_cqe *cqe) {
{ handle.invoke() } -> std::same_as<void>;
{ handle.handle_cqe(cqe) } -> std::same_as<typename T::Action>;
{ handle.handle_cqe(cqe) } -> std::same_as<detail::Action>;
};

template <typename T>
concept CQEHandlerLike = requires(T handler, io_uring_cqe *cqe) {
typename T::ReturnType;
{ handler.handle_cqe(cqe) } -> std::same_as<void>;
{ handler.extract_result() } -> std::same_as<typename T::ReturnType>;
};

template <typename T>
concept AwaiterLike = requires(T awaiter) {
typename T::HandleType;
Expand Down
52 changes: 52 additions & 0 deletions include/condy/cqe_handler.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
/**
* @file cqe_handler.hpp
* @brief Definitions of CQE handlers
* @details This file defines a series of CQE handlers, which are responsible
* for processing the completion of asynchronous operations. Each handler
* defines a `handle_cqe` method to process the CQE and an `extract_result`
* method to retrieve the result of the operation.
*/

#pragma once

#include "condy/concepts.hpp"
#include <cerrno>
#include <cstdint>
#include <utility>

namespace condy {

class SimpleCQEHandler {
public:
using ReturnType = int32_t;

void handle_cqe(io_uring_cqe *cqe) { res_ = cqe->res; }

ReturnType extract_result() { return res_; }

private:
int32_t res_ = -ENOTRECOVERABLE; // Internal error if not set
};
Comment thread
wokron marked this conversation as resolved.

template <BufferRingLike Br> class SelectBufferCQEHandler {
public:
using ReturnType = std::pair<int, typename Br::ReturnType>;

SelectBufferCQEHandler(Br *buffers) : buffers_(buffers) {}

void handle_cqe(io_uring_cqe *cqe) {
res_ = cqe->res;
flags_ = cqe->flags;
}

ReturnType extract_result() {
return std::make_pair(res_, buffers_->handle_finish(res_, flags_));
}

private:
int32_t res_ = -ENOTRECOVERABLE; // Internal error if not set
uint32_t flags_ = 0;
Br *buffers_;
};

} // namespace condy
Loading
Loading