Browse Source

解决vector<bool>导致的问题

启用event_v2版本代码
event_v2尽量兼容event_v1用法
tags/v2.9.7
tearshark 4 years ago
parent
commit
6c9110a3e4

+ 1
- 1
librf/src/def.h View File

@@ -1,6 +1,6 @@
#pragma once
#define LIB_RESUMEF_VERSION 20600 // 2.6.0
#define LIB_RESUMEF_VERSION 20700 // 2.7.0
#if defined(RESUMEF_MODULE_EXPORT)
#define RESUMEF_NS export namespace resumef

+ 1
- 1
librf/src/event_v1.cpp View File

@@ -59,7 +59,7 @@ RESUMEF_NS

}

inline namespace event_v1
namespace event_v1
{
event_t::event_t(intptr_t initial_counter_)
: _event(std::make_shared<detail::event_impl>(initial_counter_))

+ 1
- 1
librf/src/event_v1.h View File

@@ -40,7 +40,7 @@ RESUMEF_NS
};
}

inline namespace event_v1
namespace event_v1
{

//提供一种在协程和非协程之间同步的手段。

+ 1
- 1
librf/src/event_v2.cpp View File

@@ -104,7 +104,7 @@ RESUMEF_NS
}
}

namespace event_v2
inline namespace event_v2
{
event_t::event_t(bool initially)
:_event(std::make_shared<detail::event_v2_impl>(initially))

+ 105
- 16
librf/src/event_v2.h View File

@@ -7,7 +7,7 @@ RESUMEF_NS
struct event_v2_impl;
}

namespace event_v2
inline namespace event_v2
{
struct event_t
{
@@ -22,6 +22,7 @@ RESUMEF_NS
void reset() const noexcept;

struct [[nodiscard]] awaiter;

awaiter operator co_await() const noexcept;
awaiter wait() const noexcept;

@@ -31,25 +32,113 @@ RESUMEF_NS
timeout_awaiter wait_for(const std::chrono::duration<_Rep, _Period>& dt) const noexcept;
template<class _Clock, class _Duration>
timeout_awaiter wait_until(const std::chrono::time_point<_Clock, _Duration>& tp) const noexcept;





template<_IteratorT _Iter
COMMA_RESUMEF_ENABLE_IF(traits::is_iterator_v<_Iter> && std::is_same_v<event_t&, decltype(*std::declval<_Iter>())>)
>
static future_t<intptr_t>
wait_any(_Iter begin_, _Iter end_)
{
when_any_pair idx = co_await when_any(begin_, end_);
co_return idx.first;
}

template<class _Cont
COMMA_RESUMEF_ENABLE_IF(traits::is_container_v<_Cont>)
>
static future_t<intptr_t>
wait_any(_Cont& cnt_)
{
when_any_pair idx = co_await when_any(std::begin(cnt_), std::end(cnt_));
co_return idx.first;
}

template<class _Rep, class _Period, _IteratorT _Iter
COMMA_RESUMEF_ENABLE_IF(traits::is_iterator_v<_Iter> && std::is_same_v<event_t&, decltype(*std::declval<_Iter>())>)
>
static future_t<intptr_t>
wait_any_for(const std::chrono::duration<_Rep, _Period>& dt, _Iter begin_, _Iter end_)
{
auto tidx = co_await when_any(sleep_for(dt), when_any(begin_, end_));
if (tidx.first == 0) co_return -1;

when_any_pair idx = any_cast<when_any_pair>(tidx.second);
co_return idx.first;
}

template<class _Rep, class _Period, _ContainerT _Cont
COMMA_RESUMEF_ENABLE_IF(traits::is_container_v<_Cont>)
>
static future_t<intptr_t>
wait_any_for(const std::chrono::duration<_Rep, _Period>& dt, _Cont& cont)
{
return wait_any_for(dt, std::begin(cont), std::end(cont));
}




template<_IteratorT _Iter
COMMA_RESUMEF_ENABLE_IF(traits::is_iterator_v<_Iter> && std::is_same_v<event_t&, decltype(*std::declval<_Iter>())>)
>
static future_t<bool>
wait_all(_Iter begin_, _Iter end_)
{
auto vb = co_await when_all(begin_, end_);
co_return is_all_succeeded(vb);
}

template<class _Cont
COMMA_RESUMEF_ENABLE_IF(traits::is_container_v<_Cont>)
>
static future_t<bool>
wait_all(_Cont& cnt_)
{
auto vb = co_await when_all(std::begin(cnt_), std::end(cnt_));
co_return is_all_succeeded(vb);
}

template<class _Rep, class _Period, _IteratorT _Iter
COMMA_RESUMEF_ENABLE_IF(traits::is_iterator_v<_Iter> && std::is_same_v<event_t&, decltype(*std::declval<_Iter>())>)
>
static future_t<bool>
wait_all_for(const std::chrono::duration<_Rep, _Period>& dt, _Iter begin_, _Iter end_)
{
auto tidx = co_await when_any(sleep_for(dt), when_all(begin_, end_));
if (tidx.first == 0) co_return false;

std::vector<bool>& vb = any_cast<std::vector<bool>&>(tidx.second);
co_return is_all_succeeded(vb);
}

template<class _Rep, class _Period, _ContainerT _Cont
COMMA_RESUMEF_ENABLE_IF(traits::is_container_v<_Cont>)
>
static future_t<bool>
wait_all_for(const std::chrono::duration<_Rep, _Period>& dt, _Cont& cont)
{
return wait_all_for(dt, std::begin(cont), std::end(cont));
}

event_t(const event_t&) = default;
event_t(event_t&&) = default;
event_t& operator = (const event_t&) = default;
event_t& operator = (event_t&&) = default;
private:
event_impl_ptr _event;

timeout_awaiter wait_until_(const clock_type::time_point& tp) const noexcept;
inline static bool is_all_succeeded(const std::vector<bool>& v)
{
return std::none_of(std::begin(v), std::end(v), [](auto v)
{
return v == false;
});
}
};
}

template<class _Rep, class _Period>
auto wait_for(event_v2::event_t& e, const std::chrono::duration<_Rep, _Period>& dt)
{
return e.wait_for(dt);
}
template<class _Clock, class _Duration>
auto wait_until(event_v2::event_t& e, const std::chrono::time_point<_Clock, _Duration>& tp)
{
return e.wait_until(tp);
}

//when_all_for(dt, args...) -> when_all(wait_for(args, dt)...)
//就不再单独为每个支持超时的类提供when_all_for实现了。借助when_all和非成员的wait_for实现
}

+ 1
- 1
librf/src/event_v2.inl View File

@@ -101,7 +101,7 @@ RESUMEF_NS
};
}
namespace event_v2
inline namespace event_v2
{
inline void event_t::signal_all() const noexcept
{

+ 39
- 9
librf/src/type_traits.inl View File

@@ -30,6 +30,10 @@ RESUMEF_NS
//is_generator_v<T>
//判断是不是一个librf的generator_t类
//
//is_state_pointer<T>
//is_state_pointer_v<T>
//判断是不是一个librf的state_t类的指针或智能指针
//
//has_state<T>
//has_state_v<T>
//判断是否具有_state的成员变量
@@ -42,13 +46,21 @@ RESUMEF_NS
// type:awaitor的类型
// value_type:awaitor::await_resume()的返回值类型
//
//is_awaitable<T>
//is_awaitable_v<T>
//判断是否可以被co_await操作。可以是一个awaitor,也可以是重载了成员变量的T::operator co_await(),或者被重载了全局的operator co_awaitor(T)
//
//is_callable<T>
//is_callable_v<T>
//判断是不是一个可被调用的类型,如函数,仿函数,lambda等
//
//is_scheduler_task<T>
//is_scheduler_task_v<T>
//判断是不是可以被调度器调度的任务。调度器支持future和callable
//is_iterator<T>
//is_iterator_v<T>
//判断是不是一个支持向后迭代的迭代器
//
//is_container<T>
//is_container_v<T>
//判断是不是一个封闭区间的容器,或者数组。

template<class _Ty>
struct is_coroutine_handle : std::false_type {};
@@ -163,7 +175,6 @@ RESUMEF_NS

template<class _Ty, class = std::void_t<>>
struct awaitor_traits{};

template<class _Ty>
struct awaitor_traits<_Ty,
std::void_t<decltype(get_awaitor(std::declval<_Ty>()))>
@@ -173,6 +184,16 @@ RESUMEF_NS
using value_type = decltype(std::declval<type>().await_resume());
};

template<class _Ty, class = std::void_t<>>
struct is_awaitable : std::false_type {};
template<class _Ty>
struct is_awaitable<_Ty,
std::void_t<typename awaitor_traits<_Ty>::value_type>
> : std::true_type {};
template<typename _Ty>
constexpr bool is_awaitable_v = is_awaitable<_Ty>::value;


template<typename _Ty, class = std::void_t<>>
struct is_callable : std::false_type{};
template<typename _Ty>
@@ -186,14 +207,14 @@ RESUMEF_NS
struct is_iterator
<_Ty,
std::void_t<
decltype(++std::declval<_Ty>())
decltype(std::declval<_Ty>() + 1)
, decltype(std::declval<_Ty>() != std::declval<_Ty>())
, decltype(*std::declval<_Ty>())
>
>
: std::true_type{};
template<class _Ty>
constexpr bool is_iterator_v = is_iterator<remove_cvref_t<_Ty>>::value;
constexpr bool is_iterator_v = is_iterator<_Ty>::value;

template<class _Ty, class = std::void_t<>>
struct is_container : std::false_type {};
@@ -201,11 +222,20 @@ RESUMEF_NS
struct is_container
<_Ty,
std::void_t<
decltype(std::begin(std::declval<_Ty>()))
, decltype(std::end(std::declval<_Ty>()))
decltype(std::declval<_Ty>().begin())
, decltype(std::declval<_Ty>().end())
>
>
: is_iterator<decltype(std::begin(std::declval<_Ty>()))> {};
: std::true_type {};
//: is_iterator<decltype(std::declval<_Ty>().begin())> {};

template<class _Ty, size_t _Size>
struct is_container<_Ty[_Size]> : std::true_type {};
template<class _Ty, size_t _Size>
struct is_container<_Ty(&)[_Size]> : std::true_type {};
template<class _Ty, size_t _Size>
struct is_container<_Ty(&&)[_Size]> : std::true_type {};

template<class _Ty>
constexpr bool is_container_v = is_container<remove_cvref_t<_Ty>>::value;
}

+ 34
- 16
librf/src/when_v2.h View File

@@ -14,6 +14,9 @@ RESUMEF_NS

RESUMEF_NS
{
using when_any_pair = std::pair<intptr_t, any_t>;
using when_any_pair_ptr = std::shared_ptr<when_any_pair>;

namespace detail
{
struct state_when_t : public state_base_t
@@ -111,7 +114,7 @@ RESUMEF_NS


template<class _Ty>
struct is_when_task : std::bool_constant<traits::is_awaitor_v<_Ty> || traits::is_callable_v<_Ty>> {};
struct is_when_task : std::bool_constant<traits::is_awaitable_v<_Ty> || traits::is_callable_v<_Ty>> {};
template<class _Ty>
constexpr bool is_when_task_v = is_when_task<_Ty>::value;

@@ -128,10 +131,25 @@ RESUMEF_NS
}

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

if constexpr (std::is_same_v<_Ty, ignore_type>)
co_await awaitor;
else
value = co_await awaitor;
state->on_notify_one();
};

template<class _FuckBoolean>
using _FuckBoolVectorReference = typename std::vector<_FuckBoolean>::reference;

template<_WhenTaskT _Awaitable, class _Ty>
future_t<> when_all_connector_2(state_when_t* state,_Awaitable task, _FuckBoolVectorReference<_Ty> value)
{
auto&& awaitor = when_real_awaitor(task);

if constexpr(std::is_same_v<_Ty, ignore_type>)
co_await awaitor;
else
@@ -147,7 +165,7 @@ RESUMEF_NS
template<class _Tup, size_t _Idx, _WhenTaskT _Awaitable, _WhenTaskT... _Rest>
inline void when_all_one__(scheduler_t& sch, state_when_t* state, _Tup& values, _Awaitable&& awaitable, _Rest&&... rest)
{
sch + when_all_connector(state, std::forward<_Awaitable>(awaitable), std::get<_Idx>(values));
sch + when_all_connector_1(state, std::forward<_Awaitable>(awaitable), std::get<_Idx>(values));

when_all_one__<_Tup, _Idx + 1, _Rest...>(sch, state, values, std::forward<_Rest>(rest)...);
}
@@ -155,18 +173,17 @@ RESUMEF_NS
template<class _Val, _WhenIterT _Iter>
inline void when_all_range__(scheduler_t& sch, state_when_t* state, std::vector<_Val> & values, _Iter begin, _Iter end)
{
using _Awaitable = decltype(*begin);

intptr_t _Idx = 0;
for (; begin != end; ++begin, ++_Idx)
{
sch + when_all_connector(state, std::move(*begin), values[_Idx]);
sch + when_all_connector_2<_Awaitable, _Val>(state, *begin, values[_Idx]);
}
}

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

using when_any_pair = std::pair<intptr_t, any_t>;
using when_any_pair_ptr = std::shared_ptr<when_any_pair>;

template<_WhenTaskT _Awaitable>
future_t<> when_any_connector(counted_ptr<state_when_t> state, _Awaitable task, when_any_pair_ptr value, intptr_t idx)
{
@@ -276,7 +293,7 @@ inline namespace when_v2
COMMA_RESUMEF_ENABLE_IF(detail::is_when_task_iter_v<_Iter>)
>
auto when_all(_Iter begin, _Iter end)
-> future_t<std::vector<detail::awaitor_result_t<decltype(*std::declval<_Iter>())>>>
-> future_t<std::vector<detail::awaitor_result_t<decltype(*begin)>>>
{
co_return co_await when_all(*current_scheduler(), begin, end);
}
@@ -284,7 +301,8 @@ inline namespace when_v2
template<_ContainerT _Cont
COMMA_RESUMEF_ENABLE_IF(traits::is_container_v<_Cont>)
>
decltype(auto) when_all(_Cont& cont)
auto when_all(_Cont&& cont)
-> future_t<std::vector<detail::awaitor_result_t<decltype(*std::begin(cont))>>>
{
return when_all(std::begin(cont), std::end(cont));
}
@@ -295,9 +313,9 @@ inline namespace when_v2
COMMA_RESUMEF_ENABLE_IF(std::conjunction_v<detail::is_when_task<_Awaitable>...>)
>
auto when_any(scheduler_t& sch, _Awaitable&&... args)
-> detail::when_future_t<detail::when_any_pair>
-> detail::when_future_t<when_any_pair>
{
detail::when_future_t<detail::when_any_pair> awaitor{ sizeof...(_Awaitable) > 0 ? 1 : 0 };
detail::when_future_t<when_any_pair> awaitor{ sizeof...(_Awaitable) > 0 ? 1 : 0 };
awaitor._values->first = -1;
detail::when_any_one__(sch, awaitor._state.get(), awaitor._values, 0, std::forward<_Awaitable>(args)...);

@@ -308,9 +326,9 @@ inline namespace when_v2
COMMA_RESUMEF_ENABLE_IF(detail::is_when_task_iter_v<_Iter>)
>
auto when_any(scheduler_t& sch, _Iter begin, _Iter end)
-> detail::when_future_t<detail::when_any_pair>
-> detail::when_future_t<when_any_pair>
{
detail::when_future_t<detail::when_any_pair> awaitor{ begin == end ? 0 : 1 };
detail::when_future_t<when_any_pair> awaitor{ begin == end ? 0 : 1 };
awaitor._values->first = -1;
detail::when_any_range__<_Iter>(sch, awaitor._state.get(), awaitor._values, begin, end);

@@ -329,7 +347,7 @@ inline namespace when_v2
COMMA_RESUMEF_ENABLE_IF(std::conjunction_v<detail::is_when_task<_Awaitable>...>)
>
auto when_any(_Awaitable&&... awaitor)
-> future_t<detail::when_any_pair>
-> future_t<when_any_pair>
{
co_return co_await when_any(*current_scheduler(), std::forward<_Awaitable>(awaitor)...);
}
@@ -338,7 +356,7 @@ inline namespace when_v2
COMMA_RESUMEF_ENABLE_IF(detail::is_when_task_iter_v<_Iter>)
>
auto when_any(_Iter begin, _Iter end)
-> future_t<detail::when_any_pair>
-> future_t<when_any_pair>
{
co_return co_await when_any(*current_scheduler(), begin, end);
}
@@ -346,7 +364,7 @@ inline namespace when_v2
template<_ContainerT _Cont
COMMA_RESUMEF_ENABLE_IF(traits::is_container_v<_Cont>)
>
decltype(auto) when_any(_Cont& cont)
auto when_any(_Cont&& cont)
{
return when_any(std::begin(cont), std::end(cont));
}

+ 1
- 1
tutorial/test_async_event_timeout.cpp View File

@@ -139,7 +139,7 @@ void test_wait_timeout_all()
intptr_t counter = 0;
for (;;)
{
if (co_await event_t::wait_all_until(system_clock::now() + 500ms, evts))
if (co_await event_t::wait_all_for(500ms, evts))
{
std::cout << counter << std::endl;
std::cout << "all event signal!" << std::endl;

Loading…
Cancel
Save