2 * Copyright 2013 Facebook, Inc.
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
17 #ifndef FOLLY_IO_ASYNCIO_H_
18 #define FOLLY_IO_ASYNCIO_H_
20 #include <sys/types.h>
30 #include <boost/noncopyable.hpp>
32 #include "folly/Portability.h"
33 #include "folly/Range.h"
38 * An AsyncIOOp represents a pending operation. You may set a notification
39 * callback or you may use this class's methods directly.
41 * The op must remain allocated until completion.
43 class AsyncIOOp : private boost::noncopyable {
46 typedef std::function<void(AsyncIOOp*)> NotificationCallback;
48 explicit AsyncIOOp(NotificationCallback cb = NotificationCallback());
51 // There would be a cancel() method here if Linux AIO actually implemented
52 // it. But let's not get your hopes up.
62 * Initiate a read request.
64 void pread(int fd, void* buf, size_t size, off_t start);
65 void pread(int fd, Range<unsigned char*> range, off_t start);
66 void preadv(int fd, const iovec* iov, int iovcnt, off_t start);
69 * Initiate a write request.
71 void pwrite(int fd, const void* buf, size_t size, off_t start);
72 void pwrite(int fd, Range<const unsigned char*> range, off_t start);
73 void pwritev(int fd, const iovec* iov, int iovcnt, off_t start);
76 * Return the current operation state.
78 State state() const { return state_; }
81 * Reset the operation for reuse. It is an error to call reset() on
82 * an Op that is still pending.
84 void reset(NotificationCallback cb = NotificationCallback());
86 void setNotificationCallback(NotificationCallback cb) { cb_ = std::move(cb); }
87 const NotificationCallback& notificationCallback() const { return cb_; }
90 * Retrieve the result of this operation. Returns >=0 on success,
91 * -errno on failure (that is, using the Linux kernel error reporting
92 * conventions). Use checkKernelError (folly/Exception.h) on the result to
93 * throw a std::system_error in case of error instead.
95 * It is an error to call this if the Op hasn't yet started or is still
98 ssize_t result() const;
103 void complete(ssize_t result);
105 NotificationCallback cb_;
112 * C++ interface around Linux Async IO.
114 class AsyncIO : private boost::noncopyable {
116 typedef AsyncIOOp Op;
124 * Create an AsyncIO context capable of holding at most 'capacity' pending
125 * requests at the same time. As requests complete, others can be scheduled,
126 * as long as this limit is not exceeded.
128 * Note: the maximum number of allowed concurrent requests is controlled
129 * by the fs.aio-max-nr sysctl, the default value is usually 64K.
131 * If pollMode is POLLABLE, pollFd() will return a file descriptor that
132 * can be passed to poll / epoll / select and will become readable when
133 * any IOs on this AsyncIO have completed. If you do this, you must use
134 * pollCompleted() instead of wait() -- do not read from the pollFd()
135 * file descriptor directly.
137 explicit AsyncIO(size_t capacity, PollMode pollMode=NOT_POLLABLE);
141 * Wait for at least minRequests to complete. Returns the requests that
142 * have completed; the returned range is valid until the next call to
143 * wait(). minRequests may be 0 to not block.
145 Range<Op**> wait(size_t minRequests);
148 * Return the number of pending requests.
150 size_t pending() const { return pending_; }
153 * Return the maximum number of requests that can be kept outstanding
156 size_t capacity() const { return capacity_; }
159 * If POLLABLE, return a file descriptor that can be passed to poll / epoll
160 * and will become readable when any async IO operations have completed.
161 * If NOT_POLLABLE, return -1.
163 int pollFd() const { return pollFd_; }
166 * If POLLABLE, call instead of wait after the file descriptor returned
167 * by pollFd() became readable. The returned range is valid until the next
168 * call to pollCompleted().
170 Range<Op**> pollCompleted();
173 * Submit an op for execution.
178 void initializeContext();
179 Range<Op**> doWait(size_t minRequests, size_t maxRequests);
183 const size_t capacity_;
185 std::vector<Op*> completed_;
189 * Wrapper around AsyncIO that allows you to schedule more requests than
190 * the AsyncIO's object capacity. Other requests are queued and processed
196 * Create a queue, using the given AsyncIO object.
197 * The AsyncIO object may not be used by anything else until the
198 * queue is destroyed.
200 explicit AsyncIOQueue(AsyncIO* asyncIO);
203 size_t queued() const { return queue_.size(); }
206 * Submit an op to the AsyncIO queue. The op will be queued until
207 * the AsyncIO object has room.
209 void submit(AsyncIOOp* op);
212 * Submit a delayed op to the AsyncIO queue; this allows you to postpone
213 * creation of the Op (which may require allocating memory, etc) until
214 * the AsyncIO object has room.
216 typedef std::function<AsyncIOOp*()> OpFactory;
217 void submit(OpFactory op);
219 void onCompleted(AsyncIOOp* op);
224 std::deque<OpFactory> queue_;
229 #endif /* FOLLY_IO_ASYNCIO_H_ */