Added support for completely disabling noexcept using MIJIN_TEST_NO_NOEXCEPT (for testing).
This commit is contained in:
@@ -19,6 +19,7 @@
|
||||
#include "./future.hpp"
|
||||
#include "./message_queue.hpp"
|
||||
#include "../container/optional.hpp"
|
||||
#include "../internal/common.hpp"
|
||||
#include "../util/flag.hpp"
|
||||
#include "../util/iterators.hpp"
|
||||
#include "../util/traits.hpp"
|
||||
@@ -68,28 +69,28 @@ private:
|
||||
std::weak_ptr<struct TaskSharedState> state_;
|
||||
public:
|
||||
TaskHandle() = default;
|
||||
explicit TaskHandle(std::weak_ptr<TaskSharedState> state) noexcept : state_(std::move(state)) {}
|
||||
explicit TaskHandle(std::weak_ptr<TaskSharedState> state) MIJIN_NOEXCEPT : state_(std::move(state)) {}
|
||||
TaskHandle(const TaskHandle&) = default;
|
||||
TaskHandle(TaskHandle&&) = default;
|
||||
|
||||
TaskHandle& operator=(const TaskHandle&) = default;
|
||||
TaskHandle& operator=(TaskHandle&&) = default;
|
||||
|
||||
bool operator==(const TaskHandle& other) const noexcept {
|
||||
bool operator==(const TaskHandle& other) const MIJIN_NOEXCEPT {
|
||||
return !state_.owner_before(other.state_) && !other.state_.owner_before(state_);
|
||||
}
|
||||
bool operator!=(const TaskHandle& other) const noexcept {
|
||||
bool operator!=(const TaskHandle& other) const MIJIN_NOEXCEPT {
|
||||
return !(*this == other);
|
||||
}
|
||||
|
||||
[[nodiscard]] bool isValid() const noexcept
|
||||
[[nodiscard]] bool isValid() const MIJIN_NOEXCEPT
|
||||
{
|
||||
return !state_.expired();
|
||||
}
|
||||
|
||||
inline void cancel() const noexcept;
|
||||
inline void cancel() const MIJIN_NOEXCEPT;
|
||||
#if MIJIN_COROUTINE_ENABLE_DEBUG_INFO
|
||||
inline Optional<Stacktrace> getCreationStack() const noexcept;
|
||||
inline Optional<Stacktrace> getCreationStack() const MIJIN_NOEXCEPT;
|
||||
#endif
|
||||
};
|
||||
struct TaskSharedState
|
||||
@@ -110,11 +111,11 @@ struct TaskState
|
||||
|
||||
TaskState() = default;
|
||||
TaskState(const TaskState&) = default;
|
||||
TaskState(TaskState&&) noexcept = default;
|
||||
inline TaskState(T _value, TaskStatus _status) noexcept : value(std::move(_value)), status(_status) {}
|
||||
inline TaskState(std::exception_ptr _exception) noexcept : exception(std::move(_exception)), status(TaskStatus::FINISHED) {}
|
||||
TaskState(TaskState&&) MIJIN_NOEXCEPT = default;
|
||||
inline TaskState(T _value, TaskStatus _status) MIJIN_NOEXCEPT : value(std::move(_value)), status(_status) {}
|
||||
inline TaskState(std::exception_ptr _exception) MIJIN_NOEXCEPT : exception(std::move(_exception)), status(TaskStatus::FINISHED) {}
|
||||
TaskState& operator=(const TaskState&) = default;
|
||||
TaskState& operator=(TaskState&&) noexcept = default;
|
||||
TaskState& operator=(TaskState&&) MIJIN_NOEXCEPT = default;
|
||||
};
|
||||
|
||||
template<>
|
||||
@@ -125,11 +126,11 @@ struct TaskState<void>
|
||||
|
||||
TaskState() = default;
|
||||
TaskState(const TaskState&) = default;
|
||||
TaskState(TaskState&&) noexcept = default;
|
||||
inline TaskState(TaskStatus _status) noexcept : status(_status) {}
|
||||
inline TaskState(std::exception_ptr _exception) noexcept : exception(std::move(_exception)), status(TaskStatus::FINISHED) {}
|
||||
TaskState(TaskState&&) MIJIN_NOEXCEPT = default;
|
||||
inline TaskState(TaskStatus _status) MIJIN_NOEXCEPT : status(_status) {}
|
||||
inline TaskState(std::exception_ptr _exception) MIJIN_NOEXCEPT : exception(std::move(_exception)), status(TaskStatus::FINISHED) {}
|
||||
TaskState& operator=(const TaskState&) = default;
|
||||
TaskState& operator=(TaskState&&) noexcept = default;
|
||||
TaskState& operator=(TaskState&&) MIJIN_NOEXCEPT = default;
|
||||
};
|
||||
|
||||
namespace impl
|
||||
@@ -138,15 +139,15 @@ template<typename TReturn, typename TPromise>
|
||||
struct TaskReturn
|
||||
{
|
||||
template<typename... TArgs>
|
||||
constexpr void return_value(TArgs&&... args) noexcept {
|
||||
constexpr void return_value(TArgs&&... args) MIJIN_NOEXCEPT {
|
||||
(static_cast<TPromise&>(*this).state_) = TaskState<TReturn>(TReturn(std::forward<TArgs>(args)...), TaskStatus::FINISHED);
|
||||
}
|
||||
|
||||
constexpr void return_value(TReturn value) noexcept {
|
||||
constexpr void return_value(TReturn value) MIJIN_NOEXCEPT {
|
||||
(static_cast<TPromise&>(*this).state_) = TaskState<TReturn>(TReturn(std::move(value)), TaskStatus::FINISHED);
|
||||
}
|
||||
|
||||
constexpr void unhandled_exception() noexcept {
|
||||
constexpr void unhandled_exception() MIJIN_NOEXCEPT {
|
||||
(static_cast<TPromise&>(*this).state_) = TaskState<TReturn>(std::current_exception());
|
||||
}
|
||||
};
|
||||
@@ -154,11 +155,11 @@ struct TaskReturn
|
||||
template<typename TPromise>
|
||||
struct TaskReturn<void, TPromise>
|
||||
{
|
||||
constexpr void return_void() noexcept {
|
||||
constexpr void return_void() MIJIN_NOEXCEPT {
|
||||
static_cast<TPromise&>(*this).state_.status = TaskStatus::FINISHED;
|
||||
}
|
||||
|
||||
constexpr void unhandled_exception() noexcept {
|
||||
constexpr void unhandled_exception() MIJIN_NOEXCEPT {
|
||||
(static_cast<TPromise&>(*this).state_) = TaskState<void>(std::current_exception());
|
||||
}
|
||||
};
|
||||
@@ -169,8 +170,8 @@ struct TaskAwaitableFuture
|
||||
{
|
||||
FuturePtr<TValue> future;
|
||||
|
||||
[[nodiscard]] constexpr bool await_ready() const noexcept { return future->ready(); }
|
||||
constexpr void await_suspend(std::coroutine_handle<>) const noexcept {}
|
||||
[[nodiscard]] constexpr bool await_ready() const MIJIN_NOEXCEPT { return future->ready(); }
|
||||
constexpr void await_suspend(std::coroutine_handle<>) const MIJIN_NOEXCEPT {}
|
||||
constexpr TValue await_resume() const
|
||||
{
|
||||
impl::throwIfCancelled();
|
||||
@@ -188,8 +189,8 @@ struct TaskAwaitableSignal
|
||||
{
|
||||
std::shared_ptr<std::tuple<TArgs...>> data;
|
||||
|
||||
[[nodiscard]] constexpr bool await_ready() const noexcept { return false; }
|
||||
constexpr void await_suspend(std::coroutine_handle<>) const noexcept {}
|
||||
[[nodiscard]] constexpr bool await_ready() const MIJIN_NOEXCEPT { return false; }
|
||||
constexpr void await_suspend(std::coroutine_handle<>) const MIJIN_NOEXCEPT {}
|
||||
inline auto& await_resume() const
|
||||
{
|
||||
impl::throwIfCancelled();
|
||||
@@ -202,8 +203,8 @@ struct TaskAwaitableSignal<TSingleArg>
|
||||
{
|
||||
std::shared_ptr<TSingleArg> data;
|
||||
|
||||
[[nodiscard]] constexpr bool await_ready() const noexcept { return false; }
|
||||
constexpr void await_suspend(std::coroutine_handle<>) const noexcept {}
|
||||
[[nodiscard]] constexpr bool await_ready() const MIJIN_NOEXCEPT { return false; }
|
||||
constexpr void await_suspend(std::coroutine_handle<>) const MIJIN_NOEXCEPT {}
|
||||
constexpr auto& await_resume() const
|
||||
{
|
||||
impl::throwIfCancelled();
|
||||
@@ -214,8 +215,8 @@ struct TaskAwaitableSignal<TSingleArg>
|
||||
template<>
|
||||
struct TaskAwaitableSignal<>
|
||||
{
|
||||
[[nodiscard]] constexpr bool await_ready() const noexcept { return false; }
|
||||
constexpr void await_suspend(std::coroutine_handle<>) const noexcept {}
|
||||
[[nodiscard]] constexpr bool await_ready() const MIJIN_NOEXCEPT { return false; }
|
||||
constexpr void await_suspend(std::coroutine_handle<>) const MIJIN_NOEXCEPT {}
|
||||
inline void await_resume() const {
|
||||
impl::throwIfCancelled();
|
||||
}
|
||||
@@ -223,8 +224,8 @@ struct TaskAwaitableSignal<>
|
||||
|
||||
struct TaskAwaitableSuspend
|
||||
{
|
||||
[[nodiscard]] constexpr bool await_ready() const noexcept { return false; }
|
||||
constexpr void await_suspend(std::coroutine_handle<>) const noexcept {}
|
||||
[[nodiscard]] constexpr bool await_ready() const MIJIN_NOEXCEPT { return false; }
|
||||
constexpr void await_suspend(std::coroutine_handle<>) const MIJIN_NOEXCEPT {}
|
||||
inline void await_resume() const {
|
||||
impl::throwIfCancelled();
|
||||
}
|
||||
@@ -241,22 +242,22 @@ struct TaskPromise : impl::TaskReturn<typename TTraits::result_t, TaskPromise<TT
|
||||
std::shared_ptr<TaskSharedState> sharedState_ = std::make_shared<TaskSharedState>();
|
||||
TaskLoop* loop_ = nullptr;
|
||||
|
||||
constexpr task_t get_return_object() noexcept { return task_t(handle_t::from_promise(*this)); }
|
||||
constexpr TaskAwaitableSuspend initial_suspend() noexcept { return {}; }
|
||||
constexpr std::suspend_always final_suspend() noexcept { return {}; }
|
||||
constexpr task_t get_return_object() MIJIN_NOEXCEPT { return task_t(handle_t::from_promise(*this)); }
|
||||
constexpr TaskAwaitableSuspend initial_suspend() MIJIN_NOEXCEPT { return {}; }
|
||||
constexpr std::suspend_always final_suspend() noexcept { return {}; } // note: this must always be noexcept, no matter what
|
||||
|
||||
// template<typename TValue>
|
||||
// constexpr std::suspend_always yield_value(TValue value) noexcept {
|
||||
// constexpr std::suspend_always yield_value(TValue value) MIJIN_NOEXCEPT {
|
||||
// *state_ = TaskState<result_t>(std::move(value), TaskStatus::YIELDED);
|
||||
// return {};
|
||||
// }
|
||||
|
||||
// TODO: implement yielding (can't use futures for this)
|
||||
|
||||
// constexpr void unhandled_exception() noexcept {}
|
||||
// constexpr void unhandled_exception() MIJIN_NOEXCEPT {}
|
||||
|
||||
template<typename TValue>
|
||||
auto await_transform(FuturePtr<TValue> future) noexcept
|
||||
auto await_transform(FuturePtr<TValue> future) MIJIN_NOEXCEPT
|
||||
{
|
||||
MIJIN_ASSERT(loop_ != nullptr, "Cannot await future outside of a loop!");
|
||||
TaskAwaitableFuture<TValue> awaitable{future};
|
||||
@@ -272,7 +273,7 @@ struct TaskPromise : impl::TaskReturn<typename TTraits::result_t, TaskPromise<TT
|
||||
}
|
||||
|
||||
template<typename TResultOther>
|
||||
auto await_transform(TaskBase<TResultOther> task) noexcept
|
||||
auto await_transform(TaskBase<TResultOther> task) MIJIN_NOEXCEPT
|
||||
{
|
||||
MIJIN_ASSERT(loop_ != nullptr, "Cannot await another task outside of a loop!"); // NOLINT(clang-analyzer-core.UndefinedBinaryOperatorResult)
|
||||
auto future = delayEvaluation<TResultOther>(loop_)->addTask(std::move(task), &sharedState_->subTask); // hackidyhack: delay evaluation of the type of loop_ as it is only forward-declared here
|
||||
@@ -280,7 +281,7 @@ struct TaskPromise : impl::TaskReturn<typename TTraits::result_t, TaskPromise<TT
|
||||
}
|
||||
|
||||
template<typename TFirstArg, typename TSecondArg, typename... TArgs>
|
||||
auto await_transform(Signal<TFirstArg, TSecondArg, TArgs...>& signal) noexcept
|
||||
auto await_transform(Signal<TFirstArg, TSecondArg, TArgs...>& signal) MIJIN_NOEXCEPT
|
||||
{
|
||||
auto data = std::make_shared<std::tuple<TFirstArg, TSecondArg, TArgs...>>();
|
||||
signal.connect([this, data](TFirstArg arg0, TSecondArg arg1, TArgs... args) mutable
|
||||
@@ -294,7 +295,7 @@ struct TaskPromise : impl::TaskReturn<typename TTraits::result_t, TaskPromise<TT
|
||||
}
|
||||
|
||||
template<typename TFirstArg>
|
||||
auto await_transform(Signal<TFirstArg>& signal) noexcept
|
||||
auto await_transform(Signal<TFirstArg>& signal) MIJIN_NOEXCEPT
|
||||
{
|
||||
auto data = std::make_shared<TFirstArg>();
|
||||
signal.connect([this, data](TFirstArg arg0) mutable
|
||||
@@ -307,7 +308,7 @@ struct TaskPromise : impl::TaskReturn<typename TTraits::result_t, TaskPromise<TT
|
||||
return awaitable;
|
||||
}
|
||||
|
||||
auto await_transform(Signal<>& signal) noexcept
|
||||
auto await_transform(Signal<>& signal) MIJIN_NOEXCEPT
|
||||
{
|
||||
signal.connect([this]()
|
||||
{
|
||||
@@ -318,17 +319,17 @@ struct TaskPromise : impl::TaskReturn<typename TTraits::result_t, TaskPromise<TT
|
||||
return awaitable;
|
||||
}
|
||||
|
||||
std::suspend_always await_transform(std::suspend_always) noexcept
|
||||
std::suspend_always await_transform(std::suspend_always) MIJIN_NOEXCEPT
|
||||
{
|
||||
state_.status = TaskStatus::SUSPENDED;
|
||||
return std::suspend_always();
|
||||
}
|
||||
|
||||
std::suspend_never await_transform(std::suspend_never) noexcept {
|
||||
std::suspend_never await_transform(std::suspend_never) MIJIN_NOEXCEPT {
|
||||
return std::suspend_never();
|
||||
}
|
||||
|
||||
TaskAwaitableSuspend await_transform(TaskAwaitableSuspend) noexcept
|
||||
TaskAwaitableSuspend await_transform(TaskAwaitableSuspend) MIJIN_NOEXCEPT
|
||||
{
|
||||
state_.status = TaskStatus::SUSPENDED;
|
||||
return TaskAwaitableSuspend();
|
||||
@@ -352,7 +353,7 @@ public:
|
||||
private:
|
||||
handle_t handle_;
|
||||
public:
|
||||
constexpr explicit TaskBase(handle_t handle) noexcept : handle_(handle) {
|
||||
constexpr explicit TaskBase(handle_t handle) MIJIN_NOEXCEPT : handle_(handle) {
|
||||
#if MIJIN_COROUTINE_ENABLE_DEBUG_INFO
|
||||
if (Result<Stacktrace> stacktrace = captureStacktrace(2); stacktrace.isSuccess())
|
||||
{
|
||||
@@ -361,12 +362,12 @@ public:
|
||||
#endif
|
||||
}
|
||||
TaskBase(const TaskBase&) = delete;
|
||||
TaskBase(TaskBase&& other) noexcept : handle_(std::exchange(other.handle_, nullptr))
|
||||
TaskBase(TaskBase&& other) MIJIN_NOEXCEPT : handle_(std::exchange(other.handle_, nullptr))
|
||||
{}
|
||||
~TaskBase() noexcept;
|
||||
~TaskBase() MIJIN_NOEXCEPT;
|
||||
public:
|
||||
TaskBase& operator=(const TaskBase&) = delete;
|
||||
TaskBase& operator=(TaskBase&& other) noexcept
|
||||
TaskBase& operator=(TaskBase&& other) MIJIN_NOEXCEPT
|
||||
{
|
||||
if (handle_) {
|
||||
handle_.destroy();
|
||||
@@ -376,13 +377,13 @@ public:
|
||||
}
|
||||
|
||||
[[nodiscard]]
|
||||
constexpr bool operator==(const TaskBase& other) const noexcept { return handle_ == other.handle_; }
|
||||
constexpr bool operator==(const TaskBase& other) const MIJIN_NOEXCEPT { return handle_ == other.handle_; }
|
||||
|
||||
[[nodiscard]]
|
||||
constexpr bool operator!=(const TaskBase& other) const noexcept { return handle_ != other.handle_; }
|
||||
constexpr bool operator!=(const TaskBase& other) const MIJIN_NOEXCEPT { return handle_ != other.handle_; }
|
||||
public:
|
||||
[[nodiscard]]
|
||||
constexpr TaskState<TResult>& state() noexcept
|
||||
constexpr TaskState<TResult>& state() MIJIN_NOEXCEPT
|
||||
{
|
||||
return handle_.promise().state_;
|
||||
}
|
||||
@@ -392,19 +393,19 @@ public:
|
||||
handle_.resume();
|
||||
return state();
|
||||
}
|
||||
constexpr std::shared_ptr<TaskSharedState>& sharedState() noexcept
|
||||
constexpr std::shared_ptr<TaskSharedState>& sharedState() MIJIN_NOEXCEPT
|
||||
{
|
||||
return handle_.promise().sharedState_;
|
||||
}
|
||||
private:
|
||||
[[nodiscard]]
|
||||
constexpr handle_t handle() const noexcept { return handle_; }
|
||||
constexpr handle_t handle() const MIJIN_NOEXCEPT { return handle_; }
|
||||
[[nodiscard]]
|
||||
constexpr TaskLoop* getLoop() noexcept
|
||||
constexpr TaskLoop* getLoop() MIJIN_NOEXCEPT
|
||||
{
|
||||
return handle_.promise().loop_;
|
||||
}
|
||||
constexpr void setLoop(TaskLoop* loop) noexcept
|
||||
constexpr void setLoop(TaskLoop* loop) MIJIN_NOEXCEPT
|
||||
{
|
||||
// MIJIN_ASSERT(handle_.promise().loop_ == nullptr
|
||||
// || handle_.promise().loop_ == loop
|
||||
@@ -423,14 +424,14 @@ class WrappedTaskBase
|
||||
public:
|
||||
virtual ~WrappedTaskBase() = default;
|
||||
public:
|
||||
virtual TaskStatus status() noexcept = 0;
|
||||
virtual std::exception_ptr exception() noexcept = 0;
|
||||
// virtual std::any result() noexcept = 0;
|
||||
virtual TaskStatus status() MIJIN_NOEXCEPT = 0;
|
||||
virtual std::exception_ptr exception() MIJIN_NOEXCEPT = 0;
|
||||
// virtual std::any result() MIJIN_NOEXCEPT = 0;
|
||||
virtual void resume() = 0;
|
||||
virtual void* raw() noexcept = 0;
|
||||
virtual std::coroutine_handle<> handle() noexcept = 0;
|
||||
virtual void setLoop(TaskLoop* loop) noexcept = 0;
|
||||
virtual std::shared_ptr<TaskSharedState>& sharedState() noexcept = 0;
|
||||
virtual void* raw() MIJIN_NOEXCEPT = 0;
|
||||
virtual std::coroutine_handle<> handle() MIJIN_NOEXCEPT = 0;
|
||||
virtual void setLoop(TaskLoop* loop) MIJIN_NOEXCEPT = 0;
|
||||
virtual std::shared_ptr<TaskSharedState>& sharedState() MIJIN_NOEXCEPT = 0;
|
||||
|
||||
[[nodiscard]] inline bool canResume() {
|
||||
const TaskStatus stat = status();
|
||||
@@ -444,16 +445,16 @@ class WrappedTask : public WrappedTaskBase
|
||||
private:
|
||||
TTask task_;
|
||||
public:
|
||||
constexpr explicit WrappedTask(TTask&& task) noexcept : task_(std::move(task)) {}
|
||||
constexpr explicit WrappedTask(TTask&& task) MIJIN_NOEXCEPT : task_(std::move(task)) {}
|
||||
WrappedTask(const WrappedTask&) = delete;
|
||||
WrappedTask(WrappedTask&&) noexcept = default;
|
||||
WrappedTask(WrappedTask&&) MIJIN_NOEXCEPT = default;
|
||||
public:
|
||||
WrappedTask& operator=(const WrappedTask&) = delete;
|
||||
WrappedTask& operator=(WrappedTask&&) noexcept = default;
|
||||
WrappedTask& operator=(WrappedTask&&) MIJIN_NOEXCEPT = default;
|
||||
public:
|
||||
TaskStatus status() noexcept override { return task_.state().status; }
|
||||
std::exception_ptr exception() noexcept override { return task_.state().exception; }
|
||||
// std::any result() noexcept override
|
||||
TaskStatus status() MIJIN_NOEXCEPT override { return task_.state().status; }
|
||||
std::exception_ptr exception() MIJIN_NOEXCEPT override { return task_.state().exception; }
|
||||
// std::any result() MIJIN_NOEXCEPT
|
||||
// {
|
||||
// if constexpr (std::is_same_v<typename TTask::result_t, void>) {
|
||||
// return {};
|
||||
@@ -463,14 +464,14 @@ public:
|
||||
// }
|
||||
// }
|
||||
void resume() override { task_.resume(); }
|
||||
void* raw() noexcept override { return &task_; }
|
||||
std::coroutine_handle<> handle() noexcept override { return task_.handle(); }
|
||||
void setLoop(TaskLoop* loop) noexcept override { task_.setLoop(loop); }
|
||||
virtual std::shared_ptr<TaskSharedState>& sharedState() noexcept override { return task_.sharedState(); }
|
||||
void* raw() MIJIN_NOEXCEPT override { return &task_; }
|
||||
std::coroutine_handle<> handle() MIJIN_NOEXCEPT override { return task_.handle(); }
|
||||
void setLoop(TaskLoop* loop) MIJIN_NOEXCEPT override { task_.setLoop(loop); }
|
||||
virtual std::shared_ptr<TaskSharedState>& sharedState() MIJIN_NOEXCEPT override { return task_.sharedState(); }
|
||||
};
|
||||
|
||||
template<typename TTask>
|
||||
std::unique_ptr<WrappedTask<TTask>> wrapTask(TTask&& task) noexcept
|
||||
std::unique_ptr<WrappedTask<TTask>> wrapTask(TTask&& task) MIJIN_NOEXCEPT
|
||||
{
|
||||
return std::make_unique<WrappedTask<TTask>>(std::forward<TTask>(task));
|
||||
}
|
||||
@@ -499,29 +500,29 @@ protected:
|
||||
|
||||
exception_handler_t uncaughtExceptionHandler_;
|
||||
public:
|
||||
TaskLoop() = default;
|
||||
TaskLoop() MIJIN_NOEXCEPT = default;
|
||||
TaskLoop(const TaskLoop&) = delete;
|
||||
TaskLoop(TaskLoop&&) = delete;
|
||||
virtual ~TaskLoop() = default;
|
||||
virtual ~TaskLoop() MIJIN_NOEXCEPT = default;
|
||||
|
||||
TaskLoop& operator=(const TaskLoop&) = delete;
|
||||
TaskLoop& operator=(TaskLoop&&) = delete;
|
||||
|
||||
void setUncaughtExceptionHandler(exception_handler_t handler) noexcept { uncaughtExceptionHandler_ = std::move(handler); }
|
||||
void setUncaughtExceptionHandler(exception_handler_t handler) MIJIN_NOEXCEPT { uncaughtExceptionHandler_ = std::move(handler); }
|
||||
|
||||
template<typename TResult>
|
||||
inline FuturePtr<TResult> addTask(TaskBase<TResult> task, TaskHandle* outHandle = nullptr) noexcept;
|
||||
inline FuturePtr<TResult> addTask(TaskBase<TResult> task, TaskHandle* outHandle = nullptr) MIJIN_NOEXCEPT;
|
||||
|
||||
virtual void transferCurrentTask(TaskLoop& otherLoop) noexcept = 0;
|
||||
virtual void addStoredTask(StoredTask&& storedTask) noexcept = 0;
|
||||
virtual void transferCurrentTask(TaskLoop& otherLoop) MIJIN_NOEXCEPT = 0;
|
||||
virtual void addStoredTask(StoredTask&& storedTask) MIJIN_NOEXCEPT = 0;
|
||||
|
||||
[[nodiscard]] static TaskLoop& current() noexcept;
|
||||
[[nodiscard]] static TaskLoop& current() MIJIN_NOEXCEPT;
|
||||
protected:
|
||||
inline TaskStatus tickTask(StoredTask& task);
|
||||
protected:
|
||||
static inline TaskLoop*& currentLoopStorage() noexcept;
|
||||
static inline TaskLoop*& currentLoopStorage() MIJIN_NOEXCEPT;
|
||||
template<typename TResult>
|
||||
static inline void setFutureHelper(StoredTask& storedTask) noexcept;
|
||||
static inline void setFutureHelper(StoredTask& storedTask) MIJIN_NOEXCEPT;
|
||||
};
|
||||
|
||||
template<typename TResult = void>
|
||||
@@ -537,17 +538,17 @@ private:
|
||||
std::thread::id threadId_;
|
||||
|
||||
public: // TaskLoop implementation
|
||||
void transferCurrentTask(TaskLoop& otherLoop) noexcept override;
|
||||
void addStoredTask(StoredTask&& storedTask) noexcept override;
|
||||
void transferCurrentTask(TaskLoop& otherLoop) MIJIN_NOEXCEPT override;
|
||||
void addStoredTask(StoredTask&& storedTask) MIJIN_NOEXCEPT override;
|
||||
|
||||
public: // public interface
|
||||
[[nodiscard]] constexpr bool empty() const noexcept { return tasks_.empty() && newTasks_.empty(); }
|
||||
[[nodiscard]] constexpr std::size_t getNumTasks() const noexcept { return tasks_.size() + newTasks_.size(); }
|
||||
[[nodiscard]] std::size_t getActiveTasks() const noexcept;
|
||||
[[nodiscard]] constexpr bool empty() const MIJIN_NOEXCEPT { return tasks_.empty() && newTasks_.empty(); }
|
||||
[[nodiscard]] constexpr std::size_t getNumTasks() const MIJIN_NOEXCEPT { return tasks_.size() + newTasks_.size(); }
|
||||
[[nodiscard]] std::size_t getActiveTasks() const MIJIN_NOEXCEPT;
|
||||
inline CanContinue tick();
|
||||
inline void runUntilDone(IgnoreWaiting ignoreWaiting = IgnoreWaiting::NO);
|
||||
inline void cancelAllTasks() noexcept;
|
||||
[[nodiscard]] inline std::vector<TaskHandle> getAllTasks() const noexcept;
|
||||
inline void cancelAllTasks() MIJIN_NOEXCEPT;
|
||||
[[nodiscard]] inline std::vector<TaskHandle> getAllTasks() const MIJIN_NOEXCEPT;
|
||||
private:
|
||||
inline void assertCorrectThread() { MIJIN_ASSERT(threadId_ == std::thread::id() || threadId_ == std::this_thread::get_id(), "Unsafe to TaskLoop from different thread!"); }
|
||||
};
|
||||
@@ -563,8 +564,8 @@ private:
|
||||
std::vector<std::jthread> workerThreads_;
|
||||
|
||||
public: // TaskLoop implementation
|
||||
void transferCurrentTask(TaskLoop& otherLoop) noexcept override;
|
||||
void addStoredTask(StoredTask&& storedTask) noexcept override;
|
||||
void transferCurrentTask(TaskLoop& otherLoop) MIJIN_NOEXCEPT override;
|
||||
void addStoredTask(StoredTask&& storedTask) MIJIN_NOEXCEPT override;
|
||||
|
||||
public: // public interface
|
||||
void start(std::size_t numWorkerThreads);
|
||||
@@ -591,7 +592,7 @@ inline void throwIfCancelled()
|
||||
}
|
||||
}
|
||||
|
||||
void TaskHandle::cancel() const noexcept
|
||||
void TaskHandle::cancel() const MIJIN_NOEXCEPT
|
||||
{
|
||||
if (std::shared_ptr<TaskSharedState> state = state_.lock())
|
||||
{
|
||||
@@ -601,7 +602,7 @@ void TaskHandle::cancel() const noexcept
|
||||
}
|
||||
|
||||
#if MIJIN_COROUTINE_ENABLE_DEBUG_INFO
|
||||
Optional<Stacktrace> TaskHandle::getCreationStack() const noexcept
|
||||
Optional<Stacktrace> TaskHandle::getCreationStack() const MIJIN_NOEXCEPT
|
||||
{
|
||||
if (std::shared_ptr<TaskSharedState> state = state_.lock())
|
||||
{
|
||||
@@ -612,7 +613,7 @@ Optional<Stacktrace> TaskHandle::getCreationStack() const noexcept
|
||||
#endif // MIJIN_COROUTINE_ENABLE_DEBUG_INFO
|
||||
|
||||
template<typename TResult>
|
||||
TaskBase<TResult>::~TaskBase() noexcept
|
||||
TaskBase<TResult>::~TaskBase() MIJIN_NOEXCEPT
|
||||
{
|
||||
if (handle_)
|
||||
{
|
||||
@@ -621,7 +622,7 @@ TaskBase<TResult>::~TaskBase() noexcept
|
||||
}
|
||||
|
||||
template<typename TResult>
|
||||
inline FuturePtr<TResult> TaskLoop::addTask(TaskBase<TResult> task, TaskHandle* outHandle) noexcept
|
||||
inline FuturePtr<TResult> TaskLoop::addTask(TaskBase<TResult> task, TaskHandle* outHandle) MIJIN_NOEXCEPT
|
||||
{
|
||||
MIJIN_ASSERT(!task.getLoop(), "Attempting to add task that already has a loop!");
|
||||
task.setLoop(this);
|
||||
@@ -685,20 +686,20 @@ inline TaskStatus TaskLoop::tickTask(StoredTask& task)
|
||||
return status;
|
||||
}
|
||||
|
||||
/* static */ inline auto TaskLoop::current() noexcept -> TaskLoop&
|
||||
/* static */ inline auto TaskLoop::current() MIJIN_NOEXCEPT -> TaskLoop&
|
||||
{
|
||||
MIJIN_ASSERT(currentLoopStorage() != nullptr, "Attempting to fetch current loop while no coroutine is running!");
|
||||
return *currentLoopStorage();
|
||||
}
|
||||
|
||||
/* static */ auto TaskLoop::currentLoopStorage() noexcept -> TaskLoop*&
|
||||
/* static */ auto TaskLoop::currentLoopStorage() MIJIN_NOEXCEPT -> TaskLoop*&
|
||||
{
|
||||
static thread_local TaskLoop* storage = nullptr;
|
||||
return storage;
|
||||
}
|
||||
|
||||
template<typename TResult>
|
||||
/* static */ inline void TaskLoop::setFutureHelper(StoredTask& storedTask) noexcept
|
||||
/* static */ inline void TaskLoop::setFutureHelper(StoredTask& storedTask) MIJIN_NOEXCEPT
|
||||
{
|
||||
TaskBase<TResult>& task = *static_cast<TaskBase<TResult>*>(storedTask.task->raw());
|
||||
auto future = std::any_cast<FuturePtr<TResult>>(storedTask.resultData);
|
||||
@@ -801,7 +802,7 @@ inline void SimpleTaskLoop::runUntilDone(IgnoreWaiting ignoreWaiting)
|
||||
}
|
||||
}
|
||||
|
||||
inline void SimpleTaskLoop::cancelAllTasks() noexcept
|
||||
inline void SimpleTaskLoop::cancelAllTasks() MIJIN_NOEXCEPT
|
||||
{
|
||||
for (StoredTask& task : mijin::chain(tasks_, newTasks_))
|
||||
{
|
||||
@@ -814,7 +815,7 @@ inline void SimpleTaskLoop::cancelAllTasks() noexcept
|
||||
}
|
||||
}
|
||||
|
||||
inline std::vector<TaskHandle> SimpleTaskLoop::getAllTasks() const noexcept
|
||||
inline std::vector<TaskHandle> SimpleTaskLoop::getAllTasks() const MIJIN_NOEXCEPT
|
||||
{
|
||||
std::vector<TaskHandle> result;
|
||||
for (const StoredTask& task : mijin::chain(tasks_, newTasks_))
|
||||
@@ -848,7 +849,7 @@ Task<> c_allDone(const TCollection<FuturePtr<TType>, TTemplateArgs...>& futures)
|
||||
} while (!allDone);
|
||||
}
|
||||
|
||||
[[nodiscard]] inline TaskHandle getCurrentTask() noexcept
|
||||
[[nodiscard]] inline TaskHandle getCurrentTask() MIJIN_NOEXCEPT
|
||||
{
|
||||
MIJIN_ASSERT(impl::gCurrentTask != nullptr, "Attempt to call getCurrentTask() outside of task.");
|
||||
return TaskHandle(impl::gCurrentTask->task->sharedState());
|
||||
|
||||
Reference in New Issue
Block a user