@@ -30,7 +30,7 @@ RESUMEF_NS | |||
set_exception(std::make_exception_ptr(std::move(e))); | |||
} | |||
future_type get_future() | |||
future_type get_future() noexcept | |||
{ | |||
return future_type{ this->_state }; | |||
} |
@@ -6,13 +6,13 @@ RESUMEF_NS | |||
template <typename T> | |||
struct counted_ptr | |||
{ | |||
counted_ptr() = default; | |||
counted_ptr(const counted_ptr& cp) : _p(cp._p) | |||
counted_ptr() noexcept = default; | |||
counted_ptr(const counted_ptr& cp) : _p(cp._p) | |||
{ | |||
_lock(); | |||
} | |||
counted_ptr(T* p) : _p(p) | |||
counted_ptr(T* p) : _p(p) | |||
{ | |||
_lock(); | |||
} | |||
@@ -22,7 +22,7 @@ RESUMEF_NS | |||
std::swap(_p, cp._p); | |||
} | |||
counted_ptr& operator=(const counted_ptr& cp) | |||
counted_ptr& operator=(const counted_ptr& cp) | |||
{ | |||
if (&cp != this) | |||
{ | |||
@@ -44,12 +44,12 @@ RESUMEF_NS | |||
_unlock(); | |||
} | |||
T* operator->() const | |||
T* operator->() const noexcept | |||
{ | |||
return _p; | |||
} | |||
T* get() const | |||
T* get() const noexcept | |||
{ | |||
return _p; | |||
} |
@@ -14,7 +14,7 @@ RESUMEF_NS | |||
counted_ptr<state_type> _state; | |||
future_t(counted_ptr<state_type> _st) | |||
future_t(counted_ptr<state_type> _st) noexcept | |||
:_state(std::move(_st)) {} | |||
future_t(const future_t&) = default; | |||
future_t(future_t&&) = default; | |||
@@ -22,7 +22,7 @@ RESUMEF_NS | |||
future_t& operator = (const future_t&) = default; | |||
future_t& operator = (future_t&&) = default; | |||
bool await_ready() | |||
bool await_ready() noexcept | |||
{ | |||
return _state->future_await_ready(); | |||
} |
@@ -121,29 +121,29 @@ RESUMEF_NS | |||
return generator_t{ *this }; | |||
} | |||
std::experimental::suspend_always initial_suspend() | |||
std::experimental::suspend_always initial_suspend() noexcept | |||
{ | |||
return {}; | |||
} | |||
std::experimental::suspend_always final_suspend() | |||
std::experimental::suspend_always final_suspend() noexcept | |||
{ | |||
return {}; | |||
} | |||
std::experimental::suspend_always yield_value(_Ty const& _Value) | |||
std::experimental::suspend_always yield_value(_Ty const& _Value) noexcept | |||
{ | |||
_CurrentValue = std::addressof(_Value); | |||
return {}; | |||
} | |||
//template<class = std::enable_if_t<!std::is_same_v<_Ty, void>, _Ty>> | |||
void return_value(_Ty const& _Value) | |||
void return_value(_Ty const& _Value) noexcept | |||
{ | |||
_CurrentValue = std::addressof(_Value); | |||
} | |||
//template<class = std::enable_if_t<std::is_same_v<_Ty, void>, _Ty>> | |||
void return_value() | |||
void return_value() noexcept | |||
{ | |||
_CurrentValue = nullptr; | |||
} | |||
@@ -161,14 +161,14 @@ RESUMEF_NS | |||
#endif | |||
template <typename _Uty> | |||
_Uty&& await_transform(_Uty&& _Whatever) | |||
_Uty&& await_transform(_Uty&& _Whatever) noexcept | |||
{ | |||
static_assert(std::is_same_v<_Uty, void>, | |||
"co_await is not supported in coroutines of type std::experiemental::generator_t"); | |||
return std::forward<_Uty>(_Whatever); | |||
} | |||
state_type* get_state() | |||
state_type* get_state() noexcept | |||
{ | |||
#if RESUMEF_INLINE_STATE | |||
size_t _State_size = _Align_size<state_type>(); |
@@ -1,5 +1,9 @@ | |||
#pragma once | |||
#ifndef _offset_of | |||
#define _offset_of(c, m) reinterpret_cast<size_t>(&static_cast<c *>(0)->m) | |||
#endif | |||
#define co_yield_void co_yield nullptr | |||
#define co_return_void co_return nullptr | |||
#define resumf_guard_lock(lker) (lker).lock(); resumef::scoped_lock<resumef::mutex_t> __resumf_guard##lker##__(std::adopt_lock, (lker)) |
@@ -16,24 +16,24 @@ RESUMEF_NS | |||
using promise_type = promise_t<value_type>; | |||
using future_type = future_t<value_type>; | |||
promise_impl_t(){} | |||
promise_impl_t() noexcept {} | |||
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; | |||
auto get_state()->state_type*; | |||
auto get_state() noexcept->state_type*; | |||
suspend_on_initial initial_suspend() noexcept; | |||
suspend_on_final final_suspend() noexcept; | |||
template <typename _Uty> | |||
_Uty&& await_transform(_Uty&& _Whatever); | |||
_Uty&& await_transform(_Uty&& _Whatever) noexcept; | |||
void set_exception(std::exception_ptr e); | |||
#ifdef __clang__ | |||
void unhandled_exception(); //If the coroutine ends with an uncaught exception, it performs the following: | |||
#endif | |||
future_type get_return_object(); | |||
void cancellation_requested(); | |||
future_type get_return_object() noexcept; | |||
void cancellation_requested() noexcept; | |||
using _Alloc_char = std::allocator<char>; | |||
void* operator new(size_t _Size); |
@@ -57,7 +57,7 @@ RESUMEF_NS | |||
template <typename _Ty> | |||
template <typename _Uty> | |||
_Uty&& promise_impl_t<_Ty>::await_transform(_Uty&& _Whatever) | |||
_Uty&& promise_impl_t<_Ty>::await_transform(_Uty&& _Whatever) noexcept | |||
{ | |||
if constexpr (is_future_v<_Uty> || is_awaitable_v<_Uty>) | |||
{ | |||
@@ -81,19 +81,19 @@ RESUMEF_NS | |||
#endif | |||
template <typename _Ty> | |||
inline future_t<_Ty> promise_impl_t<_Ty>::get_return_object() | |||
inline future_t<_Ty> promise_impl_t<_Ty>::get_return_object() noexcept | |||
{ | |||
return { this->get_state() }; | |||
} | |||
template <typename _Ty> | |||
inline void promise_impl_t<_Ty>::cancellation_requested() | |||
inline void promise_impl_t<_Ty>::cancellation_requested() noexcept | |||
{ | |||
} | |||
template <typename _Ty> | |||
auto promise_impl_t<_Ty>::get_state() -> state_type* | |||
auto promise_impl_t<_Ty>::get_state() noexcept -> state_type* | |||
{ | |||
#if RESUMEF_INLINE_STATE | |||
size_t _State_size = _Align_size<state_type>(); |
@@ -9,7 +9,7 @@ RESUMEF_NS | |||
task_base_t() = default; | |||
virtual ~task_base_t(); | |||
state_base_t* get_state() const | |||
state_base_t* get_state() const noexcept | |||
{ | |||
return _state.get(); | |||
} |
@@ -45,7 +45,7 @@ RESUMEF_NS | |||
return _ready_task.empty() && _runing_states.empty() && _timer->empty(); | |||
} | |||
inline timer_manager* timer() const | |||
inline timer_manager* timer() const noexcept | |||
{ | |||
return _timer.get(); | |||
} |
@@ -15,12 +15,12 @@ RESUMEF_NS | |||
std::thread::id owner_thread_id; | |||
#endif | |||
spinlock() | |||
spinlock() noexcept | |||
{ | |||
lck = FREE_VALUE; | |||
} | |||
void lock() | |||
void lock() noexcept | |||
{ | |||
using namespace std::chrono; | |||
@@ -55,7 +55,7 @@ RESUMEF_NS | |||
#endif | |||
} | |||
bool try_lock() | |||
bool try_lock() noexcept | |||
{ | |||
int val = FREE_VALUE; | |||
bool ret = lck.compare_exchange_weak(val, LOCKED_VALUE, std::memory_order_acquire); | |||
@@ -67,7 +67,7 @@ RESUMEF_NS | |||
return ret; | |||
} | |||
void unlock() | |||
void unlock() noexcept | |||
{ | |||
#if _DEBUG | |||
owner_thread_id = std::thread::id(); |
@@ -54,7 +54,7 @@ RESUMEF_NS | |||
} | |||
} | |||
bool state_generator_t::has_handler() const | |||
bool state_generator_t::has_handler() const noexcept | |||
{ | |||
return (bool)_coro; | |||
} | |||
@@ -120,7 +120,7 @@ RESUMEF_NS | |||
} | |||
} | |||
bool state_future_t::has_handler() const | |||
bool state_future_t::has_handler() const noexcept | |||
{ | |||
scoped_lock<lock_type> __guard(_mtx); | |||
return has_handler_skip_lock(); |
@@ -32,7 +32,7 @@ RESUMEF_NS | |||
virtual void destroy_deallocate() = 0; | |||
public: | |||
virtual void resume() = 0; | |||
virtual bool has_handler() const = 0; | |||
virtual bool has_handler() const noexcept = 0; | |||
void set_scheduler(scheduler_t* sch) | |||
{ | |||
@@ -50,7 +50,7 @@ RESUMEF_NS | |||
virtual void destroy_deallocate() override; | |||
public: | |||
virtual void resume() override; | |||
virtual bool has_handler() const override; | |||
virtual bool has_handler() const noexcept override; | |||
bool switch_scheduler_await_suspend(scheduler_t* sch, coroutine_handle<> handler); | |||
@@ -100,6 +100,12 @@ RESUMEF_NS | |||
std::atomic<result_type> _has_value{ result_type::None }; | |||
bool _is_future; | |||
initor_type _is_initor = initor_type::None; | |||
static_assert(sizeof(std::atomic<result_type>) == 1); | |||
static_assert(alignof(std::atomic<result_type>) == 1); | |||
static_assert(sizeof(bool) == 1); | |||
static_assert(alignof(bool) == 1); | |||
static_assert(sizeof(std::atomic<initor_type>) == 1); | |||
static_assert(alignof(std::atomic<initor_type>) == 1); | |||
public: | |||
state_future_t() | |||
{ | |||
@@ -118,14 +124,22 @@ RESUMEF_NS | |||
virtual void destroy_deallocate() override; | |||
virtual void resume() override; | |||
virtual bool has_handler() const override; | |||
virtual bool has_handler() const noexcept override; | |||
inline bool is_ready() const | |||
inline bool is_ready() const noexcept | |||
{ | |||
return 0 != reinterpret_cast<const std::atomic<uint16_t> &>(_has_value).load(std::memory_order_acquire); | |||
//return _has_value.load(std::memory_order_acquire) != result_type::None || _is_future; | |||
//msvc认为是constexpr表达式(不写还给警告),然而,clang不这么认为。 | |||
//放弃constexpr,反正合格的编译器都会优化掉这个if判断的。 | |||
if | |||
#ifndef __clang__ | |||
constexpr | |||
#endif | |||
(_offset_of(state_future_t, _is_future) - _offset_of(state_future_t, _has_value) == 1) | |||
return 0 != reinterpret_cast<const std::atomic<uint16_t> &>(_has_value).load(std::memory_order_acquire); | |||
else | |||
return _has_value.load(std::memory_order_acquire) != result_type::None || _is_future; | |||
} | |||
inline bool has_handler_skip_lock() const | |||
inline bool has_handler_skip_lock() const noexcept | |||
{ | |||
return (bool)_coro || _is_initor != initor_type::None; | |||
} | |||
@@ -135,16 +149,16 @@ RESUMEF_NS | |||
return _parent ? _parent->get_scheduler() : _scheduler; | |||
} | |||
inline state_base_t * get_parent() const | |||
inline state_base_t * get_parent() const noexcept | |||
{ | |||
return _parent; | |||
} | |||
inline uint32_t get_alloc_size() const | |||
inline uint32_t get_alloc_size() const noexcept | |||
{ | |||
return _alloc_size; | |||
} | |||
inline bool future_await_ready() | |||
inline bool future_await_ready() noexcept | |||
{ | |||
//scoped_lock<lock_type> __guard(this->_mtx); | |||
return _has_value.load(std::memory_order_acquire) != result_type::None; | |||
@@ -199,7 +213,7 @@ RESUMEF_NS | |||
case result_type::Exception: | |||
_exception.~exception_ptr(); | |||
break; | |||
default: | |||
default: | |||
break; | |||
} | |||
} |
@@ -12,7 +12,7 @@ RESUMEF_NS | |||
switch_scheduler_t& operator = (const switch_scheduler_t&) = default; | |||
switch_scheduler_t& operator = (switch_scheduler_t&&) = default; | |||
bool await_ready() | |||
bool await_ready() noexcept | |||
{ | |||
return false; | |||
} | |||
@@ -26,7 +26,7 @@ RESUMEF_NS | |||
sptr->switch_scheduler_await_suspend(_scheduler, handler); | |||
} | |||
void await_resume() | |||
void await_resume() noexcept | |||
{ | |||
} | |||
private: |
@@ -46,7 +46,7 @@ | |||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration"> | |||
<ConfigurationType>Application</ConfigurationType> | |||
<UseDebugLibraries>false</UseDebugLibraries> | |||
<PlatformToolset>ClangCL</PlatformToolset> | |||
<PlatformToolset>v142</PlatformToolset> | |||
<WholeProgramOptimization>true</WholeProgramOptimization> | |||
<CharacterSet>NotSet</CharacterSet> | |||
</PropertyGroup> |