• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2021 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #ifndef INCLUDE_PERFETTO_EXT_BASE_PERIODIC_TASK_H_
18 #define INCLUDE_PERFETTO_EXT_BASE_PERIODIC_TASK_H_
19 
20 #include <functional>
21 
22 #include "perfetto/ext/base/scoped_file.h"
23 #include "perfetto/ext/base/thread_checker.h"
24 #include "perfetto/ext/base/weak_ptr.h"
25 
26 namespace perfetto {
27 namespace base {
28 
29 class TaskRunner;
30 
31 // A periodic task utility class. It wraps the logic necessary to do periodic
32 // tasks using a TaskRunner, taking care of subtleties like ensuring that
33 // outstanding tasks are cancelled after reset/dtor.
34 // Tasks are aligned on wall time, this is to ensure that when using multiple
35 // periodic tasks, they happen at the same time, minimizing wakeups.
36 // On Linux/Android it also supports suspend-aware mode (via timerfd). On other
37 // operating systems it falls back to PostDelayedTask, which is not
38 // suspend-aware.
39 // TODO(primiano): this should probably become a periodic timer scheduler, so we
40 // can use one FD for everything rather than one FD per task. For now we take
41 // the hit of a FD-per-task to keep this low-risk.
42 class PeriodicTask {
43  public:
44   explicit PeriodicTask(base::TaskRunner*);
45   ~PeriodicTask();  // Calls Reset().
46 
47   struct Args {
48     uint32_t period_ms = 0;
49     std::function<void()> task = nullptr;
50     bool start_first_task_immediately = false;
51     bool use_suspend_aware_timer = false;
52   };
53 
54   void Start(Args);
55 
56   // Safe to be called multiple times, even without calling Start():
57   void Reset();
58 
59   // No copy or move. WeakPtr-wrapped pointers to |this| are posted on the
60   // task runner, this class is not easily movable.
61   PeriodicTask(const PeriodicTask&) = delete;
62   PeriodicTask& operator=(const PeriodicTask&) = delete;
63   PeriodicTask(PeriodicTask&&) = delete;
64   PeriodicTask& operator=(PeriodicTask&&) = delete;
65 
timer_fd_for_testing()66   base::PlatformHandle timer_fd_for_testing() { return *timer_fd_; }
67 
68  private:
69   static void RunTaskAndPostNext(base::WeakPtr<PeriodicTask>,
70                                  uint32_t generation);
71   void PostNextTask();
72   void ResetTimerFd();
73 
74   base::TaskRunner* const task_runner_;
75   Args args_;
76   uint32_t generation_ = 0;
77   base::ScopedPlatformHandle timer_fd_;
78 
79   PERFETTO_THREAD_CHECKER(thread_checker_)
80   base::WeakPtrFactory<PeriodicTask> weak_ptr_factory_;  // Keep last.
81 };
82 
83 }  // namespace base
84 }  // namespace perfetto
85 
86 #endif  // INCLUDE_PERFETTO_EXT_BASE_PERIODIC_TASK_H_
87