Commit e4e020b9 authored by François Doray's avatar François Doray Committed by Commit Bot

ThreadPool: Add base::CreateUpdateableSequencedTaskRunnerWithTraits().

This function creates a SequencedTaskRunner whose priority can be
updated at any time.

To update the priority from BEST_EFFORT to USER_VISIBLE/USER_BLOCKING,
a ThreadPolicy must be specified.

Bug: 889029
Change-Id: I4e6d119eda0a4a880922d49f97f84c30e8725516
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1532826
Commit-Queue: François Doray <fdoray@chromium.org>
Reviewed-by: default avatarGabriel Charette <gab@chromium.org>
Cr-Commit-Position: refs/heads/master@{#664774}
parent 2148146b
...@@ -52,10 +52,8 @@ TaskTraits PostTaskAndroid::CreateTaskTraits( ...@@ -52,10 +52,8 @@ TaskTraits PostTaskAndroid::CreateTaskTraits(
jbyte extension_id, jbyte extension_id,
const base::android::JavaParamRef<jbyteArray>& extension_data) { const base::android::JavaParamRef<jbyteArray>& extension_data) {
return TaskTraits(priority_set_explicitly, return TaskTraits(priority_set_explicitly,
static_cast<TaskPriority>(priority), static_cast<TaskPriority>(priority), may_block,
/* shutdown_behavior_set_explicitly */ false, use_thread_pool,
TaskShutdownBehavior::SKIP_ON_SHUTDOWN, may_block,
/* with_base_sync_primitives */ false, use_thread_pool,
TaskTraitsExtensionStorage( TaskTraitsExtensionStorage(
extension_id, GetExtensionData(env, extension_data))); extension_id, GetExtensionData(env, extension_data)));
} }
......
...@@ -110,6 +110,24 @@ scoped_refptr<SequencedTaskRunner> CreateSequencedTaskRunnerWithTraits( ...@@ -110,6 +110,24 @@ scoped_refptr<SequencedTaskRunner> CreateSequencedTaskRunnerWithTraits(
->CreateSequencedTaskRunnerWithTraits(adjusted_traits); ->CreateSequencedTaskRunnerWithTraits(adjusted_traits);
} }
scoped_refptr<UpdateableSequencedTaskRunner>
CreateUpdateableSequencedTaskRunnerWithTraits(const TaskTraits& traits) {
DCHECK(ThreadPoolInstance::Get())
<< "Ref. Prerequisite section of post_task.h.\n\n"
"Hint: if this is in a unit test, you're likely merely missing a "
"base::test::ScopedTaskEnvironment member in your fixture.\n";
DCHECK(traits.use_thread_pool())
<< "The base::UseThreadPool() trait is mandatory with "
"CreateUpdateableSequencedTaskRunnerWithTraits().";
CHECK_EQ(traits.extension_id(),
TaskTraitsExtensionStorage::kInvalidExtensionId)
<< "Extension traits cannot be used with "
"CreateUpdateableSequencedTaskRunnerWithTraits().";
const TaskTraits adjusted_traits = GetTaskTraitsWithExplicitPriority(traits);
return static_cast<internal::ThreadPoolImpl*>(ThreadPoolInstance::Get())
->CreateUpdateableSequencedTaskRunnerWithTraits(adjusted_traits);
}
scoped_refptr<SingleThreadTaskRunner> CreateSingleThreadTaskRunnerWithTraits( scoped_refptr<SingleThreadTaskRunner> CreateSingleThreadTaskRunnerWithTraits(
const TaskTraits& traits, const TaskTraits& traits,
SingleThreadTaskRunnerThreadMode thread_mode) { SingleThreadTaskRunnerThreadMode thread_mode) {
......
...@@ -21,6 +21,7 @@ ...@@ -21,6 +21,7 @@
#include "base/task/task_traits.h" #include "base/task/task_traits.h"
#include "base/task_runner.h" #include "base/task_runner.h"
#include "base/time/time.h" #include "base/time/time.h"
#include "base/updateable_sequenced_task_runner.h"
#include "build/build_config.h" #include "build/build_config.h"
namespace base { namespace base {
...@@ -178,6 +179,20 @@ BASE_EXPORT scoped_refptr<TaskRunner> CreateTaskRunnerWithTraits( ...@@ -178,6 +179,20 @@ BASE_EXPORT scoped_refptr<TaskRunner> CreateTaskRunnerWithTraits(
BASE_EXPORT scoped_refptr<SequencedTaskRunner> BASE_EXPORT scoped_refptr<SequencedTaskRunner>
CreateSequencedTaskRunnerWithTraits(const TaskTraits& traits); CreateSequencedTaskRunnerWithTraits(const TaskTraits& traits);
// Returns a task runner whose PostTask invocations result in scheduling tasks
// using |traits|. The priority in |traits| can be updated at any time via
// UpdateableSequencedTaskRunner::UpdatePriority(). An update affects all tasks
// posted to the task runner that aren't running yet. Tasks run one at a time in
// posting order.
//
// |traits| requirements:
// - base::ThreadPool() must be specified.
// - Extension traits (e.g. BrowserThread) cannot be specified.
// - base::ThreadPolicy must be specified if the priority of the task runner
// will ever be increased from BEST_EFFORT.
BASE_EXPORT scoped_refptr<UpdateableSequencedTaskRunner>
CreateUpdateableSequencedTaskRunnerWithTraits(const TaskTraits& traits);
// Returns a SingleThreadTaskRunner whose PostTask invocations result in // Returns a SingleThreadTaskRunner whose PostTask invocations result in
// scheduling tasks using |traits| on a thread determined by |thread_mode|. See // scheduling tasks using |traits| on a thread determined by |thread_mode|. See
// base/task/single_thread_task_runner_thread_mode.h for |thread_mode| details. // base/task/single_thread_task_runner_thread_mode.h for |thread_mode| details.
......
This diff is collapsed.
...@@ -12,7 +12,9 @@ TEST(TaskTraitsTest, Default) { ...@@ -12,7 +12,9 @@ TEST(TaskTraitsTest, Default) {
constexpr TaskTraits traits = {}; constexpr TaskTraits traits = {};
EXPECT_FALSE(traits.priority_set_explicitly()); EXPECT_FALSE(traits.priority_set_explicitly());
EXPECT_EQ(TaskPriority::USER_BLOCKING, traits.priority()); EXPECT_EQ(TaskPriority::USER_BLOCKING, traits.priority());
EXPECT_FALSE(traits.shutdown_behavior_set_explicitly());
EXPECT_EQ(TaskShutdownBehavior::SKIP_ON_SHUTDOWN, traits.shutdown_behavior()); EXPECT_EQ(TaskShutdownBehavior::SKIP_ON_SHUTDOWN, traits.shutdown_behavior());
EXPECT_FALSE(traits.thread_policy_set_explicitly());
EXPECT_EQ(ThreadPolicy::PREFER_BACKGROUND, traits.thread_policy()); EXPECT_EQ(ThreadPolicy::PREFER_BACKGROUND, traits.thread_policy());
EXPECT_FALSE(traits.may_block()); EXPECT_FALSE(traits.may_block());
EXPECT_FALSE(traits.with_base_sync_primitives()); EXPECT_FALSE(traits.with_base_sync_primitives());
...@@ -22,7 +24,9 @@ TEST(TaskTraitsTest, TaskPriority) { ...@@ -22,7 +24,9 @@ TEST(TaskTraitsTest, TaskPriority) {
constexpr TaskTraits traits = {TaskPriority::BEST_EFFORT}; constexpr TaskTraits traits = {TaskPriority::BEST_EFFORT};
EXPECT_TRUE(traits.priority_set_explicitly()); EXPECT_TRUE(traits.priority_set_explicitly());
EXPECT_EQ(TaskPriority::BEST_EFFORT, traits.priority()); EXPECT_EQ(TaskPriority::BEST_EFFORT, traits.priority());
EXPECT_FALSE(traits.shutdown_behavior_set_explicitly());
EXPECT_EQ(TaskShutdownBehavior::SKIP_ON_SHUTDOWN, traits.shutdown_behavior()); EXPECT_EQ(TaskShutdownBehavior::SKIP_ON_SHUTDOWN, traits.shutdown_behavior());
EXPECT_FALSE(traits.thread_policy_set_explicitly());
EXPECT_EQ(ThreadPolicy::PREFER_BACKGROUND, traits.thread_policy()); EXPECT_EQ(ThreadPolicy::PREFER_BACKGROUND, traits.thread_policy());
EXPECT_FALSE(traits.may_block()); EXPECT_FALSE(traits.may_block());
EXPECT_FALSE(traits.with_base_sync_primitives()); EXPECT_FALSE(traits.with_base_sync_primitives());
...@@ -32,7 +36,9 @@ TEST(TaskTraitsTest, TaskShutdownBehavior) { ...@@ -32,7 +36,9 @@ TEST(TaskTraitsTest, TaskShutdownBehavior) {
constexpr TaskTraits traits = {TaskShutdownBehavior::BLOCK_SHUTDOWN}; constexpr TaskTraits traits = {TaskShutdownBehavior::BLOCK_SHUTDOWN};
EXPECT_FALSE(traits.priority_set_explicitly()); EXPECT_FALSE(traits.priority_set_explicitly());
EXPECT_EQ(TaskPriority::USER_BLOCKING, traits.priority()); EXPECT_EQ(TaskPriority::USER_BLOCKING, traits.priority());
EXPECT_TRUE(traits.shutdown_behavior_set_explicitly());
EXPECT_EQ(TaskShutdownBehavior::BLOCK_SHUTDOWN, traits.shutdown_behavior()); EXPECT_EQ(TaskShutdownBehavior::BLOCK_SHUTDOWN, traits.shutdown_behavior());
EXPECT_FALSE(traits.thread_policy_set_explicitly());
EXPECT_EQ(ThreadPolicy::PREFER_BACKGROUND, traits.thread_policy()); EXPECT_EQ(ThreadPolicy::PREFER_BACKGROUND, traits.thread_policy());
EXPECT_FALSE(traits.may_block()); EXPECT_FALSE(traits.may_block());
EXPECT_FALSE(traits.with_base_sync_primitives()); EXPECT_FALSE(traits.with_base_sync_primitives());
...@@ -42,7 +48,9 @@ TEST(TaskTraitsTest, ThreadPolicy) { ...@@ -42,7 +48,9 @@ TEST(TaskTraitsTest, ThreadPolicy) {
constexpr TaskTraits traits = {ThreadPolicy::MUST_USE_FOREGROUND}; constexpr TaskTraits traits = {ThreadPolicy::MUST_USE_FOREGROUND};
EXPECT_FALSE(traits.priority_set_explicitly()); EXPECT_FALSE(traits.priority_set_explicitly());
EXPECT_EQ(TaskPriority::USER_BLOCKING, traits.priority()); EXPECT_EQ(TaskPriority::USER_BLOCKING, traits.priority());
EXPECT_FALSE(traits.shutdown_behavior_set_explicitly());
EXPECT_EQ(TaskShutdownBehavior::SKIP_ON_SHUTDOWN, traits.shutdown_behavior()); EXPECT_EQ(TaskShutdownBehavior::SKIP_ON_SHUTDOWN, traits.shutdown_behavior());
EXPECT_TRUE(traits.thread_policy_set_explicitly());
EXPECT_EQ(ThreadPolicy::MUST_USE_FOREGROUND, traits.thread_policy()); EXPECT_EQ(ThreadPolicy::MUST_USE_FOREGROUND, traits.thread_policy());
EXPECT_FALSE(traits.may_block()); EXPECT_FALSE(traits.may_block());
EXPECT_FALSE(traits.with_base_sync_primitives()); EXPECT_FALSE(traits.with_base_sync_primitives());
...@@ -52,7 +60,9 @@ TEST(TaskTraitsTest, MayBlock) { ...@@ -52,7 +60,9 @@ TEST(TaskTraitsTest, MayBlock) {
constexpr TaskTraits traits = {MayBlock()}; constexpr TaskTraits traits = {MayBlock()};
EXPECT_FALSE(traits.priority_set_explicitly()); EXPECT_FALSE(traits.priority_set_explicitly());
EXPECT_EQ(TaskPriority::USER_BLOCKING, traits.priority()); EXPECT_EQ(TaskPriority::USER_BLOCKING, traits.priority());
EXPECT_FALSE(traits.shutdown_behavior_set_explicitly());
EXPECT_EQ(TaskShutdownBehavior::SKIP_ON_SHUTDOWN, traits.shutdown_behavior()); EXPECT_EQ(TaskShutdownBehavior::SKIP_ON_SHUTDOWN, traits.shutdown_behavior());
EXPECT_FALSE(traits.thread_policy_set_explicitly());
EXPECT_EQ(ThreadPolicy::PREFER_BACKGROUND, traits.thread_policy()); EXPECT_EQ(ThreadPolicy::PREFER_BACKGROUND, traits.thread_policy());
EXPECT_TRUE(traits.may_block()); EXPECT_TRUE(traits.may_block());
EXPECT_FALSE(traits.with_base_sync_primitives()); EXPECT_FALSE(traits.with_base_sync_primitives());
...@@ -62,7 +72,9 @@ TEST(TaskTraitsTest, WithBaseSyncPrimitives) { ...@@ -62,7 +72,9 @@ TEST(TaskTraitsTest, WithBaseSyncPrimitives) {
constexpr TaskTraits traits = {WithBaseSyncPrimitives()}; constexpr TaskTraits traits = {WithBaseSyncPrimitives()};
EXPECT_FALSE(traits.priority_set_explicitly()); EXPECT_FALSE(traits.priority_set_explicitly());
EXPECT_EQ(TaskPriority::USER_BLOCKING, traits.priority()); EXPECT_EQ(TaskPriority::USER_BLOCKING, traits.priority());
EXPECT_FALSE(traits.shutdown_behavior_set_explicitly());
EXPECT_EQ(TaskShutdownBehavior::SKIP_ON_SHUTDOWN, traits.shutdown_behavior()); EXPECT_EQ(TaskShutdownBehavior::SKIP_ON_SHUTDOWN, traits.shutdown_behavior());
EXPECT_FALSE(traits.thread_policy_set_explicitly());
EXPECT_EQ(ThreadPolicy::PREFER_BACKGROUND, traits.thread_policy()); EXPECT_EQ(ThreadPolicy::PREFER_BACKGROUND, traits.thread_policy());
EXPECT_FALSE(traits.may_block()); EXPECT_FALSE(traits.may_block());
EXPECT_TRUE(traits.with_base_sync_primitives()); EXPECT_TRUE(traits.with_base_sync_primitives());
...@@ -74,7 +86,9 @@ TEST(TaskTraitsTest, MultipleTraits) { ...@@ -74,7 +86,9 @@ TEST(TaskTraitsTest, MultipleTraits) {
ThreadPolicy::MUST_USE_FOREGROUND, MayBlock(), WithBaseSyncPrimitives()}; ThreadPolicy::MUST_USE_FOREGROUND, MayBlock(), WithBaseSyncPrimitives()};
EXPECT_TRUE(traits.priority_set_explicitly()); EXPECT_TRUE(traits.priority_set_explicitly());
EXPECT_EQ(TaskPriority::BEST_EFFORT, traits.priority()); EXPECT_EQ(TaskPriority::BEST_EFFORT, traits.priority());
EXPECT_TRUE(traits.shutdown_behavior_set_explicitly());
EXPECT_EQ(TaskShutdownBehavior::BLOCK_SHUTDOWN, traits.shutdown_behavior()); EXPECT_EQ(TaskShutdownBehavior::BLOCK_SHUTDOWN, traits.shutdown_behavior());
EXPECT_TRUE(traits.thread_policy_set_explicitly());
EXPECT_EQ(ThreadPolicy::MUST_USE_FOREGROUND, traits.thread_policy()); EXPECT_EQ(ThreadPolicy::MUST_USE_FOREGROUND, traits.thread_policy());
EXPECT_TRUE(traits.may_block()); EXPECT_TRUE(traits.may_block());
EXPECT_TRUE(traits.with_base_sync_primitives()); EXPECT_TRUE(traits.with_base_sync_primitives());
...@@ -85,10 +99,17 @@ TEST(TaskTraitsTest, Copy) { ...@@ -85,10 +99,17 @@ TEST(TaskTraitsTest, Copy) {
TaskPriority::BEST_EFFORT, TaskShutdownBehavior::BLOCK_SHUTDOWN, TaskPriority::BEST_EFFORT, TaskShutdownBehavior::BLOCK_SHUTDOWN,
ThreadPolicy::MUST_USE_FOREGROUND, MayBlock(), WithBaseSyncPrimitives()}; ThreadPolicy::MUST_USE_FOREGROUND, MayBlock(), WithBaseSyncPrimitives()};
constexpr TaskTraits traits_copy(traits); constexpr TaskTraits traits_copy(traits);
EXPECT_EQ(traits, traits_copy);
EXPECT_EQ(traits.priority_set_explicitly(), EXPECT_EQ(traits.priority_set_explicitly(),
traits_copy.priority_set_explicitly()); traits_copy.priority_set_explicitly());
EXPECT_EQ(traits.priority(), traits_copy.priority()); EXPECT_EQ(traits.priority(), traits_copy.priority());
EXPECT_EQ(traits.shutdown_behavior_set_explicitly(),
traits_copy.shutdown_behavior_set_explicitly());
EXPECT_EQ(traits.shutdown_behavior(), traits_copy.shutdown_behavior()); EXPECT_EQ(traits.shutdown_behavior(), traits_copy.shutdown_behavior());
EXPECT_EQ(traits.thread_policy_set_explicitly(),
traits_copy.thread_policy_set_explicitly());
EXPECT_EQ(traits.thread_policy(), traits_copy.thread_policy()); EXPECT_EQ(traits.thread_policy(), traits_copy.thread_policy());
EXPECT_EQ(traits.may_block(), traits_copy.may_block()); EXPECT_EQ(traits.may_block(), traits_copy.may_block());
EXPECT_EQ(traits.with_base_sync_primitives(), EXPECT_EQ(traits.with_base_sync_primitives(),
......
...@@ -256,7 +256,7 @@ ThreadPoolImpl::CreateCOMSTATaskRunnerWithTraits( ...@@ -256,7 +256,7 @@ ThreadPoolImpl::CreateCOMSTATaskRunnerWithTraits(
#endif // defined(OS_WIN) #endif // defined(OS_WIN)
scoped_refptr<UpdateableSequencedTaskRunner> scoped_refptr<UpdateableSequencedTaskRunner>
ThreadPoolImpl::CreateUpdateableSequencedTaskRunnerWithTraitsForTesting( ThreadPoolImpl::CreateUpdateableSequencedTaskRunnerWithTraits(
const TaskTraits& traits) { const TaskTraits& traits) {
const TaskTraits new_traits = SetUserBlockingPriorityIfNeeded(traits); const TaskTraits new_traits = SetUserBlockingPriorityIfNeeded(traits);
return MakeRefCounted<PooledSequencedTaskRunner>(new_traits, this); return MakeRefCounted<PooledSequencedTaskRunner>(new_traits, this);
...@@ -383,6 +383,16 @@ void ThreadPoolImpl::UpdatePriority(scoped_refptr<TaskSource> task_source, ...@@ -383,6 +383,16 @@ void ThreadPoolImpl::UpdatePriority(scoped_refptr<TaskSource> task_source,
TaskPriority priority) { TaskPriority priority) {
auto transaction = task_source->BeginTransaction(); auto transaction = task_source->BeginTransaction();
if (transaction.traits().priority() == priority)
return;
if (transaction.traits().priority() == TaskPriority::BEST_EFFORT) {
DCHECK(transaction.traits().thread_policy_set_explicitly())
<< "A ThreadPolicy must be specified in the TaskTraits of an "
"UpdateableSequencedTaskRunner whose priority is increased from "
"BEST_EFFORT. See ThreadPolicy documentation.";
}
ThreadGroup* const current_thread_group = ThreadGroup* const current_thread_group =
GetThreadGroupForTraits(transaction.traits()); GetThreadGroupForTraits(transaction.traits());
transaction.UpdatePriority(priority); transaction.UpdatePriority(priority);
......
...@@ -99,8 +99,7 @@ class BASE_EXPORT ThreadPoolImpl : public ThreadPoolInstance, ...@@ -99,8 +99,7 @@ class BASE_EXPORT ThreadPoolImpl : public ThreadPoolInstance,
SingleThreadTaskRunnerThreadMode thread_mode) override; SingleThreadTaskRunnerThreadMode thread_mode) override;
#endif // defined(OS_WIN) #endif // defined(OS_WIN)
scoped_refptr<UpdateableSequencedTaskRunner> scoped_refptr<UpdateableSequencedTaskRunner>
CreateUpdateableSequencedTaskRunnerWithTraitsForTesting( CreateUpdateableSequencedTaskRunnerWithTraits(const TaskTraits& traits);
const TaskTraits& traits);
private: private:
// Invoked after |has_fence_| or |has_best_effort_fence_| is updated. Sets the // Invoked after |has_fence_| or |has_best_effort_fence_| is updated. Sets the
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment