1 // 2 // Copyright (C) 2022 The Android Open Source Project 3 // 4 // Licensed under the Apache License, Version 2.0 (the "License"); 5 // you may not use this file except in compliance with the License. 6 // You may obtain a copy of the License at 7 // 8 // http://www.apache.org/licenses/LICENSE-2.0 9 // 10 // Unless required by applicable law or agreed to in writing, software 11 // distributed under the License is distributed on an "AS IS" BASIS, 12 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 // See the License for the specific language governing permissions and 14 // limitations under the License. 15 // 16 17 #ifndef __IO_URING_CPP_H 18 #define __IO_URING_CPP_H 19 20 #include <errno.h> 21 #include <string.h> 22 23 #include <sys/uio.h> 24 25 #include <algorithm> 26 #include <memory> 27 #include <optional> 28 #include <variant> 29 30 #include "IoUringCQE.h" 31 #include "IoUringSQE.h" 32 33 namespace io_uring_cpp { 34 35 template <typename Err, typename Res> 36 struct [[nodiscard]] Result : public std::variant<Err, Res> { IsOkResult37 constexpr bool IsOk() const { return std::holds_alternative<Res>(*this); } IsErrResult38 constexpr bool IsErr() const { return std::holds_alternative<Err>(*this); } GetErrorResult39 constexpr Err GetError() const { return std::get<Err>(*this); } GetResultResult40 constexpr const Res& GetResult() const& { return std::get<Res>(*this); } GetResultResult41 constexpr Res&& GetResult() && { return std::get<Res>(*this); } 42 }; 43 44 class IoUringInterface { 45 public: ~IoUringInterface()46 virtual ~IoUringInterface() {} 47 // Registration helpers 48 // Register a fixed set of buffers to kernel. 49 virtual Errno RegisterBuffers(const struct iovec* iovecs, 50 size_t iovec_size) = 0; 51 virtual Errno UnregisterBuffers() = 0; 52 53 // Register a set of file descriptors to kernel. 54 virtual Errno RegisterFiles(const int* files, size_t files_size) = 0; 55 virtual Errno UnregisterFiles() = 0; 56 // Append a submission entry into this io_uring. This does not submit the 57 // operation to the kernel. For that, call |IoUringInterface::Submit()| 58 virtual IoUringSQE PrepRead(int fd, void *buf, unsigned nbytes, 59 uint64_t offset) = 0; 60 // Caller is responsible for making sure the input memory is available until 61 // this write operation completes. 62 virtual IoUringSQE PrepWrite(int fd, const void *buf, unsigned nbytes, 63 uint64_t offset) = 0; 64 65 // Return number of SQEs available in the queue. If this is 0, subsequent 66 // calls to Prep*() functions will fail. 67 virtual size_t SQELeft() const = 0; 68 // Return number of SQEs currently in the queue. SQEs already submitted would 69 // not be counted. 70 virtual size_t SQEReady() const = 0; 71 72 // Ring operations 73 virtual IoUringSubmitResult Submit() = 0; 74 // Submit and block until |completions| number of CQEs are available 75 virtual IoUringSubmitResult SubmitAndWait(size_t completions) = 0; 76 virtual Result<Errno, IoUringCQE> PopCQE() = 0; 77 virtual Result<Errno, std::vector<IoUringCQE>> PopCQE(unsigned int count) = 0; 78 virtual Result<Errno, IoUringCQE> PeekCQE() = 0; 79 80 static std::unique_ptr<IoUringInterface> CreateLinuxIoUring(int queue_depth, 81 int flags); 82 }; 83 84 } // namespace io_uring_cpp 85 86 #endif 87