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 183
|
// 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_
|