0
0
Fork 0
mirror of https://github.com/matrix-construct/construct synced 2024-11-12 04:51:08 +01:00

ircd::fs::aio: Use ctx::dock for waiter; minor reorg.

This commit is contained in:
Jason Volk 2019-08-19 20:19:51 -07:00
parent 25f5f28102
commit 6ccbede478
2 changed files with 45 additions and 45 deletions

View file

@ -422,7 +422,6 @@ ircd::fs::aio::request::operator()()
{
assert(system);
assert(ctx::current);
assert(waiter == ctx::current);
const size_t submitted_bytes
{
@ -446,7 +445,7 @@ ircd::fs::aio::request::operator()()
system->submit(*this);
// Wait for completion
while(!system->wait(*this));
while(!wait());
assert(completed());
assert(retval <= ssize_t(submitted_bytes));
@ -491,6 +490,47 @@ ircd::fs::aio::request::operator()()
};
}
/// Block the current context while waiting for results.
///
/// This function returns true when the request completes and it's safe to
/// continue. This function intercepts all exceptions and cancels the request
/// if it's appropriate before rethrowing; after which it is safe to continue.
///
/// If this function returns false it is not safe to continue; it *must* be
/// called again until it no longer returns false.
bool
ircd::fs::aio::request::wait()
try
{
waiter.wait([this]
{
return completed();
});
return true;
}
catch(...)
{
// When the ctx is interrupted we're obliged to cancel the request
// if it has not reached a completed state.
if(completed())
throw;
// The handler callstack is invoked synchronously on this stack for
// requests which are still in our userspace queue.
if(queued())
{
cancel();
throw;
}
// The handler callstack is invoked asynchronously for requests
// submitted to the kernel; we *must* wait for that by blocking
// ctx interrupts and terminations and continue to wait. The caller
// must loop into this call again until it returns true or throws.
return false;
}
bool
ircd::fs::aio::request::queued()
const
@ -669,46 +709,6 @@ ircd::fs::aio::system::wait()
return true;
}
/// Block the current context while waiting for results.
///
/// This function returns true when the request completes and it's safe to
/// continue. This function intercepts all exceptions and cancels the request
/// if it's appropriate before rethrowing; after which it is safe to continue.
///
/// If this function returns false it is not safe to continue; it *must* be
/// called again until it no longer returns false.
bool
ircd::fs::aio::system::wait(request &request)
try
{
assert(ctx::current == request.waiter);
while(!request.completed())
ctx::wait();
return true;
}
catch(...)
{
// When the ctx is interrupted we're obliged to cancel the request
// if it has not reached a completed state.
if(request.completed())
throw;
// The handler callstack is invoked synchronously on this stack for
// requests which are still in our userspace queue.
if(request.queued())
{
request.cancel();
throw;
}
// The handler callstack is invoked asynchronously for requests
// submitted to the kernel; we *must* wait for that by blocking
// ctx interrupts and terminations and continue to wait. The caller
// must loop into this call again until it returns true or throws.
return false;
}
bool
ircd::fs::aio::system::cancel(request &request)
try
@ -1181,8 +1181,7 @@ noexcept try
// Notify the waiting context. Note that we are on the main async stack
// but it is safe to notify from here.
assert(request->waiter);
ctx::notify(*request->waiter);
request->waiter.notify_one();
stats.events++;
}
catch(const std::exception &e)

View file

@ -125,12 +125,13 @@ struct ircd::fs::aio::request
ssize_t retval {-2L};
ssize_t errcode {0L};
const struct opts *opts {nullptr};
ctx::ctx *waiter {ctx::current};
ctx::dock waiter;
public:
const_iovec_view iovec() const;
bool completed() const;
bool queued() const;
bool wait();
size_t operator()();
bool cancel();