From 8d580dcda49c2fc34679ab55ba87d2c73a97434a Mon Sep 17 00:00:00 2001 From: tearshark Date: Sun, 16 Feb 2020 11:33:19 +0800 Subject: [PATCH] =?UTF-8?q?=E6=94=AF=E6=8C=81generator=EF=BC=8C=E5=AE=8C?= =?UTF-8?q?=E6=88=90=E7=9B=B8=E5=85=B3=E8=8C=83=E4=BE=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- librf/src/def.h | 2 +- librf/src/generator.h | 11 ++++-- librf/src/rf_task.h | 51 +++++++++++++++++----------- librf/src/scheduler.h | 8 ++--- librf/src/state.cpp | 5 +++ librf/src/state.h | 10 ++++-- tutorial/test_async_resumable.cpp | 2 +- tutorial/test_async_yield_return.cpp | 5 ++- vs_proj/librf.cpp | 7 ++-- vs_proj/librf.vcxproj | 5 +-- 10 files changed, 66 insertions(+), 40 deletions(-) diff --git a/librf/src/def.h b/librf/src/def.h index dc6241d..37c0151 100644 --- a/librf/src/def.h +++ b/librf/src/def.h @@ -67,7 +67,7 @@ namespace resumef template using coroutine_handle = std::experimental::coroutine_handle<_PromiseT>; - template > + template > using generator_t = std::experimental::generator<_Ty, _Alloc>; enum struct error_code diff --git a/librf/src/generator.h b/librf/src/generator.h index 08f15cb..fa651c3 100644 --- a/librf/src/generator.h +++ b/librf/src/generator.h @@ -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(_Ptr), _Size); } }; @@ -228,6 +228,13 @@ namespace experimental { } } + coroutine_handle detach() + { + auto t = _Coro; + _Coro = nullptr; + return t; + } + private: coroutine_handle _Coro = nullptr; }; diff --git a/librf/src/rf_task.h b/librf/src/rf_task.h index bdc0a4d..37e8532 100644 --- a/librf/src/rf_task.h +++ b/librf/src/rf_task.h @@ -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; + public: task_base_t* _next_node; task_base_t* _prev_node; }; @@ -31,17 +36,34 @@ namespace resumef using future_type = future_t; using state_type = state_t; - counted_ptr _state; - task_t() = default; task_t(future_type && f) - : _state(std::move(f._state)) { + initialize(std::forward(f)); } - - virtual state_base_t * get_state() const + protected: + void initialize(future_type&& f) { - return _state.get(); + _state = f._state.get(); + } + }; + + template + struct task_t> : public task_base_t + { + using value_type = _Ty; + using future_type = generator_t; + using state_type = state_generator_t; + + task_t() = default; + task_t(future_type&& f) + { + initialize(std::forward(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 - struct ctx_task_t : public task_base_t + struct ctx_task_t : public task_t()())>::type> { using context_type = _Ctx; - using future_type = typename std::remove_cvref()())>::type; - using value_type = typename future_type::value_type; - using state_type = state_t; context_type _context; - counted_ptr _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()); } }; } diff --git a/librf/src/scheduler.h b/librf/src/scheduler.h index a68e91f..c619059 100644 --- a/librf/src/scheduler.h +++ b/librf/src/scheduler.h @@ -40,13 +40,13 @@ namespace resumef RF_API void run(); //RF_API void break_all(); - template || is_future_v<_Ty>>> + template || 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 diff --git a/librf/src/state.cpp b/librf/src/state.cpp index d9a26af..d55a21d 100644 --- a/librf/src/state.cpp +++ b/librf/src/state.cpp @@ -15,9 +15,14 @@ namespace resumef { _coro.resume(); if (_coro.done()) + { _coro = nullptr; + _scheduler->del_final(this); + } else + { _scheduler->add_generator(this); + } } } diff --git a/librf/src/state.h b/librf/src/state.h index a8a3b80..83aa415 100644 --- a/librf/src/state.h +++ b/librf/src/state.h @@ -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 diff --git a/tutorial/test_async_resumable.cpp b/tutorial/test_async_resumable.cpp index 2f1a995..0abc14a 100644 --- a/tutorial/test_async_resumable.cpp +++ b/tutorial/test_async_resumable.cpp @@ -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(); diff --git a/tutorial/test_async_yield_return.cpp b/tutorial/test_async_yield_return.cpp index aec2a32..1e60142 100644 --- a/tutorial/test_async_yield_return.cpp +++ b/tutorial/test_async_yield_return.cpp @@ -9,8 +9,7 @@ using namespace resumef; -//std::experimental::generator -auto test_yield_int() -> std::experimental::generator +auto test_yield_int() -> generator_t { 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 +auto test_yield_void() -> generator_t<> { std::cout << "block 1 will yield return" << std::endl; co_yield_void; diff --git a/vs_proj/librf.cpp b/vs_proj/librf.cpp index 9a09061..15000e3 100644 --- a/vs_proj/librf.cpp +++ b/vs_proj/librf.cpp @@ -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(); diff --git a/vs_proj/librf.vcxproj b/vs_proj/librf.vcxproj index 32f3c87..c901a9d 100644 --- a/vs_proj/librf.vcxproj +++ b/vs_proj/librf.vcxproj @@ -243,10 +243,7 @@ true true - - true - true - + true