@@ -41,7 +41,7 @@ union uarray | |||
std::atomic<intptr_t> g_echo_count = 0; | |||
future_vt RunEchoSession(tcp::socket socket) | |||
future_t<> RunEchoSession(tcp::socket socket) | |||
{ | |||
std::size_t bytes_transferred = 0; | |||
std::array<char, BUF_SIZE> buffer; | |||
@@ -73,7 +73,7 @@ void AcceptConnections(tcp::acceptor & acceptor, uarray<tcp::socket, _N> & socke | |||
{ | |||
for (size_t idx = 0; idx < socketes.c.size(); ++idx) | |||
{ | |||
go[&, idx]() -> future_vt | |||
go[&, idx]() -> future_t<> | |||
{ | |||
for (;;) | |||
{ | |||
@@ -147,7 +147,7 @@ void resumable_main_benchmark_asio_server() | |||
//---------------------------------------------------------------------------------------------------------------------- | |||
future_vt RunPipelineEchoClient(asio::io_service & ios, tcp::resolver::iterator ep) | |||
future_t<> RunPipelineEchoClient(asio::io_service & ios, tcp::resolver::iterator ep) | |||
{ | |||
std::shared_ptr<tcp::socket> sptr = std::make_shared<tcp::socket>(ios); | |||
@@ -198,7 +198,7 @@ future_vt RunPipelineEchoClient(asio::io_service & ios, tcp::resolver::iterator | |||
#if _HAS_CXX17 | |||
future_vt RunPingPongEchoClient(asio::io_service & ios, tcp::resolver::iterator ep) | |||
future_t<> RunPingPongEchoClient(asio::io_service & ios, tcp::resolver::iterator ep) | |||
{ | |||
tcp::socket socket_{ ios }; | |||
@@ -15,7 +15,7 @@ using namespace std::literals; | |||
const static auto MaxNum = 20000; | |||
using int_channel_ptr = std::shared_ptr<channel_t<intptr_t>>; | |||
static future_vt passing_next(int_channel_ptr rd, int_channel_ptr wr) | |||
static future_t<> passing_next(int_channel_ptr rd, int_channel_ptr wr) | |||
{ | |||
for (;;) | |||
{ |
@@ -20,7 +20,10 @@ | |||
#include "src/mutex.h" | |||
#include "src/channel.h" | |||
#include "src/scheduler.h" | |||
#include "src/promise.inl" | |||
#include "src/sleep.h" | |||
#include "src/awaitable.h" | |||
#if _HAS_CXX17 || RESUMEF_USE_BOOST_ANY | |||
#include "src/when.h" | |||
#endif | |||
#endif |
@@ -3,6 +3,23 @@ | |||
namespace resumef | |||
{ | |||
template<class _Derived> | |||
struct counted_t | |||
{ | |||
std::atomic<intptr_t> _count{ 0 }; | |||
void lock() | |||
{ | |||
++_count; | |||
} | |||
void unlock() | |||
{ | |||
if (--_count == 0) | |||
delete static_cast<_Derived*>(this); | |||
} | |||
}; | |||
template <typename T> | |||
struct counted_ptr | |||
{ | |||
@@ -26,8 +43,8 @@ namespace resumef | |||
{ | |||
if (&cp != this) | |||
{ | |||
_unlock(); | |||
_lock(cp._p); | |||
counted_ptr t = cp; | |||
std::swap(_p, t._p); | |||
} | |||
return *this; | |||
} |
@@ -15,6 +15,7 @@ | |||
#include <map> | |||
#include <unordered_map> | |||
#include <unordered_set> | |||
#include <optional> | |||
#include <assert.h> | |||
@@ -66,22 +67,6 @@ namespace resumef | |||
template<typename _PromiseT = void> | |||
using coroutine_handle = std::experimental::coroutine_handle<_PromiseT>; | |||
template<typename _PromiseT = void> | |||
inline void * _coro_function_ptr(coroutine_handle<> coro) | |||
{ | |||
auto frame_prefix = (coroutine_handle<void>::_Resumable_frame_prefix*)coro.address(); | |||
return reinterpret_cast<void *>(frame_prefix->_Fn); | |||
} | |||
template<typename _PromiseT> | |||
inline _PromiseT * _coro_promise_ptr__(void * _Ptr) | |||
{ | |||
using coroutine_instance = coroutine_handle<_PromiseT>; | |||
return reinterpret_cast<_PromiseT *>(reinterpret_cast<char *>(_Ptr) - coroutine_instance::_ALIGNED_SIZE); | |||
} | |||
#define _coro_promise_ptr(T) _coro_promise_ptr__<resumef::promise_t<T> >(_coro_frame_ptr()) | |||
enum struct error_code | |||
{ | |||
none, | |||
@@ -95,7 +80,6 @@ namespace resumef | |||
}; | |||
const char * get_error_string(error_code fe, const char * classname); | |||
//const char * future_error_string[size_t(future_error::max__)]; | |||
struct future_exception : std::exception | |||
{ | |||
@@ -137,11 +121,36 @@ namespace resumef | |||
} | |||
}; | |||
struct scheduler; | |||
struct state_base; | |||
struct scheduler_t; | |||
struct state_base_t; | |||
template<class _Ty = void> | |||
struct future_t; | |||
using future_vt = future_t<>; | |||
template<class _Ty = void> | |||
struct promise_t; | |||
template<class _Ty = void> | |||
struct awaitable_t; | |||
template<class _PromiseT> | |||
struct is_promise : std::false_type {}; | |||
template<class _Ty> | |||
struct is_promise<promise_t<_Ty>> : std::true_type {}; | |||
template<class _Ty> | |||
_INLINE_VAR constexpr bool is_promise_v = is_promise<std::remove_cvref_t<_Ty>>::value; | |||
template<class _PromiseT> | |||
struct is_future : std::false_type {}; | |||
template<class _Ty> | |||
struct is_future<future_t<_Ty>> : std::true_type {}; | |||
template<class _Ty> | |||
_INLINE_VAR constexpr bool is_future_v = is_future<std::remove_cvref_t<_Ty>>::value; | |||
//获得当前线程下的调度器 | |||
scheduler * this_scheduler(); | |||
scheduler_t* this_scheduler(); | |||
} | |||
#define co_yield_void co_yield nullptr |
@@ -5,380 +5,63 @@ | |||
namespace resumef | |||
{ | |||
template <typename T> | |||
template<class _Ty> | |||
struct future_impl_t | |||
{ | |||
typedef T value_type; | |||
typedef promise_t<T> promise_type; | |||
typedef state_t<T> state_type; | |||
counted_ptr<state_type> _state; | |||
using value_type = _Ty; | |||
using state_type = state_t<value_type>; | |||
using promise_type = promise_t<value_type>; | |||
using future_type = future_t<value_type>; | |||
future_impl_t(const counted_ptr<state_type>& state) : _state(state) | |||
{ | |||
} | |||
counted_ptr<state_type> _state; | |||
// movable, but not copyable | |||
future_impl_t() = default; | |||
future_impl_t(future_impl_t&& f) = default; | |||
future_impl_t & operator = (future_impl_t&& f) = default; | |||
future_impl_t(counted_ptr<state_type> _st) | |||
:_state(std::move(_st)) {} | |||
future_impl_t(const future_impl_t&) = default; | |||
future_impl_t & operator = (const future_impl_t&) = default; | |||
future_impl_t(future_impl_t&&) = default; | |||
//------------------------------------------------------------------------------------------ | |||
//以下是与编译器生成的resumable function交互的接口 | |||
future_impl_t& operator = (const future_impl_t&) = default; | |||
future_impl_t& operator = (future_impl_t&&) = default; | |||
bool await_ready() | |||
{ | |||
return _state->ready(); | |||
} | |||
void await_suspend(coroutine_handle<> resume_cb) | |||
{ | |||
_state->await_suspend(resume_cb); | |||
} | |||
//return_value, return_void只能由派生类去实现 | |||
//以上是与编译器生成的resumable function交互的接口 | |||
//------------------------------------------------------------------------------------------ | |||
//if ready, can get value | |||
bool ready() | |||
{ | |||
return _state->ready(); | |||
} | |||
auto & get_value() | |||
{ | |||
return _state->get_value(); | |||
} | |||
bool is_suspend() const | |||
{ | |||
return _state->is_suspend(); | |||
} | |||
bool cancellation_requested() const | |||
{ | |||
return _state->cancellation_requested(); | |||
return _state->has_value(); | |||
} | |||
void set_exception(std::exception_ptr e_) | |||
template<class _PromiseT, typename = std::enable_if_t<is_promise_v<_PromiseT>>> | |||
void await_suspend(coroutine_handle<_PromiseT> handler) | |||
{ | |||
_state->set_exception(std::move(e_)); | |||
} | |||
void cancel() | |||
{ | |||
_state->cancel(); | |||
_PromiseT& promise = handler.promise(); | |||
scheduler_t* sch = promise._state->_scheduler; | |||
sch->add_await(_state.get(), handler); | |||
} | |||
}; | |||
template <typename T = void> | |||
struct future_t : public future_impl_t<T> | |||
template<class _Ty> | |||
struct future_t : public future_impl_t<_Ty> | |||
{ | |||
using state_type = typename future_impl_t<T>::state_type; | |||
using future_impl_t<T>::_state; | |||
using future_impl_t::future_impl_t; | |||
using future_impl_t::_state; | |||
future_t(const counted_ptr<state_type>& state) | |||
: future_impl_t<T>(state) | |||
value_type await_resume() | |||
{ | |||
if (_state->_exception) | |||
std::rethrow_exception(std::move(_state->_exception)); | |||
return std::move(_state->_value.value()); | |||
} | |||
// movable, but not copyable | |||
future_t(const future_t&) = default; | |||
future_t(future_t&& f) = default; | |||
future_t() = default; | |||
future_t & operator = (const future_t&) = default; | |||
future_t & operator = (future_t&& f) = default; | |||
//------------------------------------------------------------------------------------------ | |||
//以下是与编译器生成的resumable function交互的接口 | |||
T await_resume() | |||
{ | |||
_state->rethrow_if_exception(); | |||
return std::move(_state->get_value()); | |||
} | |||
void return_value(const T& val) | |||
{ | |||
_state->set_value(val); | |||
} | |||
void return_value(T&& val) | |||
{ | |||
_state->set_value(std::forward<T>(val)); | |||
} | |||
//以上是与编译器生成的resumable function交互的接口 | |||
//------------------------------------------------------------------------------------------ | |||
}; | |||
template <> | |||
template<> | |||
struct future_t<void> : public future_impl_t<void> | |||
{ | |||
using future_impl_t<void>::_state; | |||
future_t(const counted_ptr<state_type>& state) | |||
: future_impl_t<void>(state) | |||
{ | |||
} | |||
// movable, but not copyable | |||
future_t(const future_t&) = default; | |||
future_t(future_t&& f) = default; | |||
future_t() = default; | |||
future_t & operator = (const future_t&) = default; | |||
future_t & operator = (future_t&& f) = default; | |||
//------------------------------------------------------------------------------------------ | |||
//以下是与编译器生成的resumable function交互的接口 | |||
using future_impl_t::future_impl_t; | |||
using future_impl_t::_state; | |||
void await_resume() | |||
{ | |||
_state->rethrow_if_exception(); | |||
return _state->get_value(); | |||
if (_state->_exception) | |||
std::rethrow_exception(std::move(_state->_exception)); | |||
} | |||
void return_void() | |||
{ | |||
_state->set_value(); | |||
} | |||
//以上是与编译器生成的resumable function交互的接口 | |||
//------------------------------------------------------------------------------------------ | |||
}; | |||
using future_vt = future_t<void>; | |||
template <typename T> | |||
struct promise_impl_t | |||
{ | |||
typedef future_t<T> future_type; | |||
typedef state_t<T> state_type; | |||
counted_ptr<state_type> _state; | |||
// movable not copyable | |||
promise_impl_t() | |||
: _state(make_counted<state_type>()) | |||
{ | |||
#if RESUMEF_ENABLE_MULT_SCHEDULER | |||
_state->this_promise(this); | |||
#endif | |||
} | |||
promise_impl_t(promise_impl_t&& _Right) noexcept | |||
: _state(std::move(_Right._state)) | |||
{ | |||
#if RESUMEF_ENABLE_MULT_SCHEDULER | |||
_state->this_promise(this); | |||
#endif | |||
} | |||
promise_impl_t & operator = (promise_impl_t&& _Right) noexcept | |||
{ | |||
if (this != _Right) | |||
{ | |||
_state = std::move(_Right._state); | |||
#if RESUMEF_ENABLE_MULT_SCHEDULER | |||
_state->this_promise(this); | |||
#endif | |||
} | |||
return *this; | |||
} | |||
promise_impl_t(const promise_impl_t&) = delete; | |||
promise_impl_t & operator = (const promise_impl_t&) = delete; | |||
//这个函数,用于callback里,返回关联的future对象 | |||
//callback里,不应该调用 get_return_object() | |||
future_type get_future() | |||
{ | |||
return future_type(_state); | |||
} | |||
// Most functions don't need this but timers and reads from streams | |||
// cause multiple callbacks. | |||
future_type next_future() | |||
{ | |||
return future_type(_state); | |||
} | |||
//------------------------------------------------------------------------------------------ | |||
//以下是与编译器生成的resumable function交互的接口 | |||
//如果在协程外启动一个resumable function,则: | |||
// 1、即将交给调度器调度 | |||
// 2、手工获取结果(将来支持) | |||
// 无论哪种情况,都返回未准备好。则编译器调用await_suspend()获得继续运行的resume_cb | |||
//如果在协程内启动一个resumable function,则: | |||
// 1、即将交给调度器调度 | |||
// 2、通过await启动另外一个子函数 | |||
// (1)情况下,无法区分是否已经拥有的resume_cb,可以特殊处理 | |||
// (2)情况下,返回准备好了,让编译器继续运行 | |||
auto initial_suspend() noexcept | |||
{ | |||
return std::experimental::suspend_never{}; | |||
} | |||
//这在一个协程被销毁之时调用。 | |||
//我们选择不挂起协程,只是通知state的对象,本协程已经准备好了删除了 | |||
auto final_suspend() noexcept | |||
{ | |||
_state->final_suspend(); | |||
return std::experimental::suspend_never{}; | |||
} | |||
//返回与之关联的future对象 | |||
future_type get_return_object() | |||
{ | |||
return future_type(_state); | |||
} | |||
void set_exception(std::exception_ptr e_) | |||
{ | |||
_state->set_exception(std::move(e_)); | |||
} | |||
bool cancellation_requested() | |||
{ | |||
return _state->cancellation_requested(); | |||
} | |||
/* | |||
void unhandled_exception() | |||
{ | |||
std::terminate(); | |||
} | |||
*/ | |||
//return_value/return_void 只能由派生类去实现 | |||
//以上是与编译器生成的resumable function交互的接口 | |||
//------------------------------------------------------------------------------------------ | |||
}; | |||
template <typename T> | |||
struct promise_t : public promise_impl_t<T> | |||
{ | |||
typedef promise_t<T> promise_type; | |||
using promise_impl_t<T>::_state; | |||
//------------------------------------------------------------------------------------------ | |||
//以下是与编译器生成的resumable function交互的接口 | |||
void return_value(const T& val) | |||
{ | |||
_state->set_value(val); | |||
} | |||
void return_value(T&& val) | |||
{ | |||
_state->set_value(std::forward<T>(val)); | |||
} | |||
void yield_value(const T& val) | |||
{ | |||
_state->set_value(val); | |||
} | |||
void yield_value(T&& val) | |||
{ | |||
_state->set_value(std::forward<T>(val)); | |||
} | |||
//以上是与编译器生成的resumable function交互的接口 | |||
//------------------------------------------------------------------------------------------ | |||
//兼容std::promise<>用法 | |||
void set_value(const T& val) | |||
{ | |||
_state->set_value(val); | |||
} | |||
void set_value(T&& val) | |||
{ | |||
_state->set_value(std::forward<T>(val)); | |||
} | |||
}; | |||
template <> | |||
struct promise_t<void> : public promise_impl_t<void> | |||
{ | |||
typedef promise_t<void> promise_type; | |||
using promise_impl_t<void>::_state; | |||
//------------------------------------------------------------------------------------------ | |||
//以下是与编译器生成的resumable function交互的接口 | |||
void return_void() | |||
{ | |||
_state->set_value(); | |||
} | |||
//以上是与编译器生成的resumable function交互的接口 | |||
//------------------------------------------------------------------------------------------ | |||
//兼容std::promise<>用法 | |||
void set_value() | |||
{ | |||
_state->set_value(); | |||
} | |||
}; | |||
using promise_vt = promise_t<void>; | |||
/* | |||
template <typename T = void> | |||
struct awaitable_t | |||
{ | |||
typedef state_t<T> state_type; | |||
counted_ptr<state_type> _state; | |||
// movable not copyable | |||
awaitable_t() | |||
: _state(make_counted<state_type>()) | |||
{ | |||
} | |||
// movable, but not copyable | |||
awaitable_t(const awaitable_t&) = delete; | |||
awaitable_t(awaitable_t&& f) = default; | |||
awaitable_t & operator = (const awaitable_t&) = delete; | |||
awaitable_t & operator = (awaitable_t&& f) = default; | |||
//------------------------------------------------------------------------------------------ | |||
//以下是与编译器生成的resumable function交互的接口 | |||
bool await_ready() | |||
{ | |||
return _state->ready(); | |||
} | |||
void await_suspend(coroutine_handle<> resume_cb) | |||
{ | |||
_state->await_suspend(resume_cb); | |||
} | |||
T await_resume() | |||
{ | |||
_state->rethrow_if_exception(); | |||
return _state->get_value(); | |||
} | |||
//以上是与编译器生成的resumable function交互的接口 | |||
//------------------------------------------------------------------------------------------ | |||
}; | |||
using awaitable_vt = awaitable_t<void>; | |||
*/ | |||
#if RESUMEF_ENABLE_MULT_SCHEDULER | |||
inline promise_t<void> * state_base::parent_promise() const | |||
{ | |||
if (_coro) return _coro_promise_ptr__<promise_t<void>>(_coro.address()); | |||
return nullptr; | |||
} | |||
inline scheduler * state_base::parent_scheduler() const | |||
{ | |||
auto promise_ = parent_promise(); | |||
if (promise_) | |||
return promise_->_state->current_scheduler(); | |||
return nullptr; | |||
} | |||
#endif | |||
} | |||
@@ -5,20 +5,13 @@ | |||
namespace resumef | |||
{ | |||
task_base::task_base() | |||
task_base_t::task_base_t() | |||
: _next_node(nullptr) | |||
, _prev_node(nullptr) | |||
{ | |||
#if RESUMEF_DEBUG_COUNTER | |||
++g_resumef_task_count; | |||
#endif | |||
} | |||
task_base::~task_base() | |||
task_base_t::~task_base_t() | |||
{ | |||
#if RESUMEF_DEBUG_COUNTER | |||
--g_resumef_task_count; | |||
#endif | |||
} | |||
} |
@@ -2,28 +2,21 @@ | |||
#include "def.h" | |||
#include "future.h" | |||
#include "promise.h" | |||
namespace resumef | |||
{ | |||
struct task_base; | |||
struct task_base_t; | |||
struct task_base | |||
struct task_base_t | |||
{ | |||
RF_API task_base(); | |||
RF_API virtual ~task_base(); | |||
//如果返回true,则不会调用go_next() | |||
virtual bool is_suspend() = 0; | |||
//返回true,表示任务还未完成,后续还需要继续执行 | |||
//否则,任务从调度器里删除 | |||
virtual bool go_next(scheduler *) = 0; | |||
virtual void cancel() = 0; | |||
virtual void * get_id() = 0; | |||
#if RESUMEF_ENABLE_MULT_SCHEDULER | |||
virtual void bind(scheduler *) = 0; | |||
#endif | |||
task_base * _next_node; | |||
task_base * _prev_node; | |||
RF_API task_base_t(); | |||
RF_API virtual ~task_base_t(); | |||
virtual state_base_t * get_state() const = 0; | |||
task_base_t* _next_node; | |||
task_base_t* _prev_node; | |||
}; | |||
//---------------------------------------------------------------------------------------------- | |||
@@ -31,116 +24,25 @@ namespace resumef | |||
template<class _Ty> | |||
struct task_t; | |||
//task_t接受的是一个experimental::generator<_Ty>类型,是调用一个支持异步的函数后返回的结果 | |||
template<class _Ty> | |||
struct task_t<std::experimental::generator<_Ty> > : public task_base | |||
{ | |||
typedef std::experimental::generator<_Ty> future_type; | |||
typedef typename future_type::iterator iterator_type; | |||
future_type _future; | |||
iterator_type _iterator; | |||
bool _ready; | |||
task_t() | |||
: _iterator(nullptr) | |||
, _ready(false) | |||
{ | |||
} | |||
task_t(future_type && f) | |||
: _future(std::forward<future_type>(f)) | |||
, _iterator(nullptr) | |||
, _ready(false) | |||
{ | |||
} | |||
virtual bool is_suspend() override | |||
{ | |||
return false; | |||
} | |||
virtual bool go_next(scheduler *) override | |||
{ | |||
if (!this->_ready) | |||
{ | |||
this->_iterator = this->_future.begin(); | |||
this->_ready = true; | |||
} | |||
if (this->_iterator != this->_future.end()) | |||
{ | |||
return (++this->_iterator) != this->_future.end(); | |||
} | |||
return false; | |||
} | |||
virtual void cancel() override | |||
{ | |||
} | |||
virtual void * get_id() override | |||
{ | |||
return nullptr; | |||
} | |||
#if RESUMEF_ENABLE_MULT_SCHEDULER | |||
virtual void bind(scheduler *) override | |||
{ | |||
} | |||
#endif | |||
}; | |||
template<class _Ty> | |||
struct task_t<future_t<_Ty> > : public task_base | |||
struct task_t<future_t<_Ty>> : public task_base_t | |||
{ | |||
typedef future_t<_Ty> future_type; | |||
using value_type = _Ty; | |||
using future_type = future_t<value_type>; | |||
using state_type = state_t<value_type>; | |||
future_type _future; | |||
counted_ptr<state_type> _state; | |||
task_t() = default; | |||
task_t(future_type && f) | |||
: _future(std::forward<future_type>(f)) | |||
{ | |||
} | |||
//如果返回true,则不会调用go_next() | |||
// | |||
//如果第一次运行,则state应该有: | |||
// _coro != nullptr | |||
// _ready == false | |||
//运行一次后,则state应该是: | |||
// _coro == nullptr | |||
// _ready == false | |||
//最后一次运行,则state应该是: | |||
// _coro == nullptr | |||
// _ready == true | |||
virtual bool is_suspend() override | |||
: _state(std::move(f._state)) | |||
{ | |||
auto * _state = _future._state.get(); | |||
return _state->is_suspend(); | |||
} | |||
//返回true,表示任务还未完成,后续还需要继续执行 | |||
//否则,任务从调度器里删除 | |||
virtual bool go_next(scheduler * ) override | |||
{ | |||
auto * _state = _future._state.get(); | |||
_state->resume(); | |||
return !_state->ready() && !_state->done(); | |||
} | |||
virtual void cancel() override | |||
{ | |||
_future.cancel(); | |||
} | |||
virtual void * get_id() override | |||
virtual state_base_t * get_state() const | |||
{ | |||
return _future._state.get(); | |||
return _state.get(); | |||
} | |||
#if RESUMEF_ENABLE_MULT_SCHEDULER | |||
virtual void bind(scheduler * schdler) override | |||
{ | |||
auto * _state = _future._state.get(); | |||
_state->current_scheduler(schdler); | |||
} | |||
#endif | |||
}; | |||
//---------------------------------------------------------------------------------------------- | |||
@@ -149,24 +51,25 @@ namespace resumef | |||
//这个'函数对象'被调用后,返回generator<_Ty>/future_t<_Ty>类型 | |||
//然后'函数对象'作为异步执行的上下文状态保存起来 | |||
template<class _Ctx> | |||
struct ctx_task_t : public task_t<typename std::remove_cvref<decltype(std::declval<_Ctx>()())>::type> | |||
struct ctx_task_t : public task_base_t | |||
{ | |||
typedef task_t<typename std::remove_cvref<decltype(std::declval<_Ctx>()())>::type> base_type; | |||
using base_type::_future; | |||
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>; | |||
typedef _Ctx context_type; | |||
context_type _context; | |||
counted_ptr<state_type> _state; | |||
ctx_task_t(context_type && ctx) | |||
: _context(std::forward<context_type>(ctx)) | |||
ctx_task_t(context_type ctx) | |||
: _context(std::move(ctx)) | |||
{ | |||
_future = std::move(_context()); | |||
_state = _context()._state; | |||
} | |||
ctx_task_t(const context_type & ctx) | |||
: _context(ctx) | |||
virtual state_base_t* get_state() const | |||
{ | |||
_future = std::move(_context()); | |||
return _state.get(); | |||
} | |||
}; | |||
} |
@@ -10,7 +10,6 @@ std::atomic<intptr_t> g_resumef_evtctx_count = 0; | |||
namespace resumef | |||
{ | |||
static const char * future_error_string[(size_t)error_code::max__] | |||
{ | |||
"none", | |||
@@ -34,12 +33,12 @@ namespace resumef | |||
} | |||
#if RESUMEF_ENABLE_MULT_SCHEDULER | |||
thread_local scheduler * th_scheduler_ptr = nullptr; | |||
thread_local scheduler_t * th_scheduler_ptr = nullptr; | |||
//获得当前线程下的调度器 | |||
scheduler * this_scheduler() | |||
scheduler_t * this_scheduler() | |||
{ | |||
return th_scheduler_ptr ? th_scheduler_ptr : &scheduler::g_scheduler; | |||
return th_scheduler_ptr ? th_scheduler_ptr : &scheduler_t::g_scheduler; | |||
} | |||
#endif | |||
@@ -48,7 +47,7 @@ namespace resumef | |||
#if RESUMEF_ENABLE_MULT_SCHEDULER | |||
if (th_scheduler_ptr == nullptr) | |||
{ | |||
_scheduler_ptr = new scheduler; | |||
_scheduler_ptr = new scheduler_t; | |||
th_scheduler_ptr = _scheduler_ptr; | |||
} | |||
#endif | |||
@@ -63,14 +62,14 @@ namespace resumef | |||
#endif | |||
} | |||
scheduler::scheduler() | |||
scheduler_t::scheduler_t() | |||
: _task() | |||
, _ready_task() | |||
, _timer(std::make_shared<timer_manager>()) | |||
{ | |||
} | |||
scheduler::~scheduler() | |||
scheduler_t::~scheduler_t() | |||
{ | |||
cancel_all_task_(); | |||
#if RESUMEF_ENABLE_MULT_SCHEDULER | |||
@@ -79,19 +78,18 @@ namespace resumef | |||
#endif | |||
} | |||
void scheduler::new_task(task_base * task) | |||
void scheduler_t::new_task(task_base_t * task) | |||
{ | |||
if (task) | |||
{ | |||
scoped_lock<spinlock> __guard(_mtx_ready); | |||
#if RESUMEF_ENABLE_MULT_SCHEDULER | |||
task->bind(this); | |||
#endif | |||
this->_ready_task.push_back(task); | |||
this->add_initial(task->get_state()); | |||
} | |||
} | |||
void scheduler::cancel_all_task_() | |||
void scheduler_t::cancel_all_task_() | |||
{ | |||
{ | |||
scoped_lock<lock_type> __guard(_mtx_task); | |||
@@ -103,7 +101,7 @@ namespace resumef | |||
} | |||
} | |||
void scheduler::break_all() | |||
void scheduler_t::break_all() | |||
{ | |||
cancel_all_task_(); | |||
@@ -111,7 +109,7 @@ namespace resumef | |||
this->_timer->clear(); | |||
} | |||
void scheduler::run_one_batch() | |||
void scheduler_t::run_one_batch() | |||
{ | |||
#if RESUMEF_ENABLE_MULT_SCHEDULER | |||
if (th_scheduler_ptr == nullptr) | |||
@@ -122,42 +120,23 @@ namespace resumef | |||
this->_timer->update(); | |||
using namespace std::chrono; | |||
for (auto task = this->_task.begin(); task != nullptr; ) | |||
{ | |||
#if _DEBUG | |||
#define MAX_TIME_COST 10000us | |||
#else | |||
#define MAX_TIME_COST 1000us | |||
#endif | |||
// time_cost_evaluation<microseconds> eva(MAX_TIME_COST); | |||
if (task->is_suspend() || task->go_next(this)) | |||
{ | |||
// eva.add("coscheduler"); | |||
task = task->_next_node; | |||
continue; | |||
} | |||
task = this->_task.erase(task, false); | |||
} | |||
{ | |||
scoped_lock<spinlock> __guard(_mtx_ready); | |||
if (!this->_ready_task.empty()) | |||
{ | |||
this->_task.merge_back(this->_ready_task); | |||
} | |||
} | |||
state_vector states = std::move(_runing_states); | |||
for (state_sptr& sptr : states) | |||
sptr->resume(); | |||
} | |||
} | |||
void scheduler::run_until_notask() | |||
void scheduler_t::run_until_notask() | |||
{ | |||
while (!this->empty()) | |||
this->run_one_batch(); | |||
} | |||
scheduler scheduler::g_scheduler; | |||
void scheduler_t::run() | |||
{ | |||
for (;;) | |||
this->run_one_batch(); | |||
} | |||
scheduler_t scheduler_t::g_scheduler; | |||
} |
@@ -14,8 +14,12 @@ namespace resumef | |||
{ | |||
struct local_scheduler; | |||
struct scheduler : public std::enable_shared_from_this<scheduler> | |||
struct scheduler_t : public std::enable_shared_from_this<scheduler_t> | |||
{ | |||
using state_sptr = std::shared_ptr<state_base_t>; | |||
using state_vector = std::vector<state_sptr>; | |||
private: | |||
state_vector _runing_states; | |||
private: | |||
//typedef spinlock lock_type; | |||
typedef std::recursive_mutex lock_type; | |||
@@ -27,26 +31,26 @@ namespace resumef | |||
task_list _task; | |||
timer_mgr_ptr _timer; | |||
RF_API void new_task(task_base * task); | |||
RF_API void new_task(task_base_t * task); | |||
void cancel_all_task_(); | |||
public: | |||
RF_API void run_one_batch(); | |||
RF_API void run_until_notask(); | |||
RF_API void run(); | |||
template<class _Ty> | |||
template<class _Ty, typename = std::enable_if_t<std::is_callable_v<_Ty> || is_future_v<_Ty>>> | |||
inline void operator + (_Ty && t_) | |||
{ | |||
typedef typename std::conditional< | |||
std::is_callable<_Ty>::value, | |||
ctx_task_t<_Ty>, | |||
task_t<_Ty> >::type task_type; | |||
return new_task(new task_type(std::forward<_Ty>(t_))); | |||
if constexpr(is_future_v<_Ty>) | |||
new_task(new task_t<_Ty>(std::forward<_Ty>(t_))); | |||
else | |||
new_task(new ctx_task_t<_Ty>(std::forward<_Ty>(t_))); | |||
} | |||
inline void push_task_internal(task_base * t_) | |||
inline void push_task_internal(task_base_t * t_) | |||
{ | |||
return new_task(t_); | |||
new_task(t_); | |||
} | |||
inline bool empty() const | |||
@@ -66,17 +70,38 @@ namespace resumef | |||
friend struct task_base; | |||
friend struct local_scheduler; | |||
void add_initial(state_base_t* sptr) | |||
{ | |||
sptr->_scheduler = this; | |||
assert(sptr->_coro != nullptr); | |||
_runing_states.emplace_back(sptr); | |||
} | |||
void add_await(state_base_t* sptr, coroutine_handle<> handler) | |||
{ | |||
sptr->_scheduler = this; | |||
sptr->_coro = handler; | |||
if (sptr->has_value() || sptr->_exception != nullptr) | |||
_runing_states.emplace_back(sptr); | |||
} | |||
void add_ready(state_base_t* sptr) | |||
{ | |||
assert(sptr->_scheduler == this); | |||
if (sptr->_coro != nullptr) | |||
_runing_states.emplace_back(sptr); | |||
} | |||
protected: | |||
RF_API scheduler(); | |||
RF_API scheduler_t(); | |||
public: | |||
RF_API ~scheduler(); | |||
RF_API ~scheduler_t(); | |||
scheduler(scheduler && right_) = delete; | |||
scheduler & operator = (scheduler && right_) = delete; | |||
scheduler(const scheduler &) = delete; | |||
scheduler & operator = (const scheduler &) = delete; | |||
scheduler_t(scheduler_t&& right_) = delete; | |||
scheduler_t& operator = (scheduler_t&& right_) = delete; | |||
scheduler_t(const scheduler_t&) = delete; | |||
scheduler_t& operator = (const scheduler_t&) = delete; | |||
static scheduler g_scheduler; | |||
static scheduler_t g_scheduler; | |||
}; | |||
struct local_scheduler | |||
@@ -90,21 +115,21 @@ namespace resumef | |||
local_scheduler & operator = (const local_scheduler &) = delete; | |||
#if RESUMEF_ENABLE_MULT_SCHEDULER | |||
private: | |||
scheduler * _scheduler_ptr; | |||
scheduler_t* _scheduler_ptr; | |||
#endif | |||
}; | |||
//-------------------------------------------------------------------------------------------------- | |||
#if !RESUMEF_ENABLE_MULT_SCHEDULER | |||
//获得当前线程下的调度器 | |||
inline scheduler * this_scheduler() | |||
inline scheduler_t* this_scheduler() | |||
{ | |||
return &scheduler::g_scheduler; | |||
return &scheduler_t::g_scheduler; | |||
} | |||
#endif | |||
#if !defined(_DISABLE_RESUMEF_GO_MACRO) | |||
#define go (*::resumef::this_scheduler()) + | |||
#define GO (*::resumef::this_scheduler()) + [=]()mutable->resumef::future_vt | |||
#define GO (*::resumef::this_scheduler()) + [=]()mutable->resumef::future_t<> | |||
#endif | |||
//-------------------------------------------------------------------------------------------------- |
@@ -4,7 +4,7 @@ | |||
namespace resumef | |||
{ | |||
future_vt sleep_until_(const std::chrono::system_clock::time_point& tp_, scheduler & scheduler_) | |||
future_t<> sleep_until_(const std::chrono::system_clock::time_point& tp_, scheduler_t& scheduler_) | |||
{ | |||
promise_vt awaitable; | |||
@@ -6,39 +6,39 @@ | |||
namespace resumef | |||
{ | |||
struct scheduler; | |||
struct scheduler_t; | |||
RF_API future_vt sleep_until_(const std::chrono::system_clock::time_point& tp_, scheduler & scheduler_); | |||
RF_API future_t<> sleep_until_(const std::chrono::system_clock::time_point& tp_, scheduler_t& scheduler_); | |||
inline future_vt sleep_for_(const std::chrono::system_clock::duration& dt_, scheduler & scheduler_) | |||
inline future_t<> sleep_for_(const std::chrono::system_clock::duration& dt_, scheduler_t& scheduler_) | |||
{ | |||
return std::move(sleep_until_(std::chrono::system_clock::now() + dt_, scheduler_)); | |||
} | |||
template<class _Rep, class _Period> | |||
inline future_vt sleep_for(const std::chrono::duration<_Rep, _Period>& dt_, scheduler & scheduler_) | |||
inline future_t<> sleep_for(const std::chrono::duration<_Rep, _Period>& dt_, scheduler_t& scheduler_) | |||
{ | |||
return sleep_for_(std::chrono::duration_cast<std::chrono::system_clock::duration>(dt_), scheduler_); | |||
} | |||
template<class _Rep, class _Period> | |||
inline future_vt sleep_for(const std::chrono::duration<_Rep, _Period>& dt_) | |||
inline future_t<> sleep_for(const std::chrono::duration<_Rep, _Period>& dt_) | |||
{ | |||
return sleep_for_(std::chrono::duration_cast<std::chrono::system_clock::duration>(dt_), *this_scheduler()); | |||
} | |||
template<class _Clock, class _Duration = typename _Clock::duration> | |||
inline future_vt sleep_until(const std::chrono::time_point<_Clock, _Duration>& tp_, scheduler & scheduler_) | |||
inline future_t<> sleep_until(const std::chrono::time_point<_Clock, _Duration>& tp_, scheduler_t& scheduler_) | |||
{ | |||
return sleep_until_(std::chrono::time_point_cast<std::chrono::system_clock::duration>(tp_), scheduler_); | |||
} | |||
template<class _Clock, class _Duration> | |||
inline future_vt sleep_until(const std::chrono::time_point<_Clock, _Duration>& tp_) | |||
inline future_t<> sleep_until(const std::chrono::time_point<_Clock, _Duration>& tp_) | |||
{ | |||
return sleep_until_(std::chrono::time_point_cast<std::chrono::system_clock::duration>(tp_), *this_scheduler()); | |||
} | |||
template <class Rep, class Period> | |||
inline future_vt operator co_await(std::chrono::duration<Rep, Period> dt_) | |||
inline future_t<> operator co_await(std::chrono::duration<Rep, Period> dt_) | |||
{ | |||
return sleep_for(dt_); | |||
} |
@@ -5,121 +5,7 @@ | |||
namespace resumef | |||
{ | |||
template<class state_tt> | |||
struct awaitable_task_t : public task_base | |||
state_base_t::~state_base_t() | |||
{ | |||
counted_ptr<state_tt> _state; | |||
awaitable_task_t() {} | |||
awaitable_task_t(state_tt * state) | |||
: _state(state) | |||
{ | |||
} | |||
virtual bool is_suspend() override | |||
{ | |||
return !_state->ready(); | |||
} | |||
virtual bool go_next(scheduler * ) override | |||
{ | |||
_state->resume(); | |||
return false; | |||
} | |||
virtual void cancel() override | |||
{ | |||
_state->cancel(); | |||
} | |||
virtual void * get_id() override | |||
{ | |||
return _state.get(); | |||
} | |||
#if RESUMEF_ENABLE_MULT_SCHEDULER | |||
virtual void bind(scheduler * ) override | |||
{ | |||
} | |||
#endif | |||
}; | |||
state_base::~state_base() | |||
{ | |||
#if RESUMEF_DEBUG_COUNTER | |||
--g_resumef_state_count; | |||
#endif | |||
} | |||
void state_base::set_value_none_lock() | |||
{ | |||
// Set all members first as calling coroutine may reset stuff here. | |||
_ready = true; | |||
if (_coro) | |||
{ | |||
#if RESUMEF_ENABLE_MULT_SCHEDULER | |||
auto sch_ = this->current_scheduler(); | |||
#else | |||
auto sch_ = this_scheduler(); | |||
#endif | |||
if(sch_) sch_->push_task_internal(new awaitable_task_t<state_base>(this)); | |||
} | |||
} | |||
void state_base::set_exception(std::exception_ptr && e_) | |||
{ | |||
scoped_lock<lock_type> __guard(_mtx); | |||
_exception = std::move(e_); | |||
// Set all members first as calling coroutine may reset stuff here. | |||
_ready = true; | |||
if (_coro) | |||
{ | |||
#if RESUMEF_ENABLE_MULT_SCHEDULER | |||
auto sch_ = this->current_scheduler(); | |||
#else | |||
auto sch_ = this_scheduler(); | |||
#endif | |||
if (sch_) sch_->push_task_internal(new awaitable_task_t<state_base>(this)); | |||
} | |||
} | |||
void state_base::await_suspend(coroutine_handle<> resume_cb) | |||
{ | |||
scoped_lock<lock_type> __guard(_mtx); | |||
_coro = resume_cb; | |||
#if RESUMEF_ENABLE_MULT_SCHEDULER | |||
if (_current_scheduler == nullptr) | |||
{ | |||
auto * promise_ = this->parent_promise(); | |||
if (promise_) | |||
{ | |||
scheduler * sch_ = promise_->_state->current_scheduler(); | |||
if (sch_) | |||
this->current_scheduler(sch_); | |||
else | |||
promise_->_state->_depend_states.push_back(counted_ptr<state_base>(this)); | |||
} | |||
} | |||
else | |||
{ | |||
for (auto & stptr : _depend_states) | |||
stptr->current_scheduler(_current_scheduler); | |||
_depend_states.clear(); | |||
} | |||
#endif | |||
} | |||
#if RESUMEF_ENABLE_MULT_SCHEDULER | |||
void state_base::current_scheduler(scheduler * sch_) | |||
{ | |||
scoped_lock<lock_type> __guard(_mtx); | |||
_current_scheduler = sch_; | |||
for (auto & stptr : _depend_states) | |||
stptr->current_scheduler(sch_); | |||
_depend_states.clear(); | |||
} | |||
#endif | |||
} |
@@ -8,255 +8,48 @@ | |||
namespace resumef | |||
{ | |||
template <typename T = void> | |||
struct promise_t; | |||
struct state_base | |||
struct state_base_t : public counted_t<state_base_t> | |||
{ | |||
protected: | |||
//typedef spinlock lock_type; | |||
typedef std::recursive_mutex lock_type; | |||
lock_type _mtx; //for value, _exception | |||
RF_API void set_value_none_lock(); | |||
#if RESUMEF_ENABLE_MULT_SCHEDULER | |||
private: | |||
std::atomic<void *> _this_promise = nullptr; | |||
scheduler * _current_scheduler = nullptr; | |||
std::vector<counted_ptr<state_base>> _depend_states; | |||
#endif | |||
protected: | |||
lock_type _mtx; | |||
scheduler_t * _scheduler = nullptr; | |||
coroutine_handle<> _coro; | |||
std::atomic<intptr_t> _count{0}; // tracks reference count of state object | |||
std::exception_ptr _exception; | |||
std::atomic<bool> _ready = false; | |||
std::atomic<bool> _cancellation = false; | |||
std::atomic<bool> _done = false; | |||
public: | |||
state_base() noexcept | |||
{ | |||
#if RESUMEF_DEBUG_COUNTER | |||
++g_resumef_state_count; | |||
#endif | |||
} | |||
//某个地方的代码,发生过截断,导致了内存泄漏。还是加上虚析构函数吧。 | |||
virtual ~state_base(); | |||
state_base(state_base&&) = delete; | |||
state_base(const state_base&) = delete; | |||
state_base & operator = (state_base&&) = delete; | |||
state_base & operator = (const state_base&) = delete; | |||
RF_API void set_exception(std::exception_ptr && e_); | |||
template<class _Exp> | |||
void throw_exception(const _Exp & e_) | |||
{ | |||
set_exception(std::make_exception_ptr(e_)); | |||
} | |||
void rethrow_if_exception() | |||
{ | |||
if (_exception) | |||
std::rethrow_exception(_exception); | |||
} | |||
bool ready() const | |||
{ | |||
return _ready; | |||
} | |||
bool done() const | |||
{ | |||
return _done; | |||
} | |||
void reset_none_lock() | |||
{ | |||
_coro = nullptr; | |||
_ready = false; | |||
} | |||
void cancel() | |||
{ | |||
scoped_lock<lock_type> __guard(_mtx); | |||
_cancellation = true; | |||
_coro = nullptr; | |||
} | |||
RF_API virtual ~state_base_t(); | |||
virtual bool has_value() const = 0; | |||
bool is_suspend() const | |||
{ | |||
return !_coro && !(_done || _ready || _cancellation); | |||
} | |||
void resume() | |||
{ | |||
scoped_lock<lock_type> __guard(_mtx); | |||
if (_coro) | |||
{ | |||
#if RESUMEF_DEBUG_COUNTER | |||
{ | |||
scoped_lock<std::mutex> __lock(g_resumef_cout_mutex); | |||
std::cout | |||
<< "coro=" << _coro.address() | |||
<< ",thread=" << std::this_thread::get_id() | |||
#if RESUMEF_ENABLE_MULT_SCHEDULER | |||
<< ",scheduler=" << current_scheduler() | |||
<< ",this_promise=" << this_promise() | |||
<< ",parent_promise=" << parent_promise() | |||
#endif | |||
<< std::endl; | |||
} | |||
#endif | |||
auto coro = _coro; | |||
_coro = nullptr; | |||
coro(); | |||
} | |||
} | |||
state_base* lock() | |||
{ | |||
++_count; | |||
return this; | |||
} | |||
void unlock() | |||
{ | |||
if (--_count == 0) | |||
delete this; | |||
} | |||
#if RESUMEF_ENABLE_MULT_SCHEDULER | |||
promise_t<void> * parent_promise() const; | |||
scheduler * parent_scheduler() const; | |||
void * this_promise() const | |||
{ | |||
return _this_promise; | |||
} | |||
void this_promise(void * promise_) | |||
{ | |||
_this_promise = promise_; | |||
} | |||
scheduler * current_scheduler() const | |||
{ | |||
return _current_scheduler; | |||
} | |||
void current_scheduler(scheduler * sch_); | |||
#endif | |||
//------------------------------------------------------------------------------------------ | |||
//以下是通过future_t/promise_t, 与编译器生成的resumable function交互的接口 | |||
void await_suspend(coroutine_handle<> resume_cb); | |||
void final_suspend() | |||
{ | |||
scoped_lock<lock_type> __guard(_mtx); | |||
_done = true; | |||
auto handler = _coro; | |||
_coro = nullptr; | |||
handler(); | |||
} | |||
//以上是通过future_t/promise_t, 与编译器生成的resumable function交互的接口 | |||
//------------------------------------------------------------------------------------------ | |||
}; | |||
template <typename _Ty> | |||
struct state_t : public state_base | |||
struct state_t : public state_base_t | |||
{ | |||
public: | |||
typedef _Ty value_type; | |||
value_type _value; | |||
state_t<_Ty>* lock() | |||
{ | |||
++_count; | |||
return this; | |||
} | |||
void set_value(const value_type& t) | |||
{ | |||
scoped_lock<lock_type> __guard(_mtx); | |||
_value = t; | |||
state_base::set_value_none_lock(); | |||
} | |||
void set_value(value_type&& t) | |||
{ | |||
scoped_lock<lock_type> __guard(_mtx); | |||
_value = std::forward<value_type>(t); | |||
state_base::set_value_none_lock(); | |||
} | |||
value_type & set_value__() | |||
{ | |||
scoped_lock<lock_type> __guard(_mtx); | |||
state_base::set_value_none_lock(); | |||
return _value; | |||
} | |||
value_type & get_value() | |||
{ | |||
scoped_lock<lock_type> __guard(_mtx); | |||
using value_type = _Ty; | |||
if (!_ready) | |||
throw future_exception{ error_code::not_ready }; | |||
return _value; | |||
} | |||
void reset() | |||
{ | |||
scoped_lock<lock_type> __guard(_mtx); | |||
state_base::reset_none_lock(); | |||
_value = value_type{}; | |||
} | |||
#if RESUMEF_ENABLE_MULT_SCHEDULER | |||
promise_t<_Ty> * parent_promise() const | |||
std::optional<value_type> _value; | |||
virtual bool has_value() const override | |||
{ | |||
return reinterpret_cast<promise_t<_Ty> *>(state_base::parent_promise()); | |||
return _value.has_value(); | |||
} | |||
#endif | |||
}; | |||
template<> | |||
struct state_t<void> : public state_base | |||
struct state_t<void> : public state_base_t | |||
{ | |||
state_t<void>* lock() | |||
bool _has_value = false; | |||
virtual bool has_value() const override | |||
{ | |||
++_count; | |||
return this; | |||
return _has_value; | |||
} | |||
void set_value() | |||
{ | |||
scoped_lock<lock_type> __guard(_mtx); | |||
set_value_none_lock(); | |||
} | |||
void get_value() | |||
{ | |||
scoped_lock<lock_type> __guard(_mtx); | |||
if (!_ready) | |||
throw future_exception{ error_code::not_ready }; | |||
} | |||
void reset() | |||
{ | |||
scoped_lock<lock_type> __guard(_mtx); | |||
reset_none_lock(); | |||
} | |||
#if RESUMEF_ENABLE_MULT_SCHEDULER | |||
promise_t<void> * parent_promise() const | |||
{ | |||
return reinterpret_cast<promise_t<void> *>(state_base::parent_promise()); | |||
} | |||
#endif | |||
}; | |||
} | |||
@@ -4,7 +4,7 @@ namespace resumef | |||
{ | |||
struct task_list | |||
{ | |||
using value_type = task_base; | |||
using value_type = task_base_t; | |||
using size_type = std::size_t; | |||
using difference_type = std::ptrdiff_t; | |||
using pointer = value_type *; | |||
@@ -63,8 +63,8 @@ namespace resumef | |||
pointer temp = header; | |||
header = header->_next_node; | |||
if (cancel_) | |||
temp->cancel(); | |||
//if (cancel_) | |||
// temp->cancel(); | |||
delete temp; | |||
} | |||
} | |||
@@ -93,8 +93,8 @@ namespace resumef | |||
if (_M_last == node) | |||
_M_last = prev; | |||
if (cancel_) | |||
node->cancel(); | |||
//if (cancel_) | |||
// node->cancel(); | |||
delete node; | |||
return next; |
@@ -109,7 +109,7 @@ namespace resumef | |||
when_all_functor & operator = (const when_all_functor &) = default; | |||
when_all_functor & operator = (when_all_functor &&) = default; | |||
inline future_vt operator ()() const | |||
inline future_t<> operator ()() const | |||
{ | |||
_val.get() = co_await _f; | |||
_e->signal(); | |||
@@ -117,10 +117,10 @@ namespace resumef | |||
}; | |||
template<class _Ty> | |||
struct when_all_functor<future_vt, _Ty> | |||
struct when_all_functor<future_t<>, _Ty> | |||
{ | |||
using value_type = _Ty; | |||
using future_type = future_vt; | |||
using future_type = future_t<>; | |||
when_impl_ptr _e; | |||
mutable future_type _f; | |||
@@ -135,7 +135,7 @@ namespace resumef | |||
when_all_functor & operator = (const when_all_functor &) = default; | |||
when_all_functor & operator = (when_all_functor &&) = default; | |||
inline future_vt operator ()() const | |||
inline future_t<> operator ()() const | |||
{ | |||
co_await _f; | |||
_val.get() = std::ignore; | |||
@@ -144,12 +144,12 @@ namespace resumef | |||
}; | |||
template<class _Tup, size_t _Idx> | |||
inline void when_all_one__(scheduler & , const when_impl_ptr & , _Tup & ) | |||
inline void when_all_one__(scheduler_t & , const when_impl_ptr & , _Tup & ) | |||
{ | |||
} | |||
template<class _Tup, size_t _Idx, class _Fty, class... _Rest> | |||
inline void when_all_one__(scheduler & s, const when_impl_ptr & e, _Tup & t, _Fty f, _Rest&&... rest) | |||
inline void when_all_one__(scheduler_t& s, const when_impl_ptr & e, _Tup & t, _Fty f, _Rest&&... rest) | |||
{ | |||
s + when_all_functor<_Fty, std::tuple_element_t<_Idx, _Tup> >{e, std::move(f), std::get<_Idx>(t)}; | |||
@@ -157,7 +157,7 @@ namespace resumef | |||
} | |||
template<class _Val, class _Iter, typename _Fty = decltype(*std::declval<_Iter>())> | |||
inline void when_all_range__(scheduler & s, const when_impl_ptr & e, std::vector<_Val> & t, _Iter begin, _Iter end) | |||
inline void when_all_range__(scheduler_t& s, const when_impl_ptr & e, std::vector<_Val> & t, _Iter begin, _Iter end) | |||
{ | |||
using future_type = std::remove_reference_t<_Fty>; | |||
@@ -169,7 +169,7 @@ namespace resumef | |||
template<class _Tup, class... _Fty> | |||
future_t<_Tup> when_all_count(size_t count, const std::shared_ptr<_Tup> & vals, scheduler & s, _Fty&&... f) | |||
future_t<_Tup> when_all_count(size_t count, const std::shared_ptr<_Tup> & vals, scheduler_t & s, _Fty&&... f) | |||
{ | |||
promise_t<_Tup> awaitable; | |||
@@ -191,7 +191,7 @@ namespace resumef | |||
} | |||
template<class _Tup, class _Iter> | |||
future_t<_Tup> when_all_range(size_t count, const std::shared_ptr<_Tup> & vals, scheduler & s, _Iter begin, _Iter end) | |||
future_t<_Tup> when_all_range(size_t count, const std::shared_ptr<_Tup> & vals, scheduler_t& s, _Iter begin, _Iter end) | |||
{ | |||
promise_t<_Tup> awaitable; | |||
@@ -238,7 +238,7 @@ namespace resumef | |||
when_any_functor & operator = (const when_any_functor &) = default; | |||
when_any_functor & operator = (when_any_functor &&) = default; | |||
inline future_vt operator ()() const | |||
inline future_t<> operator ()() const | |||
{ | |||
if (_val->first < 0) | |||
{ | |||
@@ -258,10 +258,10 @@ namespace resumef | |||
}; | |||
template<> | |||
struct when_any_functor<future_vt> | |||
struct when_any_functor<future_t<>> | |||
{ | |||
using value_type = when_any_pair; | |||
using future_type = future_vt; | |||
using future_type = future_t<>; | |||
when_impl_ptr _e; | |||
mutable future_type _f; | |||
@@ -280,7 +280,7 @@ namespace resumef | |||
when_any_functor & operator = (const when_any_functor &) = default; | |||
when_any_functor & operator = (when_any_functor &&) = default; | |||
inline future_vt operator ()() const | |||
inline future_t<> operator ()() const | |||
{ | |||
if (_val->first < 0) | |||
{ | |||
@@ -299,12 +299,12 @@ namespace resumef | |||
}; | |||
template<intptr_t _Idx> | |||
inline void when_any_one__(scheduler & , const when_impl_ptr & , const when_any_result_ptr & ) | |||
inline void when_any_one__(scheduler_t & , const when_impl_ptr & , const when_any_result_ptr & ) | |||
{ | |||
} | |||
template<intptr_t _Idx, class _Fty, class... _Rest> | |||
inline void when_any_one__(scheduler & s, const when_impl_ptr & e, const when_any_result_ptr & t, _Fty f, _Rest&&... rest) | |||
inline void when_any_one__(scheduler_t & s, const when_impl_ptr & e, const when_any_result_ptr & t, _Fty f, _Rest&&... rest) | |||
{ | |||
s + when_any_functor<_Fty>{e, std::move(f), t, _Idx}; | |||
@@ -312,7 +312,7 @@ namespace resumef | |||
} | |||
template<class... _Fty> | |||
future_t<when_any_pair> when_any_count(size_t count, const when_any_result_ptr & val_ptr, scheduler & s, _Fty&&... f) | |||
future_t<when_any_pair> when_any_count(size_t count, const when_any_result_ptr & val_ptr, scheduler_t & s, _Fty&&... f) | |||
{ | |||
promise_t<when_any_pair> awaitable; | |||
@@ -335,7 +335,7 @@ namespace resumef | |||
template<class _Iter, typename _Fty = decltype(*std::declval<_Iter>())> | |||
inline void when_any_range__(scheduler & s, const when_impl_ptr & e, const when_any_result_ptr & t, _Iter begin, _Iter end) | |||
inline void when_any_range__(scheduler_t & s, const when_impl_ptr & e, const when_any_result_ptr & t, _Iter begin, _Iter end) | |||
{ | |||
using future_type = std::remove_reference_t<_Fty>; | |||
@@ -345,7 +345,7 @@ namespace resumef | |||
} | |||
template<class _Iter> | |||
future_t<when_any_pair> when_any_range(size_t count, const when_any_result_ptr & val_ptr, scheduler & s, _Iter begin, _Iter end) | |||
future_t<when_any_pair> when_any_range(size_t count, const when_any_result_ptr & val_ptr, scheduler_t & s, _Iter begin, _Iter end) | |||
{ | |||
promise_t<when_any_pair> awaitable; | |||
@@ -368,7 +368,7 @@ namespace resumef | |||
} | |||
template<class... _Fty> | |||
auto when_all(scheduler & s, _Fty&&... f) -> future_t<std::tuple<detail::remove_future_vt<_Fty>...> > | |||
auto when_all(scheduler_t & s, _Fty&&... f) -> future_t<std::tuple<detail::remove_future_vt<_Fty>...> > | |||
{ | |||
using tuple_type = std::tuple<detail::remove_future_vt<_Fty>...>; | |||
auto vals = std::make_shared<tuple_type>(); | |||
@@ -381,7 +381,7 @@ namespace resumef | |||
return when_all(*this_scheduler(), std::forward<_Fty>(f)...); | |||
} | |||
template<class _Iter, typename _Fty = decltype(*std::declval<_Iter>())> | |||
auto when_all(scheduler & s, _Iter begin, _Iter end) -> future_t<std::vector<detail::remove_future_vt<_Fty> > > | |||
auto when_all(scheduler_t & s, _Iter begin, _Iter end) -> future_t<std::vector<detail::remove_future_vt<_Fty> > > | |||
{ | |||
using value_type = detail::remove_future_vt<_Fty>; | |||
using vector_type = std::vector<value_type>; | |||
@@ -399,7 +399,7 @@ namespace resumef | |||
template<class... _Fty> | |||
auto when_any(scheduler & s, _Fty&&... f) -> future_t<detail::when_any_pair> | |||
auto when_any(scheduler_t & s, _Fty&&... f) -> future_t<detail::when_any_pair> | |||
{ | |||
auto vals = std::make_shared<detail::when_any_pair>(-1, any_t{}); | |||
@@ -411,7 +411,7 @@ namespace resumef | |||
return when_any(*this_scheduler(), std::forward<_Fty>(f)...); | |||
} | |||
template<class _Iter, typename _Fty = decltype(*std::declval<_Iter>())> | |||
auto when_any(scheduler & s, _Iter begin, _Iter end) -> future_t<detail::when_any_pair> | |||
auto when_any(scheduler_t & s, _Iter begin, _Iter end) -> future_t<detail::when_any_pair> | |||
{ | |||
auto vals = std::make_shared<detail::when_any_pair>(-1, any_t{}); | |||
@@ -21,16 +21,16 @@ void callback_get_long(int64_t val, _Ctype&& cb) | |||
//这种情况下,没有生成 frame-context,因此,并没有promise_type被内嵌在frame-context里 | |||
auto async_get_long(int64_t val) | |||
{ | |||
resumef::promise_t<int64_t> awaitable; | |||
callback_get_long(val, [st = awaitable._state](int64_t val) | |||
resumef::awaitable_t<int64_t> st; | |||
callback_get_long(val, [st](int64_t val) | |||
{ | |||
st->set_value(val); | |||
st.set_value(val); | |||
}); | |||
return awaitable.get_future(); | |||
return st.get_future(); | |||
} | |||
//这种情况下,会生成对应的 frame-context,一个promise_type被内嵌在frame-context里 | |||
resumef::future_vt resumable_get_long(int64_t val) | |||
resumef::future_t<> resumable_get_long(int64_t val) | |||
{ | |||
std::cout << val << std::endl; | |||
val = co_await async_get_long(val); | |||
@@ -56,7 +56,7 @@ void resumable_main_cb() | |||
{ | |||
std::cout << std::this_thread::get_id() << std::endl; | |||
go []()->resumef::future_vt | |||
go []()->resumef::future_t<> | |||
{ | |||
auto val = co_await loop_get_long(2); | |||
std::cout << val << std::endl; |
@@ -13,7 +13,7 @@ using namespace resumef; | |||
const size_t MAX_CHANNEL_QUEUE = 5; //0, 1, 5, 10, -1 | |||
future_vt test_channel_read(const channel_t<std::string> & c) | |||
future_t<> test_channel_read(const channel_t<std::string> & c) | |||
{ | |||
using namespace std::chrono; | |||
@@ -41,7 +41,7 @@ future_vt test_channel_read(const channel_t<std::string> & c) | |||
} | |||
} | |||
future_vt test_channel_write(const channel_t<std::string> & c) | |||
future_t<> test_channel_write(const channel_t<std::string> & c) | |||
{ | |||
using namespace std::chrono; | |||
@@ -18,7 +18,7 @@ std::atomic<intptr_t> gcounter = 0; | |||
#define OUTPUT_DEBUG 0 | |||
future_vt test_channel_consumer(const channel_t<std::string> & c, size_t cnt) | |||
future_t<> test_channel_consumer(const channel_t<std::string> & c, size_t cnt) | |||
{ | |||
for (size_t i = 0; i < cnt; ++i) | |||
{ | |||
@@ -46,7 +46,7 @@ future_vt test_channel_consumer(const channel_t<std::string> & c, size_t cnt) | |||
} | |||
} | |||
future_vt test_channel_producer(const channel_t<std::string> & c, size_t cnt) | |||
future_t<> test_channel_producer(const channel_t<std::string> & c, size_t cnt) | |||
{ | |||
for (size_t i = 0; i < cnt; ++i) | |||
{ | |||
@@ -96,7 +96,7 @@ void resumable_main_channel_mult_thread() | |||
#if !RESUMEF_ENABLE_MULT_SCHEDULER | |||
std::this_thread::sleep_for(100ms); | |||
scheduler::g_scheduler.run_until_notask(); | |||
scheduler_t::g_scheduler.run_until_notask(); | |||
#endif | |||
for(auto & th : read_th) | |||
th.join(); |
@@ -20,7 +20,7 @@ std::thread async_set_event(const event_t & e, std::chrono::milliseconds dt) | |||
} | |||
future_vt resumable_wait_event(const event_t & e) | |||
future_t<> resumable_wait_event(const event_t & e) | |||
{ | |||
using namespace std::chrono; | |||
@@ -44,12 +44,12 @@ void test_wait_one() | |||
} | |||
{ | |||
event_t evt2(1); | |||
go[&]() -> future_vt | |||
go[&]() -> future_t<> | |||
{ | |||
(void)co_await evt2.wait(); | |||
std::cout << "event signal on 1!" << std::endl; | |||
}; | |||
go[&]() -> future_vt | |||
go[&]() -> future_t<> | |||
{ | |||
(void)co_await evt2.wait(); | |||
std::cout << "event signal on 2!" << std::endl; | |||
@@ -69,7 +69,7 @@ void test_wait_any() | |||
event_t evts[8]; | |||
go[&]() -> future_vt | |||
go[&]() -> future_t<> | |||
{ | |||
for (int i = 0; i < _countof(evts); ++i) | |||
{ | |||
@@ -98,7 +98,7 @@ void test_wait_all() | |||
event_t evts[8]; | |||
go[&]() -> future_vt | |||
go[&]() -> future_t<> | |||
{ | |||
if (co_await event_t::wait_all(evts)) | |||
std::cout << "all event signal!" << std::endl; | |||
@@ -126,7 +126,7 @@ void test_wait_all_timeout() | |||
event_t evts[8]; | |||
go[&]() -> future_vt | |||
go[&]() -> future_t<> | |||
{ | |||
if (co_await event_t::wait_all_for(1000ms, evts)) | |||
std::cout << "all event signal!" << std::endl; |
@@ -9,7 +9,7 @@ | |||
using namespace resumef; | |||
future_vt resumalbe_set_event(const event_t & e, std::chrono::milliseconds dt) | |||
future_t<> resumalbe_set_event(const event_t & e, std::chrono::milliseconds dt) | |||
{ | |||
co_await resumef::sleep_for(dt); | |||
e.signal(); | |||
@@ -32,7 +32,7 @@ void test_wait_timeout_one() | |||
event_t evt; | |||
go [&evt]() -> future_vt | |||
go [&evt]() -> future_t<> | |||
{ | |||
intptr_t counter = 0; | |||
for (;;) | |||
@@ -59,7 +59,7 @@ void test_wait_timeout_any_invalid() | |||
event_t evts[8]; | |||
//无效的等待 | |||
go[&]()-> future_vt | |||
go[&]()-> future_t<> | |||
{ | |||
intptr_t idx = co_await event_t::wait_any_for(500ms, std::begin(evts), std::end(evts)); | |||
assert(idx < 0); | |||
@@ -77,7 +77,7 @@ void test_wait_timeout_any() | |||
event_t evts[8]; | |||
go[&]() -> future_vt | |||
go[&]() -> future_t<> | |||
{ | |||
intptr_t counter = 0; | |||
for (;;) | |||
@@ -116,7 +116,7 @@ void test_wait_timeout_all_invalid() | |||
event_t evts[8]; | |||
//无效的等待 | |||
go[&]()-> future_vt | |||
go[&]()-> future_t<> | |||
{ | |||
bool result = co_await event_t::wait_all_for(500ms, std::begin(evts), std::end(evts)); | |||
assert(!result); | |||
@@ -134,7 +134,7 @@ void test_wait_timeout_all() | |||
event_t evts[8]; | |||
go[&]() -> future_vt | |||
go[&]() -> future_t<> | |||
{ | |||
intptr_t counter = 0; | |||
for (;;) |
@@ -49,7 +49,7 @@ auto async_signal_exception2(const intptr_t dividend) | |||
return awaitable.get_future(); | |||
} | |||
future_vt test_signal_exception() | |||
future_t<> test_signal_exception() | |||
{ | |||
for (intptr_t i = 10; i >= 0; --i) | |||
{ | |||
@@ -69,7 +69,7 @@ future_vt test_signal_exception() | |||
} | |||
} | |||
future_vt test_bomb_exception() | |||
future_t<> test_bomb_exception() | |||
{ | |||
for (intptr_t i = 10; i >= 0; --i) | |||
{ |
@@ -86,5 +86,5 @@ void resumable_main_multi_thread() | |||
//运行主调度器里面的协程 | |||
//但本范例不应该有协程存在,仅演示不要忽略了主调度器 | |||
scheduler::g_scheduler.run_until_notask(); | |||
scheduler_t::g_scheduler.run_until_notask(); | |||
} |
@@ -26,327 +26,6 @@ extern void resumable_main_benchmark_mem(); | |||
extern void resumable_main_benchmark_asio_server(); | |||
extern void resumable_main_benchmark_asio_client(intptr_t nNum); | |||
namespace coro = std::experimental; | |||
namespace librf2 | |||
{ | |||
struct scheduler_t; | |||
template<class _Ty = void> | |||
struct future_t; | |||
template<class _Ty = void> | |||
struct promise_t; | |||
template<class _PromiseT> | |||
struct is_promise : std::false_type {}; | |||
template<class _Ty> | |||
struct is_promise<promise_t<_Ty>> : std::true_type {}; | |||
template<class _Ty> | |||
_INLINE_VAR constexpr bool is_promise_v = is_promise<_Ty>::value; | |||
struct state_base_t | |||
{ | |||
scheduler_t* _scheduler = nullptr; | |||
coro::coroutine_handle<> _coro; | |||
std::exception_ptr _exception; | |||
virtual ~state_base_t() {} | |||
virtual bool has_value() const = 0; | |||
void resume() | |||
{ | |||
auto handler = _coro; | |||
_coro = nullptr; | |||
handler(); | |||
} | |||
}; | |||
template<class _Ty = void> | |||
struct state_t : public state_base_t | |||
{ | |||
using value_type = _Ty; | |||
std::optional<value_type> _value; | |||
virtual bool has_value() const override | |||
{ | |||
return _value.has_value(); | |||
} | |||
}; | |||
template<> | |||
struct state_t<void> : public state_base_t | |||
{ | |||
bool _has_value = false; | |||
virtual bool has_value() const override | |||
{ | |||
return _has_value; | |||
} | |||
}; | |||
struct scheduler_t | |||
{ | |||
using state_sptr = std::shared_ptr<state_base_t>; | |||
using state_vector = std::vector<state_sptr>; | |||
private: | |||
state_vector _runing_states; | |||
public: | |||
void add_initial(state_sptr sptr) | |||
{ | |||
sptr->_scheduler = this; | |||
assert(sptr->_coro != nullptr); | |||
_runing_states.emplace_back(std::move(sptr)); | |||
} | |||
void add_await(state_sptr sptr, coro::coroutine_handle<> handler) | |||
{ | |||
sptr->_scheduler = this; | |||
sptr->_coro = handler; | |||
if (sptr->has_value() || sptr->_exception != nullptr) | |||
_runing_states.emplace_back(std::move(sptr)); | |||
} | |||
void add_ready(state_sptr sptr) | |||
{ | |||
assert(sptr->_scheduler == this); | |||
if (sptr->_coro != nullptr) | |||
_runing_states.emplace_back(std::move(sptr)); | |||
} | |||
void run() | |||
{ | |||
for (;;) | |||
{ | |||
state_vector states = std::move(_runing_states); | |||
for (state_sptr& sptr : states) | |||
sptr->resume(); | |||
} | |||
} | |||
}; | |||
template<class _Ty> | |||
struct future_t | |||
{ | |||
using value_type = _Ty; | |||
using state_type = state_t<value_type>; | |||
using promise_type = promise_t<value_type>; | |||
using future_type = future_t<value_type>; | |||
std::shared_ptr<state_type> _state; | |||
future_t(std::shared_ptr<state_type> _st) | |||
:_state(std::move(_st)) {} | |||
future_t(const future_t&) = default; | |||
future_t(future_t&&) = default; | |||
future_t& operator = (const future_t&) = default; | |||
future_t& operator = (future_t&&) = default; | |||
bool await_ready() | |||
{ | |||
return _state->has_value(); | |||
} | |||
template<class _PromiseT, typename = std::enable_if_t<is_promise_v<_PromiseT>>> | |||
void await_suspend(coro::coroutine_handle<_PromiseT> handler) | |||
{ | |||
_PromiseT& promise = handler.promise(); | |||
scheduler_t * sch = promise._state->_scheduler; | |||
sch->add_await(_state, handler); | |||
} | |||
value_type await_resume() | |||
{ | |||
if (_state->_exception) | |||
std::rethrow_exception(std::move(_state->_exception)); | |||
return std::move(_state->_value.value()); | |||
} | |||
void resume() const | |||
{ | |||
auto coro_handle = _state->_coro; | |||
_state->_coro = nullptr; | |||
coro_handle(); | |||
} | |||
}; | |||
struct suspend_on_initial | |||
{ | |||
std::shared_ptr<state_base_t> _state; | |||
bool await_ready() noexcept | |||
{ | |||
return false; | |||
} | |||
void await_suspend(coro::coroutine_handle<> handler) noexcept | |||
{ | |||
_state->_coro = handler; | |||
} | |||
void await_resume() noexcept | |||
{ | |||
} | |||
}; | |||
template<class _Ty> | |||
struct promise_impl_t | |||
{ | |||
using value_type = _Ty; | |||
using state_type = state_t<value_type>; | |||
using promise_type = promise_t<value_type>; | |||
using future_type = future_t<value_type>; | |||
std::shared_ptr<state_type> _state = std::make_shared<state_type>(); | |||
promise_impl_t() {} | |||
promise_impl_t(const promise_impl_t&) = delete; | |||
promise_impl_t(promise_impl_t&&) = delete; | |||
promise_impl_t& operator = (const promise_impl_t&) = delete; | |||
promise_impl_t& operator = (promise_impl_t&&) = delete; | |||
auto initial_suspend() noexcept | |||
{ | |||
return suspend_on_initial{ _state }; | |||
} | |||
auto final_suspend() noexcept | |||
{ | |||
return coro::suspend_never{}; | |||
} | |||
void set_exception(std::exception_ptr e) | |||
{ | |||
_state->_exception = std::move(e); | |||
if (_state->_scheduler != nullptr) | |||
_state->_scheduler->add_ready(_state); | |||
} | |||
future_t<value_type> get_return_object() | |||
{ | |||
return { _state }; | |||
} | |||
void cancellation_requested() | |||
{ | |||
} | |||
}; | |||
template<class _Ty> | |||
struct promise_t : public promise_impl_t<_Ty> | |||
{ | |||
void return_value(value_type val) | |||
{ | |||
_state->_value = std::move(val); | |||
if (_state->_scheduler != nullptr) | |||
_state->_scheduler->add_ready(_state); | |||
} | |||
void yield_value(value_type val) | |||
{ | |||
_state->_value = std::move(val); | |||
if (_state->_scheduler != nullptr) | |||
_state->_scheduler->add_ready(_state); | |||
} | |||
}; | |||
template<> | |||
struct promise_t<void> : public promise_impl_t<void> | |||
{ | |||
void return_void() | |||
{ | |||
_state->_has_value = true; | |||
if (_state->_scheduler != nullptr) | |||
_state->_scheduler->add_ready(_state); | |||
} | |||
void yield_value() | |||
{ | |||
_state->_has_value = true; | |||
if (_state->_scheduler != nullptr) | |||
_state->_scheduler->add_ready(_state); | |||
} | |||
}; | |||
template<class _Ty> | |||
struct awaitable_t | |||
{ | |||
using value_type = _Ty; | |||
using state_type = state_t<value_type>; | |||
using future_type = future_t<value_type>; | |||
private: | |||
mutable std::shared_ptr<state_type> _state = std::make_shared<state_type>(); | |||
public: | |||
awaitable_t() {} | |||
awaitable_t(const awaitable_t&) = default; | |||
awaitable_t(awaitable_t&&) = default; | |||
awaitable_t& operator = (const awaitable_t&) = default; | |||
awaitable_t& operator = (awaitable_t&&) = default; | |||
void set_value(value_type value) const | |||
{ | |||
_state->_value = std::move(value); | |||
if (_state->_scheduler != nullptr) | |||
_state->_scheduler->add_ready(_state); | |||
_state = nullptr; | |||
} | |||
void set_exception(std::exception_ptr e) | |||
{ | |||
_state->_exception = std::move(e); | |||
if (_state->_scheduler != nullptr) | |||
_state->_scheduler->add_ready(_state); | |||
_state = nullptr; | |||
} | |||
future_type get_future() | |||
{ | |||
return future_type{ _state }; | |||
} | |||
}; | |||
template<> | |||
struct awaitable_t<void> | |||
{ | |||
using value_type = void; | |||
using state_type = state_t<>; | |||
using future_type = future_t<>; | |||
mutable std::shared_ptr<state_type> _state = std::make_shared<state_type>(); | |||
awaitable_t() {} | |||
awaitable_t(const awaitable_t&) = default; | |||
awaitable_t(awaitable_t&&) = default; | |||
awaitable_t& operator = (const awaitable_t&) = default; | |||
awaitable_t& operator = (awaitable_t&&) = default; | |||
void set_value() const | |||
{ | |||
_state->_has_value = true; | |||
if (_state->_scheduler != nullptr) | |||
_state->_scheduler->add_ready(_state); | |||
_state = nullptr; | |||
} | |||
void set_exception(std::exception_ptr e) | |||
{ | |||
_state->_exception = std::move(e); | |||
if (_state->_scheduler != nullptr) | |||
_state->_scheduler->add_ready(_state); | |||
_state = nullptr; | |||
} | |||
future_type get_future() | |||
{ | |||
return future_type{ _state }; | |||
} | |||
}; | |||
} | |||
void async_get_long(int64_t val, std::function<void(int64_t)> cb) | |||
{ | |||
using namespace std::chrono; | |||
@@ -358,9 +37,9 @@ void async_get_long(int64_t val, std::function<void(int64_t)> cb) | |||
} | |||
//这种情况下,没有生成 frame-context,因此,并没有promise_type被内嵌在frame-context里 | |||
librf2::future_t<int64_t> co_get_long(int64_t val) | |||
resumef::future_t<int64_t> co_get_long(int64_t val) | |||
{ | |||
librf2::awaitable_t<int64_t > st; | |||
resumef::awaitable_t<int64_t > st; | |||
std::cout << "co_get_long@1" << std::endl; | |||
async_get_long(val, [st](int64_t value) | |||
@@ -374,7 +53,7 @@ librf2::future_t<int64_t> co_get_long(int64_t val) | |||
} | |||
//这种情况下,会生成对应的 frame-context,一个promise_type被内嵌在frame-context里 | |||
librf2::future_t<> test_librf2() | |||
resumef::future_t<> test_librf2() | |||
{ | |||
auto f = co_await co_get_long(2); | |||
std::cout << f << std::endl; | |||
@@ -382,21 +61,15 @@ librf2::future_t<> test_librf2() | |||
int main(int argc, const char* argv[]) | |||
{ | |||
librf2::scheduler_t sch; | |||
librf2::future_t<> ft = test_librf2(); | |||
sch.add_initial(ft._state); | |||
sch.run(); | |||
resumable_main_cb(); | |||
resumable_main_resumable(); | |||
//resumable_main_benchmark_mem(); | |||
/* | |||
resumable_main_resumable(); | |||
resumable_main_benchmark_mem(); | |||
if (argc > 1) | |||
resumable_main_benchmark_asio_client(atoi(argv[1])); | |||
else | |||
resumable_main_benchmark_asio_server(); | |||
*/ | |||
//return 0; | |||
resumable_main_when_all(); | |||
resumable_main_multi_thread(); | |||
@@ -413,6 +86,7 @@ int main(int argc, const char* argv[]) | |||
resumable_main_channel(); | |||
resumable_main_cb(); | |||
resumable_main_exception(); | |||
*/ | |||
return 0; | |||
} |
@@ -180,34 +180,103 @@ | |||
</Link> | |||
</ItemDefinitionGroup> | |||
<ItemGroup> | |||
<ClCompile Include="..\benchmark\benchmark_asio_echo.cpp" /> | |||
<ClCompile Include="..\benchmark\benchmark_async_mem.cpp" /> | |||
<ClCompile Include="..\benchmark\benchmark_channel_passing_next.cpp" /> | |||
<ClCompile Include="..\librf\src\event.cpp" /> | |||
<ClCompile Include="..\librf\src\mutex.cpp" /> | |||
<ClCompile Include="..\benchmark\benchmark_asio_echo.cpp"> | |||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild> | |||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild> | |||
</ClCompile> | |||
<ClCompile Include="..\benchmark\benchmark_async_mem.cpp"> | |||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild> | |||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild> | |||
</ClCompile> | |||
<ClCompile Include="..\benchmark\benchmark_channel_passing_next.cpp"> | |||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild> | |||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild> | |||
</ClCompile> | |||
<ClCompile Include="..\librf\src\event.cpp"> | |||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild> | |||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild> | |||
</ClCompile> | |||
<ClCompile Include="..\librf\src\mutex.cpp"> | |||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild> | |||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild> | |||
</ClCompile> | |||
<ClCompile Include="..\librf\src\rf_task.cpp" /> | |||
<ClCompile Include="..\librf\src\scheduler.cpp" /> | |||
<ClCompile Include="..\librf\src\sleep.cpp" /> | |||
<ClCompile Include="..\librf\src\sleep.cpp"> | |||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild> | |||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild> | |||
</ClCompile> | |||
<ClCompile Include="..\librf\src\state.cpp" /> | |||
<ClCompile Include="..\librf\src\timer.cpp" /> | |||
<ClCompile Include="..\librf\src\when.cpp" /> | |||
<ClCompile Include="..\librf\src\when.cpp"> | |||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild> | |||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild> | |||
</ClCompile> | |||
<ClCompile Include="..\tutorial\test_async_cb.cpp" /> | |||
<ClCompile Include="..\tutorial\test_async_channel.cpp" /> | |||
<ClCompile Include="..\tutorial\test_async_channel_mult_thread.cpp" /> | |||
<ClCompile Include="..\tutorial\test_async_dynamic_go.cpp" /> | |||
<ClCompile Include="..\tutorial\test_async_event.cpp" /> | |||
<ClCompile Include="..\tutorial\test_async_event_timeout.cpp" /> | |||
<ClCompile Include="..\tutorial\test_async_exception.cpp" /> | |||
<ClCompile Include="..\tutorial\test_async_modern_cb.cpp" /> | |||
<ClCompile Include="..\tutorial\test_async_multi_thread.cpp" /> | |||
<ClCompile Include="..\tutorial\test_async_mutex.cpp" /> | |||
<ClCompile Include="..\tutorial\test_async_resumable.cpp" /> | |||
<ClCompile Include="..\tutorial\test_async_routine.cpp" /> | |||
<ClCompile Include="..\tutorial\test_async_sleep.cpp" /> | |||
<ClCompile Include="..\tutorial\test_async_suspend_always.cpp" /> | |||
<ClCompile Include="..\tutorial\test_async_timer.cpp" /> | |||
<ClCompile Include="..\tutorial\test_async_when_all.cpp" /> | |||
<ClCompile Include="..\tutorial\test_async_yield_return.cpp" /> | |||
<ClCompile Include="..\tutorial\test_async_channel.cpp"> | |||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild> | |||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild> | |||
</ClCompile> | |||
<ClCompile Include="..\tutorial\test_async_channel_mult_thread.cpp"> | |||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild> | |||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild> | |||
</ClCompile> | |||
<ClCompile Include="..\tutorial\test_async_dynamic_go.cpp"> | |||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild> | |||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild> | |||
</ClCompile> | |||
<ClCompile Include="..\tutorial\test_async_event.cpp"> | |||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild> | |||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild> | |||
</ClCompile> | |||
<ClCompile Include="..\tutorial\test_async_event_timeout.cpp"> | |||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild> | |||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild> | |||
</ClCompile> | |||
<ClCompile Include="..\tutorial\test_async_exception.cpp"> | |||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild> | |||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild> | |||
</ClCompile> | |||
<ClCompile Include="..\tutorial\test_async_modern_cb.cpp"> | |||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild> | |||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild> | |||
</ClCompile> | |||
<ClCompile Include="..\tutorial\test_async_multi_thread.cpp"> | |||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild> | |||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild> | |||
</ClCompile> | |||
<ClCompile Include="..\tutorial\test_async_mutex.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"> | |||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild> | |||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild> | |||
</ClCompile> | |||
<ClCompile Include="..\tutorial\test_async_routine.cpp"> | |||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild> | |||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild> | |||
</ClCompile> | |||
<ClCompile Include="..\tutorial\test_async_sleep.cpp"> | |||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild> | |||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild> | |||
</ClCompile> | |||
<ClCompile Include="..\tutorial\test_async_suspend_always.cpp"> | |||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild> | |||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild> | |||
</ClCompile> | |||
<ClCompile Include="..\tutorial\test_async_timer.cpp"> | |||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild> | |||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild> | |||
</ClCompile> | |||
<ClCompile Include="..\tutorial\test_async_when_all.cpp"> | |||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild> | |||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild> | |||
</ClCompile> | |||
<ClCompile Include="..\tutorial\test_async_yield_return.cpp"> | |||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild> | |||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild> | |||
</ClCompile> | |||
<ClCompile Include="librf.cpp"> | |||
<BasicRuntimeChecks Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Default</BasicRuntimeChecks> | |||
<BufferSecurityCheck Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">false</BufferSecurityCheck> | |||
@@ -217,12 +286,13 @@ | |||
<ItemGroup> | |||
<ClInclude Include="..\librf\librf.h" /> | |||
<ClInclude Include="..\librf\src\asio_task.h" /> | |||
<ClInclude Include="..\librf\src\awaitable.h" /> | |||
<ClInclude Include="..\librf\src\channel.h" /> | |||
<ClInclude Include="..\librf\src\counted_ptr.h" /> | |||
<ClInclude Include="..\librf\src\def.h" /> | |||
<ClInclude Include="..\librf\src\event.h" /> | |||
<ClInclude Include="..\librf\src\future.h" /> | |||
<ClInclude Include="..\librf\src\generator.h" /> | |||
<ClInclude Include="..\librf\src\promise.h" /> | |||
<ClInclude Include="..\librf\src\task_list.h" /> | |||
<ClInclude Include="..\librf\src\mutex.h" /> | |||
<ClInclude Include="..\librf\src\rf_task.h" /> | |||
@@ -239,6 +309,7 @@ | |||
<ItemGroup> | |||
<None Include="..\librf\src\asio_task_1.10.0.inl" /> | |||
<None Include="..\librf\src\asio_task_1.12.0.inl" /> | |||
<None Include="..\librf\src\promise.inl" /> | |||
</ItemGroup> | |||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" /> | |||
<ImportGroup Label="ExtensionTargets"> |
@@ -132,9 +132,6 @@ | |||
<ClInclude Include="..\librf\src\future.h"> | |||
<Filter>librf\src</Filter> | |||
</ClInclude> | |||
<ClInclude Include="..\librf\src\generator.h"> | |||
<Filter>librf\src</Filter> | |||
</ClInclude> | |||
<ClInclude Include="..\librf\src\mutex.h"> | |||
<Filter>librf\src</Filter> | |||
</ClInclude> | |||
@@ -171,6 +168,12 @@ | |||
<ClInclude Include="..\librf\src\task_list.h"> | |||
<Filter>librf\src</Filter> | |||
</ClInclude> | |||
<ClInclude Include="..\librf\src\promise.h"> | |||
<Filter>librf\src</Filter> | |||
</ClInclude> | |||
<ClInclude Include="..\librf\src\awaitable.h"> | |||
<Filter>librf</Filter> | |||
</ClInclude> | |||
</ItemGroup> | |||
<ItemGroup> | |||
<None Include="..\librf\src\asio_task_1.12.0.inl"> | |||
@@ -179,5 +182,8 @@ | |||
<None Include="..\librf\src\asio_task_1.10.0.inl"> | |||
<Filter>librf\src</Filter> | |||
</None> | |||
<None Include="..\librf\src\promise.inl"> | |||
<Filter>librf\src</Filter> | |||
</None> | |||
</ItemGroup> | |||
</Project> |