repeating_task.h 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142
  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 RTC_BASE_TASK_UTILS_REPEATING_TASK_H_
  11. #define RTC_BASE_TASK_UTILS_REPEATING_TASK_H_
  12. #include <memory>
  13. #include <type_traits>
  14. #include <utility>
  15. #include "api/task_queue/queued_task.h"
  16. #include "api/task_queue/task_queue_base.h"
  17. #include "api/units/time_delta.h"
  18. #include "api/units/timestamp.h"
  19. #include "system_wrappers/include/clock.h"
  20. namespace webrtc {
  21. class RepeatingTaskHandle;
  22. namespace webrtc_repeating_task_impl {
  23. class RepeatingTaskBase : public QueuedTask {
  24. public:
  25. RepeatingTaskBase(TaskQueueBase* task_queue,
  26. TimeDelta first_delay,
  27. Clock* clock);
  28. ~RepeatingTaskBase() override;
  29. void Stop();
  30. private:
  31. virtual TimeDelta RunClosure() = 0;
  32. bool Run() final;
  33. TaskQueueBase* const task_queue_;
  34. Clock* const clock_;
  35. // This is always finite, except for the special case where it's PlusInfinity
  36. // to signal that the task should stop.
  37. Timestamp next_run_time_ RTC_GUARDED_BY(task_queue_);
  38. };
  39. // The template closure pattern is based on rtc::ClosureTask.
  40. template <class Closure>
  41. class RepeatingTaskImpl final : public RepeatingTaskBase {
  42. public:
  43. RepeatingTaskImpl(TaskQueueBase* task_queue,
  44. TimeDelta first_delay,
  45. Closure&& closure,
  46. Clock* clock)
  47. : RepeatingTaskBase(task_queue, first_delay, clock),
  48. closure_(std::forward<Closure>(closure)) {
  49. static_assert(
  50. std::is_same<TimeDelta,
  51. typename std::result_of<decltype (&Closure::operator())(
  52. Closure)>::type>::value,
  53. "");
  54. }
  55. private:
  56. TimeDelta RunClosure() override { return closure_(); }
  57. typename std::remove_const<
  58. typename std::remove_reference<Closure>::type>::type closure_;
  59. };
  60. } // namespace webrtc_repeating_task_impl
  61. // Allows starting tasks that repeat themselves on a TaskQueue indefinately
  62. // until they are stopped or the TaskQueue is destroyed. It allows starting and
  63. // stopping multiple times, but you must stop one task before starting another
  64. // and it can only be stopped when in the running state. The public interface is
  65. // not thread safe.
  66. class RepeatingTaskHandle {
  67. public:
  68. RepeatingTaskHandle() = default;
  69. ~RepeatingTaskHandle() = default;
  70. RepeatingTaskHandle(RepeatingTaskHandle&& other);
  71. RepeatingTaskHandle& operator=(RepeatingTaskHandle&& other);
  72. RepeatingTaskHandle(const RepeatingTaskHandle&) = delete;
  73. RepeatingTaskHandle& operator=(const RepeatingTaskHandle&) = delete;
  74. // Start can be used to start a task that will be reposted with a delay
  75. // determined by the return value of the provided closure. The actual task is
  76. // owned by the TaskQueue and will live until it has been stopped or the
  77. // TaskQueue is destroyed. Note that this means that trying to stop the
  78. // repeating task after the TaskQueue is destroyed is an error. However, it's
  79. // perfectly fine to destroy the handle while the task is running, since the
  80. // repeated task is owned by the TaskQueue.
  81. template <class Closure>
  82. static RepeatingTaskHandle Start(TaskQueueBase* task_queue,
  83. Closure&& closure,
  84. Clock* clock = Clock::GetRealTimeClock()) {
  85. auto repeating_task = std::make_unique<
  86. webrtc_repeating_task_impl::RepeatingTaskImpl<Closure>>(
  87. task_queue, TimeDelta::Zero(), std::forward<Closure>(closure), clock);
  88. auto* repeating_task_ptr = repeating_task.get();
  89. task_queue->PostTask(std::move(repeating_task));
  90. return RepeatingTaskHandle(repeating_task_ptr);
  91. }
  92. // DelayedStart is equivalent to Start except that the first invocation of the
  93. // closure will be delayed by the given amount.
  94. template <class Closure>
  95. static RepeatingTaskHandle DelayedStart(
  96. TaskQueueBase* task_queue,
  97. TimeDelta first_delay,
  98. Closure&& closure,
  99. Clock* clock = Clock::GetRealTimeClock()) {
  100. auto repeating_task = std::make_unique<
  101. webrtc_repeating_task_impl::RepeatingTaskImpl<Closure>>(
  102. task_queue, first_delay, std::forward<Closure>(closure), clock);
  103. auto* repeating_task_ptr = repeating_task.get();
  104. task_queue->PostDelayedTask(std::move(repeating_task), first_delay.ms());
  105. return RepeatingTaskHandle(repeating_task_ptr);
  106. }
  107. // Stops future invocations of the repeating task closure. Can only be called
  108. // from the TaskQueue where the task is running. The closure is guaranteed to
  109. // not be running after Stop() returns unless Stop() is called from the
  110. // closure itself.
  111. void Stop();
  112. // Returns true if Start() or DelayedStart() was called most recently. Returns
  113. // false initially and if Stop() or PostStop() was called most recently.
  114. bool Running() const;
  115. private:
  116. explicit RepeatingTaskHandle(
  117. webrtc_repeating_task_impl::RepeatingTaskBase* repeating_task);
  118. // Owned by the task queue.
  119. webrtc_repeating_task_impl::RepeatingTaskBase* repeating_task_ = nullptr;
  120. };
  121. } // namespace webrtc
  122. #endif // RTC_BASE_TASK_UTILS_REPEATING_TASK_H_