Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 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 "base/threading/sequenced_worker_pool.h" | 5 #include "base/threading/sequenced_worker_pool.h" |
| 6 | 6 |
| 7 #include <stdint.h> | 7 #include <stdint.h> |
| 8 | 8 |
| 9 #include <list> | 9 #include <list> |
| 10 #include <map> | 10 #include <map> |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 47 #endif | 47 #endif |
| 48 | 48 |
| 49 #if !defined(OS_NACL) | 49 #if !defined(OS_NACL) |
| 50 #include "base/metrics/histogram_macros.h" | 50 #include "base/metrics/histogram_macros.h" |
| 51 #endif | 51 #endif |
| 52 | 52 |
| 53 namespace base { | 53 namespace base { |
| 54 | 54 |
| 55 namespace { | 55 namespace { |
| 56 | 56 |
| 57 // An enum representing the state of all pools. Any given process should only | 57 // An enum representing the state of all pools. Any given non-test process |
| 58 // ever transition from NONE_ACTIVE to the active states, transitions between | 58 // should only ever transition from NONE_ACTIVE to the active states, |
|
danakj
2016/09/16 20:29:36
to one of the active states. Transitions between a
fdoray
2016/09/16 21:21:31
Done.
| |
| 59 // actives states are unexpected. The REDIRECTED_TO_TASK_SCHEDULER transition | 59 // transitions between actives states are unexpected. The |
| 60 // occurs when RedirectSequencedWorkerPoolsToTaskSchedulerForProcess() is called | 60 // REDIRECTED_TO_TASK_SCHEDULER transition occurs when |
| 61 // and the WORKER_CREATED transition occurs when a Worker needs to be created | 61 // RedirectToTaskSchedulerForProcess() is called. The WORKER_CREATED transition |
| 62 // because the first task was posted and the state is still NONE_ACTIVE. | 62 // occurs when a Worker needs to be created because the first task was posted |
| 63 // and the state is still NONE_ACTIVE. In a test process, a transition to | |
| 64 // NONE_ACTIVE occurs when ResetRedirectToTaskSchedulerForProcessForTesting() is | |
| 65 // called. | |
| 66 // | |
| 63 // |g_all_pools_state| uses relaxed atomic operations to ensure no data race | 67 // |g_all_pools_state| uses relaxed atomic operations to ensure no data race |
| 64 // between reads/writes, strict memory ordering isn't required per no other | 68 // between reads/writes, strict memory ordering isn't required per no other |
| 65 // state being inferred from its value. Explicit synchronization (e.g. locks or | 69 // state being inferred from its value. Explicit synchronization (e.g. locks or |
| 66 // events) would be overkill (it's fine for other threads to still see | 70 // events) would be overkill (it's fine for other threads to still see |
| 67 // NONE_ACTIVE after the first Worker was created -- this is not possible for | 71 // NONE_ACTIVE after the first Worker was created -- this is not possible for |
| 68 // REDIRECTED_TO_TASK_SCHEDULER per its API requesting to be invoked while no | 72 // REDIRECTED_TO_TASK_SCHEDULER per its API requesting to be invoked while no |
| 69 // other threads are active). | 73 // other threads are active). |
| 74 // | |
| 70 // TODO(gab): Remove this if http://crbug.com/622400 fails (SequencedWorkerPool | 75 // TODO(gab): Remove this if http://crbug.com/622400 fails (SequencedWorkerPool |
| 71 // will be phased out completely otherwise). | 76 // will be phased out completely otherwise). |
| 72 enum AllPoolsState : subtle::Atomic32 { | 77 enum AllPoolsState : subtle::Atomic32 { |
| 73 NONE_ACTIVE, | 78 NONE_ACTIVE, |
| 74 WORKER_CREATED, | 79 WORKER_CREATED, |
| 75 REDIRECTED_TO_TASK_SCHEDULER, | 80 REDIRECTED_TO_TASK_SCHEDULER, |
| 76 }; | 81 }; |
| 77 subtle::Atomic32 g_all_pools_state = AllPoolsState::NONE_ACTIVE; | 82 subtle::Atomic32 g_all_pools_state = AllPoolsState::NONE_ACTIVE; |
| 78 | 83 |
| 79 struct SequencedTask : public TrackingInfo { | 84 struct SequencedTask : public TrackingInfo { |
| (...skipping 815 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 895 } else { | 900 } else { |
| 896 ThreadMap::const_iterator found = | 901 ThreadMap::const_iterator found = |
| 897 threads_.find(PlatformThread::CurrentId()); | 902 threads_.find(PlatformThread::CurrentId()); |
| 898 return found != threads_.end() && found->second->is_processing_task() && | 903 return found != threads_.end() && found->second->is_processing_task() && |
| 899 sequence_token.Equals(found->second->task_sequence_token()); | 904 sequence_token.Equals(found->second->task_sequence_token()); |
| 900 } | 905 } |
| 901 } | 906 } |
| 902 | 907 |
| 903 // See https://code.google.com/p/chromium/issues/detail?id=168415 | 908 // See https://code.google.com/p/chromium/issues/detail?id=168415 |
| 904 void SequencedWorkerPool::Inner::CleanupForTesting() { | 909 void SequencedWorkerPool::Inner::CleanupForTesting() { |
| 910 DCHECK_NE(subtle::NoBarrier_Load(&g_all_pools_state), | |
| 911 AllPoolsState::REDIRECTED_TO_TASK_SCHEDULER); | |
| 905 DCHECK(!RunsTasksOnCurrentThread()); | 912 DCHECK(!RunsTasksOnCurrentThread()); |
| 906 base::ThreadRestrictions::ScopedAllowWait allow_wait; | 913 base::ThreadRestrictions::ScopedAllowWait allow_wait; |
| 907 AutoLock lock(lock_); | 914 AutoLock lock(lock_); |
| 908 CHECK_EQ(CLEANUP_DONE, cleanup_state_); | 915 CHECK_EQ(CLEANUP_DONE, cleanup_state_); |
| 909 if (shutdown_called_) | 916 if (shutdown_called_) |
| 910 return; | 917 return; |
| 911 if (pending_tasks_.empty() && waiting_thread_count_ == threads_.size()) | 918 if (pending_tasks_.empty() && waiting_thread_count_ == threads_.size()) |
| 912 return; | 919 return; |
| 913 cleanup_state_ = CLEANUP_REQUESTED; | 920 cleanup_state_ = CLEANUP_REQUESTED; |
| 914 cleanup_idlers_ = 0; | 921 cleanup_idlers_ = 0; |
| (...skipping 527 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1442 scoped_refptr<SequencedWorkerPool> | 1449 scoped_refptr<SequencedWorkerPool> |
| 1443 SequencedWorkerPool::GetWorkerPoolForCurrentThread() { | 1450 SequencedWorkerPool::GetWorkerPoolForCurrentThread() { |
| 1444 Worker* worker = Worker::GetForCurrentThread(); | 1451 Worker* worker = Worker::GetForCurrentThread(); |
| 1445 if (!worker) | 1452 if (!worker) |
| 1446 return nullptr; | 1453 return nullptr; |
| 1447 | 1454 |
| 1448 return worker->worker_pool(); | 1455 return worker->worker_pool(); |
| 1449 } | 1456 } |
| 1450 | 1457 |
| 1451 // static | 1458 // static |
| 1452 void SequencedWorkerPool:: | 1459 void SequencedWorkerPool::RedirectToTaskSchedulerForProcess() { |
| 1453 RedirectSequencedWorkerPoolsToTaskSchedulerForProcess() { | |
| 1454 DCHECK(TaskScheduler::GetInstance()); | 1460 DCHECK(TaskScheduler::GetInstance()); |
| 1455 // Hitting this DCHECK indicates that a task was posted to a | 1461 // Hitting this DCHECK indicates that a task was posted to a |
| 1456 // SequencedWorkerPool before the TaskScheduler was initialized and | 1462 // SequencedWorkerPool before the TaskScheduler was initialized and |
| 1457 // redirected, posting task to SequencedWorkerPools needs to at least be | 1463 // redirected, posting task to SequencedWorkerPools needs to at least be |
| 1458 // delayed until after that point. | 1464 // delayed until after that point. |
| 1459 DCHECK_EQ(AllPoolsState::NONE_ACTIVE, | 1465 DCHECK_EQ(AllPoolsState::NONE_ACTIVE, |
| 1460 subtle::NoBarrier_Load(&g_all_pools_state)); | 1466 subtle::NoBarrier_Load(&g_all_pools_state)); |
| 1461 subtle::NoBarrier_Store(&g_all_pools_state, | 1467 subtle::NoBarrier_Store(&g_all_pools_state, |
| 1462 AllPoolsState::REDIRECTED_TO_TASK_SCHEDULER); | 1468 AllPoolsState::REDIRECTED_TO_TASK_SCHEDULER); |
| 1463 } | 1469 } |
| 1464 | 1470 |
| 1471 // static | |
| 1472 void SequencedWorkerPool::ResetRedirectToTaskSchedulerForProcessForTesting() { | |
| 1473 // This can be called when the current state is REDIRECTED_TO_TASK_SCHEDULER | |
| 1474 // to stop redirecting tasks. It can also be called when the current state is | |
| 1475 // WORKER_CREATED to allow RedirectToTaskSchedulerForProcess() to be called | |
| 1476 // (can usually not be called after a worker has been created). | |
|
gab
2016/09/16 20:16:10
"when current state is WORKER_CREATED" and "usuall
fdoray
2016/09/16 21:21:31
Made the comment clearer.
| |
| 1477 subtle::NoBarrier_Store(&g_all_pools_state, AllPoolsState::NONE_ACTIVE); | |
| 1478 } | |
| 1479 | |
| 1465 SequencedWorkerPool::SequencedWorkerPool(size_t max_threads, | 1480 SequencedWorkerPool::SequencedWorkerPool(size_t max_threads, |
| 1466 const std::string& thread_name_prefix, | 1481 const std::string& thread_name_prefix, |
| 1467 base::TaskPriority task_priority) | 1482 base::TaskPriority task_priority) |
| 1468 : constructor_task_runner_(ThreadTaskRunnerHandle::Get()), | 1483 : constructor_task_runner_(ThreadTaskRunnerHandle::Get()), |
| 1469 inner_(new Inner(this, | 1484 inner_(new Inner(this, |
| 1470 max_threads, | 1485 max_threads, |
| 1471 thread_name_prefix, | 1486 thread_name_prefix, |
| 1472 task_priority, | 1487 task_priority, |
| 1473 NULL)) {} | 1488 NULL)) {} |
| 1474 | 1489 |
| (...skipping 136 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1611 bool SequencedWorkerPool::IsShutdownInProgress() { | 1626 bool SequencedWorkerPool::IsShutdownInProgress() { |
| 1612 return inner_->IsShutdownInProgress(); | 1627 return inner_->IsShutdownInProgress(); |
| 1613 } | 1628 } |
| 1614 | 1629 |
| 1615 bool SequencedWorkerPool::IsRunningSequenceOnCurrentThread( | 1630 bool SequencedWorkerPool::IsRunningSequenceOnCurrentThread( |
| 1616 SequenceToken sequence_token) const { | 1631 SequenceToken sequence_token) const { |
| 1617 return inner_->IsRunningSequenceOnCurrentThread(sequence_token); | 1632 return inner_->IsRunningSequenceOnCurrentThread(sequence_token); |
| 1618 } | 1633 } |
| 1619 | 1634 |
| 1620 } // namespace base | 1635 } // namespace base |
| OLD | NEW |