@@ -67,7 +67,7 @@ namespace resumef | |||
template<typename _PromiseT = void> | |||
using coroutine_handle = std::experimental::coroutine_handle<_PromiseT>; | |||
template <typename _Ty, typename _Alloc = std::allocator<char>> | |||
template <typename _Ty = std::nullptr_t, typename _Alloc = std::allocator<char>> | |||
using generator_t = std::experimental::generator<_Ty, _Alloc>; | |||
enum struct error_code |
@@ -166,13 +166,13 @@ namespace experimental { | |||
void *operator new(size_t _Size) | |||
{ | |||
_Alloc_of_char_type _Al; | |||
_Alloc_char _Al; | |||
return _Al.allocate(_Size); | |||
} | |||
void operator delete(void *_Ptr, size_t _Size) | |||
{ | |||
_Alloc_of_char_type _Al; | |||
_Alloc_char _Al; | |||
return _Al.deallocate(static_cast<char *>(_Ptr), _Size); | |||
} | |||
}; | |||
@@ -228,6 +228,13 @@ namespace experimental { | |||
} | |||
} | |||
coroutine_handle<promise_type> detach() | |||
{ | |||
auto t = _Coro; | |||
_Coro = nullptr; | |||
return t; | |||
} | |||
private: | |||
coroutine_handle<promise_type> _Coro = nullptr; | |||
}; |
@@ -13,8 +13,13 @@ namespace resumef | |||
RF_API task_base_t(); | |||
RF_API virtual ~task_base_t(); | |||
virtual state_base_t * get_state() const = 0; | |||
state_base_t* get_state() const | |||
{ | |||
return _state.get(); | |||
} | |||
protected: | |||
counted_ptr<state_base_t> _state; | |||
public: | |||
task_base_t* _next_node; | |||
task_base_t* _prev_node; | |||
}; | |||
@@ -31,17 +36,34 @@ namespace resumef | |||
using future_type = future_t<value_type>; | |||
using state_type = state_t<value_type>; | |||
counted_ptr<state_type> _state; | |||
task_t() = default; | |||
task_t(future_type && f) | |||
: _state(std::move(f._state)) | |||
{ | |||
initialize(std::forward<future_type>(f)); | |||
} | |||
protected: | |||
void initialize(future_type&& f) | |||
{ | |||
_state = f._state.get(); | |||
} | |||
}; | |||
virtual state_base_t * get_state() const | |||
template<class _Ty> | |||
struct task_t<generator_t<_Ty>> : public task_base_t | |||
{ | |||
using value_type = _Ty; | |||
using future_type = generator_t<value_type>; | |||
using state_type = state_generator_t; | |||
task_t() = default; | |||
task_t(future_type&& f) | |||
{ | |||
return _state.get(); | |||
initialize(std::forward<future_type>(f)); | |||
} | |||
protected: | |||
void initialize(future_type&& f) | |||
{ | |||
_state = new state_type(f.detach()); | |||
} | |||
}; | |||
@@ -51,25 +73,16 @@ namespace resumef | |||
//这个'函数对象'被调用后,返回generator<_Ty>/future_t<_Ty>类型 | |||
//然后'函数对象'作为异步执行的上下文状态保存起来 | |||
template<class _Ctx> | |||
struct ctx_task_t : public task_base_t | |||
struct ctx_task_t : public task_t<typename std::remove_cvref<decltype(std::declval<_Ctx>()())>::type> | |||
{ | |||
using context_type = _Ctx; | |||
using future_type = typename std::remove_cvref<decltype(std::declval<_Ctx>()())>::type; | |||
using value_type = typename future_type::value_type; | |||
using state_type = state_t<value_type>; | |||
context_type _context; | |||
counted_ptr<state_type> _state; | |||
ctx_task_t(context_type ctx) | |||
: _context(std::move(ctx)) | |||
{ | |||
_state = _context()._state; | |||
} | |||
virtual state_base_t* get_state() const | |||
{ | |||
return _state.get(); | |||
this->initialize(_context()); | |||
} | |||
}; | |||
} |
@@ -40,13 +40,13 @@ namespace resumef | |||
RF_API void run(); | |||
//RF_API void break_all(); | |||
template<class _Ty, typename = std::enable_if_t<std::is_callable_v<_Ty> || is_future_v<_Ty>>> | |||
template<class _Ty, typename = std::enable_if_t<std::is_callable_v<_Ty> || is_future_v<_Ty> || is_generator_v<_Ty> >> | |||
inline void operator + (_Ty && t_) | |||
{ | |||
if constexpr(is_future_v<_Ty>) | |||
new_task(new task_t<_Ty>(std::forward<_Ty>(t_))); | |||
else | |||
if constexpr(std::is_callable_v<_Ty>) | |||
new_task(new ctx_task_t<_Ty>(std::forward<_Ty>(t_))); | |||
else | |||
new_task(new task_t<_Ty>(std::forward<_Ty>(t_))); | |||
} | |||
inline bool empty() const |
@@ -15,9 +15,14 @@ namespace resumef | |||
{ | |||
_coro.resume(); | |||
if (_coro.done()) | |||
{ | |||
_coro = nullptr; | |||
_scheduler->del_final(this); | |||
} | |||
else | |||
{ | |||
_scheduler->add_generator(this); | |||
} | |||
} | |||
} | |||
@@ -20,8 +20,8 @@ namespace resumef | |||
coroutine_handle<> _coro; | |||
public: | |||
virtual void resume() = 0; | |||
virtual bool is_ready() const = 0; | |||
virtual bool has_handler() const = 0; | |||
virtual bool is_ready() const = 0; | |||
void set_scheduler(scheduler_t* sch) | |||
{ | |||
@@ -35,9 +35,15 @@ namespace resumef | |||
struct state_generator_t : public state_base_t | |||
{ | |||
public: | |||
state_generator_t(coroutine_handle<> handler) | |||
{ | |||
_coro = handler; | |||
} | |||
virtual void resume() override; | |||
virtual bool is_ready() const override; | |||
virtual bool has_handler() const override; | |||
virtual bool is_ready() const override; | |||
}; | |||
struct state_future_t : public state_base_t |
@@ -46,7 +46,7 @@ void resumable_switch(intptr_t coro, size_t idx) | |||
{ | |||
for (intptr_t i = 0; i < N / coro; ++i) | |||
co_yield i; | |||
return N / coro; | |||
co_return N / coro; | |||
}; | |||
} | |||
auto middle = std::chrono::steady_clock::now(); |
@@ -9,8 +9,7 @@ | |||
using namespace resumef; | |||
//std::experimental::generator<int> | |||
auto test_yield_int() -> std::experimental::generator<int> | |||
auto test_yield_int() -> generator_t<int> | |||
{ | |||
std::cout << "1 will yield return" << std::endl; | |||
co_yield 1; | |||
@@ -43,7 +42,7 @@ auto test_yield_void() | |||
} | |||
*/ | |||
auto test_yield_void() -> std::experimental::generator<std::nullptr_t> | |||
auto test_yield_void() -> generator_t<> | |||
{ | |||
std::cout << "block 1 will yield return" << std::endl; | |||
co_yield_void; |
@@ -30,11 +30,12 @@ int main(int argc, const char* argv[]) | |||
{ | |||
//resumable_main_cb(); | |||
//resumable_main_suspend_always(); | |||
resumable_main_routine(); | |||
//resumable_main_yield_return(); | |||
resumable_main_resumable(); | |||
//resumable_main_routine(); | |||
//resumable_main_exception(); | |||
/* | |||
resumable_main_resumable(); | |||
resumable_main_benchmark_mem(); | |||
if (argc > 1) | |||
resumable_main_benchmark_asio_client(atoi(argv[1])); | |||
@@ -43,10 +44,8 @@ int main(int argc, const char* argv[]) | |||
resumable_main_when_all(); | |||
resumable_main_multi_thread(); | |||
resumable_main_yield_return(); | |||
resumable_main_timer(); | |||
resumable_main_sleep(); | |||
resumable_main_resumable(); | |||
resumable_main_mutex(); | |||
resumable_main_event(); | |||
resumable_main_event_timeout(); |
@@ -243,10 +243,7 @@ | |||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild> | |||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild> | |||
</ClCompile> | |||
<ClCompile Include="..\tutorial\test_async_resumable.cpp"> | |||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild> | |||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild> | |||
</ClCompile> | |||
<ClCompile Include="..\tutorial\test_async_resumable.cpp" /> | |||
<ClCompile Include="..\tutorial\test_async_routine.cpp" /> | |||
<ClCompile Include="..\tutorial\test_async_sleep.cpp"> | |||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild> |