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