xref: /aosp_15_r20/external/libchrome/base/task_scheduler/task_traits.h (revision 635a864187cb8b6c713ff48b7e790a6b21769273)
1*635a8641SAndroid Build Coastguard Worker // Copyright 2016 The Chromium Authors. All rights reserved.
2*635a8641SAndroid Build Coastguard Worker // Use of this source code is governed by a BSD-style license that can be
3*635a8641SAndroid Build Coastguard Worker // found in the LICENSE file.
4*635a8641SAndroid Build Coastguard Worker 
5*635a8641SAndroid Build Coastguard Worker #ifndef BASE_TASK_SCHEDULER_TASK_TRAITS_H_
6*635a8641SAndroid Build Coastguard Worker #define BASE_TASK_SCHEDULER_TASK_TRAITS_H_
7*635a8641SAndroid Build Coastguard Worker 
8*635a8641SAndroid Build Coastguard Worker #include <stdint.h>
9*635a8641SAndroid Build Coastguard Worker 
10*635a8641SAndroid Build Coastguard Worker #include <iosfwd>
11*635a8641SAndroid Build Coastguard Worker #include <type_traits>
12*635a8641SAndroid Build Coastguard Worker 
13*635a8641SAndroid Build Coastguard Worker #include "base/base_export.h"
14*635a8641SAndroid Build Coastguard Worker #include "base/task_scheduler/task_traits_details.h"
15*635a8641SAndroid Build Coastguard Worker #include "build/build_config.h"
16*635a8641SAndroid Build Coastguard Worker 
17*635a8641SAndroid Build Coastguard Worker namespace base {
18*635a8641SAndroid Build Coastguard Worker 
19*635a8641SAndroid Build Coastguard Worker // Valid priorities supported by the task scheduler. Note: internal algorithms
20*635a8641SAndroid Build Coastguard Worker // depend on priorities being expressed as a continuous zero-based list from
21*635a8641SAndroid Build Coastguard Worker // lowest to highest priority. Users of this API shouldn't otherwise care about
22*635a8641SAndroid Build Coastguard Worker // nor use the underlying values.
23*635a8641SAndroid Build Coastguard Worker enum class TaskPriority {
24*635a8641SAndroid Build Coastguard Worker   // This will always be equal to the lowest priority available.
25*635a8641SAndroid Build Coastguard Worker   LOWEST = 0,
26*635a8641SAndroid Build Coastguard Worker   // User won't notice if this task takes an arbitrarily long time to complete.
27*635a8641SAndroid Build Coastguard Worker   BACKGROUND = LOWEST,
28*635a8641SAndroid Build Coastguard Worker   // This task affects UI or responsiveness of future user interactions. It is
29*635a8641SAndroid Build Coastguard Worker   // not an immediate response to a user interaction.
30*635a8641SAndroid Build Coastguard Worker   // Examples:
31*635a8641SAndroid Build Coastguard Worker   // - Updating the UI to reflect progress on a long task.
32*635a8641SAndroid Build Coastguard Worker   // - Loading data that might be shown in the UI after a future user
33*635a8641SAndroid Build Coastguard Worker   //   interaction.
34*635a8641SAndroid Build Coastguard Worker   USER_VISIBLE,
35*635a8641SAndroid Build Coastguard Worker   // This task affects UI immediately after a user interaction.
36*635a8641SAndroid Build Coastguard Worker   // Example: Generating data shown in the UI immediately after a click.
37*635a8641SAndroid Build Coastguard Worker   USER_BLOCKING,
38*635a8641SAndroid Build Coastguard Worker   // This will always be equal to the highest priority available.
39*635a8641SAndroid Build Coastguard Worker   HIGHEST = USER_BLOCKING,
40*635a8641SAndroid Build Coastguard Worker };
41*635a8641SAndroid Build Coastguard Worker 
42*635a8641SAndroid Build Coastguard Worker // Valid shutdown behaviors supported by the task scheduler.
43*635a8641SAndroid Build Coastguard Worker enum class TaskShutdownBehavior {
44*635a8641SAndroid Build Coastguard Worker   // Tasks posted with this mode which have not started executing before
45*635a8641SAndroid Build Coastguard Worker   // shutdown is initiated will never run. Tasks with this mode running at
46*635a8641SAndroid Build Coastguard Worker   // shutdown will be ignored (the worker will not be joined).
47*635a8641SAndroid Build Coastguard Worker   //
48*635a8641SAndroid Build Coastguard Worker   // This option provides a nice way to post stuff you don't want blocking
49*635a8641SAndroid Build Coastguard Worker   // shutdown. For example, you might be doing a slow DNS lookup and if it's
50*635a8641SAndroid Build Coastguard Worker   // blocked on the OS, you may not want to stop shutdown, since the result
51*635a8641SAndroid Build Coastguard Worker   // doesn't really matter at that point.
52*635a8641SAndroid Build Coastguard Worker   //
53*635a8641SAndroid Build Coastguard Worker   // However, you need to be very careful what you do in your callback when you
54*635a8641SAndroid Build Coastguard Worker   // use this option. Since the thread will continue to run until the OS
55*635a8641SAndroid Build Coastguard Worker   // terminates the process, the app can be in the process of tearing down when
56*635a8641SAndroid Build Coastguard Worker   // you're running. This means any singletons or global objects you use may
57*635a8641SAndroid Build Coastguard Worker   // suddenly become invalid out from under you. For this reason, it's best to
58*635a8641SAndroid Build Coastguard Worker   // use this only for slow but simple operations like the DNS example.
59*635a8641SAndroid Build Coastguard Worker   CONTINUE_ON_SHUTDOWN,
60*635a8641SAndroid Build Coastguard Worker 
61*635a8641SAndroid Build Coastguard Worker   // Tasks posted with this mode that have not started executing at
62*635a8641SAndroid Build Coastguard Worker   // shutdown will never run. However, any task that has already begun
63*635a8641SAndroid Build Coastguard Worker   // executing when shutdown is invoked will be allowed to continue and
64*635a8641SAndroid Build Coastguard Worker   // will block shutdown until completion.
65*635a8641SAndroid Build Coastguard Worker   //
66*635a8641SAndroid Build Coastguard Worker   // Note: Because TaskScheduler::Shutdown() may block while these tasks are
67*635a8641SAndroid Build Coastguard Worker   // executing, care must be taken to ensure that they do not block on the
68*635a8641SAndroid Build Coastguard Worker   // thread that called TaskScheduler::Shutdown(), as this may lead to deadlock.
69*635a8641SAndroid Build Coastguard Worker   SKIP_ON_SHUTDOWN,
70*635a8641SAndroid Build Coastguard Worker 
71*635a8641SAndroid Build Coastguard Worker   // Tasks posted with this mode before shutdown is complete will block shutdown
72*635a8641SAndroid Build Coastguard Worker   // until they're executed. Generally, this should be used only to save
73*635a8641SAndroid Build Coastguard Worker   // critical user data.
74*635a8641SAndroid Build Coastguard Worker   //
75*635a8641SAndroid Build Coastguard Worker   // Note: Tasks with BACKGROUND priority that block shutdown will be promoted
76*635a8641SAndroid Build Coastguard Worker   // to USER_VISIBLE priority during shutdown.
77*635a8641SAndroid Build Coastguard Worker   BLOCK_SHUTDOWN,
78*635a8641SAndroid Build Coastguard Worker };
79*635a8641SAndroid Build Coastguard Worker 
80*635a8641SAndroid Build Coastguard Worker // Tasks with this trait may block. This includes but is not limited to tasks
81*635a8641SAndroid Build Coastguard Worker // that wait on synchronous file I/O operations: read or write a file from disk,
82*635a8641SAndroid Build Coastguard Worker // interact with a pipe or a socket, rename or delete a file, enumerate files in
83*635a8641SAndroid Build Coastguard Worker // a directory, etc. This trait isn't required for the mere use of locks. For
84*635a8641SAndroid Build Coastguard Worker // tasks that block on base/ synchronization primitives, see the
85*635a8641SAndroid Build Coastguard Worker // WithBaseSyncPrimitives trait.
86*635a8641SAndroid Build Coastguard Worker struct MayBlock {};
87*635a8641SAndroid Build Coastguard Worker 
88*635a8641SAndroid Build Coastguard Worker // DEPRECATED. Use base::ScopedAllowBaseSyncPrimitives(ForTesting) instead.
89*635a8641SAndroid Build Coastguard Worker //
90*635a8641SAndroid Build Coastguard Worker // Tasks with this trait will pass base::AssertBaseSyncPrimitivesAllowed(), i.e.
91*635a8641SAndroid Build Coastguard Worker // will be allowed on the following methods :
92*635a8641SAndroid Build Coastguard Worker // - base::WaitableEvent::Wait
93*635a8641SAndroid Build Coastguard Worker // - base::ConditionVariable::Wait
94*635a8641SAndroid Build Coastguard Worker // - base::PlatformThread::Join
95*635a8641SAndroid Build Coastguard Worker // - base::PlatformThread::Sleep
96*635a8641SAndroid Build Coastguard Worker // - base::Process::WaitForExit
97*635a8641SAndroid Build Coastguard Worker // - base::Process::WaitForExitWithTimeout
98*635a8641SAndroid Build Coastguard Worker //
99*635a8641SAndroid Build Coastguard Worker // Tasks should generally not use these methods.
100*635a8641SAndroid Build Coastguard Worker //
101*635a8641SAndroid Build Coastguard Worker // Instead of waiting on a WaitableEvent or a ConditionVariable, put the work
102*635a8641SAndroid Build Coastguard Worker // that should happen after the wait in a callback and post that callback from
103*635a8641SAndroid Build Coastguard Worker // where the WaitableEvent or ConditionVariable would have been signaled. If
104*635a8641SAndroid Build Coastguard Worker // something needs to be scheduled after many tasks have executed, use
105*635a8641SAndroid Build Coastguard Worker // base::BarrierClosure.
106*635a8641SAndroid Build Coastguard Worker //
107*635a8641SAndroid Build Coastguard Worker // On Windows, join processes asynchronously using base::win::ObjectWatcher.
108*635a8641SAndroid Build Coastguard Worker //
109*635a8641SAndroid Build Coastguard Worker // MayBlock() must be specified in conjunction with this trait if and only if
110*635a8641SAndroid Build Coastguard Worker // removing usage of methods listed above in the labeled tasks would still
111*635a8641SAndroid Build Coastguard Worker // result in tasks that may block (per MayBlock()'s definition).
112*635a8641SAndroid Build Coastguard Worker //
113*635a8641SAndroid Build Coastguard Worker // In doubt, consult with //base/task_scheduler/OWNERS.
114*635a8641SAndroid Build Coastguard Worker struct WithBaseSyncPrimitives {};
115*635a8641SAndroid Build Coastguard Worker 
116*635a8641SAndroid Build Coastguard Worker // Describes immutable metadata for a single task or a group of tasks.
117*635a8641SAndroid Build Coastguard Worker class BASE_EXPORT TaskTraits {
118*635a8641SAndroid Build Coastguard Worker  private:
119*635a8641SAndroid Build Coastguard Worker   // ValidTrait ensures TaskTraits' constructor only accepts appropriate types.
120*635a8641SAndroid Build Coastguard Worker   struct ValidTrait {
ValidTraitValidTrait121*635a8641SAndroid Build Coastguard Worker     ValidTrait(TaskPriority) {}
ValidTraitValidTrait122*635a8641SAndroid Build Coastguard Worker     ValidTrait(TaskShutdownBehavior) {}
ValidTraitValidTrait123*635a8641SAndroid Build Coastguard Worker     ValidTrait(MayBlock) {}
ValidTraitValidTrait124*635a8641SAndroid Build Coastguard Worker     ValidTrait(WithBaseSyncPrimitives) {}
125*635a8641SAndroid Build Coastguard Worker   };
126*635a8641SAndroid Build Coastguard Worker 
127*635a8641SAndroid Build Coastguard Worker  public:
128*635a8641SAndroid Build Coastguard Worker   // Invoking this constructor without arguments produces TaskTraits that are
129*635a8641SAndroid Build Coastguard Worker   // appropriate for tasks that
130*635a8641SAndroid Build Coastguard Worker   //     (1) don't block (ref. MayBlock() and WithBaseSyncPrimitives()),
131*635a8641SAndroid Build Coastguard Worker   //     (2) prefer inheriting the current priority to specifying their own, and
132*635a8641SAndroid Build Coastguard Worker   //     (3) can either block shutdown or be skipped on shutdown
133*635a8641SAndroid Build Coastguard Worker   //         (TaskScheduler implementation is free to choose a fitting default).
134*635a8641SAndroid Build Coastguard Worker   //
135*635a8641SAndroid Build Coastguard Worker   // To get TaskTraits for tasks that require stricter guarantees and/or know
136*635a8641SAndroid Build Coastguard Worker   // the specific TaskPriority appropriate for them, provide arguments of type
137*635a8641SAndroid Build Coastguard Worker   // TaskPriority, TaskShutdownBehavior, MayBlock, and/or WithBaseSyncPrimitives
138*635a8641SAndroid Build Coastguard Worker   // in any order to the constructor.
139*635a8641SAndroid Build Coastguard Worker   //
140*635a8641SAndroid Build Coastguard Worker   // E.g.
141*635a8641SAndroid Build Coastguard Worker   // constexpr base::TaskTraits default_traits = {};
142*635a8641SAndroid Build Coastguard Worker   // constexpr base::TaskTraits user_visible_traits =
143*635a8641SAndroid Build Coastguard Worker   //     {base::TaskPriority::USER_VISIBLE};
144*635a8641SAndroid Build Coastguard Worker   // constexpr base::TaskTraits user_visible_may_block_traits = {
145*635a8641SAndroid Build Coastguard Worker   //     base::TaskPriority::USER_VISIBLE, base::MayBlock()};
146*635a8641SAndroid Build Coastguard Worker   // constexpr base::TaskTraits other_user_visible_may_block_traits = {
147*635a8641SAndroid Build Coastguard Worker   //     base::MayBlock(), base::TaskPriority::USER_VISIBLE};
148*635a8641SAndroid Build Coastguard Worker   template <class... ArgTypes,
149*635a8641SAndroid Build Coastguard Worker             class CheckArgumentsAreValid = internal::InitTypes<
150*635a8641SAndroid Build Coastguard Worker                 decltype(ValidTrait(std::declval<ArgTypes>()))...>>
TaskTraits(ArgTypes...args)151*635a8641SAndroid Build Coastguard Worker   constexpr TaskTraits(ArgTypes... args)
152*635a8641SAndroid Build Coastguard Worker       : priority_set_explicitly_(
153*635a8641SAndroid Build Coastguard Worker             internal::HasArgOfType<TaskPriority, ArgTypes...>::value),
154*635a8641SAndroid Build Coastguard Worker         priority_(internal::GetValueFromArgList(
155*635a8641SAndroid Build Coastguard Worker             internal::EnumArgGetter<TaskPriority, TaskPriority::USER_VISIBLE>(),
156*635a8641SAndroid Build Coastguard Worker             args...)),
157*635a8641SAndroid Build Coastguard Worker         shutdown_behavior_set_explicitly_(
158*635a8641SAndroid Build Coastguard Worker             internal::HasArgOfType<TaskShutdownBehavior, ArgTypes...>::value),
159*635a8641SAndroid Build Coastguard Worker         shutdown_behavior_(internal::GetValueFromArgList(
160*635a8641SAndroid Build Coastguard Worker             internal::EnumArgGetter<TaskShutdownBehavior,
161*635a8641SAndroid Build Coastguard Worker                                     TaskShutdownBehavior::SKIP_ON_SHUTDOWN>(),
162*635a8641SAndroid Build Coastguard Worker             args...)),
163*635a8641SAndroid Build Coastguard Worker         may_block_(internal::GetValueFromArgList(
164*635a8641SAndroid Build Coastguard Worker             internal::BooleanArgGetter<MayBlock>(),
165*635a8641SAndroid Build Coastguard Worker             args...)),
166*635a8641SAndroid Build Coastguard Worker         with_base_sync_primitives_(internal::GetValueFromArgList(
167*635a8641SAndroid Build Coastguard Worker             internal::BooleanArgGetter<WithBaseSyncPrimitives>(),
168*635a8641SAndroid Build Coastguard Worker             args...)) {}
169*635a8641SAndroid Build Coastguard Worker 
170*635a8641SAndroid Build Coastguard Worker   constexpr TaskTraits(const TaskTraits& other) = default;
171*635a8641SAndroid Build Coastguard Worker   TaskTraits& operator=(const TaskTraits& other) = default;
172*635a8641SAndroid Build Coastguard Worker 
173*635a8641SAndroid Build Coastguard Worker   // Returns TaskTraits constructed by combining |left| and |right|. If a trait
174*635a8641SAndroid Build Coastguard Worker   // is specified in both |left| and |right|, the returned TaskTraits will have
175*635a8641SAndroid Build Coastguard Worker   // the value from |right|.
Override(const TaskTraits & left,const TaskTraits & right)176*635a8641SAndroid Build Coastguard Worker   static constexpr TaskTraits Override(const TaskTraits& left,
177*635a8641SAndroid Build Coastguard Worker                                        const TaskTraits& right) {
178*635a8641SAndroid Build Coastguard Worker     return TaskTraits(left, right);
179*635a8641SAndroid Build Coastguard Worker   }
180*635a8641SAndroid Build Coastguard Worker 
181*635a8641SAndroid Build Coastguard Worker   // Returns true if the priority was set explicitly.
priority_set_explicitly()182*635a8641SAndroid Build Coastguard Worker   constexpr bool priority_set_explicitly() const {
183*635a8641SAndroid Build Coastguard Worker     return priority_set_explicitly_;
184*635a8641SAndroid Build Coastguard Worker   }
185*635a8641SAndroid Build Coastguard Worker 
186*635a8641SAndroid Build Coastguard Worker   // Returns the priority of tasks with these traits.
priority()187*635a8641SAndroid Build Coastguard Worker   constexpr TaskPriority priority() const { return priority_; }
188*635a8641SAndroid Build Coastguard Worker 
189*635a8641SAndroid Build Coastguard Worker   // Returns true if the shutdown behavior was set explicitly.
shutdown_behavior_set_explicitly()190*635a8641SAndroid Build Coastguard Worker   constexpr bool shutdown_behavior_set_explicitly() const {
191*635a8641SAndroid Build Coastguard Worker     return shutdown_behavior_set_explicitly_;
192*635a8641SAndroid Build Coastguard Worker   }
193*635a8641SAndroid Build Coastguard Worker 
194*635a8641SAndroid Build Coastguard Worker   // Returns the shutdown behavior of tasks with these traits.
shutdown_behavior()195*635a8641SAndroid Build Coastguard Worker   constexpr TaskShutdownBehavior shutdown_behavior() const {
196*635a8641SAndroid Build Coastguard Worker     return shutdown_behavior_;
197*635a8641SAndroid Build Coastguard Worker   }
198*635a8641SAndroid Build Coastguard Worker 
199*635a8641SAndroid Build Coastguard Worker   // Returns true if tasks with these traits may block.
may_block()200*635a8641SAndroid Build Coastguard Worker   constexpr bool may_block() const { return may_block_; }
201*635a8641SAndroid Build Coastguard Worker 
202*635a8641SAndroid Build Coastguard Worker   // Returns true if tasks with these traits may use base/ sync primitives.
with_base_sync_primitives()203*635a8641SAndroid Build Coastguard Worker   constexpr bool with_base_sync_primitives() const {
204*635a8641SAndroid Build Coastguard Worker     return with_base_sync_primitives_;
205*635a8641SAndroid Build Coastguard Worker   }
206*635a8641SAndroid Build Coastguard Worker 
207*635a8641SAndroid Build Coastguard Worker  private:
TaskTraits(const TaskTraits & left,const TaskTraits & right)208*635a8641SAndroid Build Coastguard Worker   constexpr TaskTraits(const TaskTraits& left, const TaskTraits& right)
209*635a8641SAndroid Build Coastguard Worker       : priority_set_explicitly_(left.priority_set_explicitly_ ||
210*635a8641SAndroid Build Coastguard Worker                                  right.priority_set_explicitly_),
211*635a8641SAndroid Build Coastguard Worker         priority_(right.priority_set_explicitly_ ? right.priority_
212*635a8641SAndroid Build Coastguard Worker                                                  : left.priority_),
213*635a8641SAndroid Build Coastguard Worker         shutdown_behavior_set_explicitly_(
214*635a8641SAndroid Build Coastguard Worker             left.shutdown_behavior_set_explicitly_ ||
215*635a8641SAndroid Build Coastguard Worker             right.shutdown_behavior_set_explicitly_),
216*635a8641SAndroid Build Coastguard Worker         shutdown_behavior_(right.shutdown_behavior_set_explicitly_
217*635a8641SAndroid Build Coastguard Worker                                ? right.shutdown_behavior_
218*635a8641SAndroid Build Coastguard Worker                                : left.shutdown_behavior_),
219*635a8641SAndroid Build Coastguard Worker         may_block_(left.may_block_ || right.may_block_),
220*635a8641SAndroid Build Coastguard Worker         with_base_sync_primitives_(left.with_base_sync_primitives_ ||
221*635a8641SAndroid Build Coastguard Worker                                    right.with_base_sync_primitives_) {}
222*635a8641SAndroid Build Coastguard Worker 
223*635a8641SAndroid Build Coastguard Worker   bool priority_set_explicitly_;
224*635a8641SAndroid Build Coastguard Worker   TaskPriority priority_;
225*635a8641SAndroid Build Coastguard Worker   bool shutdown_behavior_set_explicitly_;
226*635a8641SAndroid Build Coastguard Worker   TaskShutdownBehavior shutdown_behavior_;
227*635a8641SAndroid Build Coastguard Worker   bool may_block_;
228*635a8641SAndroid Build Coastguard Worker   bool with_base_sync_primitives_;
229*635a8641SAndroid Build Coastguard Worker };
230*635a8641SAndroid Build Coastguard Worker 
231*635a8641SAndroid Build Coastguard Worker // Returns string literals for the enums defined in this file. These methods
232*635a8641SAndroid Build Coastguard Worker // should only be used for tracing and debugging.
233*635a8641SAndroid Build Coastguard Worker BASE_EXPORT const char* TaskPriorityToString(TaskPriority task_priority);
234*635a8641SAndroid Build Coastguard Worker BASE_EXPORT const char* TaskShutdownBehaviorToString(
235*635a8641SAndroid Build Coastguard Worker     TaskShutdownBehavior task_priority);
236*635a8641SAndroid Build Coastguard Worker 
237*635a8641SAndroid Build Coastguard Worker // Stream operators so that the enums defined in this file can be used in
238*635a8641SAndroid Build Coastguard Worker // DCHECK and EXPECT statements.
239*635a8641SAndroid Build Coastguard Worker BASE_EXPORT std::ostream& operator<<(std::ostream& os,
240*635a8641SAndroid Build Coastguard Worker                                      const TaskPriority& shutdown_behavior);
241*635a8641SAndroid Build Coastguard Worker BASE_EXPORT std::ostream& operator<<(
242*635a8641SAndroid Build Coastguard Worker     std::ostream& os,
243*635a8641SAndroid Build Coastguard Worker     const TaskShutdownBehavior& shutdown_behavior);
244*635a8641SAndroid Build Coastguard Worker 
245*635a8641SAndroid Build Coastguard Worker }  // namespace base
246*635a8641SAndroid Build Coastguard Worker 
247*635a8641SAndroid Build Coastguard Worker #endif  // BASE_TASK_SCHEDULER_TASK_TRAITS_H_
248