| OLD | NEW |
| 1 // Copyright (c) 2015, the Fletch project authors. Please see the AUTHORS file | 1 // Copyright (c) 2015, the Fletch project authors. Please see the AUTHORS file |
| 2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
| 3 // BSD-style license that can be found in the LICENSE.md file. | 3 // BSD-style license that can be found in the LICENSE.md file. |
| 4 | 4 |
| 5 #if defined(FLETCH_TARGET_OS_POSIX) | 5 #if defined(FLETCH_TARGET_OS_POSIX) |
| 6 | 6 |
| 7 #include "src/vm/event_handler.h" | 7 #include "src/vm/event_handler.h" |
| 8 | 8 |
| 9 #include <fcntl.h> | 9 #include <fcntl.h> |
| 10 #include <unistd.h> | 10 #include <unistd.h> |
| 11 | 11 |
| 12 #include "src/shared/flags.h" | 12 #include "src/shared/flags.h" |
| 13 | 13 |
| 14 #include "src/vm/object.h" | 14 #include "src/vm/object.h" |
| 15 #include "src/vm/port.h" | 15 #include "src/vm/port.h" |
| 16 #include "src/vm/process.h" | 16 #include "src/vm/process.h" |
| 17 #include "src/vm/scheduler.h" | 17 #include "src/vm/scheduler.h" |
| 18 #include "src/vm/thread.h" | 18 #include "src/vm/thread.h" |
| 19 | 19 |
| 20 namespace fletch { | 20 namespace fletch { |
| 21 | 21 |
| 22 EventHandler::EventHandler() | 22 EventHandler::EventHandler() |
| 23 : monitor_(Platform::CreateMonitor()), | 23 : monitor_(Platform::CreateMonitor()), |
| 24 fd_(-1), | 24 fd_(-1), |
| 25 next_timeout_(INT64_MAX), |
| 25 read_fd_(-1), | 26 read_fd_(-1), |
| 26 write_fd_(-1) { | 27 write_fd_(-1) { |
| 27 } | 28 } |
| 28 | 29 |
| 29 EventHandler::~EventHandler() { | 30 EventHandler::~EventHandler() { |
| 30 if (fd_ != -1) { | 31 if (fd_ != -1) { |
| 31 // TODO(runtime-developers): This is pretty nasty, inside the destructor we | 32 // TODO(runtime-developers): This is pretty nasty, inside the destructor we |
| 32 // notify the other thread (via close()) to shut down. The other thread will | 33 // notify the other thread (via close()) to shut down. The other thread will |
| 33 // then access members of the [EventHandler] object which is in the middle | 34 // then access members of the [EventHandler] object which is in the middle |
| 34 // of destruction. | 35 // of destruction. |
| (...skipping 26 matching lines...) Expand all Loading... |
| 61 int status = fcntl(fds[0], F_SETFD, FD_CLOEXEC); | 62 int status = fcntl(fds[0], F_SETFD, FD_CLOEXEC); |
| 62 if (status == -1) FATAL("Failed making read pipe close on exec."); | 63 if (status == -1) FATAL("Failed making read pipe close on exec."); |
| 63 status = fcntl(fds[1], F_SETFD, FD_CLOEXEC); | 64 status = fcntl(fds[1], F_SETFD, FD_CLOEXEC); |
| 64 if (status == -1) FATAL("Failed making write pipe close on exec."); | 65 if (status == -1) FATAL("Failed making write pipe close on exec."); |
| 65 read_fd_ = fds[0]; | 66 read_fd_ = fds[0]; |
| 66 write_fd_ = fds[1]; | 67 write_fd_ = fds[1]; |
| 67 thread_ = Thread::Run(RunEventHandler, reinterpret_cast<void*>(this)); | 68 thread_ = Thread::Run(RunEventHandler, reinterpret_cast<void*>(this)); |
| 68 return fd_; | 69 return fd_; |
| 69 } | 70 } |
| 70 | 71 |
| 72 void EventHandler::ScheduleTimeout(int64 timeout, Port* port) { |
| 73 ASSERT(timeout != INT64_MAX); |
| 74 |
| 75 // Be sure it's running. |
| 76 GetEventHandler(); |
| 77 |
| 78 ScopedMonitorLock scoped_lock(monitor_); |
| 79 |
| 80 auto it = timeouts_.Find(port); |
| 81 if (it == timeouts_.End()) { |
| 82 if (timeout == -1) return; |
| 83 timeouts_[port] = timeout; |
| 84 next_timeout_ = Utils::Minimum(next_timeout_, timeout); |
| 85 // Be sure to mark the port as referenced. |
| 86 port->IncrementRef(); |
| 87 } else if (timeout == -1) { |
| 88 timeouts_.Erase(it); |
| 89 // TODO(ajohnsen): We could consider a heap structure to avoid O(n) in this |
| 90 // case? |
| 91 int64 next_timeout = INT64_MAX; |
| 92 for (auto it = timeouts_.Begin(); it != timeouts_.End(); ++it) { |
| 93 next_timeout = Utils::Minimum(next_timeout, it->second); |
| 94 } |
| 95 next_timeout_ = next_timeout; |
| 96 // The port is no longer "referenced" by the event manager. |
| 97 port->DecrementRef(); |
| 98 } else { |
| 99 timeouts_[port] = timeout; |
| 100 next_timeout_ = Utils::Minimum(next_timeout_, timeout); |
| 101 } |
| 102 char b = 0; |
| 103 write(write_fd_, &b, 1); |
| 104 } |
| 105 |
| 106 void EventHandler::HandleTimeouts() { |
| 107 // Check timeouts. |
| 108 int64 current_time = Platform::GetMicroseconds() / 1000; |
| 109 |
| 110 ScopedMonitorLock scoped_lock(monitor_); |
| 111 if (next_timeout_ > current_time) return; |
| 112 |
| 113 int64 next_timeout = INT64_MAX; |
| 114 |
| 115 // TODO(ajohnsen): We could consider a heap structure to avoid O(n^2) in |
| 116 // this case? |
| 117 // The following is O(n^2), because we can't continue iterating a hash-map |
| 118 // once we have removed from it. |
| 119 while (true) { |
| 120 bool found = false; |
| 121 for (auto it = timeouts_.Begin(); it != timeouts_.End(); ++it) { |
| 122 if (it->second <= current_time) { |
| 123 Send(it->first, 0); |
| 124 timeouts_.Erase(it); |
| 125 found = true; |
| 126 break; |
| 127 } else { |
| 128 next_timeout = Utils::Minimum(next_timeout, it->second); |
| 129 } |
| 130 } |
| 131 if (!found) break; |
| 132 } |
| 133 |
| 134 next_timeout_ = next_timeout; |
| 135 } |
| 136 |
| 71 void EventHandler::Send(Port* port, uword mask) { | 137 void EventHandler::Send(Port* port, uword mask) { |
| 72 Object* message = Smi::FromWord(mask); | 138 Object* message = Smi::FromWord(mask); |
| 73 port->Lock(); | 139 port->Lock(); |
| 74 Process* port_process = port->process(); | 140 Process* port_process = port->process(); |
| 75 if (port_process != NULL) { | 141 if (port_process != NULL) { |
| 76 port_process->mailbox()->Enqueue(port, message); | 142 port_process->mailbox()->Enqueue(port, message); |
| 77 port_process->program()->scheduler()->ResumeProcess(port_process); | 143 port_process->program()->scheduler()->ResumeProcess(port_process); |
| 78 } | 144 } |
| 79 port->Unlock(); | 145 port->Unlock(); |
| 80 port->DecrementRef(); | 146 port->DecrementRef(); |
| 81 } | 147 } |
| 82 | 148 |
| 83 } // namespace fletch | 149 } // namespace fletch |
| 84 | 150 |
| 85 #endif // FLETCH_TARGET_OS_POSIX | 151 #endif // FLETCH_TARGET_OS_POSIX |
| OLD | NEW |