tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

task_queue_base.h (8471B)


      1 /*
      2 *  Copyright 2019 The WebRTC Project Authors. All rights reserved.
      3 *
      4 *  Use of this source code is governed by a BSD-style license
      5 *  that can be found in the LICENSE file in the root of the source
      6 *  tree. An additional intellectual property rights grant can be found
      7 *  in the file PATENTS.  All contributing project authors may
      8 *  be found in the AUTHORS file in the root of the source tree.
      9 */
     10 #ifndef API_TASK_QUEUE_TASK_QUEUE_BASE_H_
     11 #define API_TASK_QUEUE_TASK_QUEUE_BASE_H_
     12 
     13 #include <utility>
     14 
     15 #include "absl/functional/any_invocable.h"
     16 #include "api/location.h"
     17 #include "api/units/time_delta.h"
     18 #include "rtc_base/system/rtc_export.h"
     19 #include "rtc_base/thread_annotations.h"
     20 
     21 namespace webrtc {
     22 
     23 // Asynchronously executes tasks in a way that guarantees that they're executed
     24 // in FIFO order and that tasks never overlap. Tasks may always execute on the
     25 // same worker thread and they may not. To DCHECK that tasks are executing on a
     26 // known task queue, use IsCurrent().
     27 class RTC_LOCKABLE RTC_EXPORT TaskQueueBase {
     28 public:
     29  enum class DelayPrecision {
     30    // This may include up to a 17 ms leeway in addition to OS timer precision.
     31    // See PostDelayedTask() for more information.
     32    kLow,
     33    // This does not have the additional delay that kLow has, but it is still
     34    // limited by OS timer precision. See PostDelayedHighPrecisionTask() for
     35    // more information.
     36    kHigh,
     37  };
     38 
     39  // Starts destruction of the task queue.
     40  // On return ensures no task are running and no new tasks are able to start
     41  // on the task queue.
     42  // Responsible for deallocation. Deallocation may happen synchronously during
     43  // Delete or asynchronously after Delete returns.
     44  // Code not running on the TaskQueue should not make any assumption when
     45  // TaskQueue is deallocated and thus should not call any methods after Delete.
     46  // Code running on the TaskQueue should not call Delete, but can assume
     47  // TaskQueue still exists and may call other methods, e.g. PostTask.
     48  // Should be called on the same task queue or thread that this task queue
     49  // was created on.
     50  virtual void Delete() = 0;
     51 
     52  // Schedules a `task` to execute. Tasks are executed in FIFO order.
     53  // When a TaskQueue is deleted, pending tasks will not be executed but they
     54  // will be deleted.
     55  //
     56  // As long as tasks are not posted from task destruction, posted tasks are
     57  // guaranteed to be destroyed with Current() pointing to the task queue they
     58  // were posted to, whether they're executed or not. That means SequenceChecker
     59  // works during task destruction, a fact that can be used to guarantee
     60  // thread-compatible object deletion happening on a particular task queue
     61  // which can simplify class design.
     62  // Note that this guarantee does not apply to delayed tasks.
     63  //
     64  // May be called on any thread or task queue, including this task queue.
     65  void PostTask(absl::AnyInvocable<void() &&> task,
     66                const Location& location = Location::Current()) {
     67    PostTaskImpl(std::move(task), PostTaskTraits{}, location);
     68  }
     69 
     70  // Prefer PostDelayedTask() over PostDelayedHighPrecisionTask() whenever
     71  // possible.
     72  //
     73  // Schedules a `task` to execute a specified `delay` from when the call is
     74  // made, using "low" precision. All scheduling is affected by OS-specific
     75  // leeway and current workloads which means that in terms of precision there
     76  // are no hard guarantees, but in addition to the OS induced leeway, "low"
     77  // precision adds up to a 17 ms additional leeway. The purpose of this leeway
     78  // is to achieve more efficient CPU scheduling and reduce Idle Wake Up
     79  // frequency.
     80  //
     81  // The task may execute with [-1, 17 + OS induced leeway) ms additional delay.
     82  //
     83  // Avoid making assumptions about the precision of the OS scheduler. On macOS,
     84  // the OS induced leeway may be 10% of sleep interval. On Windows, 1 ms
     85  // precision timers may be used but there are cases, such as when running on
     86  // battery, when the timer precision can be as poor as 15 ms.
     87  //
     88  // "Low" precision is not implemented everywhere yet. Where not yet
     89  // implemented, PostDelayedTask() has "high" precision. See
     90  // https://crbug.com/webrtc/13583 for more information.
     91  //
     92  // May be called on any thread or task queue, including this task queue.
     93  void PostDelayedTask(absl::AnyInvocable<void() &&> task,
     94                       TimeDelta delay,
     95                       const Location& location = Location::Current()) {
     96    PostDelayedTaskImpl(std::move(task), delay, PostDelayedTaskTraits{},
     97                        location);
     98  }
     99 
    100  // Prefer PostDelayedTask() over PostDelayedHighPrecisionTask() whenever
    101  // possible.
    102  //
    103  // Schedules a `task` to execute a specified `delay` from when the call is
    104  // made, using "high" precision. All scheduling is affected by OS-specific
    105  // leeway and current workloads which means that in terms of precision there
    106  // are no hard guarantees.
    107  //
    108  // The task may execute with [-1, OS induced leeway] ms additional delay.
    109  //
    110  // Avoid making assumptions about the precision of the OS scheduler. On macOS,
    111  // the OS induced leeway may be 10% of sleep interval. On Windows, 1 ms
    112  // precision timers may be used but there are cases, such as when running on
    113  // battery, when the timer precision can be as poor as 15 ms.
    114  //
    115  // May be called on any thread or task queue, including this task queue.
    116  void PostDelayedHighPrecisionTask(
    117      absl::AnyInvocable<void() &&> task,
    118      TimeDelta delay,
    119      const Location& location = Location::Current()) {
    120    PostDelayedTaskTraits traits;
    121    traits.high_precision = true;
    122    PostDelayedTaskImpl(std::move(task), delay, traits, location);
    123  }
    124 
    125  // As specified by `precision`, calls either PostDelayedTask() or
    126  // PostDelayedHighPrecisionTask().
    127  void PostDelayedTaskWithPrecision(
    128      DelayPrecision precision,
    129      absl::AnyInvocable<void() &&> task,
    130      TimeDelta delay,
    131      const Location& location = Location::Current()) {
    132    switch (precision) {
    133      case DelayPrecision::kLow:
    134        PostDelayedTask(std::move(task), delay, location);
    135        break;
    136      case DelayPrecision::kHigh:
    137        PostDelayedHighPrecisionTask(std::move(task), delay, location);
    138        break;
    139    }
    140  }
    141 
    142  // Returns the task queue that is running the current thread.
    143  // Returns nullptr if this thread is not associated with any task queue.
    144  // May be called on any thread or task queue, including this task queue.
    145  static TaskQueueBase* Current();
    146  bool IsCurrent() const { return Current() == this; }
    147 
    148 protected:
    149  // This is currently only present here to simplify introduction of future
    150  // planned task queue changes.
    151  struct PostTaskTraits {};
    152 
    153  struct PostDelayedTaskTraits {
    154    // If `high_precision` is false, tasks may execute within up to a 17 ms
    155    // leeway in addition to OS timer precision. Otherwise the task should be
    156    // limited to OS timer precision. See PostDelayedTask() and
    157    // PostDelayedHighPrecisionTask() for more information.
    158    bool high_precision = false;
    159  };
    160 
    161  class RTC_EXPORT CurrentTaskQueueSetter {
    162   public:
    163    explicit CurrentTaskQueueSetter(TaskQueueBase* task_queue);
    164    CurrentTaskQueueSetter(const CurrentTaskQueueSetter&) = delete;
    165    CurrentTaskQueueSetter& operator=(const CurrentTaskQueueSetter&) = delete;
    166    ~CurrentTaskQueueSetter();
    167 
    168   private:
    169    TaskQueueBase* const previous_;
    170  };
    171 
    172  // Subclasses should implement this method to support the behavior defined in
    173  // the PostTask and PostTaskTraits docs above.
    174  virtual void PostTaskImpl(absl::AnyInvocable<void() &&> task,
    175                            const PostTaskTraits& traits,
    176                            const Location& location) = 0;
    177 
    178  // Subclasses should implement this method to support the behavior defined in
    179  // the PostDelayedTask/PostHighPrecisionDelayedTask and PostDelayedTaskTraits
    180  // docs above.
    181  virtual void PostDelayedTaskImpl(absl::AnyInvocable<void() &&> task,
    182                                   TimeDelta delay,
    183                                   const PostDelayedTaskTraits& traits,
    184                                   const Location& location) = 0;
    185 
    186  // Users of the TaskQueue should call Delete instead of directly deleting
    187  // this object.
    188  virtual ~TaskQueueBase() = default;
    189 };
    190 
    191 struct TaskQueueDeleter {
    192  void operator()(TaskQueueBase* task_queue) const { task_queue->Delete(); }
    193 };
    194 
    195 }  // namespace webrtc
    196 
    197 #endif  // API_TASK_QUEUE_TASK_QUEUE_BASE_H_