Browse Source

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

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

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

template<typename _PromiseT = void> template<typename _PromiseT = void>
using coroutine_handle = std::experimental::coroutine_handle<_PromiseT>; 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; struct state_base_t;

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

return generator_t{ *this }; return generator_t{ *this };
} }
std::experimental::suspend_always initial_suspend() noexcept
suspend_always initial_suspend() noexcept
{ {
return {}; return {};
} }
std::experimental::suspend_always final_suspend() noexcept
suspend_always final_suspend() noexcept
{ {
return {}; return {};
} }
std::experimental::suspend_always yield_value(_Ty const& _Value) noexcept
suspend_always yield_value(_Ty const& _Value) noexcept
{ {
_CurrentValue = std::addressof(_Value); _CurrentValue = std::addressof(_Value);
return {}; return {};

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

> >
static future_t<scoped_unlock_t<_Mtxs...>> lock(_Mtxs&... mtxs); 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 在非协程中,无死锁的批量加锁。会阻塞当前线程,直到获得所有锁为止。 * @brief 在非协程中,无死锁的批量加锁。会阻塞当前线程,直到获得所有锁为止。

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

private: private:
void* _Address; void* _Address;
public: public:
std::vector<mutex_t> _Lks;
std::vector<mutex_t> _mutex;


template<class... _Mtxs> template<class... _Mtxs>
_MutexAddressAssembleT(void* unique_address, _Mtxs&... mtxs) _MutexAddressAssembleT(void* unique_address, _Mtxs&... mtxs)
: _Address(unique_address) : _Address(unique_address)
, _Lks({ mtxs... })
, _mutex({ mtxs... })
{} {}
size_t size() const size_t size() const
{ {
return _Lks.size();
return _mutex.size();
} }
mutex_t& operator[](int _Idx) mutex_t& operator[](int _Idx)
{ {
return _Lks[_Idx];
return _mutex[_Idx];
} }
void _Lock_ref(mutex_t& _LkN) const void _Lock_ref(mutex_t& _LkN) const
{ {
co_return std::move(unlock_guard); 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> template<class... _Mtxs, typename>
inline scoped_unlock_t<_Mtxs...> 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); 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> template<class... _Mtxs, typename>
inline void mutex_t::lock(adopt_manual_unlock_t, void* unique_address, _Mtxs&... mtxs) inline void mutex_t::lock(adopt_manual_unlock_t, void* unique_address, _Mtxs&... mtxs)
{ {
assert(unique_address != nullptr); 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); detail::scoped_lock_range_lock_impl::_Lock_range(_MAA);
} }


{ {
assert(unique_address != nullptr); assert(unique_address != nullptr);


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

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

template<class U> template<class U>
void return_value(U&& val); //co_return val void return_value(U&& val); //co_return val
template<class U> template<class U>
std::experimental::suspend_always yield_value(U&& val);
suspend_always yield_value(U&& val);
}; };


template<class _Ty> template<class _Ty>
using promise_impl_t<_Ty&>::get_return_object; using promise_impl_t<_Ty&>::get_return_object;


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


template<> template<>
using promise_impl_t<void>::get_return_object; using promise_impl_t<void>::get_return_object;


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


} }

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



template<class _Ty> template<class _Ty>
template<class U> 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)); this->get_state()->promise_yield_value(this, std::forward<U>(val));
return {}; return {};
} }


template<class _Ty> 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); this->get_state()->promise_yield_value(this, val);
return {}; return {};
this->get_state()->set_value(); 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); this->get_state()->promise_yield_value(this);
return {}; return {};

+ 4
- 3
tutorial/test_async_mutex.cpp View File

static future_t<> resumable_mutex_range_push(size_t idx, mutex_t a, mutex_t b, mutex_t c) 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); scoped_unlock_t __lockers = co_await mutex_t::lock(a, b, c);
assert(a.is_locked()); assert(a.is_locked());
static future_t<> resumable_mutex_range_pop(size_t idx, mutex_t a, mutex_t b, mutex_t c) 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(a.is_locked());
assert(b.is_locked()); assert(b.is_locked());
assert(c.is_locked()); assert(c.is_locked());
//std::cout << "pop :" << g_counter << " on " << idx << std::endl; //std::cout << "pop :" << g_counter << " on " << idx << std::endl;
//co_await 5ms; //co_await 5ms;
co_await mutex_t::unlock(a, b, c);
} }
} }

+ 2
- 2
vs_proj/librf.cpp View File

//test_ring_queue<resumef::ring_queue_spinlock<int, false, uint32_t>>(); //test_ring_queue<resumef::ring_queue_spinlock<int, false, uint32_t>>();
//test_ring_queue<resumef::ring_queue_lockfree<int, uint64_t>>(); //test_ring_queue<resumef::ring_queue_lockfree<int, uint64_t>>();
//resumable_main_mutex();
//return 0;
resumable_main_mutex();
return 0;
//if (argc > 1) //if (argc > 1)
// resumable_main_benchmark_asio_client(atoi(argv[1])); // resumable_main_benchmark_asio_client(atoi(argv[1]));

Loading…
Cancel
Save