Browse Source

使用自旋锁替代递归锁

tags/v2.9.7
tearshark 4 years ago
parent
commit
8de633c8b6
6 changed files with 98 additions and 46 deletions
  1. 19
    0
      librf/src/spinlock.h
  2. 13
    6
      librf/src/state.cpp
  3. 2
    1
      librf/src/state.h
  4. 57
    36
      librf/src/state.inl
  5. 1
    1
      vs_proj/librf.cpp
  6. 6
    2
      vs_proj/librf.vcxproj

+ 19
- 0
librf/src/spinlock.h View File

@@ -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);
}
};

+ 13
- 6
librf/src/state.cpp View File

@@ -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);

+ 2
- 1
librf/src/state.h View File

@@ -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;

+ 57
- 36
librf/src/state.inl View File

@@ -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();

+ 1
- 1
vs_proj/librf.cpp View File

@@ -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)

+ 6
- 2
vs_proj/librf.vcxproj View File

@@ -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>

Loading…
Cancel
Save