/Src/Dependencies/Boost/boost/asio/detail/impl/service_registry.ipp

http://hadesmem.googlecode.com/ · C++ Header · 196 lines · 139 code · 28 blank · 29 comment · 26 complexity · cf3be479b3a9180114ce86a52cb37c62 MD5 · raw file

  1. //
  2. // detail/impl/service_registry.ipp
  3. // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  4. //
  5. // Copyright (c) 2003-2011 Christopher M. Kohlhoff (chris at kohlhoff dot com)
  6. //
  7. // Distributed under the Boost Software License, Version 1.0. (See accompanying
  8. // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
  9. //
  10. #ifndef BOOST_ASIO_DETAIL_IMPL_SERVICE_REGISTRY_IPP
  11. #define BOOST_ASIO_DETAIL_IMPL_SERVICE_REGISTRY_IPP
  12. #if defined(_MSC_VER) && (_MSC_VER >= 1200)
  13. # pragma once
  14. #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
  15. #include <boost/asio/detail/config.hpp>
  16. #include <boost/throw_exception.hpp>
  17. #include <vector>
  18. #include <boost/asio/detail/service_registry.hpp>
  19. #include <boost/asio/detail/push_options.hpp>
  20. namespace boost {
  21. namespace asio {
  22. namespace detail {
  23. service_registry::service_registry(boost::asio::io_service& o)
  24. : owner_(o),
  25. first_service_(0)
  26. {
  27. }
  28. service_registry::~service_registry()
  29. {
  30. // Shutdown all services. This must be done in a separate loop before the
  31. // services are destroyed since the destructors of user-defined handler
  32. // objects may try to access other service objects.
  33. boost::asio::io_service::service* service = first_service_;
  34. while (service)
  35. {
  36. service->shutdown_service();
  37. service = service->next_;
  38. }
  39. // Destroy all services.
  40. while (first_service_)
  41. {
  42. boost::asio::io_service::service* next_service = first_service_->next_;
  43. destroy(first_service_);
  44. first_service_ = next_service;
  45. }
  46. }
  47. void service_registry::notify_fork(boost::asio::io_service::fork_event fork_ev)
  48. {
  49. // Make a copy of all of the services while holding the lock. We don't want
  50. // to hold the lock while calling into each service, as it may try to call
  51. // back into this class.
  52. std::vector<boost::asio::io_service::service*> services;
  53. {
  54. boost::asio::detail::mutex::scoped_lock lock(mutex_);
  55. boost::asio::io_service::service* service = first_service_;
  56. while (service)
  57. {
  58. services.push_back(service);
  59. service = service->next_;
  60. }
  61. }
  62. // If processing the fork_prepare event, we want to go in reverse order of
  63. // service registration, which happens to be the existing order of the
  64. // services in the vector. For the other events we want to go in the other
  65. // direction.
  66. std::size_t num_services = services.size();
  67. if (fork_ev == boost::asio::io_service::fork_prepare)
  68. for (std::size_t i = 0; i < num_services; ++i)
  69. services[i]->fork_service(fork_ev);
  70. else
  71. for (std::size_t i = num_services; i > 0; --i)
  72. services[i - 1]->fork_service(fork_ev);
  73. }
  74. void service_registry::init_key(boost::asio::io_service::service::key& key,
  75. const boost::asio::io_service::id& id)
  76. {
  77. key.type_info_ = 0;
  78. key.id_ = &id;
  79. }
  80. bool service_registry::keys_match(
  81. const boost::asio::io_service::service::key& key1,
  82. const boost::asio::io_service::service::key& key2)
  83. {
  84. if (key1.id_ && key2.id_)
  85. if (key1.id_ == key2.id_)
  86. return true;
  87. if (key1.type_info_ && key2.type_info_)
  88. if (*key1.type_info_ == *key2.type_info_)
  89. return true;
  90. return false;
  91. }
  92. void service_registry::destroy(boost::asio::io_service::service* service)
  93. {
  94. delete service;
  95. }
  96. boost::asio::io_service::service* service_registry::do_use_service(
  97. const boost::asio::io_service::service::key& key,
  98. factory_type factory)
  99. {
  100. boost::asio::detail::mutex::scoped_lock lock(mutex_);
  101. // First see if there is an existing service object with the given key.
  102. boost::asio::io_service::service* service = first_service_;
  103. while (service)
  104. {
  105. if (keys_match(service->key_, key))
  106. return service;
  107. service = service->next_;
  108. }
  109. // Create a new service object. The service registry's mutex is not locked
  110. // at this time to allow for nested calls into this function from the new
  111. // service's constructor.
  112. lock.unlock();
  113. auto_service_ptr new_service = { factory(owner_) };
  114. new_service.ptr_->key_ = key;
  115. lock.lock();
  116. // Check that nobody else created another service object of the same type
  117. // while the lock was released.
  118. service = first_service_;
  119. while (service)
  120. {
  121. if (keys_match(service->key_, key))
  122. return service;
  123. service = service->next_;
  124. }
  125. // Service was successfully initialised, pass ownership to registry.
  126. new_service.ptr_->next_ = first_service_;
  127. first_service_ = new_service.ptr_;
  128. new_service.ptr_ = 0;
  129. return first_service_;
  130. }
  131. void service_registry::do_add_service(
  132. const boost::asio::io_service::service::key& key,
  133. boost::asio::io_service::service* new_service)
  134. {
  135. if (&owner_ != &new_service->get_io_service())
  136. boost::throw_exception(invalid_service_owner());
  137. boost::asio::detail::mutex::scoped_lock lock(mutex_);
  138. // Check if there is an existing service object with the given key.
  139. boost::asio::io_service::service* service = first_service_;
  140. while (service)
  141. {
  142. if (keys_match(service->key_, key))
  143. boost::throw_exception(service_already_exists());
  144. service = service->next_;
  145. }
  146. // Take ownership of the service object.
  147. new_service->key_ = key;
  148. new_service->next_ = first_service_;
  149. first_service_ = new_service;
  150. }
  151. bool service_registry::do_has_service(
  152. const boost::asio::io_service::service::key& key) const
  153. {
  154. boost::asio::detail::mutex::scoped_lock lock(mutex_);
  155. boost::asio::io_service::service* service = first_service_;
  156. while (service)
  157. {
  158. if (keys_match(service->key_, key))
  159. return true;
  160. service = service->next_;
  161. }
  162. return false;
  163. }
  164. } // namespace detail
  165. } // namespace asio
  166. } // namespace boost
  167. #include <boost/asio/detail/pop_options.hpp>
  168. #endif // BOOST_ASIO_DETAIL_IMPL_SERVICE_REGISTRY_IPP