restore nf7::Task once removed
This commit is contained in:
parent
79f3cc9639
commit
09375ced9c
@ -103,6 +103,7 @@ target_sources(nf7
|
||||
common/mutable_memento.hh
|
||||
common/mutex.hh
|
||||
common/native_file.hh
|
||||
common/nfile_watcher.hh
|
||||
common/node.hh
|
||||
common/node_link_store.hh
|
||||
common/node_root_lambda.hh
|
||||
@ -111,6 +112,7 @@ target_sources(nf7
|
||||
common/queue.hh
|
||||
common/sequencer.hh
|
||||
common/squashed_history.hh
|
||||
common/task.hh
|
||||
common/thread.hh
|
||||
common/timed_queue.hh
|
||||
common/util_algorithm.hh
|
||||
|
@ -18,6 +18,12 @@
|
||||
|
||||
namespace nf7 {
|
||||
|
||||
class CoroutineAbortException final : public nf7::Exception {
|
||||
public:
|
||||
using nf7::Exception::Exception;
|
||||
};
|
||||
|
||||
|
||||
// How To Use (factory side)
|
||||
// 1. Create Future<T>::Promise. (T is a type of returned value)
|
||||
// 2. Get Future<T> from Future<T>::Promise and Pass it to ones who want to get T.
|
||||
@ -27,6 +33,7 @@ namespace nf7 {
|
||||
// by Future::Then(), Future::ThenSub(), or co_await.
|
||||
|
||||
|
||||
|
||||
// T must not be void, use std::monostate instead
|
||||
template <typename T>
|
||||
class Future final {
|
||||
@ -110,7 +117,7 @@ class Future final {
|
||||
auto Wrap(const std::function<T()>& f) noexcept
|
||||
try {
|
||||
Return(f());
|
||||
} catch (Exception&) {
|
||||
} catch (...) {
|
||||
Throw(std::current_exception());
|
||||
}
|
||||
|
||||
@ -186,7 +193,7 @@ class Future final {
|
||||
}
|
||||
void Abort() noexcept {
|
||||
h_.promise().Throw(
|
||||
std::make_exception_ptr<nf7::Exception>({"coroutine aborted"}));
|
||||
std::make_exception_ptr<CoroutineAbortException>({"coroutine aborted"}));
|
||||
data_->aborted = true;
|
||||
}
|
||||
|
||||
@ -283,7 +290,6 @@ class Future final {
|
||||
|
||||
std::unique_lock<std::mutex> k(data.mtx);
|
||||
auto callee_ctx = data.ctx.lock();
|
||||
assert(callee_ctx);
|
||||
|
||||
auto caller_data = caller.promise().data__();
|
||||
auto caller_ctx = caller_data->ctx.lock();
|
||||
@ -306,7 +312,7 @@ class Future final {
|
||||
caller.resume();
|
||||
}
|
||||
}
|
||||
auto await_resume() { return value(); }
|
||||
auto& await_resume() { return value(); }
|
||||
|
||||
private:
|
||||
std::optional<Imm> imm_;
|
||||
|
95
common/task.hh
Normal file
95
common/task.hh
Normal file
@ -0,0 +1,95 @@
|
||||
#pragma once
|
||||
|
||||
#include <memory>
|
||||
#include <optional>
|
||||
#include <utility>
|
||||
|
||||
#include "nf7.hh"
|
||||
|
||||
#include "common/future.hh"
|
||||
|
||||
|
||||
namespace nf7 {
|
||||
|
||||
template <typename T>
|
||||
class Task : public nf7::Context,
|
||||
public std::enable_shared_from_this<Task<T>> {
|
||||
public:
|
||||
class Holder;
|
||||
|
||||
using Future = nf7::Future<T>;
|
||||
using Coro = typename Future::Coro;
|
||||
|
||||
using nf7::Context::Context;
|
||||
|
||||
Task(const Task&) = delete;
|
||||
Task(Task&&) = delete;
|
||||
Task& operator=(const Task&) = delete;
|
||||
Task& operator=(Task&&) = delete;
|
||||
|
||||
void Start() noexcept {
|
||||
coro_ = Proc();
|
||||
fu_ = coro_->Start(self());
|
||||
}
|
||||
void Abort() noexcept {
|
||||
coro_->Abort();
|
||||
}
|
||||
|
||||
auto self() noexcept {
|
||||
return std::enable_shared_from_this<Task<T>>::shared_from_this();
|
||||
}
|
||||
std::optional<Future>& fu() noexcept { return *fu_; }
|
||||
|
||||
protected:
|
||||
virtual Coro Proc() noexcept = 0;
|
||||
|
||||
private:
|
||||
std::optional<Coro> coro_;
|
||||
std::optional<Future> fu_;
|
||||
};
|
||||
|
||||
// all operations are not thread-safe
|
||||
template <typename T>
|
||||
class Task<T>::Holder final {
|
||||
public:
|
||||
Holder() = default;
|
||||
~Holder() noexcept {
|
||||
Abort();
|
||||
}
|
||||
|
||||
Holder(const Holder&) = delete;
|
||||
Holder(Holder&&) = delete;
|
||||
Holder& operator=(const Holder&) = delete;
|
||||
Holder& operator=(Holder&&) = delete;
|
||||
|
||||
bool CleanUp() noexcept {
|
||||
return !!std::exchange(fu_, std::nullopt);
|
||||
}
|
||||
void Abort() noexcept {
|
||||
if (auto task = task_.lock()) {
|
||||
task->Abort();
|
||||
}
|
||||
}
|
||||
|
||||
template <typename U, typename... Args>
|
||||
nf7::Future<T> StartIf(Args&&... args) noexcept {
|
||||
if (fu_) return *fu_;
|
||||
|
||||
auto task = std::make_shared<U>(std::forward<Args>(args)...);
|
||||
task->Start();
|
||||
|
||||
task_ = task;
|
||||
fu_ = task->fu();
|
||||
return *fu_;
|
||||
}
|
||||
|
||||
std::optional<nf7::Future<T>>& fu() noexcept { return fu_; }
|
||||
const std::optional<nf7::Future<T>>& fu() const noexcept { return fu_; }
|
||||
|
||||
private:
|
||||
std::weak_ptr<Task<T>> task_;
|
||||
|
||||
std::optional<nf7::Future<T>> fu_;
|
||||
};
|
||||
|
||||
} // namespace nf7
|
Loading…
x
Reference in New Issue
Block a user