Index: base/task_scheduler/scheduler_worker_pool_impl_unittest.cc |
diff --git a/base/task_scheduler/scheduler_worker_pool_impl_unittest.cc b/base/task_scheduler/scheduler_worker_pool_impl_unittest.cc |
index dfaa9c7ff3d3a8071aceda80584d98eb447622d9..d8aa212c792817b4a18ca1aaace1b409e6a0d8cf 100644 |
--- a/base/task_scheduler/scheduler_worker_pool_impl_unittest.cc |
+++ b/base/task_scheduler/scheduler_worker_pool_impl_unittest.cc |
@@ -719,60 +719,113 @@ TEST_F(TaskSchedulerWorkerPoolHistogramTest, NumTasksBetweenWaitsWithDetach) { |
worker_pool_->DisallowWorkerDetachmentForTesting(); |
} |
-namespace { |
- |
-void NotReachedReEnqueueSequenceCallback(scoped_refptr<Sequence> sequence) { |
- ADD_FAILURE() |
- << "Unexpected invocation of NotReachedReEnqueueSequenceCallback."; |
-} |
- |
-void CaptureThreadId(PlatformThreadId* thread_id) { |
- ASSERT_TRUE(thread_id); |
- *thread_id = PlatformThread::CurrentId(); |
-} |
- |
-void VerifyThreadIdIsNot(PlatformThreadId thread_id) { |
- EXPECT_NE(thread_id, PlatformThread::CurrentId()); |
-} |
- |
-} // namespace |
- |
TEST_F(TaskSchedulerWorkerPoolHistogramTest, NumTasksBeforeDetach) { |
InitializeWorkerPool(kReclaimTimeForDetachTests, kNumWorkersInWorkerPool); |
- // This test assumes that the TaskRunners aren't assigned to the same worker. |
- auto task_runner = |
- worker_pool_->CreateSingleThreadTaskRunnerWithTraits(TaskTraits()); |
- auto other_task_runner = |
- worker_pool_->CreateSingleThreadTaskRunnerWithTraits(TaskTraits()); |
- |
- // Post 3 tasks and wait until they run. |
- PlatformThreadId thread_id; |
- task_runner->PostTask(FROM_HERE, |
- Bind(&CaptureThreadId, Unretained(&thread_id))); |
- task_runner->PostTask(FROM_HERE, Bind(&DoNothing)); |
- task_runner->PostTask(FROM_HERE, Bind(&DoNothing)); |
- worker_pool_->WaitForAllWorkersIdleForTesting(); |
- |
- // To allow the SchedulerWorker associated with |task_runner| to detach: |
- // - Make sure it isn't on top of the idle stack by waking up another |
- // SchedulerWorker and waiting until it goes back to sleep. |
- // - Release |task_runner|. |
- other_task_runner->PostTask(FROM_HERE, Bind(&VerifyThreadIdIsNot, thread_id)); |
+ auto histogrammed_thread_task_runner = |
+ worker_pool_->CreateSequencedTaskRunnerWithTraits( |
+ TaskTraits().WithBaseSyncPrimitives()); |
+ |
+ // Post 3 tasks and hold the thread for idle thread stack ordering. |
+ // This test assumes |histogrammed_thread_task_runner| gets assigned the same |
+ // thread for each of its tasks. |
+ PlatformThreadRef thread_ref; |
+ histogrammed_thread_task_runner->PostTask( |
+ FROM_HERE, Bind( |
+ [](PlatformThreadRef* thread_ref) { |
+ ASSERT_TRUE(thread_ref); |
+ *thread_ref = PlatformThread::CurrentRef(); |
+ }, |
+ Unretained(&thread_ref))); |
+ histogrammed_thread_task_runner->PostTask( |
+ FROM_HERE, Bind( |
+ [](PlatformThreadRef thread_ref) { |
+ EXPECT_EQ(thread_ref, PlatformThreadRef()); |
+ }, |
+ thread_ref)); |
+ WaitableEvent detach_thread_running( |
+ WaitableEvent::ResetPolicy::MANUAL, |
+ WaitableEvent::InitialState::NOT_SIGNALED); |
+ WaitableEvent detach_thread_continue( |
+ WaitableEvent::ResetPolicy::MANUAL, |
+ WaitableEvent::InitialState::NOT_SIGNALED); |
+ histogrammed_thread_task_runner->PostTask( |
+ FROM_HERE, |
+ Bind( |
+ [](PlatformThreadRef thread_ref, WaitableEvent* detach_thread_running, |
+ WaitableEvent* detach_thread_continue) { |
+ EXPECT_EQ(thread_ref, PlatformThreadRef()); |
+ detach_thread_running->Signal(); |
+ detach_thread_continue->Wait(); |
+ }, |
+ thread_ref, Unretained(&detach_thread_running), |
+ Unretained(&detach_thread_continue))); |
+ |
+ detach_thread_running.Wait(); |
+ |
+ // To allow the SchedulerWorker associated with |
+ // |histogrammed_thread_task_runner| to detach, make sure it isn't on top of |
+ // the idle stack by waking up another SchedulerWorker via |
+ // |task_runner_for_top_idle|. |histogrammed_thread_task_runner| should |
+ // release and go idle first and then |task_runner_for_top_idle| should |
+ // release and go idle. This allows the SchedulerWorker associated with |
+ // |histogrammed_thread_task_runner| to detach. |
+ WaitableEvent top_idle_thread_running( |
+ WaitableEvent::ResetPolicy::MANUAL, |
+ WaitableEvent::InitialState::NOT_SIGNALED); |
+ WaitableEvent top_idle_thread_continue( |
+ WaitableEvent::ResetPolicy::MANUAL, |
+ WaitableEvent::InitialState::NOT_SIGNALED); |
+ auto task_runner_for_top_idle = |
+ worker_pool_->CreateSequencedTaskRunnerWithTraits( |
+ TaskTraits().WithBaseSyncPrimitives()); |
+ task_runner_for_top_idle->PostTask( |
+ FROM_HERE, Bind( |
+ [](PlatformThreadRef thread_ref, |
+ WaitableEvent* top_idle_thread_running, |
+ WaitableEvent* top_idle_thread_continue) { |
+ EXPECT_NE(thread_ref, PlatformThread::CurrentRef()) |
+ << "Worker reused. Thread will not detach and the " |
+ "histogram value will be wrong."; |
+ top_idle_thread_running->Signal(); |
+ top_idle_thread_continue->Wait(); |
+ }, |
+ thread_ref, Unretained(&top_idle_thread_running), |
+ Unretained(&top_idle_thread_continue))); |
+ top_idle_thread_running.Wait(); |
+ detach_thread_continue.Signal(); |
+ // Wait for the thread processing the |histogrammed_thread_task_runner| work |
+ // to go to the idle stack. |
+ PlatformThread::Sleep(TestTimeouts::tiny_timeout()); |
+ top_idle_thread_continue.Signal(); |
+ // Allow the thread processing the |histogrammed_thread_task_runner| work to |
+ // detach. |
+ PlatformThread::Sleep(kReclaimTimeForDetachTests + |
+ kReclaimTimeForDetachTests); |
worker_pool_->WaitForAllWorkersIdleForTesting(); |
- task_runner = nullptr; |
- |
- // Allow the SchedulerWorker that was associated with |task_runner| to detach. |
- PlatformThread::Sleep(kReclaimTimeForDetachTests + kExtraTimeToWaitForDetach); |
worker_pool_->DisallowWorkerDetachmentForTesting(); |
// Verify that counts were recorded to the histogram as expected. |
const auto* histogram = worker_pool_->num_tasks_before_detach_histogram(); |
EXPECT_EQ(0, histogram->SnapshotSamples()->GetCount(0)); |
+ EXPECT_EQ(0, histogram->SnapshotSamples()->GetCount(1)); |
+ EXPECT_EQ(0, histogram->SnapshotSamples()->GetCount(2)); |
EXPECT_EQ(1, histogram->SnapshotSamples()->GetCount(3)); |
+ EXPECT_EQ(0, histogram->SnapshotSamples()->GetCount(4)); |
+ EXPECT_EQ(0, histogram->SnapshotSamples()->GetCount(5)); |
+ EXPECT_EQ(0, histogram->SnapshotSamples()->GetCount(6)); |
EXPECT_EQ(0, histogram->SnapshotSamples()->GetCount(10)); |
} |
+namespace { |
+ |
+void NotReachedReEnqueueSequenceCallback(scoped_refptr<Sequence> sequence) { |
+ ADD_FAILURE() |
+ << "Unexpected invocation of NotReachedReEnqueueSequenceCallback."; |
+} |
+ |
+} // namespace |
+ |
TEST(TaskSchedulerWorkerPoolStandbyPolicyTest, InitLazy) { |
TaskTracker task_tracker; |
DelayedTaskManager delayed_task_manager( |