blob: 345b1a720a12530bd7ed45710bf2ce01aaec5ec3 [file] [log] [blame]
// Copyright 2019 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_ASYNC_CPP_ASYNC_TRANSACTION_H_
#define LIB_FIDL_ASYNC_CPP_ASYNC_TRANSACTION_H_
#include <lib/fidl/llcpp/async_binding.h>
#include <lib/fidl/llcpp/transaction.h>
#include <lib/zx/channel.h>
#include <zircon/fidl.h>
#include <memory>
#include <utility>
namespace fidl {
namespace internal {
// An implementation of |fidl::Transaction|. Designed to work with |fidl::AsyncBind|, which allows
// message dispatching of multiple in-flight asynchronous transactions from a multi-threaded
// |dispatcher|. Note that |AsyncTransaction| itself assumes that only one thread at a time will act
// on it.
// The channel is owned by |AsyncBinding|, not the transaction.
class AsyncTransaction final : public Transaction {
public:
explicit AsyncTransaction(zx_txid_t txid, TypeErasedServerDispatchFn dispatch_fn,
bool* binding_released, zx_status_t* resume_status)
: Transaction(),
txid_(txid),
dispatch_fn_(dispatch_fn),
binding_released_(binding_released),
resume_status_(resume_status) {}
AsyncTransaction(AsyncTransaction&& other) noexcept : Transaction(std::move(other)) {
if (this != &other) {
MoveImpl(std::move(other));
}
}
AsyncTransaction& operator=(AsyncTransaction&& other) noexcept {
Transaction::operator=(std::move(other));
if (this != &other) {
MoveImpl(std::move(other));
}
return *this;
}
virtual ~AsyncTransaction() { ZX_ASSERT(!owned_binding_); }
void Reply(fidl::Message msg) final;
void EnableNextDispatch() final;
void Close(zx_status_t epitaph) final;
std::unique_ptr<Transaction> TakeOwnership() final;
private:
friend fidl::internal::AsyncBinding;
void Dispatch(std::shared_ptr<AsyncBinding>&& binding, fidl_msg_t* msg);
void MoveImpl(AsyncTransaction&& other) noexcept {
txid_ = other.txid_;
other.txid_ = 0;
owned_binding_ = std::move(other.owned_binding_);
unowned_binding_ = std::move(other.unowned_binding_);
binding_released_ = other.binding_released_;
other.binding_released_ = nullptr;
resume_status_ = other.resume_status_;
other.resume_status_ = nullptr;
}
zx_txid_t txid_ = 0;
// An AsyncTransaction may only access the AsyncBinding via one of owned_binding_ or
// unowned_binding_. On Dispatch(), the AsyncTransaction takes ownership of the internal reference
// used by the dispatcher (keep_alive_) in owned_binding_. Calls to EnableNextDispatch(), Close(),
// or TakeOwnership() within the scope of Dispatch() move the reference back into keep_alive_,
// setting unowned_binding_. Otherwise, keep_alive_ is restored from owned_binding_ prior to
// Dispatch() returning.
std::shared_ptr<AsyncBinding> owned_binding_ = {};
std::weak_ptr<AsyncBinding> unowned_binding_ = {};
TypeErasedServerDispatchFn dispatch_fn_ = {};
bool* binding_released_ = nullptr;
zx_status_t* resume_status_ = nullptr;
bool* moved_ = nullptr;
};
} // namespace internal
} // namespace fidl
#endif // LIB_FIDL_ASYNC_CPP_ASYNC_TRANSACTION_H_