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