blob: 1d94612d6a0828a17f99c24c2fef04f90c51a862 [file] [log] [blame]
Vitaly Buka4615e0d2015-10-14 15:35:12 -07001// Copyright 2015 The Weave Authors. All rights reserved.
Vitaly Buka17b0a8a2015-08-31 19:12:35 -07002// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
Johan Euphrosine3523fdd2015-10-14 20:46:05 -07005#include "examples/provider/event_task_runner.h"
Vitaly Buka17b0a8a2015-08-31 19:12:35 -07006
7#include <signal.h>
8
9namespace weave {
10namespace examples {
11
12namespace {
13event_base* g_event_base = nullptr;
14}
15
16void EventTaskRunner::PostDelayedTask(
17 const tracked_objects::Location& from_here,
18 const base::Closure& task,
19 base::TimeDelta delay) {
20 base::Time new_time = base::Time::Now() + delay;
21 if (queue_.empty() || new_time < queue_.top().first.first) {
22 ReScheduleEvent(delay);
23 }
24 queue_.emplace(std::make_pair(new_time, ++counter_), task);
25}
26
ilewisf1fa93d2015-11-09 09:01:11 -080027void EventTaskRunner::AddIoCompletionTask(
28 int fd,
29 int16_t what,
30 const EventTaskRunner::IoCompletionCallback& task) {
31 int16_t flags = EV_PERSIST | EV_ET;
32 flags |= (what & kReadable) ? EV_READ : 0;
33 flags |= (what & kWriteable) ? EV_WRITE : 0;
34 flags |= (what & kClosed) ? EV_CLOSED : 0;
35 event* ioevent = event_new(base_.get(), fd, flags, FdEventHandler, this);
36 EventPtr<event> ioeventPtr{ioevent};
Vitaly Buka52d006a2015-11-21 17:14:51 -080037 fd_task_map_.insert(
38 std::make_pair(fd, std::make_pair(std::move(ioeventPtr), task)));
ilewisf1fa93d2015-11-09 09:01:11 -080039 event_add(ioevent, nullptr);
40}
41
42void EventTaskRunner::RemoveIoCompletionTask(int fd) {
43 fd_task_map_.erase(fd);
44}
45
Vitaly Buka17b0a8a2015-08-31 19:12:35 -070046void EventTaskRunner::Run() {
47 g_event_base = base_.get();
48
49 struct sigaction sa = {};
50 sa.sa_handler = [](int signal) {
51 event_base_loopexit(g_event_base, nullptr);
52 };
53 sigfillset(&sa.sa_mask);
54 sigaction(SIGINT, &sa, nullptr);
55
56 event_base_loop(g_event_base, EVLOOP_NO_EXIT_ON_EMPTY);
57 g_event_base = nullptr;
58}
59
60void EventTaskRunner::ReScheduleEvent(base::TimeDelta delay) {
61 timespec ts = delay.ToTimeSpec();
62 timeval tv = {ts.tv_sec, ts.tv_nsec / 1000};
63 event_add(task_event_.get(), &tv);
64}
65
ilewisf1fa93d2015-11-09 09:01:11 -080066void EventTaskRunner::EventHandler(int /* fd */,
67 int16_t /* what */,
68 void* runner) {
Vitaly Buka17b0a8a2015-08-31 19:12:35 -070069 static_cast<EventTaskRunner*>(runner)->Process();
70}
71
72void EventTaskRunner::FreeEvent(event* evnt) {
73 event_del(evnt);
74 event_free(evnt);
75}
76
77void EventTaskRunner::Process() {
78 while (!queue_.empty() && queue_.top().first.first <= base::Time::Now()) {
79 auto cb = queue_.top().second;
80 queue_.pop();
81 cb.Run();
82 }
83 if (!queue_.empty()) {
84 base::TimeDelta delta = std::max(
85 base::TimeDelta(), queue_.top().first.first - base::Time::Now());
86 ReScheduleEvent(delta);
87 }
88}
89
ilewisf1fa93d2015-11-09 09:01:11 -080090void EventTaskRunner::FdEventHandler(int fd, int16_t what, void* runner) {
91 static_cast<EventTaskRunner*>(runner)->ProcessFd(fd, what);
92}
93
94void EventTaskRunner::ProcessFd(int fd, int16_t what) {
95 auto it = fd_task_map_.find(fd);
96 if (it != fd_task_map_.end()) {
97 const IoCompletionCallback& callback = it->second.second;
98 callback.Run(fd, what, this);
99 }
100}
101
Vitaly Buka17b0a8a2015-08-31 19:12:35 -0700102} // namespace examples
103} // namespace weave