1 // Copyright 2016 The Chromium Authors 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #ifndef BASE_TASK_TASK_TRAITS_H_ 6 #define BASE_TASK_TASK_TRAITS_H_ 7 8 #include <stdint.h> 9 10 #include <iosfwd> 11 #include <tuple> 12 #include <type_traits> 13 #include <utility> 14 15 #include "base/base_export.h" 16 #include "base/check.h" 17 #include "base/check_op.h" 18 #include "base/traits_bag.h" 19 #include "build/build_config.h" 20 21 namespace base { 22 23 // Valid priorities supported by the task scheduling infrastructure. 24 // 25 // Note: internal algorithms depend on priorities being expressed as a 26 // continuous zero-based list from lowest to highest priority. Users of this API 27 // shouldn't otherwise care about nor use the underlying values. 28 // 29 // GENERATED_JAVA_ENUM_PACKAGE: org.chromium.base.task 30 enum class TaskPriority : uint8_t { 31 // This will always be equal to the lowest priority available. 32 LOWEST = 0, 33 // Best effort tasks will only start running when machine resources are 34 // available. The application may preempt best effort tasks if it expects that 35 // resources will soon be needed by work of higher priority. Dependending on 36 // the ThreadPolicy, best effort tasks may run on a thread that is likely to 37 // be descheduled when higher priority work arrives (in this process or 38 // another). 39 // 40 // Examples: 41 // - Reporting metrics. 42 // - Persisting data to disk. 43 // - Loading data that is required for a potential future user interaction 44 // (Note: Use CreateUpdateableSequencedTaskRunner() to increase the priority 45 // when that user interactions happens). 46 BEST_EFFORT = LOWEST, 47 48 // The result of user visible tasks is visible to the user (in the UI or as a 49 // side-effect on the system) but it is not an immediate response to a user 50 // interaction. 51 // 52 // Examples: 53 // - Updating the UI to reflect progress on a long task. 54 // - Downloading a file requested by the user. 55 // - Loading an image that is displayed in the UI but is non-critical. 56 USER_VISIBLE, 57 58 // User blocking tasks affects UI immediately after a user interaction. 59 // 60 // Example: 61 // - Loading and rendering a web page after the user clicks a link. 62 // - Sorting suggestions after the user types a character in the omnibox. 63 // 64 // This is the default TaskPriority in order for tasks to run in order by 65 // default and avoid unintended consequences. The only way to get a task to 66 // run at a higher priority than USER_BLOCKING is to coordinate with a 67 // higher-level scheduler (contact [email protected] for such use 68 // cases). 69 USER_BLOCKING, 70 71 // This will always be equal to the highest priority available. 72 HIGHEST = USER_BLOCKING 73 }; 74 75 // Valid shutdown behaviors supported by the thread pool. 76 enum class TaskShutdownBehavior : uint8_t { 77 // Tasks posted with this mode which have not started executing before 78 // shutdown is initiated will never run. Tasks with this mode running at 79 // shutdown will be ignored (the worker will not be joined). 80 // 81 // This option provides a nice way to post stuff you don't want blocking 82 // shutdown. For example, you might be doing a slow DNS lookup and if it's 83 // blocked on the OS, you may not want to stop shutdown, since the result 84 // doesn't really matter at that point. 85 // 86 // However, you need to be very careful what you do in your callback when you 87 // use this option. Since the thread will continue to run until the OS 88 // terminates the process, the app can be in the process of tearing down when 89 // you're running. This means any singletons or global objects you use may 90 // suddenly become invalid out from under you. For this reason, it's best to 91 // use this only for slow but simple operations like the DNS example. 92 CONTINUE_ON_SHUTDOWN, 93 94 // Tasks posted with this mode that have not started executing at 95 // shutdown will never run. However, any task that has already begun 96 // executing when shutdown is invoked will be allowed to continue and 97 // will block shutdown until completion. 98 // 99 // Note: Because ThreadPoolInstance::Shutdown() may block while these tasks 100 // are executing, care must be taken to ensure that they do not block on the 101 // thread that called ThreadPoolInstance::Shutdown(), as this may lead to 102 // deadlock. 103 SKIP_ON_SHUTDOWN, 104 105 // Tasks posted with this mode before shutdown is complete will block shutdown 106 // until they're executed. Generally, this should be used only to save 107 // critical user data. 108 // 109 // Note 1: Delayed tasks cannot block shutdown. Delayed tasks posted as part 110 // of a BLOCK_SHUTDOWN sequence will behave like SKIP_ON_SHUTDOWN tasks. 111 // 112 // Note 2: Background threads will be promoted to normal threads at shutdown 113 // (i.e. TaskPriority::BEST_EFFORT + TaskShutdownBehavior::BLOCK_SHUTDOWN will 114 // resolve without a priority inversion). 115 BLOCK_SHUTDOWN, 116 }; 117 118 // Determines at which thread priority a task may run. 119 // 120 // ThreadPolicy and priority updates 121 // --------------------------------- 122 // 123 // If the TaskPriority of an UpdateableSequencedTaskRunner is increased while 124 // one of its tasks is running at background thread priority, the task's 125 // execution will have to complete at background thread priority (may take a 126 // long time) before the next task can be scheduled with the new TaskPriority. 127 // If it is important that priority increases take effect quickly, 128 // MUST_USE_FOREGROUND should be used to prevent the tasks from running at 129 // background thread priority. If it is important to minimize impact on the 130 // rest on the system when the TaskPriority is BEST_EFFORT, PREFER_BACKGROUND 131 // should be used. 132 // 133 // ThreadPolicy and priority inversions 134 // ------------------------------------ 135 // 136 // A priority inversion occurs when a task running at background thread 137 // priority is descheduled while holding a resource needed by a thread of 138 // higher priority. MUST_USE_FOREGROUND can be combined with BEST_EFFORT to 139 // indicate that a task has a low priority, but shouldn't run at background 140 // thread priority in order to avoid priority inversions. Please consult with 141 // //base/task/OWNERS if you suspect a priority inversion. 142 enum class ThreadPolicy : uint8_t { 143 // The task runs on a background priority thread if: 144 // - The TaskPriority is BEST_EFFORT. 145 // - Background thread priority is supported by the platform (see 146 // environment_config_unittest.cc). 147 // - ThreadPoolInstance::Shutdown() hadn't been called when the task started 148 // running. 149 // (Remaining TaskShutdownBehavior::BLOCK_SHUTDOWN tasks use foreground 150 // threads during shutdown regardless of TaskPriority) 151 // Otherwise, it runs on a normal priority thread. 152 // This is the default. 153 PREFER_BACKGROUND, 154 155 // The task runs at normal thread priority, irrespective of its TaskPriority. 156 MUST_USE_FOREGROUND 157 }; 158 159 // Tasks with this trait may block. This includes but is not limited to tasks 160 // that wait on synchronous file I/O operations: read or write a file from disk, 161 // interact with a pipe or a socket, rename or delete a file, enumerate files in 162 // a directory, etc. This trait isn't required for the mere use of locks. For 163 // tasks that block on base/ synchronization primitives, see the 164 // WithBaseSyncPrimitives trait. 165 struct MayBlock {}; 166 167 // DEPRECATED. Use base::ScopedAllowBaseSyncPrimitives(ForTesting) instead. 168 // 169 // Tasks with this trait will pass base::AssertBaseSyncPrimitivesAllowed(), i.e. 170 // will be allowed on the following methods : 171 // - base::WaitableEvent::Wait 172 // - base::ConditionVariable::Wait 173 // - base::PlatformThread::Join 174 // - base::PlatformThread::Sleep 175 // - base::Process::WaitForExit 176 // - base::Process::WaitForExitWithTimeout 177 // 178 // Tasks should generally not use these methods. 179 // 180 // Instead of waiting on a WaitableEvent or a ConditionVariable, put the work 181 // that should happen after the wait in a callback and post that callback from 182 // where the WaitableEvent or ConditionVariable would have been signaled. If 183 // something needs to be scheduled after many tasks have executed, use 184 // base::BarrierClosure. 185 // 186 // On Windows, join processes asynchronously using base::win::ObjectWatcher. 187 // 188 // MayBlock() must be specified in conjunction with this trait if and only if 189 // removing usage of methods listed above in the labeled tasks would still 190 // result in tasks that may block (per MayBlock()'s definition). 191 // 192 // In doubt, consult with //base/task/OWNERS. 193 struct WithBaseSyncPrimitives {}; 194 195 // Describes metadata for a single task or a group of tasks. 196 class BASE_EXPORT TaskTraits { 197 public: 198 // ValidTrait ensures TaskTraits' constructor only accepts appropriate types. 199 struct ValidTrait { 200 ValidTrait(TaskPriority); 201 ValidTrait(TaskShutdownBehavior); 202 ValidTrait(ThreadPolicy); 203 ValidTrait(MayBlock); 204 ValidTrait(WithBaseSyncPrimitives); 205 }; 206 207 // Invoking this constructor without arguments produces default TaskTraits 208 // that are appropriate for tasks that 209 // (1) don't block (ref. MayBlock() and WithBaseSyncPrimitives()), 210 // (2) pertain to user-blocking activity, 211 // (explicitly or implicitly by having an ordering dependency with a 212 // component that does) 213 // (3) can either block shutdown or be skipped on shutdown 214 // (the task recipient is free to choose a fitting default). 215 // 216 // To get TaskTraits for tasks that have more precise traits: provide any 217 // combination of ValidTrait's as arguments to this constructor. 218 // 219 // Note: When posting to well-known threads (e.g. UI/IO), default traits are 220 // almost always what you want unless you know for sure the task being posted 221 // has no explicit/implicit ordering dependency with anything else running at 222 // default (USER_BLOCKING) priority. 223 // 224 // E.g. 225 // constexpr base::TaskTraits default_traits = {}; 226 // constexpr base::TaskTraits user_visible_traits = { 227 // base::TaskPriority::USER_VISIBLE}; 228 // constexpr base::TaskTraits user_visible_may_block_traits = { 229 // base::TaskPriority::USER_VISIBLE, base::MayBlock() 230 // }; 231 // constexpr base::TaskTraits other_user_visible_may_block_traits = { 232 // base::MayBlock(), base::TaskPriority::USER_VISIBLE 233 // }; 234 template <class... ArgTypes> 235 requires trait_helpers::AreValidTraits<ValidTrait, ArgTypes...> 236 // TaskTraits are intended to be implicitly-constructable (eg {}). 237 // NOLINTNEXTLINE(google-explicit-constructor) TaskTraits(ArgTypes...args)238 constexpr TaskTraits(ArgTypes... args) 239 : priority_( 240 trait_helpers::GetEnum<TaskPriority, TaskPriority::USER_BLOCKING>( 241 args...)), 242 shutdown_behavior_( 243 static_cast<uint8_t>( 244 trait_helpers::GetEnum<TaskShutdownBehavior, 245 TaskShutdownBehavior::SKIP_ON_SHUTDOWN>( 246 args...)) | 247 (trait_helpers::HasTrait<TaskShutdownBehavior, ArgTypes...>() 248 ? kIsExplicitFlag 249 : 0)), 250 thread_policy_( 251 static_cast<uint8_t>( 252 trait_helpers::GetEnum<ThreadPolicy, 253 ThreadPolicy::PREFER_BACKGROUND>( 254 args...)) | 255 (trait_helpers::HasTrait<ThreadPolicy, ArgTypes...>() 256 ? kIsExplicitFlag 257 : 0)), 258 may_block_(trait_helpers::HasTrait<MayBlock, ArgTypes...>()), 259 with_base_sync_primitives_( 260 trait_helpers::HasTrait<WithBaseSyncPrimitives, ArgTypes...>()) {} 261 262 constexpr TaskTraits(const TaskTraits& other) = default; 263 TaskTraits& operator=(const TaskTraits& other) = default; 264 265 friend bool operator==(const TaskTraits&, const TaskTraits&) = default; 266 267 // Sets the priority of tasks with these traits to |priority|. UpdatePriority(TaskPriority priority)268 void UpdatePriority(TaskPriority priority) { priority_ = priority; } 269 270 // Returns the priority of tasks with these traits. priority()271 constexpr TaskPriority priority() const { return priority_; } 272 273 // Returns true if the shutdown behavior was set explicitly. shutdown_behavior_set_explicitly()274 constexpr bool shutdown_behavior_set_explicitly() const { 275 return shutdown_behavior_ & kIsExplicitFlag; 276 } 277 278 // Returns the shutdown behavior of tasks with these traits. shutdown_behavior()279 constexpr TaskShutdownBehavior shutdown_behavior() const { 280 return static_cast<TaskShutdownBehavior>(shutdown_behavior_ & 281 ~kIsExplicitFlag); 282 } 283 284 // Returns true if the thread policy was set explicitly. thread_policy_set_explicitly()285 constexpr bool thread_policy_set_explicitly() const { 286 return thread_policy_ & kIsExplicitFlag; 287 } 288 289 // Returns the thread policy of tasks with these traits. thread_policy()290 constexpr ThreadPolicy thread_policy() const { 291 return static_cast<ThreadPolicy>(thread_policy_ & ~kIsExplicitFlag); 292 } 293 294 // Returns true if tasks with these traits may block. may_block()295 constexpr bool may_block() const { return may_block_; } 296 297 // Returns true if tasks with these traits may use base/ sync primitives. with_base_sync_primitives()298 constexpr bool with_base_sync_primitives() const { 299 return with_base_sync_primitives_; 300 } 301 302 private: 303 // This bit is set in |priority_|, |shutdown_behavior_| and |thread_policy_| 304 // when the value was set explicitly. 305 static constexpr uint8_t kIsExplicitFlag = 0x80; 306 307 // Ordered for packing. 308 TaskPriority priority_; 309 uint8_t shutdown_behavior_; 310 uint8_t thread_policy_; 311 bool may_block_; 312 bool with_base_sync_primitives_; 313 }; 314 315 // Returns string literals for the enums defined in this file. These methods 316 // should only be used for tracing and debugging. 317 BASE_EXPORT const char* TaskPriorityToString(TaskPriority task_priority); 318 BASE_EXPORT const char* TaskShutdownBehaviorToString( 319 TaskShutdownBehavior task_priority); 320 321 // Stream operators so that the enums defined in this file can be used in 322 // DCHECK and EXPECT statements. 323 BASE_EXPORT std::ostream& operator<<(std::ostream& os, 324 const TaskPriority& shutdown_behavior); 325 BASE_EXPORT std::ostream& operator<<( 326 std::ostream& os, 327 const TaskShutdownBehavior& shutdown_behavior); 328 329 } // namespace base 330 331 #endif // BASE_TASK_TASK_TRAITS_H_ 332