• 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/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