blob: 10e35106596f7b438297097e2f69c6ef5639b1ac [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.
#pragma once
#include <fbl/unique_ptr.h>
#include <lib/async/cpp/wait.h>
#include <lib/zx/channel.h>
#include <utility>
namespace devmgr {
// Mixin for representing a type that represents an RPC handler and is owned
// by an async loop. The loop will own both the wrapped type and the RPC
// connection handle.
// Deriving classes should define and implement this function:
// static void HandleRpc(fbl::unique_ptr<T> conn,
// async_dispatcher_t* dispatcher, async::WaitBase* wait, zx_status_t status,
// const zx_packet_signal_t* signal);
template <typename T> class AsyncLoopOwnedRpcHandler {
~AsyncLoopOwnedRpcHandler() {
zx_status_t status = wait_.Cancel();
ZX_ASSERT(status == ZX_OK || status == ZX_ERR_NOT_FOUND);
// Variant of BeginWait that conditionally consumes |conn|. On failure,
// |*conn| is untouched.
static zx_status_t BeginWait(fbl::unique_ptr<T>* conn, async_dispatcher_t* dispatcher) {
zx_status_t status = (*conn)->wait_.Begin(dispatcher);
if (status == ZX_OK) {
__UNUSED auto ptr = conn->release();
return status;
// Begins waiting in |dispatcher| on |conn->wait|. This transfers ownership
// of |conn| to the dispatcher. The dispatcher returns ownership when the
// handler is invoked.
static zx_status_t BeginWait(fbl::unique_ptr<T> conn, async_dispatcher_t* dispatcher) {
return BeginWait(&conn, dispatcher);
// Entrypoint for the RPC handler that captures the pointer ownership
// semantics.
void HandleRpcEntry(async_dispatcher_t* dispatcher, async::WaitBase* wait, zx_status_t status,
const zx_packet_signal_t* signal) {
fbl::unique_ptr<T> self(static_cast<T*>(this));
T::HandleRpc(std::move(self), dispatcher, wait, status, signal);
zx::unowned_channel channel() const { return zx::unowned_channel(wait_.object()); }
// Sets the channel to the given handle and returns the old value
zx::channel set_channel(zx::channel h) {
zx::channel old(wait_.object());
return old;
using WaitType = async::WaitMethod<AsyncLoopOwnedRpcHandler<T>,
} // namespace devmgr