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>
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

View File

@ -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;
};

View File

@ -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)
{
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(future_type&& f)
: _state(std::move(f._state))
{
initialize(std::forward<future_type>(f));
}
virtual state_base_t * get_state() const
protected:
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>类型
//然后'函数对象'作为异步执行的上下文状态保存起来
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());
}
};
}

View File

@ -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

View File

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

View File

@ -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

View File

@ -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();

View File

@ -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;

View File

@ -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();

View File

@ -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>