@@ -905,7 +905,11 @@ RECURSIVE = NO | |||
EXCLUDE = channel_v1.h \ | |||
event_v1.h \ | |||
mutex_v1.h | |||
mutex_v1.h \ | |||
ring_queue.h \ | |||
ring_queue_lockfree.h \ | |||
ring_queue_spinlock.h \ | |||
intrusive_link_queue.h | |||
# The EXCLUDE_SYMLINKS tag can be used to select whether or not files or | |||
# directories that are symbolic links (a Unix file system feature) are excluded |
@@ -45,14 +45,24 @@ RESUMEF_NS | |||
struct [[nodiscard]] any_awaiter; | |||
template<class _Iter | |||
#ifndef DOXYGEN_SKIP_PROPERTY | |||
COMMA_RESUMEF_ENABLE_IF(traits::is_iterator_of_v<_Iter, event_t>) | |||
> RESUMEF_REQUIRES(_IteratorOfT<_Iter, event_t>) | |||
#endif //DOXYGEN_SKIP_PROPERTY | |||
> | |||
#ifndef DOXYGEN_SKIP_PROPERTY | |||
RESUMEF_REQUIRES(_IteratorOfT<_Iter, event_t>) | |||
#endif //DOXYGEN_SKIP_PROPERTY | |||
static auto wait_any(_Iter begin_, _Iter end_) | |||
->any_awaiter<_Iter>; | |||
template<class _Cont | |||
#ifndef DOXYGEN_SKIP_PROPERTY | |||
COMMA_RESUMEF_ENABLE_IF(traits::is_container_of_v<_Cont, event_t>) | |||
> RESUMEF_REQUIRES(_ContainerOfT<_Cont, event_t>) | |||
#endif //DOXYGEN_SKIP_PROPERTY | |||
> | |||
#ifndef DOXYGEN_SKIP_PROPERTY | |||
RESUMEF_REQUIRES(_ContainerOfT<_Cont, event_t>) | |||
#endif //DOXYGEN_SKIP_PROPERTY | |||
static auto wait_any(_Cont& cnt_) | |||
->any_awaiter<decltype(std::begin(cnt_))>; | |||
@@ -60,14 +70,24 @@ RESUMEF_NS | |||
struct [[nodiscard]] timeout_any_awaiter; | |||
template<class _Rep, class _Period, class _Iter | |||
#ifndef DOXYGEN_SKIP_PROPERTY | |||
COMMA_RESUMEF_ENABLE_IF(traits::is_iterator_of_v<_Iter, event_t>) | |||
> RESUMEF_REQUIRES(_IteratorOfT<_Iter, event_t>) | |||
#endif //DOXYGEN_SKIP_PROPERTY | |||
> | |||
#ifndef DOXYGEN_SKIP_PROPERTY | |||
RESUMEF_REQUIRES(_IteratorOfT<_Iter, event_t>) | |||
#endif //DOXYGEN_SKIP_PROPERTY | |||
static auto wait_any_for(const std::chrono::duration<_Rep, _Period>& dt, _Iter begin_, _Iter end_) | |||
->timeout_any_awaiter<_Iter>; | |||
template<class _Rep, class _Period, class _Cont | |||
#ifndef DOXYGEN_SKIP_PROPERTY | |||
COMMA_RESUMEF_ENABLE_IF(traits::is_container_of_v<_Cont, event_t>) | |||
> RESUMEF_REQUIRES(_ContainerOfT<_Cont, event_t>) | |||
#endif //DOXYGEN_SKIP_PROPERTY | |||
> | |||
#ifndef DOXYGEN_SKIP_PROPERTY | |||
RESUMEF_REQUIRES(_ContainerOfT<_Cont, event_t>) | |||
#endif //DOXYGEN_SKIP_PROPERTY | |||
static auto wait_any_for(const std::chrono::duration<_Rep, _Period>& dt, _Cont& cnt_) | |||
->timeout_any_awaiter<decltype(std::begin(cnt_))>; | |||
@@ -77,14 +97,24 @@ RESUMEF_NS | |||
struct [[nodiscard]] all_awaiter; | |||
template<class _Iter | |||
#ifndef DOXYGEN_SKIP_PROPERTY | |||
COMMA_RESUMEF_ENABLE_IF(traits::is_iterator_of_v<_Iter, event_t>) | |||
> RESUMEF_REQUIRES(_IteratorOfT<_Iter, event_t>) | |||
#endif //DOXYGEN_SKIP_PROPERTY | |||
> | |||
#ifndef DOXYGEN_SKIP_PROPERTY | |||
RESUMEF_REQUIRES(_IteratorOfT<_Iter, event_t>) | |||
#endif //DOXYGEN_SKIP_PROPERTY | |||
static auto wait_all(_Iter begin_, _Iter end_) | |||
->all_awaiter<_Iter>; | |||
template<class _Cont | |||
#ifndef DOXYGEN_SKIP_PROPERTY | |||
COMMA_RESUMEF_ENABLE_IF(traits::is_container_of_v<_Cont, event_t>) | |||
> RESUMEF_REQUIRES(_ContainerOfT<_Cont, event_t>) | |||
#endif //DOXYGEN_SKIP_PROPERTY | |||
> | |||
#ifndef DOXYGEN_SKIP_PROPERTY | |||
RESUMEF_REQUIRES(_ContainerOfT<_Cont, event_t>) | |||
#endif //DOXYGEN_SKIP_PROPERTY | |||
static auto wait_all(_Cont& cnt_) | |||
->all_awaiter<decltype(std::begin(cnt_))>; | |||
@@ -92,14 +122,24 @@ RESUMEF_NS | |||
struct [[nodiscard]] timeout_all_awaiter; | |||
template<class _Rep, class _Period, class _Iter | |||
#ifndef DOXYGEN_SKIP_PROPERTY | |||
COMMA_RESUMEF_ENABLE_IF(traits::is_iterator_of_v<_Iter, event_t>) | |||
> RESUMEF_REQUIRES(_IteratorOfT<_Iter, event_t>) | |||
#endif //DOXYGEN_SKIP_PROPERTY | |||
> | |||
#ifndef DOXYGEN_SKIP_PROPERTY | |||
RESUMEF_REQUIRES(_IteratorOfT<_Iter, event_t>) | |||
#endif //DOXYGEN_SKIP_PROPERTY | |||
static auto wait_all_for(const std::chrono::duration<_Rep, _Period>& dt, _Iter begin_, _Iter end_) | |||
->timeout_all_awaiter<_Iter>; | |||
template<class _Rep, class _Period, class _Cont | |||
#ifndef DOXYGEN_SKIP_PROPERTY | |||
COMMA_RESUMEF_ENABLE_IF(traits::is_container_of_v<_Cont, event_t>) | |||
> RESUMEF_REQUIRES(_ContainerOfT<_Cont, event_t>) | |||
#endif //DOXYGEN_SKIP_PROPERTY | |||
> | |||
#ifndef DOXYGEN_SKIP_PROPERTY | |||
RESUMEF_REQUIRES(_ContainerOfT<_Cont, event_t>) | |||
#endif //DOXYGEN_SKIP_PROPERTY | |||
static auto wait_all_for(const std::chrono::duration<_Rep, _Period>& dt, _Cont& cnt_) | |||
->timeout_all_awaiter<decltype(std::begin(cnt_))>; | |||
@@ -273,7 +273,7 @@ RESUMEF_NS | |||
lockes.emplace_back(std::ref(evt->_lock)); | |||
} | |||
scoped_lock_range<ref_lock_type> lock_(lockes); | |||
batch_lock_t<ref_lock_type> lock_(lockes); | |||
for (auto iter = _begin; iter != _end; ++iter) | |||
{ | |||
@@ -404,7 +404,7 @@ RESUMEF_NS | |||
(void)_state->on_await_suspend(handler); | |||
cb(); | |||
scoped_lock_range<ref_lock_type> lock_(lockes); | |||
batch_lock_t<ref_lock_type> lock_(lockes); | |||
for (auto iter = _begin; iter != _end; ++iter) | |||
{ |
@@ -256,7 +256,7 @@ RESUMEF_NS | |||
}; | |||
#endif //DOXYGEN_SKIP_PROPERTY | |||
typedef generator_iterator<_Ty, promise_type> iterator; | |||
using iterator = generator_iterator<_Ty, promise_type>; | |||
iterator begin() | |||
{ |
@@ -12,12 +12,12 @@ RESUMEF_NS | |||
{ | |||
#endif //DOXYGEN_SKIP_PROPERTY | |||
/** | |||
* @brief 提示手工解锁,故相关的lock()函数不再返回scoped_unlock_t。 | |||
* @brief 提示手工解锁,故相关的lock()函数不再返回batch_unlock_t。 | |||
*/ | |||
struct adopt_manual_unlock_t{}; | |||
/** | |||
* @brief 提示手工解锁,故相关的lock()函数不再返回scoped_unlock_t。 | |||
* @brief 提示手工解锁,故相关的lock()函数不再返回batch_unlock_t。 | |||
*/ | |||
constexpr adopt_manual_unlock_t adopt_manual_unlock; | |||
@@ -25,7 +25,7 @@ RESUMEF_NS | |||
* @brief 在析构的时候自动解锁mutex_t的辅助类。 | |||
*/ | |||
template<class... _Mtxs> | |||
struct [[nodiscard]] scoped_unlock_t; | |||
struct [[nodiscard]] batch_unlock_t; | |||
/** | |||
* @brief 支持递归的锁。 | |||
@@ -41,15 +41,15 @@ RESUMEF_NS | |||
/** | |||
* @brief 在协程中加锁,如果不能立即获得锁,则阻塞当前协程。但不会阻塞当前线程。 | |||
* @return [co_await] scoped_unlock_t | |||
* @return [co_await] batch_unlock_t | |||
*/ | |||
awaiter/*scoped_unlock_t*/ lock() const noexcept; | |||
awaiter/*batch_unlock_t*/ lock() const noexcept; | |||
/** | |||
* @brief 等同调用 co_await lock()。 | |||
* @return [co_await] scoped_unlock_t | |||
* @return [co_await] batch_unlock_t | |||
*/ | |||
awaiter/*scoped_unlock_t*/ operator co_await() const noexcept; | |||
awaiter/*batch_unlock_t*/ operator co_await() const noexcept; | |||
/** | |||
* @brief 在协程中加锁,如果不能立即获得锁,则阻塞当前协程。但不会阻塞当前线程。 | |||
@@ -137,14 +137,14 @@ RESUMEF_NS | |||
/** | |||
* @brief 在协程中,无死锁的批量加锁。不会阻塞当前线程。直到获得所有锁之前,会阻塞当前协程。 | |||
* @param mtxs... 需要获得的锁列表。 | |||
* @return [co_await] scoped_unlock_t | |||
* @return [co_await] batch_unlock_t | |||
*/ | |||
template<class... _Mtxs | |||
#ifndef DOXYGEN_SKIP_PROPERTY | |||
, typename = std::enable_if_t<std::conjunction_v<std::is_same<remove_cvref_t<_Mtxs>, mutex_t>...>> | |||
#endif //DOXYGEN_SKIP_PROPERTY | |||
> | |||
static future_t<scoped_unlock_t<_Mtxs...>> lock(_Mtxs&... mtxs); | |||
static future_t<batch_unlock_t<_Mtxs...>> lock(_Mtxs&... mtxs); | |||
/** | |||
* @brief 在协程中,无死锁的批量加锁。不会阻塞当前线程。直到获得所有锁之前,会阻塞当前协程。 | |||
@@ -176,14 +176,14 @@ RESUMEF_NS | |||
* @brief 在非协程中,无死锁的批量加锁。会阻塞当前线程,直到获得所有锁为止。 | |||
* @param unique_address 代表获得锁的拥有者。 | |||
* @param mtxs... 需要获得的锁列表。 | |||
* @return scoped_unlock_t | |||
* @return batch_unlock_t | |||
*/ | |||
template<class... _Mtxs | |||
#ifndef DOXYGEN_SKIP_PROPERTY | |||
, typename = std::enable_if_t<std::conjunction_v<std::is_same<remove_cvref_t<_Mtxs>, mutex_t>...>> | |||
#endif //DOXYGEN_SKIP_PROPERTY | |||
> | |||
static scoped_unlock_t<_Mtxs...> lock(void* unique_address, _Mtxs&... mtxs); | |||
static batch_unlock_t<_Mtxs...> lock(void* unique_address, _Mtxs&... mtxs); | |||
/** | |||
* @brief 在非协程中,无死锁的批量加锁。会阻塞当前线程,直到获得所有锁为止。 | |||
@@ -229,7 +229,7 @@ RESUMEF_NS | |||
private: | |||
struct _MutexAwaitAssembleT; | |||
template<class... _Mtxs> friend struct scoped_unlock_t; | |||
template<class... _Mtxs> friend struct batch_unlock_t; | |||
mutex_impl_ptr _mutex; | |||
#endif //DOXYGEN_SKIP_PROPERTY |
@@ -127,23 +127,28 @@ RESUMEF_NS | |||
inline namespace mutex_v2 | |||
{ | |||
template<> | |||
struct [[nodiscard]] scoped_unlock_t<mutex_t> | |||
struct [[nodiscard]] batch_unlock_t<mutex_t> | |||
{ | |||
typedef std::shared_ptr<detail::mutex_v2_impl> mutex_impl_ptr; | |||
scoped_unlock_t() | |||
batch_unlock_t() | |||
: _owner(nullptr) | |||
{} | |||
//此函数,应该在try_lock()获得锁后使用 | |||
//或者在协程里,由awaiter使用 | |||
scoped_unlock_t(std::adopt_lock_t, void* sch, mutex_impl_ptr mtx) | |||
batch_unlock_t(std::adopt_lock_t, void* sch, mutex_impl_ptr mtx) | |||
: _mutex(std::move(mtx)) | |||
, _owner(sch) | |||
{} | |||
batch_unlock_t(std::adopt_lock_t, void* sch, const mutex_t& mtx) | |||
: batch_unlock_t(std::adopt_lock, sch, mtx._mutex) | |||
{} | |||
/* | |||
//此函数,适合在非协程里使用 | |||
scoped_unlock_t(void* sch, mutex_impl_ptr mtx) | |||
batch_unlock_t(void* sch, mutex_impl_ptr mtx) | |||
: _mutex(std::move(mtx)) | |||
, _owner(sch) | |||
{ | |||
@@ -151,15 +156,12 @@ RESUMEF_NS | |||
_mutex->lock_until_succeed(sch); | |||
} | |||
scoped_unlock_t(std::adopt_lock_t, void* sch, const mutex_t& mtx) | |||
: scoped_unlock_t(std::adopt_lock, sch, mtx._mutex) | |||
{} | |||
scoped_unlock_t(void* sch, const mutex_t& mtx) | |||
: scoped_unlock_t(sch, mtx._mutex) | |||
batch_unlock_t(void* sch, const mutex_t& mtx) | |||
: batch_unlock_t(sch, mtx._mutex) | |||
{} | |||
*/ | |||
~scoped_unlock_t() | |||
~batch_unlock_t() | |||
{ | |||
if (_mutex != nullptr) | |||
_mutex->unlock(_owner); | |||
@@ -174,10 +176,10 @@ RESUMEF_NS | |||
} | |||
} | |||
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; | |||
batch_unlock_t(const batch_unlock_t&) = delete; | |||
batch_unlock_t& operator = (const batch_unlock_t&) = delete; | |||
batch_unlock_t(batch_unlock_t&& _Right) = default; | |||
batch_unlock_t& operator = (batch_unlock_t&& _Right) = default; | |||
private: | |||
mutex_impl_ptr _mutex; | |||
void* _owner; | |||
@@ -241,7 +243,7 @@ RESUMEF_NS | |||
{ | |||
return await_suspend2(handler, []{}); | |||
} | |||
scoped_unlock_t<mutex_t> await_resume() noexcept | |||
batch_unlock_t<mutex_t> await_resume() noexcept | |||
{ | |||
mutex_impl_ptr mtx = _mutex ? _mutex->shared_from_this() : nullptr; | |||
_mutex = nullptr; | |||
@@ -487,16 +489,16 @@ RESUMEF_NS | |||
}; | |||
template<class... _Mtxs> | |||
struct [[nodiscard]] scoped_unlock_t | |||
struct [[nodiscard]] batch_unlock_t | |||
{ | |||
mutex_t::_MutexAwaitAssembleT _MAA; | |||
template<class... U> | |||
scoped_unlock_t(std::adopt_lock_t, void* sch, U&&... mtxs) | |||
batch_unlock_t(std::adopt_lock_t, void* sch, U&&... mtxs) | |||
: _MAA(sch, std::forward<U>(mtxs)...) | |||
{} | |||
~scoped_unlock_t() | |||
~batch_unlock_t() | |||
{ | |||
if (_MAA._owner != nullptr) | |||
{ | |||
@@ -515,19 +517,19 @@ RESUMEF_NS | |||
} | |||
} | |||
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; | |||
batch_unlock_t(const batch_unlock_t&) = delete; | |||
batch_unlock_t& operator = (const batch_unlock_t&) = delete; | |||
batch_unlock_t(batch_unlock_t&& _Right) = default; | |||
batch_unlock_t& operator = (batch_unlock_t&& _Right) = default; | |||
}; | |||
template<class... _Mtxs> | |||
scoped_unlock_t()->scoped_unlock_t<_Mtxs...>; | |||
batch_unlock_t()->batch_unlock_t<_Mtxs...>; | |||
template<class... _Mtxs, typename> | |||
inline future_t<scoped_unlock_t<_Mtxs...>> mutex_t::lock(_Mtxs&... mtxs) | |||
inline future_t<batch_unlock_t<_Mtxs...>> mutex_t::lock(_Mtxs&... mtxs) | |||
{ | |||
scoped_unlock_t<_Mtxs...> unlock_guard{ std::adopt_lock, root_state(), mtxs... }; | |||
batch_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 std::move(unlock_guard); | |||
} | |||
@@ -548,14 +550,14 @@ RESUMEF_NS | |||
} | |||
template<class... _Mtxs, typename> | |||
inline scoped_unlock_t<_Mtxs...> mutex_t::lock(void* unique_address, _Mtxs&... mtxs) | |||
inline batch_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); | |||
scoped_unlock_t<_Mtxs...> su{ std::adopt_lock, unique_address }; | |||
batch_unlock_t<_Mtxs...> su{ std::adopt_lock, unique_address }; | |||
su._MAA._mutex = std::move(_MAA._mutex); | |||
return su; | |||
} |
@@ -1,15 +1,17 @@ | |||
#pragma once | |||
#ifndef DOXYGEN_SKIP_PROPERTY | |||
RESUMEF_NS | |||
{ | |||
struct local_scheduler; | |||
#endif //DOXYGEN_SKIP_PROPERTY | |||
struct scheduler_t : public std::enable_shared_from_this<scheduler_t> | |||
{ | |||
private: | |||
using state_sptr = counted_ptr<state_base_t>; | |||
using state_vector = std::vector<state_sptr>; | |||
private: | |||
using lock_type = std::recursive_mutex; | |||
using lock_type = spinlock; | |||
using task_dictionary_type = std::unordered_map<state_base_t*, std::unique_ptr<task_base_t>>; | |||
mutable spinlock _lock_running; | |||
@@ -23,7 +25,6 @@ RESUMEF_NS | |||
void new_task(task_base_t* task); | |||
//void cancel_all_task_(); | |||
public: | |||
void run_one_batch(); | |||
void run_until_notask(); | |||
@@ -31,10 +32,14 @@ RESUMEF_NS | |||
//void break_all(); | |||
template<class _Ty | |||
#ifndef DOXYGEN_SKIP_PROPERTY | |||
COMMA_RESUMEF_ENABLE_IF(traits::is_callable_v<_Ty> || traits::is_future_v<_Ty> || traits::is_generator_v<_Ty>) | |||
#endif //DOXYGEN_SKIP_PROPERTY | |||
> | |||
RESUMEF_REQUIRES(traits::is_callable_v<_Ty> || traits::is_future_v<_Ty> || traits::is_generator_v<_Ty>) | |||
inline void operator + (_Ty&& t_) | |||
#ifndef DOXYGEN_SKIP_PROPERTY | |||
RESUMEF_REQUIRES(traits::is_callable_v<_Ty> || traits::is_future_v<_Ty> || traits::is_generator_v<_Ty>) | |||
#endif //DOXYGEN_SKIP_PROPERTY | |||
void operator + (_Ty&& t_) | |||
{ | |||
if constexpr (traits::is_callable_v<_Ty>) | |||
new_task(new ctx_task_t<_Ty>(t_)); | |||
@@ -42,17 +47,18 @@ RESUMEF_NS | |||
new_task(new task_t<_Ty>(t_)); | |||
} | |||
inline bool empty() const | |||
bool empty() const | |||
{ | |||
scoped_lock<spinlock, spinlock> __guard(_lock_ready, _lock_running); | |||
return _ready_task.empty() && _runing_states.empty() && _timer->empty(); | |||
} | |||
inline timer_manager* timer() const noexcept | |||
timer_manager* timer() const noexcept | |||
{ | |||
return _timer.get(); | |||
} | |||
#ifndef DOXYGEN_SKIP_PROPERTY | |||
void add_generator(state_base_t* sptr); | |||
void del_final(state_base_t* sptr); | |||
std::unique_ptr<task_base_t> del_switch(state_base_t* sptr); | |||
@@ -70,6 +76,7 @@ RESUMEF_NS | |||
scheduler_t& operator = (const scheduler_t&) = delete; | |||
static scheduler_t g_scheduler; | |||
#endif //DOXYGEN_SKIP_PROPERTY | |||
}; | |||
struct local_scheduler | |||
@@ -87,7 +94,8 @@ RESUMEF_NS | |||
scheduler_t* _scheduler_ptr; | |||
#endif | |||
}; | |||
//-------------------------------------------------------------------------------------------------- | |||
#if !RESUMEF_ENABLE_MULT_SCHEDULER | |||
//获得当前线程下的调度器 | |||
inline scheduler_t* this_scheduler() | |||
@@ -95,6 +103,4 @@ RESUMEF_NS | |||
return &scheduler_t::g_scheduler; | |||
} | |||
#endif | |||
//-------------------------------------------------------------------------------------------------- | |||
} |
@@ -178,34 +178,36 @@ RESUMEF_NS | |||
} | |||
#endif //DOXYGEN_SKIP_PROPERTY | |||
// class with destructor that unlocks mutexes | |||
template<class _Ty, class _Cont = std::vector<_Ty>, class _Assemble = detail::_LockVectorAssembleT<_Ty, _Cont>> | |||
class scoped_lock_range { // class with destructor that unlocks mutexes | |||
class batch_lock_t | |||
{ | |||
public: | |||
explicit scoped_lock_range(_Cont& locks_) | |||
explicit batch_lock_t(_Cont& locks_) | |||
: _LkN(&locks_) | |||
, _LA(*_LkN) | |||
{ | |||
detail::scoped_lock_range_lock_impl::_Lock_range(_LA); | |||
} | |||
explicit scoped_lock_range(_Cont& locks_, _Assemble& la_) | |||
explicit batch_lock_t(_Cont& locks_, _Assemble& la_) | |||
: _LkN(&locks_) | |||
, _LA(la_) | |||
{ | |||
detail::scoped_lock_range_lock_impl::_Lock_range(_LA); | |||
} | |||
explicit scoped_lock_range(std::adopt_lock_t, _Cont& locks_) | |||
explicit batch_lock_t(std::adopt_lock_t, _Cont& locks_) | |||
: _LkN(&locks_) | |||
, _LA(*_LkN) | |||
{ // construct but don't lock | |||
} | |||
explicit scoped_lock_range(std::adopt_lock_t, _Cont& locks_, _Assemble& la_) | |||
explicit batch_lock_t(std::adopt_lock_t, _Cont& locks_, _Assemble& la_) | |||
: _LkN(&locks_) | |||
, _LA(la_) | |||
{ // construct but don't lock | |||
} | |||
~scoped_lock_range() noexcept | |||
~batch_lock_t() noexcept | |||
{ | |||
if (_LkN != nullptr) | |||
detail::scoped_lock_range_lock_impl::_Unlock_locks(0, (int)_LA.size(), _LA); | |||
@@ -220,16 +222,16 @@ RESUMEF_NS | |||
} | |||
} | |||
scoped_lock_range(const scoped_lock_range&) = delete; | |||
scoped_lock_range& operator=(const scoped_lock_range&) = delete; | |||
batch_lock_t(const batch_lock_t&) = delete; | |||
batch_lock_t& operator=(const batch_lock_t&) = delete; | |||
scoped_lock_range(scoped_lock_range&& _Right) | |||
batch_lock_t(batch_lock_t&& _Right) | |||
: _LkN(_Right._LkN) | |||
, _LA(std::move(_Right._LA)) | |||
{ | |||
_Right._LkN = nullptr; | |||
} | |||
scoped_lock_range& operator=(scoped_lock_range&& _Right) | |||
batch_lock_t& operator=(batch_lock_t&& _Right) | |||
{ | |||
if (this != &_Right) | |||
{ |
@@ -21,14 +21,14 @@ static future_t<> test_mutex_pop(size_t idx) | |||
for (size_t i = 0; i < N / 2; ++i) | |||
{ | |||
{ | |||
scoped_unlock_t _locker = co_await g_lock.lock(); //_locker析构后,会调用对应的unlock()函数。 | |||
batch_unlock_t _locker = co_await g_lock.lock(); //_locker析构后,会调用对应的unlock()函数。 | |||
--g_counter; | |||
std::cout << "pop :" << g_counter << " on " << idx << std::endl; | |||
co_await 50ms; | |||
scoped_unlock_t _locker_2 = co_await g_lock; | |||
batch_unlock_t _locker_2 = co_await g_lock; | |||
--g_counter; | |||
std::cout << "pop :" << g_counter << " on " << idx << std::endl; | |||
@@ -45,7 +45,7 @@ static future_t<> test_mutex_push(size_t idx) | |||
for (size_t i = 0; i < N; ++i) | |||
{ | |||
{ | |||
scoped_unlock_t _locker = co_await g_lock.lock(); | |||
batch_unlock_t _locker = co_await g_lock.lock(); | |||
++g_counter; | |||
std::cout << "push:" << g_counter << " on " << idx << std::endl; | |||
@@ -103,7 +103,7 @@ static std::thread test_mutex_async_push(size_t idx) | |||
{ | |||
if (g_lock.try_lock_for(500ms, &provide_unique_address)) | |||
{ | |||
scoped_unlock_t _locker(std::adopt_lock, &provide_unique_address, g_lock); | |||
batch_unlock_t _locker(std::adopt_lock, &provide_unique_address, g_lock); | |||
++g_counter; | |||
std::cout << "push:" << g_counter << " on " << idx << std::endl; | |||
@@ -143,7 +143,7 @@ static future_t<> resumable_mutex_range_push(size_t idx, mutex_t a, mutex_t b, m | |||
{ | |||
for (int i = 0; i < 10000; ++i) | |||
{ | |||
scoped_unlock_t __lockers = co_await mutex_t::lock(a, b, c); | |||
batch_unlock_t __lockers = co_await mutex_t::lock(a, b, c); | |||
assert(a.is_locked()); | |||
assert(b.is_locked()); | |||
assert(c.is_locked()); |