### librf - 协程库 | ### librf - 协程库 | ||||
2020-02-16 更新: | 2020-02-16 更新: | ||||
更新调度器算法,深入应用Coroutines的特性,以期获得更高调度性能。 | 更新调度器算法,深入应用Coroutines的特性,以期获得更高调度性能。 | ||||
不再支持C++14。 | 不再支持C++14。 | ||||
librf是一个基于C++ Coroutines提案 ‘Stackless Resumable Functions’编写的非对称stackless协程库。 | |||||
librf是一个基于C++ Coroutines提案 ‘Stackless Resumable Functions’编写的非对称stackless协程库。 | |||||
目前仅支持: | 目前仅支持: | ||||
void set_exception(std::exception_ptr e) const | void set_exception(std::exception_ptr e) const | ||||
{ | { | ||||
_state->set_exception(std::move(e)); | |||||
_state = nullptr; | |||||
this->_state->set_exception(std::move(e)); | |||||
this->_state = nullptr; | |||||
} | } | ||||
template<class _Exp> | template<class _Exp> | ||||
future_type get_future() | future_type get_future() | ||||
{ | { | ||||
return future_type{ _state }; | |||||
return future_type{ this->_state }; | |||||
} | } | ||||
mutable counted_ptr<state_type> _state = make_counted<state_type>(true); | mutable counted_ptr<state_type> _state = make_counted<state_type>(true); | ||||
template<class _Ty> | template<class _Ty> | ||||
struct awaitable_t : public awaitable_impl_t<_Ty> | struct awaitable_t : public awaitable_impl_t<_Ty> | ||||
{ | { | ||||
using awaitable_impl_t::awaitable_impl_t; | |||||
using typename awaitable_impl_t<_Ty>::value_type; | |||||
using awaitable_impl_t<_Ty>::awaitable_impl_t; | |||||
void set_value(value_type value) const | void set_value(value_type value) const | ||||
{ | { | ||||
_state->set_value(std::move(value)); | |||||
_state = nullptr; | |||||
this->_state->set_value(std::move(value)); | |||||
this->_state = nullptr; | |||||
} | } | ||||
}; | }; | ||||
template<> | template<> | ||||
struct awaitable_t<void> : public awaitable_impl_t<void> | struct awaitable_t<void> : public awaitable_impl_t<void> | ||||
{ | { | ||||
using awaitable_impl_t::awaitable_impl_t; | |||||
using awaitable_impl_t<void>::awaitable_impl_t; | |||||
void set_value() const | void set_value() const | ||||
{ | { | ||||
_state->set_value(); | |||||
_state = nullptr; | |||||
this->_state->set_value(); | |||||
this->_state = nullptr; | |||||
} | } | ||||
}; | }; | ||||
} | } |
#include <deque> | #include <deque> | ||||
#include <mutex> | #include <mutex> | ||||
#include <map> | #include <map> | ||||
#include <unordered_map> | |||||
#include <optional> | #include <optional> | ||||
#include <assert.h> | #include <assert.h> | ||||
struct state_base_t; | struct state_base_t; | ||||
#if _HAS_CXX17 | |||||
template<class... _Mutexes> | template<class... _Mutexes> | ||||
using scoped_lock = std::scoped_lock<_Mutexes...>; | using scoped_lock = std::scoped_lock<_Mutexes...>; | ||||
#else | |||||
template<class... _Mutexes> | |||||
using scoped_lock = std::lock_guard<_Mutexes...>; | |||||
#endif | |||||
} | } | ||||
#if RESUMEF_DEBUG_COUNTER | #if RESUMEF_DEBUG_COUNTER | ||||
extern std::atomic<intptr_t> g_resumef_state_id; | extern std::atomic<intptr_t> g_resumef_state_id; | ||||
#endif | #endif | ||||
namespace std | |||||
namespace resumef | |||||
{ | { | ||||
#if !_HAS_CXX20 | |||||
template<class T> | template<class T> | ||||
struct remove_cvref | struct remove_cvref | ||||
{ | { | ||||
typedef std::remove_cv_t<std::remove_reference_t<T>> type; | typedef std::remove_cv_t<std::remove_reference_t<T>> type; | ||||
}; | }; | ||||
#if _HAS_CXX17 | |||||
template<class T> | template<class T> | ||||
using remove_cvref_t = typename std::remove_cvref<T>::type; | |||||
#endif | |||||
#endif | |||||
using remove_cvref_t = typename remove_cvref<T>::type; | |||||
} | } | ||||
#if defined(RESUMEF_DLL_EXPORT) | #if defined(RESUMEF_DLL_EXPORT) |
RF_API void reset(); | RF_API void reset(); | ||||
//如果已经触发了awaker,则返回true | //如果已经触发了awaker,则返回true | ||||
RF_API bool wait_(const event_awaker_ptr & awaker); | |||||
RF_API bool wait_(const event_awaker_ptr& awaker); | |||||
template<class callee_t, class dummy_t = std::enable_if<!std::is_same<std::remove_cv_t<callee_t>, event_awaker_ptr>::value>> | template<class callee_t, class dummy_t = std::enable_if<!std::is_same<std::remove_cv_t<callee_t>, event_awaker_ptr>::value>> | ||||
decltype(auto) wait(callee_t && awaker, dummy_t * dummy_ = nullptr) | |||||
decltype(auto) wait(callee_t&& awaker, dummy_t* dummy_ = nullptr) | |||||
{ | { | ||||
(void)dummy_; | |||||
return wait_(std::make_shared<event_awaker>(std::forward<callee_t>(awaker))); | return wait_(std::make_shared<event_awaker>(std::forward<callee_t>(awaker))); | ||||
} | } | ||||
event_impl(const event_impl &) = delete; | |||||
event_impl(event_impl &&) = delete; | |||||
event_impl & operator = (const event_impl &) = delete; | |||||
event_impl & operator = (event_impl &&) = delete; | |||||
event_impl(const event_impl&) = delete; | |||||
event_impl(event_impl&&) = delete; | |||||
event_impl& operator = (const event_impl&) = delete; | |||||
event_impl& operator = (event_impl&&) = delete; | |||||
}; | }; | ||||
} | } | ||||
RF_API future_t<bool> | RF_API future_t<bool> | ||||
wait() const; | wait() const; | ||||
template<class _Rep, class _Period> | |||||
template<class _Rep, class _Period> | |||||
future_t<bool> | future_t<bool> | ||||
wait_for(const std::chrono::duration<_Rep, _Period> & dt) const | |||||
wait_for(const std::chrono::duration<_Rep, _Period>& dt) const | |||||
{ | { | ||||
return wait_for_(std::chrono::duration_cast<clock_type::duration>(dt)); | return wait_for_(std::chrono::duration_cast<clock_type::duration>(dt)); | ||||
} | } | ||||
template<class _Clock, class _Duration> | |||||
template<class _Clock, class _Duration> | |||||
future_t<bool> | future_t<bool> | ||||
wait_until(const std::chrono::time_point<_Clock, _Duration> & tp) const | |||||
wait_until(const std::chrono::time_point<_Clock, _Duration>& tp) const | |||||
{ | { | ||||
return wait_until_(std::chrono::time_point_cast<clock_type::duration>(tp)); | return wait_until_(std::chrono::time_point_cast<clock_type::duration>(tp)); | ||||
} | } | ||||
} | } | ||||
template<class _Cont> | template<class _Cont> | ||||
static future_t<intptr_t> | static future_t<intptr_t> | ||||
wait_any(const _Cont & cnt_) | |||||
wait_any(const _Cont& cnt_) | |||||
{ | { | ||||
return wait_any_(make_event_vector(std::begin(cnt_), std::end(cnt_))); | return wait_any_(make_event_vector(std::begin(cnt_), std::end(cnt_))); | ||||
} | } | ||||
template<class _Rep, class _Period, class _Iter> | template<class _Rep, class _Period, class _Iter> | ||||
static future_t<intptr_t> | static future_t<intptr_t> | ||||
wait_any_for(const std::chrono::duration<_Rep, _Period> & dt, _Iter begin_, _Iter end_) | |||||
wait_any_for(const std::chrono::duration<_Rep, _Period>& dt, _Iter begin_, _Iter end_) | |||||
{ | { | ||||
return wait_any_for_(std::chrono::duration_cast<clock_type::duration>(dt), make_event_vector(begin_, end_)); | return wait_any_for_(std::chrono::duration_cast<clock_type::duration>(dt), make_event_vector(begin_, end_)); | ||||
} | } | ||||
template<class _Rep, class _Period, class _Cont> | template<class _Rep, class _Period, class _Cont> | ||||
static future_t<intptr_t> | static future_t<intptr_t> | ||||
wait_any_for(const std::chrono::duration<_Rep, _Period> & dt, const _Cont & cnt_) | |||||
wait_any_for(const std::chrono::duration<_Rep, _Period>& dt, const _Cont& cnt_) | |||||
{ | { | ||||
return wait_any_for_(std::chrono::duration_cast<clock_type::duration>(dt), make_event_vector(std::begin(cnt_), std::end(cnt_))); | return wait_any_for_(std::chrono::duration_cast<clock_type::duration>(dt), make_event_vector(std::begin(cnt_), std::end(cnt_))); | ||||
} | } | ||||
template<class _Clock, class _Duration, class _Iter> | |||||
template<class _Clock, class _Duration, class _Iter> | |||||
static future_t<intptr_t> | static future_t<intptr_t> | ||||
wait_any_until(const std::chrono::time_point<_Clock, _Duration> & tp, _Iter begin_, _Iter end_) | |||||
wait_any_until(const std::chrono::time_point<_Clock, _Duration>& tp, _Iter begin_, _Iter end_) | |||||
{ | { | ||||
return wait_any_until_(std::chrono::time_point_cast<clock_type::duration>(tp), make_event_vector(begin_, end_)); | return wait_any_until_(std::chrono::time_point_cast<clock_type::duration>(tp), make_event_vector(begin_, end_)); | ||||
} | } | ||||
template<class _Clock, class _Duration, class _Cont> | template<class _Clock, class _Duration, class _Cont> | ||||
static future_t<intptr_t> | static future_t<intptr_t> | ||||
wait_any_until(const std::chrono::time_point<_Clock, _Duration> & tp, const _Cont & cnt_) | |||||
wait_any_until(const std::chrono::time_point<_Clock, _Duration>& tp, const _Cont& cnt_) | |||||
{ | { | ||||
return wait_any_until_(std::chrono::time_point_cast<clock_type::duration>(tp), make_event_vector(std::begin(cnt_), std::end(cnt_))); | return wait_any_until_(std::chrono::time_point_cast<clock_type::duration>(tp), make_event_vector(std::begin(cnt_), std::end(cnt_))); | ||||
} | } | ||||
} | } | ||||
template<class _Cont> | template<class _Cont> | ||||
static future_t<bool> | static future_t<bool> | ||||
wait_all(const _Cont & cnt_) | |||||
wait_all(const _Cont& cnt_) | |||||
{ | { | ||||
return wait_all(std::begin(cnt_), std::end(cnt_)); | return wait_all(std::begin(cnt_), std::end(cnt_)); | ||||
} | } | ||||
template<class _Rep, class _Period, class _Iter> | template<class _Rep, class _Period, class _Iter> | ||||
static future_t<bool> | static future_t<bool> | ||||
wait_all_for(const std::chrono::duration<_Rep, _Period> & dt, _Iter begin_, _Iter end_) | |||||
wait_all_for(const std::chrono::duration<_Rep, _Period>& dt, _Iter begin_, _Iter end_) | |||||
{ | { | ||||
return wait_all_for_(std::chrono::duration_cast<clock_type::duration>(dt), make_event_vector(begin_, end_)); | return wait_all_for_(std::chrono::duration_cast<clock_type::duration>(dt), make_event_vector(begin_, end_)); | ||||
} | } | ||||
template<class _Rep, class _Period, class _Cont> | template<class _Rep, class _Period, class _Cont> | ||||
static future_t<bool> | static future_t<bool> | ||||
wait_all_for(const std::chrono::duration<_Rep, _Period> & dt, const _Cont & cnt_) | |||||
wait_all_for(const std::chrono::duration<_Rep, _Period>& dt, const _Cont& cnt_) | |||||
{ | { | ||||
return wait_all_for_(std::chrono::duration_cast<clock_type::duration>(dt), make_event_vector(std::begin(cnt_), std::end(cnt_))); | return wait_all_for_(std::chrono::duration_cast<clock_type::duration>(dt), make_event_vector(std::begin(cnt_), std::end(cnt_))); | ||||
} | } | ||||
template<class _Clock, class _Duration, class _Iter> | template<class _Clock, class _Duration, class _Iter> | ||||
static future_t<bool> | static future_t<bool> | ||||
wait_all_until(const std::chrono::time_point<_Clock, _Duration> & tp, _Iter begin_, _Iter end_) | |||||
wait_all_until(const std::chrono::time_point<_Clock, _Duration>& tp, _Iter begin_, _Iter end_) | |||||
{ | { | ||||
return wait_all_until_(std::chrono::time_point_cast<clock_type::duration>(tp), make_event_vector(begin_, end_)); | return wait_all_until_(std::chrono::time_point_cast<clock_type::duration>(tp), make_event_vector(begin_, end_)); | ||||
} | } | ||||
template<class _Clock, class _Duration, class _Cont> | template<class _Clock, class _Duration, class _Cont> | ||||
static future_t<bool> | static future_t<bool> | ||||
wait_all_until(const std::chrono::time_point<_Clock, _Duration> & tp, const _Cont & cnt_) | |||||
wait_all_until(const std::chrono::time_point<_Clock, _Duration>& tp, const _Cont& cnt_) | |||||
{ | { | ||||
return wait_all_until_(std::chrono::time_point_cast<clock_type::duration>(tp), make_event_vector(std::begin(cnt_), std::end(cnt_))); | return wait_all_until_(std::chrono::time_point_cast<clock_type::duration>(tp), make_event_vector(std::begin(cnt_), std::end(cnt_))); | ||||
} | } | ||||
RF_API event_t(const event_t &) = default; | |||||
RF_API event_t(event_t &&) = default; | |||||
RF_API event_t & operator = (const event_t &) = default; | |||||
RF_API event_t & operator = (event_t &&) = default; | |||||
RF_API event_t(const event_t&) = default; | |||||
RF_API event_t(event_t&&) = default; | |||||
RF_API event_t& operator = (const event_t&) = default; | |||||
RF_API event_t& operator = (event_t&&) = default; | |||||
private: | private: | ||||
template<class _Iter> | template<class _Iter> | ||||
for (auto i = begin_; i != end_; ++i) | for (auto i = begin_; i != end_; ++i) | ||||
evts.push_back((*i)._event); | evts.push_back((*i)._event); | ||||
return std::move(evts); | |||||
return evts; | |||||
} | } | ||||
inline future_t<bool> wait_for_(const clock_type::duration & dt) const | |||||
inline future_t<bool> wait_for_(const clock_type::duration& dt) const | |||||
{ | { | ||||
return wait_until_(clock_type::now() + dt); | return wait_until_(clock_type::now() + dt); | ||||
} | } | ||||
RF_API future_t<bool> wait_until_(const clock_type::time_point & tp) const; | |||||
RF_API future_t<bool> wait_until_(const clock_type::time_point& tp) const; | |||||
RF_API static future_t<intptr_t> wait_any_(std::vector<event_impl_ptr> && evts); | |||||
inline static future_t<intptr_t> wait_any_for_(const clock_type::duration & dt, std::vector<event_impl_ptr> && evts) | |||||
RF_API static future_t<intptr_t> wait_any_(std::vector<event_impl_ptr>&& evts); | |||||
inline static future_t<intptr_t> wait_any_for_(const clock_type::duration& dt, std::vector<event_impl_ptr>&& evts) | |||||
{ | { | ||||
return wait_any_until_(clock_type::now() + dt, std::forward<std::vector<event_impl_ptr>>(evts)); | return wait_any_until_(clock_type::now() + dt, std::forward<std::vector<event_impl_ptr>>(evts)); | ||||
} | } | ||||
RF_API static future_t<intptr_t> wait_any_until_(const clock_type::time_point & tp, std::vector<event_impl_ptr> && evts); | |||||
RF_API static future_t<intptr_t> wait_any_until_(const clock_type::time_point& tp, std::vector<event_impl_ptr>&& evts); | |||||
RF_API static future_t<bool> wait_all_(std::vector<event_impl_ptr> && evts); | |||||
inline static future_t<bool> wait_all_for_(const clock_type::duration & dt, std::vector<event_impl_ptr> && evts) | |||||
RF_API static future_t<bool> wait_all_(std::vector<event_impl_ptr>&& evts); | |||||
inline static future_t<bool> wait_all_for_(const clock_type::duration& dt, std::vector<event_impl_ptr>&& evts) | |||||
{ | { | ||||
return wait_all_until_(clock_type::now() + dt, std::forward<std::vector<event_impl_ptr>>(evts)); | return wait_all_until_(clock_type::now() + dt, std::forward<std::vector<event_impl_ptr>>(evts)); | ||||
} | } | ||||
RF_API static future_t<bool> wait_all_until_(const clock_type::time_point & tp, std::vector<event_impl_ptr> && evts); | |||||
RF_API static future_t<bool> wait_all_until_(const clock_type::time_point& tp, std::vector<event_impl_ptr>&& evts); | |||||
}; | }; | ||||
} | } |
const char* get_error_string(error_code fe, const char* classname); | const char* get_error_string(error_code fe, const char* classname); | ||||
struct future_exception : std::exception | |||||
struct future_exception : std::logic_error | |||||
{ | { | ||||
error_code _error; | error_code _error; | ||||
future_exception(error_code fe) | future_exception(error_code fe) | ||||
: exception(get_error_string(fe, "future_exception")) | |||||
: logic_error(get_error_string(fe, "future_exception")) | |||||
, _error(fe) | , _error(fe) | ||||
{ | { | ||||
} | } | ||||
}; | }; | ||||
struct lock_exception : std::exception | |||||
struct lock_exception : std::logic_error | |||||
{ | { | ||||
error_code _error; | error_code _error; | ||||
lock_exception(error_code fe) | lock_exception(error_code fe) | ||||
: exception(get_error_string(fe, "lock_exception")) | |||||
: logic_error(get_error_string(fe, "lock_exception")) | |||||
, _error(fe) | , _error(fe) | ||||
{ | { | ||||
} | } | ||||
}; | }; | ||||
struct channel_exception : std::exception | |||||
struct channel_exception : std::logic_error | |||||
{ | { | ||||
error_code _error; | error_code _error; | ||||
channel_exception(error_code fe) | channel_exception(error_code fe) | ||||
: exception(get_error_string(fe, "channel_exception")) | |||||
: logic_error(get_error_string(fe, "channel_exception")) | |||||
, _error(fe) | , _error(fe) | ||||
{ | { | ||||
} | } | ||||
}; | }; | ||||
struct timer_canceled_exception : public std::exception | |||||
struct timer_canceled_exception : public std::logic_error | |||||
{ | { | ||||
error_code _error; | error_code _error; | ||||
timer_canceled_exception(error_code fe) | timer_canceled_exception(error_code fe) | ||||
: exception(get_error_string(fe, "timer canceled")) | |||||
: logic_error(get_error_string(fe, "timer canceled")) | |||||
, _error(fe) | , _error(fe) | ||||
{ | { | ||||
} | } |
#define _EXPERIMENTAL_GENERATOR_ | #define _EXPERIMENTAL_GENERATOR_ | ||||
#ifndef RC_INVOKED | #ifndef RC_INVOKED | ||||
#ifndef _RESUMABLE_FUNCTIONS_SUPPORTED | |||||
#error <experimental/generator> requires /await compiler option | |||||
#endif /* _RESUMABLE_FUNCTIONS_SUPPORTED */ | |||||
#include <experimental/resumable> | |||||
#include <experimental/coroutine> | |||||
#pragma pack(push,_CRT_PACKING) | #pragma pack(push,_CRT_PACKING) | ||||
#pragma warning(push,_STL_WARNING_LEVEL) | |||||
#pragma warning(disable: _STL_DISABLED_WARNINGS) | |||||
_STL_DISABLE_CLANG_WARNINGS | |||||
#pragma push_macro("new") | #pragma push_macro("new") | ||||
#undef new | #undef new | ||||
_STD_BEGIN | |||||
namespace experimental { | |||||
template <typename _Ty, typename promise_type> | |||||
struct generator_iterator; | |||||
template<typename promise_type> | |||||
struct generator_iterator<void, promise_type> | |||||
{ | |||||
typedef _STD input_iterator_tag iterator_category; | |||||
typedef ptrdiff_t difference_type; | |||||
coroutine_handle<promise_type> _Coro; | |||||
generator_iterator(nullptr_t) : _Coro(nullptr) | |||||
{ | |||||
} | |||||
generator_iterator(coroutine_handle<promise_type> _CoroArg) : _Coro(_CoroArg) | |||||
{ | |||||
} | |||||
generator_iterator &operator++() | |||||
{ | |||||
_Coro.resume(); | |||||
if (_Coro.done()) | |||||
_Coro = nullptr; | |||||
return *this; | |||||
} | |||||
namespace std { | |||||
namespace experimental { | |||||
void operator++(int) | |||||
{ | |||||
// This postincrement operator meets the requirements of the Ranges TS | |||||
// InputIterator concept, but not those of Standard C++ InputIterator. | |||||
++* this; | |||||
} | |||||
template <typename _Ty, typename promise_type> | |||||
struct generator_iterator; | |||||
bool operator==(generator_iterator const &right_) const | |||||
template<typename promise_type> | |||||
struct generator_iterator<void, promise_type> | |||||
{ | { | ||||
return _Coro == right_._Coro; | |||||
} | |||||
typedef std::input_iterator_tag iterator_category; | |||||
typedef ptrdiff_t difference_type; | |||||
bool operator!=(generator_iterator const &right_) const | |||||
{ | |||||
return !(*this == right_); | |||||
} | |||||
}; | |||||
template <typename promise_type> | |||||
struct generator_iterator<nullptr_t, promise_type> : public generator_iterator<void, promise_type> | |||||
{ | |||||
generator_iterator(nullptr_t) : generator_iterator<void, promise_type>(nullptr) | |||||
{ | |||||
} | |||||
generator_iterator(coroutine_handle<promise_type> _CoroArg) : generator_iterator<void, promise_type>(_CoroArg) | |||||
{ | |||||
} | |||||
}; | |||||
coroutine_handle<promise_type> _Coro; | |||||
template <typename _Ty, typename promise_type> | |||||
struct generator_iterator : public generator_iterator<void, promise_type> | |||||
{ | |||||
using value_type = _Ty; | |||||
using reference = _Ty const&; | |||||
using pointer = _Ty const*; | |||||
generator_iterator(nullptr_t) : generator_iterator<void, promise_type>(nullptr) | |||||
{ | |||||
} | |||||
generator_iterator(coroutine_handle<promise_type> _CoroArg) : generator_iterator<void, promise_type>(_CoroArg) | |||||
{ | |||||
} | |||||
reference operator*() const | |||||
{ | |||||
return *_Coro.promise()._CurrentValue; | |||||
} | |||||
generator_iterator(nullptr_t) : _Coro(nullptr) | |||||
{ | |||||
} | |||||
pointer operator->() const | |||||
{ | |||||
return _Coro.promise()._CurrentValue; | |||||
} | |||||
}; | |||||
template <typename _Ty, typename _Alloc = allocator<char>> | |||||
struct generator | |||||
{ | |||||
struct promise_type | |||||
{ | |||||
_Ty const *_CurrentValue; | |||||
generator_iterator(coroutine_handle<promise_type> _CoroArg) : _Coro(_CoroArg) | |||||
{ | |||||
} | |||||
promise_type &get_return_object() | |||||
generator_iterator& operator++() | |||||
{ | { | ||||
_Coro.resume(); | |||||
if (_Coro.done()) | |||||
_Coro = nullptr; | |||||
return *this; | return *this; | ||||
} | } | ||||
bool initial_suspend() | |||||
void operator++(int) | |||||
{ | { | ||||
return (true); | |||||
// This postincrement operator meets the requirements of the Ranges TS | |||||
// InputIterator concept, but not those of Standard C++ InputIterator. | |||||
++* this; | |||||
} | } | ||||
bool final_suspend() | |||||
bool operator==(generator_iterator const& right_) const | |||||
{ | { | ||||
return (true); | |||||
return _Coro == right_._Coro; | |||||
} | } | ||||
void yield_value(_Ty const &_Value) | |||||
bool operator!=(generator_iterator const& right_) const | |||||
{ | { | ||||
_CurrentValue = _STD addressof(_Value); | |||||
return !(*this == right_); | |||||
} | } | ||||
}; | |||||
template<class = _STD enable_if_t<!is_same_v<_Ty, void>, _Ty>> | |||||
void return_value(_Ty const &_Value) | |||||
template <typename promise_type> | |||||
struct generator_iterator<nullptr_t, promise_type> : public generator_iterator<void, promise_type> | |||||
{ | |||||
generator_iterator(nullptr_t) : generator_iterator<void, promise_type>(nullptr) | |||||
{ | { | ||||
_CurrentValue = _STD addressof(_Value); | |||||
} | } | ||||
template<class = _STD enable_if_t<is_same_v<_Ty, void>, _Ty>> | |||||
void return_value() | |||||
generator_iterator(coroutine_handle<promise_type> _CoroArg) : generator_iterator<void, promise_type>(_CoroArg) | |||||
{ | { | ||||
_CurrentValue = nullptr; | |||||
} | } | ||||
}; | |||||
template <typename _Ty, typename promise_type> | |||||
struct generator_iterator : public generator_iterator<void, promise_type> | |||||
{ | |||||
using value_type = _Ty; | |||||
using reference = _Ty const&; | |||||
using pointer = _Ty const*; | |||||
template <typename _Uty> | |||||
_Uty && await_transform(_Uty &&_Whatever) | |||||
generator_iterator(nullptr_t) : generator_iterator<void, promise_type>(nullptr) | |||||
{ | |||||
} | |||||
generator_iterator(coroutine_handle<promise_type> _CoroArg) : generator_iterator<void, promise_type>(_CoroArg) | |||||
{ | { | ||||
static_assert(_Always_false<_Uty>::value, | |||||
"co_await is not supported in coroutines of type std::experiemental::generator"); | |||||
return _STD forward<_Uty>(_Whatever); | |||||
} | } | ||||
using _Alloc_char = _Rebind_alloc_t<_Alloc, char>; | |||||
static_assert(is_same_v<char*, typename allocator_traits<_Alloc_char>::pointer>, | |||||
"generator does not support allocators with fancy pointer types"); | |||||
static_assert(allocator_traits<_Alloc_char>::is_always_equal::value, | |||||
"generator only supports stateless allocators"); | |||||
void *operator new(size_t _Size) | |||||
reference operator*() const | |||||
{ | { | ||||
_Alloc_char _Al; | |||||
return _Al.allocate(_Size); | |||||
return *this->_Coro.promise()._CurrentValue; | |||||
} | } | ||||
void operator delete(void *_Ptr, size_t _Size) | |||||
pointer operator->() const | |||||
{ | { | ||||
_Alloc_char _Al; | |||||
return _Al.deallocate(static_cast<char *>(_Ptr), _Size); | |||||
return this->_Coro.promise()._CurrentValue; | |||||
} | } | ||||
}; | }; | ||||
typedef generator_iterator<_Ty, promise_type> iterator; | |||||
iterator begin() | |||||
template <typename _Ty, typename _Alloc = allocator<char>> | |||||
struct generator | |||||
{ | { | ||||
if (_Coro) | |||||
struct promise_type | |||||
{ | { | ||||
_Coro.resume(); | |||||
if (_Coro.done()) | |||||
return{ nullptr }; | |||||
_Ty const* _CurrentValue; | |||||
promise_type& get_return_object() | |||||
{ | |||||
return *this; | |||||
} | |||||
bool initial_suspend() | |||||
{ | |||||
return (true); | |||||
} | |||||
bool final_suspend() | |||||
{ | |||||
return (true); | |||||
} | |||||
void yield_value(_Ty const& _Value) | |||||
{ | |||||
_CurrentValue = std::addressof(_Value); | |||||
} | |||||
template<class = std::enable_if_t<!std::is_same_v<_Ty, void>, _Ty>> | |||||
void return_value(_Ty const& _Value) | |||||
{ | |||||
_CurrentValue = std::addressof(_Value); | |||||
} | |||||
template<class = std::enable_if_t<std::is_same_v<_Ty, void>, _Ty>> | |||||
void return_value() | |||||
{ | |||||
_CurrentValue = nullptr; | |||||
} | |||||
template <typename _Uty> | |||||
_Uty&& await_transform(_Uty&& _Whatever) | |||||
{ | |||||
static_assert(std::is_same_v<_Uty, void>, | |||||
"co_await is not supported in coroutines of type std::experiemental::generator"); | |||||
return std::forward<_Uty>(_Whatever); | |||||
} | |||||
using _Alloc_char = typename allocator_traits<_Alloc>::template rebind_alloc<char>; | |||||
static_assert(std::is_same_v<char*, typename std::allocator_traits<_Alloc_char>::pointer>, | |||||
"generator does not support allocators with fancy pointer types"); | |||||
static_assert(std::allocator_traits<_Alloc_char>::is_always_equal::value, | |||||
"generator only supports stateless allocators"); | |||||
void* operator new(size_t _Size) | |||||
{ | |||||
_Alloc_char _Al; | |||||
return _Al.allocate(_Size); | |||||
} | |||||
void operator delete(void* _Ptr, size_t _Size) | |||||
{ | |||||
_Alloc_char _Al; | |||||
return _Al.deallocate(static_cast<char*>(_Ptr), _Size); | |||||
} | |||||
}; | |||||
typedef generator_iterator<_Ty, promise_type> iterator; | |||||
iterator begin() | |||||
{ | |||||
if (_Coro) | |||||
{ | |||||
_Coro.resume(); | |||||
if (_Coro.done()) | |||||
return{ nullptr }; | |||||
} | |||||
return { _Coro }; | |||||
} | } | ||||
return { _Coro }; | |||||
} | |||||
iterator end() | |||||
{ | |||||
return{ nullptr }; | |||||
} | |||||
explicit generator(promise_type &_Prom) | |||||
: _Coro(coroutine_handle<promise_type>::from_promise(_Prom)) | |||||
{ | |||||
} | |||||
iterator end() | |||||
{ | |||||
return{ nullptr }; | |||||
} | |||||
generator() = default; | |||||
explicit generator(promise_type& _Prom) | |||||
: _Coro(coroutine_handle<promise_type>::from_promise(_Prom)) | |||||
{ | |||||
} | |||||
generator(generator const &) = delete; | |||||
generator() = default; | |||||
generator &operator=(generator const &) = delete; | |||||
generator(generator const&) = delete; | |||||
generator(generator &&right_) noexcept | |||||
: _Coro(right_._Coro) | |||||
{ | |||||
right_._Coro = nullptr; | |||||
} | |||||
generator& operator=(generator const&) = delete; | |||||
generator &operator=(generator &&right_) noexcept | |||||
{ | |||||
if (this != _STD addressof(right_)) { | |||||
_Coro = right_._Coro; | |||||
generator(generator&& right_) noexcept | |||||
: _Coro(right_._Coro) | |||||
{ | |||||
right_._Coro = nullptr; | right_._Coro = nullptr; | ||||
} | } | ||||
return *this; | |||||
} | |||||
~generator() | |||||
{ | |||||
if (_Coro) { | |||||
_Coro.destroy(); | |||||
generator& operator=(generator&& right_) noexcept | |||||
{ | |||||
if (this != std::addressof(right_)) { | |||||
_Coro = right_._Coro; | |||||
right_._Coro = nullptr; | |||||
} | |||||
return *this; | |||||
} | } | ||||
} | |||||
coroutine_handle<promise_type> detach() | |||||
{ | |||||
auto t = _Coro; | |||||
_Coro = nullptr; | |||||
return t; | |||||
} | |||||
~generator() | |||||
{ | |||||
if (_Coro) { | |||||
_Coro.destroy(); | |||||
} | |||||
} | |||||
private: | |||||
coroutine_handle<promise_type> _Coro = nullptr; | |||||
}; | |||||
coroutine_handle<promise_type> detach() | |||||
{ | |||||
auto t = _Coro; | |||||
_Coro = nullptr; | |||||
return t; | |||||
} | |||||
} // namespace experimental | |||||
private: | |||||
coroutine_handle<promise_type> _Coro = nullptr; | |||||
}; | |||||
_STD_END | |||||
} // namespace experimental | |||||
} // namespace std | |||||
#pragma pop_macro("new") | #pragma pop_macro("new") | ||||
#pragma pack(pop) | #pragma pack(pop) |
RF_API mutex_impl(); | RF_API mutex_impl(); | ||||
//如果已经触发了awaker,则返回true | //如果已经触发了awaker,则返回true | ||||
RF_API bool lock_(const mutex_awaker_ptr & awaker); | |||||
RF_API bool try_lock_(const mutex_awaker_ptr & awaker); | |||||
RF_API bool lock_(const mutex_awaker_ptr& awaker); | |||||
RF_API bool try_lock_(const mutex_awaker_ptr& awaker); | |||||
RF_API void unlock(); | RF_API void unlock(); | ||||
template<class callee_t, class dummy_t = std::enable_if<!std::is_same<std::remove_cv_t<callee_t>, mutex_awaker_ptr>::value>> | template<class callee_t, class dummy_t = std::enable_if<!std::is_same<std::remove_cv_t<callee_t>, mutex_awaker_ptr>::value>> | ||||
decltype(auto) lock(callee_t && awaker, dummy_t * dummy_ = nullptr) | |||||
decltype(auto) lock(callee_t&& awaker, dummy_t* dummy_ = nullptr) | |||||
{ | { | ||||
(void)dummy_; | |||||
return lock_(std::make_shared<mutex_awaker>(std::forward<callee_t>(awaker))); | return lock_(std::make_shared<mutex_awaker>(std::forward<callee_t>(awaker))); | ||||
} | } | ||||
private: | private: | ||||
mutex_impl(const mutex_impl &) = delete; | |||||
mutex_impl(mutex_impl &&) = delete; | |||||
mutex_impl & operator = (const mutex_impl &) = delete; | |||||
mutex_impl & operator = (mutex_impl &&) = delete; | |||||
mutex_impl(const mutex_impl&) = delete; | |||||
mutex_impl(mutex_impl&&) = delete; | |||||
mutex_impl& operator = (const mutex_impl&) = delete; | |||||
mutex_impl& operator = (mutex_impl&&) = delete; | |||||
}; | }; | ||||
} | } | ||||
RF_API bool | RF_API bool | ||||
try_lock() const; | try_lock() const; | ||||
/* | |||||
template<class _Rep, class _Period> | |||||
awaitable_t<bool> | |||||
/* | |||||
template<class _Rep, class _Period> | |||||
awaitable_t<bool> | |||||
try_lock_for(const std::chrono::duration<_Rep, _Period> & dt) const | try_lock_for(const std::chrono::duration<_Rep, _Period> & dt) const | ||||
{ | { | ||||
return try_lock_for_(std::chrono::duration_cast<clock_type::duration>(dt)); | return try_lock_for_(std::chrono::duration_cast<clock_type::duration>(dt)); | ||||
} | } | ||||
template<class _Clock, class _Duration> | |||||
awaitable_t<bool> | |||||
template<class _Clock, class _Duration> | |||||
awaitable_t<bool> | |||||
try_lock_until(const std::chrono::time_point<_Clock, _Duration> & tp) const | try_lock_until(const std::chrono::time_point<_Clock, _Duration> & tp) const | ||||
{ | { | ||||
return try_lock_until_(std::chrono::time_point_cast<clock_type::duration>(tp)); | return try_lock_until_(std::chrono::time_point_cast<clock_type::duration>(tp)); | ||||
} | } | ||||
*/ | |||||
*/ | |||||
RF_API mutex_t(const mutex_t &) = default; | |||||
RF_API mutex_t(mutex_t &&) = default; | |||||
RF_API mutex_t & operator = (const mutex_t &) = default; | |||||
RF_API mutex_t & operator = (mutex_t &&) = default; | |||||
RF_API mutex_t(const mutex_t&) = default; | |||||
RF_API mutex_t(mutex_t&&) = default; | |||||
RF_API mutex_t& operator = (const mutex_t&) = default; | |||||
RF_API mutex_t& operator = (mutex_t&&) = default; | |||||
private: | private: | ||||
inline future_t<bool> try_lock_for_(const clock_type::duration & dt) const | |||||
inline future_t<bool> try_lock_for_(const clock_type::duration& dt) const | |||||
{ | { | ||||
return try_lock_until_(clock_type::now() + dt); | return try_lock_until_(clock_type::now() + dt); | ||||
} | } | ||||
RF_API future_t<bool> try_lock_until_(const clock_type::time_point & tp) const; | |||||
RF_API future_t<bool> try_lock_until_(const clock_type::time_point& tp) const; | |||||
}; | }; | ||||
#if _HAS_CXX17 | #if _HAS_CXX17 |
promise_impl_t(promise_impl_t&& _Right) noexcept = default; | promise_impl_t(promise_impl_t&& _Right) noexcept = default; | ||||
promise_impl_t& operator = (promise_impl_t&& _Right) noexcept = default; | promise_impl_t& operator = (promise_impl_t&& _Right) noexcept = default; | ||||
promise_impl_t(const promise_impl_t&) = delete; | promise_impl_t(const promise_impl_t&) = delete; | ||||
promise_impl_t & operator = (const promise_impl_t&) = delete; | |||||
promise_impl_t& operator = (const promise_impl_t&) = delete; | |||||
suspend_on_initial initial_suspend() noexcept; | suspend_on_initial initial_suspend() noexcept; | ||||
suspend_on_final final_suspend() noexcept; | suspend_on_final final_suspend() noexcept; | ||||
future_type get_return_object(); | future_type get_return_object(); | ||||
void cancellation_requested(); | void cancellation_requested(); | ||||
}; | }; | ||||
template<class _Ty> | template<class _Ty> | ||||
struct promise_t : public promise_impl_t<_Ty> | struct promise_t : public promise_impl_t<_Ty> | ||||
{ | { | ||||
using typename promise_impl_t<_Ty>::value_type; | |||||
using promise_impl_t<_Ty>::_state; | using promise_impl_t<_Ty>::_state; | ||||
void return_value(value_type val); | void return_value(value_type val); |
using state_type = state_t<value_type>; | using state_type = state_t<value_type>; | ||||
task_t() = default; | task_t() = default; | ||||
task_t(future_type && f) | |||||
task_t(future_type&& f) | |||||
{ | { | ||||
initialize(std::forward<future_type>(f)); | initialize(std::forward<future_type>(f)); | ||||
} | } | ||||
//这个'函数对象'被调用后,返回generator<_Ty>/future_t<_Ty>类型 | //这个'函数对象'被调用后,返回generator<_Ty>/future_t<_Ty>类型 | ||||
//然后'函数对象'作为异步执行的上下文状态保存起来 | //然后'函数对象'作为异步执行的上下文状态保存起来 | ||||
template<class _Ctx> | 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_t<remove_cvref_t<decltype(std::declval<_Ctx>()())>> | |||||
{ | { | ||||
using context_type = _Ctx; | using context_type = _Ctx; | ||||
timer_mgr_ptr _timer; | timer_mgr_ptr _timer; | ||||
RF_API void new_task(task_base_t * task); | |||||
RF_API void new_task(task_base_t* task); | |||||
//void cancel_all_task_(); | //void cancel_all_task_(); | ||||
public: | public: | ||||
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> || is_generator_v<_Ty> >> | |||||
inline void operator + (_Ty && t_) | |||||
template<class _Ty, typename = std::enable_if_t<std::is_callable<_Ty>::value || is_future_v<_Ty> || is_generator_v<_Ty> >> | |||||
inline void operator + (_Ty&& t_) | |||||
{ | { | ||||
if constexpr(std::is_callable_v<_Ty>) | |||||
if constexpr (std::is_callable<_Ty>::value) | |||||
new_task(new ctx_task_t<_Ty>(std::forward<_Ty>(t_))); | new_task(new ctx_task_t<_Ty>(std::forward<_Ty>(t_))); | ||||
else | else | ||||
new_task(new task_t<_Ty>(std::forward<_Ty>(t_))); | new_task(new task_t<_Ty>(std::forward<_Ty>(t_))); | ||||
return _ready_task.empty() && _runing_states.empty() && _timer->empty(); | return _ready_task.empty() && _runing_states.empty() && _timer->empty(); | ||||
} | } | ||||
inline timer_manager * timer() const | |||||
inline timer_manager* timer() const | |||||
{ | { | ||||
return _timer.get(); | return _timer.get(); | ||||
} | } | ||||
RF_API local_scheduler(); | RF_API local_scheduler(); | ||||
RF_API ~local_scheduler(); | RF_API ~local_scheduler(); | ||||
local_scheduler(local_scheduler && right_) = delete; | |||||
local_scheduler & operator = (local_scheduler && right_) = delete; | |||||
local_scheduler(const local_scheduler &) = delete; | |||||
local_scheduler & operator = (const local_scheduler &) = delete; | |||||
local_scheduler(local_scheduler&& right_) = delete; | |||||
local_scheduler& operator = (local_scheduler&& right_) = delete; | |||||
local_scheduler(const local_scheduler&) = delete; | |||||
local_scheduler& operator = (const local_scheduler&) = delete; | |||||
#if RESUMEF_ENABLE_MULT_SCHEDULER | #if RESUMEF_ENABLE_MULT_SCHEDULER | ||||
private: | private: | ||||
scheduler_t* _scheduler_ptr; | scheduler_t* _scheduler_ptr; | ||||
#endif | #endif | ||||
}; | }; | ||||
//-------------------------------------------------------------------------------------------------- | |||||
//-------------------------------------------------------------------------------------------------- | |||||
#if !RESUMEF_ENABLE_MULT_SCHEDULER | #if !RESUMEF_ENABLE_MULT_SCHEDULER | ||||
//获得当前线程下的调度器 | //获得当前线程下的调度器 | ||||
inline scheduler_t* this_scheduler() | inline scheduler_t* this_scheduler() | ||||
#define GO (*::resumef::this_scheduler()) + [=]()mutable->resumef::future_t<> | #define GO (*::resumef::this_scheduler()) + [=]()mutable->resumef::future_t<> | ||||
#endif | #endif | ||||
//-------------------------------------------------------------------------------------------------- | |||||
//-------------------------------------------------------------------------------------------------- | |||||
} | } |
inline future_t<> sleep_for_(const std::chrono::system_clock::duration& dt_, scheduler_t& 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_)); | |||||
return sleep_until_(std::chrono::system_clock::now() + dt_, scheduler_); | |||||
} | } | ||||
template<class _Rep, class _Period> | template<class _Rep, class _Period> |
template<class _Ty> | template<class _Ty> | ||||
struct is_promise<promise_t<_Ty>> : std::true_type {}; | struct is_promise<promise_t<_Ty>> : std::true_type {}; | ||||
template<class _Ty> | template<class _Ty> | ||||
_INLINE_VAR constexpr bool is_promise_v = is_promise<std::remove_cvref_t<_Ty>>::value; | |||||
constexpr bool is_promise_v = is_promise<remove_cvref_t<_Ty>>::value; | |||||
template<class _PromiseT> | template<class _PromiseT> | ||||
struct is_future : std::false_type {}; | struct is_future : std::false_type {}; | ||||
template<class _Ty> | template<class _Ty> | ||||
struct is_future<future_t<_Ty>> : std::true_type {}; | struct is_future<future_t<_Ty>> : std::true_type {}; | ||||
template<class _Ty> | template<class _Ty> | ||||
_INLINE_VAR constexpr bool is_future_v = is_future<std::remove_cvref_t<_Ty>>::value; | |||||
constexpr bool is_future_v = is_future<remove_cvref_t<_Ty>>::value; | |||||
template<class _G> | template<class _G> | ||||
struct is_generator : std::false_type {}; | struct is_generator : std::false_type {}; | ||||
template <typename _Ty, typename _Alloc> | template <typename _Ty, typename _Alloc> | ||||
struct is_generator<generator_t<_Ty, _Alloc>> : std::true_type {}; | struct is_generator<generator_t<_Ty, _Alloc>> : std::true_type {}; | ||||
template<class _Ty> | template<class _Ty> | ||||
_INLINE_VAR constexpr bool is_generator_v = is_generator<std::remove_cvref_t<_Ty>>::value; | |||||
constexpr bool is_generator_v = is_generator<remove_cvref_t<_Ty>>::value; | |||||
} | } |
auto tostring_async(_Input_t&& value, _Callable_t&& token) | auto tostring_async(_Input_t&& value, _Callable_t&& token) | ||||
{ | { | ||||
//适配器类型 | //适配器类型 | ||||
using _Adapter_t = modern_callback_adapter_t<typename std::remove_cvref<_Callable_t>::type, void(std::string)>; | |||||
using _Adapter_t = modern_callback_adapter_t<typename resumef::remove_cvref_t<_Callable_t>, void(std::string)>; | |||||
//通过适配器获得兼容_Signature_t类型的真正的回调,以及返回值_Return_t | //通过适配器获得兼容_Signature_t类型的真正的回调,以及返回值_Return_t | ||||
auto adapter = typename _Adapter_t::traits(std::forward<_Callable_t>(token)); | auto adapter = typename _Adapter_t::traits(std::forward<_Callable_t>(token)); | ||||
//或者宏版本写法 | //或者宏版本写法 | ||||
#define MODERN_CALLBACK_TRAITS(_Token_value, _Signature_t) \ | #define MODERN_CALLBACK_TRAITS(_Token_value, _Signature_t) \ | ||||
using _Adapter_t = modern_callback_adapter_t<typename std::remove_cvref<_Callable_t>::type, _Signature_t>; \ | |||||
using _Adapter_t = modern_callback_adapter_t<typename resumef::remove_cvref_t<_Callable_t>, _Signature_t>; \ | |||||
auto _Adapter_value = typename _Adapter_t::traits(std::forward<_Callable_t>(_Token_value)) | auto _Adapter_value = typename _Adapter_t::traits(std::forward<_Callable_t>(_Token_value)) | ||||
#define MODERN_CALLBACK_CALL() std::move(std::get<0>(_Adapter_value)) | #define MODERN_CALLBACK_CALL() std::move(std::get<0>(_Adapter_value)) | ||||
#define MODERN_CALLBACK_RETURN() return std::move(std::get<1>(_Adapter_value)).get() | #define MODERN_CALLBACK_RETURN() return std::move(std::get<1>(_Adapter_value)).get() |