blob: fec4ab52e2b93faeb0adda9b781b29d786fea757 [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 "base/base_export.h"
#include "base/location.h"
#include "base/macros.h"
#include "base/message_loop/message_pump.h"
#include <magenta/syscalls/port.h>
#include <mxio/io.h>
#include <mxio/private.h>
namespace base {
class BASE_EXPORT MessagePumpFuchsia : public MessagePump {
public:
class Watcher {
public:
// Called from MessageLoop::Run when an FD can be read from/written to
// without blocking
virtual void OnFileCanReadWithoutBlocking(int fd) = 0;
virtual void OnFileCanWriteWithoutBlocking(int fd) = 0;
protected:
virtual ~Watcher() {}
};
// Object returned by WatchFileDescriptor to manage further watching.
class FileDescriptorWatcher {
public:
explicit FileDescriptorWatcher(const tracked_objects::Location& from_here);
~FileDescriptorWatcher(); // Implicitly calls StopWatchingFileDescriptor.
// Stop watching the FD, always safe to call. No-op if there's nothing
// to do.
bool StopWatchingFileDescriptor();
const tracked_objects::Location& created_from_location() {
return created_from_location_;
}
private:
// Start watching the FD.
bool WaitBegin();
// Stop watching the FD. Returns the set of events the watcher is interested
// in based on the observed bits from the underlying packet.
uint32_t WaitEnd(uint32_t observed);
friend class MessagePumpFuchsia;
const tracked_objects::Location created_from_location_;
// Set directly from the inputs to WatchFileDescriptor.
Watcher* watcher_ = nullptr;
mx_handle_t port_ = MX_HANDLE_INVALID;
int fd_ = -1;
uint32_t desired_events_ = 0;
// Set by WatchFileDescriptor to hold a reference to the descriptor's mxio.
mxio_t* io_ = nullptr;
// Set to the mxio's waitable handle, while a wait is pending (i.e. between
// WaitBegin and WaitEnd calls), and MX_HANDLE_INVALID otherwise.
mx_handle_t handle_ = MX_HANDLE_INVALID;
// This bool is used during calling |Watcher| callbacks. This object's
// lifetime is owned by the user of this class. If the message loop is woken
// up in the case where it needs to call both the readable and writable
// callbacks, we need to take care not to call the second one if this object
// is destroyed by the first one. The bool points to the stack, and is set
// to true in ~FileDescriptorWatcher() to handle this case.
bool* was_destroyed_ = nullptr;
// A watch may be marked as persistent, which means it remains active even
// after triggering.
bool persistent_ = false;
DISALLOW_COPY_AND_ASSIGN(FileDescriptorWatcher);
};
enum Mode {
WATCH_READ = 1 << 0,
WATCH_WRITE = 1 << 1,
WATCH_READ_WRITE = WATCH_READ | WATCH_WRITE
};
MessagePumpFuchsia();
~MessagePumpFuchsia() override;
bool WatchFileDescriptor(int fd,
bool persistent,
int mode,
FileDescriptorWatcher* controller,
Watcher* delegate);
// MessagePump implementation:
void Run(Delegate* delegate) override;
void Quit() override;
void ScheduleWork() override;
void ScheduleDelayedWork(const TimeTicks& delayed_work_time) override;
private:
// This flag is set to false when Run should return.
bool keep_running_;
mx_handle_t port_;
// The time at which we should call DoDelayedWork.
TimeTicks delayed_work_time_;
DISALLOW_COPY_AND_ASSIGN(MessagePumpFuchsia);
};
} // namespace base
#endif // BASE_MESSAGE_LOOP_MESSAGE_PUMP_FUCHSIA_H_