2020-05-21 16:42:44 +08:00
|
|
|
|
//依赖 https://github.com/tearshark/modern_cb 项目
|
|
|
|
|
//依赖 https://github.com/tearshark/librf 项目
|
2019-04-21 09:05:04 +08:00
|
|
|
|
|
|
|
|
|
#include <future>
|
2020-04-04 23:02:51 +08:00
|
|
|
|
#include <string>
|
|
|
|
|
#include <iostream>
|
|
|
|
|
|
|
|
|
|
#include "modern_callback.h"
|
2019-04-21 09:05:04 +08:00
|
|
|
|
|
2019-04-25 16:07:37 +08:00
|
|
|
|
//原旨主义的异步函数,其回调写法大致如下
|
2019-04-21 09:05:04 +08:00
|
|
|
|
template<typename _Input_t, typename _Callable_t>
|
2019-04-25 16:07:37 +08:00
|
|
|
|
void tostring_async_originalism(_Input_t&& value, _Callable_t&& token)
|
2019-04-21 09:05:04 +08:00
|
|
|
|
{
|
2019-04-25 16:07:37 +08:00
|
|
|
|
std::thread([callback = std::move(token), value = std::forward<_Input_t>(value)]
|
2019-04-21 09:05:04 +08:00
|
|
|
|
{
|
|
|
|
|
callback(std::to_string(value));
|
|
|
|
|
}).detach();
|
|
|
|
|
}
|
2020-07-07 15:00:38 +08:00
|
|
|
|
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();
|
|
|
|
|
}
|
2019-04-21 09:05:04 +08:00
|
|
|
|
|
2019-04-25 16:07:37 +08:00
|
|
|
|
//使用原旨主义的方式扩展异步方法来支持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);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//----------------------------------------------------------------------------------------------------------------------
|
2020-04-04 23:02:51 +08:00
|
|
|
|
//下面演示如何扩展tostring_async函数,以支持future模式
|
2019-04-21 09:05:04 +08:00
|
|
|
|
|
|
|
|
|
template<typename _Input_t, typename _Callable_t>
|
2019-04-25 16:07:37 +08:00
|
|
|
|
auto tostring_async(_Input_t&& value, _Callable_t&& token)
|
2019-04-21 09:05:04 +08:00
|
|
|
|
{
|
2019-04-25 17:56:51 +08:00
|
|
|
|
MODERN_CALLBACK_TRAITS(token, void(std::string));
|
2019-04-21 09:05:04 +08:00
|
|
|
|
|
2019-04-25 17:56:51 +08:00
|
|
|
|
std::thread([callback = MODERN_CALLBACK_CALL(), value = std::forward<_Input_t>(value)]
|
2019-04-21 09:05:04 +08:00
|
|
|
|
{
|
2019-04-25 16:07:37 +08:00
|
|
|
|
callback(std::to_string(value));
|
2019-04-21 09:05:04 +08:00
|
|
|
|
}).detach();
|
|
|
|
|
|
2020-04-18 07:50:02 +08:00
|
|
|
|
MODERN_CALLBACK_RETURN();
|
2019-04-21 09:05:04 +08:00
|
|
|
|
}
|
|
|
|
|
|
2019-04-25 17:26:16 +08:00
|
|
|
|
//演示异步库有多个异步回调函数,只要按照Modern Callback范式去做回调,就不再需要写额外的代码,就可以适配到future+librf,以及更多的其他库
|
|
|
|
|
template<typename _Ty1, typename _Ty2, typename _Callable_t>
|
|
|
|
|
auto add_async(_Ty1&& val1, _Ty2&& val2, _Callable_t&& token)
|
|
|
|
|
{
|
2019-04-25 17:56:51 +08:00
|
|
|
|
MODERN_CALLBACK_TRAITS(token, void(decltype(val1 + val2)));
|
2019-04-25 17:26:16 +08:00
|
|
|
|
|
2019-04-25 17:56:51 +08:00
|
|
|
|
std::thread([=, callback = MODERN_CALLBACK_CALL()]
|
2019-04-25 17:26:16 +08:00
|
|
|
|
{
|
|
|
|
|
using namespace std::literals;
|
|
|
|
|
std::this_thread::sleep_for(0.1s);
|
|
|
|
|
callback(val1 + val2);
|
|
|
|
|
}).detach();
|
|
|
|
|
|
2020-04-18 07:50:02 +08:00
|
|
|
|
MODERN_CALLBACK_RETURN();
|
2019-04-25 17:26:16 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//演示异步库有多个异步回调函数,只要按照Modern Callback范式去做回调,就不再需要写额外的代码,就可以适配到future+librf,以及更多的其他库
|
|
|
|
|
template<typename _Ty1, typename _Ty2, typename _Callable_t>
|
|
|
|
|
auto muldiv_async(_Ty1&& val1, _Ty2&& val2, _Callable_t&& token)
|
|
|
|
|
{
|
2019-04-25 17:56:51 +08:00
|
|
|
|
MODERN_CALLBACK_TRAITS(token, void(std::exception_ptr, decltype(val1 * val2), decltype(val1 / val2)));
|
2019-04-25 17:26:16 +08:00
|
|
|
|
|
2019-04-25 17:56:51 +08:00
|
|
|
|
std::thread([=, callback = MODERN_CALLBACK_CALL()]
|
2019-04-25 17:26:16 +08:00
|
|
|
|
{
|
|
|
|
|
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();
|
|
|
|
|
|
2020-04-18 07:50:02 +08:00
|
|
|
|
MODERN_CALLBACK_RETURN();
|
2019-04-25 17:26:16 +08:00
|
|
|
|
}
|
|
|
|
|
|
2020-04-04 23:02:51 +08:00
|
|
|
|
#include "use_future.h"
|
2020-07-07 15:00:38 +08:00
|
|
|
|
#if TEST_ASYNC_CALLBACK
|
|
|
|
|
#include "async_call.hpp"
|
|
|
|
|
#endif
|
2020-04-04 23:02:51 +08:00
|
|
|
|
|
|
|
|
|
static void example_future()
|
2019-04-21 09:05:04 +08:00
|
|
|
|
{
|
|
|
|
|
using namespace std::literals;
|
|
|
|
|
|
|
|
|
|
//使用lambda作为异步回调函数,传统用法
|
2020-04-04 23:02:51 +08:00
|
|
|
|
tostring_async_originalism(-1.0, [](std::string&& value)
|
2019-04-25 16:07:37 +08:00
|
|
|
|
{
|
|
|
|
|
std::cout << value << std::endl;
|
|
|
|
|
});
|
2019-04-25 17:26:16 +08:00
|
|
|
|
std::this_thread::sleep_for(0.5s);
|
2019-04-21 09:05:04 +08:00
|
|
|
|
|
2020-04-04 23:02:51 +08:00
|
|
|
|
tostring_async(1.0, [](std::string&& value)
|
2019-04-21 09:05:04 +08:00
|
|
|
|
{
|
|
|
|
|
std::cout << value << std::endl;
|
|
|
|
|
});
|
2019-04-25 16:07:37 +08:00
|
|
|
|
|
2019-04-25 17:26:16 +08:00
|
|
|
|
std::this_thread::sleep_for(0.5s);
|
2019-04-21 09:05:04 +08:00
|
|
|
|
std::cout << "......" << std::endl;
|
|
|
|
|
|
|
|
|
|
//支持future的用法
|
2019-04-25 16:07:37 +08:00
|
|
|
|
std::future<std::string> f1 = tostring_async_originalism_future(5);
|
2019-04-21 09:05:04 +08:00
|
|
|
|
std::cout << f1.get() << std::endl;
|
|
|
|
|
|
2019-04-25 16:07:37 +08:00
|
|
|
|
std::future<std::string> f2 = tostring_async(6.0f, std_future);
|
2019-04-21 09:05:04 +08:00
|
|
|
|
std::cout << f2.get() << std::endl;
|
2020-07-07 15:00:38 +08:00
|
|
|
|
|
|
|
|
|
#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
|
2020-04-04 23:02:51 +08:00
|
|
|
|
}
|
2019-04-21 09:05:04 +08:00
|
|
|
|
|
2021-11-01 17:59:08 +08:00
|
|
|
|
#include "librf/librf.h"
|
2020-04-04 23:02:51 +08:00
|
|
|
|
#include "use_librf.h"
|
|
|
|
|
|
|
|
|
|
static void example_librf()
|
|
|
|
|
{
|
2019-04-21 09:05:04 +08:00
|
|
|
|
//支持librf的用法
|
|
|
|
|
GO
|
|
|
|
|
{
|
2019-04-25 17:26:16 +08:00
|
|
|
|
try
|
|
|
|
|
{
|
|
|
|
|
int val = co_await add_async(1, 2, use_librf);
|
2020-02-16 12:03:51 +08:00
|
|
|
|
std::cout << val << std::endl;
|
2019-04-25 17:26:16 +08:00
|
|
|
|
|
|
|
|
|
//muldiv_async函数可能会抛异常,取决于val是否是0
|
|
|
|
|
//异常将会带回到本协程里的代码,所以需要try-catch
|
2020-04-18 07:50:02 +08:00
|
|
|
|
auto [a, b] = co_await muldiv_async(9, val, use_librf);
|
2019-04-25 17:26:16 +08:00
|
|
|
|
|
2020-04-18 07:50:02 +08:00
|
|
|
|
std::string result = co_await tostring_async(a + b, use_librf);
|
2020-07-07 15:00:38 +08:00
|
|
|
|
std::cout << result << std::endl;
|
2019-04-25 17:26:16 +08:00
|
|
|
|
|
2020-07-07 15:00:38 +08:00
|
|
|
|
#if TEST_ASYNC_CALLBACK
|
|
|
|
|
result = co_await async_call(&tostring_async_originalism2, 99, placeholder::_cb(use_librf), 2.0);
|
2019-04-25 17:26:16 +08:00
|
|
|
|
std::cout << result << std::endl;
|
2020-07-07 15:00:38 +08:00
|
|
|
|
#endif
|
2019-04-25 17:26:16 +08:00
|
|
|
|
}
|
2020-04-04 23:02:51 +08:00
|
|
|
|
catch (const std::exception & e)
|
2019-04-25 17:26:16 +08:00
|
|
|
|
{
|
|
|
|
|
std::cout << "exception signal : " << e.what() << std::endl;
|
|
|
|
|
}
|
|
|
|
|
catch (...)
|
|
|
|
|
{
|
|
|
|
|
std::cout << "exception signal : who knows?" << std::endl;
|
|
|
|
|
}
|
2019-04-21 09:05:04 +08:00
|
|
|
|
};
|
2019-04-25 17:26:16 +08:00
|
|
|
|
|
2021-11-01 17:59:08 +08:00
|
|
|
|
librf::this_scheduler()->run_until_notask();
|
2019-04-21 09:05:04 +08:00
|
|
|
|
}
|
2020-04-04 23:02:51 +08:00
|
|
|
|
|
|
|
|
|
void resumable_main_modern_cb()
|
|
|
|
|
{
|
2020-05-26 11:52:53 +08:00
|
|
|
|
std::cout << __FUNCTION__ << std::endl;
|
2020-04-04 23:02:51 +08:00
|
|
|
|
example_future();
|
|
|
|
|
example_librf();
|
2020-09-23 22:56:51 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int main()
|
|
|
|
|
{
|
|
|
|
|
resumable_main_modern_cb();
|
|
|
|
|
return 0;
|
|
|
|
|
}
|