mirror of
https://github.com/tearshark/librf.git
synced 2024-10-04 08:50:31 +08:00
支持generator,完成相关范例
This commit is contained in:
parent
7289258a75
commit
8d580dcda4
@ -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
|
||||||
|
@ -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;
|
||||||
};
|
};
|
||||||
|
@ -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() = 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 = 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)
|
||||||
|
{
|
||||||
|
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>类型
|
//这个'函数对象'被调用后,返回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();
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -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
|
||||||
|
@ -15,9 +15,14 @@ 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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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
|
||||||
|
@ -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();
|
||||||
|
@ -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;
|
||||||
|
@ -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();
|
||||||
|
@ -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>
|
||||||
|
Loading…
Reference in New Issue
Block a user