if (oldValue != nullptr && _value.compare_exchange_strong(oldValue, nullptr, std::memory_order_acq_rel)) | if (oldValue != nullptr && _value.compare_exchange_strong(oldValue, nullptr, std::memory_order_acq_rel)) | ||||
{ | { | ||||
*oldValue = false; | *oldValue = false; | ||||
_thandler.stop(); | |||||
this->_coro = nullptr; | this->_coro = nullptr; | ||||
} | } | ||||
} | } | ||||
if (oldValue != nullptr && _value.compare_exchange_strong(oldValue, nullptr, std::memory_order_acq_rel)) | if (oldValue != nullptr && _value.compare_exchange_strong(oldValue, nullptr, std::memory_order_acq_rel)) | ||||
{ | { | ||||
*oldValue = true; | *oldValue = true; | ||||
_thandler.stop(); | |||||
assert(this->_scheduler != nullptr); | assert(this->_scheduler != nullptr); | ||||
if (this->_coro) | if (this->_coro) | ||||
if (oldValue != nullptr && _value.compare_exchange_strong(oldValue, nullptr, std::memory_order_acq_rel)) | if (oldValue != nullptr && _value.compare_exchange_strong(oldValue, nullptr, std::memory_order_acq_rel)) | ||||
{ | { | ||||
*oldValue = false; | *oldValue = false; | ||||
_thandler.reset(); | |||||
assert(this->_scheduler != nullptr); | assert(this->_scheduler != nullptr); | ||||
if (this->_coro) | if (this->_coro) |
timeout_awaiter wait_until_(const clock_type::time_point& tp) const noexcept; | timeout_awaiter wait_until_(const clock_type::time_point& tp) const noexcept; | ||||
}; | }; | ||||
} | } | ||||
template<class _Rep, class _Period> | |||||
auto wait_for(event_v2::event_t& e, const std::chrono::duration<_Rep, _Period>& dt) | |||||
{ | |||||
return e.wait_for(dt); | |||||
} | |||||
template<class _Clock, class _Duration> | |||||
auto wait_until(event_v2::event_t& e, const std::chrono::time_point<_Clock, _Duration>& tp) | |||||
{ | |||||
return e.wait_until(tp); | |||||
} | |||||
//when_all_for(dt, args...) -> when_all(wait_for(args, dt)...) | |||||
//就不再单独为每个支持超时的类提供when_all_for实现了。借助when_all和非成员的wait_for实现 | |||||
} | } |
//为浸入式单向链表提供的next指针 | //为浸入式单向链表提供的next指针 | ||||
counted_ptr<state_event_t> _next = nullptr; | counted_ptr<state_event_t> _next = nullptr; | ||||
timer_handler _thandler; | |||||
private: | private: | ||||
//_value引用awaitor保存的值,这样可以尽可能减少创建state的可能。而不必进入没有state就没有value实体被用于返回。 | //_value引用awaitor保存的值,这样可以尽可能减少创建state的可能。而不必进入没有state就没有value实体被用于返回。 | ||||
//在调用on_notify()或on_timeout()任意之一后,置为nullptr。 | //在调用on_notify()或on_timeout()任意之一后,置为nullptr。 | ||||
_event->add_wait_list(_state.get()); | _event->add_wait_list(_state.get()); | ||||
(void)sch->timer()->add(_tp, [_state=_state](bool canceld) | |||||
_state->_thandler = sch->timer()->add_handler(_tp, [_state=_state](bool canceld) | |||||
{ | { | ||||
if (!canceld) | if (!canceld) | ||||
_state->on_timeout(); | _state->on_timeout(); |
void timer_manager::clear() | void timer_manager::clear() | ||||
{ | { | ||||
std::unique_lock<spinlock> __lock(_added_mtx); | |||||
auto _atimer = std::move(_added_timers); | auto _atimer = std::move(_added_timers); | ||||
for (auto & sptr : _atimer) | |||||
__lock.unlock(); | |||||
for (auto& sptr : _atimer) | |||||
call_target_(sptr, true); | call_target_(sptr, true); | ||||
auto _rtimer = std::move(_runing_timers); | auto _rtimer = std::move(_runing_timers); | ||||
{ | { | ||||
assert(sptr); | assert(sptr); | ||||
assert(sptr->st == timer_target::State::Invalid); | assert(sptr->st == timer_target::State::Invalid); | ||||
scoped_lock<spinlock> __lock(_added_mtx); | |||||
#if _DEBUG | #if _DEBUG | ||||
assert(sptr->_manager == nullptr); | assert(sptr->_manager == nullptr); | ||||
sptr->_manager = this; | sptr->_manager = this; | ||||
void timer_manager::update() | void timer_manager::update() | ||||
{ | { | ||||
if (_added_timers.size() > 0) | |||||
{ | { | ||||
for (auto & sptr : _added_timers) | |||||
std::unique_lock<spinlock> __lock(_added_mtx); | |||||
if (_added_timers.size() > 0) | |||||
{ | { | ||||
if (sptr->st == timer_target::State::Added) | |||||
{ | |||||
sptr->st = timer_target::State::Runing; | |||||
_runing_timers.insert({ sptr->tp, sptr }); | |||||
} | |||||
else | |||||
auto _atimer = std::move(_added_timers); | |||||
_added_timers.reserve(128); | |||||
__lock.unlock(); | |||||
for (auto& sptr : _atimer) | |||||
{ | { | ||||
assert(sptr->st == timer_target::State::Invalid); | |||||
call_target_(sptr, true); | |||||
if (sptr->st == timer_target::State::Added) | |||||
{ | |||||
sptr->st = timer_target::State::Runing; | |||||
_runing_timers.insert({ sptr->tp, sptr }); | |||||
} | |||||
else | |||||
{ | |||||
assert(sptr->st == timer_target::State::Invalid); | |||||
call_target_(sptr, true); | |||||
} | |||||
} | } | ||||
} | } | ||||
_added_timers.clear(); | |||||
} | } | ||||
if (_runing_timers.size() > 0) | if (_runing_timers.size() > 0) | ||||
{ | { | ||||
auto now_ = clock_type::now(); | auto now_ = clock_type::now(); | ||||
timer_map_type _timers = std::move(_runing_timers); | |||||
auto iter = _timers.begin(); | |||||
for (; iter != _timers.end(); ++iter) | |||||
auto iter = _runing_timers.begin(); | |||||
for (; iter != _runing_timers.end(); ++iter) | |||||
{ | { | ||||
auto & kv = *iter; | auto & kv = *iter; | ||||
if (kv.first > now_) | if (kv.first > now_) | ||||
call_target_(kv.second, kv.second->st == timer_target::State::Invalid); | call_target_(kv.second, kv.second->st == timer_target::State::Invalid); | ||||
} | } | ||||
_timers.erase(_timers.begin(), iter); | |||||
_runing_timers = std::move(_timers); | |||||
_runing_timers.erase(_runing_timers.begin(), iter); | |||||
} | } | ||||
} | } | ||||
} | } |
typedef std::vector<timer_target_ptr> timer_vector_type; | typedef std::vector<timer_target_ptr> timer_vector_type; | ||||
typedef std::multimap<clock_type::time_point, timer_target_ptr> timer_map_type; | typedef std::multimap<clock_type::time_point, timer_target_ptr> timer_map_type; | ||||
protected: | protected: | ||||
spinlock _added_mtx; | |||||
timer_vector_type _added_timers; | timer_vector_type _added_timers; | ||||
public: | public: | ||||
timer_map_type _runing_timers; | timer_map_type _runing_timers; | ||||
inline bool empty() const | inline bool empty() const | ||||
{ | { | ||||
return _added_timers.empty() && _runing_timers.empty(); | |||||
return _runing_timers.empty() && _added_timers.empty(); | |||||
} | } | ||||
void clear(); | void clear(); | ||||
void update(); | void update(); |