@@ -39,8 +39,11 @@ | |||
#endif | |||
#include "src/def.h" | |||
#include "src/macro_def.inl" | |||
#include "src/spinlock.h" | |||
#include "src/counted_ptr.h" | |||
#include "src/type_traits.inl" | |||
#include "src/type_concept.inl" | |||
#include "src/state.h" | |||
#include "src/future.h" | |||
#include "src/promise.h" |
@@ -78,6 +78,3 @@ RESUMEF_NS | |||
} | |||
#include "exception.inl" | |||
#include "type_traits.inl" | |||
#include "type_concept.inl" | |||
#include "macro_def.inl" |
@@ -43,7 +43,8 @@ RESUMEF_NS | |||
{ | |||
return e.wait_for(dt); | |||
} | |||
template<class _Clock, class _Duration> | |||
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); |
@@ -1,11 +1,15 @@ | |||
#pragma once | |||
#ifndef RESUMEF_ENABLE_CONCEPT | |||
#define RESUMEF_ENABLE_CONCEPT 0 | |||
#endif | |||
#if RESUMEF_ENABLE_CONCEPT | |||
#include <concepts> | |||
#endif | |||
RESUMEF_NS | |||
{ | |||
#ifndef RESUMEF_ENABLE_CONCEPT | |||
#define RESUMEF_ENABLE_CONCEPT 1 | |||
#endif | |||
#if RESUMEF_ENABLE_CONCEPT | |||
@@ -21,6 +25,7 @@ RESUMEF_NS | |||
concept _HasStateT = requires(T && v) | |||
{ | |||
{ v._state }; | |||
{ traits::is_state_pointer_v<decltype(v._state)> != false }; | |||
}; | |||
template<typename T> | |||
@@ -41,14 +46,29 @@ RESUMEF_NS | |||
concept _WhenTaskT = _AwaitorT<T> || _CallableT<T>; | |||
template<typename T> | |||
concept _WhenIterT = requires(T&& u, T&& v) | |||
concept _IteratorT = requires(T && u, T && v) | |||
{ | |||
{ ++u } -> T; | |||
{ ++u }->T; | |||
{ u != v } -> bool; | |||
{ *u }; | |||
}; | |||
template<typename T> | |||
concept _WhenIterT = _IteratorT<T> && requires(T&& u, T&& v) | |||
{ | |||
requires _WhenTaskT<decltype(*u)>; | |||
}; | |||
template<typename T> | |||
concept _ContainerT = requires(T && v) | |||
{ | |||
{ std::begin(v) }; | |||
{ std::end(v) }; | |||
requires std::same_as<decltype(std::begin(v)), decltype(std::end(v))>; | |||
requires _IteratorT<decltype(std::begin(v))>; | |||
requires _IteratorT<decltype(std::end(v))>; | |||
}; | |||
#define COMMA_RESUMEF_ENABLE_IF(...) | |||
#define RESUMEF_ENABLE_IF(...) | |||
#define RESUMEF_REQUIRES(...) requires __VA_ARGS__ | |||
@@ -61,7 +81,9 @@ RESUMEF_NS | |||
#define _CallableT typename | |||
#define _GeneratorT typename | |||
#define _WhenTaskT typename | |||
#define _IteratorT typename | |||
#define _WhenIterT typename | |||
#define _ContainerT typename | |||
#define COMMA_RESUMEF_ENABLE_IF(...) ,typename=std::enable_if_t<__VA_ARGS__> | |||
#define RESUMEF_ENABLE_IF(...) typename=std::enable_if_t<__VA_ARGS__> |
@@ -114,6 +114,16 @@ RESUMEF_NS | |||
template<class _Ty> | |||
constexpr bool is_generator_v = is_generator<remove_cvref_t<_Ty>>::value; | |||
template<class _Ty, class = std::void_t<>> | |||
struct is_state_pointer : std::false_type {}; | |||
template<class _Ty> | |||
struct is_state_pointer<_Ty, std::void_t<std::enable_if_t<std::is_convertible_v<_Ty, state_base_t*>>>> : std::true_type {}; | |||
template<class _Ty> | |||
struct is_state_pointer<counted_ptr<_Ty>> : is_state_pointer<_Ty> {}; | |||
template<class _Ty> | |||
constexpr bool is_state_pointer_v = is_state_pointer<remove_cvref_t<_Ty>>::value; | |||
template<class _Ty, class = std::void_t<>> | |||
struct has_state : std::false_type {}; | |||
template<class _Ty> | |||
@@ -183,15 +193,20 @@ RESUMEF_NS | |||
> | |||
: std::true_type{}; | |||
template<class _Ty> | |||
struct is_iterator<_Ty&> : is_iterator<_Ty> {}; | |||
template<class _Ty> | |||
struct is_iterator<_Ty&&> : is_iterator<_Ty> {}; | |||
template<class _Ty> | |||
struct is_iterator<const _Ty> : is_iterator<_Ty> {}; | |||
template<class _Ty> | |||
struct is_iterator<const _Ty&> : is_iterator<_Ty> {}; | |||
constexpr bool is_iterator_v = is_iterator<remove_cvref_t<_Ty>>::value; | |||
template<class _Ty, class = std::void_t<>> | |||
struct is_container : std::false_type {}; | |||
template<class _Ty> | |||
constexpr bool is_iterator_v = is_iterator<remove_cvref_t<_Ty>>::value; | |||
struct is_container | |||
<_Ty, | |||
std::void_t< | |||
decltype(std::begin(std::declval<_Ty>())) | |||
, decltype(std::end(std::declval<_Ty>())) | |||
> | |||
> | |||
: is_iterator<decltype(std::begin(std::declval<_Ty>()))> {}; | |||
template<class _Ty> | |||
constexpr bool is_container_v = is_container<remove_cvref_t<_Ty>>::value; | |||
} | |||
} |
@@ -115,9 +115,8 @@ RESUMEF_NS | |||
template<class _Ty> | |||
constexpr bool is_when_task_v = is_when_task<_Ty>::value; | |||
template<class _Ty> | |||
constexpr bool is_when_task_iter_v = traits::is_iterator_v<_Ty> | |||
&& is_when_task_v<decltype(*std::declval<_Ty>())>; | |||
template<class _Ty, class _Task = decltype(*std::declval<_Ty>())> | |||
constexpr bool is_when_task_iter_v = traits::is_iterator_v<_Ty> && is_when_task_v<_Task>; | |||
template<_WhenTaskT _Awaitable> | |||
decltype(auto) when_real_awaitor(_Awaitable&& awaitor) | |||
@@ -256,6 +255,14 @@ inline namespace when_v2 | |||
return awaitor; | |||
} | |||
template<_ContainerT _Cont | |||
COMMA_RESUMEF_ENABLE_IF(traits::is_container_v<_Cont>) | |||
> | |||
decltype(auto) when_all(scheduler_t& sch, _Cont& cont) | |||
{ | |||
return when_all(sch, std::begin(cont), std::end(cont)); | |||
} | |||
template<_WhenTaskT... _Awaitable | |||
COMMA_RESUMEF_ENABLE_IF(std::conjunction_v<detail::is_when_task<_Awaitable>...>) | |||
> | |||
@@ -274,6 +281,14 @@ inline namespace when_v2 | |||
co_return co_await when_all(*current_scheduler(), begin, end); | |||
} | |||
template<_ContainerT _Cont | |||
COMMA_RESUMEF_ENABLE_IF(traits::is_container_v<_Cont>) | |||
> | |||
decltype(auto) when_all(_Cont& cont) | |||
{ | |||
return when_all(std::begin(cont), std::end(cont)); | |||
} | |||
template<_WhenTaskT... _Awaitable | |||
@@ -302,6 +317,14 @@ inline namespace when_v2 | |||
return awaitor; | |||
} | |||
template<_ContainerT _Cont | |||
COMMA_RESUMEF_ENABLE_IF(traits::is_container_v<_Cont>) | |||
> | |||
decltype(auto) when_any(scheduler_t& sch, _Cont& cont) | |||
{ | |||
return when_any(sch, std::begin(cont), std::end(cont)); | |||
} | |||
template<_WhenTaskT... _Awaitable | |||
COMMA_RESUMEF_ENABLE_IF(std::conjunction_v<detail::is_when_task<_Awaitable>...>) | |||
> | |||
@@ -320,5 +343,13 @@ inline namespace when_v2 | |||
co_return co_await when_any(*current_scheduler(), begin, end); | |||
} | |||
template<_ContainerT _Cont | |||
COMMA_RESUMEF_ENABLE_IF(traits::is_container_v<_Cont>) | |||
> | |||
decltype(auto) when_any(_Cont& cont) | |||
{ | |||
return when_any(std::begin(cont), std::end(cont)); | |||
} | |||
} | |||
} |
@@ -8,11 +8,8 @@ | |||
#include "librf.h" | |||
#if _HAS_CXX17 || RESUMEF_USE_BOOST_ANY | |||
using namespace resumef; | |||
/* | |||
void test_when_any() | |||
{ | |||
using namespace std::chrono; | |||
@@ -61,12 +58,14 @@ void test_when_any() | |||
}; | |||
std::vector<future_t<int> > v{ my_sleep("g"), my_sleep("h"), my_sleep("i") }; | |||
vals = co_await when_any(std::begin(v), std::end(v)); | |||
//vals = co_await when_any(*this_scheduler(), std::begin(v), std::end(v)); | |||
//vals = co_await when_any(std::begin(v), std::end(v)); | |||
vals = co_await when_any(v); | |||
std::cout << "any range done! index is " << vals.first << ", valus is " << resumef::any_cast<int>(vals.second) << std::endl; | |||
}; | |||
this_scheduler()->run_until_notask(); | |||
} | |||
*/ | |||
void test_when_all() | |||
{ | |||
@@ -91,7 +90,6 @@ void test_when_all() | |||
GO | |||
{ | |||
/* | |||
co_await when_all(); | |||
std::cout << "when all: zero!" << std::endl << std::endl; | |||
@@ -129,26 +127,24 @@ void test_when_all() | |||
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 - 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(*this_scheduler(), std::begin(v), std::end(v)); | |||
//std::cout << "when all - 5:" << vals[0] << "," << vals[1] << "," << vals[2] << "," << std::endl << std::endl; | |||
//auto vals = co_await when_all(*this_scheduler(), std::begin(v), std::end(v)); | |||
//auto vals = co_await when_all(*this_scheduler(), v); | |||
auto vals = co_await when_all(v); | |||
std::cout << "when all - 5:" << vals[0] << "," << vals[1] << "," << vals[2] << "," << std::endl << std::endl; | |||
//std::cout << "all range done!" << std::endl; | |||
std::cout << "all range done!" << std::endl; | |||
}; | |||
this_scheduler()->run_until_notask(); | |||
} | |||
#endif | |||
void resumable_main_when_all() | |||
{ | |||
#if _HAS_CXX17 || RESUMEF_USE_BOOST_ANY | |||
srand((uint32_t)time(nullptr)); | |||
//test_when_any(); | |||
test_when_any(); | |||
std::cout << std::endl; | |||
test_when_all(); | |||
#endif | |||
} | |||