Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(943)

Unified Diff: base/task_scheduler/task_traits.h

Issue 2829083002: Add constexpr TaskTraits constructor. (Closed)
Patch Set: rebase Created 3 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « base/BUILD.gn ('k') | base/task_scheduler/task_traits.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: base/task_scheduler/task_traits.h
diff --git a/base/task_scheduler/task_traits.h b/base/task_scheduler/task_traits.h
index 47e9b81eeecd46877ffb4f71a42d173b04aa35b8..84499d550468837e95f923d782116e854641ca64 100644
--- a/base/task_scheduler/task_traits.h
+++ b/base/task_scheduler/task_traits.h
@@ -8,6 +8,7 @@
#include <stdint.h>
#include <iosfwd>
+#include <utility>
#include "base/base_export.h"
#include "build/build_config.h"
@@ -77,72 +78,159 @@ enum class TaskShutdownBehavior {
BLOCK_SHUTDOWN,
};
+// Tasks with this trait may block. This includes but is not limited to tasks
+// that wait on synchronous file I/O operations: read or write a file from disk,
+// interact with a pipe or a socket, rename or delete a file, enumerate files in
+// a directory, etc. This trait isn't required for the mere use of locks. For
+// tasks that block on base/ synchronization primitives, see
+// WithBaseSyncPrimitives().
+struct MayBlock {};
+
+// Tasks with this trait will pass base::AssertWaitAllowed(), i.e. will be
+// allowed on the following methods :
+// - base::WaitableEvent::Wait
+// - base::ConditionVariable::Wait
+// - base::PlatformThread::Join
+// - base::PlatformThread::Sleep
+// - base::Process::WaitForExit
+// - base::Process::WaitForExitWithTimeout
+//
+// Tasks should generally not use these methods.
+//
+// Instead of waiting on a WaitableEvent or a ConditionVariable, put the work
+// that should happen after the wait in a callback and post that callback from
+// where the WaitableEvent or ConditionVariable would have been signaled. If
+// something needs to be scheduled after many tasks have executed, use
+// base::BarrierClosure.
+//
+// Avoid creating threads. Instead, use
+// base::Create(Sequenced|SingleTreaded)TaskRunnerWithTraits(). If a thread is
+// really needed, make it non-joinable and add cleanup work at the end of the
+// thread's main function (if using base::Thread, override Cleanup()).
+//
+// On Windows, join processes asynchronously using base::win::ObjectWatcher.
+//
+// MayBlock() must be specified in conjunction with this trait if and only if
+// removing usage of methods listed above in the labeled tasks would still
+// result in tasks that may block (per MayBlock()'s definition).
+//
+// In doubt, consult with //base/task_scheduler/OWNERS.
+struct WithBaseSyncPrimitives {};
+
+namespace internal {
+
+// When the following call is made:
+// GetTraitFromArgList(CallFirstTag(), GetterType(), args...);
+// The compiler prefers using the 3rd overload of GetTraitFromArgList(), because
+// the type of the first argument matches exactly. That overload uses
+// Getter::operator()(FirstArgType) to transform |first_arg| into a value that
+// can be used to initialize a member of TaskTraits. If
+// Getter::operator()(FirstArgType) isn't defined, the compiler uses the 1st or
+// the 2nd overload instead (depending on whether |args| is empty). The 1st
+// overload returns a default value. The 2nd overload discards |first_arg| and
+// calls back GetTraitFromArgList() with CallFirstTag() as first argument.
gab 2017/04/25 17:48:14 Can you give a concrete example of the resolution
fdoray 2017/04/26 17:20:33 Improved documentation.
+struct CallSecondTag {};
+struct CallFirstTag : CallSecondTag {};
+
+// Overload 1: Default value.
+template <class GetterType>
+constexpr auto GetTraitFromArgList(CallSecondTag, GetterType getter)
+ -> decltype(getter()) {
+ return getter();
+}
+
+// Overload 2: Discard first arg.
+template <class GetterType, class FirstArgType, class... ArgTypes>
+constexpr auto GetTraitFromArgList(CallSecondTag,
+ GetterType getter,
+ const FirstArgType&,
+ const ArgTypes&... args)
+ -> decltype(GetTraitFromArgList(CallFirstTag(), getter, args...)) {
+ return GetTraitFromArgList(CallFirstTag(), getter, args...);
+}
+
+// Overload 3: Get value of TaskTraits member from first arg.
+template <class GetterType,
+ class FirstArgType,
+ class... ArgTypes,
+ class Instantiation = decltype(
+ std::declval<GetterType>()(std::declval<FirstArgType>()))>
+constexpr typename GetterType::MemberType GetTraitFromArgList(
+ CallFirstTag,
+ GetterType getter,
+ const FirstArgType& first_arg,
+ const ArgTypes&...) {
+ return getter(first_arg);
+}
+
+template <typename ArgType>
+struct BooleanArgGetterType {
+ using MemberType = bool;
+ constexpr MemberType operator()(ArgType) const { return true; }
+ constexpr MemberType operator()() const { return false; }
+};
+
+template <typename ArgType, ArgType DefaultValue>
+struct EnumArgGetterType {
+ using MemberType = ArgType;
+ constexpr MemberType operator()(ArgType arg) const { return arg; }
+ constexpr MemberType operator()() const { return DefaultValue; }
+};
+
+} // namespace internal
+
// Describes metadata for a single task or a group of tasks.
class BASE_EXPORT TaskTraits {
public:
- // Constructs a default TaskTraits for tasks that
+ // Invoking this constructor without arguments produces TaskTraits that are
+ // appropriate for tasks that
// (1) don't block (ref. MayBlock() and WithBaseSyncPrimitives()),
// (2) prefer inheriting the current priority to specifying their own, and
// (3) can either block shutdown or be skipped on shutdown
// (TaskScheduler implementation is free to choose a fitting default).
- // Tasks that require stricter guarantees and/or know the specific
- // TaskPriority appropriate for them should highlight those by requesting
- // explicit traits below.
- TaskTraits();
- TaskTraits(const TaskTraits& other) = default;
- TaskTraits& operator=(const TaskTraits& other) = default;
- ~TaskTraits();
-
- // Tasks with this trait may block. This includes but is not limited to tasks
- // that wait on synchronous file I/O operations: read or write a file from
- // disk, interact with a pipe or a socket, rename or delete a file, enumerate
- // files in a directory, etc. This trait isn't required for the mere use of
- // locks. For tasks that block on base/ synchronization primitives, see
- // WithBaseSyncPrimitives().
- TaskTraits& MayBlock();
-
- // Tasks with this trait will pass base::AssertWaitAllowed(), i.e. will be
- // allowed on the following methods :
- // - base::WaitableEvent::Wait
- // - base::ConditionVariable::Wait
- // - base::PlatformThread::Join
- // - base::PlatformThread::Sleep
- // - base::Process::WaitForExit
- // - base::Process::WaitForExitWithTimeout
- //
- // Tasks should generally not use these methods.
//
- // Instead of waiting on a WaitableEvent or a ConditionVariable, put the work
- // that should happen after the wait in a callback and post that callback from
- // where the WaitableEvent or ConditionVariable would have been signaled. If
- // something needs to be scheduled after many tasks have executed, use
- // base::BarrierClosure.
+ // To get TaskTraits for tasks that require stricter guarantees and/or know
+ // the specific TaskPriority appropriate for them, provide arguments of type
+ // TaskPriority, TaskShutdownBehavior, MayBlock and/or WithBaseSyncPrimitives
+ // in any order to the constructor.
//
- // Avoid creating threads. Instead, use
- // base::Create(Sequenced|SingleTreaded)TaskRunnerWithTraits(). If a thread is
- // really needed, make it non-joinable and add cleanup work at the end of the
- // thread's main function (if using base::Thread, override Cleanup()).
- //
- // On Windows, join processes asynchronously using base::win::ObjectWatcher.
- //
- // MayBlock() must be specified in conjunction with this trait if and only if
- // removing usage of methods listed above in the labeled tasks would still
- // result in tasks that may block (per MayBlock()'s definition).
- //
- // In doubt, consult with //base/task_scheduler/OWNERS.
- TaskTraits& WithBaseSyncPrimitives();
+ // E.g.
+ // constexpr TaskTraits default_traits;
+ // constexpr TaskTraits user_visible_traits = {TaskPriority::USER_VISIBLE};
+ // constexpr TaskTraits user_visible_may_block_traits = {
+ // TaskPriority::USER_VISIBLE, MayBlock()};
+ // constexpr TaskTraits other_user_visible_may_block_traits = {
+ // MayBlock(), TaskPriority::USER_VISIBLE};
+ template <class... ArgTypes>
+ constexpr TaskTraits(const ArgTypes&... args)
+ : priority_(internal::GetTraitFromArgList(
+ internal::CallFirstTag(),
+ internal::EnumArgGetterType<base::TaskPriority,
+ base::TaskPriority::INHERITED>(),
+ args...)),
+ shutdown_behavior_(internal::GetTraitFromArgList(
+ internal::CallFirstTag(),
+ internal::EnumArgGetterType<
+ base::TaskShutdownBehavior,
+ base::TaskShutdownBehavior::SKIP_ON_SHUTDOWN>(),
+ args...)),
+ may_block_(internal::GetTraitFromArgList(
+ internal::CallFirstTag(),
+ internal::BooleanArgGetterType<base::MayBlock>(),
+ args...)),
+ with_base_sync_primitives_(internal::GetTraitFromArgList(
+ internal::CallFirstTag(),
+ internal::BooleanArgGetterType<base::WithBaseSyncPrimitives>(),
+ args...)) {}
- // Applies |priority| to tasks with these traits.
- TaskTraits& WithPriority(TaskPriority priority);
+ constexpr TaskTraits(const TaskTraits& other) = default;
+ TaskTraits& operator=(const TaskTraits& other) = default;
- // Applies |shutdown_behavior| to tasks with these traits.
+ // Deprecated.
+ TaskTraits& WithPriority(TaskPriority priority);
TaskTraits& WithShutdownBehavior(TaskShutdownBehavior shutdown_behavior);
-
- // Returns true if tasks with these traits may block.
- bool may_block() const { return may_block_; }
-
- // Returns true if tasks with these traits may use base/ sync primitives.
- bool with_base_sync_primitives() const { return with_base_sync_primitives_; }
+ TaskTraits& MayBlock();
+ TaskTraits& WithBaseSyncPrimitives();
// Returns the priority of tasks with these traits.
TaskPriority priority() const { return priority_; }
@@ -150,11 +238,17 @@ class BASE_EXPORT TaskTraits {
// Returns the shutdown behavior of tasks with these traits.
TaskShutdownBehavior shutdown_behavior() const { return shutdown_behavior_; }
+ // Returns true if tasks with these traits may block.
+ bool may_block() const { return may_block_; }
+
+ // Returns true if tasks with these traits may use base/ sync primitives.
+ bool with_base_sync_primitives() const { return with_base_sync_primitives_; }
+
private:
- bool may_block_;
- bool with_base_sync_primitives_;
TaskPriority priority_;
TaskShutdownBehavior shutdown_behavior_;
+ bool may_block_;
+ bool with_base_sync_primitives_;
};
// Returns string literals for the enums defined in this file. These methods
« no previous file with comments | « base/BUILD.gn ('k') | base/task_scheduler/task_traits.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698