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