1 // Copyright 2018 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 #ifndef BASE_TASK_CURRENT_THREAD_H_ 6 #define BASE_TASK_CURRENT_THREAD_H_ 7 8 #include <ostream> 9 10 #include "base/base_export.h" 11 #include "base/check.h" 12 #include "base/functional/callback_forward.h" 13 #include "base/memory/raw_ptr.h" 14 #include "base/memory/scoped_refptr.h" 15 #include "base/message_loop/ios_cronet_buildflags.h" 16 #include "base/message_loop/message_pump_for_io.h" 17 #include "base/message_loop/message_pump_for_ui.h" 18 #include "base/pending_task.h" 19 #include "base/task/sequence_manager/task_time_observer.h" 20 #include "base/task/single_thread_task_runner.h" 21 #include "base/task/task_observer.h" 22 #include "build/build_config.h" 23 24 namespace web { 25 class WebTaskEnvironment; 26 } 27 28 namespace base { 29 30 namespace sequence_manager { 31 namespace internal { 32 class SequenceManagerImpl; 33 } 34 } // namespace sequence_manager 35 36 // CurrentThread is a proxy to a subset of Task related APIs bound to the 37 // current thread 38 // 39 // Current(UI|IO)Thread is available statically through 40 // Current(UI|IO)Thread::Get() on threads that have registered as CurrentThread 41 // on this physical thread (e.g. by using SingleThreadTaskExecutor). APIs 42 // intended for all consumers on the thread should be on Current(UI|IO)Thread, 43 // while internal APIs might be on multiple internal classes (e.g. 44 // SequenceManager). 45 // 46 // Why: Historically MessageLoop would take care of everything related to event 47 // processing on a given thread. Nowadays that functionality is split among 48 // different classes. At that time MessageLoop::current() gave access to the 49 // full MessageLoop API, preventing both addition of powerful owner-only APIs as 50 // well as making it harder to remove callers of deprecated APIs (that need to 51 // stick around for a few owner-only use cases and re-accrue callers after 52 // cleanup per remaining publicly available). 53 // 54 // As such, many methods below are flagged as deprecated and should be removed 55 // once all static callers have been migrated. 56 class BASE_EXPORT CurrentThread { 57 public: 58 // CurrentThread is effectively just a disguised pointer and is fine to 59 // copy/move around. 60 CurrentThread(const CurrentThread& other) = default; 61 CurrentThread(CurrentThread&& other) = default; 62 CurrentThread& operator=(const CurrentThread& other) = default; 63 64 bool operator==(const CurrentThread& other) const; 65 66 // Returns a proxy object to interact with the Task related APIs for the 67 // current thread. It must only be used on the thread it was obtained. 68 static CurrentThread Get(); 69 70 // Return an empty CurrentThread. No methods should be called on this 71 // object. 72 static CurrentThread GetNull(); 73 74 // Returns true if the current thread is registered to expose CurrentThread 75 // API. Prefer this to verifying the boolean value of Get() (so that Get() can 76 // ultimately DCHECK it's only invoked when IsSet()). 77 static bool IsSet(); 78 79 // Allow CurrentThread to be used like a pointer to support the many 80 // callsites that used MessageLoop::current() that way when it was a 81 // MessageLoop*. 82 CurrentThread* operator->() { return this; } 83 explicit operator bool() const { return !!current_; } 84 85 // A DestructionObserver is notified when the current task execution 86 // environment is being destroyed. These observers are notified prior to 87 // CurrentThread::IsSet() being changed to return false. This gives interested 88 // parties the chance to do final cleanup. 89 // 90 // NOTE: Any tasks posted to the current thread during this notification will 91 // not be run. Instead, they will be deleted. 92 // 93 // Deprecation note: Prefer SequenceLocalStorageSlot<std::unique_ptr<Foo>> to 94 // DestructionObserver to bind an object's lifetime to the current 95 // thread/sequence. 96 class BASE_EXPORT DestructionObserver { 97 public: 98 // TODO(https://crbug.com/891670): Rename to 99 // WillDestroyCurrentTaskExecutionEnvironment 100 virtual void WillDestroyCurrentMessageLoop() = 0; 101 102 protected: 103 virtual ~DestructionObserver() = default; 104 }; 105 106 // Add a DestructionObserver, which will start receiving notifications 107 // immediately. 108 void AddDestructionObserver(DestructionObserver* destruction_observer); 109 110 // Remove a DestructionObserver. It is safe to call this method while a 111 // DestructionObserver is receiving a notification callback. 112 void RemoveDestructionObserver(DestructionObserver* destruction_observer); 113 114 // Forwards to SequenceManager::SetTaskRunner(). 115 // DEPRECATED(https://crbug.com/825327): only owners of the SequenceManager 116 // instance should replace its TaskRunner. 117 void SetTaskRunner(scoped_refptr<SingleThreadTaskRunner> task_runner); 118 119 // Forwards to SequenceManager::(Add|Remove)TaskObserver. 120 // DEPRECATED(https://crbug.com/825327): only owners of the SequenceManager 121 // instance should add task observers on it. 122 void AddTaskObserver(TaskObserver* task_observer); 123 void RemoveTaskObserver(TaskObserver* task_observer); 124 125 // When this functionality is enabled, the queue time will be recorded for 126 // posted tasks. 127 void SetAddQueueTimeToTasks(bool enable); 128 129 // Registers a OnceClosure to be called on this thread the next time it goes 130 // idle. This is meant for internal usage; callers should use BEST_EFFORT 131 // tasks instead of this for generic work that needs to wait until quiescence 132 // to run. There can only be one OnNextIdleCallback at a time. Can be called 133 // with a null callback to clear any potentially pending callbacks. 134 void RegisterOnNextIdleCallback(OnceClosure on_next_idle_callback); 135 136 // Enables nested task processing in scope of an upcoming native message loop. 137 // Some unwanted message loops may occur when using common controls or printer 138 // functions. Hence, nested task processing is disabled by default to avoid 139 // unplanned reentrancy. This re-enables it in cases where the stack is 140 // reentrancy safe and processing nestable tasks is explicitly safe. 141 // 142 // For instance, 143 // - The current thread is running a message loop. 144 // - It receives a task #1 and executes it. 145 // - The task #1 implicitly starts a nested message loop, like a MessageBox in 146 // the unit test. This can also be StartDoc or GetSaveFileName. 147 // - The thread receives a task #2 before or while in this second message 148 // loop. 149 // - With NestableTasksAllowed set to true, the task #2 will run right away. 150 // Otherwise, it will get executed right after task #1 completes at "thread 151 // message loop level". 152 // 153 // Use RunLoop::Type::kNestableTasksAllowed when nesting is triggered by the 154 // application RunLoop rather than by native code. 155 class BASE_EXPORT ScopedAllowApplicationTasksInNativeNestedLoop { 156 public: 157 ScopedAllowApplicationTasksInNativeNestedLoop(); 158 ~ScopedAllowApplicationTasksInNativeNestedLoop(); 159 160 private: 161 const raw_ptr<sequence_manager::internal::SequenceManagerImpl> 162 sequence_manager_; 163 const bool previous_state_; 164 }; 165 166 // Returns true if nestable tasks are allowed on the current thread at this 167 // time (i.e. if a native nested loop would start from the callee's point in 168 // the stack, would it be allowed to run application tasks). 169 bool ApplicationTasksAllowedInNativeNestedLoop() const; 170 171 // Returns true if this instance is bound to the current thread. 172 bool IsBoundToCurrentThread() const; 173 174 // Returns true if the current thread is idle (ignoring delayed tasks). This 175 // is the same condition which triggers DoWork() to return false: i.e. out of 176 // tasks which can be processed at the current run-level -- there might be 177 // deferred non-nestable tasks remaining if currently in a nested run level. 178 bool IsIdleForTesting(); 179 180 // Enables ThreadControllerWithMessagePumpImpl's TimeKeeper metrics. 181 // `thread_name` will be used as a suffix. 182 void EnableMessagePumpTimeKeeperMetrics(const char* thread_name); 183 184 protected: CurrentThread(sequence_manager::internal::SequenceManagerImpl * sequence_manager)185 explicit CurrentThread( 186 sequence_manager::internal::SequenceManagerImpl* sequence_manager) 187 : current_(sequence_manager) {} 188 189 static sequence_manager::internal::SequenceManagerImpl* 190 GetCurrentSequenceManagerImpl(); 191 192 friend class MessagePumpLibeventTest; 193 friend class ScheduleWorkTest; 194 friend class Thread; 195 friend class sequence_manager::internal::SequenceManagerImpl; 196 friend class MessageLoopTaskRunnerTest; 197 friend class web::WebTaskEnvironment; 198 199 raw_ptr<sequence_manager::internal::SequenceManagerImpl> current_; 200 }; 201 202 #if !BUILDFLAG(IS_NACL) 203 204 // UI extension of CurrentThread. 205 class BASE_EXPORT CurrentUIThread : public CurrentThread { 206 public: 207 // Returns an interface for the CurrentUIThread of the current thread. 208 // Asserts that IsSet(). 209 static CurrentUIThread Get(); 210 211 // Returns true if the current thread is running a CurrentUIThread. 212 static bool IsSet(); 213 214 CurrentUIThread* operator->() { return this; } 215 216 #if BUILDFLAG(IS_OZONE) && !BUILDFLAG(IS_FUCHSIA) && !BUILDFLAG(IS_WIN) 217 static_assert( 218 std::is_base_of<WatchableIOMessagePumpPosix, MessagePumpForUI>::value, 219 "CurrentThreadForUI::WatchFileDescriptor is supported only" 220 "by MessagePumpLibevent and MessagePumpGlib implementations."); 221 bool WatchFileDescriptor(int fd, 222 bool persistent, 223 MessagePumpForUI::Mode mode, 224 MessagePumpForUI::FdWatchController* controller, 225 MessagePumpForUI::FdWatcher* delegate); 226 #endif 227 228 #if BUILDFLAG(IS_IOS) 229 // Forwards to SequenceManager::Attach(). 230 // TODO(https://crbug.com/825327): Plumb the actual SequenceManager* to 231 // callers and remove ability to access this method from 232 // CurrentUIThread. 233 void Attach(); 234 #endif 235 236 #if BUILDFLAG(IS_ANDROID) 237 // Forwards to MessagePumpForUI::Abort(). 238 // TODO(https://crbug.com/825327): Plumb the actual MessagePumpForUI* to 239 // callers and remove ability to access this method from 240 // CurrentUIThread. 241 void Abort(); 242 #endif 243 244 #if BUILDFLAG(IS_WIN) 245 void AddMessagePumpObserver(MessagePumpForUI::Observer* observer); 246 void RemoveMessagePumpObserver(MessagePumpForUI::Observer* observer); 247 #endif 248 249 private: CurrentUIThread(sequence_manager::internal::SequenceManagerImpl * current)250 explicit CurrentUIThread( 251 sequence_manager::internal::SequenceManagerImpl* current) 252 : CurrentThread(current) {} 253 254 MessagePumpForUI* GetMessagePumpForUI() const; 255 }; 256 257 #endif // !BUILDFLAG(IS_NACL) 258 259 // ForIO extension of CurrentThread. 260 class BASE_EXPORT CurrentIOThread : public CurrentThread { 261 public: 262 // Returns an interface for the CurrentIOThread of the current thread. 263 // Asserts that IsSet(). 264 static CurrentIOThread Get(); 265 266 // Returns true if the current thread is running a CurrentIOThread. 267 static bool IsSet(); 268 269 CurrentIOThread* operator->() { return this; } 270 271 #if !BUILDFLAG(IS_NACL) 272 273 #if BUILDFLAG(IS_WIN) 274 // Please see MessagePumpWin for definitions of these methods. 275 HRESULT RegisterIOHandler(HANDLE file, MessagePumpForIO::IOHandler* handler); 276 bool RegisterJobObject(HANDLE job, MessagePumpForIO::IOHandler* handler); 277 #elif BUILDFLAG(IS_POSIX) || BUILDFLAG(IS_FUCHSIA) 278 // Please see WatchableIOMessagePumpPosix for definition. 279 // Prefer base::FileDescriptorWatcher for non-critical IO. 280 bool WatchFileDescriptor(int fd, 281 bool persistent, 282 MessagePumpForIO::Mode mode, 283 MessagePumpForIO::FdWatchController* controller, 284 MessagePumpForIO::FdWatcher* delegate); 285 #endif // BUILDFLAG(IS_WIN) 286 287 #if BUILDFLAG(IS_MAC) || (BUILDFLAG(IS_IOS) && !BUILDFLAG(CRONET_BUILD)) 288 bool WatchMachReceivePort( 289 mach_port_t port, 290 MessagePumpForIO::MachPortWatchController* controller, 291 MessagePumpForIO::MachPortWatcher* delegate); 292 #endif 293 294 #if BUILDFLAG(IS_FUCHSIA) 295 // Additional watch API for native platform resources. 296 bool WatchZxHandle(zx_handle_t handle, 297 bool persistent, 298 zx_signals_t signals, 299 MessagePumpForIO::ZxHandleWatchController* controller, 300 MessagePumpForIO::ZxHandleWatcher* delegate); 301 #endif // BUILDFLAG(IS_FUCHSIA) 302 303 #endif // !BUILDFLAG(IS_NACL) 304 305 private: CurrentIOThread(sequence_manager::internal::SequenceManagerImpl * current)306 explicit CurrentIOThread( 307 sequence_manager::internal::SequenceManagerImpl* current) 308 : CurrentThread(current) {} 309 310 MessagePumpForIO* GetMessagePumpForIO() const; 311 }; 312 313 } // namespace base 314 315 #endif // BASE_TASK_CURRENT_THREAD_H_ 316