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 #include <set> | 8 #include <set> |
9 #include <vector> | 9 #include <vector> |
10 | 10 |
(...skipping 29 matching lines...) Expand all Loading... |
40 // Returns the shared instance. | 40 // Returns the shared instance. |
41 static WatcherThreadManager* GetInstance(); | 41 static WatcherThreadManager* GetInstance(); |
42 | 42 |
43 // Starts watching the requested handle. Returns a unique ID that is used to | 43 // Starts watching the requested handle. Returns a unique ID that is used to |
44 // stop watching the handle. When the handle is ready |callback| is notified | 44 // stop watching the handle. When the handle is ready |callback| is notified |
45 // on the thread StartWatching() was invoked on. | 45 // on the thread StartWatching() was invoked on. |
46 // This may be invoked on any thread. | 46 // This may be invoked on any thread. |
47 WatcherID StartWatching(MojoHandle handle, | 47 WatcherID StartWatching(MojoHandle handle, |
48 MojoWaitFlags wait_flags, | 48 MojoWaitFlags wait_flags, |
49 base::TimeTicks deadline, | 49 base::TimeTicks deadline, |
50 const base::Callback<void(MojoResult)>& callback); | 50 const base::Closure& callback); |
51 | 51 |
52 // Stops watching a handle. | 52 // Stops watching a handle. |
53 void StopWatching(WatcherID watcher_id); | 53 void StopWatching(WatcherID watcher_id); |
54 | 54 |
55 private: | 55 private: |
56 friend struct base::DefaultLazyInstanceTraits<WatcherThreadManager>; | 56 friend struct base::DefaultLazyInstanceTraits<WatcherThreadManager>; |
57 | 57 |
58 // Tracks a single request. | 58 // Tracks a single request. |
59 struct HandleAndCallback { | 59 struct HandleAndCallback { |
60 HandleAndCallback() | 60 HandleAndCallback() |
61 : handle(MOJO_HANDLE_INVALID), | 61 : handle(MOJO_HANDLE_INVALID), |
62 wait_flags(MOJO_WAIT_FLAG_NONE), | 62 wait_flags(MOJO_WAIT_FLAG_NONE), |
63 message_loop(NULL) {} | 63 message_loop(NULL) {} |
64 | 64 |
65 MojoHandle handle; | 65 MojoHandle handle; |
66 MojoWaitFlags wait_flags; | 66 MojoWaitFlags wait_flags; |
67 base::TimeTicks deadline; | 67 base::TimeTicks deadline; |
68 base::Callback<void(MojoResult)> callback; | 68 base::Closure callback; |
69 scoped_refptr<base::MessageLoopProxy> message_loop; | 69 scoped_refptr<base::MessageLoopProxy> message_loop; |
70 }; | 70 }; |
71 | 71 |
72 // Contains the state needed for MojoWaitMany. | 72 // Contains the state needed for MojoWaitMany. |
73 // NOTE: |handles| and |wait_flags| are separate vectors to make it easy to | 73 // NOTE: |handles| and |wait_flags| are separate vectors to make it easy to |
74 // pass to MojoWaitMany. | 74 // pass to MojoWaitMany. |
75 struct WaitState { | 75 struct WaitState { |
76 // List of ids. | 76 // List of ids. |
77 std::vector<WatcherID> ids; | 77 std::vector<WatcherID> ids; |
78 | 78 |
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
131 | 131 |
132 DISALLOW_COPY_AND_ASSIGN(WatcherThreadManager); | 132 DISALLOW_COPY_AND_ASSIGN(WatcherThreadManager); |
133 }; | 133 }; |
134 | 134 |
135 WatcherThreadManager* WatcherThreadManager::GetInstance() { | 135 WatcherThreadManager* WatcherThreadManager::GetInstance() { |
136 static base::LazyInstance<WatcherThreadManager> instance = | 136 static base::LazyInstance<WatcherThreadManager> instance = |
137 LAZY_INSTANCE_INITIALIZER; | 137 LAZY_INSTANCE_INITIALIZER; |
138 return &instance.Get(); | 138 return &instance.Get(); |
139 } | 139 } |
140 | 140 |
141 WatcherID WatcherThreadManager::StartWatching( | 141 WatcherID WatcherThreadManager::StartWatching(MojoHandle handle, |
142 MojoHandle handle, | 142 MojoWaitFlags wait_flags, |
143 MojoWaitFlags wait_flags, | 143 base::TimeTicks deadline, |
144 base::TimeTicks deadline, | 144 const base::Closure& callback) { |
145 const base::Callback<void(MojoResult)>& callback) { | |
146 WatcherID id = 0; | 145 WatcherID id = 0; |
147 { | 146 { |
148 static int next_id = 0; | 147 static int next_id = 0; |
149 base::AutoLock lock(lock_); | 148 base::AutoLock lock(lock_); |
150 // TODO(sky): worry about overflow? | 149 // TODO(sky): worry about overflow? |
151 id = ++next_id; | 150 id = ++next_id; |
152 id_to_callback_[id].handle = handle; | 151 id_to_callback_[id].handle = handle; |
153 id_to_callback_[id].callback = callback; | 152 id_to_callback_[id].callback = callback; |
154 id_to_callback_[id].wait_flags = wait_flags; | 153 id_to_callback_[id].wait_flags = wait_flags; |
155 id_to_callback_[id].deadline = deadline; | 154 id_to_callback_[id].deadline = deadline; |
(...skipping 102 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
258 void WatcherThreadManager::RemoveAndNotify(WatcherID id, MojoResult result) { | 257 void WatcherThreadManager::RemoveAndNotify(WatcherID id, MojoResult result) { |
259 HandleAndCallback to_notify; | 258 HandleAndCallback to_notify; |
260 { | 259 { |
261 base::AutoLock lock(lock_); | 260 base::AutoLock lock(lock_); |
262 IDToCallbackMap::iterator i = id_to_callback_.find(id); | 261 IDToCallbackMap::iterator i = id_to_callback_.find(id); |
263 if (i == id_to_callback_.end()) | 262 if (i == id_to_callback_.end()) |
264 return; | 263 return; |
265 to_notify = i->second; | 264 to_notify = i->second; |
266 id_to_callback_.erase(i); | 265 id_to_callback_.erase(i); |
267 } | 266 } |
268 to_notify.message_loop->PostTask(FROM_HERE, | 267 to_notify.message_loop->PostTask(FROM_HERE, to_notify.callback); |
269 base::Bind(to_notify.callback, result)); | |
270 } | 268 } |
271 | 269 |
272 void WatcherThreadManager::RemoveHandle(MojoHandle handle) { | 270 void WatcherThreadManager::RemoveHandle(MojoHandle handle) { |
273 { | 271 { |
274 base::AutoLock lock(lock_); | 272 base::AutoLock lock(lock_); |
275 for (IDToCallbackMap::iterator i = id_to_callback_.begin(); | 273 for (IDToCallbackMap::iterator i = id_to_callback_.begin(); |
276 i != id_to_callback_.end(); ) { | 274 i != id_to_callback_.end(); ) { |
277 if (i->second.handle == handle) { | 275 if (i->second.handle == handle) { |
278 id_to_callback_.erase(i++); | 276 id_to_callback_.erase(i++); |
279 } else { | 277 } else { |
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
323 explicit StartState(HandleWatcher* watcher) : weak_factory(watcher) { | 321 explicit StartState(HandleWatcher* watcher) : weak_factory(watcher) { |
324 } | 322 } |
325 | 323 |
326 ~StartState() { | 324 ~StartState() { |
327 } | 325 } |
328 | 326 |
329 // ID assigned by WatcherThreadManager. | 327 // ID assigned by WatcherThreadManager. |
330 WatcherID watcher_id; | 328 WatcherID watcher_id; |
331 | 329 |
332 // Callback to notify when done. | 330 // Callback to notify when done. |
333 base::Callback<void(MojoResult)> callback; | 331 base::Closure callback; |
334 | 332 |
335 // When Start() is invoked a callback is passed to WatcherThreadManager | 333 // When Start() is invoked a callback is passed to WatcherThreadManager |
336 // using a WeakRef from |weak_refactory_|. The callback invokes | 334 // using a WeakRef from |weak_refactory_|. The callback invokes |
337 // OnHandleReady() (on the thread Start() is invoked from) which in turn | 335 // OnHandleReady() (on the thread Start() is invoked from) which in turn |
338 // notifies |callback_|. Doing this allows us to reset state when the handle | 336 // notifies |callback_|. Doing this allows us to reset state when the handle |
339 // is ready, and then notify the callback. Doing this also means Stop() | 337 // is ready, and then notify the callback. Doing this also means Stop() |
340 // cancels any pending callbacks that may be inflight. | 338 // cancels any pending callbacks that may be inflight. |
341 base::WeakPtrFactory<HandleWatcher> weak_factory; | 339 base::WeakPtrFactory<HandleWatcher> weak_factory; |
342 }; | 340 }; |
343 | 341 |
344 // HandleWatcher --------------------------------------------------------------- | 342 // HandleWatcher --------------------------------------------------------------- |
345 | 343 |
346 // static | 344 // static |
347 base::TickClock* HandleWatcher::tick_clock_ = NULL; | 345 base::TickClock* HandleWatcher::tick_clock_ = NULL; |
348 | 346 |
349 HandleWatcher::HandleWatcher() { | 347 HandleWatcher::HandleWatcher() { |
350 } | 348 } |
351 | 349 |
352 HandleWatcher::~HandleWatcher() { | 350 HandleWatcher::~HandleWatcher() { |
353 Stop(); | 351 Stop(); |
354 } | 352 } |
355 | 353 |
356 void HandleWatcher::Start(MojoHandle handle, | 354 void HandleWatcher::Start(MojoHandle handle, |
357 MojoWaitFlags wait_flags, | 355 MojoWaitFlags wait_flags, |
358 MojoDeadline deadline, | 356 MojoDeadline deadline, |
359 const base::Callback<void(MojoResult)>& callback) { | 357 const base::Closure& callback) { |
360 DCHECK_NE(MOJO_HANDLE_INVALID, handle); | 358 DCHECK_NE(MOJO_HANDLE_INVALID, handle); |
361 DCHECK_NE(MOJO_WAIT_FLAG_NONE, wait_flags); | 359 DCHECK_NE(MOJO_WAIT_FLAG_NONE, wait_flags); |
362 | 360 |
363 Stop(); | 361 Stop(); |
364 | 362 |
365 start_state_.reset(new StartState(this)); | 363 start_state_.reset(new StartState(this)); |
366 start_state_->callback = callback; | 364 start_state_->callback = callback; |
367 start_state_->watcher_id = | 365 start_state_->watcher_id = |
368 WatcherThreadManager::GetInstance()->StartWatching( | 366 WatcherThreadManager::GetInstance()->StartWatching( |
369 handle, | 367 handle, |
370 wait_flags, | 368 wait_flags, |
371 MojoDeadlineToTimeTicks(deadline), | 369 MojoDeadlineToTimeTicks(deadline), |
372 base::Bind(&HandleWatcher::OnHandleReady, | 370 base::Bind(&HandleWatcher::OnHandleReady, |
373 start_state_->weak_factory.GetWeakPtr())); | 371 start_state_->weak_factory.GetWeakPtr())); |
374 } | 372 } |
375 | 373 |
376 void HandleWatcher::Stop() { | 374 void HandleWatcher::Stop() { |
377 if (!start_state_.get()) | 375 if (!start_state_.get()) |
378 return; | 376 return; |
379 | 377 |
380 scoped_ptr<StartState> old_state(start_state_.Pass()); | 378 scoped_ptr<StartState> old_state(start_state_.Pass()); |
381 WatcherThreadManager::GetInstance()->StopWatching(old_state->watcher_id); | 379 WatcherThreadManager::GetInstance()->StopWatching(old_state->watcher_id); |
382 } | 380 } |
383 | 381 |
384 void HandleWatcher::OnHandleReady(MojoResult result) { | 382 void HandleWatcher::OnHandleReady() { |
385 DCHECK(start_state_.get()); | 383 DCHECK(start_state_.get()); |
386 scoped_ptr<StartState> old_state(start_state_.Pass()); | 384 scoped_ptr<StartState> old_state(start_state_.Pass()); |
387 old_state->callback.Run(result); | 385 old_state->callback.Run(); |
388 | |
389 // NOTE: We may have been deleted during callback execution. | |
390 } | 386 } |
391 | 387 |
392 // static | 388 // static |
393 base::TimeTicks HandleWatcher::NowTicks() { | 389 base::TimeTicks HandleWatcher::NowTicks() { |
394 return tick_clock_ ? tick_clock_->NowTicks() : base::TimeTicks::Now(); | 390 return tick_clock_ ? tick_clock_->NowTicks() : base::TimeTicks::Now(); |
395 } | 391 } |
396 | 392 |
397 // static | 393 // static |
398 base::TimeTicks HandleWatcher::MojoDeadlineToTimeTicks(MojoDeadline deadline) { | 394 base::TimeTicks HandleWatcher::MojoDeadlineToTimeTicks(MojoDeadline deadline) { |
399 return deadline == MOJO_DEADLINE_INDEFINITE ? base::TimeTicks() : | 395 return deadline == MOJO_DEADLINE_INDEFINITE ? base::TimeTicks() : |
400 NowTicks() + base::TimeDelta::FromMicroseconds(deadline); | 396 NowTicks() + base::TimeDelta::FromMicroseconds(deadline); |
401 } | 397 } |
402 | 398 |
403 } // namespace common | 399 } // namespace common |
404 } // namespace mojo | 400 } // namespace mojo |
OLD | NEW |