2021-11-01 17:59:08 +08:00
|
|
|
|
#include "librf/librf.h"
|
2020-03-04 11:23:10 +08:00
|
|
|
|
|
2021-11-01 17:59:08 +08:00
|
|
|
|
namespace librf
|
2020-03-04 11:23:10 +08:00
|
|
|
|
{
|
|
|
|
|
namespace detail
|
|
|
|
|
{
|
2020-03-17 18:26:22 +08:00
|
|
|
|
void state_event_base_t::resume()
|
2020-03-04 11:23:10 +08:00
|
|
|
|
{
|
2020-03-10 21:31:05 +08:00
|
|
|
|
coroutine_handle<> handler = _coro;
|
|
|
|
|
if (handler)
|
2020-03-04 11:23:10 +08:00
|
|
|
|
{
|
2020-03-10 21:31:05 +08:00
|
|
|
|
_coro = nullptr;
|
|
|
|
|
_scheduler->del_final(this);
|
|
|
|
|
handler.resume();
|
2020-03-04 11:23:10 +08:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2020-03-17 18:26:22 +08:00
|
|
|
|
bool state_event_base_t::has_handler() const noexcept
|
2020-03-04 11:23:10 +08:00
|
|
|
|
{
|
2020-03-10 21:31:05 +08:00
|
|
|
|
return (bool)_coro;
|
2020-03-04 11:23:10 +08:00
|
|
|
|
}
|
|
|
|
|
|
2020-03-10 22:34:50 +08:00
|
|
|
|
void state_event_t::on_cancel() noexcept
|
2020-03-04 11:23:10 +08:00
|
|
|
|
{
|
2020-03-17 01:40:42 +08:00
|
|
|
|
event_v2_impl** oldValue = _value.load(std::memory_order_acquire);
|
2020-03-10 22:58:06 +08:00
|
|
|
|
if (oldValue != nullptr && _value.compare_exchange_strong(oldValue, nullptr, std::memory_order_acq_rel))
|
2020-03-10 22:34:50 +08:00
|
|
|
|
{
|
2020-03-17 01:40:42 +08:00
|
|
|
|
*oldValue = nullptr;
|
2020-03-10 23:38:06 +08:00
|
|
|
|
_thandler.stop();
|
|
|
|
|
|
2020-03-10 22:51:44 +08:00
|
|
|
|
this->_coro = nullptr;
|
2020-03-10 22:34:50 +08:00
|
|
|
|
}
|
2020-03-10 21:31:05 +08:00
|
|
|
|
}
|
2020-03-04 11:23:10 +08:00
|
|
|
|
|
2020-03-17 01:40:42 +08:00
|
|
|
|
bool state_event_t::on_notify(event_v2_impl* eptr)
|
2020-03-10 21:31:05 +08:00
|
|
|
|
{
|
2020-03-17 01:40:42 +08:00
|
|
|
|
event_v2_impl** oldValue = _value.load(std::memory_order_acquire);
|
2020-03-10 22:58:06 +08:00
|
|
|
|
if (oldValue != nullptr && _value.compare_exchange_strong(oldValue, nullptr, std::memory_order_acq_rel))
|
2020-03-10 22:34:50 +08:00
|
|
|
|
{
|
2020-03-17 01:40:42 +08:00
|
|
|
|
*oldValue = eptr;
|
2020-03-10 23:38:06 +08:00
|
|
|
|
_thandler.stop();
|
2020-03-10 22:34:50 +08:00
|
|
|
|
|
|
|
|
|
assert(this->_scheduler != nullptr);
|
|
|
|
|
if (this->_coro)
|
|
|
|
|
this->_scheduler->add_generator(this);
|
|
|
|
|
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool state_event_t::on_timeout()
|
|
|
|
|
{
|
2020-03-17 01:40:42 +08:00
|
|
|
|
event_v2_impl** oldValue = _value.load(std::memory_order_acquire);
|
2020-03-10 22:58:06 +08:00
|
|
|
|
if (oldValue != nullptr && _value.compare_exchange_strong(oldValue, nullptr, std::memory_order_acq_rel))
|
2020-03-10 22:34:50 +08:00
|
|
|
|
{
|
2020-03-17 01:40:42 +08:00
|
|
|
|
*oldValue = nullptr;
|
2020-03-10 23:38:06 +08:00
|
|
|
|
_thandler.reset();
|
2020-03-10 22:34:50 +08:00
|
|
|
|
|
|
|
|
|
assert(this->_scheduler != nullptr);
|
|
|
|
|
if (this->_coro)
|
|
|
|
|
this->_scheduler->add_generator(this);
|
|
|
|
|
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
2020-03-17 18:26:22 +08:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void state_event_all_t::on_cancel() noexcept
|
|
|
|
|
{
|
|
|
|
|
intptr_t oldValue = _counter.load(std::memory_order_acquire);
|
|
|
|
|
if (oldValue >= 0 && _counter.compare_exchange_strong(oldValue, -1, std::memory_order_acq_rel))
|
|
|
|
|
{
|
|
|
|
|
*_value = false;
|
|
|
|
|
_thandler.stop();
|
|
|
|
|
|
|
|
|
|
this->_coro = nullptr;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool state_event_all_t::on_notify(event_v2_impl*)
|
|
|
|
|
{
|
|
|
|
|
intptr_t oldValue = _counter.load(std::memory_order_acquire);
|
|
|
|
|
if (oldValue <= 0) return false;
|
|
|
|
|
|
|
|
|
|
oldValue = _counter.fetch_add(-1, std::memory_order_acq_rel);
|
|
|
|
|
if (oldValue == 1)
|
|
|
|
|
{
|
|
|
|
|
*_value = true;
|
|
|
|
|
_thandler.stop();
|
|
|
|
|
|
|
|
|
|
assert(this->_scheduler != nullptr);
|
|
|
|
|
if (this->_coro)
|
|
|
|
|
this->_scheduler->add_generator(this);
|
|
|
|
|
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return oldValue >= 1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool state_event_all_t::on_timeout()
|
|
|
|
|
{
|
|
|
|
|
intptr_t oldValue = _counter.load(std::memory_order_acquire);
|
|
|
|
|
if (oldValue >= 0 && _counter.compare_exchange_strong(oldValue, -1, std::memory_order_acq_rel))
|
|
|
|
|
{
|
|
|
|
|
*_value = false;
|
|
|
|
|
_thandler.reset();
|
|
|
|
|
|
|
|
|
|
assert(this->_scheduler != nullptr);
|
|
|
|
|
if (this->_coro)
|
|
|
|
|
this->_scheduler->add_generator(this);
|
|
|
|
|
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2020-03-10 22:34:50 +08:00
|
|
|
|
event_v2_impl::event_v2_impl(bool initially) noexcept
|
|
|
|
|
: _counter(initially ? 1 : 0)
|
|
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
2020-03-15 21:59:53 +08:00
|
|
|
|
template<class _Ty, class _Ptr>
|
|
|
|
|
static auto try_pop_list(intrusive_link_queue<_Ty, _Ptr>& list)
|
|
|
|
|
{
|
|
|
|
|
return list.try_pop();
|
|
|
|
|
}
|
|
|
|
|
template<class _Ptr>
|
|
|
|
|
static _Ptr try_pop_list(std::list<_Ptr>& list)
|
|
|
|
|
{
|
|
|
|
|
if (!list.empty())
|
|
|
|
|
{
|
|
|
|
|
_Ptr ptr = list.front();
|
|
|
|
|
list.pop_front();
|
|
|
|
|
return ptr;
|
|
|
|
|
}
|
|
|
|
|
return nullptr;
|
|
|
|
|
}
|
|
|
|
|
template<class _Ty, class _Ptr>
|
|
|
|
|
static void clear_list(intrusive_link_queue<_Ty, _Ptr>& list)
|
|
|
|
|
{
|
|
|
|
|
for (; list.try_pop() != nullptr;);
|
|
|
|
|
}
|
|
|
|
|
template<class _Ptr>
|
|
|
|
|
static void clear_list(std::list<_Ptr>& list)
|
|
|
|
|
{
|
|
|
|
|
list.clear();
|
|
|
|
|
}
|
|
|
|
|
|
2020-03-10 22:34:50 +08:00
|
|
|
|
event_v2_impl::~event_v2_impl()
|
|
|
|
|
{
|
2020-03-15 21:59:53 +08:00
|
|
|
|
clear_list(_wait_awakes);
|
2020-03-04 11:23:10 +08:00
|
|
|
|
}
|
|
|
|
|
|
2020-03-10 21:31:05 +08:00
|
|
|
|
void event_v2_impl::signal_all() noexcept
|
2020-03-04 11:23:10 +08:00
|
|
|
|
{
|
2020-03-10 21:31:05 +08:00
|
|
|
|
scoped_lock<lock_type> lock_(_lock);
|
|
|
|
|
|
|
|
|
|
_counter.store(0, std::memory_order_release);
|
|
|
|
|
|
2020-03-16 18:12:57 +08:00
|
|
|
|
state_event_ptr state;
|
2020-03-15 21:59:53 +08:00
|
|
|
|
for (; (state = try_pop_list(_wait_awakes)) != nullptr;)
|
2020-03-04 11:23:10 +08:00
|
|
|
|
{
|
2020-03-17 01:40:42 +08:00
|
|
|
|
(void)state->on_notify(this);
|
2020-03-04 11:23:10 +08:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2020-03-10 21:31:05 +08:00
|
|
|
|
void event_v2_impl::signal() noexcept
|
2020-03-04 11:23:10 +08:00
|
|
|
|
{
|
2020-03-10 21:31:05 +08:00
|
|
|
|
scoped_lock<lock_type> lock_(_lock);
|
|
|
|
|
|
2020-03-16 18:12:57 +08:00
|
|
|
|
state_event_ptr state;
|
2020-03-15 21:59:53 +08:00
|
|
|
|
for (; (state = try_pop_list(_wait_awakes)) != nullptr;)
|
2020-03-10 22:34:50 +08:00
|
|
|
|
{
|
2020-03-17 01:40:42 +08:00
|
|
|
|
if (state->on_notify(this))
|
2020-03-10 22:34:50 +08:00
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
_counter.fetch_add(1, std::memory_order_acq_rel);
|
2020-03-04 11:23:10 +08:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2020-09-15 23:07:30 +08:00
|
|
|
|
event_t::event_t(bool initially)
|
|
|
|
|
:_event(std::make_shared<detail::event_v2_impl>(initially))
|
2020-03-04 11:23:10 +08:00
|
|
|
|
{
|
2020-09-15 23:07:30 +08:00
|
|
|
|
}
|
2020-03-04 11:23:10 +08:00
|
|
|
|
|
2020-09-15 23:07:30 +08:00
|
|
|
|
event_t::event_t(std::adopt_lock_t)
|
|
|
|
|
{
|
|
|
|
|
}
|
2020-03-17 01:40:42 +08:00
|
|
|
|
|
2020-09-15 23:07:30 +08:00
|
|
|
|
event_t::~event_t()
|
|
|
|
|
{
|
2020-03-04 11:23:10 +08:00
|
|
|
|
}
|
|
|
|
|
}
|