#pragma once #include #include #include #include "nf7.hh" #include "common/future.hh" namespace nf7 { template class Task : public nf7::Context, public std::enable_shared_from_this> { public: class Holder; using Future = nf7::Future; 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>::shared_from_this(); } std::optional& fu() noexcept { return *fu_; } protected: virtual Coro Proc() noexcept = 0; private: std::optional coro_; std::optional fu_; }; // all operations are not thread-safe template class Task::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 nf7::Future StartIf(Args&&... args) noexcept { if (fu_) return *fu_; auto task = std::make_shared(std::forward(args)...); task->Start(); task_ = task; fu_ = task->fu(); return *fu_; } std::optional>& fu() noexcept { return fu_; } const std::optional>& fu() const noexcept { return fu_; } private: std::weak_ptr> task_; std::optional> fu_; }; } // namespace nf7