blob: 91a40e0714ea72966e162552ea2fb7745e71a0f9 [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
55// The template closure pattern is based on rtc::ClosureTask.
56template <class Closure>
57class RepeatingTaskImpl final : public RepeatingTaskBase {
58 public:
Danil Chapovalov4423c362019-03-06 18:41:39 +010059 RepeatingTaskImpl(TaskQueueBase* task_queue,
Sebastian Janssonecb68972019-01-18 10:30:54 +010060 TimeDelta first_delay,
Tommi532cac52020-05-18 14:53:42 +020061 Closure&& closure,
Danil Chapovalov0f9a8e32021-06-11 18:39:17 +020062 Clock* clock,
63 rtc::scoped_refptr<PendingTaskSafetyFlag> alive_flag)
64 : RepeatingTaskBase(task_queue,
65 first_delay,
66 clock,
67 std::move(alive_flag)),
Sebastian Janssonecb68972019-01-18 10:30:54 +010068 closure_(std::forward<Closure>(closure)) {
69 static_assert(
70 std::is_same<TimeDelta,
71 typename std::result_of<decltype (&Closure::operator())(
72 Closure)>::type>::value,
73 "");
74 }
75
Tommia0a44802020-05-13 18:27:26 +020076 private:
Markus Handellc1c6bef2021-07-23 11:11:32 +020077 TimeDelta RunClosure() override {
78 RepeatingTaskImplDTraceProbeRun();
79 return closure_();
80 }
Sebastian Janssonecb68972019-01-18 10:30:54 +010081
Sebastian Janssonecb68972019-01-18 10:30:54 +010082 typename std::remove_const<
83 typename std::remove_reference<Closure>::type>::type closure_;
84};
85} // namespace webrtc_repeating_task_impl
86
87// Allows starting tasks that repeat themselves on a TaskQueue indefinately
88// until they are stopped or the TaskQueue is destroyed. It allows starting and
89// stopping multiple times, but you must stop one task before starting another
90// and it can only be stopped when in the running state. The public interface is
91// not thread safe.
92class RepeatingTaskHandle {
93 public:
Sebastian Jansson46b4a0f2019-03-26 15:24:23 +010094 RepeatingTaskHandle() = default;
95 ~RepeatingTaskHandle() = default;
Danil Chapovalov0f9a8e32021-06-11 18:39:17 +020096 RepeatingTaskHandle(RepeatingTaskHandle&& other) = default;
97 RepeatingTaskHandle& operator=(RepeatingTaskHandle&& other) = default;
Sebastian Janssonecb68972019-01-18 10:30:54 +010098 RepeatingTaskHandle(const RepeatingTaskHandle&) = delete;
99 RepeatingTaskHandle& operator=(const RepeatingTaskHandle&) = delete;
100
101 // Start can be used to start a task that will be reposted with a delay
102 // determined by the return value of the provided closure. The actual task is
103 // owned by the TaskQueue and will live until it has been stopped or the
Danil Chapovalov0f9a8e32021-06-11 18:39:17 +0200104 // TaskQueue deletes it. It's perfectly fine to destroy the handle while the
105 // task is running, since the repeated task is owned by the TaskQueue.
Sebastian Janssonecb68972019-01-18 10:30:54 +0100106 template <class Closure>
Danil Chapovalov4423c362019-03-06 18:41:39 +0100107 static RepeatingTaskHandle Start(TaskQueueBase* task_queue,
Tommi532cac52020-05-18 14:53:42 +0200108 Closure&& closure,
109 Clock* clock = Clock::GetRealTimeClock()) {
Danil Chapovalov0f9a8e32021-06-11 18:39:17 +0200110 auto alive_flag = PendingTaskSafetyFlag::CreateDetached();
Markus Handellc1c6bef2021-07-23 11:11:32 +0200111 webrtc_repeating_task_impl::RepeatingTaskHandleDTraceProbeStart();
Danil Chapovalov0f9a8e32021-06-11 18:39:17 +0200112 task_queue->PostTask(
113 std::make_unique<
114 webrtc_repeating_task_impl::RepeatingTaskImpl<Closure>>(
115 task_queue, TimeDelta::Zero(), std::forward<Closure>(closure),
116 clock, alive_flag));
117 return RepeatingTaskHandle(std::move(alive_flag));
Sebastian Janssonecb68972019-01-18 10:30:54 +0100118 }
Sebastian Janssonecb68972019-01-18 10:30:54 +0100119
120 // DelayedStart is equivalent to Start except that the first invocation of the
121 // closure will be delayed by the given amount.
122 template <class Closure>
Tommi532cac52020-05-18 14:53:42 +0200123 static RepeatingTaskHandle DelayedStart(
124 TaskQueueBase* task_queue,
125 TimeDelta first_delay,
126 Closure&& closure,
127 Clock* clock = Clock::GetRealTimeClock()) {
Danil Chapovalov0f9a8e32021-06-11 18:39:17 +0200128 auto alive_flag = PendingTaskSafetyFlag::CreateDetached();
Markus Handellc1c6bef2021-07-23 11:11:32 +0200129 webrtc_repeating_task_impl::RepeatingTaskHandleDTraceProbeDelayedStart();
Danil Chapovalov0f9a8e32021-06-11 18:39:17 +0200130 task_queue->PostDelayedTask(
131 std::make_unique<
132 webrtc_repeating_task_impl::RepeatingTaskImpl<Closure>>(
133 task_queue, first_delay, std::forward<Closure>(closure), clock,
134 alive_flag),
135 first_delay.ms());
136 return RepeatingTaskHandle(std::move(alive_flag));
Sebastian Janssonecb68972019-01-18 10:30:54 +0100137 }
Sebastian Janssonecb68972019-01-18 10:30:54 +0100138
139 // Stops future invocations of the repeating task closure. Can only be called
140 // from the TaskQueue where the task is running. The closure is guaranteed to
141 // not be running after Stop() returns unless Stop() is called from the
142 // closure itself.
143 void Stop();
144
Danil Chapovalov0f9a8e32021-06-11 18:39:17 +0200145 // Returns true until Stop() was called.
146 // Can only be called from the TaskQueue where the task is running.
Sebastian Janssonecb68972019-01-18 10:30:54 +0100147 bool Running() const;
148
149 private:
150 explicit RepeatingTaskHandle(
Danil Chapovalov0f9a8e32021-06-11 18:39:17 +0200151 rtc::scoped_refptr<PendingTaskSafetyFlag> alive_flag)
152 : repeating_task_(std::move(alive_flag)) {}
153 rtc::scoped_refptr<PendingTaskSafetyFlag> repeating_task_;
Sebastian Janssonecb68972019-01-18 10:30:54 +0100154};
155
156} // namespace webrtc
157#endif // RTC_BASE_TASK_UTILS_REPEATING_TASK_H_