Files
engine/fml/platform/linux/message_loop_linux.cc
T

94 lines
2.3 KiB
C++
Raw Normal View History

2018-11-07 12:24:35 -08:00
// Copyright 2013 The Flutter Authors. All rights reserved.
2017-03-20 14:49:10 -07:00
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "flutter/fml/platform/linux/message_loop_linux.h"
#include <sys/epoll.h>
#include <unistd.h>
#include "flutter/fml/eintr_wrapper.h"
2017-03-20 14:49:10 -07:00
#include "flutter/fml/platform/linux/timerfd.h"
namespace fml {
static constexpr int kClockType = CLOCK_MONOTONIC;
MessageLoopLinux::MessageLoopLinux()
: epoll_fd_(FML_HANDLE_EINTR(::epoll_create(1 /* unused */))),
2017-03-20 14:49:10 -07:00
timer_fd_(::timerfd_create(kClockType, TFD_NONBLOCK | TFD_CLOEXEC)),
running_(false) {
2018-05-18 15:43:49 -07:00
FML_CHECK(epoll_fd_.is_valid());
FML_CHECK(timer_fd_.is_valid());
2017-03-20 14:49:10 -07:00
bool added_source = AddOrRemoveTimerSource(true);
2018-05-18 15:43:49 -07:00
FML_CHECK(added_source);
2017-03-20 14:49:10 -07:00
}
MessageLoopLinux::~MessageLoopLinux() {
bool removed_source = AddOrRemoveTimerSource(false);
2018-05-18 15:43:49 -07:00
FML_CHECK(removed_source);
2017-03-20 14:49:10 -07:00
}
bool MessageLoopLinux::AddOrRemoveTimerSource(bool add) {
struct epoll_event event = {};
event.events = EPOLLIN;
// The data is just for informational purposes so we know when we were worken
// by the FD.
event.data.fd = timer_fd_.get();
int ctl_result =
::epoll_ctl(epoll_fd_.get(), add ? EPOLL_CTL_ADD : EPOLL_CTL_DEL,
timer_fd_.get(), &event);
return ctl_result == 0;
}
// |fml::MessageLoopImpl|
2017-03-20 14:49:10 -07:00
void MessageLoopLinux::Run() {
running_ = true;
while (running_) {
struct epoll_event event = {};
int epoll_result = FML_HANDLE_EINTR(
2017-03-20 14:49:10 -07:00
::epoll_wait(epoll_fd_.get(), &event, 1, -1 /* timeout */));
// Errors are fatal.
if (event.events & (EPOLLERR | EPOLLHUP)) {
running_ = false;
continue;
}
// Timeouts are fatal since we specified an infinite timeout already.
// Likewise, > 1 is not possible since we waited for one result.
if (epoll_result != 1) {
running_ = false;
continue;
}
if (event.data.fd == timer_fd_.get()) {
OnEventFired();
}
}
}
// |fml::MessageLoopImpl|
2017-03-20 14:49:10 -07:00
void MessageLoopLinux::Terminate() {
running_ = false;
2018-07-26 12:49:34 -07:00
WakeUp(fml::TimePoint::Now());
2017-03-20 14:49:10 -07:00
}
// |fml::MessageLoopImpl|
2018-07-26 12:49:34 -07:00
void MessageLoopLinux::WakeUp(fml::TimePoint time_point) {
2017-03-20 14:49:10 -07:00
bool result = TimerRearm(timer_fd_.get(), time_point);
2018-05-18 15:43:49 -07:00
FML_DCHECK(result);
2017-03-20 14:49:10 -07:00
}
void MessageLoopLinux::OnEventFired() {
if (TimerDrain(timer_fd_.get())) {
RunExpiredTasksNow();
}
}
} // namespace fml