/*
- * Copyright 2015 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 <folly/Portability.h>
#include <folly/Range.h>
+#include <folly/portability/SysUio.h>
namespace folly {
* An AsyncIOOp represents a pending operation. You may set a notification
* callback or you may use this class's methods directly.
*
- * The op must remain allocated until completion.
+ * The op must remain allocated until it is completed or canceled.
*/
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;
explicit AsyncIOOp(NotificationCallback cb = NotificationCallback());
~AsyncIOOp();
- // There would be a cancel() method here if Linux AIO actually implemented
- // it. But let's not get your hopes up.
-
enum class State {
UNINITIALIZED,
INITIALIZED,
PENDING,
- COMPLETED
+ COMPLETED,
+ CANCELED,
};
/**
* conventions). Use checkKernelError (folly/Exception.h) on the result to
* throw a std::system_error in case of error instead.
*
- * It is an error to call this if the Op hasn't yet started or is still
- * pending.
+ * It is an error to call this if the Op hasn't completed.
*/
ssize_t result() const;
void init();
void start();
void complete(ssize_t result);
+ void cancel();
NotificationCallback cb_;
iocb iocb_;
enum PollMode {
NOT_POLLABLE,
- POLLABLE
+ POLLABLE,
};
/**
* 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
+ * there is only one concurrent caller of wait() / pollCompleted() / cancel()
+ * (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);
+ explicit AsyncIO(size_t capacity, PollMode pollMode = NOT_POLLABLE);
~AsyncIO();
/**
*/
Range<Op**> wait(size_t minRequests);
+ /**
+ * Cancel all pending requests and return them; the returned range is
+ * valid until the next call to cancel().
+ */
+ Range<Op**> cancel();
+
/**
* Return the number of pending requests.
*/
void decrementPending();
void initializeContext();
- Range<Op**> doWait(size_t minRequests, size_t maxRequests);
+ enum class WaitType { COMPLETE, CANCEL };
+ Range<AsyncIO::Op**> doWait(
+ WaitType type,
+ size_t minRequests,
+ size_t maxRequests,
+ std::vector<Op*>& result);
- io_context_t ctx_;
- std::atomic<bool> ctxSet_;
+ io_context_t ctx_{nullptr};
+ std::atomic<bool> ctxSet_{false};
std::mutex initMutex_;
- std::atomic<size_t> pending_;
- std::atomic<size_t> submitted_;
+ std::atomic<size_t> pending_{0};
+ std::atomic<size_t> submitted_{0};
const size_t capacity_;
- int pollFd_;
+ int pollFd_{-1};
std::vector<Op*> completed_;
+ std::vector<Op*> canceled_;
};
/**
};
} // namespace folly
-
-#endif /* FOLLY_IO_ASYNCIO_H_ */