annotate DEPENDENCIES/generic/include/boost/asio/detail/impl/service_registry.ipp @ 133:4acb5d8d80b6 tip

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