xref: /aosp_15_r20/external/cronet/base/memory/post_delayed_memory_reduction_task.cc (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
1 // Copyright 2024 The Chromium Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #include "base/memory/post_delayed_memory_reduction_task.h"
6 
7 #include "base/timer/timer.h"
8 
9 #if BUILDFLAG(IS_ANDROID)
10 #include "base/android/pre_freeze_background_memory_trimmer.h"
11 #endif
12 
13 namespace base {
14 
PostDelayedMemoryReductionTask(scoped_refptr<SequencedTaskRunner> task_runner,const Location & from_here,OnceClosure task,base::TimeDelta delay)15 void PostDelayedMemoryReductionTask(
16     scoped_refptr<SequencedTaskRunner> task_runner,
17     const Location& from_here,
18     OnceClosure task,
19     base::TimeDelta delay) {
20 #if BUILDFLAG(IS_ANDROID)
21   android::PreFreezeBackgroundMemoryTrimmer::PostDelayedBackgroundTask(
22       std::move(task_runner), from_here, std::move(task), delay);
23 #else
24   task_runner->PostDelayedTask(from_here, std::move(task), delay);
25 #endif
26 }
27 
PostDelayedMemoryReductionTask(scoped_refptr<SequencedTaskRunner> task_runner,const Location & from_here,OnceCallback<void (MemoryReductionTaskContext)> task,base::TimeDelta delay)28 void PostDelayedMemoryReductionTask(
29     scoped_refptr<SequencedTaskRunner> task_runner,
30     const Location& from_here,
31     OnceCallback<void(MemoryReductionTaskContext)> task,
32     base::TimeDelta delay) {
33 #if BUILDFLAG(IS_ANDROID)
34   android::PreFreezeBackgroundMemoryTrimmer::PostDelayedBackgroundTask(
35       std::move(task_runner), from_here, std::move(task), delay);
36 #else
37   task_runner->PostDelayedTask(
38       from_here,
39       BindOnce(std::move(task), MemoryReductionTaskContext::kDelayExpired),
40       delay);
41 #endif  // BUILDFLAG(IS_ANDROID)
42 }
43 
44 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
45  *                                                                           *
46  *                OneShotDelayedBackgroundTimer::TimerImpl                   *
47  *                                                                           *
48  * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
49 
50 // This implementation is just a small wrapper around a |base::OneShotTimer|.
51 class OneShotDelayedBackgroundTimer::TimerImpl final
52     : public OneShotDelayedBackgroundTimer::OneShotDelayedBackgroundTimerImpl {
53  public:
54   ~TimerImpl() override = default;
Start(const Location & from_here,TimeDelta delay,OnceCallback<void (MemoryReductionTaskContext)> task)55   void Start(const Location& from_here,
56              TimeDelta delay,
57              OnceCallback<void(MemoryReductionTaskContext)> task) override {
58     timer_.Start(
59         from_here, delay,
60         BindOnce(std::move(task), MemoryReductionTaskContext::kDelayExpired));
61   }
Stop()62   void Stop() override { timer_.Stop(); }
IsRunning() const63   bool IsRunning() const override { return timer_.IsRunning(); }
SetTaskRunner(scoped_refptr<SequencedTaskRunner> task_runner)64   void SetTaskRunner(scoped_refptr<SequencedTaskRunner> task_runner) override {
65     timer_.SetTaskRunner(std::move(task_runner));
66   }
67 
68  private:
69   OneShotTimer timer_;
70 };
71 
72 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
73  *                                                                           *
74  *                                TaskImpl                                   *
75  *                                                                           *
76  * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
77 
78 #if BUILDFLAG(IS_ANDROID)
79 class OneShotDelayedBackgroundTimer::TaskImpl final
80     : public OneShotDelayedBackgroundTimer::OneShotDelayedBackgroundTimerImpl {
81  public:
82   ~TaskImpl() override = default;
Start(const Location & from_here,TimeDelta delay,OnceCallback<void (MemoryReductionTaskContext)> task)83   void Start(const Location& from_here,
84              TimeDelta delay,
85              OnceCallback<void(MemoryReductionTaskContext)> task) override {
86     this->StartInternal(
87         from_here, delay,
88         BindOnce(
89             [](TaskImpl* timer,
90                OnceCallback<void(MemoryReductionTaskContext)> task,
91                MemoryReductionTaskContext in_pre_freeze) {
92               std::move(task).Run(in_pre_freeze);
93               timer->task_ = nullptr;
94             },
95             // |base::Unretained(this)| is safe here because destroying this
96             // will cancel the task. We do not need to worry about race
97             // conditions here because destruction should always happen on the
98             // same thread that the task is started on.
99             base::Unretained(this), std::move(task)));
100   }
StartInternal(const Location & from_here,TimeDelta delay,OnceCallback<void (MemoryReductionTaskContext)> task)101   void StartInternal(const Location& from_here,
102                      TimeDelta delay,
103                      OnceCallback<void(MemoryReductionTaskContext)> task) {
104     if (IsRunning()) {
105       Stop();
106     }
107     DCHECK(GetTaskRunner()->RunsTasksInCurrentSequence());
108     base::AutoLock locker(
109         android::PreFreezeBackgroundMemoryTrimmer::Instance().lock_);
110     task_ = android::PreFreezeBackgroundMemoryTrimmer::Instance()
111                 .PostDelayedBackgroundTaskModernHelper(
112                     GetTaskRunner(), from_here, std::move(task), delay);
113   }
Stop()114   void Stop() override {
115     if (IsRunning()) {
116       task_.ExtractAsDangling()->CancelTask();
117     }
118   }
IsRunning() const119   bool IsRunning() const override { return task_ != nullptr; }
SetTaskRunner(scoped_refptr<SequencedTaskRunner> task_runner)120   void SetTaskRunner(scoped_refptr<SequencedTaskRunner> task_runner) override {
121     task_runner_ = task_runner;
122   }
123 
124  private:
GetTaskRunner()125   scoped_refptr<SequencedTaskRunner> GetTaskRunner() {
126     // This matches the semantics of |OneShotTimer::GetTaskRunner()|.
127     return task_runner_ ? task_runner_
128                         : SequencedTaskRunner::GetCurrentDefault();
129   }
130 
131   raw_ptr<android::PreFreezeBackgroundMemoryTrimmer::BackgroundTask> task_ =
132       nullptr;
133   scoped_refptr<SequencedTaskRunner> task_runner_ = nullptr;
134 };
135 #endif
136 
137 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
138  *                                                                           *
139  *                       OneShotDelayedBackgroundTimer                       *
140  *                                                                           *
141  * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
142 
OneShotDelayedBackgroundTimer()143 OneShotDelayedBackgroundTimer::OneShotDelayedBackgroundTimer() {
144 #if BUILDFLAG(IS_ANDROID)
145   if (android::PreFreezeBackgroundMemoryTrimmer::ShouldUseModernTrim()) {
146     impl_ = std::make_unique<TaskImpl>();
147   } else {
148     impl_ = std::make_unique<TimerImpl>();
149   }
150 #else
151   impl_ = std::make_unique<TimerImpl>();
152 #endif
153 }
154 
~OneShotDelayedBackgroundTimer()155 OneShotDelayedBackgroundTimer::~OneShotDelayedBackgroundTimer() {
156   Stop();
157 }
158 
Stop()159 void OneShotDelayedBackgroundTimer::Stop() {
160   impl_->Stop();
161 }
162 
IsRunning() const163 bool OneShotDelayedBackgroundTimer::IsRunning() const {
164   return impl_->IsRunning();
165 }
166 
SetTaskRunner(scoped_refptr<SequencedTaskRunner> task_runner)167 void OneShotDelayedBackgroundTimer::SetTaskRunner(
168     scoped_refptr<SequencedTaskRunner> task_runner) {
169   impl_->SetTaskRunner(std::move(task_runner));
170 }
171 
Start(const Location & from_here,TimeDelta delay,OnceCallback<void (MemoryReductionTaskContext)> task)172 void OneShotDelayedBackgroundTimer::Start(
173     const Location& from_here,
174     TimeDelta delay,
175     OnceCallback<void(MemoryReductionTaskContext)> task) {
176 #if BUILDFLAG(IS_ANDROID)
177   android::PreFreezeBackgroundMemoryTrimmer::SetDidRegisterTask();
178 #endif
179   impl_->Start(from_here, delay, std::move(task));
180 }
181 
182 }  // namespace base
183