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 |