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

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

Issue 1448233002: Avoid iterating over all handles in MessagePumpMojo on every iteration to calculate deadlines. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Review comments. Created 5 years, 1 month 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') | no next file » | 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 <algorithm> 7 #include <algorithm>
8 #include <vector> 8 #include <vector>
9 9
10 #include "base/debug/alias.h" 10 #include "base/debug/alias.h"
(...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after
84 CHECK(handler); 84 CHECK(handler);
85 DCHECK(handle.is_valid()); 85 DCHECK(handle.is_valid());
86 // Assume it's an error if someone tries to reregister an existing handle. 86 // Assume it's an error if someone tries to reregister an existing handle.
87 CHECK_EQ(0u, handlers_.count(handle)); 87 CHECK_EQ(0u, handlers_.count(handle));
88 Handler handler_data; 88 Handler handler_data;
89 handler_data.handler = handler; 89 handler_data.handler = handler;
90 handler_data.wait_signals = wait_signals; 90 handler_data.wait_signals = wait_signals;
91 handler_data.deadline = deadline; 91 handler_data.deadline = deadline;
92 handler_data.id = next_handler_id_++; 92 handler_data.id = next_handler_id_++;
93 handlers_[handle] = handler_data; 93 handlers_[handle] = handler_data;
94 if (!deadline.is_null()) {
95 bool inserted = deadline_handles_.insert(handle).second;
96 DCHECK(inserted);
97 }
94 } 98 }
95 99
96 void MessagePumpMojo::RemoveHandler(const Handle& handle) { 100 void MessagePumpMojo::RemoveHandler(const Handle& handle) {
97 handlers_.erase(handle); 101 handlers_.erase(handle);
102 deadline_handles_.erase(handle);
98 } 103 }
99 104
100 void MessagePumpMojo::AddObserver(Observer* observer) { 105 void MessagePumpMojo::AddObserver(Observer* observer) {
101 observers_.AddObserver(observer); 106 observers_.AddObserver(observer);
102 } 107 }
103 108
104 void MessagePumpMojo::RemoveObserver(Observer* observer) { 109 void MessagePumpMojo::RemoveObserver(Observer* observer) {
105 observers_.RemoveObserver(observer); 110 observers_.RemoveObserver(observer);
106 } 111 }
107 112
(...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after
200 case MOJO_RESULT_DEADLINE_EXCEEDED: 205 case MOJO_RESULT_DEADLINE_EXCEEDED:
201 did_work = false; 206 did_work = false;
202 break; 207 break;
203 default: 208 default:
204 base::debug::Alias(&result); 209 base::debug::Alias(&result);
205 // Unexpected result is likely fatal, crash so we can determine cause. 210 // Unexpected result is likely fatal, crash so we can determine cause.
206 CHECK(false); 211 CHECK(false);
207 } 212 }
208 } 213 }
209 214
210 // Notify and remove any handlers whose time has expired. Make a copy in case 215 // Notify and remove any handlers whose time has expired. First, iterate over
211 // someone tries to add/remove new handlers from notification. 216 // the set of handles that have a deadline, and add the expired handles to a
212 const HandleToHandler cloned_handlers(handlers_); 217 // map of <Handle, id>. Then, iterate over those expired handles and remove
218 // them. The two-step process is because a handler can add/remove new
219 // handlers.
220 std::map<Handle, int> expired_handles;
213 const base::TimeTicks now(internal::NowTicks()); 221 const base::TimeTicks now(internal::NowTicks());
214 for (HandleToHandler::const_iterator i = cloned_handlers.begin(); 222 for (const Handle handle : deadline_handles_) {
215 i != cloned_handlers.end(); ++i) { 223 const auto it = handlers_.find(handle);
216 // Since we're iterating over a clone of the handlers, verify the handler is 224 // Expect any handle in |deadline_handles_| to also be in |handlers_| since
217 // still valid before notifying. 225 // the two are modified in lock-step.
218 if (!i->second.deadline.is_null() && i->second.deadline < now && 226 DCHECK(it != handlers_.end());
219 handlers_.find(i->first) != handlers_.end() && 227 if (!it->second.deadline.is_null() && it->second.deadline < now)
220 handlers_[i->first].id == i->second.id) { 228 expired_handles[handle] = it->second.id;
229 }
230 for (auto& pair : expired_handles) {
231 auto it = handlers_.find(pair.first);
232 // Don't need to check deadline again since it can't change if id hasn't
233 // changed.
234 if (it != handlers_.end() && it->second.id == pair.second) {
235 MessagePumpMojoHandler* handler = handlers_[pair.first].handler;
236 RemoveHandler(pair.first);
221 WillSignalHandler(); 237 WillSignalHandler();
222 i->second.handler->OnHandleError(i->first, MOJO_RESULT_DEADLINE_EXCEEDED); 238 handler->OnHandleError(pair.first, MOJO_RESULT_DEADLINE_EXCEEDED);
223 DidSignalHandler(); 239 DidSignalHandler();
224 handlers_.erase(i->first);
225 did_work = true; 240 did_work = true;
226 } 241 }
227 } 242 }
228 return did_work; 243 return did_work;
229 } 244 }
230 245
231 void MessagePumpMojo::RemoveInvalidHandle(const WaitState& wait_state, 246 void MessagePumpMojo::RemoveInvalidHandle(const WaitState& wait_state,
232 MojoResult result, 247 MojoResult result,
233 uint32_t index) { 248 uint32_t index) {
234 // TODO(sky): deal with control pipe going bad. 249 // TODO(sky): deal with control pipe going bad.
235 CHECK(result == MOJO_RESULT_FAILED_PRECONDITION || 250 CHECK(result == MOJO_RESULT_FAILED_PRECONDITION ||
236 result == MOJO_RESULT_CANCELLED); 251 result == MOJO_RESULT_CANCELLED);
237 CHECK_NE(index, 0u); // Indicates the control pipe went bad. 252 CHECK_NE(index, 0u); // Indicates the control pipe went bad.
238 253
239 // Remove the handle first, this way if OnHandleError() tries to remove the 254 // Remove the handle first, this way if OnHandleError() tries to remove the
240 // handle our iterator isn't invalidated. 255 // handle our iterator isn't invalidated.
241 CHECK(handlers_.find(wait_state.handles[index]) != handlers_.end()); 256 Handle handle = wait_state.handles[index];
242 MessagePumpMojoHandler* handler = 257 CHECK(handlers_.find(handle) != handlers_.end());
243 handlers_[wait_state.handles[index]].handler; 258 MessagePumpMojoHandler* handler = handlers_[handle].handler;
244 handlers_.erase(wait_state.handles[index]); 259 RemoveHandler(handle);
245 WillSignalHandler(); 260 WillSignalHandler();
246 handler->OnHandleError(wait_state.handles[index], result); 261 handler->OnHandleError(handle, result);
247 DidSignalHandler(); 262 DidSignalHandler();
248 } 263 }
249 264
250 void MessagePumpMojo::SignalControlPipe(const RunState& run_state) { 265 void MessagePumpMojo::SignalControlPipe(const RunState& run_state) {
251 const MojoResult result = 266 const MojoResult result =
252 WriteMessageRaw(run_state.write_handle.get(), NULL, 0, NULL, 0, 267 WriteMessageRaw(run_state.write_handle.get(), NULL, 0, NULL, 0,
253 MOJO_WRITE_MESSAGE_FLAG_NONE); 268 MOJO_WRITE_MESSAGE_FLAG_NONE);
254 // If we can't write we likely won't wake up the thread and there is a strong 269 // If we can't write we likely won't wake up the thread and there is a strong
255 // chance we'll deadlock. 270 // chance we'll deadlock.
256 CHECK_EQ(MOJO_RESULT_OK, result); 271 CHECK_EQ(MOJO_RESULT_OK, result);
(...skipping 11 matching lines...) Expand all
268 wait_state.wait_signals.push_back(i->second.wait_signals); 283 wait_state.wait_signals.push_back(i->second.wait_signals);
269 } 284 }
270 return wait_state; 285 return wait_state;
271 } 286 }
272 287
273 MojoDeadline MessagePumpMojo::GetDeadlineForWait( 288 MojoDeadline MessagePumpMojo::GetDeadlineForWait(
274 const RunState& run_state) const { 289 const RunState& run_state) const {
275 const base::TimeTicks now(internal::NowTicks()); 290 const base::TimeTicks now(internal::NowTicks());
276 MojoDeadline deadline = TimeTicksToMojoDeadline(run_state.delayed_work_time, 291 MojoDeadline deadline = TimeTicksToMojoDeadline(run_state.delayed_work_time,
277 now); 292 now);
278 for (HandleToHandler::const_iterator i = handlers_.begin(); 293 for (const Handle handle : deadline_handles_) {
279 i != handlers_.end(); ++i) { 294 auto it = handlers_.find(handle);
295 DCHECK(it != handlers_.end());
280 deadline = std::min( 296 deadline = std::min(
281 TimeTicksToMojoDeadline(i->second.deadline, now), deadline); 297 TimeTicksToMojoDeadline(it->second.deadline, now), deadline);
282 } 298 }
283 return deadline; 299 return deadline;
284 } 300 }
285 301
286 void MessagePumpMojo::WillSignalHandler() { 302 void MessagePumpMojo::WillSignalHandler() {
287 FOR_EACH_OBSERVER(Observer, observers_, WillSignalHandler()); 303 FOR_EACH_OBSERVER(Observer, observers_, WillSignalHandler());
288 } 304 }
289 305
290 void MessagePumpMojo::DidSignalHandler() { 306 void MessagePumpMojo::DidSignalHandler() {
291 FOR_EACH_OBSERVER(Observer, observers_, DidSignalHandler()); 307 FOR_EACH_OBSERVER(Observer, observers_, DidSignalHandler());
292 } 308 }
293 309
294 } // namespace common 310 } // namespace common
295 } // namespace mojo 311 } // namespace mojo
OLDNEW
« no previous file with comments | « mojo/message_pump/message_pump_mojo.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698