• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
57   // Prepare read to a registered buffer. This does not submit the operation
58   // to the kernel. For that, call |IoUringInterface::Submit()|
59   virtual IoUringSQE PrepReadFixed(
60       int fd, void* buf, unsigned nbytes, uint64_t offset, int buf_index) = 0;
61 
62   // Append a submission entry into this io_uring. This does not submit the
63   // operation to the kernel. For that, call |IoUringInterface::Submit()|
64   virtual IoUringSQE PrepRead(int fd, void *buf, unsigned nbytes,
65                               uint64_t offset) = 0;
66   // Caller is responsible for making sure the input memory is available until
67   // this write operation completes.
68   virtual IoUringSQE PrepWrite(int fd, const void *buf, unsigned nbytes,
69                                uint64_t offset) = 0;
70 
71   // Return number of SQEs available in the queue. If this is 0, subsequent
72   // calls to Prep*() functions will fail.
73   virtual size_t SQELeft() const = 0;
74   // Return number of SQEs currently in the queue. SQEs already submitted would
75   // not be counted.
76   virtual size_t SQEReady() const = 0;
77 
78   // Ring operations
79   virtual IoUringSubmitResult Submit() = 0;
80   // Submit and block until |completions| number of CQEs are available
81   virtual IoUringSubmitResult SubmitAndWait(size_t completions) = 0;
82   virtual Result<Errno, IoUringCQE> PopCQE() = 0;
83   virtual Result<Errno, std::vector<IoUringCQE>> PopCQE(unsigned int count) = 0;
84   virtual Result<Errno, IoUringCQE> PeekCQE() = 0;
85 
86   static std::unique_ptr<IoUringInterface> CreateLinuxIoUring(int queue_depth,
87                                                               int flags);
88 };
89 
90 }  // namespace io_uring_cpp
91 
92 #endif
93