• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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