//
// detail/impl/service_registry.ipp
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
// Copyright (c) 2003-2011 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//

#ifndef BOOST_ASIO_DETAIL_IMPL_SERVICE_REGISTRY_IPP
#define BOOST_ASIO_DETAIL_IMPL_SERVICE_REGISTRY_IPP

#if defined(_MSC_VER) && (_MSC_VER >= 1200)
# pragma once
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)

#include <boost/asio/detail/config.hpp>
#include <boost/throw_exception.hpp>
#include <vector>
#include <boost/asio/detail/service_registry.hpp>

#include <boost/asio/detail/push_options.hpp>

namespace boost {
namespace asio {
namespace detail {

service_registry::service_registry(boost::asio::io_service& o)
  : owner_(o),
    first_service_(0)
{
}

service_registry::~service_registry()
{
  // Shutdown all services. This must be done in a separate loop before the
  // services are destroyed since the destructors of user-defined handler
  // objects may try to access other service objects.
  boost::asio::io_service::service* service = first_service_;
  while (service)
  {
    service->shutdown_service();
    service = service->next_;
  }

  // Destroy all services.
  while (first_service_)
  {
    boost::asio::io_service::service* next_service = first_service_->next_;
    destroy(first_service_);
    first_service_ = next_service;
  }
}

void service_registry::notify_fork(boost::asio::io_service::fork_event fork_ev)
{
  // Make a copy of all of the services while holding the lock. We don't want
  // to hold the lock while calling into each service, as it may try to call
  // back into this class.
  std::vector<boost::asio::io_service::service*> services;
  {
    boost::asio::detail::mutex::scoped_lock lock(mutex_);
    boost::asio::io_service::service* service = first_service_;
    while (service)
    {
      services.push_back(service);
      service = service->next_;
    }
  }

  // If processing the fork_prepare event, we want to go in reverse order of
  // service registration, which happens to be the existing order of the
  // services in the vector. For the other events we want to go in the other
  // direction.
  std::size_t num_services = services.size();
  if (fork_ev == boost::asio::io_service::fork_prepare)
    for (std::size_t i = 0; i < num_services; ++i)
      services[i]->fork_service(fork_ev);
  else
    for (std::size_t i = num_services; i > 0; --i)
      services[i - 1]->fork_service(fork_ev);
}

void service_registry::init_key(boost::asio::io_service::service::key& key,
    const boost::asio::io_service::id& id)
{
  key.type_info_ = 0;
  key.id_ = &id;
}

bool service_registry::keys_match(
    const boost::asio::io_service::service::key& key1,
    const boost::asio::io_service::service::key& key2)
{
  if (key1.id_ && key2.id_)
    if (key1.id_ == key2.id_)
      return true;
  if (key1.type_info_ && key2.type_info_)
    if (*key1.type_info_ == *key2.type_info_)
      return true;
  return false;
}

void service_registry::destroy(boost::asio::io_service::service* service)
{
  delete service;
}

boost::asio::io_service::service* service_registry::do_use_service(
    const boost::asio::io_service::service::key& key,
    factory_type factory)
{
  boost::asio::detail::mutex::scoped_lock lock(mutex_);

  // First see if there is an existing service object with the given key.
  boost::asio::io_service::service* service = first_service_;
  while (service)
  {
    if (keys_match(service->key_, key))
      return service;
    service = service->next_;
  }

  // Create a new service object. The service registry's mutex is not locked
  // at this time to allow for nested calls into this function from the new
  // service's constructor.
  lock.unlock();
  auto_service_ptr new_service = { factory(owner_) };
  new_service.ptr_->key_ = key;
  lock.lock();

  // Check that nobody else created another service object of the same type
  // while the lock was released.
  service = first_service_;
  while (service)
  {
    if (keys_match(service->key_, key))
      return service;
    service = service->next_;
  }

  // Service was successfully initialised, pass ownership to registry.
  new_service.ptr_->next_ = first_service_;
  first_service_ = new_service.ptr_;
  new_service.ptr_ = 0;
  return first_service_;
}

void service_registry::do_add_service(
    const boost::asio::io_service::service::key& key,
    boost::asio::io_service::service* new_service)
{
  if (&owner_ != &new_service->get_io_service())
    boost::throw_exception(invalid_service_owner());

  boost::asio::detail::mutex::scoped_lock lock(mutex_);

  // Check if there is an existing service object with the given key.
  boost::asio::io_service::service* service = first_service_;
  while (service)
  {
    if (keys_match(service->key_, key))
      boost::throw_exception(service_already_exists());
    service = service->next_;
  }

  // Take ownership of the service object.
  new_service->key_ = key;
  new_service->next_ = first_service_;
  first_service_ = new_service;
}

bool service_registry::do_has_service(
    const boost::asio::io_service::service::key& key) const
{
  boost::asio::detail::mutex::scoped_lock lock(mutex_);

  boost::asio::io_service::service* service = first_service_;
  while (service)
  {
    if (keys_match(service->key_, key))
      return true;
    service = service->next_;
  }

  return false;
}

} // namespace detail
} // namespace asio
} // namespace boost

#include <boost/asio/detail/pop_options.hpp>

#endif // BOOST_ASIO_DETAIL_IMPL_SERVICE_REGISTRY_IPP
