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