blob: 4c9983c3497db25e6d21de4bffc35a9bdf991bae [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,
37 TimeDelta first_delay,
Danil Chapovalov0f9a8e32021-06-11 18:39:17 +020038 Clock* clock,
39 rtc::scoped_refptr<PendingTaskSafetyFlag> alive_flag);
Sebastian Janssonecb68972019-01-18 10:30:54 +010040 ~RepeatingTaskBase() override;
Tommia0a44802020-05-13 18:27:26 +020041
Sebastian Janssonecb68972019-01-18 10:30:54 +010042 private:
Tommia0a44802020-05-13 18:27:26 +020043 virtual TimeDelta RunClosure() = 0;
Sebastian Janssonecb68972019-01-18 10:30:54 +010044
45 bool Run() final;
Sebastian Janssonecb68972019-01-18 10:30:54 +010046
Danil Chapovalov4423c362019-03-06 18:41:39 +010047 TaskQueueBase* const task_queue_;
Tommi532cac52020-05-18 14:53:42 +020048 Clock* const clock_;
Danil Chapovalov0f9a8e32021-06-11 18:39:17 +020049 // This is always finite.
Tommi29a5fe82020-05-15 10:12:36 +020050 Timestamp next_run_time_ RTC_GUARDED_BY(task_queue_);
Danil Chapovalov0f9a8e32021-06-11 18:39:17 +020051 rtc::scoped_refptr<PendingTaskSafetyFlag> alive_flag_
52 RTC_GUARDED_BY(task_queue_);
Sebastian Janssonecb68972019-01-18 10:30:54 +010053};
54
Niels Möller902b5542022-01-17 15:20:24 +010055// The template closure pattern is based on rtc::ClosureTask. The provided
56// closure should have a TimeDelta return value, specifing the desired
57// non-negative interval to next repetition, or TimeDelta::PlusInfinity to
58// indicate that the task should be deleted and not called again.
Sebastian Janssonecb68972019-01-18 10:30:54 +010059template <class Closure>
60class RepeatingTaskImpl final : public RepeatingTaskBase {
61 public:
Danil Chapovalov4423c362019-03-06 18:41:39 +010062 RepeatingTaskImpl(TaskQueueBase* task_queue,
Sebastian Janssonecb68972019-01-18 10:30:54 +010063 TimeDelta first_delay,
Tommi532cac52020-05-18 14:53:42 +020064 Closure&& closure,
Danil Chapovalov0f9a8e32021-06-11 18:39:17 +020065 Clock* clock,
66 rtc::scoped_refptr<PendingTaskSafetyFlag> alive_flag)
67 : RepeatingTaskBase(task_queue,
68 first_delay,
69 clock,
70 std::move(alive_flag)),
Sebastian Janssonecb68972019-01-18 10:30:54 +010071 closure_(std::forward<Closure>(closure)) {
72 static_assert(
73 std::is_same<TimeDelta,
74 typename std::result_of<decltype (&Closure::operator())(
75 Closure)>::type>::value,
76 "");
77 }
78
Tommia0a44802020-05-13 18:27:26 +020079 private:
Markus Handellc1c6bef2021-07-23 11:11:32 +020080 TimeDelta RunClosure() override {
81 RepeatingTaskImplDTraceProbeRun();
82 return closure_();
83 }
Sebastian Janssonecb68972019-01-18 10:30:54 +010084
Sebastian Janssonecb68972019-01-18 10:30:54 +010085 typename std::remove_const<
86 typename std::remove_reference<Closure>::type>::type closure_;
87};
88} // namespace webrtc_repeating_task_impl
89
90// Allows starting tasks that repeat themselves on a TaskQueue indefinately
91// until they are stopped or the TaskQueue is destroyed. It allows starting and
92// stopping multiple times, but you must stop one task before starting another
93// and it can only be stopped when in the running state. The public interface is
94// not thread safe.
95class RepeatingTaskHandle {
96 public:
Sebastian Jansson46b4a0f2019-03-26 15:24:23 +010097 RepeatingTaskHandle() = default;
98 ~RepeatingTaskHandle() = default;
Danil Chapovalov0f9a8e32021-06-11 18:39:17 +020099 RepeatingTaskHandle(RepeatingTaskHandle&& other) = default;
100 RepeatingTaskHandle& operator=(RepeatingTaskHandle&& other) = default;
Sebastian Janssonecb68972019-01-18 10:30:54 +0100101 RepeatingTaskHandle(const RepeatingTaskHandle&) = delete;
102 RepeatingTaskHandle& operator=(const RepeatingTaskHandle&) = delete;
103
104 // Start can be used to start a task that will be reposted with a delay
105 // determined by the return value of the provided closure. The actual task is
106 // owned by the TaskQueue and will live until it has been stopped or the
Danil Chapovalov0f9a8e32021-06-11 18:39:17 +0200107 // TaskQueue deletes it. It's perfectly fine to destroy the handle while the
108 // task is running, since the repeated task is owned by the TaskQueue.
Sebastian Janssonecb68972019-01-18 10:30:54 +0100109 template <class Closure>
Danil Chapovalov4423c362019-03-06 18:41:39 +0100110 static RepeatingTaskHandle Start(TaskQueueBase* task_queue,
Tommi532cac52020-05-18 14:53:42 +0200111 Closure&& closure,
112 Clock* clock = Clock::GetRealTimeClock()) {
Danil Chapovalov0f9a8e32021-06-11 18:39:17 +0200113 auto alive_flag = PendingTaskSafetyFlag::CreateDetached();
Markus Handellc1c6bef2021-07-23 11:11:32 +0200114 webrtc_repeating_task_impl::RepeatingTaskHandleDTraceProbeStart();
Danil Chapovalov0f9a8e32021-06-11 18:39:17 +0200115 task_queue->PostTask(
116 std::make_unique<
117 webrtc_repeating_task_impl::RepeatingTaskImpl<Closure>>(
118 task_queue, TimeDelta::Zero(), std::forward<Closure>(closure),
119 clock, alive_flag));
120 return RepeatingTaskHandle(std::move(alive_flag));
Sebastian Janssonecb68972019-01-18 10:30:54 +0100121 }
Sebastian Janssonecb68972019-01-18 10:30:54 +0100122
123 // DelayedStart is equivalent to Start except that the first invocation of the
124 // closure will be delayed by the given amount.
125 template <class Closure>
Tommi532cac52020-05-18 14:53:42 +0200126 static RepeatingTaskHandle DelayedStart(
127 TaskQueueBase* task_queue,
128 TimeDelta first_delay,
129 Closure&& closure,
130 Clock* clock = Clock::GetRealTimeClock()) {
Danil Chapovalov0f9a8e32021-06-11 18:39:17 +0200131 auto alive_flag = PendingTaskSafetyFlag::CreateDetached();
Markus Handellc1c6bef2021-07-23 11:11:32 +0200132 webrtc_repeating_task_impl::RepeatingTaskHandleDTraceProbeDelayedStart();
Danil Chapovalov0f9a8e32021-06-11 18:39:17 +0200133 task_queue->PostDelayedTask(
134 std::make_unique<
135 webrtc_repeating_task_impl::RepeatingTaskImpl<Closure>>(
136 task_queue, first_delay, std::forward<Closure>(closure), clock,
137 alive_flag),
138 first_delay.ms());
139 return RepeatingTaskHandle(std::move(alive_flag));
Sebastian Janssonecb68972019-01-18 10:30:54 +0100140 }
Sebastian Janssonecb68972019-01-18 10:30:54 +0100141
142 // Stops future invocations of the repeating task closure. Can only be called
143 // from the TaskQueue where the task is running. The closure is guaranteed to
144 // not be running after Stop() returns unless Stop() is called from the
145 // closure itself.
146 void Stop();
147
Danil Chapovalov0f9a8e32021-06-11 18:39:17 +0200148 // Returns true until Stop() was called.
149 // Can only be called from the TaskQueue where the task is running.
Sebastian Janssonecb68972019-01-18 10:30:54 +0100150 bool Running() const;
151
152 private:
153 explicit RepeatingTaskHandle(
Danil Chapovalov0f9a8e32021-06-11 18:39:17 +0200154 rtc::scoped_refptr<PendingTaskSafetyFlag> alive_flag)
155 : repeating_task_(std::move(alive_flag)) {}
156 rtc::scoped_refptr<PendingTaskSafetyFlag> repeating_task_;
Sebastian Janssonecb68972019-01-18 10:30:54 +0100157};
158
159} // namespace webrtc
160#endif // RTC_BASE_TASK_UTILS_REPEATING_TASK_H_