Chromium Code Reviews| Index: src/vm/event_handler_linux.cc |
| diff --git a/src/vm/event_handler_linux.cc b/src/vm/event_handler_linux.cc |
| index cad69ae3fcb60d0e35c365aec2f5df233b57e6fd..2392bd75e57fe1fda3868c33d94907b3fd8871fc 100644 |
| --- a/src/vm/event_handler_linux.cc |
| +++ b/src/vm/event_handler_linux.cc |
| @@ -7,11 +7,14 @@ |
| #include "src/vm/event_handler.h" |
| #include <sys/epoll.h> |
| +#include <sys/timerfd.h> |
| #include <sys/types.h> |
| #include <fcntl.h> |
| #include <unistd.h> |
| +#include "src/shared/utils.h" |
| #include "src/vm/thread.h" |
| +#include "src/vm/vector.h" |
| // Some versions of android sys/epoll does not define |
| // EPOLLRDHUP. However, it works as intended, so we just |
| @@ -31,24 +34,71 @@ int EventHandler::Create() { |
| void EventHandler::Run() { |
| struct epoll_event event; |
| - event.events = EPOLLHUP | EPOLLRDHUP; |
| + event.events = EPOLLHUP | EPOLLRDHUP | EPOLLIN; |
| event.data.fd = read_fd_; |
| epoll_ctl(fd_, EPOLL_CTL_ADD, read_fd_, &event); |
| while (true) { |
| - int status = epoll_wait(fd_, &event, 1, -1); |
| + int64 next_timeout; |
| + { |
| + ScopedMonitorLock locker(monitor_); |
| + next_timeout = next_timeout_; |
| + } |
| + |
| + if (next_timeout == INT64_MAX) { |
| + next_timeout = -1; |
| + } else { |
| + next_timeout -= Platform::GetMicroseconds() / 1000LL; |
| + if (next_timeout < 0) next_timeout = 0; |
| + } |
| + |
| + int status = epoll_wait(fd_, &event, 1, next_timeout); |
| + |
| + { |
| + // Check timeouts. |
| + int64 current_time = Platform::GetMicroseconds() / 1000LL; |
| + ScopedMonitorLock scoped_lock(monitor_); |
| + if (next_timeout_ <= current_time) { |
| + int64 next_timeout = INT64_MAX; |
| + // TODO(ajohnsen): We could consider a heap structure to avoid O(n^2) in |
| + // this case? |
| + while (true) { |
|
Mads Ager (google)
2015/10/01 14:08:37
Would this be easier to read if it was a do-while?
Anders Johnsen
2015/10/02 00:25:14
I need to reset found to false, so sadly not a rea
|
| + bool found = false; |
| + for (auto it = timeouts_.Begin(); it != timeouts_.End(); ++it) { |
| + if (it->second <= current_time) { |
| + Send(it->first, 0); |
| + timeouts_.Erase(it); |
| + found = true; |
| + break; |
| + } else { |
| + next_timeout = Utils::Minimum(next_timeout, it->second); |
| + } |
| + } |
| + if (!found) break; |
| + } |
| + next_timeout_ = next_timeout; |
| + } |
| + } |
| + |
| if (status != 1) continue; |
| + int events = event.events; |
| + |
| if (event.data.fd == read_fd_) { |
| - close(read_fd_); |
| - close(fd_); |
| + if ((events & EPOLLIN) != 0) { |
| + char b; |
| + read(read_fd_, &b, 1); |
| + continue; |
| + } else { |
| + close(read_fd_); |
| + close(fd_); |
| - ScopedMonitorLock locker(monitor_); |
| - fd_ = -1; |
| - monitor_->Notify(); |
| - return; |
| + ScopedMonitorLock locker(monitor_); |
| + fd_ = -1; |
| + monitor_->Notify(); |
| + return; |
| + } |
| } |
| - int events = event.events; |
| word mask = 0; |
| if ((events & EPOLLIN) != 0) mask |= READ_EVENT; |
| if ((events & EPOLLOUT) != 0) mask |= WRITE_EVENT; |