game2006/server/robotserver/coroutine.cc
aozhiwei bdb5e79713 1
2023-05-27 14:27:39 +08:00

143 lines
2.6 KiB
C++

#include "precompile.h"
#include <iostream>
#include <f8/timer.h>
#include "coroutine.h"
#include "comgr.h"
#include "app.h"
void Awaiter::Await(std::shared_ptr<Awaiter> notifyer)
{
notifyers_.push_back(notifyer);
DoAwait();
}
std::shared_ptr<Awaiter> Awaiter::Sleep(int time)
{
return std::make_shared<TimerPromise>(time);
}
void Promise::DoAwait()
{
}
Coroutine::Coroutine(std::function<void(Coroutine*)> cb)
{
INIT_LIST_HEAD(&co_entry_);
INIT_LIST_HEAD(&exec_entry_);
list_add_tail(&co_entry_, &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);
CallExit(sink);
for (auto notifyer : notifyers_) {
if (!notifyer.expired()) {
notifyer.lock()->DoResume();
}
}
});
}
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<Awaiter> awaiter)
{
CoSuspend();
awaiter->Await(shared_from_this());
while (!awaiter->Done()) {
CoYield();
}
//CoResume();
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;
}
void Coroutine::CallExit(boost::coroutines2::coroutine<void>::push_type& sink)
{
sink_ = nullptr;
}
void Coroutine::DoAwait()
{
}
void Coroutine::DoResume()
{
CoResume();
}
void TimerPromise::DoAwait()
{
f8::Timer::Instance()->SetTimeout
(
time_,
[this, self = shared_from_this()] (int event, const a8::Args* args) mutable
{
if (event == a8::TIMER_EXEC_EVENT) {
done_ = true;
for (auto notifyer : notifyers_) {
if (!notifyer.expired()) {
notifyer.lock()->DoResume();
}
}
}
});
}