1
0
mirror of https://github.com/tearshark/librf.git synced 2024-10-04 08:50:31 +08:00

支持generator,完成相关范例

This commit is contained in:
tearshark 2020-02-16 11:33:19 +08:00
parent 7289258a75
commit 8d580dcda4
10 changed files with 66 additions and 40 deletions

View File

@ -67,7 +67,7 @@ namespace resumef
template<typename _PromiseT = void> template<typename _PromiseT = void>
using coroutine_handle = std::experimental::coroutine_handle<_PromiseT>; 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>; using generator_t = std::experimental::generator<_Ty, _Alloc>;
enum struct error_code enum struct error_code

View File

@ -166,13 +166,13 @@ namespace experimental {
void *operator new(size_t _Size) void *operator new(size_t _Size)
{ {
_Alloc_of_char_type _Al; _Alloc_char _Al;
return _Al.allocate(_Size); return _Al.allocate(_Size);
} }
void operator delete(void *_Ptr, size_t _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); 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: private:
coroutine_handle<promise_type> _Coro = nullptr; coroutine_handle<promise_type> _Coro = nullptr;
}; };

View File

@ -13,8 +13,13 @@ namespace resumef
RF_API task_base_t(); RF_API task_base_t();
RF_API virtual ~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* _next_node;
task_base_t* _prev_node; task_base_t* _prev_node;
}; };
@ -31,17 +36,34 @@ namespace resumef
using future_type = future_t<value_type>; using future_type = future_t<value_type>;
using state_type = state_t<value_type>; using state_type = state_t<value_type>;
counted_ptr<state_type> _state; task_t() = default;
task_t(future_type && f)
{
initialize(std::forward<future_type>(f));
}
protected:
void initialize(future_type&& f)
{
_state = f._state.get();
}
};
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() = default;
task_t(future_type&& f) task_t(future_type&& f)
: _state(std::move(f._state))
{ {
initialize(std::forward<future_type>(f));
} }
protected:
virtual state_base_t * get_state() const void initialize(future_type&& f)
{ {
return _state.get(); _state = new state_type(f.detach());
} }
}; };
@ -51,25 +73,16 @@ namespace resumef
//这个'函数对象'被调用后返回generator<_Ty>/future_t<_Ty>类型 //这个'函数对象'被调用后返回generator<_Ty>/future_t<_Ty>类型
//然后'函数对象'作为异步执行的上下文状态保存起来 //然后'函数对象'作为异步执行的上下文状态保存起来
template<class _Ctx> 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 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; context_type _context;
counted_ptr<state_type> _state;
ctx_task_t(context_type ctx) ctx_task_t(context_type ctx)
: _context(std::move(ctx)) : _context(std::move(ctx))
{ {
_state = _context()._state; this->initialize(_context());
}
virtual state_base_t* get_state() const
{
return _state.get();
} }
}; };
} }

View File

@ -40,13 +40,13 @@ namespace resumef
RF_API void run(); RF_API void run();
//RF_API void break_all(); //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_) inline void operator + (_Ty && t_)
{ {
if constexpr(is_future_v<_Ty>) if constexpr(std::is_callable_v<_Ty>)
new_task(new task_t<_Ty>(std::forward<_Ty>(t_)));
else
new_task(new ctx_task_t<_Ty>(std::forward<_Ty>(t_))); 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 inline bool empty() const

View File

@ -15,11 +15,16 @@ namespace resumef
{ {
_coro.resume(); _coro.resume();
if (_coro.done()) if (_coro.done())
{
_coro = nullptr; _coro = nullptr;
_scheduler->del_final(this);
}
else else
{
_scheduler->add_generator(this); _scheduler->add_generator(this);
} }
} }
}
bool state_generator_t::is_ready() const bool state_generator_t::is_ready() const
{ {

View File

@ -20,8 +20,8 @@ namespace resumef
coroutine_handle<> _coro; coroutine_handle<> _coro;
public: public:
virtual void resume() = 0; virtual void resume() = 0;
virtual bool is_ready() const = 0;
virtual bool has_handler() const = 0; virtual bool has_handler() const = 0;
virtual bool is_ready() const = 0;
void set_scheduler(scheduler_t* sch) void set_scheduler(scheduler_t* sch)
{ {
@ -35,9 +35,15 @@ namespace resumef
struct state_generator_t : public state_base_t struct state_generator_t : public state_base_t
{ {
public:
state_generator_t(coroutine_handle<> handler)
{
_coro = handler;
}
virtual void resume() override; virtual void resume() override;
virtual bool is_ready() const override;
virtual bool has_handler() const override; virtual bool has_handler() const override;
virtual bool is_ready() const override;
}; };
struct state_future_t : public state_base_t struct state_future_t : public state_base_t

View File

@ -46,7 +46,7 @@ void resumable_switch(intptr_t coro, size_t idx)
{ {
for (intptr_t i = 0; i < N / coro; ++i) for (intptr_t i = 0; i < N / coro; ++i)
co_yield i; co_yield i;
return N / coro; co_return N / coro;
}; };
} }
auto middle = std::chrono::steady_clock::now(); auto middle = std::chrono::steady_clock::now();

View File

@ -9,8 +9,7 @@
using namespace resumef; using namespace resumef;
//std::experimental::generator<int> auto test_yield_int() -> generator_t<int>
auto test_yield_int() -> std::experimental::generator<int>
{ {
std::cout << "1 will yield return" << std::endl; std::cout << "1 will yield return" << std::endl;
co_yield 1; 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; std::cout << "block 1 will yield return" << std::endl;
co_yield_void; co_yield_void;

View File

@ -30,11 +30,12 @@ int main(int argc, const char* argv[])
{ {
//resumable_main_cb(); //resumable_main_cb();
//resumable_main_suspend_always(); //resumable_main_suspend_always();
resumable_main_routine(); //resumable_main_yield_return();
resumable_main_resumable();
//resumable_main_routine();
//resumable_main_exception(); //resumable_main_exception();
/* /*
resumable_main_resumable();
resumable_main_benchmark_mem(); resumable_main_benchmark_mem();
if (argc > 1) if (argc > 1)
resumable_main_benchmark_asio_client(atoi(argv[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_when_all();
resumable_main_multi_thread(); resumable_main_multi_thread();
resumable_main_yield_return();
resumable_main_timer(); resumable_main_timer();
resumable_main_sleep(); resumable_main_sleep();
resumable_main_resumable();
resumable_main_mutex(); resumable_main_mutex();
resumable_main_event(); resumable_main_event();
resumable_main_event_timeout(); resumable_main_event_timeout();

View File

@ -243,10 +243,7 @@
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild> <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild> <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild>
</ClCompile> </ClCompile>
<ClCompile Include="..\tutorial\test_async_resumable.cpp"> <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_routine.cpp" /> <ClCompile Include="..\tutorial\test_async_routine.cpp" />
<ClCompile Include="..\tutorial\test_async_sleep.cpp"> <ClCompile Include="..\tutorial\test_async_sleep.cpp">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild> <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>