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