blob: 1086c1629edf92f1c69af39c0d05b8ce11245b52 [file] [log] [blame]
Sebastian Janssonecb68972019-01-18 10:30:54 +01001/*
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
11#ifndef RTC_BASE_TASK_UTILS_REPEATING_TASK_H_
12#define RTC_BASE_TASK_UTILS_REPEATING_TASK_H_
13
Mirko Bonadei317a1f02019-09-17 17:06:18 +020014#include <memory>
Sebastian Janssonecb68972019-01-18 10:30:54 +010015#include <type_traits>
16#include <utility>
17
Danil Chapovalov4423c362019-03-06 18:41:39 +010018#include "api/task_queue/queued_task.h"
19#include "api/task_queue/task_queue_base.h"
Sebastian Janssonecb68972019-01-18 10:30:54 +010020#include "api/units/time_delta.h"
21#include "api/units/timestamp.h"
Danil Chapovalov0f9a8e32021-06-11 18:39:17 +020022#include "rtc_base/task_utils/pending_task_safety_flag.h"
Tommi532cac52020-05-18 14:53:42 +020023#include "system_wrappers/include/clock.h"
Sebastian Janssonecb68972019-01-18 10:30:54 +010024
25namespace webrtc {
Markus Handellc1c6bef2021-07-23 11:11:32 +020026
Sebastian Janssonecb68972019-01-18 10:30:54 +010027namespace webrtc_repeating_task_impl {
Markus Handellc1c6bef2021-07-23 11:11:32 +020028
29// Methods simplifying external tracing of RepeatingTaskHandle operations.
30void RepeatingTaskHandleDTraceProbeStart();
31void RepeatingTaskHandleDTraceProbeDelayedStart();
32void RepeatingTaskImplDTraceProbeRun();
33
Danil Chapovalov4423c362019-03-06 18:41:39 +010034class RepeatingTaskBase : public QueuedTask {
Sebastian Janssonecb68972019-01-18 10:30:54 +010035 public:
Tommi532cac52020-05-18 14:53:42 +020036 RepeatingTaskBase(TaskQueueBase* task_queue,
Henrik Boström27e8a092022-01-24 17:12:35 +010037 TaskQueueBase::DelayPrecision precision,
Tommi532cac52020-05-18 14:53:42 +020038 TimeDelta first_delay,
Danil Chapovalov0f9a8e32021-06-11 18:39:17 +020039 Clock* clock,
40 rtc::scoped_refptr<PendingTaskSafetyFlag> alive_flag);
Sebastian Janssonecb68972019-01-18 10:30:54 +010041 ~RepeatingTaskBase() override;
Tommia0a44802020-05-13 18:27:26 +020042
Sebastian Janssonecb68972019-01-18 10:30:54 +010043 private:
Tommia0a44802020-05-13 18:27:26 +020044 virtual TimeDelta RunClosure() = 0;
Sebastian Janssonecb68972019-01-18 10:30:54 +010045
46 bool Run() final;
Sebastian Janssonecb68972019-01-18 10:30:54 +010047
Danil Chapovalov4423c362019-03-06 18:41:39 +010048 TaskQueueBase* const task_queue_;
Henrik Boström27e8a092022-01-24 17:12:35 +010049 const TaskQueueBase::DelayPrecision precision_;
Tommi532cac52020-05-18 14:53:42 +020050 Clock* const clock_;
Danil Chapovalov0f9a8e32021-06-11 18:39:17 +020051 // This is always finite.
Tommi29a5fe82020-05-15 10:12:36 +020052 Timestamp next_run_time_ RTC_GUARDED_BY(task_queue_);
Danil Chapovalov0f9a8e32021-06-11 18:39:17 +020053 rtc::scoped_refptr<PendingTaskSafetyFlag> alive_flag_
54 RTC_GUARDED_BY(task_queue_);
Sebastian Janssonecb68972019-01-18 10:30:54 +010055};
56
Niels Möller902b5542022-01-17 15:20:24 +010057// The template closure pattern is based on rtc::ClosureTask. The provided
58// closure should have a TimeDelta return value, specifing the desired
59// non-negative interval to next repetition, or TimeDelta::PlusInfinity to
60// indicate that the task should be deleted and not called again.
Sebastian Janssonecb68972019-01-18 10:30:54 +010061template <class Closure>
62class RepeatingTaskImpl final : public RepeatingTaskBase {
63 public:
Danil Chapovalov4423c362019-03-06 18:41:39 +010064 RepeatingTaskImpl(TaskQueueBase* task_queue,
Henrik Boström27e8a092022-01-24 17:12:35 +010065 TaskQueueBase::DelayPrecision precision,
Sebastian Janssonecb68972019-01-18 10:30:54 +010066 TimeDelta first_delay,
Tommi532cac52020-05-18 14:53:42 +020067 Closure&& closure,
Danil Chapovalov0f9a8e32021-06-11 18:39:17 +020068 Clock* clock,
69 rtc::scoped_refptr<PendingTaskSafetyFlag> alive_flag)
70 : RepeatingTaskBase(task_queue,
Henrik Boström27e8a092022-01-24 17:12:35 +010071 precision,
Danil Chapovalov0f9a8e32021-06-11 18:39:17 +020072 first_delay,
73 clock,
74 std::move(alive_flag)),
Sebastian Janssonecb68972019-01-18 10:30:54 +010075 closure_(std::forward<Closure>(closure)) {
76 static_assert(
77 std::is_same<TimeDelta,
Peter Kasting662d7f12022-05-04 12:57:00 -070078 typename std::invoke_result<decltype(&Closure::operator()),
79 Closure>::type>::value,
Sebastian Janssonecb68972019-01-18 10:30:54 +010080 "");
81 }
82
Tommia0a44802020-05-13 18:27:26 +020083 private:
Markus Handellc1c6bef2021-07-23 11:11:32 +020084 TimeDelta RunClosure() override {
85 RepeatingTaskImplDTraceProbeRun();
86 return closure_();
87 }
Sebastian Janssonecb68972019-01-18 10:30:54 +010088
Sebastian Janssonecb68972019-01-18 10:30:54 +010089 typename std::remove_const<
90 typename std::remove_reference<Closure>::type>::type closure_;
91};
92} // namespace webrtc_repeating_task_impl
93
94// Allows starting tasks that repeat themselves on a TaskQueue indefinately
95// until they are stopped or the TaskQueue is destroyed. It allows starting and
96// stopping multiple times, but you must stop one task before starting another
97// and it can only be stopped when in the running state. The public interface is
98// not thread safe.
99class RepeatingTaskHandle {
100 public:
Sebastian Jansson46b4a0f2019-03-26 15:24:23 +0100101 RepeatingTaskHandle() = default;
102 ~RepeatingTaskHandle() = default;
Danil Chapovalov0f9a8e32021-06-11 18:39:17 +0200103 RepeatingTaskHandle(RepeatingTaskHandle&& other) = default;
104 RepeatingTaskHandle& operator=(RepeatingTaskHandle&& other) = default;
Sebastian Janssonecb68972019-01-18 10:30:54 +0100105 RepeatingTaskHandle(const RepeatingTaskHandle&) = delete;
106 RepeatingTaskHandle& operator=(const RepeatingTaskHandle&) = delete;
107
108 // Start can be used to start a task that will be reposted with a delay
109 // determined by the return value of the provided closure. The actual task is
110 // owned by the TaskQueue and will live until it has been stopped or the
Danil Chapovalov0f9a8e32021-06-11 18:39:17 +0200111 // TaskQueue deletes it. It's perfectly fine to destroy the handle while the
112 // task is running, since the repeated task is owned by the TaskQueue.
Henrik Boström27e8a092022-01-24 17:12:35 +0100113 // The tasks are scheduled onto the task queue using the specified precision.
Sebastian Janssonecb68972019-01-18 10:30:54 +0100114 template <class Closure>
Danil Chapovalov4423c362019-03-06 18:41:39 +0100115 static RepeatingTaskHandle Start(TaskQueueBase* task_queue,
Tommi532cac52020-05-18 14:53:42 +0200116 Closure&& closure,
Henrik Boström27e8a092022-01-24 17:12:35 +0100117 TaskQueueBase::DelayPrecision precision =
118 TaskQueueBase::DelayPrecision::kLow,
Tommi532cac52020-05-18 14:53:42 +0200119 Clock* clock = Clock::GetRealTimeClock()) {
Danil Chapovalov0f9a8e32021-06-11 18:39:17 +0200120 auto alive_flag = PendingTaskSafetyFlag::CreateDetached();
Markus Handellc1c6bef2021-07-23 11:11:32 +0200121 webrtc_repeating_task_impl::RepeatingTaskHandleDTraceProbeStart();
Danil Chapovalov0f9a8e32021-06-11 18:39:17 +0200122 task_queue->PostTask(
123 std::make_unique<
124 webrtc_repeating_task_impl::RepeatingTaskImpl<Closure>>(
Henrik Boström27e8a092022-01-24 17:12:35 +0100125 task_queue, precision, TimeDelta::Zero(),
126 std::forward<Closure>(closure), clock, alive_flag));
Danil Chapovalov0f9a8e32021-06-11 18:39:17 +0200127 return RepeatingTaskHandle(std::move(alive_flag));
Sebastian Janssonecb68972019-01-18 10:30:54 +0100128 }
Sebastian Janssonecb68972019-01-18 10:30:54 +0100129
130 // DelayedStart is equivalent to Start except that the first invocation of the
131 // closure will be delayed by the given amount.
132 template <class Closure>
Tommi532cac52020-05-18 14:53:42 +0200133 static RepeatingTaskHandle DelayedStart(
134 TaskQueueBase* task_queue,
135 TimeDelta first_delay,
136 Closure&& closure,
Henrik Boström27e8a092022-01-24 17:12:35 +0100137 TaskQueueBase::DelayPrecision precision =
138 TaskQueueBase::DelayPrecision::kLow,
Tommi532cac52020-05-18 14:53:42 +0200139 Clock* clock = Clock::GetRealTimeClock()) {
Danil Chapovalov0f9a8e32021-06-11 18:39:17 +0200140 auto alive_flag = PendingTaskSafetyFlag::CreateDetached();
Markus Handellc1c6bef2021-07-23 11:11:32 +0200141 webrtc_repeating_task_impl::RepeatingTaskHandleDTraceProbeDelayedStart();
Henrik Boström27e8a092022-01-24 17:12:35 +0100142 task_queue->PostDelayedTaskWithPrecision(
143 precision,
Danil Chapovalov0f9a8e32021-06-11 18:39:17 +0200144 std::make_unique<
145 webrtc_repeating_task_impl::RepeatingTaskImpl<Closure>>(
Henrik Boström27e8a092022-01-24 17:12:35 +0100146 task_queue, precision, first_delay, std::forward<Closure>(closure),
147 clock, alive_flag),
Danil Chapovalov0f9a8e32021-06-11 18:39:17 +0200148 first_delay.ms());
149 return RepeatingTaskHandle(std::move(alive_flag));
Sebastian Janssonecb68972019-01-18 10:30:54 +0100150 }
Sebastian Janssonecb68972019-01-18 10:30:54 +0100151
152 // Stops future invocations of the repeating task closure. Can only be called
153 // from the TaskQueue where the task is running. The closure is guaranteed to
154 // not be running after Stop() returns unless Stop() is called from the
155 // closure itself.
156 void Stop();
157
Danil Chapovalov0f9a8e32021-06-11 18:39:17 +0200158 // Returns true until Stop() was called.
159 // Can only be called from the TaskQueue where the task is running.
Sebastian Janssonecb68972019-01-18 10:30:54 +0100160 bool Running() const;
161
162 private:
163 explicit RepeatingTaskHandle(
Danil Chapovalov0f9a8e32021-06-11 18:39:17 +0200164 rtc::scoped_refptr<PendingTaskSafetyFlag> alive_flag)
165 : repeating_task_(std::move(alive_flag)) {}
166 rtc::scoped_refptr<PendingTaskSafetyFlag> repeating_task_;
Sebastian Janssonecb68972019-01-18 10:30:54 +0100167};
168
169} // namespace webrtc
170#endif // RTC_BASE_TASK_UTILS_REPEATING_TASK_H_