Quellcode durchsuchen

解决vector<bool>导致的问题

启用event_v2版本代码
event_v2尽量兼容event_v1用法
tags/v2.9.7
tearshark vor 4 Jahren
Ursprung
Commit
6c9110a3e4

+ 1
- 1
librf/src/def.h Datei anzeigen

#pragma once #pragma once
#define LIB_RESUMEF_VERSION 20600 // 2.6.0
#define LIB_RESUMEF_VERSION 20700 // 2.7.0
#if defined(RESUMEF_MODULE_EXPORT) #if defined(RESUMEF_MODULE_EXPORT)
#define RESUMEF_NS export namespace resumef #define RESUMEF_NS export namespace resumef

+ 1
- 1
librf/src/event_v1.cpp Datei anzeigen



} }


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

+ 1
- 1
librf/src/event_v1.h Datei anzeigen

}; };
} }


inline namespace event_v1
namespace event_v1
{ {


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

+ 1
- 1
librf/src/event_v2.cpp Datei anzeigen

} }
} }


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

+ 105
- 16
librf/src/event_v2.h Datei anzeigen

struct event_v2_impl; struct event_v2_impl;
} }


namespace event_v2
inline namespace event_v2
{ {
struct event_t struct event_t
{ {
void reset() const noexcept; void reset() const noexcept;


struct [[nodiscard]] awaiter; struct [[nodiscard]] awaiter;

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


timeout_awaiter wait_for(const std::chrono::duration<_Rep, _Period>& dt) const noexcept; timeout_awaiter wait_for(const std::chrono::duration<_Rep, _Period>& dt) const noexcept;
template<class _Clock, class _Duration> template<class _Clock, class _Duration>
timeout_awaiter wait_until(const std::chrono::time_point<_Clock, _Duration>& tp) const noexcept; 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: private:
event_impl_ptr _event; event_impl_ptr _event;


timeout_awaiter wait_until_(const clock_type::time_point& tp) const noexcept; 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 Datei anzeigen

}; };
} }
namespace event_v2
inline namespace event_v2
{ {
inline void event_t::signal_all() const noexcept inline void event_t::signal_all() const noexcept
{ {

+ 39
- 9
librf/src/type_traits.inl Datei anzeigen

//is_generator_v<T> //is_generator_v<T>
//判断是不是一个librf的generator_t类 //判断是不是一个librf的generator_t类
// //
//is_state_pointer<T>
//is_state_pointer_v<T>
//判断是不是一个librf的state_t类的指针或智能指针
//
//has_state<T> //has_state<T>
//has_state_v<T> //has_state_v<T>
//判断是否具有_state的成员变量 //判断是否具有_state的成员变量
// type:awaitor的类型 // type:awaitor的类型
// value_type:awaitor::await_resume()的返回值类型 // 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<T>
//is_callable_v<T> //is_callable_v<T>
//判断是不是一个可被调用的类型,如函数,仿函数,lambda等 //判断是不是一个可被调用的类型,如函数,仿函数,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> template<class _Ty>
struct is_coroutine_handle : std::false_type {}; struct is_coroutine_handle : std::false_type {};


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

template<class _Ty> template<class _Ty>
struct awaitor_traits<_Ty, struct awaitor_traits<_Ty,
std::void_t<decltype(get_awaitor(std::declval<_Ty>()))> std::void_t<decltype(get_awaitor(std::declval<_Ty>()))>
using value_type = decltype(std::declval<type>().await_resume()); 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<>> template<typename _Ty, class = std::void_t<>>
struct is_callable : std::false_type{}; struct is_callable : std::false_type{};
template<typename _Ty> template<typename _Ty>
struct is_iterator struct is_iterator
<_Ty, <_Ty,
std::void_t< std::void_t<
decltype(++std::declval<_Ty>())
decltype(std::declval<_Ty>() + 1)
, decltype(std::declval<_Ty>() != std::declval<_Ty>()) , decltype(std::declval<_Ty>() != std::declval<_Ty>())
, decltype(*std::declval<_Ty>()) , decltype(*std::declval<_Ty>())
> >
> >
: std::true_type{}; : std::true_type{};
template<class _Ty> 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<>> template<class _Ty, class = std::void_t<>>
struct is_container : std::false_type {}; struct is_container : std::false_type {};
struct is_container struct is_container
<_Ty, <_Ty,
std::void_t< 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> template<class _Ty>
constexpr bool is_container_v = is_container<remove_cvref_t<_Ty>>::value; constexpr bool is_container_v = is_container<remove_cvref_t<_Ty>>::value;
} }

+ 34
- 16
librf/src/when_v2.h Datei anzeigen



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 namespace detail
{ {
struct state_when_t : public state_base_t struct state_when_t : public state_base_t




template<class _Ty> 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> template<class _Ty>
constexpr bool is_when_task_v = is_when_task<_Ty>::value; constexpr bool is_when_task_v = is_when_task<_Ty>::value;


} }


template<_WhenTaskT _Awaitable, class _Ty> 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); 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>) if constexpr(std::is_same_v<_Ty, ignore_type>)
co_await awaitor; co_await awaitor;
else else
template<class _Tup, size_t _Idx, _WhenTaskT _Awaitable, _WhenTaskT... _Rest> 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) 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)...); when_all_one__<_Tup, _Idx + 1, _Rest...>(sch, state, values, std::forward<_Rest>(rest)...);
} }
template<class _Val, _WhenIterT _Iter> 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) 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; intptr_t _Idx = 0;
for (; begin != end; ++begin, ++_Idx) 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> template<_WhenTaskT _Awaitable>
future_t<> when_any_connector(counted_ptr<state_when_t> state, _Awaitable task, 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)
{ {
COMMA_RESUMEF_ENABLE_IF(detail::is_when_task_iter_v<_Iter>) COMMA_RESUMEF_ENABLE_IF(detail::is_when_task_iter_v<_Iter>)
> >
auto when_all(_Iter begin, _Iter end) 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); co_return co_await when_all(*current_scheduler(), begin, end);
} }
template<_ContainerT _Cont template<_ContainerT _Cont
COMMA_RESUMEF_ENABLE_IF(traits::is_container_v<_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)); return when_all(std::begin(cont), std::end(cont));
} }
COMMA_RESUMEF_ENABLE_IF(std::conjunction_v<detail::is_when_task<_Awaitable>...>) COMMA_RESUMEF_ENABLE_IF(std::conjunction_v<detail::is_when_task<_Awaitable>...>)
> >
auto when_any(scheduler_t& sch, _Awaitable&&... args) 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; awaitor._values->first = -1;
detail::when_any_one__(sch, awaitor._state.get(), awaitor._values, 0, std::forward<_Awaitable>(args)...); detail::when_any_one__(sch, awaitor._state.get(), awaitor._values, 0, std::forward<_Awaitable>(args)...);


COMMA_RESUMEF_ENABLE_IF(detail::is_when_task_iter_v<_Iter>) COMMA_RESUMEF_ENABLE_IF(detail::is_when_task_iter_v<_Iter>)
> >
auto when_any(scheduler_t& sch, _Iter begin, _Iter end) 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; awaitor._values->first = -1;
detail::when_any_range__<_Iter>(sch, awaitor._state.get(), awaitor._values, begin, end); detail::when_any_range__<_Iter>(sch, awaitor._state.get(), awaitor._values, begin, end);


COMMA_RESUMEF_ENABLE_IF(std::conjunction_v<detail::is_when_task<_Awaitable>...>) COMMA_RESUMEF_ENABLE_IF(std::conjunction_v<detail::is_when_task<_Awaitable>...>)
> >
auto when_any(_Awaitable&&... awaitor) 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)...); co_return co_await when_any(*current_scheduler(), std::forward<_Awaitable>(awaitor)...);
} }
COMMA_RESUMEF_ENABLE_IF(detail::is_when_task_iter_v<_Iter>) COMMA_RESUMEF_ENABLE_IF(detail::is_when_task_iter_v<_Iter>)
> >
auto when_any(_Iter begin, _Iter end) 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); co_return co_await when_any(*current_scheduler(), begin, end);
} }
template<_ContainerT _Cont template<_ContainerT _Cont
COMMA_RESUMEF_ENABLE_IF(traits::is_container_v<_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)); return when_any(std::begin(cont), std::end(cont));
} }

+ 1
- 1
tutorial/test_async_event_timeout.cpp Datei anzeigen

intptr_t counter = 0; intptr_t counter = 0;
for (;;) 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 << counter << std::endl;
std::cout << "all event signal!" << std::endl; std::cout << "all event signal!" << std::endl;

Laden…
Abbrechen
Speichern