1
0
mirror of https://github.com/tearshark/librf.git synced 2024-10-01 15:57:07 +08:00
librf/tutorial/test_async_stop_token.cpp

96 lines
2.3 KiB
C++
Raw Normal View History

2020-05-09 16:08:27 +08:00
#include <chrono>
#include <iostream>
#include <string>
#include <thread>
#include "librf.h"
using namespace resumef;
using namespace std::chrono;
//token触发停止后将不再调用cb
template<class _Ctype>
static void callback_get_long_with_stop(stop_token token, int64_t val, _Ctype&& cb)
{
std::thread([val, token = std::move(token), cb = std::forward<_Ctype>(cb)]
{
for (int i = 0; i < 10; ++i)
{
if (token.stop_requested())
return;
std::this_thread::sleep_for(10ms);
}
cb(val * val);
}).detach();
}
//token触发后设置canceled_exception异常。
static future_t<int64_t> async_get_long_with_stop(stop_token token, int64_t val)
{
awaitable_t<int64_t> awaitable;
//保证stopptr的生存期与callback_get_long_with_cancel()的回调参数的生存期一致。
//如果token已经被取消则传入的lambda会立即被调用则awaitable将不能再set_value
auto stopptr = make_stop_callback(token, [awaitable]
{
if (awaitable)
awaitable.throw_exception(canceled_exception(error_code::stop_requested));
});
if (awaitable) //处理已经被取消的情况
{
callback_get_long_with_stop(token, val, [awaitable, stopptr = std::move(stopptr)](int64_t val)
{
if (awaitable)
awaitable.set_value(val);
});
}
return awaitable.get_future();
}
//如果关联的协程被取消了则触发canceled_exception异常。
static future_t<int64_t> async_get_long_with_stop(int64_t val)
{
task_t* task = current_task();
co_return co_await async_get_long_with_stop(task->get_stop_token(), val);
}
//测试取消协程
static void test_get_long_with_stop(int64_t val)
{
//异步获取值的协程
task_t* task = GO
{
try
{
int64_t result = co_await async_get_long_with_stop(val);
std::cout << result << std::endl;
}
catch (std::logic_error& e)
{
std::cout << e.what() << std::endl;
}
};
//task的生命周期只在task代表的协程生存期间存在。
//但通过复制与其关联的stop_source生存期可以超过task的生存期。
stop_source stops = task->get_stop_source();
//取消上一个协程的延迟协程
GO
{
co_await sleep_for(1ms * (rand() % 300));
stops.request_stop();
};
this_scheduler()->run_until_notask();
}
void resumable_main_stop_token()
{
srand((int)time(nullptr));
for (int i = 0; i < 10; ++i)
test_get_long_with_stop(i);
}