tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

current_thread.h (12404B)


      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:
    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_v<WatchableIOMessagePumpPosix, MessagePumpForUI>,
    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:
    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:
    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_