143 lines
2.6 KiB
C++
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();
|
|
}
|
|
}
|
|
}
|
|
});
|
|
}
|