Browse Source

整理类型萃取代码

when_all/when_any接受functor。functor必须得返回一个awaitor
tags/v2.9.7
tearshark 4 years ago
parent
commit
2d0a597b85

+ 0
- 1
librf/librf.h View File

@@ -48,7 +48,6 @@
#include "src/generator.h"
#include "src/rf_task.h"
#include "src/utils.h"
#include "src/timer.h"
#include "src/scheduler.h"

+ 8
- 7
librf/src/sleep.h View File

@@ -20,27 +20,28 @@ RESUMEF_NS
{
return sleep_for_(std::chrono::duration_cast<std::chrono::system_clock::duration>(dt_), scheduler_);
}
template<class _Rep, class _Period>
inline future_t<> sleep_for(const std::chrono::duration<_Rep, _Period>& dt_)
{
return sleep_for_(std::chrono::duration_cast<std::chrono::system_clock::duration>(dt_), *this_scheduler());
}
template<class _Clock, class _Duration = typename _Clock::duration>
inline future_t<> sleep_until(const std::chrono::time_point<_Clock, _Duration>& tp_, scheduler_t& scheduler_)
{
return sleep_until_(std::chrono::time_point_cast<std::chrono::system_clock::duration>(tp_), scheduler_);
}
template<class _Rep, class _Period>
inline future_t<> sleep_for(const std::chrono::duration<_Rep, _Period>& dt_)
{
co_await sleep_for_(std::chrono::duration_cast<std::chrono::system_clock::duration>(dt_), *current_scheduler());
}
template<class _Clock, class _Duration>
inline future_t<> sleep_until(const std::chrono::time_point<_Clock, _Duration>& tp_)
{
return sleep_until_(std::chrono::time_point_cast<std::chrono::system_clock::duration>(tp_), *this_scheduler());
co_await sleep_until_(std::chrono::time_point_cast<std::chrono::system_clock::duration>(tp_), *current_scheduler());
}
template <class Rep, class Period>
inline future_t<> operator co_await(std::chrono::duration<Rep, Period> dt_)
{
return sleep_for(dt_);
co_await sleep_for(dt_, *current_scheduler());
}
}

+ 64
- 1
librf/src/type_traits.inl View File

@@ -4,10 +4,56 @@ RESUMEF_NS
{
namespace traits
{
//is_coroutine_handle<T>
//is_coroutine_handle_v<T>
//判断是不是coroutine_handle<>类型
//
//is_valid_await_suspend_return_v<T>
//判断是不是awaitor的await_suspend()函数的有效返回值
//
//is_awaitor<T>
//is_awaitor_v<T>
//判断是不是一个awaitor规范。
//一个awaitor可以被co_await操作,要求满足coroutine的awaitor的三个函数接口规范
//
//is_future<T>
//is_future_v<T>
//判断是不是一个librf的future规范。
//future除了要求是一个awaitor外,还要求定义了value_type/state_type/promise_type三个类型,
//并且具备counted_ptr<state_type>类型的_state变量。
//
//is_promise<T>
//is_promise_v<T>
//判断是不是一个librf的promise_t类
//
//is_generator<T>
//is_generator_v<T>
//判断是不是一个librf的generator_t类
//
//has_state<T>
//has_state_v<T>
//判断是否具有_state的成员变量
//
//get_awaitor<T>(T&&t)
//通过T获得其被co_await后的awaitor
//
//awaitor_traits<T>
//获得一个awaitor的特征。
// type:awaitor的类型
// value_type:awaitor::await_resume()的返回值类型
//
//is_callable<T>
//is_callable_v<T>
//判断是不是一个可被调用的类型,如函数,仿函数,lambda等
//
//is_scheduler_task<T>
//is_scheduler_task_v<T>
//判断是不是可以被调度器调度的任务。调度器支持future和callable

template<class _Ty>
struct is_coroutine_handle : std::false_type {};
template<class _PromiseT>
struct is_coroutine_handle<std::experimental::coroutine_handle<_PromiseT>> : std::true_type {};
struct is_coroutine_handle<coroutine_handle<_PromiseT>> : std::true_type {};
template<class _Ty>
constexpr bool is_coroutine_handle_v = is_coroutine_handle<remove_cvref_t<_Ty>>::value;

@@ -116,5 +162,22 @@ RESUMEF_NS
using type = decltype(get_awaitor(std::declval<_Ty>()));
using value_type = decltype(std::declval<type>().await_resume());
};

template<typename _Function>
inline auto _IsCallable(_Function&& _Func, int) -> decltype(_Func(), std::true_type())
{
(_Func);
return std::true_type();
}
template<typename _Function>
inline std::false_type _IsCallable(_Function&&, ...)
{
return std::false_type();
}
template<typename _Function>
using is_callable = decltype(_IsCallable(std::declval<_Function>(), 0));
template<typename _Function>
constexpr bool is_callable_v = is_callable<_Function>::value;

}
}

+ 0
- 17
librf/src/utils.h View File

@@ -4,22 +4,5 @@ RESUMEF_NS
{
namespace traits
{
template<typename _Function>
inline auto _IsCallable(_Function&& _Func, int) -> decltype(_Func(), std::true_type())
{
(_Func);
return std::true_type();
}
template<typename _Function>
inline std::false_type _IsCallable(_Function&&, ...)
{
return std::false_type();
}
template<typename _Function>
using is_callable = decltype(_IsCallable(std::declval<_Function>(), 0));
template<typename _Function>
constexpr bool is_callable_v = is_callable<_Function>::value;
}
}

+ 40
- 18
librf/src/when_v2.h View File

@@ -97,16 +97,37 @@ RESUMEF_NS
using value_type = ignore_type;
};

template<class _Ty, bool = traits::is_callable_v<_Ty>>
struct awaitor_result_impl
{
using value_type = typename convert_void_2_ignore<
typename traits::awaitor_traits<_Ty>::value_type
>::value_type;
};
template<class _Ty>
struct awaitor_result_impl<_Ty, true> : awaitor_result_impl<decltype(std::declval<_Ty>()()), false> {};
template<class _Ty>
using awaitor_result_t = typename awaitor_result_impl<_Ty>::value_type;


template<class _Ty>
using awaitor_result_t = typename convert_void_2_ignore<
typename traits::awaitor_traits<_Ty>::value_type
>::value_type;
struct is_when_task : std::bool_constant<traits::is_awaitor_v<_Ty> || traits::is_callable_v<_Ty>> {};
template<class _Ty>
constexpr bool is_when_task_v = is_when_task<_Ty>::value;

template<class _Awaitable>
decltype(auto) when_real_awaitor(_Awaitable&& awaitor)
{
if constexpr (traits::is_callable_v<_Awaitable>)
return awaitor();
else
return std::forward<_Awaitable>(awaitor);
}

template<class _Awaitable, class _Ty>
future_t<> when_all_connector(state_when_t* state, _Awaitable awaitor, _Ty& value)
future_t<> when_all_connector(state_when_t* state, _Awaitable task, _Ty& value)
{
static_assert(traits::is_awaitor_v<_Awaitable>);
decltype(auto) awaitor = when_real_awaitor(task);

if constexpr(std::is_same_v<_Ty, ignore_type>)
co_await awaitor;
@@ -145,12 +166,13 @@ RESUMEF_NS
using when_any_pair_ptr = std::shared_ptr<when_any_pair>;

template<class _Awaitable>
future_t<> when_any_connector(counted_ptr<state_when_t> state, _Awaitable awaitor, when_any_pair_ptr value, intptr_t idx)
future_t<> when_any_connector(counted_ptr<state_when_t> state, _Awaitable task, when_any_pair_ptr value, intptr_t idx)
{
assert(idx >= 0);
static_assert(traits::is_awaitor_v<_Awaitable>);

using value_type = awaitor_result_t<_Awaitable>;
decltype(auto) awaitor = when_real_awaitor(task);

using value_type = awaitor_result_t<decltype(awaitor)>;

if constexpr (std::is_same_v<value_type, ignore_type>)
{
@@ -183,7 +205,7 @@ RESUMEF_NS
template<class _Awaitable, class... _Rest>
inline void when_any_one__(scheduler_t& sch, state_when_t* state, when_any_pair_ptr value, intptr_t _Idx, _Awaitable&& awaitable, _Rest&&... rest)
{
sch + when_any_connector(state, awaitable, value, _Idx);
sch + when_any_connector(state, std::forward<_Awaitable>(awaitable), value, _Idx);

when_any_one__(sch, state, value, _Idx + 1, std::forward<_Rest>(rest)...);
}
@@ -195,7 +217,7 @@ RESUMEF_NS
intptr_t _Idx = 0;
for (; begin != end; ++begin, ++_Idx)
{
sch + when_any_connector(state, *begin, value, static_cast<intptr_t>(_Idx));
sch + when_any_connector(state, std::move(*begin), value, static_cast<intptr_t>(_Idx));
}
}
}
@@ -203,7 +225,7 @@ RESUMEF_NS
inline namespace when_v2
{
template<class... _Awaitable,
class = std::enable_if_t<std::conjunction_v<traits::is_awaitor<_Awaitable>...>>
class = std::enable_if_t<std::conjunction_v<detail::is_when_task<_Awaitable>...>>
>
auto when_all(scheduler_t& sch, _Awaitable&&... args)
-> detail::when_future_t<std::tuple<detail::awaitor_result_t<_Awaitable>...> >
@@ -218,7 +240,7 @@ inline namespace when_v2

template<class _Iter,
class _Awaitable = decltype(*std::declval<_Iter>()),
class = std::enable_if_t<traits::is_awaitor_v<_Awaitable>>
class = std::enable_if_t<detail::is_when_task_v<_Awaitable>>
>
auto when_all(scheduler_t& sch, _Iter begin, _Iter end)
-> detail::when_future_t<std::vector<detail::awaitor_result_t<_Awaitable> > >
@@ -234,7 +256,7 @@ inline namespace when_v2
}

template<class... _Awaitable,
class = std::enable_if_t<std::conjunction_v<traits::is_awaitor<_Awaitable>...>>
class = std::enable_if_t<std::conjunction_v<detail::is_when_task<_Awaitable>...>>
>
auto when_all(_Awaitable&&... awaitor)
-> future_t<std::tuple<detail::awaitor_result_t<_Awaitable>...>>
@@ -244,7 +266,7 @@ inline namespace when_v2

template<class _Iter,
class _Awaitable = decltype(*std::declval<_Iter>()),
class = std::enable_if_t<traits::is_awaitor_v<_Awaitable>>
class = std::enable_if_t<detail::is_when_task_v<_Awaitable>>
>
auto when_all(_Iter begin, _Iter end)
-> future_t<std::vector<detail::awaitor_result_t<_Awaitable>>>
@@ -258,7 +280,7 @@ inline namespace when_v2


template<class... _Awaitable,
class = std::enable_if_t<std::conjunction_v<traits::is_awaitor<_Awaitable>...>>
class = std::enable_if_t<std::conjunction_v<detail::is_when_task<_Awaitable>...>>
>
auto when_any(scheduler_t& sch, _Awaitable&&... args)
-> detail::when_future_t<detail::when_any_pair>
@@ -272,7 +294,7 @@ inline namespace when_v2

template<class _Iter,
typename _Awaitable = decltype(*std::declval<_Iter>()),
class = std::enable_if_t<traits::is_awaitor_v<_Awaitable>>
class = std::enable_if_t<detail::is_when_task_v<_Awaitable>>
>
auto when_any(scheduler_t& sch, _Iter begin, _Iter end)
-> detail::when_future_t<detail::when_any_pair>
@@ -285,7 +307,7 @@ inline namespace when_v2
}

template<class... _Awaitable,
class = std::enable_if_t<std::conjunction_v<traits::is_awaitor<_Awaitable>...>>
class = std::enable_if_t<std::conjunction_v<detail::is_when_task<_Awaitable>...>>
>
auto when_any(_Awaitable&&... awaitor)
-> future_t<detail::when_any_pair>
@@ -295,7 +317,7 @@ inline namespace when_v2

template<class _Iter,
typename _Awaitable = decltype(*std::declval<_Iter>()),
class = std::enable_if_t<traits::is_awaitor_v<_Awaitable>>
class = std::enable_if_t<detail::is_when_task_v<_Awaitable>>
>
auto when_any(_Iter begin, _Iter end)
-> future_t<detail::when_any_pair>

+ 32
- 8
tutorial/test_async_when_all.cpp View File

@@ -28,26 +28,26 @@ void test_when_any()
std::cout << dt << "@a" << std::endl;
co_return dt;
}(),
},
[]() ->future_t<>
{
auto dt = rand() % 1000;
co_await sleep_for(1ms * dt);
std::cout << dt << "@b" << std::endl;
}(),
},
[]() ->future_t<>
{
auto dt = rand() % 1000;
co_await sleep_for(1ms * dt);
std::cout << dt << "@c" << std::endl;
}());
});
if (vals.first == 0)
std::cout << "first done! value is " << resumef::any_cast<int>(vals.second) << std::endl;
else
std::cout << "any done! index is " << vals.first << std::endl;
co_await sleep_for(1010ms);
co_await 1010ms;
std::cout << std::endl;
auto my_sleep = [](const char * name) -> future_t<int>
@@ -92,20 +92,44 @@ void test_when_all()
co_await when_all();
std::cout << "when all: zero!" << std::endl << std::endl;
auto vals1 = co_await when_all(
[]() ->future_t<int>
{
auto dt = rand() % 1000;
co_await sleep_for(1ms * dt);
std::cout << dt << "@i" << std::endl;
co_return dt;
},
[]() ->future_t<>
{
auto dt = rand() % 1000;
co_await sleep_for(1ms * dt);
std::cout << dt << "@j" << std::endl;
},
[]() ->future_t<>
{
auto dt = rand() % 1000;
co_await sleep_for(1ms * dt);
std::cout << dt << "@k" << std::endl;
});
std::cout << "when all - 1:" << std::get<0>(vals1) << std::endl << std::endl;
auto ab = co_await when_all(my_sleep("a"), my_sleep_v("b"));
//ab.1 is std::ignore
std::cout << "when all:" << std::get<0>(ab) << std::endl << std::endl;
std::cout << "when all - 2:" << std::get<0>(ab) << std::endl << std::endl;
auto c = co_await my_sleep("c");
std::cout << "when all:" << c << std::endl << std::endl;
std::cout << "when all - 3:" << c << std::endl << std::endl;
auto def = co_await when_all(my_sleep("d"), my_sleep_v("e"), my_sleep("f"));
//def.1 is std::ignore
std::cout << "when all:" << std::get<0>(def) << "," << std::get<2>(def) << std::endl << std::endl;
std::cout << "when all - 4:" << std::get<0>(def) << "," << std::get<2>(def) << std::endl << std::endl;
std::vector<future_t<int> > v{ my_sleep("g"), my_sleep("h"), my_sleep("i") };
auto vals = co_await when_all(std::begin(v), std::end(v));
std::cout << "when all:" << vals[0] << "," << vals[1] << "," << vals[2] << "," << std::endl << std::endl;
std::cout << "when all - 5:" << vals[0] << "," << vals[1] << "," << vals[2] << "," << std::endl << std::endl;
std::cout << "all range done!" << std::endl;
};

+ 0
- 1
vs_proj/librf.vcxproj View File

@@ -247,7 +247,6 @@
<ClInclude Include="..\librf\src\timer.h" />
<ClInclude Include="..\librf\src\unix\clang_builtin.h" />
<ClInclude Include="..\librf\src\unix\coroutine.h" />
<ClInclude Include="..\librf\src\utils.h" />
<ClInclude Include="..\librf\src\when.h" />
<ClInclude Include="..\librf\src\when_v2.h" />
<ClInclude Include="..\librf\src\_awaker.h" />

+ 0
- 3
vs_proj/librf.vcxproj.filters View File

@@ -165,9 +165,6 @@
<ClInclude Include="..\librf\src\timer.h">
<Filter>librf\src</Filter>
</ClInclude>
<ClInclude Include="..\librf\src\utils.h">
<Filter>librf\src</Filter>
</ClInclude>
<ClInclude Include="..\librf\src\unix\coroutine.h">
<Filter>librf\src\unix</Filter>
</ClInclude>

Loading…
Cancel
Save