14615e0d5aa416ab1a8596bde68f71f7ebe431b86Vitaly Buka// Copyright 2015 The Weave Authors. All rights reserved. 217b0a8af760d75209e068d5e5479f6d849195ae5Vitaly Buka// Use of this source code is governed by a BSD-style license that can be 317b0a8af760d75209e068d5e5479f6d849195ae5Vitaly Buka// found in the LICENSE file. 417b0a8af760d75209e068d5e5479f6d849195ae5Vitaly Buka 53523fdd2a071c7b918761cf82f1ac0ff73188093Johan Euphrosine#include "examples/provider/event_task_runner.h" 617b0a8af760d75209e068d5e5479f6d849195ae5Vitaly Buka 717b0a8af760d75209e068d5e5479f6d849195ae5Vitaly Buka#include <signal.h> 817b0a8af760d75209e068d5e5479f6d849195ae5Vitaly Buka 917b0a8af760d75209e068d5e5479f6d849195ae5Vitaly Bukanamespace weave { 1017b0a8af760d75209e068d5e5479f6d849195ae5Vitaly Bukanamespace examples { 1117b0a8af760d75209e068d5e5479f6d849195ae5Vitaly Buka 1217b0a8af760d75209e068d5e5479f6d849195ae5Vitaly Bukanamespace { 1317b0a8af760d75209e068d5e5479f6d849195ae5Vitaly Bukaevent_base* g_event_base = nullptr; 1417b0a8af760d75209e068d5e5479f6d849195ae5Vitaly Buka} 1517b0a8af760d75209e068d5e5479f6d849195ae5Vitaly Buka 1617b0a8af760d75209e068d5e5479f6d849195ae5Vitaly Bukavoid EventTaskRunner::PostDelayedTask( 1717b0a8af760d75209e068d5e5479f6d849195ae5Vitaly Buka const tracked_objects::Location& from_here, 1817b0a8af760d75209e068d5e5479f6d849195ae5Vitaly Buka const base::Closure& task, 1917b0a8af760d75209e068d5e5479f6d849195ae5Vitaly Buka base::TimeDelta delay) { 2017b0a8af760d75209e068d5e5479f6d849195ae5Vitaly Buka base::Time new_time = base::Time::Now() + delay; 2117b0a8af760d75209e068d5e5479f6d849195ae5Vitaly Buka if (queue_.empty() || new_time < queue_.top().first.first) { 2217b0a8af760d75209e068d5e5479f6d849195ae5Vitaly Buka ReScheduleEvent(delay); 2317b0a8af760d75209e068d5e5479f6d849195ae5Vitaly Buka } 2417b0a8af760d75209e068d5e5479f6d849195ae5Vitaly Buka queue_.emplace(std::make_pair(new_time, ++counter_), task); 2517b0a8af760d75209e068d5e5479f6d849195ae5Vitaly Buka} 2617b0a8af760d75209e068d5e5479f6d849195ae5Vitaly Buka 27f1fa93dae92d1f4a2e264200ae3f085e19421293ilewisvoid EventTaskRunner::AddIoCompletionTask( 28f1fa93dae92d1f4a2e264200ae3f085e19421293ilewis int fd, 29f1fa93dae92d1f4a2e264200ae3f085e19421293ilewis int16_t what, 30f1fa93dae92d1f4a2e264200ae3f085e19421293ilewis const EventTaskRunner::IoCompletionCallback& task) { 31f1fa93dae92d1f4a2e264200ae3f085e19421293ilewis int16_t flags = EV_PERSIST | EV_ET; 32f1fa93dae92d1f4a2e264200ae3f085e19421293ilewis flags |= (what & kReadable) ? EV_READ : 0; 33f1fa93dae92d1f4a2e264200ae3f085e19421293ilewis flags |= (what & kWriteable) ? EV_WRITE : 0; 34331355869fb6f8e11427f35807b7c310ec7743caJacob Marble#if LIBEVENT_VERSION_NUMBER >= 0x02010400 35f1fa93dae92d1f4a2e264200ae3f085e19421293ilewis flags |= (what & kClosed) ? EV_CLOSED : 0; 36331355869fb6f8e11427f35807b7c310ec7743caJacob Marble#endif 37f1fa93dae92d1f4a2e264200ae3f085e19421293ilewis event* ioevent = event_new(base_.get(), fd, flags, FdEventHandler, this); 38f1fa93dae92d1f4a2e264200ae3f085e19421293ilewis EventPtr<event> ioeventPtr{ioevent}; 3952d006a131c61955e3a8a915d7f22941b3a4eee2Vitaly Buka fd_task_map_.insert( 4052d006a131c61955e3a8a915d7f22941b3a4eee2Vitaly Buka std::make_pair(fd, std::make_pair(std::move(ioeventPtr), task))); 41f1fa93dae92d1f4a2e264200ae3f085e19421293ilewis event_add(ioevent, nullptr); 42f1fa93dae92d1f4a2e264200ae3f085e19421293ilewis} 43f1fa93dae92d1f4a2e264200ae3f085e19421293ilewis 44f1fa93dae92d1f4a2e264200ae3f085e19421293ilewisvoid EventTaskRunner::RemoveIoCompletionTask(int fd) { 45f1fa93dae92d1f4a2e264200ae3f085e19421293ilewis fd_task_map_.erase(fd); 46f1fa93dae92d1f4a2e264200ae3f085e19421293ilewis} 47f1fa93dae92d1f4a2e264200ae3f085e19421293ilewis 4817b0a8af760d75209e068d5e5479f6d849195ae5Vitaly Bukavoid EventTaskRunner::Run() { 4917b0a8af760d75209e068d5e5479f6d849195ae5Vitaly Buka g_event_base = base_.get(); 5017b0a8af760d75209e068d5e5479f6d849195ae5Vitaly Buka 5117b0a8af760d75209e068d5e5479f6d849195ae5Vitaly Buka struct sigaction sa = {}; 5217b0a8af760d75209e068d5e5479f6d849195ae5Vitaly Buka sa.sa_handler = [](int signal) { 5317b0a8af760d75209e068d5e5479f6d849195ae5Vitaly Buka event_base_loopexit(g_event_base, nullptr); 5417b0a8af760d75209e068d5e5479f6d849195ae5Vitaly Buka }; 5517b0a8af760d75209e068d5e5479f6d849195ae5Vitaly Buka sigfillset(&sa.sa_mask); 5617b0a8af760d75209e068d5e5479f6d849195ae5Vitaly Buka sigaction(SIGINT, &sa, nullptr); 5717b0a8af760d75209e068d5e5479f6d849195ae5Vitaly Buka 58331355869fb6f8e11427f35807b7c310ec7743caJacob Marble do { 59331355869fb6f8e11427f35807b7c310ec7743caJacob Marble event_base_loop(g_event_base, EVLOOP_ONCE); 60331355869fb6f8e11427f35807b7c310ec7743caJacob Marble } while (!event_base_got_exit(g_event_base)); 6117b0a8af760d75209e068d5e5479f6d849195ae5Vitaly Buka g_event_base = nullptr; 6217b0a8af760d75209e068d5e5479f6d849195ae5Vitaly Buka} 6317b0a8af760d75209e068d5e5479f6d849195ae5Vitaly Buka 6417b0a8af760d75209e068d5e5479f6d849195ae5Vitaly Bukavoid EventTaskRunner::ReScheduleEvent(base::TimeDelta delay) { 6517b0a8af760d75209e068d5e5479f6d849195ae5Vitaly Buka timespec ts = delay.ToTimeSpec(); 6617b0a8af760d75209e068d5e5479f6d849195ae5Vitaly Buka timeval tv = {ts.tv_sec, ts.tv_nsec / 1000}; 6717b0a8af760d75209e068d5e5479f6d849195ae5Vitaly Buka event_add(task_event_.get(), &tv); 6817b0a8af760d75209e068d5e5479f6d849195ae5Vitaly Buka} 6917b0a8af760d75209e068d5e5479f6d849195ae5Vitaly Buka 70f1fa93dae92d1f4a2e264200ae3f085e19421293ilewisvoid EventTaskRunner::EventHandler(int /* fd */, 71f1fa93dae92d1f4a2e264200ae3f085e19421293ilewis int16_t /* what */, 72f1fa93dae92d1f4a2e264200ae3f085e19421293ilewis void* runner) { 7317b0a8af760d75209e068d5e5479f6d849195ae5Vitaly Buka static_cast<EventTaskRunner*>(runner)->Process(); 7417b0a8af760d75209e068d5e5479f6d849195ae5Vitaly Buka} 7517b0a8af760d75209e068d5e5479f6d849195ae5Vitaly Buka 7617b0a8af760d75209e068d5e5479f6d849195ae5Vitaly Bukavoid EventTaskRunner::FreeEvent(event* evnt) { 7717b0a8af760d75209e068d5e5479f6d849195ae5Vitaly Buka event_del(evnt); 7817b0a8af760d75209e068d5e5479f6d849195ae5Vitaly Buka event_free(evnt); 7917b0a8af760d75209e068d5e5479f6d849195ae5Vitaly Buka} 8017b0a8af760d75209e068d5e5479f6d849195ae5Vitaly Buka 8117b0a8af760d75209e068d5e5479f6d849195ae5Vitaly Bukavoid EventTaskRunner::Process() { 8217b0a8af760d75209e068d5e5479f6d849195ae5Vitaly Buka while (!queue_.empty() && queue_.top().first.first <= base::Time::Now()) { 8317b0a8af760d75209e068d5e5479f6d849195ae5Vitaly Buka auto cb = queue_.top().second; 8417b0a8af760d75209e068d5e5479f6d849195ae5Vitaly Buka queue_.pop(); 8517b0a8af760d75209e068d5e5479f6d849195ae5Vitaly Buka cb.Run(); 8617b0a8af760d75209e068d5e5479f6d849195ae5Vitaly Buka } 8717b0a8af760d75209e068d5e5479f6d849195ae5Vitaly Buka if (!queue_.empty()) { 8817b0a8af760d75209e068d5e5479f6d849195ae5Vitaly Buka base::TimeDelta delta = std::max( 8917b0a8af760d75209e068d5e5479f6d849195ae5Vitaly Buka base::TimeDelta(), queue_.top().first.first - base::Time::Now()); 9017b0a8af760d75209e068d5e5479f6d849195ae5Vitaly Buka ReScheduleEvent(delta); 9117b0a8af760d75209e068d5e5479f6d849195ae5Vitaly Buka } 9217b0a8af760d75209e068d5e5479f6d849195ae5Vitaly Buka} 9317b0a8af760d75209e068d5e5479f6d849195ae5Vitaly Buka 94f1fa93dae92d1f4a2e264200ae3f085e19421293ilewisvoid EventTaskRunner::FdEventHandler(int fd, int16_t what, void* runner) { 95f1fa93dae92d1f4a2e264200ae3f085e19421293ilewis static_cast<EventTaskRunner*>(runner)->ProcessFd(fd, what); 96f1fa93dae92d1f4a2e264200ae3f085e19421293ilewis} 97f1fa93dae92d1f4a2e264200ae3f085e19421293ilewis 98f1fa93dae92d1f4a2e264200ae3f085e19421293ilewisvoid EventTaskRunner::ProcessFd(int fd, int16_t what) { 99f1fa93dae92d1f4a2e264200ae3f085e19421293ilewis auto it = fd_task_map_.find(fd); 100f1fa93dae92d1f4a2e264200ae3f085e19421293ilewis if (it != fd_task_map_.end()) { 101f1fa93dae92d1f4a2e264200ae3f085e19421293ilewis const IoCompletionCallback& callback = it->second.second; 102f1fa93dae92d1f4a2e264200ae3f085e19421293ilewis callback.Run(fd, what, this); 103f1fa93dae92d1f4a2e264200ae3f085e19421293ilewis } 104f1fa93dae92d1f4a2e264200ae3f085e19421293ilewis} 105f1fa93dae92d1f4a2e264200ae3f085e19421293ilewis 10617b0a8af760d75209e068d5e5479f6d849195ae5Vitaly Buka} // namespace examples 10717b0a8af760d75209e068d5e5479f6d849195ae5Vitaly Buka} // namespace weave 108