1
0
mirror of https://github.com/tearshark/librf.git synced 2024-10-01 15:57:07 +08:00

完善mutex_t的接口

This commit is contained in:
tearshark 2020-03-22 02:05:14 +08:00
parent e22ae5dc12
commit 9d94bfa30c
4 changed files with 94 additions and 97 deletions

View File

@ -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<class... _Mtxs>
struct [[nodiscard]] scoped_unlock_t;
//支持递归的锁
struct mutex_t
{
typedef std::shared_ptr<detail::mutex_v2_impl> 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<class... _Mtxs
, typename = std::enable_if_t<std::conjunction_v<std::is_same<std::remove_cvref_t<_Mtxs>, mutex_t>...>>
>
static future_t<scoped_unlock_range_t> lock(_Mtxs&... mtxs);
static future_t<scoped_unlock_t<_Mtxs...>> lock(_Mtxs&... mtxs);
template<class... _Mtxs
, typename = std::enable_if_t<std::conjunction_v<std::is_same<std::remove_cvref_t<_Mtxs>, 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<class... _Mtxs
, typename = std::enable_if_t<std::conjunction_v<std::is_same<std::remove_cvref_t<_Mtxs>, 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<detail::mutex_v2_impl> mutex_impl_ptr;
typedef std::chrono::system_clock clock_type;
private:
friend struct scoped_lock_mutex_t;
struct _MutexAwaitAssembleT;
template<class... _Mtxs> friend struct scoped_unlock_t;
mutex_impl_ptr _mutex;
};
}

View File

@ -166,21 +166,22 @@ RESUMEF_NS
inline namespace mutex_v2
{
struct [[nodiscard]] scoped_lock_mutex_t
template<>
struct [[nodiscard]] scoped_unlock_t<mutex_t>
{
typedef std::shared_ptr<detail::mutex_v2_impl> 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<mutex_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<class U>
future_t<U> _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<class... _Mtxs>
struct [[nodiscard]] scoped_unlock_t
{
mutex_t::_MutexAwaitAssembleT _MAA;
//此函数应该在try_lock()获得锁后使用
//或者在协程里由awaiter使用
template<class... _Mtxs>
scoped_unlock_range_t(void* unique_address, _Mtxs&&... mtxs)
: _MAA(unique_address, std::forward<_Mtxs>(mtxs)...)
template<class... U>
scoped_unlock_t(void* sch, U&&... mtxs)
: _MAA(sch, std::forward<U>(mtxs)...)
{
detail::scoped_lock_range_lock_impl::_Lock_range(_MAA);
}
template<class... U>
scoped_unlock_t(std::adopt_lock_t, void* sch, U&&... mtxs)
: _MAA(sch, std::forward<U>(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<class... _Mtxs>
scoped_unlock_t()->scoped_unlock_t<scoped_unlock_t<_Mtxs...>&&>;
template<class... _Mtxs, typename>
inline future_t<scoped_unlock_range_t> mutex_t::lock(_Mtxs&... mtxs)
inline future_t<scoped_unlock_t<_Mtxs...>> 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<class... _Mtxs, typename>
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<class... _Mtxs, typename>

View File

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

View File

@ -40,13 +40,13 @@
</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">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>ClangCL</PlatformToolset>
<PlatformToolset>v142</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>NotSet</CharacterSet>
</PropertyGroup>