From 946656e34ee4e6e06e61efe59e0bb5efae84660c Mon Sep 17 00:00:00 2001 From: tearshark Date: Wed, 18 Mar 2020 18:36:39 +0800 Subject: [PATCH] =?UTF-8?q?=E5=AE=9E=E7=8E=B0mutex=E7=AC=AC=E4=BA=8C?= =?UTF-8?q?=E7=89=88?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- librf/src/def.h | 2 +- librf/src/exception.inl | 1 + librf/src/mutex.h | 90 +-------- librf/src/{mutex.cpp => mutex_v1.cpp} | 252 +++++++++++++------------- librf/src/mutex_v1.h | 92 ++++++++++ librf/src/mutex_v2.cpp | 127 +++++++++++++ librf/src/mutex_v2.h | 40 ++++ librf/src/mutex_v2.inl | 203 +++++++++++++++++++++ librf/src/scheduler.cpp | 1 + librf/src/spinlock.h | 2 +- librf/src/state.cpp | 10 + librf/src/state.h | 20 +- tutorial/test_async_mutex.cpp | 9 +- vs_proj/librf.cpp | 3 +- vs_proj/librf.vcxproj | 6 +- vs_proj/librf.vcxproj.filters | 18 +- 16 files changed, 649 insertions(+), 227 deletions(-) rename librf/src/{mutex.cpp => mutex_v1.cpp} (80%) create mode 100644 librf/src/mutex_v1.h create mode 100644 librf/src/mutex_v2.cpp create mode 100644 librf/src/mutex_v2.h create mode 100644 librf/src/mutex_v2.inl diff --git a/librf/src/def.h b/librf/src/def.h index 30fb3b9..6134f97 100644 --- a/librf/src/def.h +++ b/librf/src/def.h @@ -1,6 +1,6 @@ #pragma once -#define LIB_RESUMEF_VERSION 20700 // 2.7.0 +#define LIB_RESUMEF_VERSION 20800 // 2.8.0 #if defined(RESUMEF_MODULE_EXPORT) #define RESUMEF_NS export namespace resumef diff --git a/librf/src/exception.inl b/librf/src/exception.inl index 5defff8..984dd77 100644 --- a/librf/src/exception.inl +++ b/librf/src/exception.inl @@ -10,6 +10,7 @@ RESUMEF_NS unlock_more, // unlock lock read_before_write, // 0channelȶд timer_canceled, // ʱȡ + not_await_lock, // ûЭʹco_awaitȴlock max__ }; diff --git a/librf/src/mutex.h b/librf/src/mutex.h index f5d1c6a..2c4ac34 100644 --- a/librf/src/mutex.h +++ b/librf/src/mutex.h @@ -1,89 +1,5 @@ #pragma once -RESUMEF_NS -{ - namespace detail - { - struct mutex_impl; - typedef ::resumef::detail::_awaker mutex_awaker; - typedef std::shared_ptr mutex_awaker_ptr; - - struct mutex_impl : public std::enable_shared_from_this - { - private: - //typedef spinlock lock_type; - typedef std::recursive_mutex lock_type; - - std::list _awakes; - mutex_awaker_ptr _owner; - lock_type _lock; - public: - mutex_impl(); - - //如果已经触发了awaker,则返回true - bool lock_(const mutex_awaker_ptr& awaker); - bool try_lock_(const mutex_awaker_ptr& awaker); - void unlock(); - - template, mutex_awaker_ptr>::value>> - decltype(auto) lock(callee_t&& awaker, dummy_t* dummy_ = nullptr) - { - (void)dummy_; - return lock_(std::make_shared(std::forward(awaker))); - } - - private: - mutex_impl(const mutex_impl&) = delete; - mutex_impl(mutex_impl&&) = delete; - mutex_impl& operator = (const mutex_impl&) = delete; - mutex_impl& operator = (mutex_impl&&) = delete; - }; - } - - struct mutex_t - { - typedef std::shared_ptr lock_impl_ptr; - typedef std::weak_ptr lock_impl_wptr; - typedef std::chrono::system_clock clock_type; - private: - lock_impl_ptr _locker; - public: - mutex_t(); - - void unlock() const - { - _locker->unlock(); - } - - - future_t lock() const; - bool try_lock() const; - - /* - template - awaitable_t - try_lock_for(const std::chrono::duration<_Rep, _Period> & dt) const - { - return try_lock_for_(std::chrono::duration_cast(dt)); - } - template - awaitable_t - try_lock_until(const std::chrono::time_point<_Clock, _Duration> & tp) const - { - return try_lock_until_(std::chrono::time_point_cast(tp)); - } - */ - - - mutex_t(const mutex_t&) = default; - mutex_t(mutex_t&&) = default; - mutex_t& operator = (const mutex_t&) = default; - mutex_t& operator = (mutex_t&&) = default; - private: - inline future_t try_lock_for_(const clock_type::duration& dt) const - { - return try_lock_until_(clock_type::now() + dt); - } - future_t try_lock_until_(const clock_type::time_point& tp) const; - }; -} +#include "mutex_v1.h" +#include "mutex_v2.h" +#include "mutex_v2.inl" diff --git a/librf/src/mutex.cpp b/librf/src/mutex_v1.cpp similarity index 80% rename from librf/src/mutex.cpp rename to librf/src/mutex_v1.cpp index c369b6f..1e31c2d 100644 --- a/librf/src/mutex.cpp +++ b/librf/src/mutex_v1.cpp @@ -1,124 +1,128 @@ -#include "../librf.h" - -RESUMEF_NS -{ - namespace detail - { - mutex_impl::mutex_impl() - { - } - - void mutex_impl::unlock() - { - scoped_lock lock_(this->_lock); - - if (_owner != nullptr) - { - for (auto iter = _awakes.begin(); iter != _awakes.end(); ) - { - auto awaker = *iter; - iter = _awakes.erase(iter); - - if (awaker->awake(this, 1)) - { - _owner = awaker; - break; - } - - } - if (_awakes.size() == 0) - { - _owner = nullptr; - } - } - } - - bool mutex_impl::lock_(const mutex_awaker_ptr & awaker) - { - assert(awaker); - - scoped_lock lock_(this->_lock); - - if (_owner == nullptr) - { - _owner = awaker; - awaker->awake(this, 1); - return true; - } - else - { - _awakes.push_back(awaker); - return false; - } - } - - bool mutex_impl::try_lock_(const mutex_awaker_ptr & awaker) - { - assert(awaker); - - scoped_lock lock_(this->_lock); - - if (_owner == nullptr) - { - _owner = awaker; - return true; - } - else - { - return false; - } - } - - } - - mutex_t::mutex_t() - : _locker(std::make_shared()) - { - } - - future_t mutex_t::lock() const - { - awaitable_t awaitable; - - auto awaker = std::make_shared( - [st = awaitable._state](detail::mutex_impl * e) -> bool - { - st->set_value(e ? true : false); - return true; - }); - _locker->lock_(awaker); - - return awaitable.get_future(); - } - - bool mutex_t::try_lock() const - { - auto dummy_awaker = std::make_shared( - [](detail::mutex_impl * ) -> bool - { - return true; - }); - return _locker->try_lock_(dummy_awaker); - } - - future_t mutex_t::try_lock_until_(const clock_type::time_point & tp) const - { - awaitable_t awaitable; - - auto awaker = std::make_shared( - [st = awaitable._state](detail::mutex_impl * e) -> bool - { - st->set_value(e ? true : false); - return true; - }); - _locker->lock_(awaker); - - (void)this_scheduler()->timer()->add(tp, - [awaker](bool ) - { - awaker->awake(nullptr, 1); - }); - - return awaitable.get_future(); - } -} +#include "../librf.h" + +RESUMEF_NS +{ + namespace detail + { + mutex_impl::mutex_impl() + { + } + + void mutex_impl::unlock() + { + scoped_lock lock_(this->_lock); + + if (_owner != nullptr) + { + for (auto iter = _awakes.begin(); iter != _awakes.end(); ) + { + auto awaker = *iter; + iter = _awakes.erase(iter); + + if (awaker->awake(this, 1)) + { + _owner = awaker; + break; + } + + } + if (_awakes.size() == 0) + { + _owner = nullptr; + } + } + } + + bool mutex_impl::lock_(const mutex_awaker_ptr& awaker) + { + assert(awaker); + + scoped_lock lock_(this->_lock); + + if (_owner == nullptr) + { + _owner = awaker; + awaker->awake(this, 1); + return true; + } + else + { + _awakes.push_back(awaker); + return false; + } + } + + bool mutex_impl::try_lock_(const mutex_awaker_ptr& awaker) + { + assert(awaker); + + scoped_lock lock_(this->_lock); + + if (_owner == nullptr) + { + _owner = awaker; + return true; + } + else + { + return false; + } + } + + } + +namespace mutex_v1 +{ + + mutex_t::mutex_t() + : _locker(std::make_shared()) + { + } + + future_t mutex_t::lock() const + { + awaitable_t awaitable; + + auto awaker = std::make_shared( + [st = awaitable._state](detail::mutex_impl* e) -> bool + { + st->set_value(e ? true : false); + return true; + }); + _locker->lock_(awaker); + + return awaitable.get_future(); + } + + bool mutex_t::try_lock() const + { + auto dummy_awaker = std::make_shared( + [](detail::mutex_impl*) -> bool + { + return true; + }); + return _locker->try_lock_(dummy_awaker); + } + + future_t mutex_t::try_lock_until_(const clock_type::time_point& tp) const + { + awaitable_t awaitable; + + auto awaker = std::make_shared( + [st = awaitable._state](detail::mutex_impl* e) -> bool + { + st->set_value(e ? true : false); + return true; + }); + _locker->lock_(awaker); + + (void)this_scheduler()->timer()->add(tp, + [awaker](bool) + { + awaker->awake(nullptr, 1); + }); + + return awaitable.get_future(); + } +} +} diff --git a/librf/src/mutex_v1.h b/librf/src/mutex_v1.h new file mode 100644 index 0000000..b24c272 --- /dev/null +++ b/librf/src/mutex_v1.h @@ -0,0 +1,92 @@ +#pragma once + +RESUMEF_NS +{ + namespace detail + { + struct mutex_impl; + typedef ::resumef::detail::_awaker mutex_awaker; + typedef std::shared_ptr mutex_awaker_ptr; + + struct mutex_impl : public std::enable_shared_from_this + { + private: + //typedef spinlock lock_type; + typedef std::recursive_mutex lock_type; + + std::list _awakes; + mutex_awaker_ptr _owner; + lock_type _lock; + public: + mutex_impl(); + + //如果已经触发了awaker,则返回true + bool lock_(const mutex_awaker_ptr& awaker); + bool try_lock_(const mutex_awaker_ptr& awaker); + void unlock(); + + template, mutex_awaker_ptr>::value>> + decltype(auto) lock(callee_t&& awaker, dummy_t* dummy_ = nullptr) + { + (void)dummy_; + return lock_(std::make_shared(std::forward(awaker))); + } + + private: + mutex_impl(const mutex_impl&) = delete; + mutex_impl(mutex_impl&&) = delete; + mutex_impl& operator = (const mutex_impl&) = delete; + mutex_impl& operator = (mutex_impl&&) = delete; + }; + } + +namespace mutex_v1 +{ + struct mutex_t + { + typedef std::shared_ptr lock_impl_ptr; + typedef std::weak_ptr lock_impl_wptr; + typedef std::chrono::system_clock clock_type; + private: + lock_impl_ptr _locker; + public: + mutex_t(); + + void unlock() const + { + _locker->unlock(); + } + + + future_t lock() const; + bool try_lock() const; + + /* + template + awaitable_t + try_lock_for(const std::chrono::duration<_Rep, _Period> & dt) const + { + return try_lock_for_(std::chrono::duration_cast(dt)); + } + template + awaitable_t + try_lock_until(const std::chrono::time_point<_Clock, _Duration> & tp) const + { + return try_lock_until_(std::chrono::time_point_cast(tp)); + } + */ + + + mutex_t(const mutex_t&) = default; + mutex_t(mutex_t&&) = default; + mutex_t& operator = (const mutex_t&) = default; + mutex_t& operator = (mutex_t&&) = default; + private: + inline future_t try_lock_for_(const clock_type::duration& dt) const + { + return try_lock_until_(clock_type::now() + dt); + } + future_t try_lock_until_(const clock_type::time_point& tp) const; + }; +} +} diff --git a/librf/src/mutex_v2.cpp b/librf/src/mutex_v2.cpp new file mode 100644 index 0000000..446cfd6 --- /dev/null +++ b/librf/src/mutex_v2.cpp @@ -0,0 +1,127 @@ +#include "../librf.h" + +RESUMEF_NS +{ + namespace detail + { + void state_mutex_t::resume() + { + coroutine_handle<> handler = _coro; + if (handler) + { + _coro = nullptr; + _scheduler->del_final(this); + handler.resume(); + } + } + + bool state_mutex_t::has_handler() const noexcept + { + return (bool)_coro; + } + + state_base_t* state_mutex_t::get_parent() const noexcept + { + return _root; + } + + bool state_mutex_t::on_notify() + { + assert(this->_scheduler != nullptr); + if (this->_coro) + { + this->_scheduler->add_generator(this); + return true; + } + + return false; + } + + + void mutex_v2_impl::lock_until_succeed(void* sch) + { + assert(sch != nullptr); + + for (;;) + { + if (try_lock(sch)) + break; + std::this_thread::yield(); + } + } + + bool mutex_v2_impl::try_lock(void* sch) noexcept + { + scoped_lock lock_(_lock); + return try_lock_lockless(sch); + } + + bool mutex_v2_impl::try_lock_lockless(void* sch) noexcept + { + void* oldValue = _owner.load(std::memory_order_relaxed); + if (oldValue == nullptr || oldValue == sch) + { + _owner.store(sch, std::memory_order_relaxed); + _counter.fetch_add(1, std::memory_order_relaxed); + + return true; + } + return false; + } + + bool mutex_v2_impl::unlock(void* sch) + { + scoped_lock lock_(_lock); + + void* oldValue = _owner.load(std::memory_order_relaxed); + if (oldValue == sch) + { + if (_counter.fetch_sub(1, std::memory_order_relaxed) == 1) + { + if (!_wait_awakes.empty()) + { + state_mutex_ptr state = _wait_awakes.front(); + _wait_awakes.pop_front(); + + //锁定状态转移到新的state上 + _owner.store(state->get_root(), std::memory_order_relaxed); + _counter.fetch_add(1, std::memory_order_relaxed); + + state->on_notify(); + } + else + { + _owner.store(nullptr, std::memory_order_relaxed); + } + } + + return true; + } + + return false; + } + + void mutex_v2_impl::add_wait_list_lockless(state_mutex_t* state) + { + assert(state != nullptr); + + _wait_awakes.push_back(state); + } + } + + inline namespace mutex_v2 + { + mutex_t::mutex_t() + : _mutex(std::make_shared()) + { + } + + mutex_t::mutex_t(std::adopt_lock_t) noexcept + { + } + + mutex_t::~mutex_t() noexcept + { + } + } +} diff --git a/librf/src/mutex_v2.h b/librf/src/mutex_v2.h new file mode 100644 index 0000000..dcdc080 --- /dev/null +++ b/librf/src/mutex_v2.h @@ -0,0 +1,40 @@ +#pragma once + +RESUMEF_NS +{ + namespace detail + { + struct mutex_v2_impl; + } + + inline namespace mutex_v2 + { + struct scoped_lock_mutex_t; + + struct mutex_t + { + typedef std::shared_ptr mutex_impl_ptr; + typedef std::chrono::system_clock clock_type; + + mutex_t(); + mutex_t(std::adopt_lock_t) noexcept; + ~mutex_t() noexcept; + + struct [[nodiscard]] awaiter; + + awaiter lock() const noexcept; + + scoped_lock_mutex_t lock(scheduler_t* sch) const noexcept; + bool try_lock(scheduler_t* sch) const noexcept; + void unlock(scheduler_t* sch) const 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; + private: + friend struct scoped_lock_mutex_t; + mutex_impl_ptr _mutex; + }; + } +} diff --git a/librf/src/mutex_v2.inl b/librf/src/mutex_v2.inl new file mode 100644 index 0000000..7b42a9d --- /dev/null +++ b/librf/src/mutex_v2.inl @@ -0,0 +1,203 @@ +#pragma once + +RESUMEF_NS +{ + namespace detail + { + struct state_mutex_t : public state_base_t + { + virtual void resume() override; + virtual bool has_handler() const noexcept override; + virtual state_base_t* get_parent() const noexcept override; + + bool on_notify(); + + inline scheduler_t* get_scheduler() const noexcept + { + return _scheduler; + } + + inline void on_await_suspend(coroutine_handle<> handler, scheduler_t* sch, state_base_t* root) noexcept + { + this->_scheduler = sch; + this->_coro = handler; + this->_root = root; + } + + private: + state_base_t* _root; + //friend mutex_v2::mutex_t; + }; + + //做成递归锁? + struct mutex_v2_impl : public std::enable_shared_from_this + { + mutex_v2_impl() {} + + inline void* owner() const noexcept + { + return _owner.load(std::memory_order_relaxed); + } + + bool try_lock(void* sch) noexcept; //内部加锁 + bool unlock(void* sch); //内部加锁 + void lock_until_succeed(void* sch); //内部加锁 + public: + static constexpr bool USE_SPINLOCK = true; + + using lock_type = std::conditional_t; + using state_mutex_ptr = counted_ptr; + using wait_queue_type = std::list; + + bool try_lock_lockless(void* sch) noexcept; //内部不加锁,加锁由外部来进行 + void add_wait_list_lockless(state_mutex_t* state); //内部不加锁,加锁由外部来进行 + + lock_type _lock; //保证访问本对象是线程安全的 + private: + std::atomic _owner = nullptr; //锁标记 + std::atomic _counter = 0; //递归锁的次数 + wait_queue_type _wait_awakes; //等待队列 + + // No copying/moving + mutex_v2_impl(const mutex_v2_impl&) = delete; + mutex_v2_impl(mutex_v2_impl&&) = delete; + mutex_v2_impl& operator=(const mutex_v2_impl&) = delete; + mutex_v2_impl& operator=(mutex_v2_impl&&) = delete; + }; + } + + inline namespace mutex_v2 + { + struct scoped_lock_mutex_t + { + typedef std::shared_ptr mutex_impl_ptr; + + //此函数,应该在try_lock()获得锁后使用 + //或者在协程里,由awaiter使用 + scoped_lock_mutex_t(std::adopt_lock_t, detail::mutex_v2_impl* mtx, void* sch) + : _mutex(mtx->shared_from_this()) + , _owner(sch) + {} + + //此函数,适合在非协程里使用 + scoped_lock_mutex_t(detail::mutex_v2_impl* mtx, void* sch) + : _mutex(mtx->shared_from_this()) + , _owner(sch) + { + if (sch != nullptr) + _mutex->lock_until_succeed(sch); + } + + + scoped_lock_mutex_t(std::adopt_lock_t, const mutex_t& mtx, void* sch) + : scoped_lock_mutex_t(std::adopt_lock, mtx._mutex.get(), sch) + {} + scoped_lock_mutex_t(const mutex_t& mtx, void* sch) + : scoped_lock_mutex_t(mtx._mutex.get(), sch) + {} + + ~scoped_lock_mutex_t() + { + if (_mutex != nullptr) + _mutex->unlock(_owner); + } + + inline void unlock() noexcept + { + if (_mutex != nullptr) + { + _mutex->unlock(_owner); + _mutex = nullptr; + } + } + + 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&&) = default; + scoped_lock_mutex_t& operator = (scoped_lock_mutex_t&&) = default; + private: + mutex_impl_ptr _mutex; + void* _owner; + }; + + + struct [[nodiscard]] mutex_t::awaiter + { + awaiter(detail::mutex_v2_impl* evt) noexcept + : _mutex(evt) + { + } + + ~awaiter() noexcept(false) + { + assert(_mutex == nullptr); + if (_mutex != nullptr) + { + throw lock_exception(error_code::not_await_lock); + } + } + + bool await_ready() noexcept + { + return false; + } + + template>> + bool await_suspend(coroutine_handle<_PromiseT> handler) + { + _PromiseT& promise = handler.promise(); + auto* parent = promise.get_state(); + _root = parent->get_root(); + + scoped_lock lock_(_mutex->_lock); + if (_mutex->try_lock_lockless(_root)) + return false; + + _state = new detail::state_mutex_t(); + (void)_state->on_await_suspend(handler, parent->get_scheduler(), _root); + + _mutex->add_wait_list_lockless(_state.get()); + + return true; + } + + scoped_lock_mutex_t await_resume() noexcept + { + detail::mutex_v2_impl* mtx = _mutex; + _mutex = nullptr; + + return { std::adopt_lock, mtx, _root }; + } + protected: + detail::mutex_v2_impl* _mutex; + counted_ptr _state; + state_base_t* _root = nullptr; + }; + + inline mutex_t::awaiter mutex_t::lock() const noexcept + { + return { _mutex.get() }; + } + + inline scoped_lock_mutex_t mutex_t::lock(scheduler_t* sch) const noexcept + { + if (sch != nullptr) + _mutex->lock_until_succeed(sch); + + return { std::adopt_lock, _mutex.get(), sch }; + } + + inline bool mutex_t::try_lock(scheduler_t* sch) const noexcept + { + if (sch == nullptr) + return false; + return _mutex->try_lock(sch); + } + + inline void mutex_t::unlock(scheduler_t* sch) const noexcept + { + assert(sch != nullptr); + _mutex->unlock(sch); + } + } +} diff --git a/librf/src/scheduler.cpp b/librf/src/scheduler.cpp index 42d5b5a..58d0b3d 100644 --- a/librf/src/scheduler.cpp +++ b/librf/src/scheduler.cpp @@ -18,6 +18,7 @@ RESUMEF_NS "unlock_more", "read_before_write", "timer_canceled", + "not_await_lock", }; char sz_future_error_buffer[256]; diff --git a/librf/src/spinlock.h b/librf/src/spinlock.h index 8d689ba..ea7f1ba 100644 --- a/librf/src/spinlock.h +++ b/librf/src/spinlock.h @@ -15,7 +15,7 @@ RESUMEF_NS static const int FREE_VALUE = 0; static const int LOCKED_VALUE = 1; - volatile std::atomic lck; + std::atomic lck; #if _DEBUG std::thread::id owner_thread_id; #endif diff --git a/librf/src/state.cpp b/librf/src/state.cpp index 4a695e7..848906a 100644 --- a/librf/src/state.cpp +++ b/librf/src/state.cpp @@ -10,6 +10,11 @@ RESUMEF_NS { delete this; } + + state_base_t* state_base_t::get_parent() const noexcept + { + return nullptr; + } void state_future_t::destroy_deallocate() { @@ -88,6 +93,11 @@ RESUMEF_NS return true; } + state_base_t* state_future_t::get_parent() const noexcept + { + return _parent; + } + void state_future_t::resume() { std::unique_lock __guard(_mtx); diff --git a/librf/src/state.h b/librf/src/state.h index 86be3cd..94122ed 100644 --- a/librf/src/state.h +++ b/librf/src/state.h @@ -33,6 +33,7 @@ RESUMEF_NS public: virtual void resume() = 0; virtual bool has_handler() const noexcept = 0; + virtual state_base_t* get_parent() const noexcept; void set_scheduler(scheduler_t* sch) { @@ -42,6 +43,18 @@ RESUMEF_NS { return _coro; } + + state_base_t* get_root() const noexcept + { + state_base_t* root = const_cast(this); + state_base_t* next = root->get_parent(); + while (next != nullptr) + { + root = next; + next = next->get_parent(); + } + return root; + } }; struct state_generator_t : public state_base_t @@ -125,7 +138,8 @@ RESUMEF_NS virtual void destroy_deallocate() override; virtual void resume() override; virtual bool has_handler() const noexcept override; - + virtual state_base_t* get_parent() const noexcept override; + inline bool is_ready() const noexcept { //msvc认为是constexpr表达式(不写还给警告),然而,clang不这么认为。 @@ -149,10 +163,6 @@ RESUMEF_NS return _parent ? _parent->get_scheduler() : _scheduler; } - inline state_base_t * get_parent() const noexcept - { - return _parent; - } inline uint32_t get_alloc_size() const noexcept { return _alloc_size; diff --git a/tutorial/test_async_mutex.cpp b/tutorial/test_async_mutex.cpp index b919122..fd0e516 100644 --- a/tutorial/test_async_mutex.cpp +++ b/tutorial/test_async_mutex.cpp @@ -19,7 +19,7 @@ future_t<> test_mutex_pop(size_t idx) for (size_t i = 0; i < 10; ++i) { - co_await resumf_guard_lock(g_lock); + auto _locker = co_await g_lock.lock(); if (g_queue.size() > 0) { @@ -32,14 +32,15 @@ future_t<> test_mutex_pop(size_t idx) } } -future_t<> test_mutex_push() +future_t<> test_mutex_push(size_t idx) { using namespace std::chrono; for (size_t i = 0; i < 10; ++i) { - co_await resumf_guard_lock(g_lock); + auto _locker = co_await g_lock.lock(); g_queue.push_back(i); + std::cout << i << " on " << idx << std::endl; co_await sleep_for(500ms); } @@ -47,7 +48,7 @@ future_t<> test_mutex_push() void resumable_main_mutex() { - go test_mutex_push(); + go test_mutex_push(0); go test_mutex_pop(1); this_scheduler()->run_until_notask(); diff --git a/vs_proj/librf.cpp b/vs_proj/librf.cpp index beb2f8f..4970eea 100644 --- a/vs_proj/librf.cpp +++ b/vs_proj/librf.cpp @@ -47,7 +47,8 @@ int main(int argc, const char* argv[]) //resumable_main_event(); //resumable_main_event_timeout(); //resumable_main_sleep(); - //return 0; + resumable_main_mutex(); + return 0; //if (argc > 1) // resumable_main_benchmark_asio_client(atoi(argv[1])); diff --git a/vs_proj/librf.vcxproj b/vs_proj/librf.vcxproj index 3f02bbe..3aa80ef 100644 --- a/vs_proj/librf.vcxproj +++ b/vs_proj/librf.vcxproj @@ -183,7 +183,8 @@ - + + @@ -233,6 +234,8 @@ + + @@ -260,6 +263,7 @@ + diff --git a/vs_proj/librf.vcxproj.filters b/vs_proj/librf.vcxproj.filters index 8dc2c52..042be6f 100644 --- a/vs_proj/librf.vcxproj.filters +++ b/vs_proj/librf.vcxproj.filters @@ -25,9 +25,6 @@ Source Files - - librf\src - librf\src @@ -121,6 +118,12 @@ librf\src + + librf\src + + + librf\src + @@ -228,6 +231,12 @@ librf\src + + librf\src + + + librf\src + @@ -261,5 +270,8 @@ librf\src + + librf\src + \ No newline at end of file