瀏覽代碼

优化Modern Callback范例,使得modern_callback_adapter_t更加通用并简化使用

tags/v2.9.7
tearshark 5 年之前
父節點
當前提交
04d1d2ea1f
共有 6 個檔案被更改,包括 277 行新增155 行删除
  1. 2
    0
      .gitignore
  2. 26
    26
      librf/src/asio_task_1.12.0.inl
  3. 10
    0
      librf/src/future.h
  4. 232
    124
      tutorial/test_async_modern_cb.cpp
  5. 3
    1
      vs_proj/librf.cpp
  6. 4
    4
      vs_proj/librf.vcxproj

+ 2
- 0
.gitignore 查看文件

@@ -6,3 +6,5 @@
/vs_proj/.vs
/vs_proj/librf.vcxproj.user
/.vs
/vs_proj/Release
/vs_proj/Debug

+ 26
- 26
librf/src/asio_task_1.12.0.inl 查看文件

@@ -21,31 +21,31 @@ namespace asio {
namespace librf {

template <typename Executor, typename T>
struct awaitable_handler_base
struct promise_handler_base
{
public:
typedef T result_type;
typedef resumef::state_t<result_type> state_type;

awaitable_handler_base()
promise_handler_base()
: state_(resumef::make_counted<state_type>())
{
}
{
}

resumef::counted_ptr<state_type> state_;
awaitable_handler_base(awaitable_handler_base &&) = default;
awaitable_handler_base(const awaitable_handler_base &) = default;
awaitable_handler_base & operator = (awaitable_handler_base &&) = default;
awaitable_handler_base & operator = (const awaitable_handler_base &) = default;
promise_handler_base(promise_handler_base &&) = default;
promise_handler_base(const promise_handler_base &) = default;
promise_handler_base & operator = (promise_handler_base &&) = default;
promise_handler_base & operator = (const promise_handler_base &) = default;
};

template <typename, typename...>
struct promise_handler;

template <typename Executor>
struct promise_handler<Executor, void> : public awaitable_handler_base<Executor, void>
struct promise_handler<Executor, void> : public promise_handler_base<Executor, void>
{
using awaitable_handler_base<Executor, void>::awaitable_handler_base;
using promise_handler_base<Executor, void>::promise_handler_base;

void operator()() const
{
@@ -54,9 +54,9 @@ namespace asio {
};

template <typename Executor>
struct promise_handler<Executor, asio::error_code> : public awaitable_handler_base<Executor, void>
struct promise_handler<Executor, asio::error_code> : public promise_handler_base<Executor, void>
{
using awaitable_handler_base<Executor, void>::awaitable_handler_base;
using promise_handler_base<Executor, void>::promise_handler_base;

void operator()(const asio::error_code& ec) const
{
@@ -68,9 +68,9 @@ namespace asio {
};

template <typename Executor>
struct promise_handler<Executor, std::exception_ptr> : public awaitable_handler_base<Executor, void>
struct promise_handler<Executor, std::exception_ptr> : public promise_handler_base<Executor, void>
{
using awaitable_handler_base<Executor, void>::awaitable_handler_base;
using promise_handler_base<Executor, void>::promise_handler_base;

void operator()(std::exception_ptr ex) const
{
@@ -84,9 +84,9 @@ namespace asio {


template <typename Executor, typename T>
struct promise_handler<Executor, T> : public awaitable_handler_base<Executor, T>
struct promise_handler<Executor, T> : public promise_handler_base<Executor, T>
{
using awaitable_handler_base<Executor, T>::awaitable_handler_base;
using promise_handler_base<Executor, T>::promise_handler_base;

template <typename Arg>
void operator()(Arg&& arg) const
@@ -96,9 +96,9 @@ namespace asio {
};

template <typename Executor, typename T>
struct promise_handler<Executor, asio::error_code, T> : public awaitable_handler_base<Executor, T>
struct promise_handler<Executor, asio::error_code, T> : public promise_handler_base<Executor, T>
{
using awaitable_handler_base<Executor, T>::awaitable_handler_base;
using promise_handler_base<Executor, T>::promise_handler_base;

template <typename Arg>
void operator()(const asio::error_code& ec, Arg&& arg) const
@@ -111,9 +111,9 @@ namespace asio {
};

template <typename Executor, typename T>
struct promise_handler<Executor, std::exception_ptr, T> : public awaitable_handler_base<Executor, T>
struct promise_handler<Executor, std::exception_ptr, T> : public promise_handler_base<Executor, T>
{
using awaitable_handler_base<Executor, T>::awaitable_handler_base;
using promise_handler_base<Executor, T>::promise_handler_base;

template <typename Arg>
void operator()(std::exception_ptr ex, Arg&& arg) const
@@ -128,9 +128,9 @@ namespace asio {


template <typename Executor, typename... Ts>
struct promise_handler : public awaitable_handler_base<Executor, std::tuple<Ts...>>
struct promise_handler : public promise_handler_base<Executor, std::tuple<Ts...>>
{
using awaitable_handler_base<Executor, std::tuple<Ts...>>::awaitable_handler_base;
using promise_handler_base<Executor, std::tuple<Ts...>>::promise_handler_base;

template <typename... Args>
void operator()(Args&&... args) const
@@ -140,9 +140,9 @@ namespace asio {
};

template <typename Executor, typename... Ts>
struct promise_handler<Executor, asio::error_code, Ts...> : public awaitable_handler_base<Executor, std::tuple<Ts...>>
struct promise_handler<Executor, asio::error_code, Ts...> : public promise_handler_base<Executor, std::tuple<Ts...>>
{
using awaitable_handler_base<Executor, std::tuple<Ts...>>::awaitable_handler_base;
using promise_handler_base<Executor, std::tuple<Ts...>>::promise_handler_base;

template <typename... Args>
void operator()(const asio::error_code& ec, Args&&... args) const
@@ -155,9 +155,9 @@ namespace asio {
};

template <typename Executor, typename... Ts>
struct promise_handler<Executor, std::exception_ptr, Ts...> : public awaitable_handler_base<Executor, std::tuple<Ts...>>
struct promise_handler<Executor, std::exception_ptr, Ts...> : public promise_handler_base<Executor, std::tuple<Ts...>>
{
using awaitable_handler_base<Executor, std::tuple<Ts...>>::awaitable_handler_base;
using promise_handler_base<Executor, std::tuple<Ts...>>::promise_handler_base;

template <typename... Args>
void operator()(std::exception_ptr ex, Args&&... args) const

+ 10
- 0
librf/src/future.h 查看文件

@@ -276,6 +276,16 @@ namespace resumef
//以上是与编译器生成的resumable function交互的接口
//------------------------------------------------------------------------------------------
//兼容std::promise<>用法
void set_value(const T& val)
{
_state->set_value(val);
}
void set_value(T&& val)
{
_state->set_value(std::forward<T>(val));
}
};
template <>

+ 232
- 124
tutorial/test_async_modern_cb.cpp 查看文件

@@ -7,240 +7,348 @@
#include <thread>
#include <future>

//原旨主义的异步函数,其回调写法大致如下
template<typename _Input_t, typename _Callable_t>
__declspec(noinline)
void tostring_async_originalism(_Input_t&& value, _Callable_t&& callback)
void tostring_async_originalism(_Input_t&& value, _Callable_t&& token)
{
std::thread([callback = std::move(callback), value = std::forward<_Input_t>(value)]
std::thread([callback = std::move(token), value = std::forward<_Input_t>(value)]
{
callback(std::to_string(value));
}).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);
}

//----------------------------------------------------------------------------------------------------------------------
//以下演示如何通过现代回调(Modern Callback), 使用回调适配器模型,
//将异步回调函数扩展到支持future模式,调用链模式,以及协程。

//首先,准备modern_call_return_void_t和modern_callback_adapter_t给异步函数使用

//通过一个间接的类来解决返回void的语法问题,以便于优化返回值
struct modern_call_return_void_t
{
void get(){}
};

//回调适配器的模板类
//这个默认类以_Callable_t作为真正的回调
//返回无意义的int,以便于编译通过
template<typename _Callable_t, typename _Result_t>
//_Callable_t 要符合 _Signature_t 签名
//这个类除了转移token外,不做任何有效的工作
//有效工作等待特列化的类去做
template<typename _Callable_t, typename _Signature_t>
struct modern_callback_adapter_t
{
using return_type = int;
using callback_type = _Callable_t;
using return_type = modern_call_return_void_t;

static std::tuple<callback_type, return_type> traits(_Callable_t&& callback)
static std::tuple<callback_type, return_type> traits(_Callable_t&& token)
{
return { std::forward<_Callable_t>(callback), 0 };
return { std::forward<_Callable_t>(token), {} };
}
};

#define MODERN_CALLBACK_TRAITS(type) \
using _Result_t = type; \
using _Adapter_t = modern_callback_adapter_t<std::decay_t<_Callable_t>, _Result_t>; \
auto adapter = typename _Adapter_t::traits(std::forward<_Callable_t>(callback))
#define MODERN_CALLBACK_CALL() callback = std::move(std::get<0>(adapter))
#define MODERN_CALLBACK_RETURN() return std::move(std::get<1>(adapter))

template<typename _Input_t, typename _Callable_t>
auto tostring_async_macro(_Input_t&& value, _Callable_t&& callback)
{
MODERN_CALLBACK_TRAITS(std::string);

std::thread([MODERN_CALLBACK_CALL(), value = std::forward<_Input_t>(value)]
{
callback(std::to_string(value));
}).detach();

MODERN_CALLBACK_RETURN();
}

//演示如何通过回调适配器模型,将异步回调,扩展到支持future模式,调用链模式,以及协程。
//
//一个使用回调处理结果的异步函数,会涉及五个概念:
//一个使用回调处理结果的异步函数,会涉及以下概念:
//_Input_t:异步函数的输入参数;
//_Callable_t:回调函数,这个回调,必须调用一次,且只能调用一次;
//_Signature_t: 此异步回调的函数签名;应当满足‘void(_Exception_t, _Result_t...)’或者‘void(_Result_t...)’类型;
//_Callable_t:回调函数或标记,如果是回调函数,则需要符合_Signature_t的签名类型。这个回调,必须调用一次,且只能调用一次;
//_Return_t:异步函数的返回值;
//_Result_t:异步函数完成后的结果值,作为回调函数的入参部分;这个参数可以有零至多个;
//_Result_t...:异步函数完成后的结果值,作为回调函数的入参部分;这个参数可以有零至多个;
//_Exception_t:回调函数的异常, 如果不喜欢异常的则忽略这个部分,但就得异步代码将异常处置妥当;
//
//在回调适配器模型里,_Input_t/_Result_t/_Exception_t(可选)是异步函数提供的功能所固有的部分;_Callable_t/_Return_t
//部分并不直接使用,而是通过适配器去另外处理。这样给予适配器一次扩展到future模式,调用链模式的机会,以及支持协程的机会。
//
//tostring_async 演示了在其他线程里,将_Input_t的输入值,转化为std::string类型的_Result_t。
//然后调用void(std::string &&)类型的_Callable_t。忽视异常处理。
//然后调用_Signature_t为 ‘void(std::string &&)’ 类型的 _Callable_t。
//忽视异常处理,故没有_Exception_t。
//
template<typename _Input_t, typename _Callable_t>
__declspec(noinline)
auto tostring_async(_Input_t&& value, _Callable_t&& callback)
//-> typename modern_callback_adapter_t<std::decay_t<_Callable_t>, std::string>::return_type
auto tostring_async(_Input_t&& value, _Callable_t&& token)
{
using _Result_t = std::string;
//适配器类型
using _Adapter_t = modern_callback_adapter_t<std::decay_t<_Callable_t>, _Result_t>;
//通过适配器获得兼容_Callable_t类型的真正的回调,以及返回值_Return_t
auto adapter = typename _Adapter_t::traits(std::forward<_Callable_t>(callback));
using _Adapter_t = modern_callback_adapter_t<std::decay_t<_Callable_t>, void(std::string)>;
//通过适配器获得兼容_Signature_t类型的真正的回调,以及返回值_Return_t
auto adapter = typename _Adapter_t::traits(std::forward<_Callable_t>(token));

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

//返回适配器的return_type变量
return std::move(std::get<1>(adapter));
//返回适配器的_Return_t变量
return std::move(std::get<1>(adapter)).get();
}

template<typename _Input_t>
auto tostring_async_future(_Input_t&& value)
//或者宏版本写法
#define MODERN_CALLBACK_TRAITS(signature) \
using _Adapter_t = modern_callback_adapter_t<std::decay_t<_Callable_t>, void(std::string)>; \
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()

template<typename _Input_t, typename _Callable_t>
auto tostring_async_macro(_Input_t&& value, _Callable_t&& callback)
{
std::promise<std::string> _promise;
std::future<std::string> _future = _promise.get_future();
MODERN_CALLBACK_TRAITS(void(std::string));

std::thread([_promise = std::move(_promise), value = std::forward<_Input_t>(value)]() mutable
std::thread([MODERN_CALLBACK_CALL(), value = std::forward<_Input_t>(value)]
{
_promise.set_value(std::to_string(value));
callback(std::to_string(value));
}).detach();

return std::move(_future);
MODERN_CALLBACK_RETURN();
}

//-------------------------------------------------------------------------------------------------
//----------------------------------------------------------------------------------------------------------------------
//下面演示如何扩展tostring_async函数,以支持future模式
//future库有多种,但应当都提供遵循promise/future对,兼容std::promise/std::future用法
//这样的话,可以做一个更加通用的支持future的callback类

//一、做一个辅助类
struct use_future_t {};
//二、申明这个辅助类的全局变量。不什么这个变量也行,就是每次要写use_future_t{},麻烦些
//以后就使用use_future,替代tostring_async的callback参数了。
//这个参数其实不需要实质传参,最后会被编译器优化没了。
//仅仅是要指定_Callable_t的类型为use_future_t,
//从而在tostring_async函数内,使用偏特化的modern_callback_adapter_t<use_future_t, ...>而已。
inline constexpr use_future_t use_future{};
//实现use_future_callback_t的基类,避免写一些重复代码
template<typename _Promise_traits, typename _Result_t>
struct use_future_callback_base_t
{
//回调函数的结果类型,已经排除掉了异常参数
using result_type = _Result_t;

//通过_Promise_traits获取真正的promise类型
using promise_type = typename _Promise_traits::template promise_type<result_type>;

//将替换use_future_t的,真正的回调类。
//此回调类,符合tostring_async的_Callable_t函数签名。生成此类的实例作为real_callback交给tostring_async作为异步回调。
//此类持有一个std::promise<_Result_t>,便于设置值和异常
//而将与promise关联的future作为返回值_Return_t,让tostring_async返回。
mutable promise_type _promise;

auto get_future() const
{
return _promise.get_future();
}
};

//此类的实例作为真正的callback,交给异步回调函数,替换token。
//在实际应用中,需要针对是否有异常参数,结果值为0,1,多个等情况做特殊处理,故还需要通过更多的偏特化版本来支持。
//具体的异常参数,需要根据实际应用去特里化。这里仅演示通过std::exception_ptr作为异常传递的情况。
//
//future模式下,此类持有一个std::promise<_Result_t>,便于设置值和异常
//而将与promise关联的future作为返回值_Return_t,让tostring_async返回。
template<typename _Result_t>
struct use_future_callback_t
//无异常,多结果的callback类型:void(_Result_t...)
template<typename _Promise_traits, typename... _Result_t>
struct use_future_callback_t : public use_future_callback_base_t<_Promise_traits, std::tuple<_Result_t...> >
{
using promise_type = std::promise<_Result_t>;
using use_future_callback_base_t<_Promise_traits, std::tuple<_Result_t...> >::use_future_callback_base_t;

mutable promise_type _promise;
template <typename... Args>
void operator()(Args&&... args) const
{
_promise.set_value(std::make_tuple(std::forward<Args>(args)...));
}
};

//有异常,多结果的callback类型:void(std::exception_ptr, _Result_t...)
template <typename _Promise_traits, typename... _Result_t>
struct use_future_callback_t<_Promise_traits, std::exception_ptr, _Result_t...> : public use_future_callback_base_t<_Promise_traits, std::tuple<_Result_t...> >
{
using use_future_callback_base_t<_Promise_traits, std::tuple<_Result_t...> >::use_future_callback_base_t;

template <typename... Args>
void operator()(std::exception_ptr eptr, Args&&... args) const
{
if (!eptr)
_promise.set_value(std::make_tuple(std::forward<Args>(args)...));
else
_promise.set_exception(std::move(eptr));
}
};

//无异常,无结果的callback类型:void()
template<typename _Promise_traits>
struct use_future_callback_t<_Promise_traits> : public use_future_callback_base_t<_Promise_traits, void>
{
using use_future_callback_base_t<_Promise_traits, void>::use_future_callback_base_t;

void operator()(_Result_t&& value) const
void operator()() const
{
_promise.set_value(value);
_promise.set_value();
}
};

//有异常,无结果的callback类型:void(exception_ptr)
template<typename _Promise_traits>
struct use_future_callback_t<_Promise_traits, std::exception_ptr> : public use_future_callback_base_t<_Promise_traits, void>
{
using use_future_callback_base_t<_Promise_traits, void>::use_future_callback_base_t;

void operator()(_Result_t&& value, std::exception_ptr&& eptr) const
void operator()(std::exception_ptr eptr) const
{
if (eptr != nullptr)
_promise.set_exception(std::forward<std::exception_ptr>(eptr));
if (!eptr)
_promise.set_value();
else
_promise.set_value(std::forward<_Result_t>(value));
_promise.set_exception(std::move(eptr));
}
};

//偏特化_Callable_t为use_future_t类型的modern_callback_adapter_t
//真正的回调类型是use_future_callback_t,返回类型_Return_t是std::future<_Result_t>。
//配合use_future_callback_t的std::promise<_Result_t>,正好组成一对promise/future对。
//promise在真正的回调里设置结果值;
//future返回给调用者获取结果值。
template<typename _Result_t>
struct modern_callback_adapter_t<use_future_t, _Result_t>
//无异常,单结果的callback类型:void(_Result_t)
template<typename _Promise_traits, typename _Result_t>
struct use_future_callback_t<_Promise_traits, _Result_t> : public use_future_callback_base_t<_Promise_traits, _Result_t>
{
using return_type = std::future<_Result_t>;
using callback_type = use_future_callback_t<_Result_t>;
using use_future_callback_base_t<_Promise_traits, _Result_t>::use_future_callback_base_t;

static std::tuple<callback_type, return_type> traits(const use_future_t&/*没人关心这个变量*/)
void operator()(result_type && arg) const
{
callback_type real_callback{};
return_type future = real_callback._promise.get_future();
_promise.set_value(std::forward<result_type>(arg));
}
};

return { std::move(real_callback), std::move(future) };
//有异常,单结果的callback类型:void(std::exception_ptr, _Result_t)
template<typename _Promise_traits, typename _Result_t>
struct use_future_callback_t<_Promise_traits, std::exception_ptr, _Result_t> : public use_future_callback_base_t<_Promise_traits, _Result_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
{
if (!eptr)
_promise.set_value(std::forward<result_type>(arg));
else
_promise.set_exception(std::move(eptr));
}
};

//-------------------------------------------------------------------------------------------------

//同理,可以制作支持C++20的协程的下列一系列类(其实,这才是我的最终目的)
struct use_awaitable_t {};
inline constexpr use_awaitable_t use_awaitable{};

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

resumef::counted_ptr<state_type> _state;
use_future_return_t(future_type && ft)
: _future(std::move(ft)) {}

void operator()(_Result_t&& value) const
future_type get()
{
_state->set_value(std::forward<_Result_t>(value));
return std::move(_future);
}
void operator()(_Result_t&& value, std::exception_ptr&& eptr) const
};

//----------------------------------------------------------------------------------------------------------------------

//一、做一个使用std::promise/std::future的辅助类。
//这个类还负责萃取promise/future对的类型。
struct std_future_t
{
template<typename _Result_t>
using promise_type = std::promise<_Result_t>;

template<typename _Result_t>
using future_type = std::future<_Result_t>;
};

//二、申明这个辅助类的全局变量。不申明这个变量也行,就是每次要写use_future_t{},麻烦些。
//以后就使用std_future,替代tostring_async的token参数了。
//这个参数其实不需要实质传参,最后会被编译器优化没了。
//仅仅是要指定_Callable_t的类型为std_future_t,
//从而在tostring_async函数内,使用偏特化的modern_callback_adapter_t<std_future_t, ...>而已。
constexpr std_future_t std_future{};

//三、特例化的modern_callback_adapter_t的实现类
template<typename _Token_t, typename... _Result_t>
struct modern_callback_adapter_impl_t
{
using traits_type = _Token_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& /*没人关心这个变量*/)
{
if (eptr != nullptr)
_state->set_exception(std::forward<std::exception_ptr>(eptr));
else
_state->set_value(std::forward<_Result_t>(value));
callback_type callback{};
auto future = callback.get_future();
return { std::move(callback), std::move(future) };
}
};

template<typename _Result_t>
struct modern_callback_adapter_t<use_awaitable_t, _Result_t>
//四、偏特化_Callable_t为std_future_t类型的modern_callback_adapter_t
//真正的回调类型是use_future_callback_t,返回类型_Return_t是use_future_return_t。
//配合use_future_callback_t的promise<result_type>,和use_future_return_t的future<result_type>,正好组成一对promise/future对。
//promise在真正的回调里设置结果值;
//future返回给调用者获取结果值。
template<typename R, typename... _Result_t>
struct modern_callback_adapter_t<std_future_t, R(_Result_t...)> : public modern_callback_adapter_impl_t<std_future_t, _Result_t...>
{
};

//----------------------------------------------------------------------------------------------------------------------
//同理,可以制作支持C++20的协程的下列一系列类(其实,这才是我的最终目的)
struct use_librf_t
{
template<typename _Result_t>
using promise_type = resumef::promise_t<_Result_t>;
using return_type = resumef::future_t<_Result_t>;
using callback_type = use_awaitable_callback_t<_Result_t>;

static std::tuple<callback_type, return_type> traits(const use_awaitable_t&)
{
promise_type promise;
template<typename _Result_t>
using future_type = resumef::future_t<_Result_t>;
};
inline constexpr use_librf_t use_librf{};

return { callback_type{ promise._state }, promise.get_future() };
}
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...>
{
};

//所以,我现在的看法是,支持异步操作的库,尽可能如此设计回调。这样便于支持C++20的协程。以及future::then这样的任务链。
//这才是“摩登C++”!


//----------------------------------------------------------------------------------------------------------------------
//使用范例

__declspec(noinline)
void resumable_main_modern_cb()
{
using namespace std::literals;

//使用lambda作为异步回调函数,传统用法
//tostring_async_originalism(-1.0, [](std::string && value)
// {
// std::cout << value << std::endl;
// });
tostring_async_originalism(-1.0, [](std::string && value)
{
std::cout << value << std::endl;
});

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

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

//支持future的用法
std::future<std::string> f1 = tostring_async_future(5);
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, use_future);
std::future<std::string> f2 = tostring_async(6.0f, std_future);
std::cout << f2.get() << std::endl;


//支持librf的用法
GO
{
std::string result = co_await tostring_async(10.0, use_awaitable);
std::string result = co_await tostring_async(10.0, use_librf);
std::cout << result << std::endl;
};
resumef::this_scheduler()->run_until_notask();
*/
}

+ 3
- 1
vs_proj/librf.cpp 查看文件

@@ -25,12 +25,14 @@ extern void resumable_main_benchmark_asio_client(intptr_t nNum);
int main(int argc, const char * argv[])
{
//resumable_main_modern_cb();
resumable_main_modern_cb();
//resumable_main_benchmark_mem();
/*
if (argc > 1)
resumable_main_benchmark_asio_client(atoi(argv[1]));
else
resumable_main_benchmark_asio_server();
*/
return 0;
resumable_main_when_all();

+ 4
- 4
vs_proj/librf.vcxproj 查看文件

@@ -88,9 +88,9 @@
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<Optimization>Disabled</Optimization>
<PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;ASIO_STANDALONE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;ASIO_STANDALONE;_SILENCE_CXX17_ALLOCATOR_VOID_DEPRECATION_WARNING=1;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<SDLCheck>true</SDLCheck>
<AdditionalIncludeDirectories>..\librf;..\..\asio-1.10.6\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<AdditionalIncludeDirectories>..\librf;..\..\asio\asio\include;..\..\asio-1.10.6\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<AdditionalOptions>/await</AdditionalOptions>
<MultiProcessorCompilation>true</MultiProcessorCompilation>
<LanguageStandard>stdcpplatest</LanguageStandard>
@@ -126,10 +126,10 @@
<Optimization>Full</Optimization>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;ASIO_STANDALONE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;ASIO_STANDALONE;_SILENCE_CXX17_ALLOCATOR_VOID_DEPRECATION_WARNING=1;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<SDLCheck>
</SDLCheck>
<AdditionalIncludeDirectories>..\librf;..\..\asio-1.10.6\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<AdditionalIncludeDirectories>..\librf;..\..\asio\asio\include;..\..\asio-1.10.6\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<AdditionalOptions>/await</AdditionalOptions>
<MultiProcessorCompilation>true</MultiProcessorCompilation>
<LanguageStandard>stdcpplatest</LanguageStandard>

Loading…
取消
儲存