summaryrefslogtreecommitdiffstats
path: root/chromium/base/task/thread_pool
diff options
context:
space:
mode:
authorAllan Sandfeld Jensen <allan.jensen@qt.io>2021-09-03 13:32:17 +0200
committerAllan Sandfeld Jensen <allan.jensen@qt.io>2021-10-01 14:31:55 +0200
commit21ba0c5d4bf8fba15dddd97cd693bad2358b77fd (patch)
tree91be119f694044dfc1ff9fdc054459e925de9df0 /chromium/base/task/thread_pool
parent03c549e0392f92c02536d3f86d5e1d8dfa3435ac (diff)
BASELINE: Update Chromium to 92.0.4515.166
Diffstat (limited to 'chromium/base/task/thread_pool')
-rw-r--r--chromium/base/task/thread_pool/DIR_METADATA1
-rw-r--r--chromium/base/task/thread_pool/delayed_task_manager.cc5
-rw-r--r--chromium/base/task/thread_pool/delayed_task_manager.h7
-rw-r--r--chromium/base/task/thread_pool/delayed_task_manager_unittest.cc9
-rw-r--r--chromium/base/task/thread_pool/job_task_source.cc4
-rw-r--r--chromium/base/task/thread_pool/job_task_source.h1
-rw-r--r--chromium/base/task/thread_pool/pooled_parallel_task_runner.cc3
-rw-r--r--chromium/base/task/thread_pool/pooled_sequenced_task_runner.cc2
-rw-r--r--chromium/base/task/thread_pool/pooled_single_thread_task_runner_manager.cc5
-rw-r--r--chromium/base/task/thread_pool/priority_queue_unittest.cc2
-rw-r--r--chromium/base/task/thread_pool/sequence.cc12
-rw-r--r--chromium/base/task/thread_pool/sequence.h1
-rw-r--r--chromium/base/task/thread_pool/sequence_unittest.cc16
-rw-r--r--chromium/base/task/thread_pool/task.cc9
-rw-r--r--chromium/base/task/thread_pool/task.h5
-rw-r--r--chromium/base/task/thread_pool/task_source.cc2
-rw-r--r--chromium/base/task/thread_pool/task_source.h1
-rw-r--r--chromium/base/task/thread_pool/task_tracker.cc12
-rw-r--r--chromium/base/task/thread_pool/task_tracker_posix_unittest.cc6
-rw-r--r--chromium/base/task/thread_pool/task_tracker_unittest.cc72
-rw-r--r--chromium/base/task/thread_pool/thread_group.h4
-rw-r--r--chromium/base/task/thread_pool/thread_group_impl.cc11
-rw-r--r--chromium/base/task/thread_pool/thread_group_impl.h7
-rw-r--r--chromium/base/task/thread_pool/thread_group_impl_unittest.cc20
-rw-r--r--chromium/base/task/thread_pool/thread_group_native_win.cc1
-rw-r--r--chromium/base/task/thread_pool/thread_pool_impl.cc53
-rw-r--r--chromium/base/task/thread_pool/thread_pool_impl.h17
-rw-r--r--chromium/base/task/thread_pool/thread_pool_impl_unittest.cc51
-rw-r--r--chromium/base/task/thread_pool/thread_pool_perftest.cc4
-rw-r--r--chromium/base/task/thread_pool/tracked_ref.h6
-rw-r--r--chromium/base/task/thread_pool/worker_thread.cc55
-rw-r--r--chromium/base/task/thread_pool/worker_thread.h3
-rw-r--r--chromium/base/task/thread_pool/worker_thread_unittest.cc83
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