io_uring: Add wait functions
This makes it possible to write trivial applications that aren't
necessarily using a full blown event loop.
Change-Id: If19cc9f0c21c029a5fda6a0d4f3eae8677841999
Signed-off-by: William A. Kennington III <wak@google.com>
diff --git a/src/stdplus/io_uring.cpp b/src/stdplus/io_uring.cpp
index eaa2848..7acf2c7 100644
--- a/src/stdplus/io_uring.cpp
+++ b/src/stdplus/io_uring.cpp
@@ -12,6 +12,14 @@
namespace stdplus
{
+__kernel_timespec chronoToKTS(std::chrono::nanoseconds t) noexcept
+{
+ __kernel_timespec ts;
+ ts.tv_sec = std::chrono::floor<std::chrono::seconds>(t).count();
+ ts.tv_nsec = (t % std::chrono::seconds(1)).count();
+ return ts;
+}
+
IoUring::IoUring(size_t queue_size)
{
CHECK_RET(io_uring_queue_init(queue_size, &ring, 0), "io_uring_queue_init");
@@ -109,6 +117,20 @@
}
}
+void IoUring::wait()
+{
+ io_uring_cqe* cqe;
+ CHECK_RET(io_uring_wait_cqe(&ring, &cqe), "io_uring_wait_cqe");
+}
+
+void IoUring::wait(std::chrono::nanoseconds timeout)
+{
+ io_uring_cqe* cqe;
+ auto kts = chronoToKTS(timeout);
+ CHECK_RET(io_uring_wait_cqe_timeout(&ring, &cqe, &kts),
+ "io_uring_wait_cqe_timeout");
+}
+
stdplus::ManagedFd& IoUring::getEventFd()
{
if (event_fd)
diff --git a/src/stdplus/io_uring.hpp b/src/stdplus/io_uring.hpp
index f4cd269..d5f33e8 100644
--- a/src/stdplus/io_uring.hpp
+++ b/src/stdplus/io_uring.hpp
@@ -5,12 +5,16 @@
#include <stdplus/fd/managed.hpp>
#include <stdplus/handle/managed.hpp>
+#include <chrono>
#include <optional>
#include <vector>
namespace stdplus
{
+/** @brief Converts a chrono duration into a kernel duration */
+__kernel_timespec chronoToKTS(std::chrono::nanoseconds t) noexcept;
+
class IoUring
{
public:
@@ -90,6 +94,10 @@
/** @brief Non-blocking process all outstanding CQEs */
void process() noexcept;
+ /** @brief Waits for new CQEs to become available */
+ void wait();
+ void wait(std::chrono::nanoseconds timeout);
+
/** @brief Returns the EventFD associated with the ring
* A new descriptor is created if it does not yet exist
*
diff --git a/test/io_uring.cpp b/test/io_uring.cpp
index 6e9981d..6b8290e 100644
--- a/test/io_uring.cpp
+++ b/test/io_uring.cpp
@@ -1,5 +1,7 @@
#include <poll.h>
+#include <array>
+#include <chrono>
#include <stdplus/io_uring.hpp>
#include <gmock/gmock.h>
@@ -10,6 +12,16 @@
using testing::_;
+TEST(Convert, ChronoToKTS)
+{
+ const auto ns = 700;
+ const auto s = 5;
+ const auto kts =
+ chronoToKTS(std::chrono::nanoseconds(ns) + std::chrono::seconds(s));
+ EXPECT_EQ(kts.tv_sec, s);
+ EXPECT_EQ(kts.tv_nsec, ns);
+}
+
class MockHandler : public IoUring::CQEHandler
{
public:
@@ -123,6 +135,17 @@
ASSERT_EQ(0, poll(&pfd, 1, 100));
}
+TEST_F(IoUringTest, Wait)
+{
+ auto& sqe = ring.getSQE();
+ auto kts = chronoToKTS(std::chrono::milliseconds(1));
+ io_uring_prep_timeout(&sqe, &kts, 0, 0);
+ ring.setHandler(sqe, &h[0]);
+ ring.submit();
+ ring.wait(std::chrono::seconds(1));
+ EXPECT_CALL(h[0], handleCQE(_));
+}
+
TEST_F(IoUringTest, HandleCalledOnDestroy)
{
auto& sqe = ring.getSQE();