@@ -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 |
@@ -10,6 +10,7 @@ RESUMEF_NS | |||
unlock_more, // unlock 次数多余lock次数 | |||
read_before_write, // 0容量的channel,先读后写 | |||
timer_canceled, // 定时器被意外取消 | |||
not_await_lock, // 没有在协程中使用co_await等待lock结果 | |||
max__ | |||
}; |
@@ -1,89 +1,5 @@ | |||
#pragma once | |||
RESUMEF_NS | |||
{ | |||
namespace detail | |||
{ | |||
struct mutex_impl; | |||
typedef ::resumef::detail::_awaker<mutex_impl> mutex_awaker; | |||
typedef std::shared_ptr<mutex_awaker> mutex_awaker_ptr; | |||
struct mutex_impl : public std::enable_shared_from_this<mutex_impl> | |||
{ | |||
private: | |||
//typedef spinlock lock_type; | |||
typedef std::recursive_mutex lock_type; | |||
std::list<mutex_awaker_ptr> _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<class callee_t, class dummy_t = std::enable_if<!std::is_same<std::remove_cv_t<callee_t>, mutex_awaker_ptr>::value>> | |||
decltype(auto) lock(callee_t&& awaker, dummy_t* dummy_ = nullptr) | |||
{ | |||
(void)dummy_; | |||
return lock_(std::make_shared<mutex_awaker>(std::forward<callee_t>(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<detail::mutex_impl> lock_impl_ptr; | |||
typedef std::weak_ptr<detail::mutex_impl> 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<bool> lock() const; | |||
bool try_lock() const; | |||
/* | |||
template<class _Rep, class _Period> | |||
awaitable_t<bool> | |||
try_lock_for(const std::chrono::duration<_Rep, _Period> & dt) const | |||
{ | |||
return try_lock_for_(std::chrono::duration_cast<clock_type::duration>(dt)); | |||
} | |||
template<class _Clock, class _Duration> | |||
awaitable_t<bool> | |||
try_lock_until(const std::chrono::time_point<_Clock, _Duration> & tp) const | |||
{ | |||
return try_lock_until_(std::chrono::time_point_cast<clock_type::duration>(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<bool> try_lock_for_(const clock_type::duration& dt) const | |||
{ | |||
return try_lock_until_(clock_type::now() + dt); | |||
} | |||
future_t<bool> try_lock_until_(const clock_type::time_point& tp) const; | |||
}; | |||
} | |||
#include "mutex_v1.h" | |||
#include "mutex_v2.h" | |||
#include "mutex_v2.inl" |
@@ -1,124 +1,128 @@ | |||
#include "../librf.h" | |||
RESUMEF_NS | |||
{ | |||
namespace detail | |||
{ | |||
mutex_impl::mutex_impl() | |||
{ | |||
} | |||
void mutex_impl::unlock() | |||
{ | |||
scoped_lock<lock_type> 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_type> 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_type> lock_(this->_lock); | |||
if (_owner == nullptr) | |||
{ | |||
_owner = awaker; | |||
return true; | |||
} | |||
else | |||
{ | |||
return false; | |||
} | |||
} | |||
} | |||
mutex_t::mutex_t() | |||
: _locker(std::make_shared<detail::mutex_impl>()) | |||
{ | |||
} | |||
future_t<bool> mutex_t::lock() const | |||
{ | |||
awaitable_t<bool> awaitable; | |||
auto awaker = std::make_shared<detail::mutex_awaker>( | |||
[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_awaker>( | |||
[](detail::mutex_impl * ) -> bool | |||
{ | |||
return true; | |||
}); | |||
return _locker->try_lock_(dummy_awaker); | |||
} | |||
future_t<bool> mutex_t::try_lock_until_(const clock_type::time_point & tp) const | |||
{ | |||
awaitable_t<bool> awaitable; | |||
auto awaker = std::make_shared<detail::mutex_awaker>( | |||
[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_type> 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_type> 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_type> lock_(this->_lock); | |||
if (_owner == nullptr) | |||
{ | |||
_owner = awaker; | |||
return true; | |||
} | |||
else | |||
{ | |||
return false; | |||
} | |||
} | |||
} | |||
namespace mutex_v1 | |||
{ | |||
mutex_t::mutex_t() | |||
: _locker(std::make_shared<detail::mutex_impl>()) | |||
{ | |||
} | |||
future_t<bool> mutex_t::lock() const | |||
{ | |||
awaitable_t<bool> awaitable; | |||
auto awaker = std::make_shared<detail::mutex_awaker>( | |||
[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_awaker>( | |||
[](detail::mutex_impl*) -> bool | |||
{ | |||
return true; | |||
}); | |||
return _locker->try_lock_(dummy_awaker); | |||
} | |||
future_t<bool> mutex_t::try_lock_until_(const clock_type::time_point& tp) const | |||
{ | |||
awaitable_t<bool> awaitable; | |||
auto awaker = std::make_shared<detail::mutex_awaker>( | |||
[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(); | |||
} | |||
} | |||
} |
@@ -0,0 +1,92 @@ | |||
#pragma once | |||
RESUMEF_NS | |||
{ | |||
namespace detail | |||
{ | |||
struct mutex_impl; | |||
typedef ::resumef::detail::_awaker<mutex_impl> mutex_awaker; | |||
typedef std::shared_ptr<mutex_awaker> mutex_awaker_ptr; | |||
struct mutex_impl : public std::enable_shared_from_this<mutex_impl> | |||
{ | |||
private: | |||
//typedef spinlock lock_type; | |||
typedef std::recursive_mutex lock_type; | |||
std::list<mutex_awaker_ptr> _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<class callee_t, class dummy_t = std::enable_if<!std::is_same<std::remove_cv_t<callee_t>, mutex_awaker_ptr>::value>> | |||
decltype(auto) lock(callee_t&& awaker, dummy_t* dummy_ = nullptr) | |||
{ | |||
(void)dummy_; | |||
return lock_(std::make_shared<mutex_awaker>(std::forward<callee_t>(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<detail::mutex_impl> lock_impl_ptr; | |||
typedef std::weak_ptr<detail::mutex_impl> 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<bool> lock() const; | |||
bool try_lock() const; | |||
/* | |||
template<class _Rep, class _Period> | |||
awaitable_t<bool> | |||
try_lock_for(const std::chrono::duration<_Rep, _Period> & dt) const | |||
{ | |||
return try_lock_for_(std::chrono::duration_cast<clock_type::duration>(dt)); | |||
} | |||
template<class _Clock, class _Duration> | |||
awaitable_t<bool> | |||
try_lock_until(const std::chrono::time_point<_Clock, _Duration> & tp) const | |||
{ | |||
return try_lock_until_(std::chrono::time_point_cast<clock_type::duration>(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<bool> try_lock_for_(const clock_type::duration& dt) const | |||
{ | |||
return try_lock_until_(clock_type::now() + dt); | |||
} | |||
future_t<bool> try_lock_until_(const clock_type::time_point& tp) const; | |||
}; | |||
} | |||
} |
@@ -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<detail::mutex_v2_impl::lock_type> 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_type> 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<detail::mutex_v2_impl>()) | |||
{ | |||
} | |||
mutex_t::mutex_t(std::adopt_lock_t) noexcept | |||
{ | |||
} | |||
mutex_t::~mutex_t() noexcept | |||
{ | |||
} | |||
} | |||
} |
@@ -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<detail::mutex_v2_impl> 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; | |||
}; | |||
} | |||
} |
@@ -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> | |||
{ | |||
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<USE_SPINLOCK, spinlock, std::recursive_mutex>; | |||
using state_mutex_ptr = counted_ptr<state_mutex_t>; | |||
using wait_queue_type = std::list<state_mutex_ptr>; | |||
bool try_lock_lockless(void* sch) noexcept; //内部不加锁,加锁由外部来进行 | |||
void add_wait_list_lockless(state_mutex_t* state); //内部不加锁,加锁由外部来进行 | |||
lock_type _lock; //保证访问本对象是线程安全的 | |||
private: | |||
std::atomic<void*> _owner = nullptr; //锁标记 | |||
std::atomic<intptr_t> _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<detail::mutex_v2_impl> 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<class _PromiseT, typename = std::enable_if_t<traits::is_promise_v<_PromiseT>>> | |||
bool await_suspend(coroutine_handle<_PromiseT> handler) | |||
{ | |||
_PromiseT& promise = handler.promise(); | |||
auto* parent = promise.get_state(); | |||
_root = parent->get_root(); | |||
scoped_lock<detail::mutex_v2_impl::lock_type> 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<detail::state_mutex_t> _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); | |||
} | |||
} | |||
} |
@@ -18,6 +18,7 @@ RESUMEF_NS | |||
"unlock_more", | |||
"read_before_write", | |||
"timer_canceled", | |||
"not_await_lock", | |||
}; | |||
char sz_future_error_buffer[256]; |
@@ -15,7 +15,7 @@ RESUMEF_NS | |||
static const int FREE_VALUE = 0; | |||
static const int LOCKED_VALUE = 1; | |||
volatile std::atomic<int> lck; | |||
std::atomic<int> lck; | |||
#if _DEBUG | |||
std::thread::id owner_thread_id; | |||
#endif |
@@ -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<lock_type> __guard(_mtx); |
@@ -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<state_base_t*>(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; |
@@ -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(); |
@@ -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])); |
@@ -183,7 +183,8 @@ | |||
<ClCompile Include="..\benchmark\benchmark_channel_passing_next.cpp" /> | |||
<ClCompile Include="..\librf\src\event_v1.cpp" /> | |||
<ClCompile Include="..\librf\src\event_v2.cpp" /> | |||
<ClCompile Include="..\librf\src\mutex.cpp" /> | |||
<ClCompile Include="..\librf\src\mutex_v1.cpp" /> | |||
<ClCompile Include="..\librf\src\mutex_v2.cpp" /> | |||
<ClCompile Include="..\librf\src\rf_task.cpp" /> | |||
<ClCompile Include="..\librf\src\scheduler.cpp" /> | |||
<ClCompile Include="..\librf\src\sleep.cpp" /> | |||
@@ -233,6 +234,8 @@ | |||
<ClInclude Include="..\librf\src\future.h" /> | |||
<ClInclude Include="..\librf\src\generator.h" /> | |||
<ClInclude Include="..\librf\src\intrusive_link_queue.h" /> | |||
<ClInclude Include="..\librf\src\mutex_v1.h" /> | |||
<ClInclude Include="..\librf\src\mutex_v2.h" /> | |||
<ClInclude Include="..\librf\src\promise.h" /> | |||
<ClInclude Include="..\librf\src\mutex.h" /> | |||
<ClInclude Include="..\librf\src\rf_task.h" /> | |||
@@ -260,6 +263,7 @@ | |||
<None Include="..\librf\src\event_v2.inl" /> | |||
<None Include="..\librf\src\exception.inl" /> | |||
<None Include="..\librf\src\macro_def.inl" /> | |||
<None Include="..\librf\src\mutex_v2.inl" /> | |||
<None Include="..\librf\src\promise.inl" /> | |||
<None Include="..\librf\src\state.inl" /> | |||
<None Include="..\librf\src\type_concept.inl" /> |
@@ -25,9 +25,6 @@ | |||
<ClCompile Include="librf.cpp"> | |||
<Filter>Source Files</Filter> | |||
</ClCompile> | |||
<ClCompile Include="..\librf\src\mutex.cpp"> | |||
<Filter>librf\src</Filter> | |||
</ClCompile> | |||
<ClCompile Include="..\librf\src\rf_task.cpp"> | |||
<Filter>librf\src</Filter> | |||
</ClCompile> | |||
@@ -121,6 +118,12 @@ | |||
<ClCompile Include="..\librf\src\when_v2.cpp"> | |||
<Filter>librf\src</Filter> | |||
</ClCompile> | |||
<ClCompile Include="..\librf\src\mutex_v1.cpp"> | |||
<Filter>librf\src</Filter> | |||
</ClCompile> | |||
<ClCompile Include="..\librf\src\mutex_v2.cpp"> | |||
<Filter>librf\src</Filter> | |||
</ClCompile> | |||
</ItemGroup> | |||
<ItemGroup> | |||
<ClInclude Include="..\librf\librf.h"> | |||
@@ -228,6 +231,12 @@ | |||
<ClInclude Include="..\librf\src\when_v2.h"> | |||
<Filter>librf\src</Filter> | |||
</ClInclude> | |||
<ClInclude Include="..\librf\src\mutex_v1.h"> | |||
<Filter>librf\src</Filter> | |||
</ClInclude> | |||
<ClInclude Include="..\librf\src\mutex_v2.h"> | |||
<Filter>librf\src</Filter> | |||
</ClInclude> | |||
</ItemGroup> | |||
<ItemGroup> | |||
<None Include="..\librf\src\asio_task_1.12.0.inl"> | |||
@@ -261,5 +270,8 @@ | |||
<None Include="..\librf\src\type_concept.inl"> | |||
<Filter>librf\src</Filter> | |||
</None> | |||
<None Include="..\librf\src\mutex_v2.inl"> | |||
<Filter>librf\src</Filter> | |||
</None> | |||
</ItemGroup> | |||
</Project> |