| OLD | NEW |
| 1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 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 "ios/web/web_thread_impl.h" | 5 #include "ios/web/web_thread_impl.h" |
| 6 | 6 |
| 7 #include <string> | 7 #include <string> |
| 8 | 8 |
| 9 #include "base/atomicops.h" | 9 #include "base/atomicops.h" |
| 10 #include "base/bind.h" | 10 #include "base/bind.h" |
| (...skipping 30 matching lines...) Expand all Loading... |
| 41 } | 41 } |
| 42 | 42 |
| 43 // An implementation of SingleThreadTaskRunner to be used in conjunction | 43 // An implementation of SingleThreadTaskRunner to be used in conjunction |
| 44 // with WebThread. | 44 // with WebThread. |
| 45 class WebThreadTaskRunner : public base::SingleThreadTaskRunner { | 45 class WebThreadTaskRunner : public base::SingleThreadTaskRunner { |
| 46 public: | 46 public: |
| 47 explicit WebThreadTaskRunner(WebThread::ID identifier) : id_(identifier) {} | 47 explicit WebThreadTaskRunner(WebThread::ID identifier) : id_(identifier) {} |
| 48 | 48 |
| 49 // SingleThreadTaskRunner implementation. | 49 // SingleThreadTaskRunner implementation. |
| 50 bool PostDelayedTask(const tracked_objects::Location& from_here, | 50 bool PostDelayedTask(const tracked_objects::Location& from_here, |
| 51 const base::Closure& task, | 51 base::OnceClosure task, |
| 52 base::TimeDelta delay) override { | 52 base::TimeDelta delay) override { |
| 53 return WebThread::PostDelayedTask(id_, from_here, task, delay); | 53 return WebThread::PostDelayedTask(id_, from_here, std::move(task), delay); |
| 54 } | 54 } |
| 55 | 55 |
| 56 bool PostNonNestableDelayedTask(const tracked_objects::Location& from_here, | 56 bool PostNonNestableDelayedTask(const tracked_objects::Location& from_here, |
| 57 const base::Closure& task, | 57 base::OnceClosure task, |
| 58 base::TimeDelta delay) override { | 58 base::TimeDelta delay) override { |
| 59 return WebThread::PostNonNestableDelayedTask(id_, from_here, task, delay); | 59 return WebThread::PostNonNestableDelayedTask(id_, from_here, |
| 60 std::move(task), delay); |
| 60 } | 61 } |
| 61 | 62 |
| 62 bool RunsTasksOnCurrentThread() const override { | 63 bool RunsTasksOnCurrentThread() const override { |
| 63 return WebThread::CurrentlyOn(id_); | 64 return WebThread::CurrentlyOn(id_); |
| 64 } | 65 } |
| 65 | 66 |
| 66 protected: | 67 protected: |
| 67 ~WebThreadTaskRunner() override {} | 68 ~WebThreadTaskRunner() override {} |
| 68 | 69 |
| 69 private: | 70 private: |
| (...skipping 212 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 282 for (int i = identifier_ + 1; i < ID_COUNT; ++i) { | 283 for (int i = identifier_ + 1; i < ID_COUNT; ++i) { |
| 283 DCHECK(!globals.threads[i]) | 284 DCHECK(!globals.threads[i]) |
| 284 << "Threads must be listed in the reverse order that they die"; | 285 << "Threads must be listed in the reverse order that they die"; |
| 285 } | 286 } |
| 286 #endif | 287 #endif |
| 287 } | 288 } |
| 288 | 289 |
| 289 // static | 290 // static |
| 290 bool WebThreadImpl::PostTaskHelper(WebThread::ID identifier, | 291 bool WebThreadImpl::PostTaskHelper(WebThread::ID identifier, |
| 291 const tracked_objects::Location& from_here, | 292 const tracked_objects::Location& from_here, |
| 292 const base::Closure& task, | 293 base::OnceClosure task, |
| 293 base::TimeDelta delay, | 294 base::TimeDelta delay, |
| 294 bool nestable) { | 295 bool nestable) { |
| 295 DCHECK(identifier >= 0 && identifier < ID_COUNT); | 296 DCHECK(identifier >= 0 && identifier < ID_COUNT); |
| 296 // Optimization: to avoid unnecessary locks, we listed the ID enumeration in | 297 // Optimization: to avoid unnecessary locks, we listed the ID enumeration in |
| 297 // order of lifetime. So no need to lock if we know that the target thread | 298 // order of lifetime. So no need to lock if we know that the target thread |
| 298 // outlives current thread. | 299 // outlives current thread. |
| 299 // Note: since the array is so small, ok to loop instead of creating a map, | 300 // Note: since the array is so small, ok to loop instead of creating a map, |
| 300 // which would require a lock because std::map isn't thread safe, defeating | 301 // which would require a lock because std::map isn't thread safe, defeating |
| 301 // the whole purpose of this optimization. | 302 // the whole purpose of this optimization. |
| 302 WebThread::ID current_thread = ID_COUNT; | 303 WebThread::ID current_thread = ID_COUNT; |
| 303 bool target_thread_outlives_current = | 304 bool target_thread_outlives_current = |
| 304 GetCurrentThreadIdentifier(¤t_thread) && | 305 GetCurrentThreadIdentifier(¤t_thread) && |
| 305 current_thread >= identifier; | 306 current_thread >= identifier; |
| 306 | 307 |
| 307 WebThreadGlobals& globals = g_globals.Get(); | 308 WebThreadGlobals& globals = g_globals.Get(); |
| 308 if (!target_thread_outlives_current) | 309 if (!target_thread_outlives_current) |
| 309 globals.lock.Acquire(); | 310 globals.lock.Acquire(); |
| 310 | 311 |
| 311 base::MessageLoop* message_loop = | 312 base::MessageLoop* message_loop = |
| 312 globals.threads[identifier] ? globals.threads[identifier]->message_loop() | 313 globals.threads[identifier] ? globals.threads[identifier]->message_loop() |
| 313 : nullptr; | 314 : nullptr; |
| 314 if (message_loop) { | 315 if (message_loop) { |
| 315 if (nestable) { | 316 if (nestable) { |
| 316 message_loop->task_runner()->PostDelayedTask(from_here, task, delay); | 317 message_loop->task_runner()->PostDelayedTask(from_here, std::move(task), |
| 318 delay); |
| 317 } else { | 319 } else { |
| 318 message_loop->task_runner()->PostNonNestableDelayedTask(from_here, task, | 320 message_loop->task_runner()->PostNonNestableDelayedTask( |
| 319 delay); | 321 from_here, std::move(task), delay); |
| 320 } | 322 } |
| 321 } | 323 } |
| 322 | 324 |
| 323 if (!target_thread_outlives_current) | 325 if (!target_thread_outlives_current) |
| 324 globals.lock.Release(); | 326 globals.lock.Release(); |
| 325 | 327 |
| 326 return !!message_loop; | 328 return !!message_loop; |
| 327 } | 329 } |
| 328 | 330 |
| 329 // static | 331 // static |
| 330 bool WebThread::PostBlockingPoolTask(const tracked_objects::Location& from_here, | 332 bool WebThread::PostBlockingPoolTask(const tracked_objects::Location& from_here, |
| 331 const base::Closure& task) { | 333 base::OnceClosure task) { |
| 332 return g_globals.Get().blocking_pool->PostWorkerTask(from_here, task); | 334 return g_globals.Get().blocking_pool->PostWorkerTask(from_here, |
| 335 std::move(task)); |
| 333 } | 336 } |
| 334 | 337 |
| 335 // static | 338 // static |
| 336 bool WebThread::PostBlockingPoolTaskAndReply( | 339 bool WebThread::PostBlockingPoolTaskAndReply( |
| 337 const tracked_objects::Location& from_here, | 340 const tracked_objects::Location& from_here, |
| 338 const base::Closure& task, | 341 base::OnceClosure task, |
| 339 const base::Closure& reply) { | 342 base::OnceClosure reply) { |
| 340 return g_globals.Get().blocking_pool->PostTaskAndReply(from_here, task, | 343 return g_globals.Get().blocking_pool->PostTaskAndReply( |
| 341 reply); | 344 from_here, std::move(task), std::move(reply)); |
| 342 } | 345 } |
| 343 | 346 |
| 344 // static | 347 // static |
| 345 bool WebThread::PostBlockingPoolSequencedTask( | 348 bool WebThread::PostBlockingPoolSequencedTask( |
| 346 const std::string& sequence_token_name, | 349 const std::string& sequence_token_name, |
| 347 const tracked_objects::Location& from_here, | 350 const tracked_objects::Location& from_here, |
| 348 const base::Closure& task) { | 351 base::OnceClosure task) { |
| 349 return g_globals.Get().blocking_pool->PostNamedSequencedWorkerTask( | 352 return g_globals.Get().blocking_pool->PostNamedSequencedWorkerTask( |
| 350 sequence_token_name, from_here, task); | 353 sequence_token_name, from_here, std::move(task)); |
| 351 } | 354 } |
| 352 | 355 |
| 353 // static | 356 // static |
| 354 base::SequencedWorkerPool* WebThread::GetBlockingPool() { | 357 base::SequencedWorkerPool* WebThread::GetBlockingPool() { |
| 355 return g_globals.Get().blocking_pool.get(); | 358 return g_globals.Get().blocking_pool.get(); |
| 356 } | 359 } |
| 357 | 360 |
| 358 // static | 361 // static |
| 359 bool WebThread::IsThreadInitialized(ID identifier) { | 362 bool WebThread::IsThreadInitialized(ID identifier) { |
| 360 if (g_globals == nullptr) | 363 if (g_globals == nullptr) |
| (...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 403 WebThreadGlobals& globals = g_globals.Get(); | 406 WebThreadGlobals& globals = g_globals.Get(); |
| 404 base::AutoLock lock(globals.lock); | 407 base::AutoLock lock(globals.lock); |
| 405 DCHECK(identifier >= 0 && identifier < ID_COUNT); | 408 DCHECK(identifier >= 0 && identifier < ID_COUNT); |
| 406 return globals.threads[identifier] && | 409 return globals.threads[identifier] && |
| 407 globals.threads[identifier]->message_loop(); | 410 globals.threads[identifier]->message_loop(); |
| 408 } | 411 } |
| 409 | 412 |
| 410 // static | 413 // static |
| 411 bool WebThread::PostTask(ID identifier, | 414 bool WebThread::PostTask(ID identifier, |
| 412 const tracked_objects::Location& from_here, | 415 const tracked_objects::Location& from_here, |
| 413 const base::Closure& task) { | 416 base::OnceClosure task) { |
| 414 return WebThreadImpl::PostTaskHelper(identifier, from_here, task, | 417 return WebThreadImpl::PostTaskHelper(identifier, from_here, std::move(task), |
| 415 base::TimeDelta(), true); | 418 base::TimeDelta(), true); |
| 416 } | 419 } |
| 417 | 420 |
| 418 // static | 421 // static |
| 419 bool WebThread::PostDelayedTask(ID identifier, | 422 bool WebThread::PostDelayedTask(ID identifier, |
| 420 const tracked_objects::Location& from_here, | 423 const tracked_objects::Location& from_here, |
| 421 const base::Closure& task, | 424 base::OnceClosure task, |
| 422 base::TimeDelta delay) { | 425 base::TimeDelta delay) { |
| 423 return WebThreadImpl::PostTaskHelper(identifier, from_here, task, delay, | 426 return WebThreadImpl::PostTaskHelper(identifier, from_here, std::move(task), |
| 424 true); | 427 delay, true); |
| 425 } | 428 } |
| 426 | 429 |
| 427 // static | 430 // static |
| 428 bool WebThread::PostNonNestableTask(ID identifier, | 431 bool WebThread::PostNonNestableTask(ID identifier, |
| 429 const tracked_objects::Location& from_here, | 432 const tracked_objects::Location& from_here, |
| 430 const base::Closure& task) { | 433 base::OnceClosure task) { |
| 431 return WebThreadImpl::PostTaskHelper(identifier, from_here, task, | 434 return WebThreadImpl::PostTaskHelper(identifier, from_here, std::move(task), |
| 432 base::TimeDelta(), false); | 435 base::TimeDelta(), false); |
| 433 } | 436 } |
| 434 | 437 |
| 435 // static | 438 // static |
| 436 bool WebThread::PostNonNestableDelayedTask( | 439 bool WebThread::PostNonNestableDelayedTask( |
| 437 ID identifier, | 440 ID identifier, |
| 438 const tracked_objects::Location& from_here, | 441 const tracked_objects::Location& from_here, |
| 439 const base::Closure& task, | 442 base::OnceClosure task, |
| 440 base::TimeDelta delay) { | 443 base::TimeDelta delay) { |
| 441 return WebThreadImpl::PostTaskHelper(identifier, from_here, task, delay, | 444 return WebThreadImpl::PostTaskHelper(identifier, from_here, std::move(task), |
| 442 false); | 445 delay, false); |
| 443 } | 446 } |
| 444 | 447 |
| 445 // static | 448 // static |
| 446 bool WebThread::PostTaskAndReply(ID identifier, | 449 bool WebThread::PostTaskAndReply(ID identifier, |
| 447 const tracked_objects::Location& from_here, | 450 const tracked_objects::Location& from_here, |
| 448 const base::Closure& task, | 451 base::OnceClosure task, |
| 449 const base::Closure& reply) { | 452 base::OnceClosure reply) { |
| 450 return GetTaskRunnerForThread(identifier) | 453 return GetTaskRunnerForThread(identifier) |
| 451 ->PostTaskAndReply(from_here, task, reply); | 454 ->PostTaskAndReply(from_here, std::move(task), std::move(reply)); |
| 452 } | 455 } |
| 453 | 456 |
| 454 // static | 457 // static |
| 455 bool WebThread::GetCurrentThreadIdentifier(ID* identifier) { | 458 bool WebThread::GetCurrentThreadIdentifier(ID* identifier) { |
| 456 if (g_globals == nullptr) | 459 if (g_globals == nullptr) |
| 457 return false; | 460 return false; |
| 458 | 461 |
| 459 // This shouldn't use MessageLoop::current() since it uses LazyInstance which | 462 // This shouldn't use MessageLoop::current() since it uses LazyInstance which |
| 460 // may be deleted by ~AtExitManager when a WorkerPool thread calls this | 463 // may be deleted by ~AtExitManager when a WorkerPool thread calls this |
| 461 // function. | 464 // function. |
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 500 AtomicWord* storage = | 503 AtomicWord* storage = |
| 501 reinterpret_cast<AtomicWord*>(&globals.thread_delegates[identifier]); | 504 reinterpret_cast<AtomicWord*>(&globals.thread_delegates[identifier]); |
| 502 AtomicWord old_pointer = base::subtle::NoBarrier_AtomicExchange( | 505 AtomicWord old_pointer = base::subtle::NoBarrier_AtomicExchange( |
| 503 storage, reinterpret_cast<AtomicWord>(delegate)); | 506 storage, reinterpret_cast<AtomicWord>(delegate)); |
| 504 | 507 |
| 505 // This catches registration when previously registered. | 508 // This catches registration when previously registered. |
| 506 DCHECK(!delegate || !old_pointer); | 509 DCHECK(!delegate || !old_pointer); |
| 507 } | 510 } |
| 508 | 511 |
| 509 } // namespace web | 512 } // namespace web |
| OLD | NEW |