Browse Source

Modern Callback增加演示多返回值,返回异常的范例

tags/v2.9.7
tearshark 5 years ago
parent
commit
06bd2d5647
3 changed files with 84 additions and 20 deletions
  1. 0
    2
      librf/src/state.h
  2. 82
    16
      tutorial/test_async_modern_cb.cpp
  3. 2
    2
      vs_proj/librf.vcxproj

+ 0
- 2
librf/src/state.h View File

@@ -72,8 +72,6 @@ namespace resumef
void reset_none_lock()
{
scoped_lock<lock_type> __guard(_mtx);
_coro = nullptr;
_ready = false;
}

+ 82
- 16
tutorial/test_async_modern_cb.cpp View File

@@ -89,6 +89,8 @@ auto tostring_async(_Input_t&& value, _Callable_t&& token)
//callback与token未必是同一个变量,甚至未必是同一个类型
std::thread([callback = std::move(std::get<0>(adapter)), value = std::forward<_Input_t>(value)]
{
using namespace std::literals;
std::this_thread::sleep_for(0.1s);
callback(std::to_string(value));
}).detach();

@@ -98,7 +100,7 @@ auto tostring_async(_Input_t&& value, _Callable_t&& token)

//或者宏版本写法
#define MODERN_CALLBACK_TRAITS(signature) \
using _Adapter_t = modern_callback_adapter_t<std::decay_t<_Callable_t>, void(std::string)>; \
using _Adapter_t = modern_callback_adapter_t<std::decay_t<_Callable_t>, signature>; \
auto adapter = typename _Adapter_t::traits(std::forward<_Callable_t>(token))
#define MODERN_CALLBACK_CALL() callback = std::move(std::get<0>(adapter))
#define MODERN_CALLBACK_RETURN() return std::move(std::get<1>(adapter)).get()
@@ -151,9 +153,10 @@ struct use_future_callback_t : public use_future_callback_base_t<_Promise_traits
{
using use_future_callback_base_t<_Promise_traits, std::tuple<_Result_t...> >::use_future_callback_base_t;

template <typename... Args>
template<typename... Args>
void operator()(Args&&... args) const
{
static_assert(sizeof...(Args) == sizeof...(_Result_t), "");
_promise.set_value(std::make_tuple(std::forward<Args>(args)...));
}
};
@@ -164,9 +167,10 @@ struct use_future_callback_t<_Promise_traits, std::exception_ptr, _Result_t...>
{
using use_future_callback_base_t<_Promise_traits, std::tuple<_Result_t...> >::use_future_callback_base_t;

template <typename... Args>
template<typename... Args>
void operator()(std::exception_ptr eptr, Args&&... args) const
{
static_assert(sizeof...(Args) == sizeof...(_Result_t), "");
if (!eptr)
_promise.set_value(std::make_tuple(std::forward<Args>(args)...));
else
@@ -207,9 +211,10 @@ struct use_future_callback_t<_Promise_traits, _Result_t> : public use_future_cal
{
using use_future_callback_base_t<_Promise_traits, _Result_t>::use_future_callback_base_t;

void operator()(result_type && arg) const
template<typename Arg>
void operator()(Arg && arg) const
{
_promise.set_value(std::forward<result_type>(arg));
_promise.set_value(std::forward<Arg>(arg));
}
};

@@ -219,10 +224,11 @@ struct use_future_callback_t<_Promise_traits, std::exception_ptr, _Result_t> : p
{
using use_future_callback_base_t<_Promise_traits, _Result_t>::use_future_callback_base_t;

void operator()(std::exception_ptr eptr, result_type && arg) const
template<typename Arg>
void operator()(std::exception_ptr eptr, Arg && arg) const
{
if (!eptr)
_promise.set_value(std::forward<result_type>(arg));
_promise.set_value(std::forward<Arg>(arg));
else
_promise.set_exception(std::move(eptr));
}
@@ -231,11 +237,11 @@ struct use_future_callback_t<_Promise_traits, std::exception_ptr, _Result_t> : p


//与use_future_callback_t配套的获得_Return_t的类
template<typename _Future_t, typename _Result_t>
template<typename _Future_traits, typename _Result_t>
struct use_future_return_t
{
using result_type = _Result_t;
using future_type = typename _Future_t::template future_type<result_type>;
using future_type = typename _Future_traits::template future_type<result_type>;
future_type _future;

use_future_return_t(future_type && ft)
@@ -268,15 +274,15 @@ struct std_future_t
constexpr std_future_t std_future{};

//三、特例化的modern_callback_adapter_t的实现类
template<typename _Token_t, typename... _Result_t>
template<typename _Token_as_callable_t, typename... _Result_t>
struct modern_callback_adapter_impl_t
{
using traits_type = _Token_t;
using traits_type = _Token_as_callable_t;
using callback_type = use_future_callback_t<traits_type, _Result_t...>;
using result_type = typename callback_type::result_type;
using return_type = use_future_return_t<traits_type, result_type>;

static std::tuple<callback_type, return_type> traits(const _Token_t& /*没人关心这个变量*/)
static std::tuple<callback_type, return_type> traits(const _Token_as_callable_t& /*没人关心这个变量*/)
{
callback_type callback{};
auto future = callback.get_future();
@@ -305,7 +311,7 @@ struct use_librf_t
template<typename _Result_t>
using future_type = resumef::future_t<_Result_t>;
};
inline constexpr use_librf_t use_librf{};
constexpr use_librf_t use_librf{};

template<typename R, typename... _Result_t>
struct modern_callback_adapter_t<use_librf_t, R(_Result_t...)> : public modern_callback_adapter_impl_t<use_librf_t, _Result_t...>
@@ -318,6 +324,44 @@ struct modern_callback_adapter_t<use_librf_t, R(_Result_t...)> : public modern_c
//----------------------------------------------------------------------------------------------------------------------
//使用范例

//演示异步库有多个异步回调函数,只要按照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(void(decltype(val1 + val2)));

std::thread([=, 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(void(std::exception_ptr, decltype(val1 * val2), decltype(val1 / val2)));

std::thread([=, 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();
}

__declspec(noinline)
void resumable_main_modern_cb()
{
@@ -328,13 +372,14 @@ void resumable_main_modern_cb()
{
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(1s);
std::this_thread::sleep_for(0.5s);
std::cout << "......" << std::endl;

//支持future的用法
@@ -347,8 +392,29 @@ void resumable_main_modern_cb()
//支持librf的用法
GO
{
std::string result = co_await tostring_async(10.0, use_librf);
std::cout << result << std::endl;
try
{
int val = co_await add_async(1, 2, use_librf);

//muldiv_async函数可能会抛异常,取决于val是否是0
//异常将会带回到本协程里的代码,所以需要try-catch
auto ab = co_await muldiv_async(9, val, use_librf);
//C++17:
//auto [a, b] = co_await muldiv_async(9, val, use_librf);

std::string result = co_await tostring_async(std::get<0>(ab) + std::get<1>(ab), use_librf);

std::cout << result << std::endl;
}
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();
}

+ 2
- 2
vs_proj/librf.vcxproj View File

@@ -35,7 +35,7 @@
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v141</PlatformToolset>
<PlatformToolset>v140</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>NotSet</CharacterSet>
</PropertyGroup>
@@ -48,7 +48,7 @@
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v141</PlatformToolset>
<PlatformToolset>v140</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>NotSet</CharacterSet>
</PropertyGroup>

Loading…
Cancel
Save