Statistics
| Revision:

root / tmp / org.txm.statsengine.r.core.win32 / res / win32 / library / BH / include / boost / asio / detail / impl / service_registry.ipp @ 2486

History | View | Annotate | Download (5.5 kB)

1
//
2
// detail/impl/service_registry.ipp
3
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
4
//
5
// Copyright (c) 2003-2015 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

    
11
#ifndef BOOST_ASIO_DETAIL_IMPL_SERVICE_REGISTRY_IPP
12
#define BOOST_ASIO_DETAIL_IMPL_SERVICE_REGISTRY_IPP
13

    
14
#if defined(_MSC_VER) && (_MSC_VER >= 1200)
15
# pragma once
16
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
17

    
18
#include <boost/asio/detail/config.hpp>
19
#include <vector>
20
#include <boost/asio/detail/service_registry.hpp>
21
#include <boost/asio/detail/throw_exception.hpp>
22

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

    
25
namespace boost {
26
namespace asio {
27
namespace detail {
28

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

    
41
  // Destroy all services.
42
  while (first_service_)
43
  {
44
    boost::asio::io_service::service* next_service = first_service_->next_;
45
    destroy(first_service_);
46
    first_service_ = next_service;
47
  }
48
}
49

    
50
void service_registry::notify_fork(boost::asio::io_service::fork_event fork_ev)
51
{
52
  // Make a copy of all of the services while holding the lock. We don't want
53
  // to hold the lock while calling into each service, as it may try to call
54
  // back into this class.
55
  std::vector<boost::asio::io_service::service*> services;
56
  {
57
    boost::asio::detail::mutex::scoped_lock lock(mutex_);
58
    boost::asio::io_service::service* service = first_service_;
59
    while (service)
60
    {
61
      services.push_back(service);
62
      service = service->next_;
63
    }
64
  }
65

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

    
79
void service_registry::init_key(boost::asio::io_service::service::key& key,
80
    const boost::asio::io_service::id& id)
81
{
82
  key.type_info_ = 0;
83
  key.id_ = &id;
84
}
85

    
86
bool service_registry::keys_match(
87
    const boost::asio::io_service::service::key& key1,
88
    const boost::asio::io_service::service::key& key2)
89
{
90
  if (key1.id_ && key2.id_)
91
    if (key1.id_ == key2.id_)
92
      return true;
93
  if (key1.type_info_ && key2.type_info_)
94
    if (*key1.type_info_ == *key2.type_info_)
95
      return true;
96
  return false;
97
}
98

    
99
void service_registry::destroy(boost::asio::io_service::service* service)
100
{
101
  delete service;
102
}
103

    
104
boost::asio::io_service::service* service_registry::do_use_service(
105
    const boost::asio::io_service::service::key& key,
106
    factory_type factory)
107
{
108
  boost::asio::detail::mutex::scoped_lock lock(mutex_);
109

    
110
  // First see if there is an existing service object with the given key.
111
  boost::asio::io_service::service* service = first_service_;
112
  while (service)
113
  {
114
    if (keys_match(service->key_, key))
115
      return service;
116
    service = service->next_;
117
  }
118

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

    
127
  // Check that nobody else created another service object of the same type
128
  // while the lock was released.
129
  service = first_service_;
130
  while (service)
131
  {
132
    if (keys_match(service->key_, key))
133
      return service;
134
    service = service->next_;
135
  }
136

    
137
  // Service was successfully initialised, pass ownership to registry.
138
  new_service.ptr_->next_ = first_service_;
139
  first_service_ = new_service.ptr_;
140
  new_service.ptr_ = 0;
141
  return first_service_;
142
}
143

    
144
void service_registry::do_add_service(
145
    const boost::asio::io_service::service::key& key,
146
    boost::asio::io_service::service* new_service)
147
{
148
  if (&owner_ != &new_service->get_io_service())
149
    boost::asio::detail::throw_exception(invalid_service_owner());
150

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

    
153
  // Check if there is an existing service object with the given key.
154
  boost::asio::io_service::service* service = first_service_;
155
  while (service)
156
  {
157
    if (keys_match(service->key_, key))
158
      boost::asio::detail::throw_exception(service_already_exists());
159
    service = service->next_;
160
  }
161

    
162
  // Take ownership of the service object.
163
  new_service->key_ = key;
164
  new_service->next_ = first_service_;
165
  first_service_ = new_service;
166
}
167

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

    
173
  boost::asio::io_service::service* service = first_service_;
174
  while (service)
175
  {
176
    if (keys_match(service->key_, key))
177
      return true;
178
    service = service->next_;
179
  }
180

    
181
  return false;
182
}
183

    
184
} // namespace detail
185
} // namespace asio
186
} // namespace boost
187

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

    
190
#endif // BOOST_ASIO_DETAIL_IMPL_SERVICE_REGISTRY_IPP