tor-browser

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

sequenced_task_runner.h (14121B)


      1 // Copyright 2012 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_SEQUENCED_TASK_RUNNER_H_
      6 #define BASE_TASK_SEQUENCED_TASK_RUNNER_H_
      7 
      8 #include <memory>
      9 
     10 #include "base/auto_reset.h"
     11 #include "base/base_export.h"
     12 #include "base/functional/callback.h"
     13 #include "base/task/delay_policy.h"
     14 #include "base/task/delayed_task_handle.h"
     15 #include "base/task/sequenced_task_runner_helpers.h"
     16 #include "base/task/task_runner.h"
     17 #include "base/types/pass_key.h"
     18 
     19 namespace blink {
     20 class LowPrecisionTimer;
     21 class TimerBase;
     22 class TimerBasedTickProvider;
     23 class WebRtcTaskQueue;
     24 }
     25 namespace webrtc {
     26 class ThreadWrapper;
     27 }  // namespace webrtc
     28 namespace media {
     29 class AlsaPcmOutputStream;
     30 class AlsaPcmInputStream;
     31 class FakeAudioWorker;
     32 }  // namespace media
     33 
     34 namespace base {
     35 
     36 namespace internal {
     37 class DelayTimerBase;
     38 class DelayedTaskManager;
     39 }
     40 class DeadlineTimer;
     41 class MetronomeTimer;
     42 class TimeDelta;
     43 class TimeTicks;
     44 
     45 namespace subtle {
     46 
     47 // Used to restrict access to PostCancelableDelayedTaskAt() to authorize
     48 // callers.
     49 class PostDelayedTaskPassKey {
     50 private:
     51  // Avoid =default to disallow creation by uniform initialization.
     52  PostDelayedTaskPassKey() {}
     53 
     54  friend class base::internal::DelayTimerBase;
     55  friend class base::internal::DelayedTaskManager;
     56  friend class base::DeadlineTimer;
     57  friend class base::MetronomeTimer;
     58  friend class blink::LowPrecisionTimer;
     59  friend class blink::TimerBase;
     60  friend class blink::TimerBasedTickProvider;
     61  friend class blink::WebRtcTaskQueue;
     62  friend class PostDelayedTaskPassKeyForTesting;
     63  friend class webrtc::ThreadWrapper;
     64  friend class media::AlsaPcmOutputStream;
     65  friend class media::AlsaPcmInputStream;
     66  friend class media::FakeAudioWorker;
     67 };
     68 
     69 class PostDelayedTaskPassKeyForTesting : public PostDelayedTaskPassKey {};
     70 
     71 }  // namespace subtle
     72 
     73 // A SequencedTaskRunner is a subclass of TaskRunner that provides
     74 // additional guarantees on the order that tasks are started, as well
     75 // as guarantees on when tasks are in sequence, i.e. one task finishes
     76 // before the other one starts.
     77 //
     78 // Summary
     79 // -------
     80 // Non-nested tasks with the same delay will run one by one in FIFO
     81 // order.
     82 //
     83 // Detailed guarantees
     84 // -------------------
     85 //
     86 // SequencedTaskRunner also adds additional methods for posting
     87 // non-nestable tasks.  In general, an implementation of TaskRunner
     88 // may expose task-running methods which are themselves callable from
     89 // within tasks.  A non-nestable task is one that is guaranteed to not
     90 // be run from within an already-running task.  Conversely, a nestable
     91 // task (the default) is a task that can be run from within an
     92 // already-running task.
     93 //
     94 // The guarantees of SequencedTaskRunner are as follows:
     95 //
     96 //   - Given two tasks T2 and T1, T2 will start after T1 starts if:
     97 //
     98 //       * T2 is posted after T1; and
     99 //       * T2 has equal or higher delay than T1; and
    100 //       * T2 is non-nestable or T1 is nestable.
    101 //
    102 //   - If T2 will start after T1 starts by the above guarantee, then
    103 //     T2 will start after T1 finishes and is destroyed if:
    104 //
    105 //       * T2 is non-nestable, or
    106 //       * T1 doesn't call any task-running methods.
    107 //
    108 //   - If T2 will start after T1 finishes by the above guarantee, then
    109 //     all memory changes in T1 and T1's destruction will be visible
    110 //     to T2.
    111 //
    112 //   - If T2 runs nested within T1 via a call to the task-running
    113 //     method M, then all memory changes in T1 up to the call to M
    114 //     will be visible to T2, and all memory changes in T2 will be
    115 //     visible to T1 from the return from M.
    116 //
    117 // Note that SequencedTaskRunner does not guarantee that tasks are run
    118 // on a single dedicated thread, although the above guarantees provide
    119 // most (but not all) of the same guarantees.  If you do need to
    120 // guarantee that tasks are run on a single dedicated thread, see
    121 // SingleThreadTaskRunner (in single_thread_task_runner.h).
    122 //
    123 // Some corollaries to the above guarantees, assuming the tasks in
    124 // question don't call any task-running methods:
    125 //
    126 //   - Tasks posted via PostTask are run in FIFO order.
    127 //
    128 //   - Tasks posted via PostNonNestableTask are run in FIFO order.
    129 //
    130 //   - Tasks posted with the same delay and the same nestable state
    131 //     are run in FIFO order.
    132 //
    133 //   - A list of tasks with the same nestable state posted in order of
    134 //     non-decreasing delay is run in FIFO order.
    135 //
    136 //   - A list of tasks posted in order of non-decreasing delay with at
    137 //     most a single change in nestable state from nestable to
    138 //     non-nestable is run in FIFO order. (This is equivalent to the
    139 //     statement of the first guarantee above.)
    140 //
    141 // Some theoretical implementations of SequencedTaskRunner:
    142 //
    143 //   - A SequencedTaskRunner that wraps a regular TaskRunner but makes
    144 //     sure that only one task at a time is posted to the TaskRunner,
    145 //     with appropriate memory barriers in between tasks.
    146 //
    147 //   - A SequencedTaskRunner that, for each task, spawns a joinable
    148 //     thread to run that task and immediately quit, and then
    149 //     immediately joins that thread.
    150 //
    151 //   - A SequencedTaskRunner that stores the list of posted tasks and
    152 //     has a method Run() that runs each runnable task in FIFO order
    153 //     that can be called from any thread, but only if another
    154 //     (non-nested) Run() call isn't already happening.
    155 //
    156 // SequencedTaskRunner::GetCurrentDefault() can be used while running
    157 // a task to retrieve the default SequencedTaskRunner for the current
    158 // sequence.
    159 class BASE_EXPORT SequencedTaskRunner : public TaskRunner {
    160 public:
    161  // The two PostNonNestable*Task methods below are like their
    162  // nestable equivalents in TaskRunner, but they guarantee that the
    163  // posted task will not run nested within an already-running task.
    164  //
    165  // A simple corollary is that posting a task as non-nestable can
    166  // only delay when the task gets run.  That is, posting a task as
    167  // non-nestable may not affect when the task gets run, or it could
    168  // make it run later than it normally would, but it won't make it
    169  // run earlier than it normally would.
    170 
    171  // TODO(akalin): Get rid of the boolean return value for the methods
    172  // below.
    173 
    174  bool PostNonNestableTask(const Location& from_here, OnceClosure task);
    175 
    176  virtual bool PostNonNestableDelayedTask(const Location& from_here,
    177                                          OnceClosure task,
    178                                          base::TimeDelta delay) = 0;
    179 
    180  // Posts the given |task| to be run only after |delay| has passed. Returns a
    181  // handle that can be used to cancel the task. This should not be used
    182  // directly. Consider using higher level timer primitives in
    183  // base/timer/timer.h.
    184  //
    185  // The handle is only guaranteed valid while the task is pending execution.
    186  // This means that it may be invalid if the posting failed, and will be
    187  // invalid while the task is executing. Calling CancelTask() on an invalid
    188  // handle is a no-op.
    189  //
    190  // This method and the handle it returns are not thread-safe and can only be
    191  // used from the sequence this task runner runs its tasks on.
    192  virtual DelayedTaskHandle PostCancelableDelayedTask(
    193      subtle::PostDelayedTaskPassKey,
    194      const Location& from_here,
    195      OnceClosure task,
    196      TimeDelta delay);
    197 
    198  // Posts the given |task| to be run at |delayed_run_time| (or immediately if
    199  // in the past), following |delay_policy|. Returns a handle that can be used
    200  // to cancel the task. This should not be used directly. Consider using higher
    201  // level timer primitives in base/timer/timer.h.
    202  [[nodiscard]] virtual DelayedTaskHandle PostCancelableDelayedTaskAt(
    203      subtle::PostDelayedTaskPassKey,
    204      const Location& from_here,
    205      OnceClosure task,
    206      TimeTicks delayed_run_time,
    207      subtle::DelayPolicy delay_policy);
    208 
    209  // Posts the given |task| to be run at |delayed_run_time| (or immediately if
    210  // in the past), following |delay_policy|. This is used by the default
    211  // implementation of PostCancelableDelayedTaskAt(). The default behavior
    212  // subtracts TimeTicks::Now() from |delayed_run_time| to get a delay. See
    213  // base::Timer to post precise/repeating timeouts.
    214  // TODO(1153139): Make pure virtual once all SequencedTaskRunners implement
    215  // this.
    216  virtual bool PostDelayedTaskAt(subtle::PostDelayedTaskPassKey,
    217                                 const Location& from_here,
    218                                 OnceClosure task,
    219                                 TimeTicks delayed_run_time,
    220                                 subtle::DelayPolicy delay_policy);
    221 
    222  // Submits a non-nestable task to delete the given object.  Returns
    223  // true if the object may be deleted at some point in the future,
    224  // and false if the object definitely will not be deleted.
    225  //
    226  // By default, this leaks `object` if the deleter task doesn't run, e.g. if
    227  // the underlying task queue is shut down first. Subclasses can override this
    228  // behavior by specializing `DeleteOrReleaseSoonInternal()`.
    229  template <class T>
    230  bool DeleteSoon(const Location& from_here, const T* object) {
    231    return DeleteOrReleaseSoonInternal(from_here, &DeleteHelper<T>::DoDelete,
    232                                       object);
    233  }
    234 
    235  template <class T>
    236  bool DeleteSoon(const Location& from_here, std::unique_ptr<T> object) {
    237    return DeleteOrReleaseSoonInternal(
    238        from_here, &DeleteUniquePtrHelper<T>::DoDelete, object.release());
    239  }
    240 
    241  // Submits a non-nestable task to release the given object.
    242  //
    243  // By default, this leaks `object` if the releaser task doesn't run, e.g. if
    244  // the underlying task queue is shut down first. Subclasses can override this
    245  // behavior by specializing `DeleteOrReleaseSoonInternal()`.
    246  //
    247  // ReleaseSoon makes sure that the object it the scoped_refptr points to gets
    248  // properly released on the correct thread.
    249  // We apply ReleaseSoon to the rvalue as the side-effects can be unclear to
    250  // the caller if an lvalue is used. That being so, the scoped_refptr should
    251  // always be std::move'd.
    252  // Example use:
    253  //
    254  // scoped_refptr<T> foo_scoped_refptr;
    255  // ...
    256  // task_runner->ReleaseSoon(std::move(foo_scoped_refptr));
    257  template <class T>
    258  void ReleaseSoon(const Location& from_here, scoped_refptr<T>&& object) {
    259    if (!object)
    260      return;
    261 
    262    DeleteOrReleaseSoonInternal(from_here, &ReleaseHelper<T>::DoRelease,
    263                                object.release());
    264  }
    265 
    266  // Returns true iff tasks posted to this TaskRunner are sequenced
    267  // with this call.
    268  //
    269  // In particular:
    270  // - Returns true if this is a SequencedTaskRunner to which the
    271  //   current task was posted.
    272  // - Returns true if this is a SequencedTaskRunner bound to the
    273  //   same sequence as the SequencedTaskRunner to which the current
    274  //   task was posted.
    275  // - Returns true if this is a SingleThreadTaskRunner bound to
    276  //   the current thread.
    277  virtual bool RunsTasksInCurrentSequence() const = 0;
    278 
    279  // Returns the default SequencedTaskRunner for the current task. It
    280  // should only be called if HasCurrentDefault() returns true (see the comment
    281  // there for the requirements).
    282  //
    283  // It is "default" in the sense that if the current sequence multiplexes
    284  // multiple task queues (e.g. BrowserThread::UI), this will return the default
    285  // task queue. A caller that wants a specific task queue should obtain it
    286  // directly instead of going through this API.
    287  //
    288  // See
    289  // https://chromium.googlesource.com/chromium/src/+/main/docs/threading_and_tasks.md#Posting-to-the-Current-Virtual_Thread
    290  // for details
    291  [[nodiscard]] static const scoped_refptr<SequencedTaskRunner>&
    292  GetCurrentDefault();
    293 
    294  // Returns true if one of the following conditions is fulfilled:
    295  // a) A SequencedTaskRunner has been assigned to the current thread by
    296  //    instantiating a SequencedTaskRunner::CurrentDefaultHandle.
    297  // b) The current thread has a SingleThreadTaskRunner::CurrentDefaultHandle
    298  //    (which includes any thread that runs a MessagePump).
    299  [[nodiscard]] static bool HasCurrentDefault();
    300 
    301  class BASE_EXPORT CurrentDefaultHandle {
    302   public:
    303    // Binds `task_runner` to the current thread so that it is returned by
    304    // GetCurrentDefault() in the scope of the constructed
    305    // `CurrentDefaultHandle`.
    306    explicit CurrentDefaultHandle(
    307        scoped_refptr<SequencedTaskRunner> task_runner);
    308 
    309    CurrentDefaultHandle(const CurrentDefaultHandle&) = delete;
    310    CurrentDefaultHandle& operator=(const CurrentDefaultHandle&) = delete;
    311 
    312    ~CurrentDefaultHandle();
    313 
    314   private:
    315    friend class SequencedTaskRunner;
    316    friend class CurrentHandleOverride;
    317 
    318    const AutoReset<CurrentDefaultHandle*> resetter_;
    319 
    320    scoped_refptr<SequencedTaskRunner> task_runner_;
    321  };
    322 
    323 protected:
    324  ~SequencedTaskRunner() override = default;
    325 
    326  // Helper to allow SingleThreadTaskRunner::CurrentDefaultHandle to double as a
    327  // SequencedTaskRunner::CurrentDefaultHandle.
    328  static void SetCurrentDefaultHandleTaskRunner(
    329      CurrentDefaultHandle& current_default,
    330      scoped_refptr<SequencedTaskRunner> task_runner) {
    331    current_default.task_runner_ = task_runner;
    332  }
    333 
    334  virtual bool DeleteOrReleaseSoonInternal(const Location& from_here,
    335                                           void (*deleter)(const void*),
    336                                           const void* object);
    337 };
    338 
    339 // Sample usage with std::unique_ptr :
    340 // std::unique_ptr<Foo, base::OnTaskRunnerDeleter> ptr(
    341 //     new Foo, base::OnTaskRunnerDeleter(my_task_runner));
    342 //
    343 // For RefCounted see base::RefCountedDeleteOnSequence.
    344 struct BASE_EXPORT OnTaskRunnerDeleter {
    345  explicit OnTaskRunnerDeleter(scoped_refptr<SequencedTaskRunner> task_runner);
    346  ~OnTaskRunnerDeleter();
    347 
    348  OnTaskRunnerDeleter(OnTaskRunnerDeleter&&);
    349  OnTaskRunnerDeleter& operator=(OnTaskRunnerDeleter&&);
    350 
    351  // For compatibility with std:: deleters.
    352  template <typename T>
    353  void operator()(const T* ptr) {
    354    if (ptr)
    355      task_runner_->DeleteSoon(FROM_HERE, ptr);
    356  }
    357 
    358  scoped_refptr<SequencedTaskRunner> task_runner_;
    359 };
    360 
    361 }  // namespace base
    362 
    363 #endif  // BASE_TASK_SEQUENCED_TASK_RUNNER_H_