diff options
author | Allan Sandfeld Jensen <allan.jensen@qt.io> | 2021-09-03 13:32:17 +0200 |
---|---|---|
committer | Allan Sandfeld Jensen <allan.jensen@qt.io> | 2021-10-01 14:31:55 +0200 |
commit | 21ba0c5d4bf8fba15dddd97cd693bad2358b77fd (patch) | |
tree | 91be119f694044dfc1ff9fdc054459e925de9df0 /chromium/base/task/thread_pool | |
parent | 03c549e0392f92c02536d3f86d5e1d8dfa3435ac (diff) |
BASELINE: Update Chromium to 92.0.4515.166
Change-Id: I42a050486714e9e54fc271f2a8939223a02ae364
Diffstat (limited to 'chromium/base/task/thread_pool')
33 files changed, 278 insertions, 212 deletions
diff --git a/chromium/base/task/thread_pool/DIR_METADATA b/chromium/base/task/thread_pool/DIR_METADATA index b934291e67e..6cfe0948bd7 100644 --- a/chromium/base/task/thread_pool/DIR_METADATA +++ b/chromium/base/task/thread_pool/DIR_METADATA @@ -1,4 +1,3 @@ monorail { component: "Internals>ThreadPool" } -team_email: "scheduler-dev@chromium.org" diff --git a/chromium/base/task/thread_pool/delayed_task_manager.cc b/chromium/base/task/thread_pool/delayed_task_manager.cc index fae188e1a8d..50e311adbae 100644 --- a/chromium/base/task/thread_pool/delayed_task_manager.cc +++ b/chromium/base/task/thread_pool/delayed_task_manager.cc @@ -12,6 +12,7 @@ #include "base/task/post_task.h" #include "base/task/thread_pool/task.h" #include "base/task_runner.h" +#include "third_party/abseil-cpp/absl/types/optional.h" namespace base { namespace internal { @@ -128,10 +129,10 @@ void DelayedTaskManager::ProcessRipeTasks() { } } -Optional<TimeTicks> DelayedTaskManager::NextScheduledRunTime() const { +absl::optional<TimeTicks> DelayedTaskManager::NextScheduledRunTime() const { CheckedAutoLock auto_lock(queue_lock_); if (delayed_task_queue_.empty()) - return nullopt; + return absl::nullopt; return delayed_task_queue_.Min().task.delayed_run_time; } diff --git a/chromium/base/task/thread_pool/delayed_task_manager.h b/chromium/base/task/thread_pool/delayed_task_manager.h index 765bbc20285..e85c411676a 100644 --- a/chromium/base/task/thread_pool/delayed_task_manager.h +++ b/chromium/base/task/thread_pool/delayed_task_manager.h @@ -5,14 +5,10 @@ #ifndef BASE_TASK_THREAD_POOL_DELAYED_TASK_MANAGER_H_ #define BASE_TASK_THREAD_POOL_DELAYED_TASK_MANAGER_H_ -#include <memory> -#include <utility> - #include "base/base_export.h" #include "base/callback.h" #include "base/memory/ptr_util.h" #include "base/memory/ref_counted.h" -#include "base/optional.h" #include "base/synchronization/atomic_flag.h" #include "base/task/common/checked_lock.h" #include "base/task/common/intrusive_heap.h" @@ -20,6 +16,7 @@ #include "base/thread_annotations.h" #include "base/time/default_tick_clock.h" #include "base/time/tick_clock.h" +#include "third_party/abseil-cpp/absl/types/optional.h" namespace base { @@ -59,7 +56,7 @@ class BASE_EXPORT DelayedTaskManager { void ProcessRipeTasks(); // Returns the |delayed_run_time| of the next scheduled task, if any. - Optional<TimeTicks> NextScheduledRunTime() const; + absl::optional<TimeTicks> NextScheduledRunTime() const; private: struct DelayedTask { diff --git a/chromium/base/task/thread_pool/delayed_task_manager_unittest.cc b/chromium/base/task/thread_pool/delayed_task_manager_unittest.cc index dd931e6be8c..474592898c1 100644 --- a/chromium/base/task/thread_pool/delayed_task_manager_unittest.cc +++ b/chromium/base/task/thread_pool/delayed_task_manager_unittest.cc @@ -41,11 +41,7 @@ Task ConstructMockedTask(testing::StrictMock<MockCallback>& mock_task, TimeTicks now, TimeDelta delay) { Task task(FROM_HERE, BindOnce(&MockCallback::Run, Unretained(&mock_task)), - delay); - // The constructor of Task computes |delayed_run_time| by adding |delay| to - // the real time. Recompute it by adding |delay| to the given |now| (usually - // mock time). - task.delayed_run_time = now + delay; + now, delay); return task; } @@ -166,7 +162,8 @@ TEST_F(ThreadPoolDelayedTaskManagerTest, DelayedTaskRunsAfterCancelled) { // Add a cancelable task to the DelayedTaskManager with a longer delay. CancelableOnceClosure cancelable_closure(DoNothing::Once()); bool post_cancelable_task_now_invoked = false; - Task cancelable_task(FROM_HERE, cancelable_closure.callback(), kLongerDelay); + Task cancelable_task(FROM_HERE, cancelable_closure.callback(), + TimeTicks::Now(), kLongerDelay); auto post_cancelable_task_now = BindLambdaForTesting( [&](Task task) { post_cancelable_task_now_invoked = true; }); delayed_task_manager_.AddDelayedTask(std::move(cancelable_task), diff --git a/chromium/base/task/thread_pool/job_task_source.cc b/chromium/base/task/thread_pool/job_task_source.cc index 67b8a21b5c7..d44e3bc70ca 100644 --- a/chromium/base/task/thread_pool/job_task_source.cc +++ b/chromium/base/task/thread_pool/job_task_source.cc @@ -329,7 +329,7 @@ Task JobTaskSource::TakeTask(TaskSource::Transaction* transaction) { // if |transaction| is nullptr. DCHECK_GT(TS_UNCHECKED_READ(state_).Load().worker_count(), 0U); DCHECK(primary_task_); - return Task(from_here_, primary_task_, TimeDelta()); + return Task(from_here_, primary_task_, TimeTicks(), TimeDelta()); } bool JobTaskSource::DidProcessTask(TaskSource::Transaction* /*transaction*/) { @@ -368,7 +368,7 @@ Task JobTaskSource::Clear(TaskSource::Transaction* transaction) { // Nothing is cleared since other workers might still racily run tasks. For // simplicity, the destructor will take care of it once all references are // released. - return Task(from_here_, DoNothing(), TimeDelta()); + return Task(from_here_, DoNothing(), TimeTicks(), TimeDelta()); } } // namespace internal diff --git a/chromium/base/task/thread_pool/job_task_source.h b/chromium/base/task/thread_pool/job_task_source.h index 0e74e77c3fb..d84cd84181e 100644 --- a/chromium/base/task/thread_pool/job_task_source.h +++ b/chromium/base/task/thread_pool/job_task_source.h @@ -14,7 +14,6 @@ #include "base/base_export.h" #include "base/callback.h" -#include "base/optional.h" #include "base/synchronization/condition_variable.h" #include "base/task/common/checked_lock.h" #include "base/task/post_job.h" diff --git a/chromium/base/task/thread_pool/pooled_parallel_task_runner.cc b/chromium/base/task/thread_pool/pooled_parallel_task_runner.cc index 327f7366e18..00f84bb2b59 100644 --- a/chromium/base/task/thread_pool/pooled_parallel_task_runner.cc +++ b/chromium/base/task/thread_pool/pooled_parallel_task_runner.cc @@ -36,7 +36,8 @@ bool PooledParallelTaskRunner::PostDelayedTask(const Location& from_here, } return pooled_task_runner_delegate_->PostTaskWithSequence( - Task(from_here, std::move(closure), delay), std::move(sequence)); + Task(from_here, std::move(closure), TimeTicks::Now(), delay), + std::move(sequence)); } void PooledParallelTaskRunner::UnregisterSequence(Sequence* sequence) { diff --git a/chromium/base/task/thread_pool/pooled_sequenced_task_runner.cc b/chromium/base/task/thread_pool/pooled_sequenced_task_runner.cc index b07008e0cfa..7a5b5cf8579 100644 --- a/chromium/base/task/thread_pool/pooled_sequenced_task_runner.cc +++ b/chromium/base/task/thread_pool/pooled_sequenced_task_runner.cc @@ -28,7 +28,7 @@ bool PooledSequencedTaskRunner::PostDelayedTask(const Location& from_here, return false; } - Task task(from_here, std::move(closure), delay); + Task task(from_here, std::move(closure), TimeTicks::Now(), delay); // Post the task as part of |sequence_|. return pooled_task_runner_delegate_->PostTaskWithSequence(std::move(task), diff --git a/chromium/base/task/thread_pool/pooled_single_thread_task_runner_manager.cc b/chromium/base/task/thread_pool/pooled_single_thread_task_runner_manager.cc index a71ea108ad1..67538da442a 100644 --- a/chromium/base/task/thread_pool/pooled_single_thread_task_runner_manager.cc +++ b/chromium/base/task/thread_pool/pooled_single_thread_task_runner_manager.cc @@ -115,6 +115,7 @@ class WorkerThreadDelegate : public WorkerThread::Delegate { RegisteredTaskSource GetWork(WorkerThread* worker) override { CheckedAutoLock auto_lock(lock_); DCHECK(worker_awake_); + auto task_source = GetWorkLockRequired(worker); if (!task_source) { // The worker will sleep after this returns nullptr. @@ -348,7 +349,7 @@ class WorkerThreadCOMDelegate : public WorkerThreadDelegate { DispatchMessage(&msg); }, std::move(msg)), - TimeDelta()); + TimeTicks::Now(), TimeDelta()); if (task_tracker()->WillPostTask( &pump_message_task, TaskShutdownBehavior::SKIP_ON_SHUTDOWN)) { auto transaction = message_pump_sequence_->BeginTransaction(); @@ -409,7 +410,7 @@ class PooledSingleThreadTaskRunnerManager::PooledSingleThreadTaskRunner if (!g_manager_is_alive) return false; - Task task(from_here, std::move(closure), delay); + Task task(from_here, std::move(closure), TimeTicks::Now(), delay); if (!outer_->task_tracker_->WillPostTask(&task, sequence_->shutdown_behavior())) { diff --git a/chromium/base/task/thread_pool/priority_queue_unittest.cc b/chromium/base/task/thread_pool/priority_queue_unittest.cc index 135a77c61a8..1a270618e65 100644 --- a/chromium/base/task/thread_pool/priority_queue_unittest.cc +++ b/chromium/base/task/thread_pool/priority_queue_unittest.cc @@ -44,7 +44,7 @@ class PriorityQueueWithSequencesTest : public testing::Test { scoped_refptr<Sequence> sequence = MakeRefCounted<Sequence>( traits, nullptr, TaskSourceExecutionMode::kParallel); sequence->BeginTransaction().PushTask( - Task(FROM_HERE, DoNothing(), TimeDelta())); + Task(FROM_HERE, DoNothing(), TimeTicks::Now(), TimeDelta())); return sequence; } diff --git a/chromium/base/task/thread_pool/sequence.cc b/chromium/base/task/thread_pool/sequence.cc index b37b5796a46..8687f27ad83 100644 --- a/chromium/base/task/thread_pool/sequence.cc +++ b/chromium/base/task/thread_pool/sequence.cc @@ -38,18 +38,18 @@ void Sequence::Transaction::PushTask(Task task) { // Use CHECK instead of DCHECK to crash earlier. See http://crbug.com/711167 // for details. CHECK(task.task); - DCHECK(task.queue_time.is_null()); + DCHECK(!task.queue_time.is_null()); bool should_be_queued = WillPushTask(); - task.queue_time = TimeTicks::Now(); - task.task = sequence()->traits_.shutdown_behavior() == TaskShutdownBehavior::BLOCK_SHUTDOWN ? MakeCriticalClosure(task.posted_from, std::move(task.task)) : std::move(task.task); - if (sequence()->queue_.empty()) - sequence()->ready_time_.store(task.queue_time, std::memory_order_relaxed); + if (sequence()->queue_.empty()) { + sequence()->ready_time_.store(task.GetDesiredExecutionTime(), + std::memory_order_relaxed); + } sequence()->queue_.push(std::move(task)); // AddRef() matched by manual Release() when the sequence has no more tasks @@ -125,7 +125,7 @@ Task Sequence::Clear(TaskSource::Transaction* transaction) { queue.pop(); }, std::move(queue_)), - TimeDelta()); + TimeTicks(), TimeDelta()); } void Sequence::ReleaseTaskRunner() { diff --git a/chromium/base/task/thread_pool/sequence.h b/chromium/base/task/thread_pool/sequence.h index db58325bd80..bd0dc32111e 100644 --- a/chromium/base/task/thread_pool/sequence.h +++ b/chromium/base/task/thread_pool/sequence.h @@ -10,7 +10,6 @@ #include "base/base_export.h" #include "base/compiler_specific.h" #include "base/containers/queue.h" -#include "base/optional.h" #include "base/sequence_token.h" #include "base/task/task_traits.h" #include "base/task/thread_pool/pooled_parallel_task_runner.h" diff --git a/chromium/base/task/thread_pool/sequence_unittest.cc b/chromium/base/task/thread_pool/sequence_unittest.cc index 89593298772..990c7da2338 100644 --- a/chromium/base/task/thread_pool/sequence_unittest.cc +++ b/chromium/base/task/thread_pool/sequence_unittest.cc @@ -13,6 +13,7 @@ #include "base/time/time.h" #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" +#include "third_party/abseil-cpp/absl/types/optional.h" namespace base { namespace internal { @@ -26,7 +27,7 @@ class MockTask { Task CreateTask(MockTask* mock_task) { return Task(FROM_HERE, BindOnce(&MockTask::Run, Unretained(mock_task)), - TimeDelta()); + TimeTicks::Now(), TimeDelta()); } void ExpectMockTask(MockTask* mock_task, Task* task) { @@ -67,7 +68,8 @@ TEST(ThreadPoolSequenceTest, PushTakeRemove) { auto registered_task_source = RegisteredTaskSource::CreateForTesting(sequence); registered_task_source.WillRunTask(); - Optional<Task> task = registered_task_source.TakeTask(&sequence_transaction); + absl::optional<Task> task = + registered_task_source.TakeTask(&sequence_transaction); ExpectMockTask(&mock_task_a, &task.value()); EXPECT_FALSE(task->queue_time.is_null()); @@ -118,7 +120,7 @@ TEST(ThreadPoolSequenceTest, PushTakeRemove) { // Verifies the sort key of a BEST_EFFORT sequence that contains one task. TEST(ThreadPoolSequenceTest, GetSortKeyBestEffort) { // Create a BEST_EFFORT sequence with a task. - Task best_effort_task(FROM_HERE, DoNothing(), TimeDelta()); + Task best_effort_task(FROM_HERE, DoNothing(), TimeTicks::Now(), TimeDelta()); scoped_refptr<Sequence> best_effort_sequence = MakeRefCounted<Sequence>(TaskTraits(TaskPriority::BEST_EFFORT), nullptr, TaskSourceExecutionMode::kParallel); @@ -152,7 +154,7 @@ TEST(ThreadPoolSequenceTest, GetSortKeyBestEffort) { // USER_VISIBLE sequence. TEST(ThreadPoolSequenceTest, GetSortKeyForeground) { // Create a USER_VISIBLE sequence with a task. - Task foreground_task(FROM_HERE, DoNothing(), TimeDelta()); + Task foreground_task(FROM_HERE, DoNothing(), TimeTicks::Now(), TimeDelta()); scoped_refptr<Sequence> foreground_sequence = MakeRefCounted<Sequence>(TaskTraits(TaskPriority::USER_VISIBLE), nullptr, TaskSourceExecutionMode::kParallel); @@ -187,7 +189,8 @@ TEST(ThreadPoolSequenceTest, DidProcessTaskWithoutWillRunTask) { scoped_refptr<Sequence> sequence = MakeRefCounted<Sequence>( TaskTraits(), nullptr, TaskSourceExecutionMode::kParallel); Sequence::Transaction sequence_transaction(sequence->BeginTransaction()); - sequence_transaction.PushTask(Task(FROM_HERE, DoNothing(), TimeDelta())); + sequence_transaction.PushTask( + Task(FROM_HERE, DoNothing(), TimeTicks::Now(), TimeDelta())); auto registered_task_source = RegisteredTaskSource::CreateForTesting(sequence); @@ -202,7 +205,8 @@ TEST(ThreadPoolSequenceTest, TakeEmptyFrontSlot) { scoped_refptr<Sequence> sequence = MakeRefCounted<Sequence>( TaskTraits(), nullptr, TaskSourceExecutionMode::kParallel); Sequence::Transaction sequence_transaction(sequence->BeginTransaction()); - sequence_transaction.PushTask(Task(FROM_HERE, DoNothing(), TimeDelta())); + sequence_transaction.PushTask( + Task(FROM_HERE, DoNothing(), TimeTicks::Now(), TimeDelta())); auto registered_task_source = RegisteredTaskSource::CreateForTesting(sequence); diff --git a/chromium/base/task/thread_pool/task.cc b/chromium/base/task/thread_pool/task.cc index 68cfd09dbbd..763aa7f077b 100644 --- a/chromium/base/task/thread_pool/task.cc +++ b/chromium/base/task/thread_pool/task.cc @@ -17,11 +17,14 @@ AtomicSequenceNumber g_sequence_nums_for_tracing; } // namespace -Task::Task(const Location& posted_from, OnceClosure task, TimeDelta delay) +Task::Task(const Location& posted_from, + OnceClosure task, + TimeTicks queue_time, + TimeDelta delay) : PendingTask(posted_from, std::move(task), - delay.is_zero() ? TimeTicks() : TimeTicks::Now() + delay, - Nestable::kNonNestable) { + queue_time, + delay.is_zero() ? TimeTicks() : queue_time + delay) { // ThreadPoolImpl doesn't use |sequence_num| but tracing (toplevel.flow) // relies on it being unique. While this subtle dependency is a bit // overreaching, ThreadPoolImpl is the only task system that doesn't use diff --git a/chromium/base/task/thread_pool/task.h b/chromium/base/task/thread_pool/task.h index 0ec5d0b176b..8f70bf4349d 100644 --- a/chromium/base/task/thread_pool/task.h +++ b/chromium/base/task/thread_pool/task.h @@ -25,7 +25,10 @@ struct BASE_EXPORT Task : public PendingTask { // |posted_from| is the site the task was posted from. |task| is the closure // to run. |delay| is a delay that must expire before the Task runs. - Task(const Location& posted_from, OnceClosure task, TimeDelta delay); + Task(const Location& posted_from, + OnceClosure task, + TimeTicks queue_time, + TimeDelta delay); // Task is move-only to avoid mistakes that cause reference counts to be // accidentally bumped. diff --git a/chromium/base/task/thread_pool/task_source.cc b/chromium/base/task/thread_pool/task_source.cc index 1b08a321bd4..aeddbe504fa 100644 --- a/chromium/base/task/thread_pool/task_source.cc +++ b/chromium/base/task/thread_pool/task_source.cc @@ -33,8 +33,6 @@ TaskSource::Transaction::~Transaction() { } void TaskSource::Transaction::UpdatePriority(TaskPriority priority) { - if (FeatureList::IsEnabled(kAllTasksUserBlocking)) - return; task_source_->traits_.UpdatePriority(priority); task_source_->priority_racy_.store(task_source_->traits_.priority(), std::memory_order_relaxed); diff --git a/chromium/base/task/thread_pool/task_source.h b/chromium/base/task/thread_pool/task_source.h index 43f3bcfcab1..87f928a84fd 100644 --- a/chromium/base/task/thread_pool/task_source.h +++ b/chromium/base/task/thread_pool/task_source.h @@ -10,7 +10,6 @@ #include "base/base_export.h" #include "base/compiler_specific.h" #include "base/memory/ref_counted.h" -#include "base/optional.h" #include "base/sequence_token.h" #include "base/task/common/checked_lock.h" #include "base/task/common/intrusive_heap.h" diff --git a/chromium/base/task/thread_pool/task_tracker.cc b/chromium/base/task/thread_pool/task_tracker.cc index e9ee488938c..44c6d5259d8 100644 --- a/chromium/base/task/thread_pool/task_tracker.cc +++ b/chromium/base/task/thread_pool/task_tracker.cc @@ -17,7 +17,6 @@ #include "base/logging.h" #include "base/memory/ptr_util.h" #include "base/metrics/histogram_macros.h" -#include "base/optional.h" #include "base/sequence_token.h" #include "base/strings/string_util.h" #include "base/synchronization/condition_variable.h" @@ -31,6 +30,7 @@ #include "base/trace_event/base_tracing.h" #include "base/values.h" #include "build/build_config.h" +#include "third_party/abseil-cpp/absl/types/optional.h" namespace base { namespace internal { @@ -418,7 +418,7 @@ RegisteredTaskSource TaskTracker::RunAndPopNextTask( const bool should_run_tasks = BeforeRunTask(task_source->shutdown_behavior()); // Run the next task in |task_source|. - Optional<Task> task; + absl::optional<Task> task; TaskTraits traits; { auto transaction = task_source->BeginTransaction(); @@ -473,7 +473,7 @@ void TaskTracker::RunTask(Task task, scoped_set_task_priority_for_current_thread(traits.priority()); // Local storage map used if none is provided by |environment|. - Optional<SequenceLocalStorageMap> local_storage_map; + absl::optional<SequenceLocalStorageMap> local_storage_map; if (!environment.sequence_local_storage) local_storage_map.emplace(); @@ -484,9 +484,9 @@ void TaskTracker::RunTask(Task task, : &local_storage_map.value()); // Set up TaskRunnerHandle as expected for the scope of the task. - Optional<SequencedTaskRunnerHandle> sequenced_task_runner_handle; - Optional<ThreadTaskRunnerHandle> single_thread_task_runner_handle; - Optional<EphemeralTaskExecutor> ephemeral_task_executor; + absl::optional<SequencedTaskRunnerHandle> sequenced_task_runner_handle; + absl::optional<ThreadTaskRunnerHandle> single_thread_task_runner_handle; + absl::optional<EphemeralTaskExecutor> ephemeral_task_executor; switch (task_source->execution_mode()) { case TaskSourceExecutionMode::kJob: case TaskSourceExecutionMode::kParallel: diff --git a/chromium/base/task/thread_pool/task_tracker_posix_unittest.cc b/chromium/base/task/thread_pool/task_tracker_posix_unittest.cc index c6f8c193f8f..316a8a29c50 100644 --- a/chromium/base/task/thread_pool/task_tracker_posix_unittest.cc +++ b/chromium/base/task/thread_pool/task_tracker_posix_unittest.cc @@ -35,7 +35,7 @@ class ThreadPoolTaskTrackerPosixTest : public testing::Test { ThreadPoolTaskTrackerPosixTest() : service_thread_("ServiceThread") { Thread::Options service_thread_options; service_thread_options.message_pump_type = MessagePumpType::IO; - service_thread_.StartWithOptions(service_thread_options); + service_thread_.StartWithOptions(std::move(service_thread_options)); tracker_.set_io_thread_task_runner(service_thread_.task_runner()); } ThreadPoolTaskTrackerPosixTest(const ThreadPoolTaskTrackerPosixTest&) = @@ -56,7 +56,7 @@ TEST_F(ThreadPoolTaskTrackerPosixTest, RunTask) { Task task( FROM_HERE, BindOnce([](bool* did_run) { *did_run = true; }, Unretained(&did_run)), - TimeDelta()); + TimeTicks::Now(), TimeDelta()); constexpr TaskTraits default_traits; EXPECT_TRUE(tracker_.WillPostTask(&task, default_traits.shutdown_behavior())); @@ -77,7 +77,7 @@ TEST_F(ThreadPoolTaskTrackerPosixTest, FileDescriptorWatcher) { Task task(FROM_HERE, BindOnce(IgnoreResult(&FileDescriptorWatcher::WatchReadable), fds[0], DoNothing()), - TimeDelta()); + TimeTicks::Now(), TimeDelta()); constexpr TaskTraits default_traits; EXPECT_TRUE(tracker_.WillPostTask(&task, default_traits.shutdown_behavior())); diff --git a/chromium/base/task/thread_pool/task_tracker_unittest.cc b/chromium/base/task/thread_pool/task_tracker_unittest.cc index 9794e3f467f..978870eed97 100644 --- a/chromium/base/task/thread_pool/task_tracker_unittest.cc +++ b/chromium/base/task/thread_pool/task_tracker_unittest.cc @@ -174,7 +174,7 @@ class ThreadPoolTaskTrackerTest return Task( FROM_HERE, BindOnce(&ThreadPoolTaskTrackerTest::RunTaskCallback, Unretained(this)), - TimeDelta()); + TimeTicks::Now(), TimeDelta()); } RegisteredTaskSource WillPostTaskAndQueueTaskSource( @@ -308,7 +308,7 @@ TEST_P(ThreadPoolTaskTrackerTest, WillPostAndRunLongTaskBeforeShutdown) { task_running.Signal(); task_barrier.Wait(); }), - TimeDelta()); + TimeTicks::Now(), TimeDelta()); // Inform |task_tracker_| that |blocked_task| will be posted. auto sequence = @@ -491,7 +491,7 @@ TEST_P(ThreadPoolTaskTrackerTest, SingletonAllowed) { (GetParam() != TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN); Task task(FROM_HERE, BindOnce(&ThreadRestrictions::AssertSingletonAllowed), - TimeDelta()); + TimeTicks::Now(), TimeDelta()); auto sequence = WillPostTaskAndQueueTaskSource(std::move(task), {GetParam()}); EXPECT_TRUE(sequence); @@ -518,7 +518,7 @@ TEST_P(ThreadPoolTaskTrackerTest, IOAllowed) { ScopedBlockingCall scope_blocking_call( FROM_HERE, BlockingType::WILL_BLOCK); }), - TimeDelta()); + TimeTicks::Now(), TimeDelta()); TaskTraits traits_with_may_block{MayBlock(), GetParam()}; auto sequence_with_may_block = WillPostTaskAndQueueTaskSource( std::move(task_with_may_block), traits_with_may_block); @@ -534,7 +534,7 @@ TEST_P(ThreadPoolTaskTrackerTest, IOAllowed) { FROM_HERE, BlockingType::WILL_BLOCK); }); }), - TimeDelta()); + TimeTicks::Now(), TimeDelta()); TaskTraits traits_without_may_block = TaskTraits(GetParam()); auto sequence_without_may_block = WillPostTaskAndQueueTaskSource( std::move(task_without_may_block), traits_without_may_block); @@ -574,7 +574,8 @@ static void VerifyNoTaskRunnerHandle() { TEST_P(ThreadPoolTaskTrackerTest, TaskRunnerHandleIsNotSetOnParallel) { // Create a task that will verify that TaskRunnerHandles are not set in its // scope per no TaskRunner ref being set to it. - Task verify_task(FROM_HERE, BindOnce(&VerifyNoTaskRunnerHandle), TimeDelta()); + Task verify_task(FROM_HERE, BindOnce(&VerifyNoTaskRunnerHandle), + TimeTicks::Now(), TimeDelta()); RunTaskRunnerHandleVerificationTask(&tracker_, std::move(verify_task), TaskTraits(GetParam()), nullptr, @@ -597,7 +598,7 @@ TEST_P(ThreadPoolTaskTrackerTest, SequencedTaskRunnerHandleIsSetOnSequenced) { Task verify_task(FROM_HERE, BindOnce(&VerifySequencedTaskRunnerHandle, Unretained(test_task_runner.get())), - TimeDelta()); + TimeTicks::Now(), TimeDelta()); RunTaskRunnerHandleVerificationTask( &tracker_, std::move(verify_task), TaskTraits(GetParam()), @@ -622,7 +623,7 @@ TEST_P(ThreadPoolTaskTrackerTest, ThreadTaskRunnerHandleIsSetOnSingleThreaded) { Task verify_task(FROM_HERE, BindOnce(&VerifyThreadTaskRunnerHandle, Unretained(test_task_runner.get())), - TimeDelta()); + TimeTicks::Now(), TimeDelta()); RunTaskRunnerHandleVerificationTask( &tracker_, std::move(verify_task), TaskTraits(GetParam()), @@ -630,14 +631,16 @@ TEST_P(ThreadPoolTaskTrackerTest, ThreadTaskRunnerHandleIsSetOnSingleThreaded) { } TEST_P(ThreadPoolTaskTrackerTest, FlushPendingDelayedTask) { - Task delayed_task(FROM_HERE, DoNothing(), TimeDelta::FromDays(1)); + Task delayed_task(FROM_HERE, DoNothing(), TimeTicks::Now(), + TimeDelta::FromDays(1)); tracker_.WillPostTask(&delayed_task, GetParam()); // FlushForTesting() should return even if the delayed task didn't run. tracker_.FlushForTesting(); } TEST_P(ThreadPoolTaskTrackerTest, FlushAsyncForTestingPendingDelayedTask) { - Task delayed_task(FROM_HERE, DoNothing(), TimeDelta::FromDays(1)); + Task delayed_task(FROM_HERE, DoNothing(), TimeTicks::Now(), + TimeDelta::FromDays(1)); tracker_.WillPostTask(&delayed_task, GetParam()); // FlushAsyncForTesting() should callback even if the delayed task didn't run. bool called_back = false; @@ -648,7 +651,7 @@ TEST_P(ThreadPoolTaskTrackerTest, FlushAsyncForTestingPendingDelayedTask) { } TEST_P(ThreadPoolTaskTrackerTest, FlushPendingUndelayedTask) { - Task undelayed_task(FROM_HERE, DoNothing(), TimeDelta()); + Task undelayed_task(FROM_HERE, DoNothing(), TimeTicks::Now(), TimeDelta()); auto undelayed_sequence = WillPostTaskAndQueueTaskSource(std::move(undelayed_task), {GetParam()}); @@ -663,7 +666,7 @@ TEST_P(ThreadPoolTaskTrackerTest, FlushPendingUndelayedTask) { } TEST_P(ThreadPoolTaskTrackerTest, FlushAsyncForTestingPendingUndelayedTask) { - Task undelayed_task(FROM_HERE, DoNothing(), TimeDelta()); + Task undelayed_task(FROM_HERE, DoNothing(), TimeTicks::Now(), TimeDelta()); auto undelayed_sequence = WillPostTaskAndQueueTaskSource(std::move(undelayed_task), {GetParam()}); @@ -680,7 +683,7 @@ TEST_P(ThreadPoolTaskTrackerTest, FlushAsyncForTestingPendingUndelayedTask) { } TEST_P(ThreadPoolTaskTrackerTest, PostTaskDuringFlush) { - Task undelayed_task(FROM_HERE, DoNothing(), TimeDelta()); + Task undelayed_task(FROM_HERE, DoNothing(), TimeTicks::Now(), TimeDelta()); auto undelayed_sequence = WillPostTaskAndQueueTaskSource(std::move(undelayed_task), {GetParam()}); @@ -690,7 +693,8 @@ TEST_P(ThreadPoolTaskTrackerTest, PostTaskDuringFlush) { VERIFY_ASYNC_FLUSH_IN_PROGRESS(); // Simulate posting another undelayed task. - Task other_undelayed_task(FROM_HERE, DoNothing(), TimeDelta()); + Task other_undelayed_task(FROM_HERE, DoNothing(), TimeTicks::Now(), + TimeDelta()); auto other_undelayed_sequence = WillPostTaskAndQueueTaskSource( std::move(other_undelayed_task), {GetParam()}); @@ -707,7 +711,7 @@ TEST_P(ThreadPoolTaskTrackerTest, PostTaskDuringFlush) { } TEST_P(ThreadPoolTaskTrackerTest, PostTaskDuringFlushAsyncForTesting) { - Task undelayed_task(FROM_HERE, DoNothing(), TimeDelta()); + Task undelayed_task(FROM_HERE, DoNothing(), TimeTicks::Now(), TimeDelta()); auto undelayed_sequence = WillPostTaskAndQueueTaskSource(std::move(undelayed_task), {GetParam()}); @@ -719,7 +723,8 @@ TEST_P(ThreadPoolTaskTrackerTest, PostTaskDuringFlushAsyncForTesting) { EXPECT_FALSE(event.IsSignaled()); // Simulate posting another undelayed task. - Task other_undelayed_task(FROM_HERE, DoNothing(), TimeDelta()); + Task other_undelayed_task(FROM_HERE, DoNothing(), TimeTicks::Now(), + TimeDelta()); auto other_undelayed_sequence = WillPostTaskAndQueueTaskSource( std::move(other_undelayed_task), {GetParam()}); @@ -739,10 +744,11 @@ TEST_P(ThreadPoolTaskTrackerTest, PostTaskDuringFlushAsyncForTesting) { TEST_P(ThreadPoolTaskTrackerTest, RunDelayedTaskDuringFlush) { // Simulate posting a delayed and an undelayed task. - Task delayed_task(FROM_HERE, DoNothing(), TimeDelta::FromDays(1)); + Task delayed_task(FROM_HERE, DoNothing(), TimeTicks::Now(), + TimeDelta::FromDays(1)); auto delayed_sequence = WillPostTaskAndQueueTaskSource(std::move(delayed_task), {GetParam()}); - Task undelayed_task(FROM_HERE, DoNothing(), TimeDelta()); + Task undelayed_task(FROM_HERE, DoNothing(), TimeTicks::Now(), TimeDelta()); auto undelayed_sequence = WillPostTaskAndQueueTaskSource(std::move(undelayed_task), {GetParam()}); @@ -768,10 +774,11 @@ TEST_P(ThreadPoolTaskTrackerTest, RunDelayedTaskDuringFlush) { TEST_P(ThreadPoolTaskTrackerTest, RunDelayedTaskDuringFlushAsyncForTesting) { // Simulate posting a delayed and an undelayed task. - Task delayed_task(FROM_HERE, DoNothing(), TimeDelta::FromDays(1)); + Task delayed_task(FROM_HERE, DoNothing(), TimeTicks::Now(), + TimeDelta::FromDays(1)); auto delayed_sequence = WillPostTaskAndQueueTaskSource(std::move(delayed_task), {GetParam()}); - Task undelayed_task(FROM_HERE, DoNothing(), TimeDelta()); + Task undelayed_task(FROM_HERE, DoNothing(), TimeTicks::Now(), TimeDelta()); auto undelayed_sequence = WillPostTaskAndQueueTaskSource(std::move(undelayed_task), {GetParam()}); @@ -802,7 +809,7 @@ TEST_P(ThreadPoolTaskTrackerTest, FlushAfterShutdown) { return; // Simulate posting a task. - Task undelayed_task(FROM_HERE, DoNothing(), TimeDelta()); + Task undelayed_task(FROM_HERE, DoNothing(), TimeTicks::Now(), TimeDelta()); tracker_.WillPostTask(&undelayed_task, GetParam()); // Shutdown() should return immediately since there are no pending @@ -819,7 +826,7 @@ TEST_P(ThreadPoolTaskTrackerTest, FlushAfterShutdownAsync) { return; // Simulate posting a task. - Task undelayed_task(FROM_HERE, DoNothing(), TimeDelta()); + Task undelayed_task(FROM_HERE, DoNothing(), TimeTicks::Now(), TimeDelta()); tracker_.WillPostTask(&undelayed_task, GetParam()); // Shutdown() should return immediately since there are no pending @@ -840,7 +847,7 @@ TEST_P(ThreadPoolTaskTrackerTest, ShutdownDuringFlush) { return; // Simulate posting a task. - Task undelayed_task(FROM_HERE, DoNothing(), TimeDelta()); + Task undelayed_task(FROM_HERE, DoNothing(), TimeTicks::Now(), TimeDelta()); auto undelayed_sequence = WillPostTaskAndQueueTaskSource(std::move(undelayed_task), {GetParam()}); @@ -863,7 +870,7 @@ TEST_P(ThreadPoolTaskTrackerTest, ShutdownDuringFlushAsyncForTesting) { return; // Simulate posting a task. - Task undelayed_task(FROM_HERE, DoNothing(), TimeDelta()); + Task undelayed_task(FROM_HERE, DoNothing(), TimeTicks::Now(), TimeDelta()); auto undelayed_sequence = WillPostTaskAndQueueTaskSource(std::move(undelayed_task), {GetParam()}); @@ -885,7 +892,7 @@ TEST_P(ThreadPoolTaskTrackerTest, ShutdownDuringFlushAsyncForTesting) { } TEST_P(ThreadPoolTaskTrackerTest, DoublePendingFlushAsyncForTestingFails) { - Task undelayed_task(FROM_HERE, DoNothing(), TimeDelta()); + Task undelayed_task(FROM_HERE, DoNothing(), TimeTicks::Now(), TimeDelta()); auto undelayed_sequence = WillPostTaskAndQueueTaskSource(std::move(undelayed_task), {GetParam()}); @@ -901,7 +908,7 @@ TEST_P(ThreadPoolTaskTrackerTest, DoublePendingFlushAsyncForTestingFails) { TEST_P(ThreadPoolTaskTrackerTest, PostTasksDoNotBlockShutdown) { // Simulate posting an undelayed task. - Task undelayed_task(FROM_HERE, DoNothing(), TimeDelta()); + Task undelayed_task(FROM_HERE, DoNothing(), TimeTicks::Now(), TimeDelta()); EXPECT_TRUE(tracker_.WillPostTask(&undelayed_task, GetParam())); // Since no sequence was queued, a call to Shutdown() should not hang. @@ -912,7 +919,8 @@ TEST_P(ThreadPoolTaskTrackerTest, PostTasksDoNotBlockShutdown) { // of its shutdown behavior. TEST_P(ThreadPoolTaskTrackerTest, DelayedRunTasks) { // Simulate posting a delayed task. - Task delayed_task(FROM_HERE, DoNothing(), TimeDelta::FromDays(1)); + Task delayed_task(FROM_HERE, DoNothing(), TimeTicks::Now(), + TimeDelta::FromDays(1)); auto sequence = WillPostTaskAndQueueTaskSource(std::move(delayed_task), {GetParam()}); EXPECT_TRUE(sequence); @@ -953,7 +961,7 @@ TEST_F(ThreadPoolTaskTrackerTest, CurrentSequenceToken) { const SequenceToken sequence_token = sequence->token(); Task task(FROM_HERE, BindOnce(&ExpectSequenceToken, sequence_token), - TimeDelta()); + TimeTicks::Now(), TimeDelta()); tracker_.WillPostTask(&task, sequence->shutdown_behavior()); { @@ -1149,10 +1157,10 @@ TEST_F(ThreadPoolTaskTrackerTest, LoadWillPostAndRunDuringShutdown) { TEST_F(ThreadPoolTaskTrackerTest, RunAndPopNextTaskReturnsSequenceToReschedule) { TaskTraits default_traits; - Task task_1(FROM_HERE, DoNothing(), TimeDelta()); + Task task_1(FROM_HERE, DoNothing(), TimeTicks::Now(), TimeDelta()); EXPECT_TRUE( tracker_.WillPostTask(&task_1, default_traits.shutdown_behavior())); - Task task_2(FROM_HERE, DoNothing(), TimeDelta()); + Task task_2(FROM_HERE, DoNothing(), TimeTicks::Now(), TimeDelta()); EXPECT_TRUE( tracker_.WillPostTask(&task_2, default_traits.shutdown_behavior())); @@ -1182,7 +1190,7 @@ class WaitAllowedTestThread : public SimpleThread { FROM_HERE, BindOnce([]() { EXPECT_DCHECK_DEATH({ internal::AssertBaseSyncPrimitivesAllowed(); }); }), - TimeDelta()); + TimeTicks::Now(), TimeDelta()); TaskTraits default_traits; EXPECT_TRUE(task_tracker->WillPostTask(&task_without_sync_primitives, default_traits.shutdown_behavior())); @@ -1199,7 +1207,7 @@ class WaitAllowedTestThread : public SimpleThread { // Shouldn't fail. internal::AssertBaseSyncPrimitivesAllowed(); }), - TimeDelta()); + TimeTicks::Now(), TimeDelta()); TaskTraits traits_with_sync_primitives = TaskTraits(WithBaseSyncPrimitives()); EXPECT_TRUE(task_tracker->WillPostTask( diff --git a/chromium/base/task/thread_pool/thread_group.h b/chromium/base/task/thread_pool/thread_group.h index d03230ae65a..b29d0701e68 100644 --- a/chromium/base/task/thread_pool/thread_group.h +++ b/chromium/base/task/thread_pool/thread_group.h @@ -16,6 +16,7 @@ #include "base/task/thread_pool/task_source.h" #include "base/task/thread_pool/tracked_ref.h" #include "build/build_config.h" +#include "third_party/abseil-cpp/absl/types/optional.h" #if defined(OS_WIN) #include "base/win/scoped_windows_thread_environment.h" @@ -160,7 +161,8 @@ class BASE_EXPORT ThreadGroup { private: // A TransactionWithRegisteredTaskSource and the thread group in which it // should be enqueued. - Optional<TransactionWithRegisteredTaskSource> transaction_with_task_source_; + absl::optional<TransactionWithRegisteredTaskSource> + transaction_with_task_source_; ThreadGroup* destination_thread_group_ = nullptr; }; diff --git a/chromium/base/task/thread_pool/thread_group_impl.cc b/chromium/base/task/thread_pool/thread_group_impl.cc index 0aa268df2ef..7392399f8a2 100644 --- a/chromium/base/task/thread_pool/thread_group_impl.cc +++ b/chromium/base/task/thread_pool/thread_group_impl.cc @@ -21,7 +21,6 @@ #include "base/memory/ptr_util.h" #include "base/metrics/histogram.h" #include "base/numerics/clamped_math.h" -#include "base/optional.h" #include "base/ranges/algorithm.h" #include "base/sequence_token.h" #include "base/strings/string_piece.h" @@ -36,6 +35,7 @@ #include "base/threading/thread_restrictions.h" #include "base/time/time_override.h" #include "build/build_config.h" +#include "third_party/abseil-cpp/absl/types/optional.h" #if defined(OS_WIN) #include "base/win/scoped_com_initializer.h" @@ -303,7 +303,7 @@ class ThreadGroupImpl::WorkerThreadDelegateImpl : public WorkerThread::Delegate, // thread, protected by |outer_->lock_| when not on the worker thread. struct WriteWorkerReadAny { // The priority of the task the worker is currently running if any. - base::Optional<TaskPriority> current_task_priority; + absl::optional<TaskPriority> current_task_priority; // Time when MayBlockScopeEntered() was last called. Reset when // BlockingScopeExited() is called. @@ -377,7 +377,7 @@ void ThreadGroupImpl::Start( WorkerThreadObserver* worker_thread_observer, WorkerEnvironment worker_environment, bool synchronous_thread_start_for_testing, - Optional<TimeDelta> may_block_threshold) { + absl::optional<TimeDelta> may_block_threshold) { ThreadGroup::Start(); DCHECK(!replacement_thread_group_); @@ -645,7 +645,8 @@ void ThreadGroupImpl::WorkerThreadDelegateImpl::DidProcessTask( // A transaction to the TaskSource to reenqueue, if any. Instantiated here as // |TaskSource::lock_| is a UniversalPredecessor and must always be acquired // prior to acquiring a second lock - Optional<TransactionWithRegisteredTaskSource> transaction_with_task_source; + absl::optional<TransactionWithRegisteredTaskSource> + transaction_with_task_source; if (task_source) { transaction_with_task_source.emplace( TransactionWithRegisteredTaskSource::FromTaskSource( @@ -713,8 +714,6 @@ bool ThreadGroupImpl::WorkerThreadDelegateImpl::CanCleanupLockRequired( return !last_used_time.is_null() && subtle::TimeTicksNowIgnoringOverride() - last_used_time >= outer_->after_start().suggested_reclaim_time && - (outer_->workers_.size() > outer_->after_start().initial_max_tasks || - !FeatureList::IsEnabled(kNoDetachBelowInitialCapacity)) && LIKELY(!outer_->worker_cleanup_disallowed_for_testing_); } diff --git a/chromium/base/task/thread_pool/thread_group_impl.h b/chromium/base/task/thread_pool/thread_group_impl.h index 39bd53d2d82..597fa2a0429 100644 --- a/chromium/base/task/thread_pool/thread_group_impl.h +++ b/chromium/base/task/thread_pool/thread_group_impl.h @@ -16,7 +16,6 @@ #include "base/compiler_specific.h" #include "base/gtest_prod_util.h" #include "base/memory/ref_counted.h" -#include "base/optional.h" #include "base/sequenced_task_runner.h" #include "base/strings/string_piece.h" #include "base/synchronization/condition_variable.h" @@ -29,6 +28,7 @@ #include "base/task/thread_pool/worker_thread.h" #include "base/task/thread_pool/worker_thread_stack.h" #include "base/time/time.h" +#include "third_party/abseil-cpp/absl/types/optional.h" namespace base { @@ -82,7 +82,8 @@ class BASE_EXPORT ThreadGroupImpl : public ThreadGroup { WorkerThreadObserver* worker_thread_observer, WorkerEnvironment worker_environment, bool synchronous_thread_start_for_testing = false, - Optional<TimeDelta> may_block_threshold = Optional<TimeDelta>()); + absl::optional<TimeDelta> may_block_threshold = + absl::optional<TimeDelta>()); ThreadGroupImpl(const ThreadGroupImpl&) = delete; ThreadGroupImpl& operator=(const ThreadGroupImpl&) = delete; @@ -336,7 +337,7 @@ class BASE_EXPORT ThreadGroupImpl : public ThreadGroup { // Null-opt unless |synchronous_thread_start_for_testing| was true at // construction. In that case, it's signaled each time // WorkerThreadDelegateImpl::OnMainEntry() completes. - Optional<WaitableEvent> worker_started_for_testing_; + absl::optional<WaitableEvent> worker_started_for_testing_; // Cached HistogramBase pointers, can be accessed without // holding |lock_|. If |lock_| is held, add new samples using diff --git a/chromium/base/task/thread_pool/thread_group_impl_unittest.cc b/chromium/base/task/thread_pool/thread_group_impl_unittest.cc index d13582af5af..a58294b324b 100644 --- a/chromium/base/task/thread_pool/thread_group_impl_unittest.cc +++ b/chromium/base/task/thread_pool/thread_group_impl_unittest.cc @@ -52,6 +52,7 @@ #include "base/timer/timer.h" #include "build/build_config.h" #include "testing/gtest/include/gtest/gtest.h" +#include "third_party/abseil-cpp/absl/types/optional.h" namespace base { namespace internal { @@ -98,11 +99,12 @@ class ThreadGroupImplImplTestBase : public ThreadGroup::Delegate { mock_pooled_task_runner_delegate_.SetThreadGroup(thread_group_.get()); } - void StartThreadGroup(TimeDelta suggested_reclaim_time, - size_t max_tasks, - Optional<int> max_best_effort_tasks = nullopt, - WorkerThreadObserver* worker_observer = nullptr, - Optional<TimeDelta> may_block_threshold = nullopt) { + void StartThreadGroup( + TimeDelta suggested_reclaim_time, + size_t max_tasks, + absl::optional<int> max_best_effort_tasks = absl::nullopt, + WorkerThreadObserver* worker_observer = nullptr, + absl::optional<TimeDelta> may_block_threshold = absl::nullopt) { ASSERT_TRUE(thread_group_); thread_group_->Start( max_tasks, @@ -115,9 +117,9 @@ class ThreadGroupImplImplTestBase : public ThreadGroup::Delegate { void CreateAndStartThreadGroup( TimeDelta suggested_reclaim_time = TimeDelta::Max(), size_t max_tasks = kMaxTasks, - Optional<int> max_best_effort_tasks = nullopt, + absl::optional<int> max_best_effort_tasks = absl::nullopt, WorkerThreadObserver* worker_observer = nullptr, - Optional<TimeDelta> may_block_threshold = nullopt) { + absl::optional<TimeDelta> may_block_threshold = absl::nullopt) { CreateThreadGroup(); StartThreadGroup(suggested_reclaim_time, max_tasks, max_best_effort_tasks, worker_observer, may_block_threshold); @@ -1353,7 +1355,7 @@ TEST_F(ThreadGroupImplBlockingTest, ThreadBlockUnblockPremature) { // MAY_BLOCK ScopedBlockingCall never increases the max tasks. CreateAndStartThreadGroup(TimeDelta::Max(), // |suggested_reclaim_time| kMaxTasks, // |max_tasks| - nullopt, // |max_best_effort_tasks| + absl::nullopt, // |max_best_effort_tasks| nullptr, // |worker_observer| TimeDelta::Max()); // |may_block_threshold| @@ -1761,7 +1763,7 @@ TEST_F(ThreadGroupImplImplStartInBodyTest, constexpr size_t kNumWorkers = 2U; StartThreadGroup(TimeDelta::Max(), // |suggested_reclaim_time| kNumWorkers, // |max_tasks| - nullopt); // |max_best_effort_tasks| + absl::nullopt); // |max_best_effort_tasks| const scoped_refptr<TaskRunner> runner = test::CreatePooledTaskRunner( {MayBlock()}, &mock_pooled_task_runner_delegate_); diff --git a/chromium/base/task/thread_pool/thread_group_native_win.cc b/chromium/base/task/thread_pool/thread_group_native_win.cc index bd9a0232d2e..e803dafc92a 100644 --- a/chromium/base/task/thread_pool/thread_group_native_win.cc +++ b/chromium/base/task/thread_pool/thread_group_native_win.cc @@ -6,7 +6,6 @@ #include <utility> -#include "base/optional.h" #include "base/task/thread_pool/task_tracker.h" #include "base/threading/scoped_blocking_call_internal.h" #include "base/win/scoped_com_initializer.h" diff --git a/chromium/base/task/thread_pool/thread_pool_impl.cc b/chromium/base/task/thread_pool/thread_pool_impl.cc index 21e1d03927a..9a43b51e931 100644 --- a/chromium/base/task/thread_pool/thread_pool_impl.cc +++ b/chromium/base/task/thread_pool/thread_pool_impl.cc @@ -30,6 +30,7 @@ #include "base/task/thread_pool/worker_thread.h" #include "base/threading/platform_thread.h" #include "base/time/time.h" +#include "third_party/abseil-cpp/absl/types/optional.h" #if defined(OS_WIN) #include "base/task/thread_pool/thread_group_native_win.h" @@ -67,6 +68,12 @@ bool HasDisableBestEffortTasksSwitch() { // internal edge case. bool g_synchronous_thread_start_for_testing = false; +// Verifies that |traits| do not have properties that are banned in ThreadPool. +void AssertNoExtensionInTraits(const base::TaskTraits& traits) { + DCHECK_EQ(traits.extension_id(), + TaskTraitsExtensionStorage::kInvalidExtensionId); +} + } // namespace ThreadPoolImpl::ThreadPoolImpl(StringPiece histogram_label) @@ -129,11 +136,6 @@ void ThreadPoolImpl::Start(const ThreadPoolInstance::InitParams& init_params, const int max_best_effort_tasks = std::min(kMaxBestEffortTasks, init_params.max_num_foreground_threads); - // This is set in Start() and not in the constructor because variation params - // are usually not ready when ThreadPoolImpl is instantiated in a process. - if (FeatureList::IsEnabled(kAllTasksUserBlocking)) - all_tasks_user_blocking_.Set(); - #if HAS_NATIVE_THREAD_POOL() if (FeatureList::IsEnabled(kUseNativeThreadPool)) { std::unique_ptr<ThreadGroup> old_group = @@ -173,7 +175,7 @@ void ThreadPoolImpl::Start(const ThreadPoolInstance::InitParams& init_params, MessagePumpType::DEFAULT; #endif service_thread_options.timer_slack = TIMER_SLACK_MAXIMUM; - CHECK(service_thread_.StartWithOptions(service_thread_options)); + CHECK(service_thread_.StartWithOptions(std::move(service_thread_options))); if (g_synchronous_thread_start_for_testing) service_thread_.WaitUntilThreadStarted(); @@ -263,50 +265,53 @@ bool ThreadPoolImpl::PostDelayedTask(const Location& from_here, const TaskTraits& traits, OnceClosure task, TimeDelta delay) { + AssertNoExtensionInTraits(traits); // Post |task| as part of a one-off single-task Sequence. - const TaskTraits new_traits = VerifyAndAjustIncomingTraits(traits); return PostTaskWithSequence( - Task(from_here, std::move(task), delay), - MakeRefCounted<Sequence>(new_traits, nullptr, + Task(from_here, std::move(task), TimeTicks::Now(), delay), + MakeRefCounted<Sequence>(traits, nullptr, TaskSourceExecutionMode::kParallel)); } scoped_refptr<TaskRunner> ThreadPoolImpl::CreateTaskRunner( const TaskTraits& traits) { - const TaskTraits new_traits = VerifyAndAjustIncomingTraits(traits); - return MakeRefCounted<PooledParallelTaskRunner>(new_traits, this); + AssertNoExtensionInTraits(traits); + return MakeRefCounted<PooledParallelTaskRunner>(traits, this); } scoped_refptr<SequencedTaskRunner> ThreadPoolImpl::CreateSequencedTaskRunner( const TaskTraits& traits) { - const TaskTraits new_traits = VerifyAndAjustIncomingTraits(traits); - return MakeRefCounted<PooledSequencedTaskRunner>(new_traits, this); + AssertNoExtensionInTraits(traits); + return MakeRefCounted<PooledSequencedTaskRunner>(traits, this); } scoped_refptr<SingleThreadTaskRunner> ThreadPoolImpl::CreateSingleThreadTaskRunner( const TaskTraits& traits, SingleThreadTaskRunnerThreadMode thread_mode) { + AssertNoExtensionInTraits(traits); return single_thread_task_runner_manager_.CreateSingleThreadTaskRunner( - VerifyAndAjustIncomingTraits(traits), thread_mode); + traits, thread_mode); } #if defined(OS_WIN) scoped_refptr<SingleThreadTaskRunner> ThreadPoolImpl::CreateCOMSTATaskRunner( const TaskTraits& traits, SingleThreadTaskRunnerThreadMode thread_mode) { - return single_thread_task_runner_manager_.CreateCOMSTATaskRunner( - VerifyAndAjustIncomingTraits(traits), thread_mode); + AssertNoExtensionInTraits(traits); + return single_thread_task_runner_manager_.CreateCOMSTATaskRunner(traits, + thread_mode); } #endif // defined(OS_WIN) scoped_refptr<UpdateableSequencedTaskRunner> ThreadPoolImpl::CreateUpdateableSequencedTaskRunner(const TaskTraits& traits) { - const TaskTraits new_traits = VerifyAndAjustIncomingTraits(traits); - return MakeRefCounted<PooledSequencedTaskRunner>(new_traits, this); + AssertNoExtensionInTraits(traits); + return MakeRefCounted<PooledSequencedTaskRunner>(traits, this); } -Optional<TimeTicks> ThreadPoolImpl::NextScheduledRunTimeForTesting() const { +absl::optional<TimeTicks> ThreadPoolImpl::NextScheduledRunTimeForTesting() + const { if (task_tracker_->HasIncompleteTaskSourcesForTesting()) return TimeTicks::Now(); return delayed_task_manager_.NextScheduledRunTime(); @@ -573,15 +578,5 @@ void ThreadPoolImpl::UpdateCanRunPolicy() { single_thread_task_runner_manager_.DidUpdateCanRunPolicy(); } -TaskTraits ThreadPoolImpl::VerifyAndAjustIncomingTraits( - TaskTraits traits) const { - DCHECK_EQ(traits.extension_id(), - TaskTraitsExtensionStorage::kInvalidExtensionId) - << "Extension traits cannot be used with the ThreadPool API."; - if (all_tasks_user_blocking_.IsSet()) - traits.UpdatePriority(TaskPriority::USER_BLOCKING); - return traits; -} - } // namespace internal } // namespace base diff --git a/chromium/base/task/thread_pool/thread_pool_impl.h b/chromium/base/task/thread_pool/thread_pool_impl.h index cefed72b515..80709dd3fa7 100644 --- a/chromium/base/task/thread_pool/thread_pool_impl.h +++ b/chromium/base/task/thread_pool/thread_pool_impl.h @@ -13,7 +13,6 @@ #include "base/check_op.h" #include "base/memory/ptr_util.h" #include "base/memory/ref_counted.h" -#include "base/optional.h" #include "base/sequence_checker.h" #include "base/strings/string_piece.h" #include "base/synchronization/atomic_flag.h" @@ -35,6 +34,7 @@ #if defined(OS_POSIX) && !defined(OS_NACL_SFI) #include "base/task/thread_pool/task_tracker_posix.h" +#include "third_party/abseil-cpp/absl/types/optional.h" #endif #if defined(OS_WIN) @@ -115,7 +115,7 @@ class BASE_EXPORT ThreadPoolImpl : public ThreadPoolInstance, // immediate, nullopt if none). This is thread-safe, i.e., it's safe if tasks // are being posted in parallel with this call but such a situation obviously // results in a race as to whether this call will see the new tasks in time. - Optional<TimeTicks> NextScheduledRunTimeForTesting() const; + absl::optional<TimeTicks> NextScheduledRunTimeForTesting() const; // Forces ripe delayed tasks to be posted (e.g. when time is mocked and // advances faster than the real-time delay on ServiceThread). @@ -133,11 +133,6 @@ class BASE_EXPORT ThreadPoolImpl : public ThreadPoolInstance, // the CanRunPolicy in TaskTracker and wakes up workers as appropriate. void UpdateCanRunPolicy(); - // Verifies that |traits| do not have properties that are banned in ThreadPool - // and returns |traits|, with priority set to TaskPriority::USER_BLOCKING if - // |all_tasks_user_blocking_| is set. - TaskTraits VerifyAndAjustIncomingTraits(TaskTraits traits) const; - const ThreadGroup* GetThreadGroupForTraits(const TaskTraits& traits) const; // ThreadGroup::Delegate: @@ -158,14 +153,6 @@ class BASE_EXPORT ThreadPoolImpl : public ThreadPoolInstance, DelayedTaskManager delayed_task_manager_; PooledSingleThreadTaskRunnerManager single_thread_task_runner_manager_; - // Indicates that all tasks are handled as if they had been posted with - // TaskPriority::USER_BLOCKING. Since this is set in Start(), it doesn't apply - // to tasks posted before Start() or to tasks posted to TaskRunners created - // before Start(). - // - // TODO(fdoray): Remove after experiment. https://crbug.com/757022 - AtomicFlag all_tasks_user_blocking_; - std::unique_ptr<ThreadGroup> foreground_thread_group_; std::unique_ptr<ThreadGroup> background_thread_group_; diff --git a/chromium/base/task/thread_pool/thread_pool_impl_unittest.cc b/chromium/base/task/thread_pool/thread_pool_impl_unittest.cc index ce913d54648..f07c98cbd40 100644 --- a/chromium/base/task/thread_pool/thread_pool_impl_unittest.cc +++ b/chromium/base/task/thread_pool/thread_pool_impl_unittest.cc @@ -17,6 +17,7 @@ #include "base/callback.h" #include "base/callback_helpers.h" #include "base/cfi_buildflags.h" +#include "base/containers/span.h" #include "base/debug/stack_trace.h" #include "base/metrics/field_trial.h" #include "base/metrics/field_trial_params.h" @@ -300,10 +301,6 @@ class ThreadPoolImplTestBase : public testing::Test { ThreadPoolImplTestBase(const ThreadPoolImplTestBase&) = delete; ThreadPoolImplTestBase& operator=(const ThreadPoolImplTestBase&) = delete; - void EnableAllTasksUserBlocking() { - should_enable_all_tasks_user_blocking_ = true; - } - void set_worker_thread_observer( WorkerThreadObserver* worker_thread_observer) { worker_thread_observer_ = worker_thread_observer; @@ -339,9 +336,6 @@ class ThreadPoolImplTestBase : public testing::Test { void SetupFeatures() { std::vector<base::Feature> features; - if (should_enable_all_tasks_user_blocking_) - features.push_back(kAllTasksUserBlocking); - #if HAS_NATIVE_THREAD_POOL() if (GetGroupTypes().foreground_type == test::GroupType::NATIVE) features.push_back(kUseNativeThreadPool); @@ -356,7 +350,6 @@ class ThreadPoolImplTestBase : public testing::Test { base::test::ScopedFeatureList feature_list_; WorkerThreadObserver* worker_thread_observer_ = nullptr; bool did_tear_down_ = false; - bool should_enable_all_tasks_user_blocking_ = false; }; class ThreadPoolImplTest : public ThreadPoolImplTestBase, @@ -526,46 +519,6 @@ TEST_P(ThreadPoolImplTest_CoverAllSchedulingOptions, PostTaskAfterDestroy) { task_runner->PostTask(FROM_HERE, MakeExpectedNotRunClosure(FROM_HERE))); } -// Verify that all tasks posted to a TaskRunner after Start() run in a -// USER_BLOCKING environment when the AllTasksUserBlocking variation param of -// the BrowserScheduler experiment is true. -TEST_P(ThreadPoolImplTest_CoverAllSchedulingOptions, - AllTasksAreUserBlockingTaskRunner) { - TaskTraits user_blocking_traits = GetTraits(); - user_blocking_traits.UpdatePriority(TaskPriority::USER_BLOCKING); - - EnableAllTasksUserBlocking(); - StartThreadPool(); - - TestWaitableEvent task_running; - CreateTaskRunnerAndExecutionMode(thread_pool_.get(), GetTraits(), - GetExecutionMode()) - ->PostTask(FROM_HERE, BindOnce(&VerifyTaskEnvironmentAndSignalEvent, - user_blocking_traits, GetGroupTypes(), - Unretained(&task_running))); - task_running.Wait(); -} - -// Verify that all tasks posted via PostDelayedTask() after Start() run in a -// USER_BLOCKING environment when the AllTasksUserBlocking variation param of -// the BrowserScheduler experiment is true. -TEST_P(ThreadPoolImplTest_CoverAllSchedulingOptions, AllTasksAreUserBlocking) { - TaskTraits user_blocking_traits = GetTraits(); - user_blocking_traits.UpdatePriority(TaskPriority::USER_BLOCKING); - - EnableAllTasksUserBlocking(); - StartThreadPool(); - - TestWaitableEvent task_running; - // Ignore |params.execution_mode| in this test. - thread_pool_->PostDelayedTask( - FROM_HERE, GetTraits(), - BindOnce(&VerifyTaskEnvironmentAndSignalEvent, user_blocking_traits, - GetGroupTypes(), Unretained(&task_running)), - TimeDelta()); - task_running.Wait(); -} - // Verifies that FlushAsyncForTesting() calls back correctly for all trait and // execution mode pairs. TEST_P(ThreadPoolImplTest_CoverAllSchedulingOptions, @@ -961,7 +914,7 @@ TEST_P(ThreadPoolImplTest, FileDescriptorWatcherNoOpsAfterShutdown) { thread_pool_->Shutdown(); constexpr char kByte = '!'; - ASSERT_TRUE(WriteFileDescriptor(pipes[1], &kByte, sizeof(kByte))); + ASSERT_TRUE(WriteFileDescriptor(pipes[1], as_bytes(make_span(&kByte, 1)))); // Give a chance for the file watcher to fire before closing the handles. PlatformThread::Sleep(TestTimeouts::tiny_timeout()); diff --git a/chromium/base/task/thread_pool/thread_pool_perftest.cc b/chromium/base/task/thread_pool/thread_pool_perftest.cc index 74d88ef0aa3..99d467326e8 100644 --- a/chromium/base/task/thread_pool/thread_pool_perftest.cc +++ b/chromium/base/task/thread_pool/thread_pool_perftest.cc @@ -11,7 +11,6 @@ #include "base/bind.h" #include "base/callback.h" #include "base/callback_helpers.h" -#include "base/optional.h" #include "base/synchronization/waitable_event.h" #include "base/task/thread_pool.h" #include "base/task/thread_pool/thread_pool_instance.h" @@ -19,6 +18,7 @@ #include "base/time/time.h" #include "testing/gtest/include/gtest/gtest.h" #include "testing/perf/perf_result_reporter.h" +#include "third_party/abseil-cpp/absl/types/optional.h" namespace base { namespace internal { @@ -163,7 +163,7 @@ class ThreadPoolPerfTest : public testing::Test { void OnCompletePostingTasks() { complete_posting_tasks_.Signal(); } void Benchmark(const std::string& story_name, ExecutionMode execution_mode) { - base::Optional<ThreadPoolInstance::ScopedExecutionFence> execution_fence; + absl::optional<ThreadPoolInstance::ScopedExecutionFence> execution_fence; if (execution_mode == ExecutionMode::kPostThenRun) { execution_fence.emplace(); } diff --git a/chromium/base/task/thread_pool/tracked_ref.h b/chromium/base/task/thread_pool/tracked_ref.h index 736f95603da..483cbdccae7 100644 --- a/chromium/base/task/thread_pool/tracked_ref.h +++ b/chromium/base/task/thread_pool/tracked_ref.h @@ -9,9 +9,9 @@ #include "base/check.h" #include "base/gtest_prod_util.h" #include "base/memory/ptr_util.h" -#include "base/optional.h" #include "base/synchronization/waitable_event.h" #include "base/template_util.h" +#include "third_party/abseil-cpp/absl/types/optional.h" namespace base { namespace internal { @@ -168,11 +168,11 @@ class TrackedRefFactory { // Non-null during the destruction phase. Signaled once |live_tracked_refs_| // reaches 0. Note: making this optional and only initializing it in the // destruction phase avoids keeping a handle open for the entire session. - Optional<WaitableEvent> ready_to_destroy_; + absl::optional<WaitableEvent> ready_to_destroy_; // TrackedRefFactory holds a TrackedRef as well to prevent // |live_tracked_refs_| from ever reaching zero before ~TrackedRefFactory(). - Optional<TrackedRef<T>> self_ref_; + absl::optional<TrackedRef<T>> self_ref_; }; } // namespace internal diff --git a/chromium/base/task/thread_pool/worker_thread.cc b/chromium/base/task/thread_pool/worker_thread.cc index 9d72e7dcc2b..9165822fe8c 100644 --- a/chromium/base/task/thread_pool/worker_thread.cc +++ b/chromium/base/task/thread_pool/worker_thread.cc @@ -6,8 +6,11 @@ #include <stddef.h> +#include <algorithm> #include <utility> +#include "base/allocator/buildflags.h" +#include "base/allocator/partition_allocator/partition_alloc_config.h" #include "base/callback_helpers.h" #include "base/check_op.h" #include "base/compiler_specific.h" @@ -18,24 +21,59 @@ #include "base/threading/hang_watcher.h" #include "base/time/time_override.h" #include "base/trace_event/base_tracing.h" +#include "third_party/abseil-cpp/absl/types/optional.h" #if defined(OS_APPLE) #include "base/mac/scoped_nsautorelease_pool.h" #endif +#if BUILDFLAG(USE_PARTITION_ALLOC_AS_MALLOC) && \ + defined(PA_THREAD_CACHE_SUPPORTED) +#include "base/allocator/partition_allocator/thread_cache.h" +#endif + namespace base { namespace internal { +constexpr TimeDelta WorkerThread::Delegate::kPurgeThreadCacheIdleDelay; + void WorkerThread::Delegate::WaitForWork(WaitableEvent* wake_up_event) { DCHECK(wake_up_event); const TimeDelta sleep_time = GetSleepTimeout(); - if (sleep_time.is_max()) { - // Calling TimedWait with TimeDelta::Max is not recommended per - // http://crbug.com/465948. - wake_up_event->Wait(); - } else { - wake_up_event->TimedWait(sleep_time); + + // When a thread goes to sleep, the memory retained by its thread cache is + // trapped there for as long as the thread sleeps. To prevent that, we can + // either purge the thread cache right before going to sleep, or after some + // delay. + // + // Purging the thread cache incurs a cost on the next task, since its thread + // cache will be empty and allocation performance initially lower. As a lot of + // sleeps are very short, do not purge all the time (this would also make + // sleep / wakeups cycles more costly). + // + // Instead, sleep for min(timeout, 1s). If the wait times out then purge at + // that point, and go to sleep for the remaining of the time. This ensures + // that we do no work for short sleeps, and that threads do not get awaken + // many times. +#if BUILDFLAG(USE_PARTITION_ALLOC_AS_MALLOC) && \ + defined(PA_THREAD_CACHE_SUPPORTED) + bool was_signaled = wake_up_event->TimedWait( + std::min(sleep_time, kPurgeThreadCacheIdleDelay)); + + // Timed out. + if (!was_signaled) { + ThreadCache::PurgeCurrentThread(); + + if (sleep_time > kPurgeThreadCacheIdleDelay) { + wake_up_event->TimedWait(sleep_time.is_max() + ? base::TimeDelta::Max() + : sleep_time - kPurgeThreadCacheIdleDelay); + } } +#else + wake_up_event->TimedWait(sleep_time); +#endif // BUILDFLAG(USE_PARTITION_ALLOC_AS_MALLOC) && + // defined(PA_THREAD_CACHE_SUPPORTED) } WorkerThread::WorkerThread(ThreadPriority priority_hint, @@ -306,10 +344,9 @@ void WorkerThread::RunWorker() { #if defined(OS_APPLE) mac::ScopedNSAutoreleasePool autorelease_pool; #endif - base::Optional<HangWatchScopeEnabled> hang_watch_scope; + absl::optional<WatchHangsInScope> hang_watch_scope; if (watch_for_hangs) - hang_watch_scope.emplace( - base::HangWatchScopeEnabled::kDefaultHangWatchTime); + hang_watch_scope.emplace(base::WatchHangsInScope::kDefaultHangWatchTime); UpdateThreadPriority(GetDesiredThreadPriority()); diff --git a/chromium/base/task/thread_pool/worker_thread.h b/chromium/base/task/thread_pool/worker_thread.h index 09ba022f770..1a294878f95 100644 --- a/chromium/base/task/thread_pool/worker_thread.h +++ b/chromium/base/task/thread_pool/worker_thread.h @@ -91,6 +91,9 @@ class BASE_EXPORT WorkerThread : public RefCountedThreadSafe<WorkerThread>, // guaranteed that WorkerThread won't access the Delegate or the // TaskTracker after calling OnMainExit() on the Delegate. virtual void OnMainExit(WorkerThread* worker) {} + + static constexpr TimeDelta kPurgeThreadCacheIdleDelay = + TimeDelta::FromSeconds(1); }; // Creates a WorkerThread that runs Tasks from TaskSources returned by diff --git a/chromium/base/task/thread_pool/worker_thread_unittest.cc b/chromium/base/task/thread_pool/worker_thread_unittest.cc index b2181c698ec..67ea74f71e5 100644 --- a/chromium/base/task/thread_pool/worker_thread_unittest.cc +++ b/chromium/base/task/thread_pool/worker_thread_unittest.cc @@ -6,12 +6,16 @@ #include <stddef.h> +#include <atomic> #include <memory> #include <utility> #include <vector> +#include "base/allocator/buildflags.h" +#include "base/allocator/partition_allocator/partition_alloc_config.h" #include "base/bind.h" #include "base/callback_helpers.h" +#include "base/compiler_specific.h" #include "base/memory/ptr_util.h" #include "base/memory/ref_counted.h" #include "base/synchronization/condition_variable.h" @@ -31,6 +35,12 @@ #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" +#if BUILDFLAG(USE_PARTITION_ALLOC_AS_MALLOC) && \ + defined(PA_THREAD_CACHE_SUPPORTED) +#include "base/allocator/partition_allocator/thread_cache.h" +#endif // BUILDFLAG(USE_PARTITION_ALLOC_AS_MALLOC) && + // defined(PA_THREAD_CACHE_SUPPORTED) + using testing::_; using testing::Mock; using testing::Ne; @@ -181,7 +191,7 @@ class ThreadPoolWorkerTest : public testing::TestWithParam<int> { Task task(FROM_HERE, BindOnce(&ThreadPoolWorkerTest::RunTaskCallback, Unretained(outer_)), - TimeDelta()); + TimeTicks::Now(), TimeDelta()); EXPECT_TRUE(outer_->task_tracker_.WillPostTask( &task, sequence->shutdown_behavior())); sequence_transaction.PushTask(std::move(task)); @@ -463,7 +473,7 @@ class ControllableCleanupDelegate : public WorkerThreadDefaultDelegate { }, Unretained(&controls_->work_processed_), Unretained(&controls_->work_running_)), - TimeDelta()); + TimeTicks::Now(), TimeDelta()); EXPECT_TRUE( task_tracker_->WillPostTask(&task, sequence->shutdown_behavior())); sequence->BeginTransaction().PushTask(std::move(task)); @@ -827,5 +837,74 @@ TEST(ThreadPoolWorkerTest, WorkerThreadObserver) { Mock::VerifyAndClear(&observer); } +// ThreadCache tests disabled when ENABLE_RUNTIME_BACKUP_REF_PTR_CONTROL is +// enabled, because the "original" PartitionRoot has ThreadCache disabled. +#if BUILDFLAG(USE_PARTITION_ALLOC_AS_MALLOC) && \ + defined(PA_THREAD_CACHE_SUPPORTED) && \ + !BUILDFLAG(ENABLE_RUNTIME_BACKUP_REF_PTR_CONTROL) +namespace { +NOINLINE void FreeForTest(void* data) { + free(data); +} +} // namespace + +class WorkerThreadThreadCacheDelegate : public WorkerThreadDefaultDelegate { + public: + void WaitForWork(WaitableEvent* wake_up_event) override { + // Fill several buckets before going to sleep. + for (size_t size = 8; size < ThreadCache::kDefaultSizeThreshold; size++) { + void* data = malloc(size); + // A simple malloc() / free() pair can be discarded by the compiler (and + // is), making the test fail. It is sufficient to make |FreeForTest()| a + // NOINLINE function for the call to not be eliminated, but it is + // required. + FreeForTest(data); + } + + size_t cached_memory_before = ThreadCache::Get()->CachedMemory(); + WorkerThreadDefaultDelegate::WaitForWork(wake_up_event); + size_t cached_memory_after = ThreadCache::Get()->CachedMemory(); + + if (!first_wakeup_done_) { + // First time we sleep is a short sleep, no cache purging. + // + // Here and below, cannot assert on exact thread cache size, since + // anything that allocates will make it fluctuate. + EXPECT_GT(cached_memory_after, cached_memory_before / 2); + first_wakeup_done_.store(true, std::memory_order_release); + } else { + // Second one is long, should purge. + EXPECT_LT(cached_memory_after, cached_memory_before / 2); + } + } + + std::atomic<bool> first_wakeup_done_{false}; +}; + +TEST(ThreadPoolWorkerThreadCachePurgeTest, Purge) { + TaskTracker task_tracker; + auto delegate = std::make_unique<WorkerThreadThreadCacheDelegate>(); + auto* delegate_raw = delegate.get(); + auto worker = + MakeRefCounted<WorkerThread>(ThreadPriority::NORMAL, std::move(delegate), + task_tracker.GetTrackedRef()); + // Wake up before the thread is started to make sure the first sleep is short. + worker->WakeUp(); + worker->Start(nullptr); + + while (delegate_raw->first_wakeup_done_.load(std::memory_order_acquire)) { + } + + // Have to use real sleep unfortunately rather than virtual time, because + // WaitableEvent uses the non-overridable variant of TimeTicks. + PlatformThread::Sleep(1.1 * + WorkerThread::Delegate::kPurgeThreadCacheIdleDelay); + worker->JoinForTesting(); +} + +#endif // BUILDFLAG(USE_PARTITION_ALLOC_AS_MALLOC) && + // defined(PA_THREAD_CACHE_SUPPORTED) && + // !BUILDFLAG(ENABLE_RUNTIME_BACKUP_REF_PTR_CONTROL) + } // namespace internal } // namespace base |