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