|
|
|
@ -1,5 +1,5 @@
|
|
|
|
|
#include <util/thread/timer.hpp>
|
|
|
|
|
|
|
|
|
|
#include <util/logging/logger.hpp>
|
|
|
|
|
#include <util/time.hpp>
|
|
|
|
|
|
|
|
|
|
#include <atomic>
|
|
|
|
@ -65,6 +65,9 @@ struct llarp_timer_context
|
|
|
|
|
absl::Duration nextTickLen = absl::Milliseconds(100);
|
|
|
|
|
|
|
|
|
|
llarp_time_t m_Now;
|
|
|
|
|
llarp_time_t m_NextRequiredTickAt =
|
|
|
|
|
std::numeric_limits< llarp_time_t >::max();
|
|
|
|
|
size_t m_NumPendingTimers;
|
|
|
|
|
|
|
|
|
|
llarp_timer_context()
|
|
|
|
|
{
|
|
|
|
@ -118,46 +121,52 @@ struct llarp_timer_context
|
|
|
|
|
const uint32_t id = ++currentId;
|
|
|
|
|
timers.emplace(
|
|
|
|
|
id, std::make_unique< llarp::timer >(m_Now, timeout_ms, user, func));
|
|
|
|
|
m_NextRequiredTickAt = std::min(m_NextRequiredTickAt, m_Now + timeout_ms);
|
|
|
|
|
m_NumPendingTimers = timers.size();
|
|
|
|
|
return id;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
uint32_t
|
|
|
|
|
call_func_later(std::function< void(void) > func, llarp_time_t timeout)
|
|
|
|
|
call_func_later(std::function< void(void) > func, llarp_time_t timeout_ms)
|
|
|
|
|
{
|
|
|
|
|
llarp::util::Lock lock(&timersMutex);
|
|
|
|
|
|
|
|
|
|
const uint32_t id = ++currentId;
|
|
|
|
|
timers.emplace(
|
|
|
|
|
id, std::make_unique< llarp::timer >(m_Now, timeout, nullptr, nullptr));
|
|
|
|
|
id,
|
|
|
|
|
std::make_unique< llarp::timer >(m_Now, timeout_ms, nullptr, nullptr));
|
|
|
|
|
timers[id]->deferredFunc = func;
|
|
|
|
|
m_NextRequiredTickAt = std::min(m_NextRequiredTickAt, m_Now + timeout_ms);
|
|
|
|
|
m_NumPendingTimers = timers.size();
|
|
|
|
|
return id;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
cancel_all() LOCKS_EXCLUDED(timersMutex)
|
|
|
|
|
{
|
|
|
|
|
std::list< uint32_t > ids;
|
|
|
|
|
|
|
|
|
|
{
|
|
|
|
|
llarp::util::Lock lock(&timersMutex);
|
|
|
|
|
|
|
|
|
|
for(auto& item : timers)
|
|
|
|
|
{
|
|
|
|
|
ids.push_back(item.first);
|
|
|
|
|
item.second->func = nullptr;
|
|
|
|
|
item.second->canceled = true;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for(auto id : ids)
|
|
|
|
|
{
|
|
|
|
|
cancel(id);
|
|
|
|
|
}
|
|
|
|
|
bool
|
|
|
|
|
ShouldTriggerTimers(llarp_time_t peekAhead) const
|
|
|
|
|
{
|
|
|
|
|
return m_NumPendingTimers > 0
|
|
|
|
|
and (m_Now + peekAhead) >= m_NextRequiredTickAt;
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
struct llarp_timer_context*
|
|
|
|
|
llarp_init_timer()
|
|
|
|
|
{
|
|
|
|
|
return new llarp_timer_context;
|
|
|
|
|
return new llarp_timer_context();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
uint32_t
|
|
|
|
@ -175,11 +184,9 @@ llarp_timer_call_func_later(struct llarp_timer_context* t, llarp_time_t timeout,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
llarp_free_timer(struct llarp_timer_context** t)
|
|
|
|
|
llarp_free_timer(struct llarp_timer_context* t)
|
|
|
|
|
{
|
|
|
|
|
if(*t)
|
|
|
|
|
delete *t;
|
|
|
|
|
*t = nullptr;
|
|
|
|
|
delete t;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
@ -191,6 +198,7 @@ llarp_timer_remove_job(struct llarp_timer_context* t, uint32_t id)
|
|
|
|
|
void
|
|
|
|
|
llarp_timer_stop(struct llarp_timer_context* t)
|
|
|
|
|
{
|
|
|
|
|
llarp::LogDebug("timers stopping");
|
|
|
|
|
// destroy all timers
|
|
|
|
|
// don't call callbacks on timers
|
|
|
|
|
{
|
|
|
|
@ -200,6 +208,7 @@ llarp_timer_stop(struct llarp_timer_context* t)
|
|
|
|
|
}
|
|
|
|
|
if(t->ticker)
|
|
|
|
|
t->ticker->SignalAll();
|
|
|
|
|
llarp::LogDebug("timers stopped");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
@ -236,31 +245,39 @@ llarp_timer_tick_all(struct llarp_timer_context* t)
|
|
|
|
|
itr = t->timers.erase(itr);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
++itr;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
for(const auto& h : hit)
|
|
|
|
|
while(not hit.empty())
|
|
|
|
|
{
|
|
|
|
|
const auto& h = hit.front();
|
|
|
|
|
h->called_at = t->m_Now;
|
|
|
|
|
h->exec();
|
|
|
|
|
hit.pop_front();
|
|
|
|
|
}
|
|
|
|
|
// reindex next tick info
|
|
|
|
|
{
|
|
|
|
|
if(h->func)
|
|
|
|
|
llarp::util::Lock lock(&t->timersMutex);
|
|
|
|
|
t->m_Now = llarp::time_now_ms();
|
|
|
|
|
t->m_NextRequiredTickAt = std::numeric_limits< llarp_time_t >::max();
|
|
|
|
|
for(const auto& item : t->timers)
|
|
|
|
|
{
|
|
|
|
|
h->called_at = t->m_Now;
|
|
|
|
|
h->exec();
|
|
|
|
|
t->m_NextRequiredTickAt =
|
|
|
|
|
std::min(t->m_NextRequiredTickAt, item.second->timeout + t->m_Now);
|
|
|
|
|
}
|
|
|
|
|
t->m_NumPendingTimers = t->timers.size();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
llarp_timer_tick_all_job(void* user)
|
|
|
|
|
{
|
|
|
|
|
llarp_timer_tick_all(static_cast< llarp_timer_context* >(user));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
llarp_timer_tick_all_async(struct llarp_timer_context* t,
|
|
|
|
|
struct llarp_threadpool* pool, llarp_time_t now)
|
|
|
|
|
{
|
|
|
|
|
t->m_Now = now;
|
|
|
|
|
llarp_threadpool_queue_job(pool, {t, llarp_timer_tick_all_job});
|
|
|
|
|
llarp_timer_set_time(t, now);
|
|
|
|
|
if(t->ShouldTriggerTimers(pool->GuessJobLatency()))
|
|
|
|
|
llarp_threadpool_queue_job(pool, std::bind(&llarp_timer_tick_all, t));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
@ -302,8 +319,9 @@ namespace llarp
|
|
|
|
|
else
|
|
|
|
|
call(user, timeout, diff);
|
|
|
|
|
}
|
|
|
|
|
if(deferredFunc)
|
|
|
|
|
if(deferredFunc && not canceled)
|
|
|
|
|
deferredFunc();
|
|
|
|
|
done = true;
|
|
|
|
|
deferredFunc = nullptr;
|
|
|
|
|
done = true;
|
|
|
|
|
}
|
|
|
|
|
} // namespace llarp
|
|
|
|
|