Added support for completely disabling noexcept using MIJIN_TEST_NO_NOEXCEPT (for testing).

This commit is contained in:
2024-08-29 00:01:23 +02:00
parent a43f92fb58
commit 9ba097fc2f
41 changed files with 643 additions and 564 deletions

View File

@@ -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());