make folly build on OSX
[folly.git] / folly / experimental / io / AsyncIO.h
index 3c84ebb0c4f2be331669ffb88b379fdfb8fbbfc3..83c37f167ae2838905762b70fa0f78371d96ac02 100644 (file)
 #include <sys/uio.h>
 #include <libaio.h>
 
+#include <atomic>
 #include <cstdint>
 #include <deque>
 #include <functional>
+#include <mutex>
+#include <ostream>
 #include <utility>
 #include <vector>
 
@@ -42,6 +45,7 @@ namespace folly {
  */
 class AsyncIOOp : private boost::noncopyable {
   friend class AsyncIO;
+  friend std::ostream& operator<<(std::ostream& stream, const AsyncIOOp& o);
  public:
   typedef std::function<void(AsyncIOOp*)> NotificationCallback;
 
@@ -51,7 +55,7 @@ class AsyncIOOp : private boost::noncopyable {
   // There would be a cancel() method here if Linux AIO actually implemented
   // it.  But let's not get your hopes up.
 
-  enum State {
+  enum class State {
     UNINITIALIZED,
     INITIALIZED,
     PENDING,
@@ -108,6 +112,9 @@ class AsyncIOOp : private boost::noncopyable {
   ssize_t result_;
 };
 
+std::ostream& operator<<(std::ostream& stream, const AsyncIOOp& o);
+std::ostream& operator<<(std::ostream& stream, AsyncIOOp::State state);
+
 /**
  * C++ interface around Linux Async IO.
  */
@@ -133,6 +140,12 @@ class AsyncIO : private boost::noncopyable {
    * any IOs on this AsyncIO have completed.  If you do this, you must use
    * pollCompleted() instead of wait() -- do not read from the pollFd()
    * file descriptor directly.
+   *
+   * You may use the same AsyncIO object from multiple threads, as long as
+   * there is only one concurrent caller of wait() / pollCompleted() (perhaps
+   * by always calling it from the same thread, or by providing appropriate
+   * mutual exclusion)  In this case, pending() returns a snapshot
+   * of the current number of pending requests.
    */
   explicit AsyncIO(size_t capacity, PollMode pollMode=NOT_POLLABLE);
   ~AsyncIO();
@@ -175,12 +188,17 @@ class AsyncIO : private boost::noncopyable {
   void submit(Op* op);
 
  private:
+  void decrementPending();
   void initializeContext();
+
   Range<Op**> doWait(size_t minRequests, size_t maxRequests);
 
   io_context_t ctx_;
-  size_t pending_;
-  const size_t capacity_;
+  std::atomic<bool> ctxSet_;
+  std::mutex initMutex_;
+
+  std::atomic<ssize_t> pending_;
+  const ssize_t capacity_;
   int pollFd_;
   std::vector<Op*> completed_;
 };