• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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     raw_ptr<bool> was_stopped_ = nullptr;
77 
78     // Set directly from the inputs to WatchFileDescriptor.
79     raw_ptr<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     raw_ptr<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     // TODO(366045345) This is actually an owning reference, so we should
120     // probably turn it into a ScopedGeneric<> that calls fdio_unsafe_release()
121     // on destruction.
122     raw_ptr<fdio_t> io_ = nullptr;
123   };
124 
125   enum Mode {
126     WATCH_READ = 1 << 0,
127     WATCH_WRITE = 1 << 1,
128     WATCH_READ_WRITE = WATCH_READ | WATCH_WRITE
129   };
130 
131   MessagePumpFuchsia();
132 
133   MessagePumpFuchsia(const MessagePumpFuchsia&) = delete;
134   MessagePumpFuchsia& operator=(const MessagePumpFuchsia&) = delete;
135 
136   ~MessagePumpFuchsia() override;
137 
138   bool WatchZxHandle(zx_handle_t handle,
139                      bool persistent,
140                      zx_signals_t signals,
141                      ZxHandleWatchController* controller,
142                      ZxHandleWatcher* delegate);
143   bool WatchFileDescriptor(int fd,
144                            bool persistent,
145                            int mode,
146                            FdWatchController* controller,
147                            FdWatcher* delegate);
148 
149   // MessagePump implementation:
150   void Run(Delegate* delegate) override;
151   void Quit() override;
152   void ScheduleWork() override;
153   void ScheduleDelayedWork(
154       const Delegate::NextWorkInfo& next_work_info) override;
155 
156  private:
157   // Handles IO events by running |async_dispatcher_| until |deadline|. Returns
158   // true if any events were received or if ScheduleWork() was called.
159   bool HandleIoEventsUntil(zx_time_t deadline);
160 
161   struct RunState {
RunStateRunState162     explicit RunState(Delegate* delegate_in) : delegate(delegate_in) {}
163 
164     // `delegate` is not a raw_ptr<...> for performance reasons (based on
165     // analysis of sampling profiler data and tab_search:top100:2020).
166     RAW_PTR_EXCLUSION Delegate* const delegate;
167 
168     // Used to flag that the current Run() invocation should return ASAP.
169     bool should_quit = false;
170   };
171 
172   // State for the current invocation of Run(). null if not running.
173   RAW_PTR_EXCLUSION RunState* run_state_ = nullptr;
174 
175   std::unique_ptr<async::Loop> async_loop_;
176 
177   base::WeakPtrFactory<MessagePumpFuchsia> weak_factory_;
178 };
179 
180 }  // namespace base
181 
182 #endif  // BASE_MESSAGE_LOOP_MESSAGE_PUMP_FUCHSIA_H_
183