2021-11-01 17:59:08 +08:00
|
|
|
|
#include "librf/librf.h"
|
2020-03-18 18:36:39 +08:00
|
|
|
|
|
2021-11-01 17:59:08 +08:00
|
|
|
|
namespace librf
|
2020-03-18 18:36:39 +08:00
|
|
|
|
{
|
|
|
|
|
namespace detail
|
|
|
|
|
{
|
2020-03-22 14:19:10 +08:00
|
|
|
|
void state_mutex_t::resume()
|
2020-03-18 18:36:39 +08:00
|
|
|
|
{
|
|
|
|
|
coroutine_handle<> handler = _coro;
|
|
|
|
|
if (handler)
|
|
|
|
|
{
|
|
|
|
|
_coro = nullptr;
|
|
|
|
|
_scheduler->del_final(this);
|
|
|
|
|
handler.resume();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2020-03-22 14:19:10 +08:00
|
|
|
|
bool state_mutex_t::has_handler() const noexcept
|
2020-03-18 18:36:39 +08:00
|
|
|
|
{
|
|
|
|
|
return (bool)_coro;
|
|
|
|
|
}
|
|
|
|
|
|
2020-03-22 14:19:10 +08:00
|
|
|
|
state_base_t* state_mutex_t::get_parent() const noexcept
|
2020-03-18 18:36:39 +08:00
|
|
|
|
{
|
|
|
|
|
return _root;
|
|
|
|
|
}
|
|
|
|
|
|
2020-03-20 01:04:52 +08:00
|
|
|
|
|
|
|
|
|
void state_mutex_t::on_cancel() noexcept
|
|
|
|
|
{
|
|
|
|
|
mutex_v2_impl** oldValue = _value.load(std::memory_order_acquire);
|
|
|
|
|
if (oldValue != nullptr && _value.compare_exchange_strong(oldValue, nullptr, std::memory_order_acq_rel))
|
|
|
|
|
{
|
|
|
|
|
*oldValue = nullptr;
|
|
|
|
|
_thandler.stop();
|
|
|
|
|
|
|
|
|
|
this->_coro = nullptr;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool state_mutex_t::on_notify(mutex_v2_impl* eptr)
|
|
|
|
|
{
|
2020-03-22 00:50:54 +08:00
|
|
|
|
assert(eptr != nullptr);
|
|
|
|
|
|
2020-03-20 01:04:52 +08:00
|
|
|
|
mutex_v2_impl** oldValue = _value.load(std::memory_order_acquire);
|
|
|
|
|
if (oldValue != nullptr && _value.compare_exchange_strong(oldValue, nullptr, std::memory_order_acq_rel))
|
|
|
|
|
{
|
|
|
|
|
*oldValue = eptr;
|
|
|
|
|
_thandler.stop();
|
|
|
|
|
|
|
|
|
|
assert(this->_scheduler != nullptr);
|
|
|
|
|
if (this->_coro)
|
|
|
|
|
this->_scheduler->add_generator(this);
|
|
|
|
|
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool state_mutex_t::on_timeout()
|
|
|
|
|
{
|
|
|
|
|
mutex_v2_impl** oldValue = _value.load(std::memory_order_acquire);
|
|
|
|
|
if (oldValue != nullptr && _value.compare_exchange_strong(oldValue, nullptr, std::memory_order_acq_rel))
|
|
|
|
|
{
|
|
|
|
|
*oldValue = nullptr;
|
|
|
|
|
_thandler.reset();
|
|
|
|
|
|
|
|
|
|
assert(this->_scheduler != nullptr);
|
|
|
|
|
if (this->_coro)
|
|
|
|
|
this->_scheduler->add_generator(this);
|
|
|
|
|
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
2020-03-22 14:19:10 +08:00
|
|
|
|
void state_mutex_t::add_timeout_timer(std::chrono::system_clock::time_point tp)
|
2020-03-20 01:04:52 +08:00
|
|
|
|
{
|
2020-03-22 14:19:10 +08:00
|
|
|
|
this->_thandler = this->_scheduler->timer()->add_handler(tp,
|
|
|
|
|
[st = counted_ptr<state_mutex_t>{ this }](bool canceld)
|
2020-03-23 17:25:58 +08:00
|
|
|
|
{
|
|
|
|
|
if (!canceld)
|
|
|
|
|
st->on_timeout();
|
|
|
|
|
});
|
2020-03-20 01:04:52 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2020-03-18 18:36:39 +08:00
|
|
|
|
void mutex_v2_impl::lock_until_succeed(void* sch)
|
|
|
|
|
{
|
|
|
|
|
assert(sch != nullptr);
|
|
|
|
|
|
|
|
|
|
for (;;)
|
|
|
|
|
{
|
|
|
|
|
if (try_lock(sch))
|
|
|
|
|
break;
|
|
|
|
|
std::this_thread::yield();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2020-03-18 21:46:55 +08:00
|
|
|
|
bool mutex_v2_impl::try_lock(void* sch)
|
2020-03-18 18:36:39 +08:00
|
|
|
|
{
|
2020-03-22 00:50:54 +08:00
|
|
|
|
assert(sch != nullptr);
|
|
|
|
|
|
2020-03-18 18:36:39 +08:00
|
|
|
|
scoped_lock<detail::mutex_v2_impl::lock_type> lock_(_lock);
|
|
|
|
|
return try_lock_lockless(sch);
|
|
|
|
|
}
|
|
|
|
|
|
2020-03-19 17:46:10 +08:00
|
|
|
|
bool mutex_v2_impl::try_lock_until(clock_type::time_point tp, void* sch)
|
|
|
|
|
{
|
2020-03-22 00:50:54 +08:00
|
|
|
|
assert(sch != nullptr);
|
|
|
|
|
|
2020-03-19 17:46:10 +08:00
|
|
|
|
do
|
|
|
|
|
{
|
|
|
|
|
if (try_lock(sch))
|
|
|
|
|
return true;
|
|
|
|
|
std::this_thread::yield();
|
|
|
|
|
} while (clock_type::now() <= tp);
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
2020-03-18 18:36:39 +08:00
|
|
|
|
bool mutex_v2_impl::try_lock_lockless(void* sch) noexcept
|
|
|
|
|
{
|
2020-03-22 00:50:54 +08:00
|
|
|
|
assert(sch != nullptr);
|
|
|
|
|
|
2020-03-22 14:19:10 +08:00
|
|
|
|
void* oldValue = _owner.load(std::memory_order_relaxed);
|
2020-03-18 21:46:55 +08:00
|
|
|
|
if (oldValue == nullptr)
|
2020-03-18 18:36:39 +08:00
|
|
|
|
{
|
2020-03-22 14:19:10 +08:00
|
|
|
|
_owner.store(sch, std::memory_order_relaxed);
|
|
|
|
|
_counter.fetch_add(1, std::memory_order_relaxed);
|
2020-03-18 21:46:55 +08:00
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
if (oldValue == sch)
|
|
|
|
|
{
|
2020-03-22 14:19:10 +08:00
|
|
|
|
_counter.fetch_add(1, std::memory_order_relaxed);
|
2020-03-18 18:36:39 +08:00
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool mutex_v2_impl::unlock(void* sch)
|
|
|
|
|
{
|
2020-03-22 00:50:54 +08:00
|
|
|
|
assert(sch != nullptr);
|
|
|
|
|
|
2020-03-18 18:36:39 +08:00
|
|
|
|
scoped_lock<lock_type> lock_(_lock);
|
|
|
|
|
|
2020-03-22 14:19:10 +08:00
|
|
|
|
void* oldValue = _owner.load(std::memory_order_relaxed);
|
2020-03-18 18:36:39 +08:00
|
|
|
|
if (oldValue == sch)
|
|
|
|
|
{
|
2020-03-22 14:19:10 +08:00
|
|
|
|
if (_counter.fetch_sub(1, std::memory_order_relaxed) == 1)
|
2020-03-18 18:36:39 +08:00
|
|
|
|
{
|
2020-03-22 14:19:10 +08:00
|
|
|
|
_owner.store(nullptr, std::memory_order_relaxed);
|
|
|
|
|
|
2020-03-20 01:04:52 +08:00
|
|
|
|
while (!_wait_awakes.empty())
|
2020-03-18 18:36:39 +08:00
|
|
|
|
{
|
|
|
|
|
state_mutex_ptr state = _wait_awakes.front();
|
|
|
|
|
_wait_awakes.pop_front();
|
|
|
|
|
|
2020-03-22 00:50:54 +08:00
|
|
|
|
//先将锁定状态转移到新的state上
|
|
|
|
|
_owner.store(state->get_root(), std::memory_order_release);
|
|
|
|
|
_counter.fetch_add(1, std::memory_order_acq_rel);
|
|
|
|
|
|
2020-03-20 01:04:52 +08:00
|
|
|
|
if (state->on_notify(this))
|
|
|
|
|
break;
|
2020-03-22 00:50:54 +08:00
|
|
|
|
|
|
|
|
|
//转移状态失败,恢复成空
|
2020-03-22 14:19:10 +08:00
|
|
|
|
_owner.store(nullptr, std::memory_order_relaxed);
|
|
|
|
|
_counter.fetch_sub(1, std::memory_order_relaxed);
|
2020-03-18 18:36:39 +08:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void mutex_v2_impl::add_wait_list_lockless(state_mutex_t* state)
|
|
|
|
|
{
|
|
|
|
|
assert(state != nullptr);
|
|
|
|
|
|
|
|
|
|
_wait_awakes.push_back(state);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2020-09-15 23:07:30 +08:00
|
|
|
|
mutex_t::mutex_t()
|
|
|
|
|
: _mutex(std::make_shared<detail::mutex_v2_impl>())
|
2020-03-18 18:36:39 +08:00
|
|
|
|
{
|
2020-09-15 23:07:30 +08:00
|
|
|
|
}
|
2020-03-18 18:36:39 +08:00
|
|
|
|
|
2020-09-15 23:07:30 +08:00
|
|
|
|
mutex_t::mutex_t(std::adopt_lock_t) noexcept
|
|
|
|
|
{
|
|
|
|
|
}
|
2020-03-18 18:36:39 +08:00
|
|
|
|
|
2020-09-15 23:07:30 +08:00
|
|
|
|
mutex_t::~mutex_t() noexcept
|
|
|
|
|
{
|
2020-03-18 18:36:39 +08:00
|
|
|
|
}
|
|
|
|
|
}
|