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 
11 #include "rtc_base/task_utils/repeating_task.h"
12 
13 #include "absl/memory/memory.h"
14 #include "rtc_base/logging.h"
15 #include "rtc_base/task_utils/to_queued_task.h"
16 #include "rtc_base/time_utils.h"
17 
18 namespace webrtc {
19 namespace webrtc_repeating_task_impl {
20 
RepeatingTaskBase(TaskQueueBase * task_queue,TimeDelta first_delay,Clock * clock)21 RepeatingTaskBase::RepeatingTaskBase(TaskQueueBase* task_queue,
22                                      TimeDelta first_delay,
23                                      Clock* clock)
24     : task_queue_(task_queue),
25       clock_(clock),
26       next_run_time_(clock_->CurrentTime() + first_delay) {}
27 
28 RepeatingTaskBase::~RepeatingTaskBase() = default;
29 
Run()30 bool RepeatingTaskBase::Run() {
31   RTC_DCHECK_RUN_ON(task_queue_);
32   // Return true to tell the TaskQueue to destruct this object.
33   if (next_run_time_.IsPlusInfinity())
34     return true;
35 
36   TimeDelta delay = RunClosure();
37 
38   // The closure might have stopped this task, in which case we return true to
39   // destruct this object.
40   if (next_run_time_.IsPlusInfinity())
41     return true;
42 
43   RTC_DCHECK(delay.IsFinite());
44   TimeDelta lost_time = clock_->CurrentTime() - next_run_time_;
45   next_run_time_ += delay;
46   delay -= lost_time;
47   delay = std::max(delay, TimeDelta::Zero());
48 
49   task_queue_->PostDelayedTask(absl::WrapUnique(this), delay.ms());
50 
51   // Return false to tell the TaskQueue to not destruct this object since we
52   // have taken ownership with absl::WrapUnique.
53   return false;
54 }
55 
Stop()56 void RepeatingTaskBase::Stop() {
57   RTC_DCHECK_RUN_ON(task_queue_);
58   RTC_DCHECK(next_run_time_.IsFinite());
59   next_run_time_ = Timestamp::PlusInfinity();
60 }
61 
62 }  // namespace webrtc_repeating_task_impl
63 
RepeatingTaskHandle(RepeatingTaskHandle && other)64 RepeatingTaskHandle::RepeatingTaskHandle(RepeatingTaskHandle&& other)
65     : repeating_task_(other.repeating_task_) {
66   other.repeating_task_ = nullptr;
67 }
68 
operator =(RepeatingTaskHandle && other)69 RepeatingTaskHandle& RepeatingTaskHandle::operator=(
70     RepeatingTaskHandle&& other) {
71   repeating_task_ = other.repeating_task_;
72   other.repeating_task_ = nullptr;
73   return *this;
74 }
75 
RepeatingTaskHandle(webrtc_repeating_task_impl::RepeatingTaskBase * repeating_task)76 RepeatingTaskHandle::RepeatingTaskHandle(
77     webrtc_repeating_task_impl::RepeatingTaskBase* repeating_task)
78     : repeating_task_(repeating_task) {}
79 
Stop()80 void RepeatingTaskHandle::Stop() {
81   if (repeating_task_) {
82     repeating_task_->Stop();
83     repeating_task_ = nullptr;
84   }
85 }
86 
Running() const87 bool RepeatingTaskHandle::Running() const {
88   return repeating_task_ != nullptr;
89 }
90 
91 }  // namespace webrtc
92