Browse Source

mutex增加协程中手工解锁的功能

tags/v2.9.7
tearshark 4 years ago
parent
commit
34b2a4cad2

+ 3
- 0
librf/src/def.h View File

@@ -38,6 +38,9 @@ RESUMEF_NS
template<typename _PromiseT = void>
using coroutine_handle = std::experimental::coroutine_handle<_PromiseT>;
using suspend_if = std::experimental::suspend_if;
using suspend_always = std::experimental::suspend_always;
using suspend_never = std::experimental::suspend_never;
struct state_base_t;

+ 3
- 3
librf/src/generator.h View File

@@ -121,17 +121,17 @@ RESUMEF_NS
return generator_t{ *this };
}
std::experimental::suspend_always initial_suspend() noexcept
suspend_always initial_suspend() noexcept
{
return {};
}
std::experimental::suspend_always final_suspend() noexcept
suspend_always final_suspend() noexcept
{
return {};
}
std::experimental::suspend_always yield_value(_Ty const& _Value) noexcept
suspend_always yield_value(_Ty const& _Value) noexcept
{
_CurrentValue = std::addressof(_Value);
return {};

+ 18
- 0
librf/src/mutex_v2.h View File

@@ -128,6 +128,24 @@ RESUMEF_NS
>
static future_t<scoped_unlock_t<_Mtxs...>> lock(_Mtxs&... mtxs);

/**
* @brief 在协程中,无死锁的批量加锁。不会阻塞当前线程。直到获得所有锁之前,会阻塞当前协程。
* @return [co_await] void
*/
template<class... _Mtxs
, typename = std::enable_if_t<std::conjunction_v<std::is_same<remove_cvref_t<_Mtxs>, mutex_t>...>>
>
static future_t<> lock(adopt_manual_unlock_t, _Mtxs&... mtxs);

/**
* @brief 在协程中解锁。如果可能,使用unlock(root_state(), mtxs...)来替代。
* @return [co_await] void
*/
template<class... _Mtxs
, typename = std::enable_if_t<std::conjunction_v<std::is_same<remove_cvref_t<_Mtxs>, mutex_t>...>>
>
static future_t<> unlock(_Mtxs&... mtxs);


/**
* @brief 在非协程中,无死锁的批量加锁。会阻塞当前线程,直到获得所有锁为止。

+ 29
- 7
librf/src/mutex_v2.inl View File

@@ -76,20 +76,20 @@ RESUMEF_NS
private:
void* _Address;
public:
std::vector<mutex_t> _Lks;
std::vector<mutex_t> _mutex;

template<class... _Mtxs>
_MutexAddressAssembleT(void* unique_address, _Mtxs&... mtxs)
: _Address(unique_address)
, _Lks({ mtxs... })
, _mutex({ mtxs... })
{}
size_t size() const
{
return _Lks.size();
return _mutex.size();
}
mutex_t& operator[](int _Idx)
{
return _Lks[_Idx];
return _mutex[_Idx];
}
void _Lock_ref(mutex_t& _LkN) const
{
@@ -540,18 +540,40 @@ RESUMEF_NS
co_return std::move(unlock_guard);
}

template<class... _Mtxs, typename>
inline future_t<> mutex_t::lock(adopt_manual_unlock_t, _Mtxs&... mtxs)
{
mutex_t::_MutexAwaitAssembleT _MAA{ root_state(), mtxs... };
co_await detail::mutex_lock_await_lock_impl::_Lock_range(_MAA);
}

template<class... _Mtxs, typename>
inline future_t<> mutex_t::unlock(_Mtxs&... mtxs)
{
void* unique_address = root_state();

(mtxs.unlock(unique_address), ...);
}

template<class... _Mtxs, typename>
inline scoped_unlock_t<_Mtxs...> mutex_t::lock(void* unique_address, _Mtxs&... mtxs)
{
assert(unique_address != nullptr);
return { unique_address, mtxs... };

detail::_MutexAddressAssembleT _MAA{ unique_address, mtxs... };
detail::scoped_lock_range_lock_impl::_Lock_range(_MAA);
scoped_unlock_t<_Mtxs...> su{ std::adopt_lock, unique_address };
su._MAA._mutex = std::move(_MAA._mutex);
return su;
}

template<class... _Mtxs, typename>
inline void mutex_t::lock(adopt_manual_unlock_t, void* unique_address, _Mtxs&... mtxs)
{
assert(unique_address != nullptr);
mutex_t::_MutexAwaitAssembleT _MAA{ unique_address, mtxs... };

detail::_MutexAddressAssembleT _MAA{ unique_address, mtxs... };
detail::scoped_lock_range_lock_impl::_Lock_range(_MAA);
}

@@ -560,7 +582,7 @@ RESUMEF_NS
{
assert(unique_address != nullptr);

(..., mtxs.unlock(unique_address));
(mtxs.unlock(unique_address), ...);
}
}
}

+ 3
- 3
librf/src/promise.h View File

@@ -53,7 +53,7 @@ RESUMEF_NS
template<class U>
void return_value(U&& val); //co_return val
template<class U>
std::experimental::suspend_always yield_value(U&& val);
suspend_always yield_value(U&& val);
};

template<class _Ty>
@@ -63,7 +63,7 @@ RESUMEF_NS
using promise_impl_t<_Ty&>::get_return_object;

void return_value(_Ty& val); //co_return val
std::experimental::suspend_always yield_value(_Ty& val);
suspend_always yield_value(_Ty& val);
};

template<>
@@ -72,7 +72,7 @@ RESUMEF_NS
using promise_impl_t<void>::get_return_object;

void return_void(); //co_return;
std::experimental::suspend_always yield_value();
suspend_always yield_value();
};

}

+ 3
- 3
librf/src/promise.inl View File

@@ -177,7 +177,7 @@ RESUMEF_NS

template<class _Ty>
template<class U>
inline std::experimental::suspend_always promise_t<_Ty>::yield_value(U&& val)
inline suspend_always promise_t<_Ty>::yield_value(U&& val)
{
this->get_state()->promise_yield_value(this, std::forward<U>(val));
return {};
@@ -190,7 +190,7 @@ RESUMEF_NS
}

template<class _Ty>
inline std::experimental::suspend_always promise_t<_Ty&>::yield_value(_Ty& val)
inline suspend_always promise_t<_Ty&>::yield_value(_Ty& val)
{
this->get_state()->promise_yield_value(this, val);
return {};
@@ -201,7 +201,7 @@ RESUMEF_NS
this->get_state()->set_value();
}

inline std::experimental::suspend_always promise_t<void>::yield_value()
inline suspend_always promise_t<void>::yield_value()
{
this->get_state()->promise_yield_value(this);
return {};

+ 4
- 3
tutorial/test_async_mutex.cpp View File

@@ -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 < 100000; ++i)
for (int i = 0; i < 10000; ++i)
{
scoped_unlock_t __lockers = co_await mutex_t::lock(a, b, c);
assert(a.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 < 100000; ++i)
for (int i = 0; i < 10000; ++i)
{
scoped_unlock_t __lockers = co_await mutex_t::lock(a, b, c);
co_await mutex_t::lock(adopt_manual_unlock, a, b, c);
assert(a.is_locked());
assert(b.is_locked());
assert(c.is_locked());
@@ -170,6 +170,7 @@ static future_t<> resumable_mutex_range_pop(size_t idx, mutex_t a, mutex_t b, mu
//std::cout << "pop :" << g_counter << " on " << idx << std::endl;
//co_await 5ms;
co_await mutex_t::unlock(a, b, c);
}
}

+ 2
- 2
vs_proj/librf.cpp View File

@@ -45,8 +45,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]));

Loading…
Cancel
Save