1
0
mirror of https://github.com/tearshark/librf.git synced 2024-10-01 15:57:07 +08:00
librf/source/mutex_v2.cpp

199 lines
4.2 KiB
C++
Raw Normal View History

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
{
LIBRF_API 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();
}
}
LIBRF_API bool state_mutex_t::has_handler() const noexcept
2020-03-18 18:36:39 +08:00
{
return (bool)_coro;
}
LIBRF_API state_base_t* state_mutex_t::get_parent() const noexcept
2020-03-18 18:36:39 +08:00
{
return _root;
}
LIBRF_API 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;
}
}
LIBRF_API bool state_mutex_t::on_notify(mutex_v2_impl* eptr)
{
2020-03-22 00:50:54 +08:00
assert(eptr != nullptr);
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;
}
LIBRF_API 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;
}
LIBRF_API void state_mutex_t::add_timeout_timer(std::chrono::system_clock::time_point tp)
{
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();
});
}
LIBRF_API void mutex_v2_impl::lock_until_succeed(void* sch)
2020-03-18 18:36:39 +08:00
{
assert(sch != nullptr);
for (;;)
{
if (try_lock(sch))
break;
std::this_thread::yield();
}
}
LIBRF_API 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);
}
LIBRF_API 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);
do
{
if (try_lock(sch))
return true;
std::this_thread::yield();
} while (clock_type::now() <= tp);
return false;
}
LIBRF_API bool mutex_v2_impl::try_lock_lockless(void* sch) noexcept
2020-03-18 18:36:39 +08:00
{
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;
}
LIBRF_API bool mutex_v2_impl::unlock(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<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);
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);
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;
}
LIBRF_API void mutex_v2_impl::add_wait_list_lockless(state_mutex_t* state)
2020-03-18 18:36:39 +08:00
{
assert(state != nullptr);
_wait_awakes.push_back(state);
}
}
LIBRF_API mutex_t::mutex_t()
2020-09-15 23:07:30 +08:00
: _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
LIBRF_API mutex_t::mutex_t(std::adopt_lock_t) noexcept
2020-09-15 23:07:30 +08:00
{
}
2020-03-18 18:36:39 +08:00
LIBRF_API mutex_t::~mutex_t() noexcept
2020-09-15 23:07:30 +08:00
{
2020-03-18 18:36:39 +08:00
}
}