blob: 3ec5da169242f3b969161df906bc386538104a80 [file] [log] [blame]
William A. Kennington III5c20da22021-06-18 16:44:55 -07001#include <liburing.h>
2#include <sys/eventfd.h>
3
4#include <stdplus/fd/managed.hpp>
5#include <stdplus/fd/ops.hpp>
6#include <stdplus/io_uring.hpp>
7#include <stdplus/util/cexec.hpp>
8
9#include <algorithm>
10
11namespace stdplus
12{
13
14IoUring::IoUring(size_t queue_size)
15{
16 CHECK_RET(io_uring_queue_init(queue_size, &ring, 0), "io_uring_queue_init");
17}
18
19IoUring::~IoUring()
20{
21 io_uring_queue_exit(&ring);
22 io_uring_cqe cqe{};
23 cqe.res = -ECANCELED;
24 for (auto h : handlers)
25 {
26 h->handleCQE(cqe);
27 }
28}
29
30io_uring_sqe& IoUring::getSQE()
31{
32 return *CHECK_ERRNO(io_uring_get_sqe(&ring), "io_uring_get_sqe");
33}
34
35void IoUring::setHandler(io_uring_sqe& sqe, CQEHandler* h) noexcept
36{
37 auto oldh = reinterpret_cast<CQEHandler*>(sqe.user_data);
38 if (oldh == h)
39 {
40 return;
41 }
42 io_uring_cqe cqe{};
43 cqe.res = -ECANCELED;
44 dropHandler(oldh, cqe);
45 if (h != nullptr)
46 {
47 handlers.push_back(h);
48 }
49 io_uring_sqe_set_data(&sqe, h);
50}
51
52void IoUring::cancelHandler(CQEHandler& h)
53{
54 io_uring_prep_cancel(&getSQE(), &h, 0);
55 submit();
56}
57
58void IoUring::submit()
59{
60 CHECK_RET(io_uring_submit(&ring), "io_uring_submit");
61}
62
63void IoUring::process() noexcept
64{
65 io_uring_cqe* cqe;
66 while (io_uring_peek_cqe(&ring, &cqe) == 0)
67 {
68 auto h = reinterpret_cast<CQEHandler*>(cqe->user_data);
69 dropHandler(h, *cqe);
70 io_uring_cqe_seen(&ring, cqe);
71 }
72}
73
74stdplus::ManagedFd& IoUring::getEventFd()
75{
76 if (event_fd)
77 {
78 return *event_fd;
79 }
80 stdplus::ManagedFd efd(CHECK_RET(eventfd(0, EFD_NONBLOCK), "eventfd"));
81 CHECK_RET(io_uring_register_eventfd(&ring, efd.get()),
82 "io_uring_register_eventfd");
83 return *(event_fd = std::move(efd));
84}
85
86void IoUring::processEvents()
87{
88 auto& efd = getEventFd();
89 std::byte b[8];
90 while (!stdplus::fd::read(efd, b).empty())
91 {
92 process();
93 }
94}
95
96void IoUring::dropHandler(CQEHandler* h, io_uring_cqe& cqe) noexcept
97{
98 if (h == nullptr)
99 {
100 return;
101 }
102 auto it = std::find(handlers.begin(), handlers.end(), h);
103 if (it != handlers.end() - 1)
104 {
105 std::swap(*it, handlers.back());
106 }
107 handlers.pop_back();
108 h->handleCQE(cqe);
109}
110
111} // namespace stdplus