| OLD | NEW |
| 1 // Copyright 2013 The Chromium Authors. All rights reserved. | 1 // Copyright 2013 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "mojo/message_pump/message_pump_mojo.h" | 5 #include "mojo/message_pump/message_pump_mojo.h" |
| 6 | 6 |
| 7 #include <stdint.h> | 7 #include <stdint.h> |
| 8 | 8 |
| 9 #include <algorithm> | 9 #include <algorithm> |
| 10 #include <map> |
| 10 #include <vector> | 11 #include <vector> |
| 11 | 12 |
| 13 #include "base/containers/small_map.h" |
| 12 #include "base/debug/alias.h" | 14 #include "base/debug/alias.h" |
| 13 #include "base/lazy_instance.h" | 15 #include "base/lazy_instance.h" |
| 14 #include "base/logging.h" | 16 #include "base/logging.h" |
| 15 #include "base/threading/thread_local.h" | 17 #include "base/threading/thread_local.h" |
| 16 #include "base/time/time.h" | 18 #include "base/time/time.h" |
| 17 #include "mojo/message_pump/message_pump_mojo_handler.h" | 19 #include "mojo/message_pump/message_pump_mojo_handler.h" |
| 18 #include "mojo/message_pump/time_helper.h" | 20 #include "mojo/message_pump/time_helper.h" |
| 21 #include "mojo/public/c/system/wait_set.h" |
| 19 | 22 |
| 20 namespace mojo { | 23 namespace mojo { |
| 21 namespace common { | 24 namespace common { |
| 22 namespace { | 25 namespace { |
| 23 | 26 |
| 24 base::LazyInstance<base::ThreadLocalPointer<MessagePumpMojo> >::Leaky | 27 base::LazyInstance<base::ThreadLocalPointer<MessagePumpMojo> >::Leaky |
| 25 g_tls_current_pump = LAZY_INSTANCE_INITIALIZER; | 28 g_tls_current_pump = LAZY_INSTANCE_INITIALIZER; |
| 26 | 29 |
| 27 MojoDeadline TimeTicksToMojoDeadline(base::TimeTicks time_ticks, | 30 MojoDeadline TimeTicksToMojoDeadline(base::TimeTicks time_ticks, |
| 28 base::TimeTicks now) { | 31 base::TimeTicks now) { |
| 29 // The is_null() check matches that of HandleWatcher as well as how | 32 // The is_null() check matches that of HandleWatcher as well as how |
| 30 // |delayed_work_time| is used. | 33 // |delayed_work_time| is used. |
| 31 if (time_ticks.is_null()) | 34 if (time_ticks.is_null()) |
| 32 return MOJO_DEADLINE_INDEFINITE; | 35 return MOJO_DEADLINE_INDEFINITE; |
| 33 const int64_t delta = (time_ticks - now).InMicroseconds(); | 36 const int64_t delta = (time_ticks - now).InMicroseconds(); |
| 34 return delta < 0 ? static_cast<MojoDeadline>(0) : | 37 return delta < 0 ? static_cast<MojoDeadline>(0) : |
| 35 static_cast<MojoDeadline>(delta); | 38 static_cast<MojoDeadline>(delta); |
| 36 } | 39 } |
| 37 | 40 |
| 38 } // namespace | 41 } // namespace |
| 39 | 42 |
| 40 // State needed for one iteration of WaitMany. The first handle and flags | |
| 41 // corresponds to that of the control pipe. | |
| 42 struct MessagePumpMojo::WaitState { | |
| 43 std::vector<Handle> handles; | |
| 44 std::vector<MojoHandleSignals> wait_signals; | |
| 45 }; | |
| 46 | |
| 47 struct MessagePumpMojo::RunState { | 43 struct MessagePumpMojo::RunState { |
| 48 RunState() : should_quit(false) {} | 44 RunState() : should_quit(false) {} |
| 49 | 45 |
| 50 base::TimeTicks delayed_work_time; | 46 base::TimeTicks delayed_work_time; |
| 51 | 47 |
| 52 bool should_quit; | 48 bool should_quit; |
| 53 }; | 49 }; |
| 54 | 50 |
| 55 MessagePumpMojo::MessagePumpMojo() : run_state_(NULL), next_handler_id_(0) { | 51 MessagePumpMojo::MessagePumpMojo() : run_state_(NULL), next_handler_id_(0) { |
| 56 DCHECK(!current()) | 52 DCHECK(!current()) |
| 57 << "There is already a MessagePumpMojo instance on this thread."; | 53 << "There is already a MessagePumpMojo instance on this thread."; |
| 58 g_tls_current_pump.Pointer()->Set(this); | 54 g_tls_current_pump.Pointer()->Set(this); |
| 59 | 55 |
| 60 MojoResult result = CreateMessagePipe(nullptr, &read_handle_, &write_handle_); | 56 MojoResult result = CreateMessagePipe(nullptr, &read_handle_, &write_handle_); |
| 61 CHECK_EQ(result, MOJO_RESULT_OK); | 57 CHECK_EQ(result, MOJO_RESULT_OK); |
| 62 CHECK(read_handle_.is_valid()); | 58 CHECK(read_handle_.is_valid()); |
| 63 CHECK(write_handle_.is_valid()); | 59 CHECK(write_handle_.is_valid()); |
| 60 |
| 61 MojoHandle handle; |
| 62 result = MojoCreateWaitSet(&handle); |
| 63 CHECK_EQ(result, MOJO_RESULT_OK); |
| 64 wait_set_handle_.reset(Handle(handle)); |
| 65 CHECK(wait_set_handle_.is_valid()); |
| 66 |
| 67 result = |
| 68 MojoAddHandle(wait_set_handle_.get().value(), read_handle_.get().value(), |
| 69 MOJO_HANDLE_SIGNAL_READABLE); |
| 70 CHECK_EQ(result, MOJO_RESULT_OK); |
| 64 } | 71 } |
| 65 | 72 |
| 66 MessagePumpMojo::~MessagePumpMojo() { | 73 MessagePumpMojo::~MessagePumpMojo() { |
| 67 DCHECK_EQ(this, current()); | 74 DCHECK_EQ(this, current()); |
| 68 g_tls_current_pump.Pointer()->Set(NULL); | 75 g_tls_current_pump.Pointer()->Set(NULL); |
| 69 } | 76 } |
| 70 | 77 |
| 71 // static | 78 // static |
| 72 scoped_ptr<base::MessagePump> MessagePumpMojo::Create() { | 79 scoped_ptr<base::MessagePump> MessagePumpMojo::Create() { |
| 73 return scoped_ptr<MessagePump>(new MessagePumpMojo()); | 80 return scoped_ptr<MessagePump>(new MessagePumpMojo()); |
| (...skipping 15 matching lines...) Expand all Loading... |
| 89 Handler handler_data; | 96 Handler handler_data; |
| 90 handler_data.handler = handler; | 97 handler_data.handler = handler; |
| 91 handler_data.wait_signals = wait_signals; | 98 handler_data.wait_signals = wait_signals; |
| 92 handler_data.deadline = deadline; | 99 handler_data.deadline = deadline; |
| 93 handler_data.id = next_handler_id_++; | 100 handler_data.id = next_handler_id_++; |
| 94 handlers_[handle] = handler_data; | 101 handlers_[handle] = handler_data; |
| 95 if (!deadline.is_null()) { | 102 if (!deadline.is_null()) { |
| 96 bool inserted = deadline_handles_.insert(handle).second; | 103 bool inserted = deadline_handles_.insert(handle).second; |
| 97 DCHECK(inserted); | 104 DCHECK(inserted); |
| 98 } | 105 } |
| 106 |
| 107 MojoResult result = MojoAddHandle(wait_set_handle_.get().value(), |
| 108 handle.value(), wait_signals); |
| 109 // Because stopping a HandleWatcher is now asynchronous, it's possible for the |
| 110 // handle to no longer be open at this point. |
| 111 CHECK(result == MOJO_RESULT_OK || result == MOJO_RESULT_INVALID_ARGUMENT); |
| 99 } | 112 } |
| 100 | 113 |
| 101 void MessagePumpMojo::RemoveHandler(const Handle& handle) { | 114 void MessagePumpMojo::RemoveHandler(const Handle& handle) { |
| 115 MojoResult result = |
| 116 MojoRemoveHandle(wait_set_handle_.get().value(), handle.value()); |
| 117 // At this point, it's possible that the handle has been closed, which would |
| 118 // cause MojoRemoveHandle() to return MOJO_RESULT_INVALID_ARGUMENT. It's also |
| 119 // possible for the handle to have already been removed, so all of the |
| 120 // possible error codes are valid here. |
| 121 CHECK(result == MOJO_RESULT_OK || result == MOJO_RESULT_NOT_FOUND || |
| 122 result == MOJO_RESULT_INVALID_ARGUMENT); |
| 123 |
| 102 handlers_.erase(handle); | 124 handlers_.erase(handle); |
| 103 deadline_handles_.erase(handle); | 125 deadline_handles_.erase(handle); |
| 104 } | 126 } |
| 105 | 127 |
| 106 void MessagePumpMojo::AddObserver(Observer* observer) { | 128 void MessagePumpMojo::AddObserver(Observer* observer) { |
| 107 observers_.AddObserver(observer); | 129 observers_.AddObserver(observer); |
| 108 } | 130 } |
| 109 | 131 |
| 110 void MessagePumpMojo::RemoveObserver(Observer* observer) { | 132 void MessagePumpMojo::RemoveObserver(Observer* observer) { |
| 111 observers_.RemoveObserver(observer); | 133 observers_.RemoveObserver(observer); |
| (...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 165 if (more_work_is_plausible) | 187 if (more_work_is_plausible) |
| 166 continue; | 188 continue; |
| 167 | 189 |
| 168 more_work_is_plausible = delegate->DoIdleWork(); | 190 more_work_is_plausible = delegate->DoIdleWork(); |
| 169 if (run_state->should_quit) | 191 if (run_state->should_quit) |
| 170 break; | 192 break; |
| 171 } | 193 } |
| 172 } | 194 } |
| 173 | 195 |
| 174 bool MessagePumpMojo::DoInternalWork(const RunState& run_state, bool block) { | 196 bool MessagePumpMojo::DoInternalWork(const RunState& run_state, bool block) { |
| 175 const MojoDeadline deadline = block ? GetDeadlineForWait(run_state) : 0; | 197 bool did_work = block; |
| 176 const WaitState wait_state = GetWaitState(); | 198 if (block) { |
| 199 // If the wait isn't blocking (deadline == 0), there's no point in waiting. |
| 200 // Wait sets do not require a wait operation to be performed in order to |
| 201 // retreive any ready handles. Performing a wait with deadline == 0 is |
| 202 // unnecessary work. |
| 203 did_work = WaitForReadyHandles(run_state); |
| 204 } |
| 177 | 205 |
| 178 std::vector<MojoHandleSignalsState> states(wait_state.handles.size()); | 206 did_work |= ProcessReadyHandles(); |
| 179 const WaitManyResult wait_many_result = | 207 did_work |= RemoveExpiredHandles(); |
| 180 WaitMany(wait_state.handles, wait_state.wait_signals, deadline, &states); | 208 |
| 181 const MojoResult result = wait_many_result.result; | 209 return did_work; |
| 182 bool did_work = true; | 210 } |
| 183 if (result == MOJO_RESULT_OK) { | 211 |
| 184 if (wait_many_result.index == 0) { | 212 bool MessagePumpMojo::WaitForReadyHandles(const RunState& run_state) const { |
| 185 if (states[0].satisfied_signals & MOJO_HANDLE_SIGNAL_PEER_CLOSED) { | 213 const MojoDeadline deadline = GetDeadlineForWait(run_state); |
| 186 // The Mojo EDK is shutting down. The ThreadQuitHelper task in | 214 const MojoResult wait_result = Wait( |
| 187 // base::Thread won't get run since the control pipe depends on the EDK | 215 wait_set_handle_.get(), MOJO_HANDLE_SIGNAL_READABLE, deadline, nullptr); |
| 188 // staying alive. So quit manually to avoid this thread hanging. | 216 if (wait_result == MOJO_RESULT_OK) { |
| 189 Quit(); | 217 // Handles may be ready. Or not since wake-ups can be spurious in certain |
| 190 } else { | 218 // circumstances. |
| 191 // Control pipe was written to. | 219 return true; |
| 192 ReadMessageRaw(read_handle_.get(), NULL, NULL, NULL, NULL, | 220 } else if (wait_result == MOJO_RESULT_DEADLINE_EXCEEDED) { |
| 193 MOJO_READ_MESSAGE_FLAG_MAY_DISCARD); | 221 return false; |
| 194 } | 222 } |
| 195 } else { | 223 |
| 196 DCHECK(handlers_.find(wait_state.handles[wait_many_result.index]) != | 224 base::debug::Alias(&wait_result); |
| 197 handlers_.end()); | 225 // Unexpected result is likely fatal, crash so we can determine cause. |
| 198 WillSignalHandler(); | 226 CHECK(false); |
| 199 handlers_[wait_state.handles[wait_many_result.index]] | 227 return false; |
| 200 .handler->OnHandleReady(wait_state.handles[wait_many_result.index]); | 228 } |
| 201 DidSignalHandler(); | 229 |
| 230 bool MessagePumpMojo::ProcessReadyHandles() { |
| 231 // Maximum number of handles to retrieve and process. Experimentally, the 95th |
| 232 // percentile is 1 handle, and the long-term average is 1.1. However, this has |
| 233 // been seen to reach >10 under heavy load. 8 is a hand-wavy compromise. |
| 234 const uint32_t kMaxServiced = 8; |
| 235 uint32_t num_ready_handles = kMaxServiced; |
| 236 MojoHandle handles[kMaxServiced]; |
| 237 MojoResult handle_results[kMaxServiced]; |
| 238 |
| 239 const MojoResult get_result = |
| 240 MojoGetReadyHandles(wait_set_handle_.get().value(), &num_ready_handles, |
| 241 handles, handle_results, nullptr); |
| 242 CHECK(get_result == MOJO_RESULT_OK || get_result == MOJO_RESULT_SHOULD_WAIT); |
| 243 if (get_result != MOJO_RESULT_OK) |
| 244 return false; |
| 245 |
| 246 DCHECK(num_ready_handles); |
| 247 DCHECK_LE(num_ready_handles, kMaxServiced); |
| 248 // Do this in two steps, because notifying a handler may remove/add other |
| 249 // handles that may have also been woken up. |
| 250 // First, enumerate the IDs of the ready handles. Then, iterate over the |
| 251 // handles and only take action if the ID hasn't changed. |
| 252 // Since the size of this map is bounded by |kMaxServiced|, use a SmallMap to |
| 253 // avoid the per-element allocation. |
| 254 base::SmallMap<std::map<Handle, int>, kMaxServiced> ready_handles; |
| 255 for (uint32_t i = 0; i < num_ready_handles; i++) { |
| 256 const Handle handle = Handle(handles[i]); |
| 257 // Skip the control handle. It's special. |
| 258 if (handle.value() == read_handle_.get().value()) |
| 259 continue; |
| 260 DCHECK(handle.is_valid()); |
| 261 const auto it = handlers_.find(handle); |
| 262 // Skip handles that have been removed. This is possible because |
| 263 // RemoveHandler() can be called with a handle that has been closed. Because |
| 264 // the handle is closed, the MojoRemoveHandle() call in RemoveHandler() |
| 265 // would have failed, but the handle is still in the wait set. Once the |
| 266 // handle is retrieved using MojoGetReadyHandles(), it is implicitly removed |
| 267 // from the set. The result is either the pending result that existed when |
| 268 // the handle was closed, or |MOJO_RESULT_CANCELLED| to indicate that the |
| 269 // handle was closed. |
| 270 if (it == handlers_.end()) |
| 271 continue; |
| 272 ready_handles[handle] = it->second.id; |
| 273 } |
| 274 |
| 275 for (uint32_t i = 0; i < num_ready_handles; i++) { |
| 276 const Handle handle = Handle(handles[i]); |
| 277 |
| 278 // If the handle has been removed, or it's ID has changed, skip over it. |
| 279 // If the handle's ID has changed, and it still satisfies its signals, |
| 280 // then it'll be caught in the next message pump iteration. |
| 281 const auto it = handlers_.find(handle); |
| 282 if ((handle.value() != read_handle_.get().value()) && |
| 283 (it == handlers_.end() || it->second.id != ready_handles[handle])) { |
| 284 continue; |
| 202 } | 285 } |
| 203 } else { | 286 |
| 204 switch (result) { | 287 switch (handle_results[i]) { |
| 205 case MOJO_RESULT_CANCELLED: | 288 case MOJO_RESULT_CANCELLED: |
| 206 case MOJO_RESULT_FAILED_PRECONDITION: | 289 case MOJO_RESULT_FAILED_PRECONDITION: |
| 207 case MOJO_RESULT_INVALID_ARGUMENT: | 290 DVLOG(1) << "Error: " << handle_results[i] |
| 208 RemoveInvalidHandle(wait_state, result, wait_many_result.index); | 291 << " handle: " << handle.value(); |
| 292 if (handle.value() == read_handle_.get().value()) { |
| 293 // The Mojo EDK is shutting down. The ThreadQuitHelper task in |
| 294 // base::Thread won't get run since the control pipe depends on the |
| 295 // EDK staying alive. So quit manually to avoid this thread hanging. |
| 296 Quit(); |
| 297 } else { |
| 298 RemoveInvalidHandle(handle_results[i], handle); |
| 299 } |
| 209 break; | 300 break; |
| 210 case MOJO_RESULT_DEADLINE_EXCEEDED: | 301 case MOJO_RESULT_OK: |
| 211 did_work = false; | 302 if (handle.value() == read_handle_.get().value()) { |
| 303 DVLOG(1) << "Signaled control pipe"; |
| 304 // Control pipe was written to. |
| 305 ReadMessageRaw(read_handle_.get(), nullptr, nullptr, nullptr, nullptr, |
| 306 MOJO_READ_MESSAGE_FLAG_MAY_DISCARD); |
| 307 } else { |
| 308 DVLOG(1) << "Handle ready: " << handle.value(); |
| 309 SignalHandleReady(handle); |
| 310 } |
| 212 break; | 311 break; |
| 213 default: | 312 default: |
| 214 base::debug::Alias(&result); | 313 base::debug::Alias(&i); |
| 314 base::debug::Alias(&handle_results[i]); |
| 215 // Unexpected result is likely fatal, crash so we can determine cause. | 315 // Unexpected result is likely fatal, crash so we can determine cause. |
| 216 CHECK(false); | 316 CHECK(false); |
| 217 } | 317 } |
| 218 } | 318 } |
| 319 return true; |
| 320 } |
| 219 | 321 |
| 322 void MessagePumpMojo::RemoveInvalidHandle(MojoResult result, Handle handle) { |
| 323 // TODO(sky): deal with control pipe going bad. |
| 324 CHECK(result == MOJO_RESULT_FAILED_PRECONDITION || |
| 325 result == MOJO_RESULT_CANCELLED || |
| 326 result == MOJO_RESULT_DEADLINE_EXCEEDED); |
| 327 // Indicates the control pipe went bad. |
| 328 CHECK_NE(handle.value(), read_handle_.get().value()); |
| 329 |
| 330 auto it = handlers_.find(handle); |
| 331 CHECK(it != handlers_.end()); |
| 332 MessagePumpMojoHandler* handler = it->second.handler; |
| 333 RemoveHandler(handle); |
| 334 WillSignalHandler(); |
| 335 handler->OnHandleError(handle, result); |
| 336 DidSignalHandler(); |
| 337 } |
| 338 |
| 339 bool MessagePumpMojo::RemoveExpiredHandles() { |
| 340 bool removed = false; |
| 220 // Notify and remove any handlers whose time has expired. First, iterate over | 341 // Notify and remove any handlers whose time has expired. First, iterate over |
| 221 // the set of handles that have a deadline, and add the expired handles to a | 342 // the set of handles that have a deadline, and add the expired handles to a |
| 222 // map of <Handle, id>. Then, iterate over those expired handles and remove | 343 // map of <Handle, id>. Then, iterate over those expired handles and remove |
| 223 // them. The two-step process is because a handler can add/remove new | 344 // them. The two-step process is because a handler can add/remove new |
| 224 // handlers. | 345 // handlers. |
| 225 std::map<Handle, int> expired_handles; | 346 std::map<Handle, int> expired_handles; |
| 226 const base::TimeTicks now(internal::NowTicks()); | 347 const base::TimeTicks now(internal::NowTicks()); |
| 227 for (const Handle handle : deadline_handles_) { | 348 for (const Handle handle : deadline_handles_) { |
| 228 const auto it = handlers_.find(handle); | 349 const auto it = handlers_.find(handle); |
| 229 // Expect any handle in |deadline_handles_| to also be in |handlers_| since | 350 // Expect any handle in |deadline_handles_| to also be in |handlers_| since |
| 230 // the two are modified in lock-step. | 351 // the two are modified in lock-step. |
| 231 DCHECK(it != handlers_.end()); | 352 DCHECK(it != handlers_.end()); |
| 232 if (!it->second.deadline.is_null() && it->second.deadline < now) | 353 if (!it->second.deadline.is_null() && it->second.deadline < now) |
| 233 expired_handles[handle] = it->second.id; | 354 expired_handles[handle] = it->second.id; |
| 234 } | 355 } |
| 235 for (auto& pair : expired_handles) { | 356 for (const auto& pair : expired_handles) { |
| 236 auto it = handlers_.find(pair.first); | 357 auto it = handlers_.find(pair.first); |
| 237 // Don't need to check deadline again since it can't change if id hasn't | 358 // Don't need to check deadline again since it can't change if id hasn't |
| 238 // changed. | 359 // changed. |
| 239 if (it != handlers_.end() && it->second.id == pair.second) { | 360 if (it != handlers_.end() && it->second.id == pair.second) { |
| 240 MessagePumpMojoHandler* handler = handlers_[pair.first].handler; | 361 MessagePumpMojoHandler* handler = it->second.handler; |
| 241 RemoveHandler(pair.first); | 362 RemoveHandler(pair.first); |
| 242 WillSignalHandler(); | 363 WillSignalHandler(); |
| 243 handler->OnHandleError(pair.first, MOJO_RESULT_DEADLINE_EXCEEDED); | 364 handler->OnHandleError(pair.first, MOJO_RESULT_DEADLINE_EXCEEDED); |
| 244 DidSignalHandler(); | 365 DidSignalHandler(); |
| 245 did_work = true; | 366 removed = true; |
| 246 } | 367 } |
| 247 } | 368 } |
| 248 return did_work; | 369 return removed; |
| 249 } | |
| 250 | |
| 251 void MessagePumpMojo::RemoveInvalidHandle(const WaitState& wait_state, | |
| 252 MojoResult result, | |
| 253 uint32_t index) { | |
| 254 // TODO(sky): deal with control pipe going bad. | |
| 255 CHECK(result == MOJO_RESULT_INVALID_ARGUMENT || | |
| 256 result == MOJO_RESULT_FAILED_PRECONDITION || | |
| 257 result == MOJO_RESULT_CANCELLED); | |
| 258 CHECK_NE(index, 0u); // Indicates the control pipe went bad. | |
| 259 | |
| 260 // Remove the handle first, this way if OnHandleError() tries to remove the | |
| 261 // handle our iterator isn't invalidated. | |
| 262 Handle handle = wait_state.handles[index]; | |
| 263 CHECK(handlers_.find(handle) != handlers_.end()); | |
| 264 MessagePumpMojoHandler* handler = handlers_[handle].handler; | |
| 265 RemoveHandler(handle); | |
| 266 WillSignalHandler(); | |
| 267 handler->OnHandleError(handle, result); | |
| 268 DidSignalHandler(); | |
| 269 } | 370 } |
| 270 | 371 |
| 271 void MessagePumpMojo::SignalControlPipe() { | 372 void MessagePumpMojo::SignalControlPipe() { |
| 272 const MojoResult result = | 373 const MojoResult result = |
| 273 WriteMessageRaw(write_handle_.get(), NULL, 0, NULL, 0, | 374 WriteMessageRaw(write_handle_.get(), NULL, 0, NULL, 0, |
| 274 MOJO_WRITE_MESSAGE_FLAG_NONE); | 375 MOJO_WRITE_MESSAGE_FLAG_NONE); |
| 275 if (result == MOJO_RESULT_FAILED_PRECONDITION) { | 376 if (result == MOJO_RESULT_FAILED_PRECONDITION) { |
| 276 // Mojo EDK is shutting down. | 377 // Mojo EDK is shutting down. |
| 277 return; | 378 return; |
| 278 } | 379 } |
| 279 | 380 |
| 280 // If we can't write we likely won't wake up the thread and there is a strong | 381 // If we can't write we likely won't wake up the thread and there is a strong |
| 281 // chance we'll deadlock. | 382 // chance we'll deadlock. |
| 282 CHECK_EQ(MOJO_RESULT_OK, result); | 383 CHECK_EQ(MOJO_RESULT_OK, result); |
| 283 } | 384 } |
| 284 | 385 |
| 285 MessagePumpMojo::WaitState MessagePumpMojo::GetWaitState() const { | |
| 286 WaitState wait_state; | |
| 287 wait_state.handles.push_back(read_handle_.get()); | |
| 288 wait_state.wait_signals.push_back( | |
| 289 MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_PEER_CLOSED); | |
| 290 | |
| 291 for (HandleToHandler::const_iterator i = handlers_.begin(); | |
| 292 i != handlers_.end(); ++i) { | |
| 293 wait_state.handles.push_back(i->first); | |
| 294 wait_state.wait_signals.push_back(i->second.wait_signals); | |
| 295 } | |
| 296 return wait_state; | |
| 297 } | |
| 298 | |
| 299 MojoDeadline MessagePumpMojo::GetDeadlineForWait( | 386 MojoDeadline MessagePumpMojo::GetDeadlineForWait( |
| 300 const RunState& run_state) const { | 387 const RunState& run_state) const { |
| 301 const base::TimeTicks now(internal::NowTicks()); | 388 const base::TimeTicks now(internal::NowTicks()); |
| 302 MojoDeadline deadline = TimeTicksToMojoDeadline(run_state.delayed_work_time, | 389 MojoDeadline deadline = TimeTicksToMojoDeadline(run_state.delayed_work_time, |
| 303 now); | 390 now); |
| 304 for (const Handle handle : deadline_handles_) { | 391 for (const Handle handle : deadline_handles_) { |
| 305 auto it = handlers_.find(handle); | 392 auto it = handlers_.find(handle); |
| 306 DCHECK(it != handlers_.end()); | 393 DCHECK(it != handlers_.end()); |
| 307 deadline = std::min( | 394 deadline = std::min( |
| 308 TimeTicksToMojoDeadline(it->second.deadline, now), deadline); | 395 TimeTicksToMojoDeadline(it->second.deadline, now), deadline); |
| 309 } | 396 } |
| 310 return deadline; | 397 return deadline; |
| 311 } | 398 } |
| 312 | 399 |
| 400 void MessagePumpMojo::SignalHandleReady(Handle handle) { |
| 401 DCHECK(handlers_.find(handle) != handlers_.end()); |
| 402 WillSignalHandler(); |
| 403 handlers_[handle].handler->OnHandleReady(handle); |
| 404 DidSignalHandler(); |
| 405 } |
| 406 |
| 313 void MessagePumpMojo::WillSignalHandler() { | 407 void MessagePumpMojo::WillSignalHandler() { |
| 314 FOR_EACH_OBSERVER(Observer, observers_, WillSignalHandler()); | 408 FOR_EACH_OBSERVER(Observer, observers_, WillSignalHandler()); |
| 315 } | 409 } |
| 316 | 410 |
| 317 void MessagePumpMojo::DidSignalHandler() { | 411 void MessagePumpMojo::DidSignalHandler() { |
| 318 FOR_EACH_OBSERVER(Observer, observers_, DidSignalHandler()); | 412 FOR_EACH_OBSERVER(Observer, observers_, DidSignalHandler()); |
| 319 } | 413 } |
| 320 | 414 |
| 321 } // namespace common | 415 } // namespace common |
| 322 } // namespace mojo | 416 } // namespace mojo |
| OLD | NEW |