@@ -11,6 +11,9 @@ RESUMEF_NS | |||
static const int LOCKED_VALUE = 1; | |||
volatile std::atomic<int> lck; | |||
#if _DEBUG | |||
std::thread::id owner_thread_id; | |||
#endif | |||
spinlock() | |||
{ | |||
@@ -24,6 +27,10 @@ RESUMEF_NS | |||
int val = FREE_VALUE; | |||
if (!lck.compare_exchange_weak(val, LOCKED_VALUE, std::memory_order_acquire)) | |||
{ | |||
#if _DEBUG | |||
assert(owner_thread_id != std::this_thread::get_id()); | |||
#endif | |||
size_t spinCount = 0; | |||
auto dt = 1ms; | |||
do | |||
@@ -42,17 +49,29 @@ RESUMEF_NS | |||
val = FREE_VALUE; | |||
} while (!lck.compare_exchange_weak(val, LOCKED_VALUE, std::memory_order_acquire)); | |||
} | |||
#if _DEBUG | |||
owner_thread_id = std::this_thread::get_id(); | |||
#endif | |||
} | |||
bool try_lock() | |||
{ | |||
int val = FREE_VALUE; | |||
bool ret = lck.compare_exchange_weak(val, LOCKED_VALUE, std::memory_order_acquire); | |||
#if _DEBUG | |||
if (ret) owner_thread_id = std::this_thread::get_id(); | |||
#endif | |||
return ret; | |||
} | |||
void unlock() | |||
{ | |||
#if _DEBUG | |||
owner_thread_id = std::thread::id(); | |||
#endif | |||
lck.store(FREE_VALUE, std::memory_order_release); | |||
} | |||
}; |
@@ -94,10 +94,11 @@ RESUMEF_NS | |||
{ | |||
assert((bool)_initor); | |||
coroutine_handle<> handler = _initor; | |||
_is_initor = initor_type::None; | |||
__guard.unlock(); | |||
_initor.resume(); | |||
handler.resume(); | |||
return; | |||
} | |||
@@ -115,10 +116,11 @@ RESUMEF_NS | |||
{ | |||
assert((bool)_initor); | |||
coroutine_handle<> handler = _initor; | |||
_is_initor = initor_type::None; | |||
__guard.unlock(); | |||
_initor.destroy(); | |||
handler.destroy(); | |||
return; | |||
} | |||
} | |||
@@ -137,9 +139,11 @@ RESUMEF_NS | |||
void state_future_t::set_exception(std::exception_ptr e) | |||
{ | |||
scoped_lock<lock_type> __guard(this->_mtx); | |||
{ | |||
scoped_lock<lock_type> __guard(this->_mtx); | |||
this->_exception = std::move(e); | |||
} | |||
this->_exception = std::move(e); | |||
scheduler_t* sch = this->get_scheduler(); | |||
if (sch != nullptr) | |||
sch->add_ready(this); | |||
@@ -178,6 +182,7 @@ RESUMEF_NS | |||
void state_t<void>::future_await_resume() | |||
{ | |||
scoped_lock<lock_type> __guard(this->_mtx); | |||
if (this->_exception) | |||
std::rethrow_exception(std::move(this->_exception)); | |||
if (!this->_has_value) | |||
@@ -186,9 +191,11 @@ RESUMEF_NS | |||
void state_t<void>::set_value() | |||
{ | |||
scoped_lock<lock_type> __guard(this->_mtx); | |||
{ | |||
scoped_lock<lock_type> __guard(this->_mtx); | |||
this->_has_value = true; | |||
} | |||
this->_has_value = true; | |||
scheduler_t* sch = this->get_scheduler(); | |||
if (sch != nullptr) | |||
sch->add_ready(this); |
@@ -81,7 +81,8 @@ RESUMEF_NS | |||
Initial, | |||
Final | |||
}; | |||
typedef std::recursive_mutex lock_type; | |||
//typedef std::recursive_mutex lock_type; | |||
typedef spinlock lock_type; | |||
protected: | |||
mutable lock_type _mtx; | |||
coroutine_handle<> _initor; |
@@ -14,10 +14,12 @@ RESUMEF_NS | |||
template<class _PromiseT, typename _Enable> | |||
void state_future_t::promise_final_suspend(coroutine_handle<_PromiseT> handler) | |||
{ | |||
scoped_lock<lock_type> __guard(this->_mtx); | |||
{ | |||
scoped_lock<lock_type> __guard(this->_mtx); | |||
this->_initor = handler; | |||
this->_is_initor = initor_type::Final; | |||
this->_initor = handler; | |||
this->_is_initor = initor_type::Final; | |||
} | |||
scheduler_t* sch = this->get_scheduler(); | |||
assert(sch != nullptr); | |||
@@ -27,19 +29,22 @@ RESUMEF_NS | |||
template<class _PromiseT, typename _Enable> | |||
void state_future_t::future_await_suspend(coroutine_handle<_PromiseT> handler) | |||
{ | |||
scoped_lock<lock_type> __guard(this->_mtx); | |||
_PromiseT& promise = handler.promise(); | |||
auto* parent_state = promise.get_state(); | |||
scheduler_t* sch = parent_state->get_scheduler(); | |||
if (this != parent_state) | |||
{ | |||
this->_parent = parent_state; | |||
this->_scheduler = sch; | |||
scoped_lock<lock_type> __guard(this->_mtx); | |||
if (this != parent_state) | |||
{ | |||
this->_parent = parent_state; | |||
this->_scheduler = sch; | |||
} | |||
if (!this->_coro) | |||
this->_coro = handler; | |||
} | |||
if (!_coro) | |||
this->_coro = handler; | |||
if (sch != nullptr) | |||
sch->add_await(this); | |||
@@ -48,15 +53,22 @@ RESUMEF_NS | |||
template<class _PromiseT, typename _Enable > | |||
void state_t<void>::promise_yield_value(_PromiseT* promise) | |||
{ | |||
scoped_lock<lock_type> __guard(this->_mtx); | |||
coroutine_handle<_PromiseT> handler = coroutine_handle<_PromiseT>::from_promise(*promise); | |||
{ | |||
scoped_lock<lock_type> __guard(this->_mtx); | |||
this->_has_value = true; | |||
if (!handler.done()) | |||
{ | |||
if (!this->_coro) | |||
this->_coro = handler; | |||
} | |||
this->_has_value = true; | |||
} | |||
coroutine_handle<_PromiseT> handler = coroutine_handle<_PromiseT>::from_promise(*promise); | |||
if (!handler.done()) | |||
{ | |||
if (!this->_coro) | |||
this->_coro = handler; | |||
scheduler_t* sch = this->get_scheduler(); | |||
if (sch != nullptr) | |||
sch->add_generator(this); | |||
@@ -67,23 +79,30 @@ RESUMEF_NS | |||
template<class _PromiseT, typename U, typename _Enable > | |||
void state_t<_Ty>::promise_yield_value(_PromiseT* promise, U&& val) | |||
{ | |||
scoped_lock<lock_type> __guard(this->_mtx); | |||
coroutine_handle<_PromiseT> handler = coroutine_handle<_PromiseT>::from_promise(*promise); | |||
if (this->_has_value) | |||
{ | |||
*this->cast_value_ptr() = std::forward<U>(val); | |||
} | |||
else | |||
{ | |||
new (this->cast_value_ptr()) value_type(std::forward<U>(val)); | |||
this->_has_value = true; | |||
scoped_lock<lock_type> __guard(this->_mtx); | |||
if (!handler.done()) | |||
{ | |||
if (this->_coro == nullptr) | |||
this->_coro = handler; | |||
} | |||
if (this->_has_value) | |||
{ | |||
*this->cast_value_ptr() = std::forward<U>(val); | |||
} | |||
else | |||
{ | |||
new (this->cast_value_ptr()) value_type(std::forward<U>(val)); | |||
this->_has_value = true; | |||
} | |||
} | |||
coroutine_handle<_PromiseT> handler = coroutine_handle<_PromiseT>::from_promise(*promise); | |||
if (!handler.done()) | |||
{ | |||
if (this->_coro == nullptr) | |||
this->_coro = handler; | |||
scheduler_t* sch = this->get_scheduler(); | |||
if (sch != nullptr) | |||
sch->add_generator(this); | |||
@@ -106,16 +125,18 @@ RESUMEF_NS | |||
template<typename U> | |||
void state_t<_Ty>::set_value(U&& val) | |||
{ | |||
scoped_lock<lock_type> __guard(this->_mtx); | |||
if (this->_has_value) | |||
{ | |||
*this->cast_value_ptr() = std::forward<U>(val); | |||
} | |||
else | |||
{ | |||
new (this->cast_value_ptr()) value_type(std::forward<U>(val)); | |||
this->_has_value = true; | |||
scoped_lock<lock_type> __guard(this->_mtx); | |||
if (this->_has_value) | |||
{ | |||
*this->cast_value_ptr() = std::forward<U>(val); | |||
} | |||
else | |||
{ | |||
new (this->cast_value_ptr()) value_type(std::forward<U>(val)); | |||
this->_has_value = true; | |||
} | |||
} | |||
scheduler_t* sch = this->get_scheduler(); |
@@ -31,7 +31,7 @@ int main(int argc, const char* argv[]) | |||
{ | |||
(void)argc; | |||
(void)argv; | |||
//resumable_main_resumable(); | |||
//resumable_main_layout(); | |||
//return 0; | |||
//if (argc > 1) |
@@ -40,7 +40,7 @@ | |||
</PropertyGroup> | |||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration"> | |||
<ConfigurationType>Application</ConfigurationType> | |||
<PlatformToolset>ClangCL</PlatformToolset> | |||
<PlatformToolset>v142</PlatformToolset> | |||
<UseDebugLibraries>true</UseDebugLibraries> | |||
</PropertyGroup> | |||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration"> | |||
@@ -78,7 +78,6 @@ | |||
<LinkIncremental>false</LinkIncremental> | |||
</PropertyGroup> | |||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> | |||
<LinkIncremental>false</LinkIncremental> | |||
<CodeAnalysisRuleSet>NativeRecommendedRules.ruleset</CodeAnalysisRuleSet> | |||
<RunCodeAnalysis>false</RunCodeAnalysis> | |||
</PropertyGroup> | |||
@@ -158,6 +157,11 @@ | |||
<SDLCheck> | |||
</SDLCheck> | |||
<EnablePREfast>false</EnablePREfast> | |||
<InlineFunctionExpansion>AnySuitable</InlineFunctionExpansion> | |||
<OmitFramePointers>true</OmitFramePointers> | |||
<EnableFiberSafeOptimizations>true</EnableFiberSafeOptimizations> | |||
<BufferSecurityCheck>false</BufferSecurityCheck> | |||
<EnableParallelCodeGeneration>true</EnableParallelCodeGeneration> | |||
</ClCompile> | |||
<Link> | |||
<SubSystem>Console</SubSystem> |