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 <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 Loading... |
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 Loading... |
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 Loading... |
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 |
OLD | NEW |