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

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: Fix component builds. Created 5 years 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
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 <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
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
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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698