Commit 88396607 authored by Etienne Pierre-doray's avatar Etienne Pierre-doray Committed by Commit Bot

[Task Scheduler]: Make task traits more robust and simple.

Main issue: TaskTraits constructor is not robust; any
signature is part of the overload set, even if it may not compile.
Because of that, it may not possible to hold TaskTrait in a tuple (depending on implementation).
Fix: Expose a single constructor that checks if all traits are valid,
or if an extension can accept all traits.
Caveat: An extension has to redefine base TaskTrait::ValidTraits as valid
(through inheritance).
This CL also simplifies querying traits thanks to C++14 relaxed constant expressions.
This reduces compile time complexity of TaskTraits constructor from O(n^3) to O(n^2).


Cq-Include-Trybots: luci.chromium.try:ios-simulator-cronet;luci.chromium.try:ios-simulator-full-configs
Change-Id: I73f993f6be837f1ac665b4b09c78d9d7272435a8
Reviewed-on: https://chromium-review.googlesource.com/c/1194687Reviewed-by: default avatarEugene But <eugenebut@chromium.org>
Reviewed-by: default avatarAlex Moshchuk <alexmos@chromium.org>
Reviewed-by: default avatarFrançois Doray <fdoray@chromium.org>
Commit-Queue: Etienne Pierre-Doray <etiennep@chromium.org>
Cr-Commit-Position: refs/heads/master@{#596341}
parent be4ea77f
...@@ -123,15 +123,24 @@ struct WithBaseSyncPrimitives {}; ...@@ -123,15 +123,24 @@ struct WithBaseSyncPrimitives {};
// Describes immutable metadata for a single task or a group of tasks. // Describes immutable metadata for a single task or a group of tasks.
class BASE_EXPORT TaskTraits { class BASE_EXPORT TaskTraits {
private: private:
using TaskPriorityFilter =
trait_helpers::EnumTraitFilter<TaskPriority, TaskPriority::USER_VISIBLE>;
using MayBlockFilter = trait_helpers::BooleanTraitFilter<MayBlock>;
using TaskShutdownBehaviorFilter =
trait_helpers::EnumTraitFilter<TaskShutdownBehavior,
TaskShutdownBehavior::SKIP_ON_SHUTDOWN>;
using WithBaseSyncPrimitivesFilter =
trait_helpers::BooleanTraitFilter<WithBaseSyncPrimitives>;
public:
// ValidTrait ensures TaskTraits' constructor only accepts appropriate types. // ValidTrait ensures TaskTraits' constructor only accepts appropriate types.
struct ValidTrait { struct ValidTrait {
ValidTrait(TaskPriority) {} ValidTrait(TaskPriority);
ValidTrait(TaskShutdownBehavior) {} ValidTrait(TaskShutdownBehavior);
ValidTrait(MayBlock) {} ValidTrait(MayBlock);
ValidTrait(WithBaseSyncPrimitives) {} ValidTrait(WithBaseSyncPrimitives);
}; };
public:
// Invoking this constructor without arguments produces TaskTraits that are // Invoking this constructor without arguments produces TaskTraits that are
// appropriate for tasks that // appropriate for tasks that
// (1) don't block (ref. MayBlock() and WithBaseSyncPrimitives()), // (1) don't block (ref. MayBlock() and WithBaseSyncPrimitives()),
...@@ -153,49 +162,26 @@ class BASE_EXPORT TaskTraits { ...@@ -153,49 +162,26 @@ class BASE_EXPORT TaskTraits {
// constexpr base::TaskTraits other_user_visible_may_block_traits = { // constexpr base::TaskTraits other_user_visible_may_block_traits = {
// base::MayBlock(), base::TaskPriority::USER_VISIBLE}; // base::MayBlock(), base::TaskPriority::USER_VISIBLE};
template <class... ArgTypes, template <class... ArgTypes,
class CheckArgumentsAreValidBaseTraits = std::enable_if_t< class CheckArgumentsAreValid = std::enable_if_t<
trait_helpers::AreValidTraits<ValidTrait, ArgTypes...>::value>> trait_helpers::AreValidTraits<ValidTrait, ArgTypes...>::value ||
trait_helpers::AreValidTraitsForExtension<ArgTypes...>::value>>
constexpr TaskTraits(ArgTypes... args) constexpr TaskTraits(ArgTypes... args)
: priority_(trait_helpers::GetValueFromArgList( : extension_(trait_helpers::GetTaskTraitsExtension(
trait_helpers::EnumArgGetter<TaskPriority, trait_helpers::AreValidTraits<ValidTrait, ArgTypes...>{},
TaskPriority::USER_VISIBLE>(),
args...)),
shutdown_behavior_(trait_helpers::GetValueFromArgList(
trait_helpers::EnumArgGetter<
TaskShutdownBehavior,
TaskShutdownBehavior::SKIP_ON_SHUTDOWN>(),
args...)), args...)),
priority_(
trait_helpers::GetTraitFromArgList<TaskPriorityFilter>(args...)),
shutdown_behavior_(
trait_helpers::GetTraitFromArgList<TaskShutdownBehaviorFilter>(
args...)),
priority_set_explicitly_( priority_set_explicitly_(
trait_helpers::HasArgOfType<TaskPriority, ArgTypes...>::value), trait_helpers::TraitIsDefined<TaskPriorityFilter>(args...)),
shutdown_behavior_set_explicitly_( shutdown_behavior_set_explicitly_(
trait_helpers::HasArgOfType<TaskShutdownBehavior, trait_helpers::TraitIsDefined<TaskShutdownBehaviorFilter>(args...)),
ArgTypes...>::value), may_block_(trait_helpers::GetTraitFromArgList<MayBlockFilter>(args...)),
may_block_(trait_helpers::GetValueFromArgList( with_base_sync_primitives_(
trait_helpers::BooleanArgGetter<MayBlock>(), trait_helpers::GetTraitFromArgList<WithBaseSyncPrimitivesFilter>(
args...)), args...)) {}
with_base_sync_primitives_(trait_helpers::GetValueFromArgList(
trait_helpers::BooleanArgGetter<WithBaseSyncPrimitives>(),
args...)) {}
// Construct TaskTraits with extension traits. See task_traits_extension.h.
template <class... ArgTypes,
class AvoidConstructorRedeclaration = void,
class CheckArgsContainNonBaseTrait = std::enable_if_t<
!trait_helpers::AreValidTraits<ValidTrait, ArgTypes...>::value>>
constexpr TaskTraits(ArgTypes... args)
// Select those arguments that are valid base TaskTraits and forward them
// to the above constructor via a helper constructor.
: TaskTraits(std::forward_as_tuple(args...),
trait_helpers::SelectIndices<
trait_helpers::ValidTraitTester<ValidTrait>::IsValid,
ArgTypes...>{}) {
// Select all other arguments and try to create an extension with them.
extension_ = MakeTaskTraitsExtensionHelper(
std::forward_as_tuple(args...),
trait_helpers::SelectIndices<
trait_helpers::ValidTraitTester<ValidTrait>::IsInvalid,
ArgTypes...>{});
}
constexpr TaskTraits(const TaskTraits& other) = default; constexpr TaskTraits(const TaskTraits& other) = default;
TaskTraits& operator=(const TaskTraits& other) = default; TaskTraits& operator=(const TaskTraits& other) = default;
...@@ -279,16 +265,6 @@ class BASE_EXPORT TaskTraits { ...@@ -279,16 +265,6 @@ class BASE_EXPORT TaskTraits {
with_base_sync_primitives_(left.with_base_sync_primitives_ || with_base_sync_primitives_(left.with_base_sync_primitives_ ||
right.with_base_sync_primitives_) {} right.with_base_sync_primitives_) {}
// Helper constructor which selects those arguments from |args| that are
// indicated by the index_sequence and forwards them to the public
// constructor. Due to filtering, the indices may be non-contiguous.
template <class... ArgTypes, std::size_t... Indices>
constexpr TaskTraits(std::tuple<ArgTypes...> args,
std::index_sequence<Indices...>)
: TaskTraits(
std::get<Indices>(std::forward<std::tuple<ArgTypes...>>(args))...) {
}
// Ordered for packing. // Ordered for packing.
TaskTraitsExtensionStorage extension_; TaskTraitsExtensionStorage extension_;
TaskPriority priority_; TaskPriority priority_;
......
This diff is collapsed.
...@@ -12,6 +12,7 @@ ...@@ -12,6 +12,7 @@
#include <utility> #include <utility>
#include "base/base_export.h" #include "base/base_export.h"
#include "base/task/task_traits_details.h"
namespace base { namespace base {
...@@ -41,10 +42,14 @@ namespace base { ...@@ -41,10 +42,14 @@ namespace base {
// as its extension traits: // as its extension traits:
// (3) -- template <...> // (3) -- template <...>
// -- constexpr base::TaskTraitsExtensionStorage MakeTaskTraitsExtension( // -- constexpr base::TaskTraitsExtensionStorage MakeTaskTraitsExtension(
// -- ArgTypes&&... args). // -- ArgTypes... args).
// Constructs and serializes an extension with the given arguments into // Constructs and serializes an extension with the given arguments into
// a TaskTraitsExtensionStorage and returns it. Should only accept valid // a TaskTraitsExtensionStorage and returns it. When the extension is used,
// arguments for the extension. // all traits, including the base ones, are passed to this function in
// order make sure TaskTraits constructor only participates in overload
// resolution if all traits are valid. As such, this function should only
// accept valid task traits recognised by the extension and the base task
// traits.
// //
// EXAMPLE (see also base/task/test_task_traits_extension.h): // EXAMPLE (see also base/task/test_task_traits_extension.h):
// -------- // --------
...@@ -57,20 +62,24 @@ namespace base { ...@@ -57,20 +62,24 @@ namespace base {
// static constexpr uint8_t kExtensionId = // static constexpr uint8_t kExtensionId =
// TaskTraitsExtensionStorage::kFirstEmbedderExtensionId; // TaskTraitsExtensionStorage::kFirstEmbedderExtensionId;
// //
// struct ValidTrait { // struct ValidTrait : public TaskTraits::ValidTrait {
// ValidTrait(MyExtensionTrait) {} // // Accept base traits in MakeTaskTraitsExtension (see above).
// using TaskTraits::ValidTrait::ValidTrait;
//
// ValidTrait(MyExtensionTrait);
// }; // };
// //
// using MyExtensionTraitFilter =
// trait_helpers::EnumTraitFilter<MyExtensionTrait, MyExtensionTrait::kA>;
//
// // Constructor that accepts only valid traits as specified by ValidTraits. // // Constructor that accepts only valid traits as specified by ValidTraits.
// template <class... ArgTypes, // template <class... ArgTypes,
// class CheckArgumentsAreValid = std::enable_if_t< // class CheckArgumentsAreValid = std::enable_if_t<
// base::trait_helpers::AreValidTraits< // base::trait_helpers::AreValidTraits<
// ValidTrait, ArgTypes...>::value>> // ValidTrait, ArgTypes...>::value>>
// constexpr MyTaskTraitsExtension(ArgTypes... args) // constexpr MyTaskTraitsExtension(ArgTypes... args)
// : my_trait_(base::trait_helpers::GetValueFromArgList( // : my_trait_(trait_helpers::GetTraitFromArgList<MyExtensionTraitFilter>(
// base::trait_helpers::EnumArgGetter<MyExtensionTrait, // args...)) {}
// MyExtensionTrait::kValue1>(),
// args...)) {}
// //
// // Serializes MyTaskTraitsExtension into a storage object and returns it. // // Serializes MyTaskTraitsExtension into a storage object and returns it.
// constexpr base::TaskTraitsExtensionStorage Serialize() const { // constexpr base::TaskTraitsExtensionStorage Serialize() const {
...@@ -100,8 +109,8 @@ namespace base { ...@@ -100,8 +109,8 @@ namespace base {
// base::trait_helpers::AreValidTraits< // base::trait_helpers::AreValidTraits<
// MyTaskTraitsExtension::ValidTrait, ArgTypes...>::value>> // MyTaskTraitsExtension::ValidTrait, ArgTypes...>::value>>
// constexpr base::TaskTraitsExtensionStorage MakeTaskTraitsExtension( // constexpr base::TaskTraitsExtensionStorage MakeTaskTraitsExtension(
// ArgTypes&&... args) { // ArgTypes... args) {
// return MyTaskTraitsExtension(std::forward<ArgTypes>(args)...).Serialize(); // return MyTaskTraitsExtension(args...).Serialize();
// } // }
// } // namespace my_embedder // } // namespace my_embedder
// //
...@@ -171,6 +180,44 @@ inline constexpr TaskTraitsExtensionStorage::TaskTraitsExtensionStorage( ...@@ -171,6 +180,44 @@ inline constexpr TaskTraitsExtensionStorage::TaskTraitsExtensionStorage(
inline constexpr TaskTraitsExtensionStorage::TaskTraitsExtensionStorage( inline constexpr TaskTraitsExtensionStorage::TaskTraitsExtensionStorage(
const TaskTraitsExtensionStorage& other) = default; const TaskTraitsExtensionStorage& other) = default;
namespace trait_helpers {
// Helper class whose constructor tests if an extension accepts a list of
// argument types.
struct TaskTraitsExtension {
template <class... ArgTypes,
class CheckCanMakeExtension =
decltype(MakeTaskTraitsExtension(std::declval<ArgTypes>()...))>
constexpr TaskTraitsExtension(ArgTypes... args) {}
};
// Tests that that a trait extension accepts all |ArgsTypes...|.
template <class... ArgTypes>
struct AreValidTraitsForExtension
: std::integral_constant<
bool,
std::is_constructible<TaskTraitsExtension, ArgTypes...>::value> {};
// Helper function that returns the TaskTraitsExtensionStorage of a
// serialized extension created with |args...| if there are arguments that are
// not valid base traits, or a default constructed TaskTraitsExtensionStorage
// otherwise.
template <class... ArgTypes>
constexpr TaskTraitsExtensionStorage GetTaskTraitsExtension(
std::true_type base_traits,
ArgTypes... args) {
return TaskTraitsExtensionStorage();
}
template <class... ArgTypes>
constexpr TaskTraitsExtensionStorage GetTaskTraitsExtension(
std::false_type base_traits,
ArgTypes... args) {
return MakeTaskTraitsExtension(args...);
}
} // namespace trait_helpers
// TODO(eseckler): Default the comparison operator once C++20 arrives. // TODO(eseckler): Default the comparison operator once C++20 arrives.
inline bool TaskTraitsExtensionStorage::operator==( inline bool TaskTraitsExtensionStorage::operator==(
const TaskTraitsExtensionStorage& other) const { const TaskTraitsExtensionStorage& other) const {
...@@ -180,25 +227,6 @@ inline bool TaskTraitsExtensionStorage::operator==( ...@@ -180,25 +227,6 @@ inline bool TaskTraitsExtensionStorage::operator==(
return extension_id == other.extension_id && data == other.data; return extension_id == other.extension_id && data == other.data;
} }
// Default implementation of MakeTaskTraitsExtension template function, which
// doesn't accept any traits and does not create an extension.
template <class Unused = void>
constexpr TaskTraitsExtensionStorage MakeTaskTraitsExtension(
TaskTraitsExtensionStorage& storage) {
return TaskTraitsExtensionStorage();
}
// Forwards those arguments from |args| that are indicated by the index_sequence
// to a MakeTaskTraitsExtension() template function, which is provided by the
// embedder in an unknown namespace; its resolution relies on argument-dependent
// lookup. Due to filtering, the provided indices may be non-contiguous.
template <class... ArgTypes, std::size_t... Indices>
constexpr TaskTraitsExtensionStorage MakeTaskTraitsExtensionHelper(
std::tuple<ArgTypes...> args,
std::index_sequence<Indices...>) {
return MakeTaskTraitsExtension(
std::get<Indices>(std::forward<std::tuple<ArgTypes...>>(args))...);
}
} // namespace base } // namespace base
......
...@@ -9,6 +9,13 @@ ...@@ -9,6 +9,13 @@
namespace base { namespace base {
TEST(TaskTraitsExtensionTest, NoExtension) {
constexpr TaskTraits traits = {};
EXPECT_EQ(traits.extension_id(),
TaskTraitsExtensionStorage::kInvalidExtensionId);
}
TEST(TaskTraitsExtensionTest, CreateWithOneExtensionTrait) { TEST(TaskTraitsExtensionTest, CreateWithOneExtensionTrait) {
constexpr TaskTraits traits = {TestExtensionEnumTrait::kB}; constexpr TaskTraits traits = {TestExtensionEnumTrait::kB};
......
...@@ -15,7 +15,7 @@ namespace base { ...@@ -15,7 +15,7 @@ namespace base {
constexpr TaskTraits traits = {MayBlock(), MayBlock()}; constexpr TaskTraits traits = {MayBlock(), MayBlock()};
#elif defined(NCTEST_TASK_TRAITS_EXTENSION_MULTIPLE_EXTENSION_TRAITS) // [r"Multiple arguments of the same type were provided to the constructor of TaskTraits."] #elif defined(NCTEST_TASK_TRAITS_EXTENSION_MULTIPLE_EXTENSION_TRAITS) // [r"Multiple arguments of the same type were provided to the constructor of TaskTraits."]
constexpr TaskTraits traits = {TestExtensionEnumTrait::kB, TestExtensionEnumTrait::kC}; constexpr TaskTraits traits = {TestExtensionEnumTrait::kB, TestExtensionEnumTrait::kC};
#elif defined(NCTEST_TASK_TRAITS_EXTENSION_INVALID_TYPE) // [r"no matching function for call to 'MakeTaskTraitsExtension'"] #elif defined(NCTEST_TASK_TRAITS_EXTENSION_INVALID_TYPE) // [r"no matching constructor for initialization of 'const base::TaskTraits'"]
constexpr TaskTraits traits = {TestExtensionEnumTrait::kB, 123}; constexpr TaskTraits traits = {TestExtensionEnumTrait::kB, 123};
#elif defined(NCTEST_TASK_TRAITS_EXTENSION_TOO_MUCH_DATA_FOR_STORAGE) // [r"no matching constructor for initialization of 'base::TaskTraitsExtensionStorage'"] #elif defined(NCTEST_TASK_TRAITS_EXTENSION_TOO_MUCH_DATA_FOR_STORAGE) // [r"no matching constructor for initialization of 'base::TaskTraitsExtensionStorage'"]
constexpr TaskTraitsExtensionStorage TestSerializeTaskTraitsWithTooMuchData() { constexpr TaskTraitsExtensionStorage TestSerializeTaskTraitsWithTooMuchData() {
......
...@@ -24,7 +24,7 @@ constexpr TaskTraits traits = {TaskShutdownBehavior::BLOCK_SHUTDOWN, ...@@ -24,7 +24,7 @@ constexpr TaskTraits traits = {TaskShutdownBehavior::BLOCK_SHUTDOWN,
constexpr TaskTraits traits = {TaskShutdownBehavior::BLOCK_SHUTDOWN, constexpr TaskTraits traits = {TaskShutdownBehavior::BLOCK_SHUTDOWN,
MayBlock(), MayBlock(),
TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN}; TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN};
#elif defined(NCTEST_TASK_TRAITS_INVALID_TYPE) // [r"no matching function for call to 'MakeTaskTraitsExtension'"] #elif defined(NCTEST_TASK_TRAITS_INVALID_TYPE) // [r"no matching constructor for initialization of 'const base::TaskTraits'"]
constexpr TaskTraits traits = {TaskShutdownBehavior::BLOCK_SHUTDOWN, true}; constexpr TaskTraits traits = {TaskShutdownBehavior::BLOCK_SHUTDOWN, true};
#endif #endif
......
...@@ -20,21 +20,26 @@ class TestTaskTraitsExtension { ...@@ -20,21 +20,26 @@ class TestTaskTraitsExtension {
static constexpr uint8_t kExtensionId = static constexpr uint8_t kExtensionId =
TaskTraitsExtensionStorage::kFirstEmbedderExtensionId; TaskTraitsExtensionStorage::kFirstEmbedderExtensionId;
struct ValidTrait { struct ValidTrait : public TaskTraits::ValidTrait {
ValidTrait(TestExtensionEnumTrait) {} using TaskTraits::ValidTrait::ValidTrait;
ValidTrait(TestExtensionBoolTrait) {}
ValidTrait(TestExtensionEnumTrait);
ValidTrait(TestExtensionBoolTrait);
}; };
using TestExtensionEnumFilter =
trait_helpers::EnumTraitFilter<TestExtensionEnumTrait,
TestExtensionEnumTrait::kA>;
using TestExtensionBoolFilter =
trait_helpers::BooleanTraitFilter<TestExtensionBoolTrait>;
template <class... ArgTypes, template <class... ArgTypes,
class CheckArgumentsAreValid = std::enable_if_t< class CheckArgumentsAreValid = std::enable_if_t<
trait_helpers::AreValidTraits<ValidTrait, ArgTypes...>::value>> trait_helpers::AreValidTraits<ValidTrait, ArgTypes...>::value>>
constexpr TestTaskTraitsExtension(ArgTypes... args) constexpr TestTaskTraitsExtension(ArgTypes... args)
: enum_trait_(trait_helpers::GetValueFromArgList( : enum_trait_(trait_helpers::GetTraitFromArgList<TestExtensionEnumFilter>(
trait_helpers::EnumArgGetter<TestExtensionEnumTrait,
TestExtensionEnumTrait::kA>(),
args...)), args...)),
bool_trait_(trait_helpers::GetValueFromArgList( bool_trait_(trait_helpers::GetTraitFromArgList<TestExtensionBoolFilter>(
trait_helpers::BooleanArgGetter<TestExtensionBoolTrait>(),
args...)) {} args...)) {}
constexpr TaskTraitsExtensionStorage Serialize() const { constexpr TaskTraitsExtensionStorage Serialize() const {
...@@ -65,8 +70,7 @@ template <class... ArgTypes, ...@@ -65,8 +70,7 @@ template <class... ArgTypes,
class = std::enable_if_t< class = std::enable_if_t<
trait_helpers::AreValidTraits<TestTaskTraitsExtension::ValidTrait, trait_helpers::AreValidTraits<TestTaskTraitsExtension::ValidTrait,
ArgTypes...>::value>> ArgTypes...>::value>>
constexpr TaskTraitsExtensionStorage MakeTaskTraitsExtension( constexpr TaskTraitsExtensionStorage MakeTaskTraitsExtension(ArgTypes... args) {
ArgTypes&&... args) {
return TestTaskTraitsExtension(std::forward<ArgTypes>(args)...).Serialize(); return TestTaskTraitsExtension(std::forward<ArgTypes>(args)...).Serialize();
} }
......
...@@ -41,13 +41,20 @@ struct NonNestable {}; ...@@ -41,13 +41,20 @@ struct NonNestable {};
// Posting to a BrowserThread must only be done after it was initialized (ref. // Posting to a BrowserThread must only be done after it was initialized (ref.
// BrowserMainLoop::CreateThreads() phase). // BrowserMainLoop::CreateThreads() phase).
class CONTENT_EXPORT BrowserTaskTraitsExtension { class CONTENT_EXPORT BrowserTaskTraitsExtension {
using BrowserThreadIDFilter =
base::trait_helpers::RequiredEnumTraitFilter<BrowserThread::ID>;
using NonNestableFilter =
base::trait_helpers::BooleanTraitFilter<NonNestable>;
public: public:
static constexpr uint8_t kExtensionId = static constexpr uint8_t kExtensionId =
base::TaskTraitsExtensionStorage::kFirstEmbedderExtensionId; base::TaskTraitsExtensionStorage::kFirstEmbedderExtensionId;
struct ValidTrait { struct ValidTrait : public base::TaskTraits::ValidTrait {
ValidTrait(BrowserThread::ID) {} using base::TaskTraits::ValidTrait::ValidTrait;
ValidTrait(NonNestable) {}
ValidTrait(BrowserThread::ID);
ValidTrait(NonNestable);
}; };
template < template <
...@@ -55,11 +62,10 @@ class CONTENT_EXPORT BrowserTaskTraitsExtension { ...@@ -55,11 +62,10 @@ class CONTENT_EXPORT BrowserTaskTraitsExtension {
class CheckArgumentsAreValid = std::enable_if_t< class CheckArgumentsAreValid = std::enable_if_t<
base::trait_helpers::AreValidTraits<ValidTrait, ArgTypes...>::value>> base::trait_helpers::AreValidTraits<ValidTrait, ArgTypes...>::value>>
constexpr BrowserTaskTraitsExtension(ArgTypes... args) constexpr BrowserTaskTraitsExtension(ArgTypes... args)
: browser_thread_(base::trait_helpers::GetValueFromArgList( : browser_thread_(
base::trait_helpers::RequiredEnumArgGetter<BrowserThread::ID>(), base::trait_helpers::GetTraitFromArgList<BrowserThreadIDFilter>(
args...)), args...)),
nestable_(!base::trait_helpers::GetValueFromArgList( nestable_(!base::trait_helpers::GetTraitFromArgList<NonNestableFilter>(
base::trait_helpers::BooleanArgGetter<NonNestable>(),
args...)) {} args...)) {}
constexpr base::TaskTraitsExtensionStorage Serialize() const { constexpr base::TaskTraitsExtensionStorage Serialize() const {
......
...@@ -10,7 +10,7 @@ ...@@ -10,7 +10,7 @@
namespace content { namespace content {
#if defined(NCTEST_BROWSER_TASK_TRAITS_NO_THREAD) // [r"no member named 'GetDefaultValue' in 'base::trait_helpers::RequiredEnumArgGetter<content::BrowserThread::ID>'"] #if defined(NCTEST_BROWSER_TASK_TRAITS_NO_THREAD) // [r"TaskTraits contains a Trait that must be explicity initialized in its constructor."]
constexpr base::TaskTraits traits = {NonNestable()}; constexpr base::TaskTraits traits = {NonNestable()};
#elif defined(NCTEST_BROWSER_TASK_TRAITS_MULTIPLE_THREADS) // [r"Multiple arguments of the same type were provided to the constructor of TaskTraits."] #elif defined(NCTEST_BROWSER_TASK_TRAITS_MULTIPLE_THREADS) // [r"Multiple arguments of the same type were provided to the constructor of TaskTraits."]
constexpr base::TaskTraits traits = {BrowserThread::UI, constexpr base::TaskTraits traits = {BrowserThread::UI,
......
...@@ -40,13 +40,20 @@ struct NonNestable {}; ...@@ -40,13 +40,20 @@ struct NonNestable {};
// Posting to a WebThread must only be done after it was initialized (ref. // Posting to a WebThread must only be done after it was initialized (ref.
// WebMainLoop::CreateThreads() phase). // WebMainLoop::CreateThreads() phase).
class WebTaskTraitsExtension { class WebTaskTraitsExtension {
using WebThreadIDFilter =
base::trait_helpers::RequiredEnumTraitFilter<WebThread::ID>;
using NonNestableFilter =
base::trait_helpers::BooleanTraitFilter<NonNestable>;
public: public:
static constexpr uint8_t kExtensionId = static constexpr uint8_t kExtensionId =
base::TaskTraitsExtensionStorage::kFirstEmbedderExtensionId; base::TaskTraitsExtensionStorage::kFirstEmbedderExtensionId;
struct ValidTrait { struct ValidTrait : public base::TaskTraits::ValidTrait {
ValidTrait(WebThread::ID) {} using base::TaskTraits::ValidTrait::ValidTrait;
ValidTrait(NonNestable) {}
ValidTrait(WebThread::ID);
ValidTrait(NonNestable);
}; };
template < template <
...@@ -54,11 +61,9 @@ class WebTaskTraitsExtension { ...@@ -54,11 +61,9 @@ class WebTaskTraitsExtension {
class CheckArgumentsAreValid = std::enable_if_t< class CheckArgumentsAreValid = std::enable_if_t<
base::trait_helpers::AreValidTraits<ValidTrait, ArgTypes...>::value>> base::trait_helpers::AreValidTraits<ValidTrait, ArgTypes...>::value>>
constexpr WebTaskTraitsExtension(ArgTypes... args) constexpr WebTaskTraitsExtension(ArgTypes... args)
: web_thread_(base::trait_helpers::GetValueFromArgList( : web_thread_(base::trait_helpers::GetTraitFromArgList<WebThreadIDFilter>(
base::trait_helpers::RequiredEnumArgGetter<WebThread::ID>(),
args...)), args...)),
nestable_(!base::trait_helpers::GetValueFromArgList( nestable_(!base::trait_helpers::GetTraitFromArgList<NonNestableFilter>(
base::trait_helpers::BooleanArgGetter<NonNestable>(),
args...)) {} args...)) {}
constexpr base::TaskTraitsExtensionStorage Serialize() const { constexpr base::TaskTraitsExtensionStorage Serialize() const {
......
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