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

@@ -135,7 +135,7 @@ void MultiThreadedTaskLoop::workerThread(std::stop_token stopToken, std::size_t
// public functions
//
void SimpleTaskLoop::transferCurrentTask(TaskLoop& otherLoop) noexcept
void SimpleTaskLoop::transferCurrentTask(TaskLoop& otherLoop) MIJIN_NOEXCEPT
{
assertCorrectThread();
@@ -153,7 +153,7 @@ void SimpleTaskLoop::transferCurrentTask(TaskLoop& otherLoop) noexcept
otherLoop.addStoredTask(std::move(storedTask));
}
void SimpleTaskLoop::addStoredTask(StoredTask&& storedTask) noexcept
void SimpleTaskLoop::addStoredTask(StoredTask&& storedTask) MIJIN_NOEXCEPT
{
storedTask.task->setLoop(this);
if (threadId_ == std::thread::id() || threadId_ == std::this_thread::get_id())
@@ -174,7 +174,7 @@ void SimpleTaskLoop::addStoredTask(StoredTask&& storedTask) noexcept
}
}
std::size_t SimpleTaskLoop::getActiveTasks() const noexcept
std::size_t SimpleTaskLoop::getActiveTasks() const MIJIN_NOEXCEPT
{
std::size_t sum = 0;
for (const StoredTask& task : mijin::chain(tasks_, newTasks_))
@@ -188,7 +188,7 @@ std::size_t SimpleTaskLoop::getActiveTasks() const noexcept
return sum;
}
void MultiThreadedTaskLoop::transferCurrentTask(TaskLoop& otherLoop) noexcept
void MultiThreadedTaskLoop::transferCurrentTask(TaskLoop& otherLoop) MIJIN_NOEXCEPT
{
if (&otherLoop == this) {
return;
@@ -204,7 +204,7 @@ void MultiThreadedTaskLoop::transferCurrentTask(TaskLoop& otherLoop) noexcept
otherLoop.addStoredTask(std::move(storedTask));
}
void MultiThreadedTaskLoop::addStoredTask(StoredTask&& storedTask) noexcept
void MultiThreadedTaskLoop::addStoredTask(StoredTask&& storedTask) MIJIN_NOEXCEPT
{
storedTask.task->setLoop(this);

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

View File

@@ -8,8 +8,9 @@
#include <memory>
#include <type_traits>
#include "./signal.hpp"
#include "../debug/assert.hpp"
#include "../container/optional.hpp"
#include "../debug/assert.hpp"
#include "../internal/common.hpp"
namespace mijin
{
@@ -36,8 +37,8 @@ struct FutureStorage
{
Optional<TValue> value;
void setValue(TValue value_) noexcept { value = std::move(value_); }
[[nodiscard]] TValue& getValue() noexcept { return value.get(); }
void setValue(TValue value_) MIJIN_NOEXCEPT { value = std::move(value_); }
[[nodiscard]] TValue& getValue() MIJIN_NOEXCEPT { return value.get(); }
};
@@ -46,8 +47,8 @@ struct FutureStorage
// {
// Optional<TValue*> value;
//
// void setValue(TValue& value_) noexcept { value = &value_; }
// [[nodiscard]] TValue& getValue() const noexcept { return *value.get(); }
// void setValue(TValue& value_) MIJIN_NOEXCEPT { value = &value_; }
// [[nodiscard]] TValue& getValue() const MIJIN_NOEXCEPT { return *value.get(); }
// };
template<>
@@ -65,19 +66,19 @@ private:
public:
Future() = default;
Future(const Future&) = delete;
Future(Future&&) noexcept = default;
Future(Future&&) MIJIN_NOEXCEPT = default;
public:
Future& operator=(const Future&) = delete;
Future& operator=(Future&&) noexcept = default;
Future& operator=(Future&&) MIJIN_NOEXCEPT = default;
[[nodiscard]]
constexpr explicit operator bool() const noexcept { return ready(); }
constexpr explicit operator bool() const MIJIN_NOEXCEPT { return ready(); }
[[nodiscard]]
constexpr bool operator!() const noexcept { return !ready(); }
constexpr bool operator!() const MIJIN_NOEXCEPT { return !ready(); }
public: // access
[[nodiscard]]
constexpr decltype(auto) get() noexcept
constexpr decltype(auto) get() MIJIN_NOEXCEPT
{
MIJIN_ASSERT(isSet_, "Attempting to get from future that is not ready.");
if constexpr(std::is_same_v<TValue, void>) {
@@ -88,7 +89,7 @@ public: // access
}
}
[[nodiscard]]
constexpr decltype(auto) get() const noexcept
constexpr decltype(auto) get() const MIJIN_NOEXCEPT
{
MIJIN_ASSERT(isSet_, "Attempting to get from future that is not ready.");
if constexpr(std::is_same_v<TValue, void>) {
@@ -99,20 +100,20 @@ public: // access
}
}
[[nodiscard]]
constexpr bool ready() const noexcept
constexpr bool ready() const MIJIN_NOEXCEPT
{
return isSet_;
}
public: // modification
template<typename TArg> requires (!std::is_same_v<TValue, void>)
constexpr void set(TArg&& value) noexcept
constexpr void set(TArg&& value) MIJIN_NOEXCEPT
{
MIJIN_ASSERT(!isSet_, "Trying to set a future twice!");
value_.setValue(std::move(value));
isSet_ = true;
sigSet.emit();
}
constexpr void set() noexcept
constexpr void set() MIJIN_NOEXCEPT
{
MIJIN_ASSERT(!isSet_, "Trying to set a future twice!");
isSet_ = true;

View File

@@ -8,6 +8,7 @@
#include <atomic>
#include <optional>
#include <thread>
#include "../internal/common.hpp"
#include "../util/bitarray.hpp"
namespace mijin
@@ -37,7 +38,7 @@ private:
std::optional<value_type> message_;
public:
MessageQueueIterator() = default;
explicit MessageQueueIterator(TMessageQueue& queue) noexcept : queue_(&queue) {
explicit MessageQueueIterator(TMessageQueue& queue) MIJIN_NOEXCEPT : queue_(&queue) {
message_ = queue_->tryPop();
}
MessageQueueIterator(const MessageQueueIterator&) = delete;
@@ -46,26 +47,26 @@ public:
MessageQueueIterator& operator=(const MessageQueueIterator&) = delete;
MessageQueueIterator& operator=(MessageQueueIterator&&) = default;
bool operator==(const MessageQueueIterator& other) noexcept
bool operator==(const MessageQueueIterator& other) MIJIN_NOEXCEPT
{
return message_.has_value() == other.message_.has_value();
}
bool operator!=(const MessageQueueIterator& other) noexcept
bool operator!=(const MessageQueueIterator& other) MIJIN_NOEXCEPT
{
return !(*this == other);
}
reference operator*() noexcept
reference operator*() MIJIN_NOEXCEPT
{
return message_.value();
}
pointer operator->() noexcept
pointer operator->() MIJIN_NOEXCEPT
{
return &message_.value();
}
MessageQueueIterator& operator++() noexcept
MessageQueueIterator& operator++() MIJIN_NOEXCEPT
{
message_ = queue_->tryPop();
return *this;
@@ -86,10 +87,10 @@ private:
public:
MessageQueue() = default;
MessageQueue(const MessageQueue&) = delete;
MessageQueue(MessageQueue&&) noexcept = delete;
MessageQueue(MessageQueue&&) = delete;
MessageQueue& operator=(const MessageQueue&) = delete;
MessageQueue& operator=(MessageQueue&&) noexcept = delete;
MessageQueue& operator=(MessageQueue&&) = delete;
[[nodiscard]] bool tryPushMaybeMove(TMessage& message);
[[nodiscard]] bool tryPush(TMessage message) {
@@ -99,8 +100,8 @@ public:
[[nodiscard]] std::optional<TMessage> tryPop();
[[nodiscard]] TMessage wait();
iterator_t begin() noexcept { return iterator_t(*this); }
iterator_t end() noexcept { return iterator_t(); }
iterator_t begin() MIJIN_NOEXCEPT { return iterator_t(*this); }
iterator_t end() MIJIN_NOEXCEPT { return iterator_t(); }
};
template<typename TRequest, typename TResponse, std::size_t requestBufferSize = 32, std::size_t responseBufferSize = 32>

View File

@@ -10,6 +10,7 @@
#include <memory>
#include <mutex>
#include <vector>
#include "../internal/common.hpp"
#include "../util/flag.hpp"
namespace mijin
@@ -54,17 +55,17 @@ private:
public:
Signal() = default;
Signal(const Signal&) = delete;
Signal(Signal&&) noexcept = default;
Signal(Signal&&) MIJIN_NOEXCEPT = default;
public:
Signal& operator=(const Signal&) = delete;
Signal& operator=(Signal&&) noexcept = default;
Signal& operator=(Signal&&) MIJIN_NOEXCEPT = default;
public:
template<typename THandler, typename TWeak = void>
inline token_t connect(THandler handler, Oneshot oneshot = Oneshot::NO, std::weak_ptr<TWeak> referenced = std::weak_ptr<TWeak>()) noexcept;
inline token_t connect(THandler handler, Oneshot oneshot = Oneshot::NO, std::weak_ptr<TWeak> referenced = std::weak_ptr<TWeak>()) MIJIN_NOEXCEPT;
template<typename TObject, typename TWeak = void>
inline token_t connect(TObject& object, void (TObject::* handler)(TArgs...), Oneshot oneshot = Oneshot::NO, std::weak_ptr<TWeak> referenced = std::weak_ptr<TWeak>()) noexcept;
inline void disconnect(token_t token) noexcept;
inline void emit(TArgs&&... args) noexcept;
inline token_t connect(TObject& object, void (TObject::* handler)(TArgs...), Oneshot oneshot = Oneshot::NO, std::weak_ptr<TWeak> referenced = std::weak_ptr<TWeak>()) MIJIN_NOEXCEPT;
inline void disconnect(token_t token) MIJIN_NOEXCEPT;
inline void emit(TArgs&&... args) MIJIN_NOEXCEPT;
};
//
@@ -73,7 +74,7 @@ public:
template<typename... TArgs>
template<typename THandler, typename TWeak>
inline auto Signal<TArgs...>::connect(THandler handler, Oneshot oneshot, std::weak_ptr<TWeak> referenced) noexcept -> token_t
inline auto Signal<TArgs...>::connect(THandler handler, Oneshot oneshot, std::weak_ptr<TWeak> referenced) MIJIN_NOEXCEPT -> token_t
{
std::lock_guard lock(handlersMutex_);
@@ -90,7 +91,7 @@ inline auto Signal<TArgs...>::connect(THandler handler, Oneshot oneshot, std::we
template<typename... TArgs>
template<typename TObject, typename TWeak>
inline auto Signal<TArgs...>::connect(TObject& object, void (TObject::* handler)(TArgs...), Oneshot oneshot, std::weak_ptr<TWeak> referenced) noexcept -> token_t
inline auto Signal<TArgs...>::connect(TObject& object, void (TObject::* handler)(TArgs...), Oneshot oneshot, std::weak_ptr<TWeak> referenced) MIJIN_NOEXCEPT -> token_t
{
std::lock_guard lock(handlersMutex_);
@@ -109,7 +110,7 @@ inline auto Signal<TArgs...>::connect(TObject& object, void (TObject::* handler)
}
template<typename... TArgs>
inline void Signal<TArgs...>::disconnect(token_t token) noexcept
inline void Signal<TArgs...>::disconnect(token_t token) MIJIN_NOEXCEPT
{
std::lock_guard lock(handlersMutex_);
@@ -121,7 +122,7 @@ inline void Signal<TArgs...>::disconnect(token_t token) noexcept
}
template<typename... TArgs>
inline void Signal<TArgs...>::emit(TArgs&&... args) noexcept
inline void Signal<TArgs...>::emit(TArgs&&... args) MIJIN_NOEXCEPT
{
std::lock_guard lock(handlersMutex_);

View File

@@ -5,6 +5,7 @@
#define MIJIN_ASYNC_TASK_MUTEX_HPP_INCLUDED 1
#include "./coroutine.hpp"
#include "../internal/common.hpp"
namespace mijin
{
@@ -14,13 +15,13 @@ private:
class TaskMutex* mutex_;
public:
explicit TaskMutexLock(class TaskMutex* mutex) noexcept : mutex_(mutex) {}
explicit TaskMutexLock(class TaskMutex* mutex) MIJIN_NOEXCEPT : mutex_(mutex) {}
TaskMutexLock(const TaskMutexLock&) = delete;
TaskMutexLock(TaskMutexLock&& other) noexcept : mutex_(std::exchange(other.mutex_, nullptr)) {}
TaskMutexLock(TaskMutexLock&& other) MIJIN_NOEXCEPT : mutex_(std::exchange(other.mutex_, nullptr)) {}
TaskMutexLock& operator=(const TaskMutexLock&) = delete;
inline TaskMutexLock& operator=(TaskMutexLock&& other) noexcept;
inline ~TaskMutexLock() noexcept;
inline TaskMutexLock& operator=(TaskMutexLock&& other) MIJIN_NOEXCEPT;
inline ~TaskMutexLock() MIJIN_NOEXCEPT;
};
class TaskMutex
@@ -37,12 +38,12 @@ public:
locked_ = true;
co_return TaskMutexLock(this);
}
[[nodiscard]] inline bool isLocked() const noexcept { return locked_; }
[[nodiscard]] inline bool isLocked() const MIJIN_NOEXCEPT { return locked_; }
friend class TaskMutexLock;
};
TaskMutexLock::~TaskMutexLock() noexcept
TaskMutexLock::~TaskMutexLock() MIJIN_NOEXCEPT
{
if (mutex_)
{
@@ -50,7 +51,7 @@ TaskMutexLock::~TaskMutexLock() noexcept
}
}
TaskMutexLock& TaskMutexLock::operator=(TaskMutexLock&& other) noexcept
TaskMutexLock& TaskMutexLock::operator=(TaskMutexLock&& other) MIJIN_NOEXCEPT
{
if (mutex_)
{