From 9d94bfa30c996bff5f79c9903d2c25bcc271c8d6 Mon Sep 17 00:00:00 2001 From: tearshark Date: Sun, 22 Mar 2020 02:05:14 +0800 Subject: [PATCH] =?UTF-8?q?=E5=AE=8C=E5=96=84mutex=5Ft=E7=9A=84=E6=8E=A5?= =?UTF-8?q?=E5=8F=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- librf/src/mutex_v2.h | 40 ++++++----- librf/src/mutex_v2.inl | 123 ++++++++++++++++------------------ tutorial/test_async_mutex.cpp | 24 +++---- vs_proj/librf.vcxproj | 4 +- 4 files changed, 94 insertions(+), 97 deletions(-) diff --git a/librf/src/mutex_v2.h b/librf/src/mutex_v2.h index 1adf1dc..f566db8 100644 --- a/librf/src/mutex_v2.h +++ b/librf/src/mutex_v2.h @@ -9,24 +9,24 @@ RESUMEF_NS inline namespace mutex_v2 { - struct [[nodiscard]] scoped_lock_mutex_t; - struct [[nodiscard]] scoped_unlock_range_t; + struct adopt_manual_unlock_t{}; + constexpr adopt_manual_unlock_t adopt_manual_unlock; + + template + struct [[nodiscard]] scoped_unlock_t; //支持递归的锁 struct mutex_t { - typedef std::shared_ptr mutex_impl_ptr; - typedef std::chrono::system_clock clock_type; - - mutex_t(); - mutex_t(std::adopt_lock_t) noexcept; - ~mutex_t() noexcept; + bool is_locked() const; struct lock_awaiter; struct [[nodiscard]] awaiter; + struct [[nodiscard]] manual_awaiter; - awaiter/*scoped_lock_mutex_t*/ lock() const noexcept; - awaiter/*scoped_lock_mutex_t*/ operator co_await() const noexcept; + awaiter/*scoped_unlock_t*/ lock() const noexcept; + awaiter/*scoped_unlock_t*/ operator co_await() const noexcept; + manual_awaiter/*void*/ lock(adopt_manual_unlock_t) const noexcept; struct [[nodiscard]] try_awaiter; //co_await try_lock()获得是否加锁成功。此操作无论成功与否都会立即返回。 @@ -55,34 +55,38 @@ RESUMEF_NS void unlock(void* unique_address) const; - - struct _MutexAwaitAssembleT; - template, mutex_t>...>> > - static future_t lock(_Mtxs&... mtxs); + static future_t> lock(_Mtxs&... mtxs); template, mutex_t>...>> > - static scoped_unlock_range_t lock(void* unique_address, _Mtxs&... mtxs); + static scoped_unlock_t<_Mtxs...> lock(void* unique_address, _Mtxs&... mtxs); template, mutex_t>...>> > static void unlock(void* unique_address, _Mtxs&... mtxs); - bool is_locked() const; - auto lock(std::defer_lock_t) const noexcept; + mutex_t(); + mutex_t(std::adopt_lock_t) noexcept; + ~mutex_t() noexcept; mutex_t(const mutex_t&) = default; mutex_t(mutex_t&&) = default; mutex_t& operator = (const mutex_t&) = default; mutex_t& operator = (mutex_t&&) = default; + + typedef std::shared_ptr mutex_impl_ptr; + typedef std::chrono::system_clock clock_type; private: - friend struct scoped_lock_mutex_t; + struct _MutexAwaitAssembleT; + + template friend struct scoped_unlock_t; + mutex_impl_ptr _mutex; }; } diff --git a/librf/src/mutex_v2.inl b/librf/src/mutex_v2.inl index f548592..3be62de 100644 --- a/librf/src/mutex_v2.inl +++ b/librf/src/mutex_v2.inl @@ -166,21 +166,22 @@ RESUMEF_NS inline namespace mutex_v2 { - struct [[nodiscard]] scoped_lock_mutex_t + template<> + struct [[nodiscard]] scoped_unlock_t { typedef std::shared_ptr mutex_impl_ptr; - scoped_lock_mutex_t() {} + scoped_unlock_t() {} //此函数,应该在try_lock()获得锁后使用 //或者在协程里,由awaiter使用 - scoped_lock_mutex_t(std::adopt_lock_t, mutex_impl_ptr mtx, void* sch) + scoped_unlock_t(std::adopt_lock_t, void* sch, mutex_impl_ptr mtx) : _mutex(std::move(mtx)) , _owner(sch) {} //此函数,适合在非协程里使用 - scoped_lock_mutex_t(mutex_impl_ptr mtx, void* sch) + scoped_unlock_t(void* sch, mutex_impl_ptr mtx) : _mutex(std::move(mtx)) , _owner(sch) { @@ -189,14 +190,14 @@ RESUMEF_NS } - scoped_lock_mutex_t(std::adopt_lock_t, const mutex_t& mtx, void* sch) - : scoped_lock_mutex_t(std::adopt_lock, mtx._mutex, sch) + scoped_unlock_t(std::adopt_lock_t, void* sch, const mutex_t& mtx) + : scoped_unlock_t(std::adopt_lock, sch, mtx._mutex) {} - scoped_lock_mutex_t(const mutex_t& mtx, void* sch) - : scoped_lock_mutex_t(mtx._mutex, sch) + scoped_unlock_t(void* sch, const mutex_t& mtx) + : scoped_unlock_t(sch, mtx._mutex) {} - ~scoped_lock_mutex_t() + ~scoped_unlock_t() { if (_mutex != nullptr) _mutex->unlock(_owner); @@ -211,31 +212,10 @@ RESUMEF_NS } } - inline bool is_locked() const noexcept - { - return _mutex != nullptr && _mutex->owner() == _owner; - } - - scoped_lock_mutex_t(const scoped_lock_mutex_t&) = delete; - scoped_lock_mutex_t& operator = (const scoped_lock_mutex_t&) = delete; - - scoped_lock_mutex_t(scoped_lock_mutex_t&& _Right) noexcept - : _mutex(std::move(_Right._mutex)) - , _owner(_Right._owner) - { - assert(_Right._mutex == nullptr); - } - - scoped_lock_mutex_t& operator = (scoped_lock_mutex_t&& _Right) noexcept - { - if (this != &_Right) - { - _mutex = std::move(_Right._mutex); - assert(_Right._mutex == nullptr); - _owner = _Right._owner; - } - return *this; - } + scoped_unlock_t(const scoped_unlock_t&) = delete; + scoped_unlock_t& operator = (const scoped_unlock_t&) = delete; + scoped_unlock_t(scoped_unlock_t&& _Right) = default; + scoped_unlock_t& operator = (scoped_unlock_t&& _Right) = default; private: mutex_impl_ptr _mutex; void* _owner; @@ -293,12 +273,12 @@ RESUMEF_NS { using lock_awaiter::lock_awaiter; - scoped_lock_mutex_t await_resume() noexcept + scoped_unlock_t await_resume() noexcept { mutex_impl_ptr mtx = _mutex ? _mutex->shared_from_this() : nullptr; _mutex = nullptr; - return { std::adopt_lock, mtx, _root }; + return { std::adopt_lock, _root, mtx }; } }; @@ -312,18 +292,18 @@ RESUMEF_NS return { _mutex.get() }; } - inline auto mutex_t::lock(std::defer_lock_t) const noexcept + struct mutex_t::manual_awaiter : public lock_awaiter { - struct discard_unlock_awaiter : lock_awaiter + using lock_awaiter::lock_awaiter; + void await_resume() noexcept { - using lock_awaiter::lock_awaiter; - void await_resume() noexcept - { - _mutex = nullptr; - } - }; + _mutex = nullptr; + } + }; - return discard_unlock_awaiter{ _mutex.get() }; + inline mutex_t::manual_awaiter mutex_t::lock(adopt_manual_unlock_t) const noexcept + { + return { _mutex.get() }; } inline bool mutex_t::is_locked() const @@ -485,6 +465,8 @@ RESUMEF_NS _mutex->unlock(unique_address); } + + struct mutex_t::_MutexAwaitAssembleT { public: @@ -506,7 +488,7 @@ RESUMEF_NS } auto _Lock_ref(mutex_t& _LkN) const { - return _LkN.lock(std::defer_lock); + return _LkN.lock(adopt_manual_unlock); } auto _Try_lock_ref(mutex_t& _LkN) const { @@ -527,24 +509,36 @@ RESUMEF_NS future_t<> _ReturnValue() const; template future_t _ReturnValue(U v) const; + + _MutexAwaitAssembleT(const _MutexAwaitAssembleT&) = default; + _MutexAwaitAssembleT& operator = (const _MutexAwaitAssembleT&) = default; + _MutexAwaitAssembleT(_MutexAwaitAssembleT&& _Right) = default; + _MutexAwaitAssembleT& operator = (_MutexAwaitAssembleT&& _Right) = default; }; - struct [[nodiscard]] scoped_unlock_range_t + template + struct [[nodiscard]] scoped_unlock_t { mutex_t::_MutexAwaitAssembleT _MAA; //此函数,应该在try_lock()获得锁后使用 //或者在协程里,由awaiter使用 - template - scoped_unlock_range_t(void* unique_address, _Mtxs&&... mtxs) - : _MAA(unique_address, std::forward<_Mtxs>(mtxs)...) + template + scoped_unlock_t(void* sch, U&&... mtxs) + : _MAA(sch, std::forward(mtxs)...) + { + detail::scoped_lock_range_lock_impl::_Lock_range(_MAA); + } + template + scoped_unlock_t(std::adopt_lock_t, void* sch, U&&... mtxs) + : _MAA(sch, std::forward(mtxs)...) {} - ~scoped_unlock_range_t() + ~scoped_unlock_t() { if (_MAA._owner != nullptr) { - for(mutex_t& mtx : _MAA._mutex) + for (mutex_t& mtx : _MAA._mutex) mtx.unlock(_MAA._owner); } } @@ -559,29 +553,28 @@ RESUMEF_NS } } - scoped_unlock_range_t(const scoped_unlock_range_t&) = delete; - scoped_unlock_range_t& operator = (const scoped_unlock_range_t&) = delete; - scoped_unlock_range_t(scoped_unlock_range_t&& _Right) noexcept = default; - scoped_unlock_range_t& operator = (scoped_unlock_range_t&& _Right) noexcept = default; + scoped_unlock_t(const scoped_unlock_t&) = delete; + scoped_unlock_t& operator = (const scoped_unlock_t&) = delete; + scoped_unlock_t(scoped_unlock_t&& _Right) = default; + scoped_unlock_t& operator = (scoped_unlock_t&& _Right) = default; }; + template + scoped_unlock_t()->scoped_unlock_t&&>; + template - inline future_t mutex_t::lock(_Mtxs&... mtxs) + inline future_t> mutex_t::lock(_Mtxs&... mtxs) { - scoped_unlock_range_t unlock_guard{ root_state(), mtxs... }; + scoped_unlock_t<_Mtxs...> unlock_guard{ std::adopt_lock, root_state(), mtxs... }; co_await detail::mutex_lock_await_lock_impl::_Lock_range(unlock_guard._MAA); - co_return unlock_guard; + co_return std::move(unlock_guard); } template - inline scoped_unlock_range_t mutex_t::lock(void* unique_address, _Mtxs&... mtxs) + inline scoped_unlock_t<_Mtxs...> mutex_t::lock(void* unique_address, _Mtxs&... mtxs) { assert(unique_address != nullptr); - - detail::_MutexAddressAssembleT MAA(unique_address, mtxs...); - detail::scoped_lock_range_lock_impl::_Lock_range(MAA); - - return scoped_unlock_range_t{ std::move(MAA._Lks), unique_address }; + return { unique_address, mtxs... }; } template diff --git a/tutorial/test_async_mutex.cpp b/tutorial/test_async_mutex.cpp index 83a56b4..bc30fe2 100644 --- a/tutorial/test_async_mutex.cpp +++ b/tutorial/test_async_mutex.cpp @@ -23,14 +23,14 @@ static future_t<> test_mutex_pop(size_t idx) for (size_t i = 0; i < N / 2; ++i) { { - auto _locker = co_await g_lock.lock(); //_locker析构后,会调用对应的unlock()函数。 + scoped_unlock_t _locker = co_await g_lock.lock(); //_locker析构后,会调用对应的unlock()函数。 --g_counter; std::cout << "pop :" << g_counter << " on " << idx << std::endl; co_await 50ms; - auto _locker_2 = co_await g_lock; + scoped_unlock_t _locker_2 = co_await g_lock; --g_counter; std::cout << "pop :" << g_counter << " on " << idx << std::endl; @@ -47,7 +47,7 @@ static future_t<> test_mutex_push(size_t idx) for (size_t i = 0; i < N; ++i) { { - auto _locker = co_await g_lock.lock(); + scoped_unlock_t _locker = co_await g_lock.lock(); ++g_counter; std::cout << "push:" << g_counter << " on " << idx << std::endl; @@ -105,7 +105,7 @@ static std::thread test_mutex_async_push(size_t idx) { if (g_lock.try_lock_for(500ms, &provide_unique_address)) { - //scoped_lock_mutex_t _locker(std::adopt_lock, g_lock, &provide_unique_address); + //scoped_unlock_t _locker(std::adopt_lock, g_lock, &provide_unique_address); ++g_counter; std::cout << "push:" << g_counter << " on " << idx << std::endl; @@ -143,9 +143,9 @@ 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 < 1000001; ++i) + for (int i = 0; i < 1000; ++i) { - auto __lockers = co_await mutex_t::lock(a, b, c); + scoped_unlock_t __lockers = co_await mutex_t::lock(a, b, c); assert(a.is_locked()); assert(b.is_locked()); assert(c.is_locked()); @@ -159,9 +159,9 @@ 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 < 1000000; ++i) + for (int i = 0; i < 1000; ++i) { - auto __lockers = co_await mutex_t::lock(a, b, c); + scoped_unlock_t __lockers = co_await mutex_t::lock(a, b, c); assert(a.is_locked()); assert(b.is_locked()); assert(c.is_locked()); @@ -199,11 +199,11 @@ static void resumable_mutex_lock_range() void resumable_main_mutex() { - //resumable_mutex_synch(); - //std::cout << std::endl; + resumable_mutex_synch(); + std::cout << std::endl; - //resumable_mutex_async(); - //std::cout << std::endl; + resumable_mutex_async(); + std::cout << std::endl; resumable_mutex_lock_range(); } diff --git a/vs_proj/librf.vcxproj b/vs_proj/librf.vcxproj index d41ca2a..cd918c8 100644 --- a/vs_proj/librf.vcxproj +++ b/vs_proj/librf.vcxproj @@ -40,13 +40,13 @@ Application - ClangCL + v142 true Application false - ClangCL + v142 true NotSet