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

Side by Side Diff: mojo/common/handle_watcher.cc

Issue 282823003: Mojo: cancel pending AsyncWait calls when the callers thread exits (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: env first Created 6 years, 7 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 | Annotate | Revision Log
« no previous file with comments | « mojo/common/handle_watcher.h ('k') | mojo/common/handle_watcher_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/common/handle_watcher.h" 5 #include "mojo/common/handle_watcher.h"
6 6
7 #include <map> 7 #include <map>
8 8
9 #include "base/atomic_sequence_num.h" 9 #include "base/atomic_sequence_num.h"
10 #include "base/bind.h" 10 #include "base/bind.h"
(...skipping 235 matching lines...) Expand 10 before | Expand all | Expand 10 after
246 246
247 WatcherThreadManager::WatcherThreadManager() 247 WatcherThreadManager::WatcherThreadManager()
248 : thread_(kWatcherThreadName) { 248 : thread_(kWatcherThreadName) {
249 base::Thread::Options thread_options; 249 base::Thread::Options thread_options;
250 thread_options.message_pump_factory = base::Bind(&CreateMessagePumpMojo); 250 thread_options.message_pump_factory = base::Bind(&CreateMessagePumpMojo);
251 thread_.StartWithOptions(thread_options); 251 thread_.StartWithOptions(thread_options);
252 } 252 }
253 253
254 } // namespace 254 } // namespace
255 255
256 // HandleWatcher::StartState --------------------------------------------------- 256 // HandleWatcher::State --------------------------------------------------------
257 257
258 // Contains the information passed to Start(). 258 // Represents the state of the HandleWatcher. Owns the user's callback and
259 struct HandleWatcher::StartState { 259 // monitors the current thread's MessageLoop to know when to force the callback
260 explicit StartState(HandleWatcher* watcher) : weak_factory(watcher) { 260 // to run (with an error) even though the pipe hasn't been signaled yet.
261 class HandleWatcher::State : public base::MessageLoop::DestructionObserver {
262 public:
263 State(HandleWatcher* watcher,
264 const Handle& handle,
265 MojoWaitFlags wait_flags,
266 MojoDeadline deadline,
267 const base::Callback<void(MojoResult)>& callback)
268 : watcher_(watcher),
269 callback_(callback),
270 weak_factory_(this) {
271 base::MessageLoop::current()->AddDestructionObserver(this);
272
273 watcher_id_ = WatcherThreadManager::GetInstance()->StartWatching(
274 handle,
275 wait_flags,
276 MojoDeadlineToTimeTicks(deadline),
277 base::Bind(&State::OnHandleReady, weak_factory_.GetWeakPtr()));
261 } 278 }
262 279
263 ~StartState() { 280 virtual ~State() {
281 base::MessageLoop::current()->RemoveDestructionObserver(this);
282
283 WatcherThreadManager::GetInstance()->StopWatching(watcher_id_);
264 } 284 }
265 285
266 // ID assigned by WatcherThreadManager. 286 private:
267 WatcherID watcher_id; 287 virtual void WillDestroyCurrentMessageLoop() OVERRIDE {
288 // The current thread is exiting. Simulate a watch error.
289 OnHandleReady(MOJO_RESULT_ABORTED);
290 }
268 291
269 // Callback to notify when done. 292 void OnHandleReady(MojoResult result) {
270 base::Callback<void(MojoResult)> callback; 293 base::Callback<void(MojoResult)> callback = callback_;
294 watcher_->Stop(); // Destroys |this|.
271 295
272 // When Start() is invoked a callback is passed to WatcherThreadManager 296 callback.Run(result);
273 // using a WeakRef from |weak_refactory_|. The callback invokes 297 }
274 // OnHandleReady() (on the thread Start() is invoked from) which in turn 298
275 // notifies |callback_|. Doing this allows us to reset state when the handle 299 HandleWatcher* watcher_;
276 // is ready, and then notify the callback. Doing this also means Stop() 300 WatcherID watcher_id_;
277 // cancels any pending callbacks that may be inflight. 301 base::Callback<void(MojoResult)> callback_;
278 base::WeakPtrFactory<HandleWatcher> weak_factory; 302
303 // Used to weakly bind |this| to the WatcherThreadManager.
304 base::WeakPtrFactory<State> weak_factory_;
279 }; 305 };
280 306
281 // HandleWatcher --------------------------------------------------------------- 307 // HandleWatcher ---------------------------------------------------------------
282 308
283 HandleWatcher::HandleWatcher() { 309 HandleWatcher::HandleWatcher() {
284 } 310 }
285 311
286 HandleWatcher::~HandleWatcher() { 312 HandleWatcher::~HandleWatcher() {
287 Stop();
288 } 313 }
289 314
290 void HandleWatcher::Start(const Handle& handle, 315 void HandleWatcher::Start(const Handle& handle,
291 MojoWaitFlags wait_flags, 316 MojoWaitFlags wait_flags,
292 MojoDeadline deadline, 317 MojoDeadline deadline,
293 const base::Callback<void(MojoResult)>& callback) { 318 const base::Callback<void(MojoResult)>& callback) {
294 DCHECK(handle.is_valid()); 319 DCHECK(handle.is_valid());
295 DCHECK_NE(MOJO_WAIT_FLAG_NONE, wait_flags); 320 DCHECK_NE(MOJO_WAIT_FLAG_NONE, wait_flags);
296 321
297 Stop(); 322 state_.reset(new State(this, handle, wait_flags, deadline, callback));
298
299 start_state_.reset(new StartState(this));
300 start_state_->callback = callback;
301 start_state_->watcher_id =
302 WatcherThreadManager::GetInstance()->StartWatching(
303 handle,
304 wait_flags,
305 MojoDeadlineToTimeTicks(deadline),
306 base::Bind(&HandleWatcher::OnHandleReady,
307 start_state_->weak_factory.GetWeakPtr()));
308 } 323 }
309 324
310 void HandleWatcher::Stop() { 325 void HandleWatcher::Stop() {
311 if (!start_state_.get()) 326 state_.reset();
312 return;
313
314 scoped_ptr<StartState> old_state(start_state_.Pass());
315 WatcherThreadManager::GetInstance()->StopWatching(old_state->watcher_id);
316 }
317
318 void HandleWatcher::OnHandleReady(MojoResult result) {
319 DCHECK(start_state_.get());
320 scoped_ptr<StartState> old_state(start_state_.Pass());
321 old_state->callback.Run(result);
322
323 // NOTE: We may have been deleted during callback execution.
324 } 327 }
325 328
326 } // namespace common 329 } // namespace common
327 } // namespace mojo 330 } // namespace mojo
OLDNEW
« no previous file with comments | « mojo/common/handle_watcher.h ('k') | mojo/common/handle_watcher_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698