1 /* 2 * Copyright (C) 2017 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_BASE_UNIX_TASK_RUNNER_H_ 18 #define INCLUDE_PERFETTO_BASE_UNIX_TASK_RUNNER_H_ 19 20 #include "perfetto/base/build_config.h" 21 #include "perfetto/base/event.h" 22 #include "perfetto/base/scoped_file.h" 23 #include "perfetto/base/task_runner.h" 24 #include "perfetto/base/thread_checker.h" 25 #include "perfetto/base/thread_utils.h" 26 #include "perfetto/base/time.h" 27 28 #include <poll.h> 29 #include <chrono> 30 #include <deque> 31 #include <map> 32 #include <mutex> 33 #include <vector> 34 35 namespace perfetto { 36 namespace base { 37 38 // Runs a task runner on the current thread. 39 // 40 // Implementation note: we currently assume (and enforce in debug builds) that 41 // Run() is called from the thread that constructed the UnixTaskRunner. This is 42 // not strictly necessary, and we could instead track the thread that invokes 43 // Run(). However, a related property that *might* be important to enforce is 44 // that the destructor runs on the task-running thread. Otherwise, if there are 45 // still-pending tasks at the time of destruction, we would destroy those 46 // outside of the task thread (which might be unexpected to the caller). On the 47 // other hand, the std::function task interface discourages use of any 48 // resource-owning tasks (as the callable needs to be copyable), so this might 49 // not be important in practice. 50 // 51 // TODO(rsavitski): consider adding a thread-check in the destructor, after 52 // auditing existing usages. 53 class UnixTaskRunner : public TaskRunner { 54 public: 55 UnixTaskRunner(); 56 ~UnixTaskRunner() override; 57 58 // Start executing tasks. Doesn't return until Quit() is called. Run() may be 59 // called multiple times on the same task runner. 60 void Run(); 61 void Quit(); 62 63 // Checks whether there are any pending immediate tasks to run. Note that 64 // delayed tasks don't count even if they are due to run. 65 bool IsIdleForTesting(); 66 67 // TaskRunner implementation: 68 void PostTask(std::function<void()>) override; 69 void PostDelayedTask(std::function<void()>, uint32_t delay_ms) override; 70 void AddFileDescriptorWatch(int fd, std::function<void()>) override; 71 void RemoveFileDescriptorWatch(int fd) override; 72 bool RunsTasksOnCurrentThread() const override; 73 74 // Returns true if the task runner is quitting, or has quit and hasn't been 75 // restarted since. Exposed primarily for ThreadTaskRunner, not necessary for 76 // normal use of this class. 77 bool QuitCalled(); 78 79 private: 80 void WakeUp(); 81 82 void UpdateWatchTasksLocked(); 83 84 int GetDelayMsToNextTaskLocked() const; 85 void RunImmediateAndDelayedTask(); 86 void PostFileDescriptorWatches(); 87 void RunFileDescriptorWatch(int fd); 88 89 ThreadChecker thread_checker_; 90 PlatformThreadID created_thread_id_ = GetThreadId(); 91 92 // On Linux, an eventfd(2) used to waking up the task runner when a new task 93 // is posted. Otherwise the read end of a pipe used for the same purpose. 94 Event event_; 95 96 std::vector<struct pollfd> poll_fds_; 97 98 // --- Begin lock-protected members --- 99 100 std::mutex lock_; 101 102 std::deque<std::function<void()>> immediate_tasks_; 103 std::multimap<TimeMillis, std::function<void()>> delayed_tasks_; 104 bool quit_ = false; 105 106 struct WatchTask { 107 std::function<void()> callback; 108 size_t poll_fd_index; // Index into |poll_fds_|. 109 }; 110 111 std::map<int, WatchTask> watch_tasks_; 112 bool watch_tasks_changed_ = false; 113 114 // --- End lock-protected members --- 115 }; 116 117 } // namespace base 118 } // namespace perfetto 119 120 #endif // INCLUDE_PERFETTO_BASE_UNIX_TASK_RUNNER_H_ 121