Make AsyncIO::capacity_ const
[folly.git] / folly / experimental / io / AsyncIO.h
1 /*
2  * Copyright 2013 Facebook, Inc.
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 FOLLY_IO_ASYNCIO_H_
18 #define FOLLY_IO_ASYNCIO_H_
19
20 #include <sys/types.h>
21 #include <sys/uio.h>
22 #include <libaio.h>
23
24 #include <cstdint>
25 #include <functional>
26 #include <utility>
27 #include <vector>
28
29 #include <boost/noncopyable.hpp>
30
31 #include "folly/Portability.h"
32 #include "folly/Range.h"
33
34 namespace folly {
35
36 /**
37  * C++ interface around Linux Async IO.
38  */
39 class AsyncIO : private boost::noncopyable {
40  public:
41   enum PollMode {
42     NOT_POLLABLE,
43     POLLABLE
44   };
45
46   /**
47    * Create an AsyncIO context capable of holding at most 'capacity' pending
48    * requests at the same time.  As requests complete, others can be scheduled,
49    * as long as this limit is not exceeded.
50    *
51    * Note: the maximum number of allowed concurrent requests is controlled
52    * by the fs.aio-max-nr sysctl, the default value is usually 64K.
53    *
54    * If pollMode is POLLABLE, pollFd() will return a file descriptor that
55    * can be passed to poll / epoll / select and will become readable when
56    * any IOs on this AsyncIO have completed.  If you do this, you must use
57    * pollCompleted() instead of wait() -- do not read from the pollFd()
58    * file descriptor directly.
59    */
60   explicit AsyncIO(size_t capacity, PollMode pollMode=NOT_POLLABLE);
61   ~AsyncIO();
62
63   /**
64    * An Op represents a pending operation.  You may inherit from Op (and
65    * override onCompleted) in order to be notified of completion (see
66    * CallbackOp below for an example), or you may use Op's methods directly.
67    *
68    * The Op must remain allocated until completion.
69    */
70   class Op : private boost::noncopyable {
71     friend class AsyncIO;
72    public:
73     Op();
74     virtual ~Op();
75
76     // There would be a cancel() method here if Linux AIO actually implemented
77     // it.  But let's not get your hopes up.
78
79     enum State {
80       UNINITIALIZED,
81       PENDING,
82       COMPLETED
83     };
84
85     /**
86      * Return the current operation state.
87      */
88     State state() const { return state_; }
89
90     /**
91      * Reset the operation for reuse.  It is an error to call reset() on
92      * an Op that is still pending.
93      */
94     void reset();
95
96     /**
97      * Retrieve the result of this operation.  Returns >=0 on success,
98      * -errno on failure (that is, using the Linux kernel error reporting
99      * conventions).  Use checkKernelError (folly/Exception.h) on the result to
100      * throw a std::system_error in case of error instead.
101      *
102      * It is an error to call this if the Op hasn't yet started or is still
103      * pending.
104      */
105     ssize_t result() const;
106
107    private:
108     void start();
109     void complete(ssize_t result);
110
111     virtual void onCompleted();
112
113     State state_;
114     ssize_t result_;
115   };
116
117   /**
118    * Initiate a read request.
119    */
120   void pread(Op* op, int fd, void* buf, size_t size, off_t start);
121   void pread(Op* op, int fd, Range<unsigned char*> range, off_t start);
122   void preadv(Op* op, int fd, const iovec* iov, int iovcnt, off_t start);
123
124   /**
125    * Initiate a write request.
126    */
127   void pwrite(Op* op, int fd, const void* buf, size_t size, off_t start);
128   void pwrite(Op* op, int fd, Range<const unsigned char*> range, off_t start);
129   void pwritev(Op* op, int fd, const iovec* iov, int iovcnt, off_t start);
130
131   /**
132    * Wait for at least minRequests to complete.  Returns the requests that
133    * have completed; the returned range is valid until the next call to
134    * wait().  minRequests may be 0 to not block.
135    */
136   Range<Op**> wait(size_t minRequests);
137
138   /**
139    * Return the number of pending requests.
140    */
141   size_t pending() const { return pending_; }
142
143   /**
144    * Return the maximum number of requests that can be kept outstanding
145    * at any one time.
146    */
147   size_t capacity() const { return capacity_; }
148
149   /**
150    * If POLLABLE, return a file descriptor that can be passed to poll / epoll
151    * and will become readable when any async IO operations have completed.
152    * If NOT_POLLABLE, return -1.
153    */
154   int pollFd() const { return pollFd_; }
155
156   /**
157    * If POLLABLE, call instead of wait after the file descriptor returned
158    * by pollFd() became readable.  The returned range is valid until the next
159    * call to pollCompleted().
160    */
161   Range<Op**> pollCompleted();
162
163  private:
164   void initializeContext();
165   void submit(Op* op, iocb* cb);
166   Range<Op**> doWait(size_t minRequests, size_t maxRequests);
167
168   io_context_t ctx_;
169   size_t pending_;
170   const size_t capacity_;
171   int pollFd_;
172   std::vector<Op*> completed_;
173 };
174
175 /**
176  * Implementation of AsyncIO::Op that calls a callback and then deletes
177  * itself.
178  */
179 class CallbackOp : public AsyncIO::Op {
180  public:
181   typedef std::function<void(ssize_t)> Callback;
182   static CallbackOp* make(Callback&& callback);
183
184  private:
185   explicit CallbackOp(Callback&& callback);
186   ~CallbackOp();
187   void onCompleted() FOLLY_OVERRIDE;
188
189   Callback callback_;
190 };
191
192 }  // namespace folly
193
194 #endif /* FOLLY_IO_ASYNCIO_H_ */
195