blob: 3826b38c1f6e76d0337b1e628b43df3d3c2c56a9 [file] [log] [blame]
// Copyright 2022 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.
#ifndef LIB_FIDL_DRIVER_INCLUDE_LIB_FIDL_DRIVER_CPP_SERVER_H_
#define LIB_FIDL_DRIVER_INCLUDE_LIB_FIDL_DRIVER_CPP_SERVER_H_
#include <lib/fidl/llcpp/server.h>
#include <lib/fidl_driver/cpp/internal/server_details.h>
#include <lib/fidl_driver/cpp/transport.h>
namespace fdf {
// This class manages a server connection over an fdf channel and its binding to
// an |fdf_dispatcher_t*|, which may be multi-threaded. See the detailed
// documentation on the |BindServer| APIs.
template <typename Protocol>
class ServerBindingRef : public fidl::internal::ServerBindingRefBase {
public:
using ServerBindingRefBase::ServerBindingRefBase;
// Triggers an asynchronous unbind operation. If specified, |on_unbound| will
// be asynchronously run on a dispatcher thread, passing in the endpoint and
// the unbind reason.
//
// On return, the dispatcher will stop monitoring messages on the endpoint,
// though handling of any already in-flight transactions will continue.
// Pending completers may be discarded.
//
// This may be called from any thread.
//
// WARNING: While it is safe to invoke Unbind() from any thread, it is unsafe to wait on the
// OnUnboundFn from a dispatcher thread, as that will likely deadlock.
using ServerBindingRefBase::Unbind;
};
// |BindServer| starts handling message on |server_end| using implementation
// |impl|, on a potentially multi-threaded |dispatcher|. Multiple requests may
// be concurrently in-flight, and responded to synchronously or asynchronously.
//
// The behavior of |fdf::BindServer| is identical to |fidl::BindServer|, the
// specialization for channels. Please see documentation in channel.h for more
// details.
template <typename ServerImpl, typename OnUnbound = std::nullptr_t>
ServerBindingRef<typename ServerImpl::_EnclosingProtocol> BindServer(
fdf_dispatcher_t* dispatcher, ServerEnd<typename ServerImpl::_EnclosingProtocol> server_end,
ServerImpl* impl, OnUnbound&& on_unbound = nullptr) {
static_assert(std::is_same_v<typename ServerImpl::_EnclosingProtocol::Transport,
fidl::internal::DriverTransport>);
return fidl::internal::BindServerImpl<ServerImpl>(
fdf_dispatcher_get_async_dispatcher(dispatcher), std::move(server_end), impl,
fidl::internal::UnboundThunk(std::move(impl), std::forward<OnUnbound>(on_unbound)));
}
// Overload of |BindServer| that takes ownership of the server as a |unique_ptr|.
// The pointer is destroyed on the same thread as the one calling |on_unbound|,
// and happens right after |on_unbound|.
//
// The behavior of |fdf::BindServer| is identical to |fidl::BindServer|, the
// specialization for channels. Please see documentation in channel.h for more
// details.
template <typename ServerImpl, typename OnUnbound = std::nullptr_t>
ServerBindingRef<typename ServerImpl::_EnclosingProtocol> BindServer(
fdf_dispatcher_t* dispatcher, ServerEnd<typename ServerImpl::_EnclosingProtocol> server_end,
std::unique_ptr<ServerImpl>&& impl, OnUnbound&& on_unbound = nullptr) {
static_assert(std::is_same_v<typename ServerImpl::_EnclosingProtocol::Transport,
fidl::internal::DriverTransport>);
ServerImpl* impl_raw = impl.get();
return fidl::internal::BindServerImpl<ServerImpl>(
fdf_dispatcher_get_async_dispatcher(dispatcher), std::move(server_end), impl_raw,
fidl::internal::UnboundThunk(std::move(impl), std::forward<OnUnbound>(on_unbound)));
}
// Overload of |BindServer| that shares ownership of the server via a |shared_ptr|.
// The pointer is destroyed on the same thread as the one calling |on_unbound|,
// and happens right after |on_unbound|.
//
// The behavior of |fdf::BindServer| is identical to |fidl::BindServer|, the
// specialization for channels. Please see documentation in channel.h for more
// details.
template <typename ServerImpl, typename OnUnbound = std::nullptr_t>
ServerBindingRef<typename ServerImpl::_EnclosingProtocol> BindServer(
fdf_dispatcher_t* dispatcher, ServerEnd<typename ServerImpl::_EnclosingProtocol> server_end,
std::shared_ptr<ServerImpl> impl, OnUnbound&& on_unbound = nullptr) {
static_assert(std::is_same_v<typename ServerImpl::_EnclosingProtocol::Transport,
fidl::internal::DriverTransport>);
ServerImpl* impl_raw = impl.get();
return fidl::internal::BindServerImpl<ServerImpl>(
fdf_dispatcher_get_async_dispatcher(dispatcher), std::move(server_end), impl_raw,
fidl::internal::UnboundThunk(std::move(impl), std::forward<OnUnbound>(on_unbound)));
}
} // namespace fdf
#endif // LIB_FIDL_DRIVER_INCLUDE_LIB_FIDL_DRIVER_CPP_SERVER_H_