1 // Copyright 2012 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_MESSAGE_LOOP_MESSAGE_PUMP_GLIB_H_ 6 #define BASE_MESSAGE_LOOP_MESSAGE_PUMP_GLIB_H_ 7 8 #include <glib.h> 9 #include <memory> 10 11 #include "base/base_export.h" 12 #include "base/memory/raw_ptr.h" 13 #include "base/message_loop/message_pump.h" 14 #include "base/message_loop/watchable_io_message_pump_posix.h" 15 #include "base/threading/thread_checker.h" 16 #include "base/time/time.h" 17 18 namespace base { 19 20 // This class implements a base MessagePump needed for TYPE_UI MessageLoops on 21 // platforms using GLib. 22 class BASE_EXPORT MessagePumpGlib : public MessagePump, 23 public WatchableIOMessagePumpPosix { 24 public: 25 class FdWatchController : public FdWatchControllerInterface { 26 public: 27 explicit FdWatchController(const Location& from_here); 28 29 FdWatchController(const FdWatchController&) = delete; 30 FdWatchController& operator=(const FdWatchController&) = delete; 31 32 ~FdWatchController() override; 33 34 // FdWatchControllerInterface: 35 bool StopWatchingFileDescriptor() override; 36 37 private: 38 friend class MessagePumpGlib; 39 friend class MessagePumpGLibFdWatchTest; 40 41 // FdWatchController instances can be reused (unless fd changes), so we 42 // need to keep track of initialization status and taking it into account 43 // when setting up a fd watching. Please refer to 44 // WatchableIOMessagePumpPosix docs for more details. This is called by 45 // WatchFileDescriptor() and sets up a GSource for the input parameters. 46 // The source is not attached here, so the events will not be fired until 47 // Attach() is called. 48 bool InitOrUpdate(int fd, int mode, FdWatcher* watcher); 49 // Returns the current initialization status. 50 bool IsInitialized() const; 51 52 // Tries to attach the internal GSource instance to the |pump|'s 53 // GMainContext, so IO events start to be dispatched. Returns false if 54 // |this| is not correctly initialized, otherwise returns true. 55 bool Attach(MessagePumpGlib* pump); 56 57 // Forward read and write events to |watcher_|. It is a no-op if watcher_ 58 // is null, which can happen when controller is suddenly stopped through 59 // StopWatchingFileDescriptor(). 60 void NotifyCanRead(); 61 void NotifyCanWrite(); 62 63 raw_ptr<FdWatcher> watcher_ = nullptr; 64 raw_ptr<GSource> source_ = nullptr; 65 std::unique_ptr<GPollFD> poll_fd_; 66 // If this pointer is non-null, the pointee is set to true in the 67 // destructor. 68 raw_ptr<bool> was_destroyed_ = nullptr; 69 }; 70 71 MessagePumpGlib(); 72 73 MessagePumpGlib(const MessagePumpGlib&) = delete; 74 MessagePumpGlib& operator=(const MessagePumpGlib&) = delete; 75 76 ~MessagePumpGlib() override; 77 78 // Part of WatchableIOMessagePumpPosix interface. 79 // Please refer to WatchableIOMessagePumpPosix docs for more details. 80 bool WatchFileDescriptor(int fd, 81 bool persistent, 82 int mode, 83 FdWatchController* controller, 84 FdWatcher* delegate); 85 86 // Internal methods used for processing the pump callbacks. They are public 87 // for simplicity but should not be used directly. HandlePrepare is called 88 // during the prepare step of glib, and returns a timeout that will be passed 89 // to the poll. HandleCheck is called after the poll has completed, and 90 // returns whether or not HandleDispatch should be called. HandleDispatch is 91 // called if HandleCheck returned true. 92 int HandlePrepare(); 93 bool HandleCheck(); 94 void HandleDispatch(); 95 96 // Very similar to the above, with the key difference that these functions are 97 // only used to track work items and never indicate work is available, and 98 // poll indefinitely. 99 void HandleObserverPrepare(); 100 bool HandleObserverCheck(); 101 102 // Overridden from MessagePump: 103 void Run(Delegate* delegate) override; 104 void Quit() override; 105 void ScheduleWork() override; 106 void ScheduleDelayedWork( 107 const Delegate::NextWorkInfo& next_work_info) override; 108 109 // Internal methods used for processing the FdWatchSource callbacks. As for 110 // main pump callbacks, they are public for simplicity but should not be used 111 // directly. 112 bool HandleFdWatchCheck(FdWatchController* controller); 113 void HandleFdWatchDispatch(FdWatchController* controller); 114 115 private: 116 struct GMainContextDeleter { operatorGMainContextDeleter117 inline void operator()(GMainContext* context) const { 118 if (context) { 119 g_main_context_pop_thread_default(context); 120 g_main_context_unref(context); 121 } 122 } 123 }; 124 struct GSourceDeleter { operatorGSourceDeleter125 inline void operator()(GSource* source) const { 126 if (source) { 127 g_source_destroy(source); 128 g_source_unref(source); 129 } 130 } 131 }; 132 bool ShouldQuit() const; 133 134 // We may make recursive calls to Run, so we save state that needs to be 135 // separate between them in this structure type. 136 struct RunState; 137 138 raw_ptr<RunState> state_; 139 140 // Starts tracking a new work item and stores a `ScopedDoWorkItem` in 141 // `state_`. 142 void SetScopedWorkItem(); 143 // Gets rid of the current scoped work item. 144 void ClearScopedWorkItem(); 145 // Ensures there's a ScopedDoWorkItem at the current run-level. This can be 146 // useful for contexts where the caller can't tell whether they just woke up 147 // or are continuing from native work. 148 void EnsureSetScopedWorkItem(); 149 // Ensures there's no ScopedDoWorkItem at the current run-level. This can be 150 // useful in contexts where the caller knows that a sleep is imminent but 151 // doesn't know if the current context captures ongoing work (back from 152 // native). 153 void EnsureClearedScopedWorkItem(); 154 155 // Called before entrance to g_main_context_iteration to record context 156 // related to nesting depth to track native nested loops which would otherwise 157 // be invisible. 158 void OnEntryToGlib(); 159 // Cleans up state set in OnEntryToGlib. 160 void OnExitFromGlib(); 161 // Forces the pump into a nested state by creating two work items back to 162 // back. 163 void RegisterNested(); 164 // Removes all of the pump's ScopedDoWorkItems to remove the state of nesting 165 // which was forced onto the pump. 166 void UnregisterNested(); 167 // Nest if pump is not already marked as nested. 168 void NestIfRequired(); 169 // Remove the nesting if the pump is nested. 170 void UnnestIfRequired(); 171 172 std::unique_ptr<GMainContext, GMainContextDeleter> owned_context_; 173 // This is a GLib structure that we can add event sources to. On the main 174 // thread, we use the default GLib context, which is the one to which all GTK 175 // events are dispatched. 176 raw_ptr<GMainContext> context_ = nullptr; 177 178 // The work source. It is shared by all calls to Run and destroyed when 179 // the message pump is destroyed. 180 std::unique_ptr<GSource, GSourceDeleter> work_source_; 181 182 // The observer source. It is shared by all calls to Run and destroyed when 183 // the message pump is destroyed. 184 std::unique_ptr<GSource, GSourceDeleter> observer_source_; 185 186 // We use a wakeup pipe to make sure we'll get out of the glib polling phase 187 // when another thread has scheduled us to do some work. There is a glib 188 // mechanism g_main_context_wakeup, but this won't guarantee that our event's 189 // Dispatch() will be called. 190 int wakeup_pipe_read_; 191 int wakeup_pipe_write_; 192 // Use a unique_ptr to avoid needing the definition of GPollFD in the header. 193 std::unique_ptr<GPollFD> wakeup_gpollfd_; 194 195 THREAD_CHECKER(watch_fd_caller_checker_); 196 }; 197 198 } // namespace base 199 200 #endif // BASE_MESSAGE_LOOP_MESSAGE_PUMP_GLIB_H_ 201