sequenced_task_runner.h 7.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201
  1. // Copyright (c) 2012 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. #ifndef BASE_SEQUENCED_TASK_RUNNER_H_
  5. #define BASE_SEQUENCED_TASK_RUNNER_H_
  6. #include <memory>
  7. #include "base/base_export.h"
  8. #include "base/callback.h"
  9. #include "base/sequenced_task_runner_helpers.h"
  10. #include "base/task_runner.h"
  11. namespace base {
  12. // A SequencedTaskRunner is a subclass of TaskRunner that provides
  13. // additional guarantees on the order that tasks are started, as well
  14. // as guarantees on when tasks are in sequence, i.e. one task finishes
  15. // before the other one starts.
  16. //
  17. // Summary
  18. // -------
  19. // Non-nested tasks with the same delay will run one by one in FIFO
  20. // order.
  21. //
  22. // Detailed guarantees
  23. // -------------------
  24. //
  25. // SequencedTaskRunner also adds additional methods for posting
  26. // non-nestable tasks. In general, an implementation of TaskRunner
  27. // may expose task-running methods which are themselves callable from
  28. // within tasks. A non-nestable task is one that is guaranteed to not
  29. // be run from within an already-running task. Conversely, a nestable
  30. // task (the default) is a task that can be run from within an
  31. // already-running task.
  32. //
  33. // The guarantees of SequencedTaskRunner are as follows:
  34. //
  35. // - Given two tasks T2 and T1, T2 will start after T1 starts if:
  36. //
  37. // * T2 is posted after T1; and
  38. // * T2 has equal or higher delay than T1; and
  39. // * T2 is non-nestable or T1 is nestable.
  40. //
  41. // - If T2 will start after T1 starts by the above guarantee, then
  42. // T2 will start after T1 finishes and is destroyed if:
  43. //
  44. // * T2 is non-nestable, or
  45. // * T1 doesn't call any task-running methods.
  46. //
  47. // - If T2 will start after T1 finishes by the above guarantee, then
  48. // all memory changes in T1 and T1's destruction will be visible
  49. // to T2.
  50. //
  51. // - If T2 runs nested within T1 via a call to the task-running
  52. // method M, then all memory changes in T1 up to the call to M
  53. // will be visible to T2, and all memory changes in T2 will be
  54. // visible to T1 from the return from M.
  55. //
  56. // Note that SequencedTaskRunner does not guarantee that tasks are run
  57. // on a single dedicated thread, although the above guarantees provide
  58. // most (but not all) of the same guarantees. If you do need to
  59. // guarantee that tasks are run on a single dedicated thread, see
  60. // SingleThreadTaskRunner (in single_thread_task_runner.h).
  61. //
  62. // Some corollaries to the above guarantees, assuming the tasks in
  63. // question don't call any task-running methods:
  64. //
  65. // - Tasks posted via PostTask are run in FIFO order.
  66. //
  67. // - Tasks posted via PostNonNestableTask are run in FIFO order.
  68. //
  69. // - Tasks posted with the same delay and the same nestable state
  70. // are run in FIFO order.
  71. //
  72. // - A list of tasks with the same nestable state posted in order of
  73. // non-decreasing delay is run in FIFO order.
  74. //
  75. // - A list of tasks posted in order of non-decreasing delay with at
  76. // most a single change in nestable state from nestable to
  77. // non-nestable is run in FIFO order. (This is equivalent to the
  78. // statement of the first guarantee above.)
  79. //
  80. // Some theoretical implementations of SequencedTaskRunner:
  81. //
  82. // - A SequencedTaskRunner that wraps a regular TaskRunner but makes
  83. // sure that only one task at a time is posted to the TaskRunner,
  84. // with appropriate memory barriers in between tasks.
  85. //
  86. // - A SequencedTaskRunner that, for each task, spawns a joinable
  87. // thread to run that task and immediately quit, and then
  88. // immediately joins that thread.
  89. //
  90. // - A SequencedTaskRunner that stores the list of posted tasks and
  91. // has a method Run() that runs each runnable task in FIFO order
  92. // that can be called from any thread, but only if another
  93. // (non-nested) Run() call isn't already happening.
  94. class BASE_EXPORT SequencedTaskRunner : public TaskRunner {
  95. public:
  96. // The two PostNonNestable*Task methods below are like their
  97. // nestable equivalents in TaskRunner, but they guarantee that the
  98. // posted task will not run nested within an already-running task.
  99. //
  100. // A simple corollary is that posting a task as non-nestable can
  101. // only delay when the task gets run. That is, posting a task as
  102. // non-nestable may not affect when the task gets run, or it could
  103. // make it run later than it normally would, but it won't make it
  104. // run earlier than it normally would.
  105. // TODO(akalin): Get rid of the boolean return value for the methods
  106. // below.
  107. bool PostNonNestableTask(const Location& from_here, OnceClosure task);
  108. virtual bool PostNonNestableDelayedTask(const Location& from_here,
  109. OnceClosure task,
  110. base::TimeDelta delay) = 0;
  111. // Submits a non-nestable task to delete the given object. Returns
  112. // true if the object may be deleted at some point in the future,
  113. // and false if the object definitely will not be deleted.
  114. template <class T>
  115. bool DeleteSoon(const Location& from_here, const T* object) {
  116. return DeleteOrReleaseSoonInternal(from_here, &DeleteHelper<T>::DoDelete,
  117. object);
  118. }
  119. template <class T>
  120. bool DeleteSoon(const Location& from_here, std::unique_ptr<T> object) {
  121. return DeleteSoon(from_here, object.release());
  122. }
  123. // Submits a non-nestable task to release the given object.
  124. //
  125. // ReleaseSoon makes sure that the object it the scoped_refptr points to gets
  126. // properly released on the correct thread.
  127. // We apply ReleaseSoon to the rvalue as the side-effects can be unclear to
  128. // the caller if an lvalue is used. That being so, the scoped_refptr should
  129. // always be std::move'd.
  130. // Example use:
  131. //
  132. // scoped_refptr<T> foo_scoped_refptr;
  133. // ...
  134. // task_runner->ReleaseSoon(std::move(foo_scoped_refptr));
  135. template <class T>
  136. void ReleaseSoon(const Location& from_here, scoped_refptr<T>&& object) {
  137. if (!object)
  138. return;
  139. DeleteOrReleaseSoonInternal(from_here, &ReleaseHelper<T>::DoRelease,
  140. object.release());
  141. }
  142. // Returns true iff tasks posted to this TaskRunner are sequenced
  143. // with this call.
  144. //
  145. // In particular:
  146. // - Returns true if this is a SequencedTaskRunner to which the
  147. // current task was posted.
  148. // - Returns true if this is a SequencedTaskRunner bound to the
  149. // same sequence as the SequencedTaskRunner to which the current
  150. // task was posted.
  151. // - Returns true if this is a SingleThreadTaskRunner bound to
  152. // the current thread.
  153. virtual bool RunsTasksInCurrentSequence() const = 0;
  154. protected:
  155. ~SequencedTaskRunner() override = default;
  156. private:
  157. bool DeleteOrReleaseSoonInternal(const Location& from_here,
  158. void (*deleter)(const void*),
  159. const void* object);
  160. };
  161. // Sample usage with std::unique_ptr :
  162. // std::unique_ptr<Foo, base::OnTaskRunnerDeleter> ptr(
  163. // new Foo, base::OnTaskRunnerDeleter(my_task_runner));
  164. //
  165. // For RefCounted see base::RefCountedDeleteOnSequence.
  166. struct BASE_EXPORT OnTaskRunnerDeleter {
  167. explicit OnTaskRunnerDeleter(scoped_refptr<SequencedTaskRunner> task_runner);
  168. ~OnTaskRunnerDeleter();
  169. OnTaskRunnerDeleter(OnTaskRunnerDeleter&&);
  170. OnTaskRunnerDeleter& operator=(OnTaskRunnerDeleter&&);
  171. // For compatibility with std:: deleters.
  172. template <typename T>
  173. void operator()(const T* ptr) {
  174. if (ptr)
  175. task_runner_->DeleteSoon(FROM_HERE, ptr);
  176. }
  177. scoped_refptr<SequencedTaskRunner> task_runner_;
  178. };
  179. } // namespace base
  180. #endif // BASE_SEQUENCED_TASK_RUNNER_H_