diff --git a/f8/comgr.cc b/f8/comgr.cc new file mode 100644 index 0000000..3c53a05 --- /dev/null +++ b/f8/comgr.cc @@ -0,0 +1,38 @@ +#include + +#include +#include +#include + +namespace f8 +{ + + void CoMgr::Init() + { + INIT_LIST_HEAD(&co_list_); + INIT_LIST_HEAD(&exec_list_); + } + + void CoMgr::UnInit() + { + + } + + void CoMgr::Update() + { + Coroutine *co = nullptr, *tmp = nullptr; + list_for_each_entry_safe(co, tmp, &exec_list_, exec_entry_) { + if (!co->Exec()) { + co->hold_self_ = nullptr; + } + } + } + + std::weak_ptr CoMgr::CreateCo(std::function cb) + { + std::shared_ptr co(new Coroutine(cb)); + co->hold_self_ = co; + return co; + } + +} diff --git a/f8/comgr.h b/f8/comgr.h new file mode 100644 index 0000000..45d89e0 --- /dev/null +++ b/f8/comgr.h @@ -0,0 +1,30 @@ +#pragma once + +#include + +namespace f8 +{ + class Coroutine; + class CoMgr : public a8::Singleton + { + + private: + CoMgr() {}; + friend class a8::Singleton; + + public: + + void Init(); + void UnInit(); + void Update(); + + std::weak_ptr CreateCo(std::function cb); + + private: + list_head co_list_; + list_head exec_list_; + + friend class Coroutine; + }; + +} diff --git a/f8/coroutine.cc b/f8/coroutine.cc new file mode 100644 index 0000000..5572b91 --- /dev/null +++ b/f8/coroutine.cc @@ -0,0 +1,134 @@ +#include +#include +#include + +#include +#include +#include +#include + +class TimerPromise : public a8::Promise +{ + public: + + TimerPromise(long long time) { time_ = time; }; + +protected: + + virtual void DoAwait() override + { + f8::Timer::Instance()->SetTimeout + ( + time_, + [this, _self = shared_from_this()] (int event, const a8::Args* args) mutable + { + if (event == a8::TIMER_EXEC_EVENT) { + DoDone(); + } + }); + } + + private: + long long time_ = 0; + +}; + +namespace f8 +{ + + Coroutine::Coroutine(std::function cb) + { + INIT_LIST_HEAD(&co_entry_); + INIT_LIST_HEAD(&exec_entry_); + list_add_tail(&co_entry_, &f8::CoMgr::Instance()->co_list_); + Attach(); + cb_ = cb; + source_ = std::make_shared::pull_type> + ( + [this] (boost::coroutines2::coroutine::push_type& sink) + { + CallEnter(sink); + cb_(this); + DoDone(); + CallExit(sink); + }); + } + + Coroutine::~Coroutine() + { +#ifdef DEBUG + a8::XPrintf("Coroutine::~Coroutine()\n", {}); +#endif + Deatch(); + list_del_init(&co_entry_); + } + + bool Coroutine::Exec() + { + if (*source_) { + (*source_)(); + return true; + } else { + return false; + } + } + + void Coroutine::CoSuspend() + { + Deatch(); + } + + void Coroutine::CoResume() + { + Attach(); + } + + void Coroutine::CoYield() + { + (*sink_)(); + } + + std::shared_ptr Coroutine::CoAwait(std::shared_ptr awaiter) + { + CoSuspend(); + awaiter->Await(shared_from_this()); + while (!awaiter->Done()) { + CoYield(); + } + return awaiter->GetResult(); + } + + void Coroutine::Attach() + { + list_add_tail(&exec_entry_, &CoMgr::Instance()->exec_list_); + } + + void Coroutine::Deatch() + { + if (!list_empty(&exec_entry_)) { + list_del_init(&exec_entry_); + } + } + + void Coroutine::CallEnter(boost::coroutines2::coroutine::push_type& sink) + { + sink_ = &sink; + CoYield(); + } + + void Coroutine::CallExit(boost::coroutines2::coroutine::push_type& sink) + { + sink_ = nullptr; + } + + void Coroutine::DoResume() + { + CoResume(); + } + + std::shared_ptr Coroutine::Sleep(long long time) + { + return std::make_shared(time); + } + +} diff --git a/f8/coroutine.h b/f8/coroutine.h new file mode 100644 index 0000000..3c5c00f --- /dev/null +++ b/f8/coroutine.h @@ -0,0 +1,44 @@ +#pragma once + +#include + +#include + +namespace f8 +{ + + class Coroutine : public a8::Awaiter + { + public: + + virtual ~Coroutine() override; + + void CoSuspend(); + void CoResume(); + void CoYield(); + std::shared_ptr CoAwait(std::shared_ptr awaiter); + std::shared_ptr Sleep(long long time); + + private: + Coroutine(std::function cb); + + bool Exec(); + void Attach(); + void Deatch(); + void CallEnter(boost::coroutines2::coroutine::push_type& sink); + void CallExit(boost::coroutines2::coroutine::push_type& sink); + virtual void DoAwait() override {}; + virtual void DoResume() override; + + private: + list_head co_entry_; + list_head exec_entry_; + std::shared_ptr hold_self_; + std::shared_ptr::pull_type> source_; + std::function cb_; + boost::coroutines2::coroutine::push_type* sink_ = nullptr; + + friend class CoMgr; + }; + +}