xref: /aosp_15_r20/external/cronet/base/message_loop/message_pump_fuchsia.h (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
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