Added (pretty limited) support for uncaught exceptions in coroutines.
This commit is contained in:
parent
dff7b30b2d
commit
0b8772c952
@ -455,11 +455,15 @@ public:
|
||||
std::function<void(StoredTask&)> setFuture;
|
||||
std::any resultData;
|
||||
};
|
||||
|
||||
using exception_handler_t = std::function<void(std::exception_ptr)>;
|
||||
protected:
|
||||
using task_vector_t = std::vector<StoredTask>;
|
||||
|
||||
template<typename TTask>
|
||||
using wrapped_task_ptr_t = std::unique_ptr<WrappedTask<TTask>>;
|
||||
|
||||
exception_handler_t uncaughtExceptionHandler_;
|
||||
public:
|
||||
TaskLoop() = default;
|
||||
TaskLoop(const TaskLoop&) = delete;
|
||||
@ -469,6 +473,8 @@ public:
|
||||
TaskLoop& operator=(const TaskLoop&) = delete;
|
||||
TaskLoop& operator=(TaskLoop&&) = delete;
|
||||
|
||||
void setUncaughtExceptionHandler(exception_handler_t handler) noexcept { uncaughtExceptionHandler_ = std::move(handler); }
|
||||
|
||||
template<typename TResult>
|
||||
inline FuturePtr<TResult> addTask(TaskBase<TResult> task, TaskHandle* outHandle = nullptr) noexcept;
|
||||
|
||||
@ -477,7 +483,7 @@ public:
|
||||
|
||||
[[nodiscard]] static TaskLoop& current() noexcept;
|
||||
protected:
|
||||
inline TaskStatus tickTask(StoredTask& task) noexcept;
|
||||
inline TaskStatus tickTask(StoredTask& task);
|
||||
protected:
|
||||
static inline TaskLoop*& currentLoopStorage() noexcept;
|
||||
template<typename TResult>
|
||||
@ -502,8 +508,8 @@ public: // TaskLoop implementation
|
||||
|
||||
public: // public interface
|
||||
[[nodiscard]] constexpr bool empty() const noexcept { return tasks_.empty() && newTasks_.empty(); }
|
||||
inline CanContinue tick() noexcept;
|
||||
inline void runUntilDone(IgnoreWaiting ignoreWaiting = IgnoreWaiting::NO) noexcept;
|
||||
inline CanContinue tick();
|
||||
inline void runUntilDone(IgnoreWaiting ignoreWaiting = IgnoreWaiting::NO);
|
||||
private:
|
||||
inline void assertCorrectThread() { MIJIN_ASSERT(threadId_ == std::thread::id() || threadId_ == std::this_thread::get_id(), "Unsafe to TaskLoop from different thread!"); }
|
||||
};
|
||||
@ -582,7 +588,7 @@ inline FuturePtr<TResult> TaskLoop::addTask(TaskBase<TResult> task, TaskHandle*
|
||||
return future;
|
||||
}
|
||||
|
||||
inline TaskStatus TaskLoop::tickTask(StoredTask& task) noexcept
|
||||
inline TaskStatus TaskLoop::tickTask(StoredTask& task)
|
||||
{
|
||||
TaskStatus status = {};
|
||||
impl::gCurrentTask = &task;
|
||||
@ -596,6 +602,23 @@ inline TaskStatus TaskLoop::tickTask(StoredTask& task) noexcept
|
||||
|
||||
if (task.task && task.task->exception())
|
||||
{
|
||||
try
|
||||
{
|
||||
std::rethrow_exception(task.task->exception());
|
||||
}
|
||||
catch(impl::TaskCancelled&) {} // ignore those
|
||||
catch(...)
|
||||
{
|
||||
if (uncaughtExceptionHandler_)
|
||||
{
|
||||
uncaughtExceptionHandler_(std::current_exception());
|
||||
}
|
||||
else
|
||||
{
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: handle the exception somehow, others may be waiting
|
||||
return TaskStatus::FINISHED;
|
||||
}
|
||||
@ -644,7 +667,7 @@ inline std::suspend_always switchContext(TaskLoop& taskLoop)
|
||||
return {};
|
||||
}
|
||||
|
||||
inline auto SimpleTaskLoop::tick() noexcept -> CanContinue
|
||||
inline auto SimpleTaskLoop::tick() -> CanContinue
|
||||
{
|
||||
// set current taskloop
|
||||
MIJIN_ASSERT(currentLoopStorage() == nullptr, "Trying to tick a loop from a coroutine, this is not supported.");
|
||||
@ -705,7 +728,7 @@ inline auto SimpleTaskLoop::tick() noexcept -> CanContinue
|
||||
return canContinue;
|
||||
}
|
||||
|
||||
inline void SimpleTaskLoop::runUntilDone(IgnoreWaiting ignoreWaiting) noexcept
|
||||
inline void SimpleTaskLoop::runUntilDone(IgnoreWaiting ignoreWaiting)
|
||||
{
|
||||
while (!tasks_.empty() || !newTasks_.empty())
|
||||
{
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user