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

Unified Diff: mojo/common/handle_watcher.cc

Issue 409943003: Makes HandleWatcher block until no longer waiting on pipe (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: tweaks Created 6 years, 5 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
Index: mojo/common/handle_watcher.cc
diff --git a/mojo/common/handle_watcher.cc b/mojo/common/handle_watcher.cc
index 84e8b64fb9ad7a93fd0fb5ca1b211178a5f3bb6b..c8c4ac236194c13c711bda62087a7639b7a7c788 100644
--- a/mojo/common/handle_watcher.cc
+++ b/mojo/common/handle_watcher.cc
@@ -13,6 +13,7 @@
#include "base/memory/weak_ptr.h"
#include "base/message_loop/message_loop.h"
#include "base/message_loop/message_loop_proxy.h"
+#include "base/synchronization/condition_variable.h"
#include "base/synchronization/lock.h"
#include "base/threading/thread.h"
#include "base/time/time.h"
@@ -57,6 +58,20 @@ struct WatchData {
scoped_refptr<base::MessageLoopProxy> message_loop;
};
+// WaitState -------------------------------------------------------------------
+
+// Used when removing a handle. The main thread blocks until the background
+// thread successfully removes the handle from the set of handles being watched.
+// When the background thread removes the handle it sets |removed| and signals
+// |condition|.
+struct WaitState {
darin (slow to review) 2014/07/22 17:42:56 nit: You could also just use base::WaitableEvent h
sky 2014/07/22 18:20:50 I thought there was something like that. Done!
+ WaitState() : condition(&lock), removed(false) {}
+
+ base::Lock lock;
+ base::ConditionVariable condition;
+ bool removed;
+};
+
// WatcherBackend --------------------------------------------------------------
// WatcherBackend is responsible for managing the requests and interacting with
@@ -68,7 +83,10 @@ class WatcherBackend : public MessagePumpMojoHandler {
virtual ~WatcherBackend();
void StartWatching(const WatchData& data);
- void StopWatching(WatcherID watcher_id);
+
+ // Cancels a previously schedule request to start a watch. When done sets
+ // |wait_state->removed| and signals the condition.
+ void StopWatching(WatcherID watcher_id, WaitState* wait_state);
private:
typedef std::map<Handle, WatchData> HandleToWatchDataMap;
@@ -107,15 +125,19 @@ void WatcherBackend::StartWatching(const WatchData& data) {
data.deadline);
}
-void WatcherBackend::StopWatching(WatcherID watcher_id) {
+void WatcherBackend::StopWatching(WatcherID watcher_id, WaitState* wait_state) {
// Because of the thread hop it is entirely possible to get here and not
// have a valid handle registered for |watcher_id|.
Handle handle;
- if (!GetMojoHandleByWatcherID(watcher_id, &handle))
- return;
-
- handle_to_data_.erase(handle);
- message_pump_mojo->RemoveHandler(handle);
+ if (GetMojoHandleByWatcherID(watcher_id, &handle)) {
+ handle_to_data_.erase(handle);
+ message_pump_mojo->RemoveHandler(handle);
+ }
+ {
+ base::AutoLock auto_lock(wait_state->lock);
+ wait_state->removed = true;
+ wait_state->condition.Signal();
+ }
}
void WatcherBackend::RemoveAndNotify(const Handle& handle,
@@ -208,7 +230,7 @@ WatcherID WatcherThreadManager::StartWatching(
data.message_loop = base::MessageLoopProxy::current();
DCHECK_NE(static_cast<base::MessageLoopProxy*>(NULL),
data.message_loop.get());
- // We outlive |thread_|, so it's safe to use Unretained() here.
+ // We own |thread_|, so it's safe to use Unretained() here.
thread_.message_loop()->PostTask(
FROM_HERE,
base::Bind(&WatcherBackend::StartWatching,
@@ -218,12 +240,21 @@ WatcherID WatcherThreadManager::StartWatching(
}
void WatcherThreadManager::StopWatching(WatcherID watcher_id) {
- // We outlive |thread_|, so it's safe to use Unretained() here.
+ // We own |thread_|, so it's safe to use Unretained() here.
+ WaitState wait_state;
thread_.message_loop()->PostTask(
FROM_HERE,
base::Bind(&WatcherBackend::StopWatching,
base::Unretained(&backend_),
- watcher_id));
+ watcher_id,
+ &wait_state));
+
+ // We need to block until the handle is actually removed.
+ {
+ base::AutoLock auto_lock(wait_state.lock);
+ while (!wait_state.removed)
+ wait_state.condition.Wait();
+ }
}
WatcherThreadManager::WatcherThreadManager()

Powered by Google App Engine
This is Rietveld 408576698