1 // Copyright 2018 The Chromium Authors. All rights reserved. 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_MESSAGE_LOOP_MESSAGE_LOOP_CURRENT_H_ 6 #define BASE_MESSAGE_LOOP_MESSAGE_LOOP_CURRENT_H_ 7 8 #include "base/base_export.h" 9 #include "base/logging.h" 10 #include "base/memory/scoped_refptr.h" 11 #include "base/message_loop/message_pump_for_io.h" 12 #include "base/message_loop/message_pump_for_ui.h" 13 #include "base/pending_task.h" 14 #include "base/single_thread_task_runner.h" 15 #include "build/build_config.h" 16 17 namespace base { 18 19 class MessageLoop; 20 21 // MessageLoopCurrent is a proxy to the public interface of the MessageLoop 22 // bound to the thread it's obtained on. 23 // 24 // MessageLoopCurrent(ForUI|ForIO) is available statically through 25 // MessageLoopCurrent(ForUI|ForIO)::Get() on threads that have a matching 26 // MessageLoop instance. APIs intended for all consumers on the thread should be 27 // on MessageLoopCurrent(ForUI|ForIO), while APIs intended for the owner of the 28 // instance should be on MessageLoop(ForUI|ForIO). 29 // 30 // Why: Historically MessageLoop::current() gave access to the full MessageLoop 31 // API, preventing both addition of powerful owner-only APIs as well as making 32 // it harder to remove callers of deprecated APIs (that need to stick around for 33 // a few owner-only use cases and re-accrue callers after cleanup per remaining 34 // publicly available). 35 // 36 // As such, many methods below are flagged as deprecated and should be removed 37 // (or moved back to MessageLoop) once all static callers have been migrated. 38 class BASE_EXPORT MessageLoopCurrent { 39 public: 40 // MessageLoopCurrent is effectively just a disguised pointer and is fine to 41 // copy around. 42 MessageLoopCurrent(const MessageLoopCurrent& other) = default; 43 // Deleted because the pointed field member is const. 44 MessageLoopCurrent& operator=(const MessageLoopCurrent& other) = delete; 45 46 // Returns a proxy object to interact with the MessageLoop running the 47 // current thread. It must only be used on the thread it was obtained. 48 static MessageLoopCurrent Get(); 49 50 // Returns true if the current thread is running a MessageLoop. Prefer this to 51 // verifying the boolean value of Get() (so that Get() can ultimately DCHECK 52 // it's only invoked when IsSet()). 53 static bool IsSet(); 54 55 // Allow MessageLoopCurrent to be used like a pointer to support the many 56 // callsites that used MessageLoop::current() that way when it was a 57 // MessageLoop*. 58 MessageLoopCurrent* operator->() { return this; } 59 explicit operator bool() const { return !!current_; } 60 61 // TODO(gab): Migrate the types of variables that store MessageLoop::current() 62 // and remove this implicit cast back to MessageLoop*. 63 operator MessageLoop*() const { return current_; } 64 65 // A DestructionObserver is notified when the current MessageLoop is being 66 // destroyed. These observers are notified prior to MessageLoop::current() 67 // being changed to return NULL. This gives interested parties the chance to 68 // do final cleanup that depends on the MessageLoop. 69 // 70 // NOTE: Any tasks posted to the MessageLoop during this notification will 71 // not be run. Instead, they will be deleted. 72 // 73 // Deprecation note: Prefer SequenceLocalStorageSlot<std::unique_ptr<Foo>> to 74 // DestructionObserver to bind an object's lifetime to the current 75 // thread/sequence. 76 class BASE_EXPORT DestructionObserver { 77 public: 78 virtual void WillDestroyCurrentMessageLoop() = 0; 79 80 protected: 81 virtual ~DestructionObserver() = default; 82 }; 83 84 // Add a DestructionObserver, which will start receiving notifications 85 // immediately. 86 void AddDestructionObserver(DestructionObserver* destruction_observer); 87 88 // Remove a DestructionObserver. It is safe to call this method while a 89 // DestructionObserver is receiving a notification callback. 90 void RemoveDestructionObserver(DestructionObserver* destruction_observer); 91 92 // Forwards to MessageLoop::task_runner(). 93 // DEPRECATED(https://crbug.com/616447): Use ThreadTaskRunnerHandle::Get() 94 // instead of MessageLoopCurrent::Get()->task_runner(). 95 const scoped_refptr<SingleThreadTaskRunner>& task_runner() const; 96 97 // Forwards to MessageLoop::SetTaskRunner(). 98 // DEPRECATED(https://crbug.com/825327): only owners of the MessageLoop 99 // instance should replace its TaskRunner. 100 void SetTaskRunner(scoped_refptr<SingleThreadTaskRunner> task_runner); 101 102 // A TaskObserver is an object that receives task notifications from the 103 // MessageLoop. 104 // 105 // NOTE: A TaskObserver implementation should be extremely fast! 106 class BASE_EXPORT TaskObserver { 107 public: 108 // This method is called before processing a task. 109 virtual void WillProcessTask(const PendingTask& pending_task) = 0; 110 111 // This method is called after processing a task. 112 virtual void DidProcessTask(const PendingTask& pending_task) = 0; 113 114 protected: 115 virtual ~TaskObserver() = default; 116 }; 117 118 // Forwards to MessageLoop::(Add|Remove)TaskObserver. 119 // DEPRECATED(https://crbug.com/825327): only owners of the MessageLoop 120 // instance should add task observers on it. 121 void AddTaskObserver(TaskObserver* task_observer); 122 void RemoveTaskObserver(TaskObserver* task_observer); 123 124 // Enables or disables the recursive task processing. This happens in the case 125 // of recursive message loops. Some unwanted message loops may occur when 126 // using common controls or printer functions. By default, recursive task 127 // processing is disabled. 128 // 129 // Please use |ScopedNestableTaskAllower| instead of calling these methods 130 // directly. In general, nestable message loops are to be avoided. They are 131 // dangerous and difficult to get right, so please use with extreme caution. 132 // 133 // The specific case where tasks get queued is: 134 // - The thread is running a message loop. 135 // - It receives a task #1 and executes it. 136 // - The task #1 implicitly starts a message loop, like a MessageBox in the 137 // unit test. This can also be StartDoc or GetSaveFileName. 138 // - The thread receives a task #2 before or while in this second message 139 // loop. 140 // - With NestableTasksAllowed set to true, the task #2 will run right away. 141 // Otherwise, it will get executed right after task #1 completes at "thread 142 // message loop level". 143 // 144 // DEPRECATED(https://crbug.com/750779): Use RunLoop::Type on the relevant 145 // RunLoop instead of these methods. 146 // TODO(gab): Migrate usage and delete these methods. 147 void SetNestableTasksAllowed(bool allowed); 148 bool NestableTasksAllowed() const; 149 150 // Enables nestable tasks on the current MessageLoop while in scope. 151 // DEPRECATED(https://crbug.com/750779): This should not be used when the 152 // nested loop is driven by RunLoop (use RunLoop::Type::kNestableTasksAllowed 153 // instead). It can however still be useful in a few scenarios where re- 154 // entrancy is caused by a native message loop. 155 // TODO(gab): Remove usage of this class alongside RunLoop and rename it to 156 // ScopedApplicationTasksAllowedInNativeNestedLoop(?) for remaining use cases. 157 class BASE_EXPORT ScopedNestableTaskAllower { 158 public: 159 ScopedNestableTaskAllower(); 160 ~ScopedNestableTaskAllower(); 161 162 private: 163 MessageLoop* const loop_; 164 const bool old_state_; 165 }; 166 167 // Returns true if the message loop is idle (ignoring delayed tasks). This is 168 // the same condition which triggers DoWork() to return false: i.e. 169 // out of tasks which can be processed at the current run-level -- there might 170 // be deferred non-nestable tasks remaining if currently in a nested run 171 // level. 172 bool IsIdleForTesting(); 173 174 // Binds |current| to the current thread. It will from then on be the 175 // MessageLoop driven by MessageLoopCurrent on this thread. This is only meant 176 // to be invoked by the MessageLoop itself. 177 static void BindToCurrentThreadInternal(MessageLoop* current); 178 179 // Unbinds |current| from the current thread. Must be invoked on the same 180 // thread that invoked |BindToCurrentThreadInternal(current)|. This is only 181 // meant to be invoked by the MessageLoop itself. 182 static void UnbindFromCurrentThreadInternal(MessageLoop* current); 183 184 // Returns true if |message_loop| is bound to MessageLoopCurrent on the 185 // current thread. This is only meant to be invoked by the MessageLoop itself. 186 static bool IsBoundToCurrentThreadInternal(MessageLoop* message_loop); 187 188 protected: MessageLoopCurrent(MessageLoop * current)189 explicit MessageLoopCurrent(MessageLoop* current) : current_(current) {} 190 191 MessageLoop* const current_; 192 }; 193 194 #if !defined(OS_NACL) && !defined(OS_ANDROID) 195 196 // ForUI extension of MessageLoopCurrent. 197 class BASE_EXPORT MessageLoopCurrentForUI : public MessageLoopCurrent { 198 public: 199 // Returns an interface for the MessageLoopForUI of the current thread. 200 // Asserts that IsSet(). 201 static MessageLoopCurrentForUI Get(); 202 203 // Returns true if the current thread is running a MessageLoopForUI. 204 static bool IsSet(); 205 206 MessageLoopCurrentForUI* operator->() { return this; } 207 208 #if defined(USE_OZONE) && !defined(OS_FUCHSIA) && !defined(OS_WIN) 209 // Please see MessagePumpLibevent for definition. 210 static_assert(std::is_same<MessagePumpForUI, MessagePumpLibevent>::value, 211 "MessageLoopCurrentForUI::WatchFileDescriptor is not supported " 212 "when MessagePumpForUI is not a MessagePumpLibevent."); 213 bool WatchFileDescriptor(int fd, 214 bool persistent, 215 MessagePumpForUI::Mode mode, 216 MessagePumpForUI::FdWatchController* controller, 217 MessagePumpForUI::FdWatcher* delegate); 218 #endif 219 220 #if defined(OS_IOS) 221 // Forwards to MessageLoopForUI::Attach(). 222 // TODO(https://crbug.com/825327): Plumb the actual MessageLoopForUI* to 223 // callers and remove ability to access this method from 224 // MessageLoopCurrentForUI. 225 void Attach(); 226 #endif 227 228 #if defined(OS_ANDROID) 229 // Forwards to MessageLoopForUI::Abort(). 230 // TODO(https://crbug.com/825327): Plumb the actual MessageLoopForUI* to 231 // callers and remove ability to access this method from 232 // MessageLoopCurrentForUI. 233 void Abort(); 234 #endif 235 236 private: MessageLoopCurrentForUI(MessageLoop * current,MessagePumpForUI * pump)237 MessageLoopCurrentForUI(MessageLoop* current, MessagePumpForUI* pump) 238 : MessageLoopCurrent(current), pump_(pump) { 239 DCHECK(pump_); 240 } 241 242 MessagePumpForUI* const pump_; 243 }; 244 245 #endif // !defined(OS_NACL) && !defined(OS_ANDROID) 246 247 // ForIO extension of MessageLoopCurrent. 248 class BASE_EXPORT MessageLoopCurrentForIO : public MessageLoopCurrent { 249 public: 250 // Returns an interface for the MessageLoopForIO of the current thread. 251 // Asserts that IsSet(). 252 static MessageLoopCurrentForIO Get(); 253 254 // Returns true if the current thread is running a MessageLoopForIO. 255 static bool IsSet(); 256 257 MessageLoopCurrentForIO* operator->() { return this; } 258 259 #if !defined(OS_NACL_SFI) 260 261 #if defined(OS_WIN) 262 // Please see MessagePumpWin for definitions of these methods. 263 HRESULT RegisterIOHandler(HANDLE file, MessagePumpForIO::IOHandler* handler); 264 bool RegisterJobObject(HANDLE job, MessagePumpForIO::IOHandler* handler); 265 bool WaitForIOCompletion(DWORD timeout, MessagePumpForIO::IOHandler* filter); 266 #elif defined(OS_POSIX) || defined(OS_FUCHSIA) 267 // Please see WatchableIOMessagePumpPosix for definition. 268 // Prefer base::FileDescriptorWatcher for non-critical IO. 269 bool WatchFileDescriptor(int fd, 270 bool persistent, 271 MessagePumpForIO::Mode mode, 272 MessagePumpForIO::FdWatchController* controller, 273 MessagePumpForIO::FdWatcher* delegate); 274 #endif // defined(OS_WIN) 275 276 #if defined(OS_FUCHSIA) 277 // Additional watch API for native platform resources. 278 bool WatchZxHandle(zx_handle_t handle, 279 bool persistent, 280 zx_signals_t signals, 281 MessagePumpForIO::ZxHandleWatchController* controller, 282 MessagePumpForIO::ZxHandleWatcher* delegate); 283 #endif // defined(OS_FUCHSIA) 284 285 #endif // !defined(OS_NACL_SFI) 286 287 private: MessageLoopCurrentForIO(MessageLoop * current,MessagePumpForIO * pump)288 MessageLoopCurrentForIO(MessageLoop* current, MessagePumpForIO* pump) 289 : MessageLoopCurrent(current), pump_(pump) { 290 DCHECK(pump_); 291 } 292 293 MessagePumpForIO* const pump_; 294 }; 295 296 } // namespace base 297 298 #endif // BASE_MESSAGE_LOOP_MESSAGE_LOOP_CURRENT_H_ 299