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 |