/*
- * Copyright 2013 Facebook, Inc.
+ * Copyright 2017 Facebook, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* limitations under the License.
*/
-#ifndef FOLLY_IO_ASYNCIO_H_
-#define FOLLY_IO_ASYNCIO_H_
+#pragma once
#include <sys/types.h>
-#include <sys/uio.h>
#include <libaio.h>
+#include <atomic>
#include <cstdint>
#include <deque>
#include <functional>
+#include <iosfwd>
+#include <mutex>
#include <utility>
#include <vector>
#include <boost/noncopyable.hpp>
-#include "folly/Portability.h"
-#include "folly/Range.h"
+#include <folly/Portability.h>
+#include <folly/Range.h>
+#include <folly/portability/SysUio.h>
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;
// 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,
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.
*/
* 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();
*/
size_t capacity() const { return capacity_; }
+ /**
+ * Return the accumulative number of submitted I/O, since this object
+ * has been created.
+ */
+ size_t totalSubmits() const { return submitted_; }
+
/**
* If POLLABLE, return a file descriptor that can be passed to poll / epoll
* and will become readable when any async IO operations have completed.
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_;
+ std::atomic<bool> ctxSet_;
+ std::mutex initMutex_;
+
+ std::atomic<size_t> pending_;
+ std::atomic<size_t> submitted_;
const size_t capacity_;
int pollFd_;
std::vector<Op*> completed_;
*/
typedef std::function<AsyncIOOp*()> OpFactory;
void submit(OpFactory op);
+
private:
void onCompleted(AsyncIOOp* op);
void maybeDequeue();
};
} // namespace folly
-
-#endif /* FOLLY_IO_ASYNCIO_H_ */
-