// 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.

#ifndef LIB_FIDL_CPP_THREAD_SAFE_BINDING_SET_H_
#define LIB_FIDL_CPP_THREAD_SAFE_BINDING_SET_H_

#include <lib/async/dispatcher.h>
#include <zircon/compiler.h>

#include <algorithm>
#include <memory>
#include <mutex>
#include <utility>
#include <vector>

#include "lib/fidl/cpp/binding.h"

namespace fidl {

// Manages a set of bindings to implemenations owned by the bound channels.
//
// The implementation pointer type of the binding is also parameterized,
// allowing the use of smart pointer types such as |std::unique_ptr<>| to
// reference the implementation.
//
// This class is thread-safe; bindings may be added or cleared from any thread.
//
// See also:
//
//  * |BindingSet|, which is the thread-hostile analog that offers more
//    functionality.
//  * |InterfacePtrSet|, which is the client analog of |BindingSet|.
template <typename Interface, typename ImplPtr = Interface*>
class DeprecatedBrokenBindingSet final {
 public:
  using Binding = ::fidl::Binding<Interface, ImplPtr>;
  using StorageType = std::vector<std::unique_ptr<Binding>>;

  DeprecatedBrokenBindingSet() = default;

  DeprecatedBrokenBindingSet(const DeprecatedBrokenBindingSet&) = delete;
  DeprecatedBrokenBindingSet& operator=(const DeprecatedBrokenBindingSet&) = delete;

  // Adds a binding to the set.
  //
  // The given |ImplPtr| is bound to the channel underlying the
  // |InterfaceRequest|. The binding is removed (and the |~ImplPtr| called)
  // when the created binding has an error (e.g., if the remote endpoint of
  // the channel sends an invalid message).
  //
  // Whether this method takes ownership of |impl| depends on |ImplPtr|. If
  // |ImplPtr| is a raw pointer, then this method does not take ownership of
  // |impl|. If |ImplPtr| is a |unique_ptr|, then running |~ImplPtr| when the
  // binding generates an error will delete |impl| because |~ImplPtr| is
  // |~unique_ptr|, which deletes |impl|.
  //
  // The impl will use the given async_dispatcher_t in order to read messages
  // from the channel and to monitor the channel for |ZX_CHANNEL_PEER_CLOSED|.
  // It is not necessary to use the same async_dispatcher_t for each binding
  // added.
  void AddBinding(ImplPtr impl, InterfaceRequest<Interface> request,
                  async_dispatcher_t* dispatcher) {
    std::lock_guard<std::mutex> guard(lock_);
    bindings_.push_back(
        std::make_unique<Binding>(std::forward<ImplPtr>(impl), std::move(request), dispatcher));
    auto* binding = bindings_.back().get();
    // Set the connection error handler for the newly added Binding to be a
    // function that will erase it from the vector.
    binding->set_error_handler(
        [binding, this](zx_status_t status) { this->RemoveOnError(binding); });
  }

  // Adds a binding to the set for the given implementation.
  //
  // Creates a channel for the binding and returns the client endpoint of
  // the channel as an |InterfaceHandle|. If |AddBinding| fails to create the
  // underlying channel, the returned |InterfaceHandle| will return false from
  // |is_valid()|.
  //
  // The given |ImplPtr| is bound to the newly created channel. The binding is
  // removed (and the |~ImplPtr| called) when the created binding has an error
  // (e.g., if the remote endpoint of the channel sends an invalid message).
  //
  // Whether this method takes ownership of |impl| depends on |ImplPtr|. If
  // |ImplPtr| is a raw pointer, then this method does not take ownership of
  // |impl|. If |ImplPtr| is a |unique_ptr|, then running |~ImplPtr| when the
  // binding generates an error will delete |impl| because |~ImplPtr| is
  // |~unique_ptr|, which deletes |impl|.
  InterfaceHandle<Interface> AddBinding(ImplPtr impl, async_dispatcher_t* dispatcher) {
    InterfaceHandle<Interface> handle;
    InterfaceRequest<Interface> request = handle.NewRequest();
    if (!request)
      return nullptr;
    AddBinding(std::forward<ImplPtr>(impl), std::move(request), dispatcher);
    return handle;
  }

  // Removes all the bindings from the set.
  //
  // Closes all the channels associated with this |BindingSet|.
  void CloseAll() {
    std::lock_guard<std::mutex> guard(lock_);
    bindings_.clear();
  }

 private:
  // Called when a binding has an error to remove the binding from the set.
  void RemoveOnError(Binding* binding) {
    std::lock_guard<std::mutex> guard(lock_);
    auto it =
        std::find_if(bindings_.begin(), bindings_.end(),
                     [binding](const std::unique_ptr<Binding>& b) { return b.get() == binding; });
    ZX_DEBUG_ASSERT(it != bindings_.end());
    (*it)->set_error_handler(nullptr);
    bindings_.erase(it);
  }

  std::mutex lock_;
  StorageType bindings_ __TA_GUARDED(lock_);
};

}  // namespace fidl

#endif  // LIB_FIDL_CPP_THREAD_SAFE_BINDING_SET_H_
