| 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::Closure& callback); | 50 const base::Callback<void(MojoResult)>& 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::Closure callback; | 68 base::Callback<void(MojoResult)> 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(MojoHandle handle, | 141 WatcherID WatcherThreadManager::StartWatching( |
| 142 MojoWaitFlags wait_flags, | 142 MojoHandle handle, |
| 143 base::TimeTicks deadline, | 143 MojoWaitFlags wait_flags, |
| 144 const base::Closure& callback) { | 144 base::TimeTicks deadline, |
| 145 const base::Callback<void(MojoResult)>& callback) { |
| 145 WatcherID id = 0; | 146 WatcherID id = 0; |
| 146 { | 147 { |
| 147 static int next_id = 0; | 148 static int next_id = 0; |
| 148 base::AutoLock lock(lock_); | 149 base::AutoLock lock(lock_); |
| 149 // TODO(sky): worry about overflow? | 150 // TODO(sky): worry about overflow? |
| 150 id = ++next_id; | 151 id = ++next_id; |
| 151 id_to_callback_[id].handle = handle; | 152 id_to_callback_[id].handle = handle; |
| 152 id_to_callback_[id].callback = callback; | 153 id_to_callback_[id].callback = callback; |
| 153 id_to_callback_[id].wait_flags = wait_flags; | 154 id_to_callback_[id].wait_flags = wait_flags; |
| 154 id_to_callback_[id].deadline = deadline; | 155 id_to_callback_[id].deadline = deadline; |
| (...skipping 102 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 257 void WatcherThreadManager::RemoveAndNotify(WatcherID id, MojoResult result) { | 258 void WatcherThreadManager::RemoveAndNotify(WatcherID id, MojoResult result) { |
| 258 HandleAndCallback to_notify; | 259 HandleAndCallback to_notify; |
| 259 { | 260 { |
| 260 base::AutoLock lock(lock_); | 261 base::AutoLock lock(lock_); |
| 261 IDToCallbackMap::iterator i = id_to_callback_.find(id); | 262 IDToCallbackMap::iterator i = id_to_callback_.find(id); |
| 262 if (i == id_to_callback_.end()) | 263 if (i == id_to_callback_.end()) |
| 263 return; | 264 return; |
| 264 to_notify = i->second; | 265 to_notify = i->second; |
| 265 id_to_callback_.erase(i); | 266 id_to_callback_.erase(i); |
| 266 } | 267 } |
| 267 to_notify.message_loop->PostTask(FROM_HERE, to_notify.callback); | 268 to_notify.message_loop->PostTask(FROM_HERE, |
| 269 base::Bind(to_notify.callback, result)); |
| 268 } | 270 } |
| 269 | 271 |
| 270 void WatcherThreadManager::RemoveHandle(MojoHandle handle) { | 272 void WatcherThreadManager::RemoveHandle(MojoHandle handle) { |
| 271 { | 273 { |
| 272 base::AutoLock lock(lock_); | 274 base::AutoLock lock(lock_); |
| 273 for (IDToCallbackMap::iterator i = id_to_callback_.begin(); | 275 for (IDToCallbackMap::iterator i = id_to_callback_.begin(); |
| 274 i != id_to_callback_.end(); ) { | 276 i != id_to_callback_.end(); ) { |
| 275 if (i->second.handle == handle) { | 277 if (i->second.handle == handle) { |
| 276 id_to_callback_.erase(i++); | 278 id_to_callback_.erase(i++); |
| 277 } else { | 279 } else { |
| (...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 321 explicit StartState(HandleWatcher* watcher) : weak_factory(watcher) { | 323 explicit StartState(HandleWatcher* watcher) : weak_factory(watcher) { |
| 322 } | 324 } |
| 323 | 325 |
| 324 ~StartState() { | 326 ~StartState() { |
| 325 } | 327 } |
| 326 | 328 |
| 327 // ID assigned by WatcherThreadManager. | 329 // ID assigned by WatcherThreadManager. |
| 328 WatcherID watcher_id; | 330 WatcherID watcher_id; |
| 329 | 331 |
| 330 // Callback to notify when done. | 332 // Callback to notify when done. |
| 331 base::Closure callback; | 333 base::Callback<void(MojoResult)> callback; |
| 332 | 334 |
| 333 // When Start() is invoked a callback is passed to WatcherThreadManager | 335 // When Start() is invoked a callback is passed to WatcherThreadManager |
| 334 // using a WeakRef from |weak_refactory_|. The callback invokes | 336 // using a WeakRef from |weak_refactory_|. The callback invokes |
| 335 // OnHandleReady() (on the thread Start() is invoked from) which in turn | 337 // OnHandleReady() (on the thread Start() is invoked from) which in turn |
| 336 // notifies |callback_|. Doing this allows us to reset state when the handle | 338 // notifies |callback_|. Doing this allows us to reset state when the handle |
| 337 // is ready, and then notify the callback. Doing this also means Stop() | 339 // is ready, and then notify the callback. Doing this also means Stop() |
| 338 // cancels any pending callbacks that may be inflight. | 340 // cancels any pending callbacks that may be inflight. |
| 339 base::WeakPtrFactory<HandleWatcher> weak_factory; | 341 base::WeakPtrFactory<HandleWatcher> weak_factory; |
| 340 }; | 342 }; |
| 341 | 343 |
| 342 // HandleWatcher --------------------------------------------------------------- | 344 // HandleWatcher --------------------------------------------------------------- |
| 343 | 345 |
| 344 // static | 346 // static |
| 345 base::TickClock* HandleWatcher::tick_clock_ = NULL; | 347 base::TickClock* HandleWatcher::tick_clock_ = NULL; |
| 346 | 348 |
| 347 HandleWatcher::HandleWatcher() { | 349 HandleWatcher::HandleWatcher() { |
| 348 } | 350 } |
| 349 | 351 |
| 350 HandleWatcher::~HandleWatcher() { | 352 HandleWatcher::~HandleWatcher() { |
| 351 Stop(); | 353 Stop(); |
| 352 } | 354 } |
| 353 | 355 |
| 354 void HandleWatcher::Start(MojoHandle handle, | 356 void HandleWatcher::Start(MojoHandle handle, |
| 355 MojoWaitFlags wait_flags, | 357 MojoWaitFlags wait_flags, |
| 356 MojoDeadline deadline, | 358 MojoDeadline deadline, |
| 357 const base::Closure& callback) { | 359 const base::Callback<void(MojoResult)>& callback) { |
| 358 DCHECK_NE(MOJO_HANDLE_INVALID, handle); | 360 DCHECK_NE(MOJO_HANDLE_INVALID, handle); |
| 359 DCHECK_NE(MOJO_WAIT_FLAG_NONE, wait_flags); | 361 DCHECK_NE(MOJO_WAIT_FLAG_NONE, wait_flags); |
| 360 | 362 |
| 361 Stop(); | 363 Stop(); |
| 362 | 364 |
| 363 start_state_.reset(new StartState(this)); | 365 start_state_.reset(new StartState(this)); |
| 364 start_state_->callback = callback; | 366 start_state_->callback = callback; |
| 365 start_state_->watcher_id = | 367 start_state_->watcher_id = |
| 366 WatcherThreadManager::GetInstance()->StartWatching( | 368 WatcherThreadManager::GetInstance()->StartWatching( |
| 367 handle, | 369 handle, |
| 368 wait_flags, | 370 wait_flags, |
| 369 MojoDeadlineToTimeTicks(deadline), | 371 MojoDeadlineToTimeTicks(deadline), |
| 370 base::Bind(&HandleWatcher::OnHandleReady, | 372 base::Bind(&HandleWatcher::OnHandleReady, |
| 371 start_state_->weak_factory.GetWeakPtr())); | 373 start_state_->weak_factory.GetWeakPtr())); |
| 372 } | 374 } |
| 373 | 375 |
| 374 void HandleWatcher::Stop() { | 376 void HandleWatcher::Stop() { |
| 375 if (!start_state_.get()) | 377 if (!start_state_.get()) |
| 376 return; | 378 return; |
| 377 | 379 |
| 378 scoped_ptr<StartState> old_state(start_state_.Pass()); | 380 scoped_ptr<StartState> old_state(start_state_.Pass()); |
| 379 WatcherThreadManager::GetInstance()->StopWatching(old_state->watcher_id); | 381 WatcherThreadManager::GetInstance()->StopWatching(old_state->watcher_id); |
| 380 } | 382 } |
| 381 | 383 |
| 382 void HandleWatcher::OnHandleReady() { | 384 void HandleWatcher::OnHandleReady(MojoResult result) { |
| 383 DCHECK(start_state_.get()); | 385 DCHECK(start_state_.get()); |
| 384 scoped_ptr<StartState> old_state(start_state_.Pass()); | 386 scoped_ptr<StartState> old_state(start_state_.Pass()); |
| 385 old_state->callback.Run(); | 387 old_state->callback.Run(result); |
| 388 |
| 389 // NOTE: We may have been deleted during callback execution. |
| 386 } | 390 } |
| 387 | 391 |
| 388 // static | 392 // static |
| 389 base::TimeTicks HandleWatcher::NowTicks() { | 393 base::TimeTicks HandleWatcher::NowTicks() { |
| 390 return tick_clock_ ? tick_clock_->NowTicks() : base::TimeTicks::Now(); | 394 return tick_clock_ ? tick_clock_->NowTicks() : base::TimeTicks::Now(); |
| 391 } | 395 } |
| 392 | 396 |
| 393 // static | 397 // static |
| 394 base::TimeTicks HandleWatcher::MojoDeadlineToTimeTicks(MojoDeadline deadline) { | 398 base::TimeTicks HandleWatcher::MojoDeadlineToTimeTicks(MojoDeadline deadline) { |
| 395 return deadline == MOJO_DEADLINE_INDEFINITE ? base::TimeTicks() : | 399 return deadline == MOJO_DEADLINE_INDEFINITE ? base::TimeTicks() : |
| 396 NowTicks() + base::TimeDelta::FromMicroseconds(deadline); | 400 NowTicks() + base::TimeDelta::FromMicroseconds(deadline); |
| 397 } | 401 } |
| 398 | 402 |
| 399 } // namespace common | 403 } // namespace common |
| 400 } // namespace mojo | 404 } // namespace mojo |
| OLD | NEW |