Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(100)

Side by Side Diff: mojo/message_pump/message_pump_mojo.cc

Issue 1467953002: Implement MessagePumpMojo using WaitSet. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@mojo-waitset-implementation
Patch Set: Rebase, address comments, and auto format. Created 4 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « mojo/message_pump/message_pump_mojo.h ('k') | mojo/message_pump/message_pump_mojo_unittest.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
OLDNEW
« no previous file with comments | « mojo/message_pump/message_pump_mojo.h ('k') | mojo/message_pump/message_pump_mojo_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698