blob: d6995f6ac071da602feea3e2199519b215b4286a [file] [log] [blame]
// Copyright 2018 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include <lib/fdio/fd.h>
#include <lib/zxio/null.h>
#include <lib/zxio/ops.h>
#include <zircon/syscalls.h>
#include "sdk/lib/fdio/zxio.h"
struct fdio_waitable_t {
zxio_t io;
// arbitrary handle
std::variant<zx::handle, zx::unowned_handle> handle;
// signals that cause ZXIO_SIGNAL_READABLE
zx_signals_t readable;
// signals that cause ZXIO_SIGNAL_WRITABLE
zx_signals_t writable;
};
static_assert(sizeof(fdio_waitable_t) <= sizeof(zxio_storage_t),
"fdio_waitable_t must fit inside zxio_storage_t.");
static zx_status_t fdio_waitable_close(zxio_t* io, const bool should_wait) {
auto waitable = reinterpret_cast<fdio_waitable_t*>(io);
waitable->~fdio_waitable_t();
return ZX_OK;
}
static void fdio_waitable_wait_begin(zxio_t* io, zxio_signals_t zxio_signals,
zx_handle_t* out_handle, zx_signals_t* out_zx_signals) {
fdio_waitable_t* waitable = reinterpret_cast<fdio_waitable_t*>(io);
zx_signals_t zx_signals = ZX_SIGNAL_NONE;
if (zxio_signals & ZXIO_SIGNAL_READABLE) {
zx_signals |= waitable->readable;
}
if (zxio_signals & ZXIO_SIGNAL_WRITABLE) {
zx_signals |= waitable->writable;
}
std::visit(fdio::overloaded{
[out_handle](zx::handle& handle) { *out_handle = handle.get(); },
[out_handle](zx::unowned_handle& handle) { *out_handle = handle->get(); },
},
waitable->handle);
*out_zx_signals = zx_signals;
}
static void fdio_waitable_wait_end(zxio_t* io, zx_signals_t zx_signals,
zxio_signals_t* out_zxio_signals) {
fdio_waitable_t* waitable = reinterpret_cast<fdio_waitable_t*>(io);
zxio_signals_t zxio_signals = ZXIO_SIGNAL_NONE;
if (zx_signals & waitable->readable) {
zxio_signals |= ZXIO_SIGNAL_READABLE;
}
if (zx_signals & waitable->writable) {
zxio_signals |= ZXIO_SIGNAL_WRITABLE;
}
*out_zxio_signals = zxio_signals;
}
static constexpr zxio_ops_t fdio_waitable_ops = []() {
zxio_ops_t ops = zxio_default_ops;
ops.close = fdio_waitable_close;
ops.wait_begin = fdio_waitable_wait_begin;
ops.wait_end = fdio_waitable_wait_end;
return ops;
}();
zx::result<fdio_ptr> fdio_waitable_create(std::variant<zx::handle, zx::unowned_handle> handle,
zx_signals_t readable, zx_signals_t writable) {
zx::result io = fdio_internal::zxio::create();
if (io.is_error()) {
return io.take_error();
}
auto waitable = new (&io->zxio_storage()) fdio_waitable_t{
.handle = std::move(handle),
.readable = readable,
.writable = writable,
};
zxio_init(&waitable->io, &fdio_waitable_ops);
return io;
}