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