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 |