blob: 6f33e77196c32f74106f76b6301e9c513cbeffaa [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 SRC_CONNECTIVITY_NETWORK_MDNS_SERVICE_SERVICES_SERVICE_IMPL_MANAGER_H_
#define SRC_CONNECTIVITY_NETWORK_MDNS_SERVICE_SERVICES_SERVICE_IMPL_MANAGER_H_
#include <lib/fidl/cpp/binding.h>
#include <lib/fit/function.h>
#include <lib/sys/cpp/component_context.h>
#include <unordered_map>
namespace mdns {
template <typename TProtocol>
class ServiceImplManager {
public:
using Deleter = fit::closure;
using Creator =
fit::function<std::unique_ptr<TProtocol>(fidl::InterfaceRequest<TProtocol>, Deleter)>;
ServiceImplManager(Creator creator) : creator_(std::move(creator)) {}
virtual ~ServiceImplManager() = default;
// Adds the managed service as in outgoing public service of |component_context|.
void AddOutgoingPublicService(sys::ComponentContext* component_context) {
component_context->outgoing()->AddPublicService<TProtocol>(
fit::bind_member<&ServiceImplManager<TProtocol>::Connect>(this));
}
// Satisfies |request| by calling the creator to create a service implementation instance bound to
// |request|. If |OnReady| has not yet been called, the creation is deferred until it is. The
// created service implementation instance is kept alive by this manager until the instance calls
// the deleter passed to the creator.
void Connect(fidl::InterfaceRequest<TProtocol> request) {
size_t id = next_id_++;
if (ready_) {
// We're ready, so go ahead and create the implementation.
impls_by_id_.emplace(
id, std::move(creator_(std::move(request), [this, id]() { impls_by_id_.erase(id); })));
} else {
// We're not ready, so store the connect parameters until we are.
requests_by_id_.emplace(id, std::move(request));
}
}
// Transitions the manager to ready state, performing all deferred |Connect| operations.
void OnReady() {
for (auto& pair : requests_by_id_) {
size_t id = pair.first;
impls_by_id_.emplace(id, std::move(creator_(std::move(pair.second),
[this, id]() { impls_by_id_.erase(id); })));
}
requests_by_id_.clear();
ready_ = true;
}
private:
Creator creator_;
bool ready_ = false;
size_t next_id_ = 0;
std::unordered_map<size_t, std::unique_ptr<TProtocol>> impls_by_id_;
std::unordered_map<size_t, fidl::InterfaceRequest<TProtocol>> requests_by_id_;
};
} // namespace mdns
#endif // SRC_CONNECTIVITY_NETWORK_MDNS_SERVICE_SERVICES_SERVICE_IMPL_MANAGER_H_