xref: /aosp_15_r20/external/libchrome/base/message_loop/message_loop_current.h (revision 635a864187cb8b6c713ff48b7e790a6b21769273)
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