#include "librf/librf.h" namespace librf { LIBRF_API timer_manager::timer_manager() { _added_timers.reserve(128); } LIBRF_API timer_manager::~timer_manager() { clear(); } LIBRF_API void timer_manager::call_target_(const timer_target_ptr & sptr, bool canceld) { auto cb = std::move(sptr->cb); sptr->st = timer_target::State::Invalid; #if _DEBUG sptr->_manager = nullptr; #endif if(cb) cb(canceld); } LIBRF_API void timer_manager::clear() { #if !RESUMEF_DISABLE_MULT_THREAD std::unique_lock __lock(_added_mtx); #endif auto _atimer = std::move(_added_timers); #if !RESUMEF_DISABLE_MULT_THREAD __lock.unlock(); #endif for (auto& sptr : _atimer) call_target_(sptr, true); auto _rtimer = std::move(_runing_timers); for (auto & kv : _rtimer) call_target_(kv.second, true); } LIBRF_API detail::timer_target_ptr timer_manager::add_(const timer_target_ptr & sptr) { assert(sptr); assert(sptr->st == timer_target::State::Invalid); #if !RESUMEF_DISABLE_MULT_THREAD scoped_lock __lock(_added_mtx); #endif #if _DEBUG assert(sptr->_manager == nullptr); sptr->_manager = this; #endif sptr->st = timer_target::State::Added; _added_timers.push_back(sptr); return sptr; } LIBRF_API bool timer_manager::stop(const timer_target_ptr & sptr) { if (!sptr || sptr->st == timer_target::State::Invalid) return false; #if _DEBUG assert(sptr->_manager == this); #endif sptr->st = timer_target::State::Invalid; return true; } LIBRF_API void timer_manager::update() { { #if !RESUMEF_DISABLE_MULT_THREAD std::unique_lock __lock(_added_mtx); #endif if (unlikely(_added_timers.size() > 0)) { auto _atimer = std::move(_added_timers); _added_timers.reserve(128); #if !RESUMEF_DISABLE_MULT_THREAD __lock.unlock(); #endif for (auto& sptr : _atimer) { 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); } } } } if (unlikely(_runing_timers.size() > 0)) { auto now_ = clock_type::now(); auto iter = _runing_timers.begin(); for (; iter != _runing_timers.end(); ++iter) { auto & kv = *iter; if (kv.first > now_) break; call_target_(kv.second, kv.second->st == timer_target::State::Invalid); } _runing_timers.erase(_runing_timers.begin(), iter); } } }