This commit is contained in:
aozhiwei 2023-05-27 16:44:23 +08:00
parent 874ff7853e
commit ff41657bdf
4 changed files with 246 additions and 0 deletions

38
f8/comgr.cc Normal file
View File

@ -0,0 +1,38 @@
#include <a8/a8.h>
#include <f8/f8.h>
#include <f8/comgr.h>
#include <f8/coroutine.h>
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<Coroutine> CoMgr::CreateCo(std::function<void(Coroutine*)> cb)
{
std::shared_ptr<Coroutine> co(new Coroutine(cb));
co->hold_self_ = co;
return co;
}
}

30
f8/comgr.h Normal file
View File

@ -0,0 +1,30 @@
#pragma once
#include <a8/singleton.h>
namespace f8
{
class Coroutine;
class CoMgr : public a8::Singleton<CoMgr>
{
private:
CoMgr() {};
friend class a8::Singleton<CoMgr>;
public:
void Init();
void UnInit();
void Update();
std::weak_ptr<Coroutine> CreateCo(std::function<void(Coroutine*)> cb);
private:
list_head co_list_;
list_head exec_list_;
friend class Coroutine;
};
}

134
f8/coroutine.cc Normal file
View File

@ -0,0 +1,134 @@
#include <a8/a8.h>
#include <a8/awaiter.h>
#include <a8/promise.h>
#include <f8/f8.h>
#include <f8/coroutine.h>
#include <f8/comgr.h>
#include <f8/timer.h>
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<void(Coroutine*)> 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<boost::coroutines2::coroutine<void>::pull_type>
(
[this] (boost::coroutines2::coroutine<void>::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<a8::Results> Coroutine::CoAwait(std::shared_ptr<a8::Awaiter> 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<void>::push_type& sink)
{
sink_ = &sink;
CoYield();
}
void Coroutine::CallExit(boost::coroutines2::coroutine<void>::push_type& sink)
{
sink_ = nullptr;
}
void Coroutine::DoResume()
{
CoResume();
}
std::shared_ptr<a8::Awaiter> Coroutine::Sleep(long long time)
{
return std::make_shared<TimerPromise>(time);
}
}

44
f8/coroutine.h Normal file
View File

@ -0,0 +1,44 @@
#pragma once
#include <a8/awaiter.h>
#include <boost/coroutine2/all.hpp>
namespace f8
{
class Coroutine : public a8::Awaiter
{
public:
virtual ~Coroutine() override;
void CoSuspend();
void CoResume();
void CoYield();
std::shared_ptr<a8::Results> CoAwait(std::shared_ptr<a8::Awaiter> awaiter);
std::shared_ptr<a8::Awaiter> Sleep(long long time);
private:
Coroutine(std::function<void(Coroutine*)> cb);
bool Exec();
void Attach();
void Deatch();
void CallEnter(boost::coroutines2::coroutine<void>::push_type& sink);
void CallExit(boost::coroutines2::coroutine<void>::push_type& sink);
virtual void DoAwait() override {};
virtual void DoResume() override;
private:
list_head co_entry_;
list_head exec_entry_;
std::shared_ptr<Coroutine> hold_self_;
std::shared_ptr<boost::coroutines2::coroutine<void>::pull_type> source_;
std::function<void(Coroutine* co)> cb_;
boost::coroutines2::coroutine<void>::push_type* sink_ = nullptr;
friend class CoMgr;
};
}