Range<AsyncIO::Op**> AsyncIO::doWait(size_t minRequests, size_t maxRequests) { io_event events[pending_]; int count; do { // Wait forever count = io_getevents(ctx_, minRequests, maxRequests, events, nullptr); } while (count == -EINTR); checkKernelError(count, "AsyncIO: io_getevents failed"); DCHECK_GE(count, minRequests); // the man page says so DCHECK_LE(count, pending_); completed_.clear(); if (count == 0) { return folly::Range<Op**>(); } for (size_t i = 0; i < count; ++i) { DCHECK(events[i].obj); Op* op = boost::intrusive::get_parent_from_member( events[i].obj, &AsyncIOOp::iocb_); --pending_; op->complete(events[i].res); completed_.push_back(op); } return folly::Range<Op**>(&completed_.front(), count); }
Range<AsyncIO::Op**> AsyncIO::doWait(size_t minRequests, size_t maxRequests) { io_event events[maxRequests]; size_t count = 0; do { int ret; do { // GOTCHA: io_getevents() may returns less than min_nr results if // interrupted after some events have been read (if before, -EINTR // is returned). ret = io_getevents(ctx_, minRequests - count, maxRequests - count, events + count, /* timeout */ nullptr); // wait forever } while (ret == -EINTR); // Check as may not be able to recover without leaking events. CHECK_GE(ret, 0) << "AsyncIO: io_getevents failed with error " << errnoStr(-ret); count += ret; } while (count < minRequests); DCHECK_LE(count, maxRequests); completed_.clear(); if (count == 0) { return folly::Range<Op**>(); } for (size_t i = 0; i < count; ++i) { DCHECK(events[i].obj); Op* op = boost::intrusive::get_parent_from_member( events[i].obj, &AsyncIOOp::iocb_); decrementPending(); op->complete(events[i].res); completed_.push_back(op); } return folly::Range<Op**>(&completed_.front(), count); }