@@ -16,6 +16,7 @@ RESUMEF_NS | |||
struct [[nodiscard]] scoped_unlock_t; | |||
//支持递归的锁 | |||
//锁被本协程所在的跟协程所拥有。支持在跟协程下的所有协程里递归加锁。 | |||
struct mutex_t | |||
{ | |||
bool is_locked() const; | |||
@@ -24,24 +25,57 @@ RESUMEF_NS | |||
struct [[nodiscard]] awaiter; | |||
struct [[nodiscard]] manual_awaiter; | |||
/** | |||
* @brief 在协程中加锁。 | |||
* @return [co_await] scoped_unlock_t | |||
*/ | |||
awaiter/*scoped_unlock_t*/ lock() const noexcept; | |||
/** | |||
* @brief 等同调用co_await lock()。 | |||
* @return [co_await] scoped_unlock_t | |||
*/ | |||
awaiter/*scoped_unlock_t*/ operator co_await() const noexcept; | |||
/** | |||
* @brief 在协程中加锁。需要随后调用unlock()函数解锁。lock()/unlock()调用必须在同一个跟协程下配对调用。 | |||
* @return [co_await] void | |||
*/ | |||
manual_awaiter/*void*/ lock(adopt_manual_unlock_t) const noexcept; | |||
struct [[nodiscard]] try_awaiter; | |||
//co_await try_lock()获得是否加锁成功。此操作无论成功与否都会立即返回。 | |||
//如果加锁成功,则需要调用co_await unlock()解锁。或者使用unlock(root_state())解锁。 | |||
//如果加锁失败,且要循环尝试加锁,则最好调用co_await yield()让出一次调度。否则,可能造成本调度器死循环。 | |||
/** | |||
* @brief 尝试在协程中加锁。此操作无论成功与否都会立即返回。 | |||
* 如果加锁成功,则需要调用co_await unlock()解锁。或者使用unlock(root_state())解锁。 | |||
* 如果加锁失败,且要循环尝试加锁,则最好调用co_await yield()让出一次调度。否则,可能造成本调度器死循环。 | |||
* @return [co_await] bool | |||
*/ | |||
try_awaiter/*bool*/ try_lock() const noexcept; | |||
//此操作立即返回 | |||
/** | |||
* @brief 在协程中解锁。此操作立即返回。 | |||
* @return [co_await] void | |||
*/ | |||
struct [[nodiscard]] unlock_awaiter; | |||
unlock_awaiter/*void*/ unlock() const noexcept; | |||
struct [[nodiscard]] timeout_awaiter; | |||
/** | |||
* @brief 在协程中尝试加锁,直到超时 | |||
* @param dt 超时时长 | |||
* @return [co_await] bool | |||
*/ | |||
template <class _Rep, class _Period> | |||
timeout_awaiter/*bool*/ try_lock_for(const std::chrono::duration<_Rep, _Period>& dt) const noexcept; | |||
/** | |||
* @brief 在协程中尝试加锁,直到超时 | |||
* @param tp 超时时刻 | |||
* @return [co_await] bool | |||
*/ | |||
template <class _Rep, class _Period> | |||
timeout_awaiter/*bool*/ try_lock_until(const std::chrono::time_point<_Rep, _Period>& tp) const noexcept; | |||
@@ -55,17 +89,36 @@ RESUMEF_NS | |||
void unlock(void* unique_address) const; | |||
/** | |||
* @brief 在协程中,无死锁的批量加锁。捕获阻塞当前线程。直到获得所有锁之前,阻塞当前协程。 | |||
* @return [co_await] scoped_unlock_t | |||
*/ | |||
template<class... _Mtxs | |||
, typename = std::enable_if_t<std::conjunction_v<std::is_same<remove_cvref_t<_Mtxs>, mutex_t>...>> | |||
> | |||
static future_t<scoped_unlock_t<_Mtxs...>> lock(_Mtxs&... mtxs); | |||
/** | |||
* @brief 在非协程中,无死锁的批量加锁。会阻塞当前线程,直到获得所有锁为止。 | |||
* @return scoped_unlock_t | |||
*/ | |||
template<class... _Mtxs | |||
, typename = std::enable_if_t<std::conjunction_v<std::is_same<remove_cvref_t<_Mtxs>, mutex_t>...>> | |||
> | |||
static scoped_unlock_t<_Mtxs...> lock(void* unique_address, _Mtxs&... mtxs); | |||
/** | |||
* @brief 在非协程中,无死锁的批量加锁。会阻塞当前线程,直到获得所有锁为止。 | |||
*/ | |||
template<class... _Mtxs | |||
, typename = std::enable_if_t<std::conjunction_v<std::is_same<remove_cvref_t<_Mtxs>, mutex_t>...>> | |||
> | |||
static void lock(adopt_manual_unlock_t, void* unique_address, _Mtxs&... mtxs); | |||
/** | |||
* @brief 在非协程中,批量解锁加锁。立即返回。 | |||
*/ | |||
template<class... _Mtxs | |||
, typename = std::enable_if_t<std::conjunction_v<std::is_same<remove_cvref_t<_Mtxs>, mutex_t>...>> | |||
> |
@@ -547,6 +547,14 @@ RESUMEF_NS | |||
return { unique_address, mtxs... }; | |||
} | |||
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::scoped_lock_range_lock_impl::_Lock_range(_MAA); | |||
} | |||
template<class... _Mtxs, typename> | |||
inline void mutex_t::unlock(void* unique_address, _Mtxs&... mtxs) | |||
{ |
@@ -178,7 +178,7 @@ RESUMEF_NS | |||
static _Sty* _Construct(void* _Ptr, size_t _Size) | |||
{ | |||
_Sty* st = new(_Ptr) _Sty(false); | |||
st->_alloc_size = _Size; | |||
st->_alloc_size = static_cast<uint32_t>(_Size); | |||
return st; | |||
} | |||
@@ -193,7 +193,7 @@ RESUMEF_NS | |||
#endif | |||
char* _Ptr = _Al.allocate(_Size); | |||
_Sty* st = new(_Ptr) _Sty(awaitor); | |||
st->_alloc_size = _Size; | |||
st->_alloc_size = static_cast<uint32_t>(_Size); | |||
return st; | |||
} |
@@ -1,6 +1,7 @@ | |||
| |||
#include "librf.h" | |||
#include <optional> | |||
#include <crtdbg.h> | |||
//#define _WITH_LOCK_FREE_Q_KEEP_REAL_SIZE 1 | |||
#include "src/ring_queue.h" | |||
@@ -36,6 +37,7 @@ extern void resumable_main_benchmark_asio_client(intptr_t nNum); | |||
int main(int argc, const char* argv[]) | |||
{ | |||
//_CrtSetDbgFlag(_CrtSetDbgFlag(_CRTDBG_REPORT_FLAG) | _CRTDBG_ALLOC_MEM_DF | _CRTDBG_CHECK_ALWAYS_DF | _CRTDBG_LEAK_CHECK_DF); | |||
(void)argc; | |||
(void)argv; | |||
@@ -51,30 +53,31 @@ int main(int argc, const char* argv[]) | |||
//else | |||
// resumable_main_benchmark_asio_server(); | |||
resumable_main_cb(); | |||
resumable_main_layout(); | |||
resumable_main_modern_cb(); | |||
resumable_main_suspend_always(); | |||
resumable_main_yield_return(); | |||
resumable_main_resumable(); | |||
resumable_main_routine(); | |||
resumable_main_exception(); | |||
resumable_main_dynamic_go(); | |||
resumable_main_multi_thread(); | |||
resumable_main_timer(); | |||
resumable_main_benchmark_mem(false); | |||
resumable_main_mutex(); | |||
resumable_main_event(); | |||
resumable_main_event_v2(); | |||
resumable_main_event_timeout(); | |||
resumable_main_channel(); | |||
resumable_main_channel_mult_thread(); | |||
resumable_main_sleep(); | |||
resumable_main_when_all(); | |||
resumable_main_switch_scheduler(); | |||
resumable_main_cb(); _CrtCheckMemory(); | |||
resumable_main_layout(); _CrtCheckMemory(); | |||
resumable_main_modern_cb(); _CrtCheckMemory(); | |||
resumable_main_suspend_always(); _CrtCheckMemory(); | |||
resumable_main_yield_return(); _CrtCheckMemory(); | |||
resumable_main_resumable(); _CrtCheckMemory(); | |||
resumable_main_routine(); _CrtCheckMemory(); | |||
resumable_main_exception(); _CrtCheckMemory(); | |||
resumable_main_dynamic_go(); _CrtCheckMemory(); | |||
resumable_main_multi_thread(); _CrtCheckMemory(); | |||
resumable_main_timer(); _CrtCheckMemory(); | |||
resumable_main_benchmark_mem(false); _CrtCheckMemory(); | |||
resumable_main_mutex(); _CrtCheckMemory(); | |||
resumable_main_event(); _CrtCheckMemory(); | |||
resumable_main_event_v2(); _CrtCheckMemory(); | |||
resumable_main_event_timeout(); _CrtCheckMemory(); | |||
resumable_main_channel(); _CrtCheckMemory(); | |||
resumable_main_channel_mult_thread(); _CrtCheckMemory(); | |||
resumable_main_sleep(); _CrtCheckMemory(); | |||
resumable_main_when_all(); _CrtCheckMemory(); | |||
resumable_main_switch_scheduler(); _CrtCheckMemory(); | |||
std::cout << "ALL OK!" << std::endl; | |||
benchmark_main_channel_passing_next(); //这是一个死循环测试 | |||
_CrtCheckMemory(); | |||
return 0; | |||
} |
@@ -37,7 +37,6 @@ | |||
<PlatformToolset>v142</PlatformToolset> | |||
<WholeProgramOptimization>true</WholeProgramOptimization> | |||
<CharacterSet>NotSet</CharacterSet> | |||
<EnableASAN>true</EnableASAN> | |||
</PropertyGroup> | |||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration"> | |||
<ConfigurationType>Application</ConfigurationType> |