blob: b781ff44d573b8a3e3057f0d227b86b86b48bf67 [file] [log] [blame] [edit]
// Copyright 2015 The Weave Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "examples/ubuntu/event_task_runner.h"
#include <signal.h>
namespace weave {
namespace examples {
namespace {
event_base* g_event_base = nullptr;
}
void EventTaskRunner::PostDelayedTask(
const tracked_objects::Location& from_here,
const base::Closure& task,
base::TimeDelta delay) {
base::Time new_time = base::Time::Now() + delay;
if (queue_.empty() || new_time < queue_.top().first.first) {
ReScheduleEvent(delay);
}
queue_.emplace(std::make_pair(new_time, ++counter_), task);
}
void EventTaskRunner::Run() {
g_event_base = base_.get();
struct sigaction sa = {};
sa.sa_handler = [](int signal) {
event_base_loopexit(g_event_base, nullptr);
};
sigfillset(&sa.sa_mask);
sigaction(SIGINT, &sa, nullptr);
event_base_loop(g_event_base, EVLOOP_NO_EXIT_ON_EMPTY);
g_event_base = nullptr;
}
void EventTaskRunner::ReScheduleEvent(base::TimeDelta delay) {
timespec ts = delay.ToTimeSpec();
timeval tv = {ts.tv_sec, ts.tv_nsec / 1000};
event_add(task_event_.get(), &tv);
}
void EventTaskRunner::EventHandler(int, int16_t, void* runner) {
static_cast<EventTaskRunner*>(runner)->Process();
}
void EventTaskRunner::FreeEvent(event* evnt) {
event_del(evnt);
event_free(evnt);
}
void EventTaskRunner::Process() {
while (!queue_.empty() && queue_.top().first.first <= base::Time::Now()) {
auto cb = queue_.top().second;
queue_.pop();
cb.Run();
}
if (!queue_.empty()) {
base::TimeDelta delta = std::max(
base::TimeDelta(), queue_.top().first.first - base::Time::Now());
ReScheduleEvent(delta);
}
}
} // namespace examples
} // namespace weave