1
0
mirror of https://github.com/tearshark/librf.git synced 2024-10-02 00:00:11 +08:00
librf/tutorial/test_async_switch_scheduler.cpp

121 lines
3.6 KiB
C++
Raw Normal View History


#include <chrono>
#include <iostream>
#include <string>
#include <conio.h>
#include <thread>
#include "librf.h"
using namespace resumef;
static scheduler_t* sch_in_main = nullptr;
2020-02-27 14:45:55 +08:00
static std::atomic<scheduler_t*> sch_in_thread = nullptr;
2020-03-09 17:59:07 +08:00
void run_in_thread(channel_t<bool> c_done)
{
2020-02-27 14:45:55 +08:00
local_scheduler my_scheduler; //产生本线程唯一的调度器
sch_in_thread = this_scheduler(); //本线程唯一的调度器赋值给sch_in_thread以便于后续测试直接访问此线程的调度器
(void)c_done.write(true); //数据都准备好了通过channel通知其他协程可以启动后续依赖sch_in_thread变量的协程了
2020-02-27 14:45:55 +08:00
//循环直到sch_in_thread为nullptr
for (;;)
{
auto sch = sch_in_thread.load(std::memory_order_acquire);
2020-02-27 14:45:55 +08:00
if (sch == nullptr)
break;
sch->run_one_batch();
std::this_thread::yield();
}
}
template<class _Ctype>
2020-03-11 22:30:42 +08:00
static void callback_get_long_switch_scheduler(int64_t val, _Ctype&& cb)
{
using namespace std::chrono;
std::thread([val, cb = std::forward<_Ctype>(cb)]
{
std::this_thread::sleep_for(500ms);
2020-03-11 22:30:42 +08:00
cb(val + 1);
}).detach();
}
//这种情况下,没有生成 frame-context因此并没有promise_type被内嵌在frame-context里
2020-03-11 22:30:42 +08:00
static future_t<int64_t> async_get_long_switch_scheduler(int64_t val)
{
awaitable_t<int64_t> awaitable;
2020-03-11 22:30:42 +08:00
callback_get_long_switch_scheduler(val, [awaitable](int64_t result)
{
2020-03-11 22:30:42 +08:00
awaitable.set_value(result);
});
return awaitable.get_future();
}
//这种情况下,会生成对应的 frame-context一个promise_type被内嵌在frame-context里
2020-03-11 22:30:42 +08:00
static future_t<> resumable_get_long_switch_scheduler(int64_t val, channel_t<bool> c_done)
{
2020-03-11 22:30:42 +08:00
std::cout << "thread = " << std::this_thread::get_id();
std::cout << ", scheduler = " << current_scheduler();
std::cout << ", value = " << val << std::endl;
co_await *sch_in_thread;
2020-03-11 22:30:42 +08:00
val = co_await async_get_long_switch_scheduler(val);
std::cout << "thread = " << std::this_thread::get_id();
std::cout << ", scheduler = " << current_scheduler();
std::cout << ", value = " << val << std::endl;
co_await *sch_in_main;
2020-03-11 22:30:42 +08:00
val = co_await async_get_long_switch_scheduler(val);
std::cout << "thread = " << std::this_thread::get_id();
std::cout << ", scheduler = " << current_scheduler();
std::cout << ", value = " << val << std::endl;
co_await *sch_in_thread;
2020-03-11 22:30:42 +08:00
val = co_await async_get_long_switch_scheduler(val);
std::cout << "thread = " << std::this_thread::get_id();
std::cout << ", scheduler = " << current_scheduler();
std::cout << ", value = " << val << std::endl;
co_await *sch_in_thread; //fake switch
val = co_await async_get_long_switch_scheduler(val);
std::cout << "thread = " << std::this_thread::get_id();
std::cout << ", scheduler = " << current_scheduler();
std::cout << ", value = " << val << std::endl;
(void)c_done.write(true);
}
void resumable_main_switch_scheduler()
{
sch_in_main = this_scheduler();
2020-03-11 22:30:42 +08:00
std::cout << "main thread = " << std::this_thread::get_id();
std::cout << ", scheduler = " << sch_in_main << std::endl;
channel_t<bool> c_done{ 1 };
2020-02-27 14:45:55 +08:00
std::thread other(&run_in_thread, std::ref(c_done));
2020-03-11 22:30:42 +08:00
go[&other, c_done]()->future_t<>
{
2020-02-27 14:45:55 +08:00
co_await c_done; //第一次等待等待run_in_thread准备好了
2020-03-11 22:30:42 +08:00
std::cout << "other thread = " << other.get_id();
std::cout << ", sch_in_thread = " << sch_in_thread << std::endl;
go resumable_get_long_switch_scheduler(1, c_done); //开启另外一个协程
2020-02-27 14:45:55 +08:00
//co_await resumable_get_long(3, c_done);
co_await c_done; //等待新的协程运行完毕,从而保证主线程的协程不会提早退出
};
sch_in_main->run_until_notask();
2020-02-27 14:45:55 +08:00
//通知另外一个线程退出
sch_in_thread.store(nullptr, std::memory_order_release);
other.join();
}