You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

57 lines
2.1 KiB

//! Sync errors
#pragma once
#include <stop_token>
#include <stdexcept>
namespace fx::error {
/// Thrown when an operation is aborted via a stop signal.
///
/// The state may be inconsistent after the thrown exception.
struct OperationCancelledError : virtual std::runtime_error {
OperationCancelledError() noexcept;
OperationCancelledError(OperationCancelledError const&) noexcept = default;
OperationCancelledError& operator=(OperationCancelledError const&) noexcept = default;
virtual ~OperationCancelledError();
};
/// Thrown when a task is cancelled via a stop signal.
///
/// The state is **not** left in an inconsistent state after the thrown exception.
struct TaskCancelledError final : OperationCancelledError {
TaskCancelledError() noexcept;
TaskCancelledError(TaskCancelledError const&) noexcept = default;
TaskCancelledError& operator=(TaskCancelledError const&) noexcept = default;
virtual ~TaskCancelledError();
};
// Throw an `OperationCancelledError` (or, optionally, a `TaskCancelledError` if there is a completed task that was cancelled instead of an operation being aborted.)
[[gnu::noinline, gnu::cold, noreturn]]
void throw_cancelled(bool clean = false);
[[gnu::gnu_inline]]
extern inline
void throw_if_cancelled(std::stop_token const& st, bool clean = false) {
if(not st.stop_requested()) return;
else
throw_cancelled(clean);
}
namespace details [[gnu::visibility("internal")]] {
// NOTE: This assumes the existence of `extern "C" void ::throw_last_system_error()` which throws the current `errno` as a generic-categoried `std::system_error`. If that does not exist, it is re-implemented below. (XXX: There is no reason for this now? We have an impl to call... Ffs...) //
static void throw_last_system_error() __attribute__((cold, noreturn, weakref("throw_last_system_error")));
}
[[gnu::gnu_inline, gnu::cold, noreturn]]
extern inline
void throw_last_system_error()
{
if(__builtin_expect(details::throw_last_system_error != nullptr, true))
details::throw_last_system_error();
else (&throw_last_system_error)();
__builtin_unreachable();
}
}