1 // Copyright 2017 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_FUCHSIA_H_ 6 #define BASE_MESSAGE_LOOP_MESSAGE_PUMP_FUCHSIA_H_ 7 8 #include <lib/async/wait.h> 9 #include <memory> 10 11 #include "base/base_export.h" 12 #include "base/location.h" 13 #include "base/memory/raw_ptr.h" 14 #include "base/memory/weak_ptr.h" 15 #include "base/message_loop/message_pump.h" 16 #include "base/message_loop/watchable_io_message_pump_posix.h" 17 18 typedef struct fdio fdio_t; 19 20 namespace async { 21 class Loop; 22 } // namespace async 23 24 namespace base { 25 26 class BASE_EXPORT MessagePumpFuchsia : public MessagePump, 27 public WatchableIOMessagePumpPosix { 28 public: 29 // Implemented by callers to receive notifications of handle & fd events. 30 class ZxHandleWatcher { 31 public: 32 virtual void OnZxHandleSignalled(zx_handle_t handle, 33 zx_signals_t signals) = 0; 34 35 protected: 36 virtual ~ZxHandleWatcher() = default; 37 }; 38 39 // Manages an active watch on an zx_handle_t. 40 class ZxHandleWatchController : public async_wait_t { 41 public: 42 explicit ZxHandleWatchController(const Location& from_here); 43 44 ZxHandleWatchController(const ZxHandleWatchController&) = delete; 45 ZxHandleWatchController& operator=(const ZxHandleWatchController&) = delete; 46 47 // Deleting the Controller implicitly calls StopWatchingZxHandle. 48 virtual ~ZxHandleWatchController(); 49 50 // Stop watching the handle, always safe to call. No-op if there's nothing 51 // to do. 52 bool StopWatchingZxHandle(); 53 created_from_location()54 const Location& created_from_location() { return created_from_location_; } 55 56 protected: 57 friend class MessagePumpFuchsia; 58 59 virtual bool WaitBegin(); 60 is_active()61 bool is_active() const { return async_wait_t::handler != nullptr; } 62 63 static void HandleSignal(async_dispatcher_t* async, 64 async_wait_t* wait, 65 zx_status_t status, 66 const zx_packet_signal_t* signal); 67 68 const Location created_from_location_; 69 70 // This bool is used by the pump when invoking the ZxHandleWatcher callback, 71 // and by the FdHandleWatchController when invoking read & write callbacks, 72 // to cope with the possibility of the caller deleting the *Watcher within 73 // the callback. The pump sets |was_stopped_| to a location on the stack, 74 // and the Watcher writes to it, if set, when deleted, allowing the pump 75 // to check the value on the stack to short-cut any post-callback work. 76 bool* was_stopped_ = nullptr; 77 78 // Set directly from the inputs to WatchFileDescriptor. 79 ZxHandleWatcher* watcher_ = nullptr; 80 81 // Used to safely access resources owned by the associated message pump. 82 WeakPtr<MessagePumpFuchsia> weak_pump_; 83 84 // A watch may be marked as persistent, which means it remains active even 85 // after triggering. 86 bool persistent_ = false; 87 }; 88 89 class FdWatchController : public FdWatchControllerInterface, 90 public ZxHandleWatchController, 91 public ZxHandleWatcher { 92 public: 93 explicit FdWatchController(const Location& from_here); 94 95 FdWatchController(const FdWatchController&) = delete; 96 FdWatchController& operator=(const FdWatchController&) = delete; 97 98 ~FdWatchController() override; 99 100 // FdWatchControllerInterface: 101 bool StopWatchingFileDescriptor() override; 102 103 private: 104 friend class MessagePumpFuchsia; 105 106 // Determines the desires signals, and begins waiting on the handle. 107 bool WaitBegin() override; 108 109 // ZxHandleWatcher interface. 110 void OnZxHandleSignalled(zx_handle_t handle, zx_signals_t signals) override; 111 112 // Set directly from the inputs to WatchFileDescriptor. 113 FdWatcher* watcher_ = nullptr; 114 int fd_ = -1; 115 uint32_t desired_events_ = 0; 116 117 // Set by WatchFileDescriptor() to hold a reference to the descriptor's 118 // fdio. 119 fdio_t* io_ = nullptr; 120 }; 121 122 enum Mode { 123 WATCH_READ = 1 << 0, 124 WATCH_WRITE = 1 << 1, 125 WATCH_READ_WRITE = WATCH_READ | WATCH_WRITE 126 }; 127 128 MessagePumpFuchsia(); 129 130 MessagePumpFuchsia(const MessagePumpFuchsia&) = delete; 131 MessagePumpFuchsia& operator=(const MessagePumpFuchsia&) = delete; 132 133 ~MessagePumpFuchsia() override; 134 135 bool WatchZxHandle(zx_handle_t handle, 136 bool persistent, 137 zx_signals_t signals, 138 ZxHandleWatchController* controller, 139 ZxHandleWatcher* delegate); 140 bool WatchFileDescriptor(int fd, 141 bool persistent, 142 int mode, 143 FdWatchController* controller, 144 FdWatcher* delegate); 145 146 // MessagePump implementation: 147 void Run(Delegate* delegate) override; 148 void Quit() override; 149 void ScheduleWork() override; 150 void ScheduleDelayedWork( 151 const Delegate::NextWorkInfo& next_work_info) override; 152 153 private: 154 // Handles IO events by running |async_dispatcher_| until |deadline|. Returns 155 // true if any events were received or if ScheduleWork() was called. 156 bool HandleIoEventsUntil(zx_time_t deadline); 157 158 struct RunState { RunStateRunState159 explicit RunState(Delegate* delegate_in) : delegate(delegate_in) {} 160 161 // `delegate` is not a raw_ptr<...> for performance reasons (based on 162 // analysis of sampling profiler data and tab_search:top100:2020). 163 RAW_PTR_EXCLUSION Delegate* const delegate; 164 165 // Used to flag that the current Run() invocation should return ASAP. 166 bool should_quit = false; 167 }; 168 169 // State for the current invocation of Run(). null if not running. 170 RAW_PTR_EXCLUSION RunState* run_state_ = nullptr; 171 172 std::unique_ptr<async::Loop> async_loop_; 173 174 base::WeakPtrFactory<MessagePumpFuchsia> weak_factory_; 175 }; 176 177 } // namespace base 178 179 #endif // BASE_MESSAGE_LOOP_MESSAGE_PUMP_FUCHSIA_H_ 180