blob: ebd56e5c6a571c2b0abfdfffe96fd5bc9941a61b [file] [log] [blame]
// 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_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_