@@ -3,10 +3,11 @@ | |||
### librf - 协程库 | |||
2020-02-16 更新: | |||
更新调度器算法,深入应用Coroutines的特性,以期获得更高调度性能。 | |||
不再支持C++14。 | |||
librf是一个基于C++ Coroutines提案 ‘Stackless Resumable Functions’编写的非对称stackless协程库。 | |||
librf是一个基于C++ Coroutines提案 ‘Stackless Resumable Functions’编写的非对称stackless协程库。 | |||
目前仅支持: | |||
@@ -19,8 +19,8 @@ namespace resumef | |||
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> | |||
@@ -31,7 +31,7 @@ namespace resumef | |||
future_type get_future() | |||
{ | |||
return future_type{ _state }; | |||
return future_type{ this->_state }; | |||
} | |||
mutable counted_ptr<state_type> _state = make_counted<state_type>(true); | |||
@@ -40,24 +40,25 @@ namespace resumef | |||
template<class _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 | |||
{ | |||
_state->set_value(std::move(value)); | |||
_state = nullptr; | |||
this->_state->set_value(std::move(value)); | |||
this->_state = nullptr; | |||
} | |||
}; | |||
template<> | |||
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 | |||
{ | |||
_state->set_value(); | |||
_state = nullptr; | |||
this->_state->set_value(); | |||
this->_state = nullptr; | |||
} | |||
}; | |||
} |
@@ -9,6 +9,7 @@ | |||
#include <deque> | |||
#include <mutex> | |||
#include <map> | |||
#include <unordered_map> | |||
#include <optional> | |||
#include <assert.h> | |||
@@ -45,13 +46,8 @@ namespace resumef | |||
struct state_base_t; | |||
#if _HAS_CXX17 | |||
template<class... _Mutexes> | |||
using scoped_lock = std::scoped_lock<_Mutexes...>; | |||
#else | |||
template<class... _Mutexes> | |||
using scoped_lock = std::lock_guard<_Mutexes...>; | |||
#endif | |||
} | |||
#if RESUMEF_DEBUG_COUNTER | |||
@@ -62,19 +58,15 @@ extern std::atomic<intptr_t> g_resumef_evtctx_count; | |||
extern std::atomic<intptr_t> g_resumef_state_id; | |||
#endif | |||
namespace std | |||
namespace resumef | |||
{ | |||
#if !_HAS_CXX20 | |||
template<class T> | |||
struct remove_cvref | |||
{ | |||
typedef std::remove_cv_t<std::remove_reference_t<T>> type; | |||
}; | |||
#if _HAS_CXX17 | |||
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) |
@@ -26,18 +26,19 @@ namespace resumef | |||
RF_API void reset(); | |||
//如果已经触发了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>> | |||
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))); | |||
} | |||
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; | |||
}; | |||
} | |||
@@ -68,15 +69,15 @@ namespace resumef | |||
RF_API future_t<bool> | |||
wait() const; | |||
template<class _Rep, class _Period> | |||
template<class _Rep, class _Period> | |||
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)); | |||
} | |||
template<class _Clock, class _Duration> | |||
template<class _Clock, class _Duration> | |||
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)); | |||
} | |||
@@ -93,33 +94,33 @@ namespace resumef | |||
} | |||
template<class _Cont> | |||
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_))); | |||
} | |||
template<class _Rep, class _Period, class _Iter> | |||
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_)); | |||
} | |||
template<class _Rep, class _Period, class _Cont> | |||
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_))); | |||
} | |||
template<class _Clock, class _Duration, class _Iter> | |||
template<class _Clock, class _Duration, class _Iter> | |||
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_)); | |||
} | |||
template<class _Clock, class _Duration, class _Cont> | |||
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_))); | |||
} | |||
@@ -136,43 +137,43 @@ namespace resumef | |||
} | |||
template<class _Cont> | |||
static future_t<bool> | |||
wait_all(const _Cont & cnt_) | |||
wait_all(const _Cont& cnt_) | |||
{ | |||
return wait_all(std::begin(cnt_), std::end(cnt_)); | |||
} | |||
template<class _Rep, class _Period, class _Iter> | |||
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_)); | |||
} | |||
template<class _Rep, class _Period, class _Cont> | |||
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_))); | |||
} | |||
template<class _Clock, class _Duration, class _Iter> | |||
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_)); | |||
} | |||
template<class _Clock, class _Duration, class _Cont> | |||
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_))); | |||
} | |||
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: | |||
template<class _Iter> | |||
@@ -183,30 +184,30 @@ namespace resumef | |||
for (auto i = begin_; i != end_; ++i) | |||
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); | |||
} | |||
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)); | |||
} | |||
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)); | |||
} | |||
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); | |||
}; | |||
} |
@@ -16,41 +16,41 @@ namespace resumef | |||
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; | |||
future_exception(error_code fe) | |||
: exception(get_error_string(fe, "future_exception")) | |||
: logic_error(get_error_string(fe, "future_exception")) | |||
, _error(fe) | |||
{ | |||
} | |||
}; | |||
struct lock_exception : std::exception | |||
struct lock_exception : std::logic_error | |||
{ | |||
error_code _error; | |||
lock_exception(error_code fe) | |||
: exception(get_error_string(fe, "lock_exception")) | |||
: logic_error(get_error_string(fe, "lock_exception")) | |||
, _error(fe) | |||
{ | |||
} | |||
}; | |||
struct channel_exception : std::exception | |||
struct channel_exception : std::logic_error | |||
{ | |||
error_code _error; | |||
channel_exception(error_code fe) | |||
: exception(get_error_string(fe, "channel_exception")) | |||
: logic_error(get_error_string(fe, "channel_exception")) | |||
, _error(fe) | |||
{ | |||
} | |||
}; | |||
struct timer_canceled_exception : public std::exception | |||
struct timer_canceled_exception : public std::logic_error | |||
{ | |||
error_code _error; | |||
timer_canceled_exception(error_code fe) | |||
: exception(get_error_string(fe, "timer canceled")) | |||
: logic_error(get_error_string(fe, "timer canceled")) | |||
, _error(fe) | |||
{ | |||
} |
@@ -14,234 +14,225 @@ | |||
#define _EXPERIMENTAL_GENERATOR_ | |||
#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 warning(push,_STL_WARNING_LEVEL) | |||
#pragma warning(disable: _STL_DISABLED_WARNINGS) | |||
_STL_DISABLE_CLANG_WARNINGS | |||
#pragma push_macro("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; | |||
} | |||
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; | |||
} | |||
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 pack(pop) |
@@ -23,21 +23,22 @@ namespace resumef | |||
RF_API mutex_impl(); | |||
//如果已经触发了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(); | |||
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))); | |||
} | |||
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; | |||
}; | |||
} | |||
@@ -62,32 +63,32 @@ namespace resumef | |||
RF_API bool | |||
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 | |||
{ | |||
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 | |||
{ | |||
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: | |||
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); | |||
} | |||
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 |
@@ -21,7 +21,7 @@ namespace resumef | |||
promise_impl_t(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 & operator = (const promise_impl_t&) = delete; | |||
promise_impl_t& operator = (const promise_impl_t&) = delete; | |||
suspend_on_initial initial_suspend() noexcept; | |||
suspend_on_final final_suspend() noexcept; | |||
@@ -29,10 +29,11 @@ namespace resumef | |||
future_type get_return_object(); | |||
void cancellation_requested(); | |||
}; | |||
template<class _Ty> | |||
struct promise_t : public promise_impl_t<_Ty> | |||
{ | |||
using typename promise_impl_t<_Ty>::value_type; | |||
using promise_impl_t<_Ty>::_state; | |||
void return_value(value_type val); |
@@ -34,7 +34,7 @@ namespace resumef | |||
using state_type = state_t<value_type>; | |||
task_t() = default; | |||
task_t(future_type && f) | |||
task_t(future_type&& f) | |||
{ | |||
initialize(std::forward<future_type>(f)); | |||
} | |||
@@ -70,7 +70,7 @@ 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_t<remove_cvref_t<decltype(std::declval<_Ctx>()())>> | |||
{ | |||
using context_type = _Ctx; | |||
@@ -30,7 +30,7 @@ namespace resumef | |||
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_(); | |||
public: | |||
@@ -39,10 +39,10 @@ namespace resumef | |||
RF_API void run(); | |||
//RF_API void break_all(); | |||
template<class _Ty, typename = std::enable_if_t<std::is_callable_v<_Ty> || is_future_v<_Ty> || 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_))); | |||
else | |||
new_task(new task_t<_Ty>(std::forward<_Ty>(t_))); | |||
@@ -54,7 +54,7 @@ namespace resumef | |||
return _ready_task.empty() && _runing_states.empty() && _timer->empty(); | |||
} | |||
inline timer_manager * timer() const | |||
inline timer_manager* timer() const | |||
{ | |||
return _timer.get(); | |||
} | |||
@@ -85,16 +85,16 @@ namespace resumef | |||
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 | |||
private: | |||
scheduler_t* _scheduler_ptr; | |||
#endif | |||
}; | |||
//-------------------------------------------------------------------------------------------------- | |||
//-------------------------------------------------------------------------------------------------- | |||
#if !RESUMEF_ENABLE_MULT_SCHEDULER | |||
//获得当前线程下的调度器 | |||
inline scheduler_t* this_scheduler() | |||
@@ -108,5 +108,5 @@ namespace resumef | |||
#define GO (*::resumef::this_scheduler()) + [=]()mutable->resumef::future_t<> | |||
#endif | |||
//-------------------------------------------------------------------------------------------------- | |||
//-------------------------------------------------------------------------------------------------- | |||
} |
@@ -12,7 +12,7 @@ namespace resumef | |||
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> |
@@ -7,19 +7,19 @@ namespace resumef | |||
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; | |||
constexpr bool is_promise_v = is_promise<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; | |||
constexpr bool is_future_v = is_future<remove_cvref_t<_Ty>>::value; | |||
template<class _G> | |||
struct is_generator : std::false_type {}; | |||
template <typename _Ty, typename _Alloc> | |||
struct is_generator<generator_t<_Ty, _Alloc>> : std::true_type {}; | |||
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; | |||
} |
@@ -82,7 +82,7 @@ __declspec(noinline) | |||
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 | |||
auto adapter = typename _Adapter_t::traits(std::forward<_Callable_t>(token)); | |||
@@ -100,7 +100,7 @@ auto tostring_async(_Input_t&& value, _Callable_t&& token) | |||
//或者宏版本写法 | |||
#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)) | |||
#define MODERN_CALLBACK_CALL() std::move(std::get<0>(_Adapter_value)) | |||
#define MODERN_CALLBACK_RETURN() return std::move(std::get<1>(_Adapter_value)).get() |