Index: mojo/common/handle_watcher.cc |
diff --git a/mojo/common/handle_watcher.cc b/mojo/common/handle_watcher.cc |
index 84e8b64fb9ad7a93fd0fb5ca1b211178a5f3bb6b..0c7cdef63d5743300af530b84d29ce8e16e096c3 100644 |
--- a/mojo/common/handle_watcher.cc |
+++ b/mojo/common/handle_watcher.cc |
@@ -14,7 +14,9 @@ |
#include "base/message_loop/message_loop.h" |
#include "base/message_loop/message_loop_proxy.h" |
#include "base/synchronization/lock.h" |
+#include "base/synchronization/waitable_event.h" |
#include "base/threading/thread.h" |
+#include "base/threading/thread_restrictions.h" |
#include "base/time/time.h" |
#include "mojo/common/message_pump_mojo.h" |
#include "mojo/common/message_pump_mojo_handler.h" |
@@ -68,7 +70,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 signals |
+ // |event|. |
+ void StopWatching(WatcherID watcher_id, base::WaitableEvent* event); |
private: |
typedef std::map<Handle, WatchData> HandleToWatchDataMap; |
@@ -107,15 +112,16 @@ void WatcherBackend::StartWatching(const WatchData& data) { |
data.deadline); |
} |
-void WatcherBackend::StopWatching(WatcherID watcher_id) { |
+void WatcherBackend::StopWatching(WatcherID watcher_id, |
+ base::WaitableEvent* event) { |
// 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); |
+ } |
+ event->Signal(); |
} |
void WatcherBackend::RemoveAndNotify(const Handle& handle, |
@@ -153,6 +159,8 @@ void WatcherBackend::OnHandleError(const Handle& handle, MojoResult result) { |
// WatcherThreadManager manages the background thread that listens for handles |
// to be ready. All requests are handled by WatcherBackend. |
+} // namespace |
+ |
class WatcherThreadManager { |
public: |
~WatcherThreadManager(); |
@@ -208,7 +216,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 +226,18 @@ WatcherID WatcherThreadManager::StartWatching( |
} |
void WatcherThreadManager::StopWatching(WatcherID watcher_id) { |
- // We outlive |thread_|, so it's safe to use Unretained() here. |
+ base::ThreadRestrictions::ScopedAllowWait allow_wait; |
+ base::WaitableEvent event(true, false); |
+ // We own |thread_|, so it's safe to use Unretained() here. |
thread_.message_loop()->PostTask( |
FROM_HERE, |
base::Bind(&WatcherBackend::StopWatching, |
base::Unretained(&backend_), |
- watcher_id)); |
+ watcher_id, |
+ &event)); |
+ |
+ // We need to block until the handle is actually removed. |
+ event.Wait(); |
} |
WatcherThreadManager::WatcherThreadManager() |
@@ -233,8 +247,6 @@ WatcherThreadManager::WatcherThreadManager() |
thread_.StartWithOptions(thread_options); |
} |
-} // namespace |
- |
// HandleWatcher::State -------------------------------------------------------- |
// Represents the state of the HandleWatcher. Owns the user's callback and |