mirror of
https://github.com/tearshark/librf.git
synced 2024-10-01 15:57:07 +08:00
完善mutex_t的接口
This commit is contained in:
parent
e22ae5dc12
commit
9d94bfa30c
@ -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;
|
||||
};
|
||||
}
|
||||
|
@ -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,9 +292,7 @@ RESUMEF_NS
|
||||
return { _mutex.get() };
|
||||
}
|
||||
|
||||
inline auto mutex_t::lock(std::defer_lock_t) const noexcept
|
||||
{
|
||||
struct discard_unlock_awaiter : lock_awaiter
|
||||
struct mutex_t::manual_awaiter : public lock_awaiter
|
||||
{
|
||||
using lock_awaiter::lock_awaiter;
|
||||
void await_resume() noexcept
|
||||
@ -323,7 +301,9 @@ RESUMEF_NS
|
||||
}
|
||||
};
|
||||
|
||||
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,20 +509,32 @@ 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)
|
||||
{
|
||||
@ -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>
|
||||
|
@ -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();
|
||||
}
|
||||
|
@ -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>
|
||||
|
Loading…
Reference in New Issue
Block a user