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

Unified 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 side-by-side diff with in-line comments
Download patch
« no previous file with comments | « mojo/common/handle_watcher.h ('k') | mojo/common/handle_watcher_unittest.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: mojo/common/handle_watcher.cc
diff --git a/mojo/common/handle_watcher.cc b/mojo/common/handle_watcher.cc
index a95669c5803056037723de81df2a84e391fd7881..1affa9041be060f14ee455934c7ee616457b7254 100644
--- a/mojo/common/handle_watcher.cc
+++ b/mojo/common/handle_watcher.cc
@@ -253,29 +253,55 @@ WatcherThreadManager::WatcherThreadManager()
} // namespace
-// HandleWatcher::StartState ---------------------------------------------------
+// HandleWatcher::State --------------------------------------------------------
-// Contains the information passed to Start().
-struct HandleWatcher::StartState {
- explicit StartState(HandleWatcher* watcher) : weak_factory(watcher) {
+// Represents the state of the HandleWatcher. Owns the user's callback and
+// monitors the current thread's MessageLoop to know when to force the callback
+// to run (with an error) even though the pipe hasn't been signaled yet.
+class HandleWatcher::State : public base::MessageLoop::DestructionObserver {
+ public:
+ State(HandleWatcher* watcher,
+ const Handle& handle,
+ MojoWaitFlags wait_flags,
+ MojoDeadline deadline,
+ const base::Callback<void(MojoResult)>& callback)
+ : watcher_(watcher),
+ callback_(callback),
+ weak_factory_(this) {
+ base::MessageLoop::current()->AddDestructionObserver(this);
+
+ watcher_id_ = WatcherThreadManager::GetInstance()->StartWatching(
+ handle,
+ wait_flags,
+ MojoDeadlineToTimeTicks(deadline),
+ base::Bind(&State::OnHandleReady, weak_factory_.GetWeakPtr()));
}
- ~StartState() {
+ virtual ~State() {
+ base::MessageLoop::current()->RemoveDestructionObserver(this);
+
+ WatcherThreadManager::GetInstance()->StopWatching(watcher_id_);
}
- // ID assigned by WatcherThreadManager.
- WatcherID watcher_id;
+ private:
+ virtual void WillDestroyCurrentMessageLoop() OVERRIDE {
+ // The current thread is exiting. Simulate a watch error.
+ OnHandleReady(MOJO_RESULT_ABORTED);
+ }
- // Callback to notify when done.
- base::Callback<void(MojoResult)> callback;
+ void OnHandleReady(MojoResult result) {
+ base::Callback<void(MojoResult)> callback = callback_;
+ watcher_->Stop(); // Destroys |this|.
+
+ callback.Run(result);
+ }
- // When Start() is invoked a callback is passed to WatcherThreadManager
- // using a WeakRef from |weak_refactory_|. The callback invokes
- // OnHandleReady() (on the thread Start() is invoked from) which in turn
- // notifies |callback_|. Doing this allows us to reset state when the handle
- // is ready, and then notify the callback. Doing this also means Stop()
- // cancels any pending callbacks that may be inflight.
- base::WeakPtrFactory<HandleWatcher> weak_factory;
+ HandleWatcher* watcher_;
+ WatcherID watcher_id_;
+ base::Callback<void(MojoResult)> callback_;
+
+ // Used to weakly bind |this| to the WatcherThreadManager.
+ base::WeakPtrFactory<State> weak_factory_;
};
// HandleWatcher ---------------------------------------------------------------
@@ -284,7 +310,6 @@ HandleWatcher::HandleWatcher() {
}
HandleWatcher::~HandleWatcher() {
- Stop();
}
void HandleWatcher::Start(const Handle& handle,
@@ -294,33 +319,11 @@ void HandleWatcher::Start(const Handle& handle,
DCHECK(handle.is_valid());
DCHECK_NE(MOJO_WAIT_FLAG_NONE, wait_flags);
- Stop();
-
- start_state_.reset(new StartState(this));
- start_state_->callback = callback;
- start_state_->watcher_id =
- WatcherThreadManager::GetInstance()->StartWatching(
- handle,
- wait_flags,
- MojoDeadlineToTimeTicks(deadline),
- base::Bind(&HandleWatcher::OnHandleReady,
- start_state_->weak_factory.GetWeakPtr()));
+ state_.reset(new State(this, handle, wait_flags, deadline, callback));
}
void HandleWatcher::Stop() {
- if (!start_state_.get())
- return;
-
- scoped_ptr<StartState> old_state(start_state_.Pass());
- WatcherThreadManager::GetInstance()->StopWatching(old_state->watcher_id);
-}
-
-void HandleWatcher::OnHandleReady(MojoResult result) {
- DCHECK(start_state_.get());
- scoped_ptr<StartState> old_state(start_state_.Pass());
- old_state->callback.Run(result);
-
- // NOTE: We may have been deleted during callback execution.
+ state_.reset();
}
} // namespace common
« 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