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

void reset_none_lock() void reset_none_lock()
{ {
scoped_lock<lock_type> __guard(_mtx);
_coro = nullptr; _coro = nullptr;
_ready = false; _ready = false;
} }

+ 82
- 16
tutorial/test_async_modern_cb.cpp View File

//callback与token未必是同一个变量,甚至未必是同一个类型 //callback与token未必是同一个变量,甚至未必是同一个类型
std::thread([callback = std::move(std::get<0>(adapter)), value = std::forward<_Input_t>(value)] 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)); callback(std::to_string(value));
}).detach(); }).detach();




//或者宏版本写法 //或者宏版本写法
#define MODERN_CALLBACK_TRAITS(signature) \ #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)) 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_CALL() callback = std::move(std::get<0>(adapter))
#define MODERN_CALLBACK_RETURN() return std::move(std::get<1>(adapter)).get() #define MODERN_CALLBACK_RETURN() return std::move(std::get<1>(adapter)).get()
{ {
using use_future_callback_base_t<_Promise_traits, std::tuple<_Result_t...> >::use_future_callback_base_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()(Args&&... args) const void operator()(Args&&... args) const
{ {
static_assert(sizeof...(Args) == sizeof...(_Result_t), "");
_promise.set_value(std::make_tuple(std::forward<Args>(args)...)); _promise.set_value(std::make_tuple(std::forward<Args>(args)...));
} }
}; };
{ {
using use_future_callback_base_t<_Promise_traits, std::tuple<_Result_t...> >::use_future_callback_base_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 void operator()(std::exception_ptr eptr, Args&&... args) const
{ {
static_assert(sizeof...(Args) == sizeof...(_Result_t), "");
if (!eptr) if (!eptr)
_promise.set_value(std::make_tuple(std::forward<Args>(args)...)); _promise.set_value(std::make_tuple(std::forward<Args>(args)...));
else else
{ {
using use_future_callback_base_t<_Promise_traits, _Result_t>::use_future_callback_base_t; 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));
} }
}; };


{ {
using use_future_callback_base_t<_Promise_traits, _Result_t>::use_future_callback_base_t; 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) if (!eptr)
_promise.set_value(std::forward<result_type>(arg));
_promise.set_value(std::forward<Arg>(arg));
else else
_promise.set_exception(std::move(eptr)); _promise.set_exception(std::move(eptr));
} }




//与use_future_callback_t配套的获得_Return_t的类 //与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 struct use_future_return_t
{ {
using result_type = _Result_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; future_type _future;


use_future_return_t(future_type && ft) use_future_return_t(future_type && ft)
constexpr std_future_t std_future{}; constexpr std_future_t std_future{};


//三、特例化的modern_callback_adapter_t的实现类 //三、特例化的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 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 callback_type = use_future_callback_t<traits_type, _Result_t...>;
using result_type = typename callback_type::result_type; using result_type = typename callback_type::result_type;
using return_type = use_future_return_t<traits_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{}; callback_type callback{};
auto future = callback.get_future(); auto future = callback.get_future();
template<typename _Result_t> template<typename _Result_t>
using future_type = resumef::future_t<_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> 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...> struct modern_callback_adapter_t<use_librf_t, R(_Result_t...)> : public modern_callback_adapter_impl_t<use_librf_t, _Result_t...>
//---------------------------------------------------------------------------------------------------------------------- //----------------------------------------------------------------------------------------------------------------------
//使用范例 //使用范例


//演示异步库有多个异步回调函数,只要按照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) __declspec(noinline)
void resumable_main_modern_cb() void resumable_main_modern_cb()
{ {
{ {
std::cout << value << std::endl; std::cout << value << std::endl;
}); });
std::this_thread::sleep_for(0.5s);


tostring_async(1.0, [](std::string && value) tostring_async(1.0, [](std::string && value)
{ {
std::cout << value << std::endl; std::cout << value << std::endl;
}); });


std::this_thread::sleep_for(1s);
std::this_thread::sleep_for(0.5s);
std::cout << "......" << std::endl; std::cout << "......" << std::endl;


//支持future的用法 //支持future的用法
//支持librf的用法 //支持librf的用法
GO 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(); resumef::this_scheduler()->run_until_notask();
} }

+ 2
- 2
vs_proj/librf.vcxproj View File

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

Loading…
Cancel
Save