@@ -358,6 +358,7 @@ inline namespace channel_v2 | |||
read_awaiter(channel_type* ch) noexcept | |||
: _channel(ch) | |||
, _value() | |||
{} | |||
~read_awaiter() |
@@ -219,11 +219,9 @@ RESUMEF_NS | |||
clock_type::time_point _tp; | |||
}; | |||
struct [[nodiscard]] event_t::timeout_awaiter : timeout_awaitor_impl<event_t::awaiter> | |||
struct [[nodiscard]] event_t::timeout_awaiter : timeout_awaitor_impl<awaiter> | |||
{ | |||
timeout_awaiter(clock_type::time_point tp, detail::event_v2_impl* evt) noexcept | |||
: timeout_awaitor_impl<event_t::awaiter>(tp, evt) | |||
{} | |||
using timeout_awaitor_impl<awaiter>::timeout_awaitor_impl; | |||
}; | |||
template<class _Rep, class _Period> | |||
@@ -331,11 +329,9 @@ RESUMEF_NS | |||
template<class _Iter> | |||
struct [[nodiscard]] event_t::timeout_any_awaiter : timeout_awaitor_impl<event_t::any_awaiter<_Iter>> | |||
struct [[nodiscard]] event_t::timeout_any_awaiter : timeout_awaitor_impl<any_awaiter<_Iter>> | |||
{ | |||
timeout_any_awaiter(clock_type::time_point tp, _Iter begin, _Iter end) noexcept | |||
: timeout_awaitor_impl<event_t::any_awaiter<_Iter>>(tp, begin, end) | |||
{} | |||
using timeout_awaitor_impl<any_awaiter<_Iter>>::timeout_awaitor_impl; | |||
}; | |||
template<class _Rep, class _Period, class _Iter COMMA_RESUMEF_ENABLE_IF_TYPENAME()> | |||
@@ -445,11 +441,9 @@ RESUMEF_NS | |||
template<class _Iter> | |||
struct [[nodiscard]] event_t::timeout_all_awaiter : timeout_awaitor_impl<event_t::all_awaiter<_Iter>> | |||
struct [[nodiscard]] event_t::timeout_all_awaiter : timeout_awaitor_impl<all_awaiter<_Iter>> | |||
{ | |||
timeout_all_awaiter(clock_type::time_point tp, _Iter begin, _Iter end) noexcept | |||
: timeout_awaitor_impl<event_t::all_awaiter<_Iter>>(tp, begin, end) | |||
{} | |||
using timeout_awaitor_impl<all_awaiter<_Iter>>::timeout_awaitor_impl; | |||
}; | |||
template<class _Rep, class _Period, class _Iter COMMA_RESUMEF_ENABLE_IF_TYPENAME()> |
@@ -4,7 +4,7 @@ RESUMEF_NS | |||
{ | |||
namespace detail | |||
{ | |||
void state_mutex_base_t::resume() | |||
void state_mutex_t::resume() | |||
{ | |||
coroutine_handle<> handler = _coro; | |||
if (handler) | |||
@@ -15,12 +15,12 @@ RESUMEF_NS | |||
} | |||
} | |||
bool state_mutex_base_t::has_handler() const noexcept | |||
bool state_mutex_t::has_handler() const noexcept | |||
{ | |||
return (bool)_coro; | |||
} | |||
state_base_t* state_mutex_base_t::get_parent() const noexcept | |||
state_base_t* state_mutex_t::get_parent() const noexcept | |||
{ | |||
return _root; | |||
} | |||
@@ -74,59 +74,18 @@ RESUMEF_NS | |||
return false; | |||
} | |||
void state_mutex_all_t::on_cancel() noexcept | |||
void state_mutex_t::add_timeout_timer(std::chrono::system_clock::time_point tp) | |||
{ | |||
intptr_t oldValue = _counter.load(std::memory_order_acquire); | |||
if (oldValue >= 0 && _counter.compare_exchange_strong(oldValue, -1, std::memory_order_acq_rel)) | |||
this->_thandler = this->_scheduler->timer()->add_handler(tp, | |||
[st = counted_ptr<state_mutex_t>{ this }](bool canceld) | |||
{ | |||
*_value = false; | |||
_thandler.stop(); | |||
this->_coro = nullptr; | |||
} | |||
if (!canceld) | |||
st->on_timeout(); | |||
}); | |||
} | |||
bool state_mutex_all_t::on_notify(event_v2_impl*) | |||
{ | |||
intptr_t oldValue = _counter.load(std::memory_order_acquire); | |||
if (oldValue <= 0) return false; | |||
oldValue = _counter.fetch_add(-1, std::memory_order_acq_rel); | |||
if (oldValue == 1) | |||
{ | |||
*_value = true; | |||
_thandler.stop(); | |||
assert(this->_scheduler != nullptr); | |||
if (this->_coro) | |||
this->_scheduler->add_generator(this); | |||
return true; | |||
} | |||
return oldValue >= 1; | |||
} | |||
bool state_mutex_all_t::on_timeout() | |||
{ | |||
intptr_t oldValue = _counter.load(std::memory_order_acquire); | |||
if (oldValue >= 0 && _counter.compare_exchange_strong(oldValue, -1, std::memory_order_acq_rel)) | |||
{ | |||
*_value = false; | |||
_thandler.reset(); | |||
assert(this->_scheduler != nullptr); | |||
if (this->_coro) | |||
this->_scheduler->add_generator(this); | |||
return true; | |||
} | |||
return false; | |||
} | |||
void mutex_v2_impl::lock_until_succeed(void* sch) | |||
{ | |||
assert(sch != nullptr); | |||
@@ -164,16 +123,16 @@ RESUMEF_NS | |||
{ | |||
assert(sch != nullptr); | |||
void* oldValue = _owner.load(std::memory_order_acquire); | |||
void* oldValue = _owner.load(std::memory_order_relaxed); | |||
if (oldValue == nullptr) | |||
{ | |||
_owner.store(sch, std::memory_order_release); | |||
_counter.fetch_add(1, std::memory_order_acq_rel); | |||
_owner.store(sch, std::memory_order_relaxed); | |||
_counter.fetch_add(1, std::memory_order_relaxed); | |||
return true; | |||
} | |||
if (oldValue == sch) | |||
{ | |||
_counter.fetch_add(1, std::memory_order_acq_rel); | |||
_counter.fetch_add(1, std::memory_order_relaxed); | |||
return true; | |||
} | |||
return false; | |||
@@ -185,12 +144,13 @@ RESUMEF_NS | |||
scoped_lock<lock_type> lock_(_lock); | |||
void* oldValue = _owner.load(std::memory_order_acquire); | |||
void* oldValue = _owner.load(std::memory_order_relaxed); | |||
if (oldValue == sch) | |||
{ | |||
if (_counter.fetch_sub(1, std::memory_order_acquire) == 1) | |||
if (_counter.fetch_sub(1, std::memory_order_relaxed) == 1) | |||
{ | |||
_owner.store(nullptr, std::memory_order_release); | |||
_owner.store(nullptr, std::memory_order_relaxed); | |||
while (!_wait_awakes.empty()) | |||
{ | |||
state_mutex_ptr state = _wait_awakes.front(); | |||
@@ -204,8 +164,8 @@ RESUMEF_NS | |||
break; | |||
//转移状态失败,恢复成空 | |||
_owner.store(nullptr, std::memory_order_release); | |||
_counter.fetch_sub(1, std::memory_order_acq_rel); | |||
_owner.store(nullptr, std::memory_order_relaxed); | |||
_counter.fetch_sub(1, std::memory_order_relaxed); | |||
} | |||
} | |||
@@ -4,16 +4,22 @@ RESUMEF_NS | |||
{ | |||
namespace detail | |||
{ | |||
struct state_mutex_base_t : public state_base_t | |||
struct state_mutex_t : public state_base_t | |||
{ | |||
state_mutex_t(mutex_v2_impl*& val) | |||
: _value(&val) | |||
{} | |||
virtual void resume() override; | |||
virtual bool has_handler() const noexcept override; | |||
virtual state_base_t* get_parent() const noexcept override; | |||
virtual void on_cancel() noexcept = 0; | |||
virtual bool on_notify(mutex_v2_impl* eptr) = 0; | |||
virtual bool on_timeout() = 0; | |||
void on_cancel() noexcept; | |||
bool on_notify(mutex_v2_impl* eptr); | |||
bool on_timeout(); | |||
void add_timeout_timer(std::chrono::system_clock::time_point tp); | |||
inline scheduler_t* get_scheduler() const noexcept | |||
{ | |||
return _scheduler; | |||
@@ -26,62 +32,22 @@ RESUMEF_NS | |||
this->_root = root; | |||
} | |||
inline void add_timeout_timer(std::chrono::system_clock::time_point tp) | |||
{ | |||
this->_thandler = this->_scheduler->timer()->add_handler(tp, | |||
[st = counted_ptr<state_mutex_base_t>{ this }](bool canceld) | |||
{ | |||
if (!canceld) | |||
st->on_timeout(); | |||
}); | |||
} | |||
timer_handler _thandler; | |||
protected: | |||
state_base_t* _root; | |||
}; | |||
struct state_mutex_t : public state_mutex_base_t | |||
{ | |||
state_mutex_t(mutex_v2_impl*& val) | |||
: _value(&val) | |||
{} | |||
virtual void on_cancel() noexcept override; | |||
virtual bool on_notify(mutex_v2_impl* eptr) override; | |||
virtual bool on_timeout() override; | |||
public: | |||
timer_handler _thandler; | |||
protected: | |||
std::atomic<mutex_v2_impl**> _value; | |||
}; | |||
struct state_mutex_all_t : public state_event_base_t | |||
{ | |||
state_mutex_all_t(intptr_t count, bool& val) | |||
: _counter(count) | |||
, _value(&val) | |||
{} | |||
virtual void on_cancel() noexcept override; | |||
virtual bool on_notify(event_v2_impl* eptr) override; | |||
virtual bool on_timeout() override; | |||
public: | |||
timer_handler _thandler; | |||
std::atomic<intptr_t> _counter; | |||
protected: | |||
bool* _value; | |||
}; | |||
struct mutex_v2_impl : public std::enable_shared_from_this<mutex_v2_impl> | |||
{ | |||
using clock_type = std::chrono::system_clock; | |||
mutex_v2_impl() {} | |||
inline void* owner() const noexcept | |||
inline void* owner() noexcept | |||
{ | |||
return _owner.load(std::memory_order_acquire); | |||
scoped_lock<lock_type> lock_(_lock); | |||
return _owner.load(std::memory_order_relaxed); | |||
} | |||
bool try_lock(void* sch); //内部加锁 | |||
@@ -171,7 +137,9 @@ RESUMEF_NS | |||
{ | |||
typedef std::shared_ptr<detail::mutex_v2_impl> mutex_impl_ptr; | |||
scoped_unlock_t() {} | |||
scoped_unlock_t() | |||
: _owner(nullptr) | |||
{} | |||
//此函数,应该在try_lock()获得锁后使用 | |||
//或者在协程里,由awaiter使用 | |||
@@ -405,12 +373,9 @@ RESUMEF_NS | |||
struct [[nodiscard]] mutex_t::timeout_awaiter : public event_t::timeout_awaitor_impl<awaiter> | |||
struct [[nodiscard]] mutex_t::timeout_awaiter : public event_t::timeout_awaitor_impl<lock_awaiter> | |||
{ | |||
timeout_awaiter(clock_type::time_point tp, detail::mutex_v2_impl * mtx) noexcept | |||
: event_t::timeout_awaitor_impl<mutex_t::awaiter>(tp, mtx) | |||
{} | |||
using event_t::timeout_awaitor_impl<lock_awaiter>::timeout_awaitor_impl; | |||
bool await_resume() noexcept | |||
{ | |||
detail::mutex_v2_impl* mtx = this->_mutex; |
@@ -2,7 +2,7 @@ | |||
RESUMEF_NS | |||
{ | |||
future_t<> sleep_until_(const std::chrono::system_clock::time_point& tp_, scheduler_t& scheduler_) | |||
future_t<> sleep_until_(std::chrono::system_clock::time_point tp_, scheduler_t& scheduler_) | |||
{ | |||
awaitable_t<> awaitable; | |||
@@ -8,32 +8,32 @@ RESUMEF_NS | |||
{ | |||
struct scheduler_t; | |||
future_t<> sleep_until_(const std::chrono::system_clock::time_point& tp_, scheduler_t& scheduler_); | |||
future_t<> sleep_until_(std::chrono::system_clock::time_point tp_, scheduler_t& scheduler_); | |||
inline future_t<> sleep_for_(const std::chrono::system_clock::duration& dt_, scheduler_t& scheduler_) | |||
inline future_t<> sleep_for_(std::chrono::system_clock::duration dt_, scheduler_t& scheduler_) | |||
{ | |||
return sleep_until_(std::chrono::system_clock::now() + dt_, scheduler_); | |||
} | |||
template<class _Rep, class _Period> | |||
inline future_t<> sleep_for(const std::chrono::duration<_Rep, _Period>& dt_, scheduler_t& scheduler_) | |||
inline future_t<> sleep_for(std::chrono::duration<_Rep, _Period> dt_, scheduler_t& scheduler_) | |||
{ | |||
return sleep_for_(std::chrono::duration_cast<std::chrono::system_clock::duration>(dt_), scheduler_); | |||
} | |||
template<class _Clock, class _Duration = typename _Clock::duration> | |||
inline future_t<> sleep_until(const std::chrono::time_point<_Clock, _Duration>& tp_, scheduler_t& scheduler_) | |||
inline future_t<> sleep_until(std::chrono::time_point<_Clock, _Duration> tp_, scheduler_t& scheduler_) | |||
{ | |||
return sleep_until_(std::chrono::time_point_cast<std::chrono::system_clock::duration>(tp_), scheduler_); | |||
} | |||
template<class _Rep, class _Period> | |||
inline future_t<> sleep_for(const std::chrono::duration<_Rep, _Period>& dt_) | |||
inline future_t<> sleep_for(std::chrono::duration<_Rep, _Period> dt_) | |||
{ | |||
co_await sleep_for_(std::chrono::duration_cast<std::chrono::system_clock::duration>(dt_), *current_scheduler()); | |||
} | |||
template<class _Clock, class _Duration> | |||
inline future_t<> sleep_until(const std::chrono::time_point<_Clock, _Duration>& tp_) | |||
inline future_t<> sleep_until(std::chrono::time_point<_Clock, _Duration> tp_) | |||
{ | |||
co_await sleep_until_(std::chrono::time_point_cast<std::chrono::system_clock::duration>(tp_), *current_scheduler()); | |||
} |
@@ -323,7 +323,9 @@ inline namespace when_v2 | |||
auto when_any(scheduler_t& sch, _Awaitable&&... args) | |||
-> detail::when_future_t<when_any_pair> | |||
{ | |||
#pragma warning(disable : 6326) //warning C6326: Potential comparison of a constant with another constant. | |||
detail::when_future_t<when_any_pair> awaitor{ sizeof...(_Awaitable) > 0 ? 1 : 0 }; | |||
#pragma warning(default : 6326) | |||
awaitor._values->first = -1; | |||
detail::when_any_one__(sch, awaitor._state.get(), awaitor._values, 0, std::forward<_Awaitable>(args)...); | |||
@@ -143,7 +143,7 @@ static void resumable_mutex_async() | |||
static future_t<> resumable_mutex_range_push(size_t idx, mutex_t a, mutex_t b, mutex_t c) | |||
{ | |||
for (int i = 0; i < 1000; ++i) | |||
for (int i = 0; i < 100000; ++i) | |||
{ | |||
scoped_unlock_t __lockers = co_await mutex_t::lock(a, b, c); | |||
assert(a.is_locked()); | |||
@@ -159,7 +159,7 @@ static future_t<> resumable_mutex_range_push(size_t idx, mutex_t a, mutex_t b, m | |||
static future_t<> resumable_mutex_range_pop(size_t idx, mutex_t a, mutex_t b, mutex_t c) | |||
{ | |||
for (int i = 0; i < 1000; ++i) | |||
for (int i = 0; i < 100000; ++i) | |||
{ | |||
scoped_unlock_t __lockers = co_await mutex_t::lock(a, b, c); | |||
assert(a.is_locked()); |
@@ -43,8 +43,8 @@ int main(int argc, const char* argv[]) | |||
//test_ring_queue<resumef::ring_queue_spinlock<int, false, uint32_t>>(); | |||
//test_ring_queue<resumef::ring_queue_lockfree<int, uint64_t>>(); | |||
resumable_main_mutex(); | |||
return 0; | |||
//resumable_main_mutex(); | |||
//return 0; | |||
//if (argc > 1) | |||
// resumable_main_benchmark_asio_client(atoi(argv[1])); |
@@ -46,7 +46,7 @@ | |||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration"> | |||
<ConfigurationType>Application</ConfigurationType> | |||
<UseDebugLibraries>false</UseDebugLibraries> | |||
<PlatformToolset>v142</PlatformToolset> | |||
<PlatformToolset>ClangCL</PlatformToolset> | |||
<WholeProgramOptimization>true</WholeProgramOptimization> | |||
<CharacterSet>NotSet</CharacterSet> | |||
</PropertyGroup> | |||
@@ -77,7 +77,6 @@ | |||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" /> | |||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> | |||
<CodeAnalysisRuleSet>NativeRecommendedRules.ruleset</CodeAnalysisRuleSet> | |||
<EnableClangTidyCodeAnalysis>true</EnableClangTidyCodeAnalysis> | |||
</PropertyGroup> | |||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> | |||
<ClCompile> | |||
@@ -158,7 +157,7 @@ | |||
<MultiProcessorCompilation>true</MultiProcessorCompilation> | |||
<SDLCheck> | |||
</SDLCheck> | |||
<EnablePREfast>false</EnablePREfast> | |||
<EnablePREfast>true</EnablePREfast> | |||
<InlineFunctionExpansion>AnySuitable</InlineFunctionExpansion> | |||
<OmitFramePointers>true</OmitFramePointers> | |||
<EnableFiberSafeOptimizations>true</EnableFiberSafeOptimizations> |