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