diff --git a/librf/src/def.h b/librf/src/def.h index 4648553..30fb3b9 100644 --- a/librf/src/def.h +++ b/librf/src/def.h @@ -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 diff --git a/librf/src/event_v1.cpp b/librf/src/event_v1.cpp index 2b22079..4f4f50c 100644 --- a/librf/src/event_v1.cpp +++ b/librf/src/event_v1.cpp @@ -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(initial_counter_)) diff --git a/librf/src/event_v1.h b/librf/src/event_v1.h index 3695c73..f2deead 100644 --- a/librf/src/event_v1.h +++ b/librf/src/event_v1.h @@ -40,7 +40,7 @@ RESUMEF_NS }; } -inline namespace event_v1 +namespace event_v1 { //提供一种在协程和非协程之间同步的手段。 diff --git a/librf/src/event_v2.cpp b/librf/src/event_v2.cpp index 3c09d0b..31459e0 100644 --- a/librf/src/event_v2.cpp +++ b/librf/src/event_v2.cpp @@ -104,7 +104,7 @@ RESUMEF_NS } } - namespace event_v2 + inline namespace event_v2 { event_t::event_t(bool initially) :_event(std::make_shared(initially)) diff --git a/librf/src/event_v2.h b/librf/src/event_v2.h index 7f25309..1c64880 100644 --- a/librf/src/event_v2.h +++ b/librf/src/event_v2.h @@ -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 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())>) + > + static future_t + wait_any(_Iter begin_, _Iter end_) + { + when_any_pair idx = co_await when_any(begin_, end_); + co_return idx.first; + } + + template) + > + static future_t + wait_any(_Cont& cnt_) + { + when_any_pair idx = co_await when_any(std::begin(cnt_), std::end(cnt_)); + co_return idx.first; + } + + template && std::is_same_v())>) + > + static future_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(tidx.second); + co_return idx.first; + } + + template) + > + static future_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())>) + > + static future_t + wait_all(_Iter begin_, _Iter end_) + { + auto vb = co_await when_all(begin_, end_); + co_return is_all_succeeded(vb); + } + + template) + > + static future_t + wait_all(_Cont& cnt_) + { + auto vb = co_await when_all(std::begin(cnt_), std::end(cnt_)); + co_return is_all_succeeded(vb); + } + + template && std::is_same_v())>) + > + static future_t + 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& vb = any_cast&>(tidx.second); + co_return is_all_succeeded(vb); + } + + template) + > + static future_t + 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& v) + { + return std::none_of(std::begin(v), std::end(v), [](auto v) + { + return v == false; + }); + } }; } - - template - auto wait_for(event_v2::event_t& e, const std::chrono::duration<_Rep, _Period>& dt) - { - return e.wait_for(dt); - } - - template - 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实现 } diff --git a/librf/src/event_v2.inl b/librf/src/event_v2.inl index a2fe23a..8b14784 100644 --- a/librf/src/event_v2.inl +++ b/librf/src/event_v2.inl @@ -101,7 +101,7 @@ RESUMEF_NS }; } - namespace event_v2 + inline namespace event_v2 { inline void event_t::signal_all() const noexcept { diff --git a/librf/src/type_traits.inl b/librf/src/type_traits.inl index 43127fd..d1de7e2 100644 --- a/librf/src/type_traits.inl +++ b/librf/src/type_traits.inl @@ -30,6 +30,10 @@ RESUMEF_NS //is_generator_v //жDzһlibrfgenerator_t // + //is_state_pointer + //is_state_pointer_v + //жDzһlibrfstate_tָָ + // //has_state //has_state_v //жǷ_stateijԱ @@ -42,13 +46,21 @@ RESUMEF_NS // type:awaitor // value_type:awaitor::await_resume()ķֵ // + //is_awaitable + //is_awaitable_v + //жǷԱco_awaitһawaitorҲ˳ԱT::operator co_await()߱ȫֵoperator co_awaitor(T) + // //is_callable //is_callable_v //жDzһɱõͣ纯ºlambda // - //is_scheduler_task - //is_scheduler_task_v - //жDzǿԱȵ񡣵֧futurecallable + //is_iterator + //is_iterator_v + //жDzһ֧ĵ + // + //is_container + //is_container_v + //жDzһ顣 template struct is_coroutine_handle : std::false_type {}; @@ -163,7 +175,6 @@ RESUMEF_NS template> struct awaitor_traits{}; - template struct awaitor_traits<_Ty, std::void_t()))> @@ -173,6 +184,16 @@ RESUMEF_NS using value_type = decltype(std::declval().await_resume()); }; + template> + struct is_awaitable : std::false_type {}; + template + struct is_awaitable<_Ty, + std::void_t::value_type> + > : std::true_type {}; + template + constexpr bool is_awaitable_v = is_awaitable<_Ty>::value; + + template> struct is_callable : std::false_type{}; template @@ -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 - constexpr bool is_iterator_v = is_iterator>::value; + constexpr bool is_iterator_v = is_iterator<_Ty>::value; template> 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()))> {}; + : std::true_type {}; + //: is_iterator().begin())> {}; + + template + struct is_container<_Ty[_Size]> : std::true_type {}; + template + struct is_container<_Ty(&)[_Size]> : std::true_type {}; + template + struct is_container<_Ty(&&)[_Size]> : std::true_type {}; + template constexpr bool is_container_v = is_container>::value; } diff --git a/librf/src/when_v2.h b/librf/src/when_v2.h index a30b302..adeceb9 100644 --- a/librf/src/when_v2.h +++ b/librf/src/when_v2.h @@ -14,6 +14,9 @@ RESUMEF_NS RESUMEF_NS { + using when_any_pair = std::pair; + using when_any_pair_ptr = std::shared_ptr; + namespace detail { struct state_when_t : public state_base_t @@ -111,7 +114,7 @@ RESUMEF_NS template - struct is_when_task : std::bool_constant || traits::is_callable_v<_Ty>> {}; + struct is_when_task : std::bool_constant || traits::is_callable_v<_Ty>> {}; template 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 + 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 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 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; - using when_any_pair_ptr = std::shared_ptr; - template<_WhenTaskT _Awaitable> future_t<> when_any_connector(counted_ptr 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())>>> + -> future_t>> { 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>> { return when_all(std::begin(cont), std::end(cont)); } @@ -295,9 +313,9 @@ inline namespace when_v2 COMMA_RESUMEF_ENABLE_IF(std::conjunction_v...>) > auto when_any(scheduler_t& sch, _Awaitable&&... args) - -> detail::when_future_t + -> detail::when_future_t { - detail::when_future_t awaitor{ sizeof...(_Awaitable) > 0 ? 1 : 0 }; + detail::when_future_t 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_future_t { - detail::when_future_t awaitor{ begin == end ? 0 : 1 }; + detail::when_future_t 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...>) > auto when_any(_Awaitable&&... awaitor) - -> future_t + -> future_t { 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 + -> future_t { 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)); } diff --git a/tutorial/test_async_event_timeout.cpp b/tutorial/test_async_event_timeout.cpp index 96aea1d..fd86ae2 100644 --- a/tutorial/test_async_event_timeout.cpp +++ b/tutorial/test_async_event_timeout.cpp @@ -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;