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
2020-05-09 16:08:27 +08:00

96 lines
2.3 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#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);
}