| // Copyright 2017 The Chromium Authors. All rights reserved. | |
| // 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 "base/base_export.h" | |
| #include "base/fuchsia/async_dispatcher.h" | |
| #include "base/location.h" | |
| #include "base/macros.h" | |
| #include "base/memory/weak_ptr.h" | |
| #include "base/message_loop/message_pump.h" | |
| #include "base/message_loop/watchable_io_message_pump_posix.h" | |
| #include "starboard/types.h" | |
| typedef struct fdio fdio_t; | |
| 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() {} | |
| }; | |
| // Manages an active watch on an zx_handle_t. | |
| class ZxHandleWatchController : public async_wait_t { | |
| public: | |
| explicit ZxHandleWatchController(const Location& from_here); | |
| // 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(); | |
| 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. | |
| bool* was_stopped_ = nullptr; | |
| // Set directly from the inputs to WatchFileDescriptor. | |
| 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; | |
| DISALLOW_COPY_AND_ASSIGN(ZxHandleWatchController); | |
| }; | |
| class FdWatchController : public FdWatchControllerInterface, | |
| public ZxHandleWatchController, | |
| public ZxHandleWatcher { | |
| public: | |
| explicit FdWatchController(const Location& from_here); | |
| ~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. | |
| FdWatcher* watcher_ = nullptr; | |
| int fd_ = -1; | |
| uint32_t desired_events_ = 0; | |
| // Set by WatchFileDescriptor to hold a reference to the descriptor's mxio. | |
| fdio_t* io_ = nullptr; | |
| DISALLOW_COPY_AND_ASSIGN(FdWatchController); | |
| }; | |
| enum Mode { | |
| WATCH_READ = 1 << 0, | |
| WATCH_WRITE = 1 << 1, | |
| WATCH_READ_WRITE = WATCH_READ | WATCH_WRITE | |
| }; | |
| MessagePumpFuchsia(); | |
| ~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 TimeTicks& delayed_work_time) override; | |
| private: | |
| // Handles IO events by running |async_dispatcher_|. Returns true if any | |
| // events were received or if ScheduleWork() was called. | |
| bool HandleEvents(zx_time_t deadline); | |
| // This flag is set to false when Run should return. | |
| bool keep_running_ = true; | |
| AsyncDispatcher async_dispatcher_; | |
| // The time at which we should call DoDelayedWork. | |
| TimeTicks delayed_work_time_; | |
| base::WeakPtrFactory<MessagePumpFuchsia> weak_factory_; | |
| DISALLOW_COPY_AND_ASSIGN(MessagePumpFuchsia); | |
| }; | |
| } // namespace base | |
| #endif // BASE_MESSAGE_LOOP_MESSAGE_PUMP_FUCHSIA_H_ |