summaryrefslogtreecommitdiffstats
path: root/chromium/base/task/thread_pool/thread_group_unittest.cc
diff options
context:
space:
mode:
Diffstat (limited to 'chromium/base/task/thread_pool/thread_group_unittest.cc')
-rw-r--r--chromium/base/task/thread_pool/thread_group_unittest.cc76
1 files changed, 76 insertions, 0 deletions
diff --git a/chromium/base/task/thread_pool/thread_group_unittest.cc b/chromium/base/task/thread_pool/thread_group_unittest.cc
index cb4481c3cf1..3ed430a60db 100644
--- a/chromium/base/task/thread_pool/thread_group_unittest.cc
+++ b/chromium/base/task/thread_pool/thread_group_unittest.cc
@@ -53,6 +53,7 @@ using ThreadGroupNativeType =
#endif
constexpr size_t kMaxTasks = 4;
+constexpr size_t kTooManyTasks = 1000;
// By default, tests allow half of the thread group to be used by best-effort
// tasks.
constexpr size_t kMaxBestEffortTasks = kMaxTasks / 2;
@@ -654,6 +655,50 @@ TEST_P(ThreadGroupTest, ScheduleJobTaskSourceMultipleTime) {
task_tracker_.FlushForTesting();
}
+// Verify that Cancel() on a job stops running the worker task and causes
+// current workers to yield.
+TEST_P(ThreadGroupTest, CancelJobTaskSource) {
+ StartThreadGroup();
+
+ CheckedLock tasks_running_lock;
+ std::unique_ptr<ConditionVariable> tasks_running_cv =
+ tasks_running_lock.CreateConditionVariable();
+ bool tasks_running = false;
+
+ // Schedule a big number of tasks.
+ auto job_task = base::MakeRefCounted<test::MockJobTask>(
+ BindLambdaForTesting([&](experimental::JobDelegate* delegate) {
+ {
+ CheckedAutoLock auto_lock(tasks_running_lock);
+ tasks_running = true;
+ }
+ tasks_running_cv->Signal();
+
+ while (!delegate->ShouldYield()) {
+ }
+ }),
+ /* num_tasks_to_run */ kTooManyTasks);
+ scoped_refptr<JobTaskSource> task_source = job_task->GetJobTaskSource(
+ FROM_HERE, {ThreadPool()}, &mock_pooled_task_runner_delegate_);
+
+ mock_pooled_task_runner_delegate_.EnqueueJobTaskSource(task_source);
+ experimental::JobHandle job_handle =
+ internal::JobTaskSource::CreateJobHandle(task_source);
+
+ // Wait for at least 1 task to start running.
+ {
+ CheckedAutoLock auto_lock(tasks_running_lock);
+ while (!tasks_running)
+ tasks_running_cv->Wait();
+ }
+
+ // Cancels pending tasks and unblocks running ones.
+ job_handle.Cancel();
+
+ // This should not block since the job got cancelled.
+ task_tracker_.FlushForTesting();
+}
+
// Verify that calling JobTaskSource::NotifyConcurrencyIncrease() (re-)schedule
// tasks with the intended concurrency.
TEST_P(ThreadGroupTest, JobTaskSourceConcurrencyIncrease) {
@@ -733,6 +778,37 @@ TEST_P(ThreadGroupTest, ScheduleEmptyJobTaskSource) {
task_tracker_.FlushForTesting();
}
+// Verify that Join() on a job contributes to max concurrency and waits for all
+// workers to return.
+TEST_P(ThreadGroupTest, JoinJobTaskSource) {
+ StartThreadGroup();
+
+ WaitableEvent threads_continue;
+ RepeatingClosure threads_continue_barrier = BarrierClosure(
+ kMaxTasks + 1,
+ BindOnce(&WaitableEvent::Signal, Unretained(&threads_continue)));
+
+ auto job_task = base::MakeRefCounted<test::MockJobTask>(
+ BindLambdaForTesting([&](experimental::JobDelegate*) {
+ threads_continue_barrier.Run();
+ test::WaitWithoutBlockingObserver(&threads_continue);
+ }),
+ /* num_tasks_to_run */ kMaxTasks + 1);
+ scoped_refptr<JobTaskSource> task_source = job_task->GetJobTaskSource(
+ FROM_HERE, {ThreadPool()}, &mock_pooled_task_runner_delegate_);
+
+ mock_pooled_task_runner_delegate_.EnqueueJobTaskSource(task_source);
+ experimental::JobHandle job_handle =
+ internal::JobTaskSource::CreateJobHandle(task_source);
+ job_handle.Join();
+ // All worker tasks should complete before Join() returns.
+ EXPECT_EQ(0U, job_task->GetMaxConcurrency());
+ thread_group_->JoinForTesting();
+ EXPECT_EQ(1U, task_source->HasOneRef());
+ // Prevent TearDown() from calling JoinForTesting() again.
+ thread_group_ = nullptr;
+}
+
// Verify that the maximum number of BEST_EFFORT tasks that can run concurrently
// in a thread group does not affect JobTaskSource with a priority that was
// increased from BEST_EFFORT to USER_BLOCKING.