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/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" |
11 #include "base/lazy_instance.h" | 11 #include "base/lazy_instance.h" |
12 #include "base/memory/singleton.h" | 12 #include "base/memory/singleton.h" |
13 #include "base/memory/weak_ptr.h" | 13 #include "base/memory/weak_ptr.h" |
14 #include "base/message_loop/message_loop.h" | 14 #include "base/message_loop/message_loop.h" |
15 #include "base/message_loop/message_loop_proxy.h" | 15 #include "base/message_loop/message_loop_proxy.h" |
16 #include "base/synchronization/lock.h" | 16 #include "base/synchronization/lock.h" |
| 17 #include "base/synchronization/waitable_event.h" |
17 #include "base/threading/thread.h" | 18 #include "base/threading/thread.h" |
18 #include "base/time/time.h" | 19 #include "base/time/time.h" |
19 #include "mojo/common/message_pump_mojo.h" | 20 #include "mojo/common/message_pump_mojo.h" |
20 #include "mojo/common/message_pump_mojo_handler.h" | 21 #include "mojo/common/message_pump_mojo_handler.h" |
21 #include "mojo/common/time_helper.h" | 22 #include "mojo/common/time_helper.h" |
22 | 23 |
23 namespace mojo { | 24 namespace mojo { |
24 namespace common { | 25 namespace common { |
25 | 26 |
26 typedef int WatcherID; | 27 typedef int WatcherID; |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
61 | 62 |
62 // WatcherBackend is responsible for managing the requests and interacting with | 63 // WatcherBackend is responsible for managing the requests and interacting with |
63 // MessagePumpMojo. All access (outside of creation/destruction) is done on the | 64 // MessagePumpMojo. All access (outside of creation/destruction) is done on the |
64 // thread WatcherThreadManager creates. | 65 // thread WatcherThreadManager creates. |
65 class WatcherBackend : public MessagePumpMojoHandler { | 66 class WatcherBackend : public MessagePumpMojoHandler { |
66 public: | 67 public: |
67 WatcherBackend(); | 68 WatcherBackend(); |
68 virtual ~WatcherBackend(); | 69 virtual ~WatcherBackend(); |
69 | 70 |
70 void StartWatching(const WatchData& data); | 71 void StartWatching(const WatchData& data); |
71 void StopWatching(WatcherID watcher_id); | 72 |
| 73 // Cancels a previously schedule request to start a watch. When done signals |
| 74 // |event|. |
| 75 void StopWatching(WatcherID watcher_id, base::WaitableEvent* event); |
72 | 76 |
73 private: | 77 private: |
74 typedef std::map<Handle, WatchData> HandleToWatchDataMap; | 78 typedef std::map<Handle, WatchData> HandleToWatchDataMap; |
75 | 79 |
76 // Invoked when a handle needs to be removed and notified. | 80 // Invoked when a handle needs to be removed and notified. |
77 void RemoveAndNotify(const Handle& handle, MojoResult result); | 81 void RemoveAndNotify(const Handle& handle, MojoResult result); |
78 | 82 |
79 // Searches through |handle_to_data_| for |watcher_id|. Returns true if found | 83 // Searches through |handle_to_data_| for |watcher_id|. Returns true if found |
80 // and sets |handle| to the Handle. Returns false if not a known id. | 84 // and sets |handle| to the Handle. Returns false if not a known id. |
81 bool GetMojoHandleByWatcherID(WatcherID watcher_id, Handle* handle) const; | 85 bool GetMojoHandleByWatcherID(WatcherID watcher_id, Handle* handle) const; |
(...skipping 18 matching lines...) Expand all Loading... |
100 RemoveAndNotify(data.handle, MOJO_RESULT_CANCELLED); | 104 RemoveAndNotify(data.handle, MOJO_RESULT_CANCELLED); |
101 | 105 |
102 DCHECK_EQ(0u, handle_to_data_.count(data.handle)); | 106 DCHECK_EQ(0u, handle_to_data_.count(data.handle)); |
103 | 107 |
104 handle_to_data_[data.handle] = data; | 108 handle_to_data_[data.handle] = data; |
105 message_pump_mojo->AddHandler(this, data.handle, | 109 message_pump_mojo->AddHandler(this, data.handle, |
106 data.handle_signals, | 110 data.handle_signals, |
107 data.deadline); | 111 data.deadline); |
108 } | 112 } |
109 | 113 |
110 void WatcherBackend::StopWatching(WatcherID watcher_id) { | 114 void WatcherBackend::StopWatching(WatcherID watcher_id, |
| 115 base::WaitableEvent* event) { |
111 // Because of the thread hop it is entirely possible to get here and not | 116 // Because of the thread hop it is entirely possible to get here and not |
112 // have a valid handle registered for |watcher_id|. | 117 // have a valid handle registered for |watcher_id|. |
113 Handle handle; | 118 Handle handle; |
114 if (!GetMojoHandleByWatcherID(watcher_id, &handle)) | 119 if (GetMojoHandleByWatcherID(watcher_id, &handle)) { |
115 return; | 120 handle_to_data_.erase(handle); |
116 | 121 message_pump_mojo->RemoveHandler(handle); |
117 handle_to_data_.erase(handle); | 122 } |
118 message_pump_mojo->RemoveHandler(handle); | 123 event->Signal(); |
119 } | 124 } |
120 | 125 |
121 void WatcherBackend::RemoveAndNotify(const Handle& handle, | 126 void WatcherBackend::RemoveAndNotify(const Handle& handle, |
122 MojoResult result) { | 127 MojoResult result) { |
123 if (handle_to_data_.count(handle) == 0) | 128 if (handle_to_data_.count(handle) == 0) |
124 return; | 129 return; |
125 | 130 |
126 const WatchData data(handle_to_data_[handle]); | 131 const WatchData data(handle_to_data_[handle]); |
127 handle_to_data_.erase(handle); | 132 handle_to_data_.erase(handle); |
128 message_pump_mojo->RemoveHandler(handle); | 133 message_pump_mojo->RemoveHandler(handle); |
(...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
201 const base::Callback<void(MojoResult)>& callback) { | 206 const base::Callback<void(MojoResult)>& callback) { |
202 WatchData data; | 207 WatchData data; |
203 data.id = watcher_id_generator_.GetNext(); | 208 data.id = watcher_id_generator_.GetNext(); |
204 data.handle = handle; | 209 data.handle = handle; |
205 data.callback = callback; | 210 data.callback = callback; |
206 data.handle_signals = handle_signals; | 211 data.handle_signals = handle_signals; |
207 data.deadline = deadline; | 212 data.deadline = deadline; |
208 data.message_loop = base::MessageLoopProxy::current(); | 213 data.message_loop = base::MessageLoopProxy::current(); |
209 DCHECK_NE(static_cast<base::MessageLoopProxy*>(NULL), | 214 DCHECK_NE(static_cast<base::MessageLoopProxy*>(NULL), |
210 data.message_loop.get()); | 215 data.message_loop.get()); |
211 // We outlive |thread_|, so it's safe to use Unretained() here. | 216 // We own |thread_|, so it's safe to use Unretained() here. |
212 thread_.message_loop()->PostTask( | 217 thread_.message_loop()->PostTask( |
213 FROM_HERE, | 218 FROM_HERE, |
214 base::Bind(&WatcherBackend::StartWatching, | 219 base::Bind(&WatcherBackend::StartWatching, |
215 base::Unretained(&backend_), | 220 base::Unretained(&backend_), |
216 data)); | 221 data)); |
217 return data.id; | 222 return data.id; |
218 } | 223 } |
219 | 224 |
220 void WatcherThreadManager::StopWatching(WatcherID watcher_id) { | 225 void WatcherThreadManager::StopWatching(WatcherID watcher_id) { |
221 // We outlive |thread_|, so it's safe to use Unretained() here. | 226 // We own |thread_|, so it's safe to use Unretained() here. |
| 227 base::WaitableEvent event(true, false); |
222 thread_.message_loop()->PostTask( | 228 thread_.message_loop()->PostTask( |
223 FROM_HERE, | 229 FROM_HERE, |
224 base::Bind(&WatcherBackend::StopWatching, | 230 base::Bind(&WatcherBackend::StopWatching, |
225 base::Unretained(&backend_), | 231 base::Unretained(&backend_), |
226 watcher_id)); | 232 watcher_id, |
| 233 &event)); |
| 234 |
| 235 // We need to block until the handle is actually removed. |
| 236 event.Wait(); |
227 } | 237 } |
228 | 238 |
229 WatcherThreadManager::WatcherThreadManager() | 239 WatcherThreadManager::WatcherThreadManager() |
230 : thread_(kWatcherThreadName) { | 240 : thread_(kWatcherThreadName) { |
231 base::Thread::Options thread_options; | 241 base::Thread::Options thread_options; |
232 thread_options.message_pump_factory = base::Bind(&CreateMessagePumpMojo); | 242 thread_options.message_pump_factory = base::Bind(&CreateMessagePumpMojo); |
233 thread_.StartWithOptions(thread_options); | 243 thread_.StartWithOptions(thread_options); |
234 } | 244 } |
235 | 245 |
236 } // namespace | 246 } // namespace |
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
303 | 313 |
304 state_.reset(new State(this, handle, handle_signals, deadline, callback)); | 314 state_.reset(new State(this, handle, handle_signals, deadline, callback)); |
305 } | 315 } |
306 | 316 |
307 void HandleWatcher::Stop() { | 317 void HandleWatcher::Stop() { |
308 state_.reset(); | 318 state_.reset(); |
309 } | 319 } |
310 | 320 |
311 } // namespace common | 321 } // namespace common |
312 } // namespace mojo | 322 } // namespace mojo |
OLD | NEW |