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