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

176 lines
4.9 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.

//依赖 https://github.com/tearshark/modern_cb 项目
//依赖 https://github.com/tearshark/librf 项目
#include <future>
#include <string>
#include <iostream>
#include "modern_callback.h"
//原旨主义的异步函数,其回调写法大致如下
template<typename _Input_t, typename _Callable_t>
void tostring_async_originalism(_Input_t&& value, _Callable_t&& token)
{
std::thread([callback = std::move(token), value = std::forward<_Input_t>(value)]
{
callback(std::to_string(value));
}).detach();
}
void tostring_async_originalism2(int value, std::function<void(std::string)>&& token, double mu)
{
std::thread([callback = std::move(token), value, mu]
{
callback(std::to_string(value * mu));
}).detach();
}
//使用原旨主义的方式扩展异步方法来支持future
template<typename _Input_t>
auto tostring_async_originalism_future(_Input_t&& value)
{
std::promise<std::string> _promise;
std::future<std::string> _future = _promise.get_future();
std::thread([_promise = std::move(_promise), value = std::forward<_Input_t>(value)]() mutable
{
_promise.set_value(std::to_string(value));
}).detach();
return std::move(_future);
}
//----------------------------------------------------------------------------------------------------------------------
//下面演示如何扩展tostring_async函数以支持future模式
template<typename _Input_t, typename _Callable_t>
auto tostring_async(_Input_t&& value, _Callable_t&& token)
{
MODERN_CALLBACK_TRAITS(token, void(std::string));
std::thread([callback = MODERN_CALLBACK_CALL(), value = std::forward<_Input_t>(value)]
{
callback(std::to_string(value));
}).detach();
MODERN_CALLBACK_RETURN();
}
//演示异步库有多个异步回调函数只要按照Modern Callback范式去做回调就不再需要写额外的代码就可以适配到future+librf以及更多的其他库
template<typename _Ty1, typename _Ty2, typename _Callable_t>
auto add_async(_Ty1&& val1, _Ty2&& val2, _Callable_t&& token)
{
MODERN_CALLBACK_TRAITS(token, void(decltype(val1 + val2)));
std::thread([=, callback = MODERN_CALLBACK_CALL()]
{
using namespace std::literals;
std::this_thread::sleep_for(0.1s);
callback(val1 + val2);
}).detach();
MODERN_CALLBACK_RETURN();
}
//演示异步库有多个异步回调函数只要按照Modern Callback范式去做回调就不再需要写额外的代码就可以适配到future+librf以及更多的其他库
template<typename _Ty1, typename _Ty2, typename _Callable_t>
auto muldiv_async(_Ty1&& val1, _Ty2&& val2, _Callable_t&& token)
{
MODERN_CALLBACK_TRAITS(token, void(std::exception_ptr, decltype(val1 * val2), decltype(val1 / val2)));
std::thread([=, callback = MODERN_CALLBACK_CALL()]
{
using namespace std::literals;
std::this_thread::sleep_for(0.1s);
auto v1 = val1 * val2;
if (val2 == 0)
callback(std::make_exception_ptr(std::logic_error("divided by zero")), v1, 0);
else
callback(nullptr, v1, val1 / val2);
}).detach();
MODERN_CALLBACK_RETURN();
}
#include "use_future.h"
#if TEST_ASYNC_CALLBACK
#include "async_call.hpp"
#endif
static void example_future()
{
using namespace std::literals;
//使用lambda作为异步回调函数传统用法
tostring_async_originalism(-1.0, [](std::string&& value)
{
std::cout << value << std::endl;
});
std::this_thread::sleep_for(0.5s);
tostring_async(1.0, [](std::string&& value)
{
std::cout << value << std::endl;
});
std::this_thread::sleep_for(0.5s);
std::cout << "......" << std::endl;
//支持future的用法
std::future<std::string> f1 = tostring_async_originalism_future(5);
std::cout << f1.get() << std::endl;
std::future<std::string> f2 = tostring_async(6.0f, std_future);
std::cout << f2.get() << std::endl;
#if TEST_ASYNC_CALLBACK
std::future<std::string> f3 = async_call(&tostring_async_originalism2, 99, placeholder::_cb(std_future), 2.0);
std::cout << f3.get() << std::endl;
#endif
}
#include "librf.h"
#include "use_librf.h"
static void example_librf()
{
//支持librf的用法
GO
{
try
{
int val = co_await add_async(1, 2, use_librf);
std::cout << val << std::endl;
//muldiv_async函数可能会抛异常取决于val是否是0
//异常将会带回到本协程里的代码所以需要try-catch
auto [a, b] = co_await muldiv_async(9, val, use_librf);
std::string result = co_await tostring_async(a + b, use_librf);
std::cout << result << std::endl;
#if TEST_ASYNC_CALLBACK
result = co_await async_call(&tostring_async_originalism2, 99, placeholder::_cb(use_librf), 2.0);
std::cout << result << std::endl;
#endif
}
catch (const std::exception & e)
{
std::cout << "exception signal : " << e.what() << std::endl;
}
catch (...)
{
std::cout << "exception signal : who knows?" << std::endl;
}
};
resumef::this_scheduler()->run_until_notask();
}
void resumable_main_modern_cb()
{
std::cout << __FUNCTION__ << std::endl;
example_future();
example_librf();
}