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

Side by Side 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: more java fixes 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 unified diff | Download patch | Annotate | Revision Log
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"
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"
19 #include "base/threading/thread_restrictions.h"
18 #include "base/time/time.h" 20 #include "base/time/time.h"
19 #include "mojo/common/message_pump_mojo.h" 21 #include "mojo/common/message_pump_mojo.h"
20 #include "mojo/common/message_pump_mojo_handler.h" 22 #include "mojo/common/message_pump_mojo_handler.h"
21 #include "mojo/common/time_helper.h" 23 #include "mojo/common/time_helper.h"
22 24
23 namespace mojo { 25 namespace mojo {
24 namespace common { 26 namespace common {
25 27
26 typedef int WatcherID; 28 typedef int WatcherID;
27 29
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
61 63
62 // WatcherBackend is responsible for managing the requests and interacting with 64 // WatcherBackend is responsible for managing the requests and interacting with
63 // MessagePumpMojo. All access (outside of creation/destruction) is done on the 65 // MessagePumpMojo. All access (outside of creation/destruction) is done on the
64 // thread WatcherThreadManager creates. 66 // thread WatcherThreadManager creates.
65 class WatcherBackend : public MessagePumpMojoHandler { 67 class WatcherBackend : public MessagePumpMojoHandler {
66 public: 68 public:
67 WatcherBackend(); 69 WatcherBackend();
68 virtual ~WatcherBackend(); 70 virtual ~WatcherBackend();
69 71
70 void StartWatching(const WatchData& data); 72 void StartWatching(const WatchData& data);
71 void StopWatching(WatcherID watcher_id); 73
74 // Cancels a previously schedule request to start a watch. When done signals
75 // |event|.
76 void StopWatching(WatcherID watcher_id, base::WaitableEvent* event);
72 77
73 private: 78 private:
74 typedef std::map<Handle, WatchData> HandleToWatchDataMap; 79 typedef std::map<Handle, WatchData> HandleToWatchDataMap;
75 80
76 // Invoked when a handle needs to be removed and notified. 81 // Invoked when a handle needs to be removed and notified.
77 void RemoveAndNotify(const Handle& handle, MojoResult result); 82 void RemoveAndNotify(const Handle& handle, MojoResult result);
78 83
79 // Searches through |handle_to_data_| for |watcher_id|. Returns true if found 84 // 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. 85 // and sets |handle| to the Handle. Returns false if not a known id.
81 bool GetMojoHandleByWatcherID(WatcherID watcher_id, Handle* handle) const; 86 bool GetMojoHandleByWatcherID(WatcherID watcher_id, Handle* handle) const;
(...skipping 18 matching lines...) Expand all
100 RemoveAndNotify(data.handle, MOJO_RESULT_CANCELLED); 105 RemoveAndNotify(data.handle, MOJO_RESULT_CANCELLED);
101 106
102 DCHECK_EQ(0u, handle_to_data_.count(data.handle)); 107 DCHECK_EQ(0u, handle_to_data_.count(data.handle));
103 108
104 handle_to_data_[data.handle] = data; 109 handle_to_data_[data.handle] = data;
105 message_pump_mojo->AddHandler(this, data.handle, 110 message_pump_mojo->AddHandler(this, data.handle,
106 data.handle_signals, 111 data.handle_signals,
107 data.deadline); 112 data.deadline);
108 } 113 }
109 114
110 void WatcherBackend::StopWatching(WatcherID watcher_id) { 115 void WatcherBackend::StopWatching(WatcherID watcher_id,
116 base::WaitableEvent* event) {
111 // Because of the thread hop it is entirely possible to get here and not 117 // Because of the thread hop it is entirely possible to get here and not
112 // have a valid handle registered for |watcher_id|. 118 // have a valid handle registered for |watcher_id|.
113 Handle handle; 119 Handle handle;
114 if (!GetMojoHandleByWatcherID(watcher_id, &handle)) 120 if (GetMojoHandleByWatcherID(watcher_id, &handle)) {
115 return; 121 handle_to_data_.erase(handle);
116 122 message_pump_mojo->RemoveHandler(handle);
117 handle_to_data_.erase(handle); 123 }
118 message_pump_mojo->RemoveHandler(handle); 124 event->Signal();
119 } 125 }
120 126
121 void WatcherBackend::RemoveAndNotify(const Handle& handle, 127 void WatcherBackend::RemoveAndNotify(const Handle& handle,
122 MojoResult result) { 128 MojoResult result) {
123 if (handle_to_data_.count(handle) == 0) 129 if (handle_to_data_.count(handle) == 0)
124 return; 130 return;
125 131
126 const WatchData data(handle_to_data_[handle]); 132 const WatchData data(handle_to_data_[handle]);
127 handle_to_data_.erase(handle); 133 handle_to_data_.erase(handle);
128 message_pump_mojo->RemoveHandler(handle); 134 message_pump_mojo->RemoveHandler(handle);
(...skipping 17 matching lines...) Expand all
146 } 152 }
147 153
148 void WatcherBackend::OnHandleError(const Handle& handle, MojoResult result) { 154 void WatcherBackend::OnHandleError(const Handle& handle, MojoResult result) {
149 RemoveAndNotify(handle, result); 155 RemoveAndNotify(handle, result);
150 } 156 }
151 157
152 // WatcherThreadManager -------------------------------------------------------- 158 // WatcherThreadManager --------------------------------------------------------
153 159
154 // WatcherThreadManager manages the background thread that listens for handles 160 // WatcherThreadManager manages the background thread that listens for handles
155 // to be ready. All requests are handled by WatcherBackend. 161 // to be ready. All requests are handled by WatcherBackend.
162 } // namespace
163
156 class WatcherThreadManager { 164 class WatcherThreadManager {
157 public: 165 public:
158 ~WatcherThreadManager(); 166 ~WatcherThreadManager();
159 167
160 // Returns the shared instance. 168 // Returns the shared instance.
161 static WatcherThreadManager* GetInstance(); 169 static WatcherThreadManager* GetInstance();
162 170
163 // Starts watching the requested handle. Returns a unique ID that is used to 171 // Starts watching the requested handle. Returns a unique ID that is used to
164 // stop watching the handle. When the handle is ready |callback| is notified 172 // stop watching the handle. When the handle is ready |callback| is notified
165 // on the thread StartWatching() was invoked on. 173 // on the thread StartWatching() was invoked on.
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
201 const base::Callback<void(MojoResult)>& callback) { 209 const base::Callback<void(MojoResult)>& callback) {
202 WatchData data; 210 WatchData data;
203 data.id = watcher_id_generator_.GetNext(); 211 data.id = watcher_id_generator_.GetNext();
204 data.handle = handle; 212 data.handle = handle;
205 data.callback = callback; 213 data.callback = callback;
206 data.handle_signals = handle_signals; 214 data.handle_signals = handle_signals;
207 data.deadline = deadline; 215 data.deadline = deadline;
208 data.message_loop = base::MessageLoopProxy::current(); 216 data.message_loop = base::MessageLoopProxy::current();
209 DCHECK_NE(static_cast<base::MessageLoopProxy*>(NULL), 217 DCHECK_NE(static_cast<base::MessageLoopProxy*>(NULL),
210 data.message_loop.get()); 218 data.message_loop.get());
211 // We outlive |thread_|, so it's safe to use Unretained() here. 219 // We own |thread_|, so it's safe to use Unretained() here.
212 thread_.message_loop()->PostTask( 220 thread_.message_loop()->PostTask(
213 FROM_HERE, 221 FROM_HERE,
214 base::Bind(&WatcherBackend::StartWatching, 222 base::Bind(&WatcherBackend::StartWatching,
215 base::Unretained(&backend_), 223 base::Unretained(&backend_),
216 data)); 224 data));
217 return data.id; 225 return data.id;
218 } 226 }
219 227
220 void WatcherThreadManager::StopWatching(WatcherID watcher_id) { 228 void WatcherThreadManager::StopWatching(WatcherID watcher_id) {
221 // We outlive |thread_|, so it's safe to use Unretained() here. 229 base::ThreadRestrictions::ScopedAllowWait allow_wait;
230 base::WaitableEvent event(true, false);
231 // We own |thread_|, so it's safe to use Unretained() here.
222 thread_.message_loop()->PostTask( 232 thread_.message_loop()->PostTask(
223 FROM_HERE, 233 FROM_HERE,
224 base::Bind(&WatcherBackend::StopWatching, 234 base::Bind(&WatcherBackend::StopWatching,
225 base::Unretained(&backend_), 235 base::Unretained(&backend_),
226 watcher_id)); 236 watcher_id,
237 &event));
238
239 // We need to block until the handle is actually removed.
240 event.Wait();
227 } 241 }
228 242
229 WatcherThreadManager::WatcherThreadManager() 243 WatcherThreadManager::WatcherThreadManager()
230 : thread_(kWatcherThreadName) { 244 : thread_(kWatcherThreadName) {
231 base::Thread::Options thread_options; 245 base::Thread::Options thread_options;
232 thread_options.message_pump_factory = base::Bind(&CreateMessagePumpMojo); 246 thread_options.message_pump_factory = base::Bind(&CreateMessagePumpMojo);
233 thread_.StartWithOptions(thread_options); 247 thread_.StartWithOptions(thread_options);
234 } 248 }
235 249
236 } // namespace
237
238 // HandleWatcher::State -------------------------------------------------------- 250 // HandleWatcher::State --------------------------------------------------------
239 251
240 // Represents the state of the HandleWatcher. Owns the user's callback and 252 // Represents the state of the HandleWatcher. Owns the user's callback and
241 // monitors the current thread's MessageLoop to know when to force the callback 253 // monitors the current thread's MessageLoop to know when to force the callback
242 // to run (with an error) even though the pipe hasn't been signaled yet. 254 // to run (with an error) even though the pipe hasn't been signaled yet.
243 class HandleWatcher::State : public base::MessageLoop::DestructionObserver { 255 class HandleWatcher::State : public base::MessageLoop::DestructionObserver {
244 public: 256 public:
245 State(HandleWatcher* watcher, 257 State(HandleWatcher* watcher,
246 const Handle& handle, 258 const Handle& handle,
247 MojoHandleSignals handle_signals, 259 MojoHandleSignals handle_signals,
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after
303 315
304 state_.reset(new State(this, handle, handle_signals, deadline, callback)); 316 state_.reset(new State(this, handle, handle_signals, deadline, callback));
305 } 317 }
306 318
307 void HandleWatcher::Stop() { 319 void HandleWatcher::Stop() {
308 state_.reset(); 320 state_.reset();
309 } 321 }
310 322
311 } // namespace common 323 } // namespace common
312 } // namespace mojo 324 } // namespace mojo
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698