~ubuntu-branches/ubuntu/maverick/libtorrent-rasterbar/maverick

« back to all changes in this revision

Viewing changes to include/libtorrent/asio/detail/service_registry.hpp

  • Committer: Bazaar Package Importer
  • Author(s): Christophe Sauthier
  • Date: 2010-08-10 12:59:37 UTC
  • mfrom: (1.3.7 upstream)
  • Revision ID: james.westby@ubuntu.com-20100810125937-jbcmmf17y8yo9hgz
Tags: 0.15.0-0ubuntu1
* New upstream version.
* debian/patches/100_fix_html_docs.patch: refreshed.
* debian/control: bump up standards-version to 3.9.1 (no changes).

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
//
2
 
// service_registry.hpp
3
 
// ~~~~~~~~~~~~~~~~~~~~
4
 
//
5
 
// Copyright (c) 2003-2008 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 ASIO_DETAIL_SERVICE_REGISTRY_HPP
12
 
#define ASIO_DETAIL_SERVICE_REGISTRY_HPP
13
 
 
14
 
#if defined(_MSC_VER) && (_MSC_VER >= 1200)
15
 
# pragma once
16
 
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
17
 
 
18
 
#include "asio/detail/push_options.hpp"
19
 
 
20
 
#include "asio/detail/push_options.hpp"
21
 
#include <memory>
22
 
#include <typeinfo>
23
 
#include "asio/detail/pop_options.hpp"
24
 
 
25
 
#include "asio/io_service.hpp"
26
 
#include "asio/detail/mutex.hpp"
27
 
#include "asio/detail/noncopyable.hpp"
28
 
#include "asio/detail/service_id.hpp"
29
 
 
30
 
#if defined(BOOST_NO_TYPEID)
31
 
# if !defined(ASIO_NO_TYPEID)
32
 
#  define ASIO_NO_TYPEID
33
 
# endif // !defined(ASIO_NO_TYPEID)
34
 
#endif // defined(BOOST_NO_TYPEID)
35
 
 
36
 
namespace asio {
37
 
namespace detail {
38
 
 
39
 
class service_registry
40
 
  : private noncopyable
41
 
{
42
 
public:
43
 
  // Constructor.
44
 
  service_registry(asio::io_service& o)
45
 
    : owner_(o),
46
 
      first_service_(0)
47
 
  {
48
 
  }
49
 
 
50
 
  // Destructor.
51
 
  ~service_registry()
52
 
  {
53
 
    // Shutdown all services. This must be done in a separate loop before the
54
 
    // services are destroyed since the destructors of user-defined handler
55
 
    // objects may try to access other service objects.
56
 
    asio::io_service::service* service = first_service_;
57
 
    while (service)
58
 
    {
59
 
      service->shutdown_service();
60
 
      service = service->next_;
61
 
    }
62
 
 
63
 
    // Destroy all services.
64
 
    while (first_service_)
65
 
    {
66
 
      asio::io_service::service* next_service = first_service_->next_;
67
 
      delete first_service_;
68
 
      first_service_ = next_service;
69
 
    }
70
 
  }
71
 
 
72
 
  // Get the service object corresponding to the specified service type. Will
73
 
  // create a new service object automatically if no such object already
74
 
  // exists. Ownership of the service object is not transferred to the caller.
75
 
  template <typename Service>
76
 
  Service& use_service()
77
 
  {
78
 
    asio::detail::mutex::scoped_lock lock(mutex_);
79
 
 
80
 
    // First see if there is an existing service object for the given type.
81
 
    asio::io_service::service* service = first_service_;
82
 
    while (service)
83
 
    {
84
 
      if (service_id_matches(*service, Service::id))
85
 
        return *static_cast<Service*>(service);
86
 
      service = service->next_;
87
 
    }
88
 
 
89
 
    // Create a new service object. The service registry's mutex is not locked
90
 
    // at this time to allow for nested calls into this function from the new
91
 
    // service's constructor.
92
 
    lock.unlock();
93
 
    std::auto_ptr<Service> new_service(new Service(owner_));
94
 
    init_service_id(*new_service, Service::id);
95
 
    Service& new_service_ref = *new_service;
96
 
    lock.lock();
97
 
 
98
 
    // Check that nobody else created another service object of the same type
99
 
    // while the lock was released.
100
 
    service = first_service_;
101
 
    while (service)
102
 
    {
103
 
      if (service_id_matches(*service, Service::id))
104
 
        return *static_cast<Service*>(service);
105
 
      service = service->next_;
106
 
    }
107
 
 
108
 
    // Service was successfully initialised, pass ownership to registry.
109
 
    new_service->next_ = first_service_;
110
 
    first_service_ = new_service.release();
111
 
 
112
 
    return new_service_ref;
113
 
  }
114
 
 
115
 
  // Add a service object. Returns false on error, in which case ownership of
116
 
  // the object is retained by the caller.
117
 
  template <typename Service>
118
 
  bool add_service(Service* new_service)
119
 
  {
120
 
    asio::detail::mutex::scoped_lock lock(mutex_);
121
 
 
122
 
    // Check if there is an existing service object for the given type.
123
 
    asio::io_service::service* service = first_service_;
124
 
    while (service)
125
 
    {
126
 
      if (service_id_matches(*service, Service::id))
127
 
        return false;
128
 
      service = service->next_;
129
 
    }
130
 
 
131
 
    // Take ownership of the service object.
132
 
    init_service_id(*new_service, Service::id);
133
 
    new_service->next_ = first_service_;
134
 
    first_service_ = new_service;
135
 
 
136
 
    return true;
137
 
  }
138
 
 
139
 
  // Check whether a service object of the specified type already exists.
140
 
  template <typename Service>
141
 
  bool has_service() const
142
 
  {
143
 
    asio::detail::mutex::scoped_lock lock(mutex_);
144
 
 
145
 
    asio::io_service::service* service = first_service_;
146
 
    while (service)
147
 
    {
148
 
      if (service_id_matches(*service, Service::id))
149
 
        return true;
150
 
      service = service->next_;
151
 
    }
152
 
 
153
 
    return false;
154
 
  }
155
 
 
156
 
private:
157
 
  // Set a service's id.
158
 
  void init_service_id(asio::io_service::service& service,
159
 
      const asio::io_service::id& id)
160
 
  {
161
 
    service.type_info_ = 0;
162
 
    service.id_ = &id;
163
 
  }
164
 
 
165
 
#if !defined(ASIO_NO_TYPEID)
166
 
  // Set a service's id.
167
 
  template <typename Service>
168
 
  void init_service_id(asio::io_service::service& service,
169
 
      const asio::detail::service_id<Service>& /*id*/)
170
 
  {
171
 
    service.type_info_ = &typeid(Service);
172
 
    service.id_ = 0;
173
 
  }
174
 
#endif // !defined(ASIO_NO_TYPEID)
175
 
 
176
 
  // Check if a service matches the given id.
177
 
  static bool service_id_matches(
178
 
      const asio::io_service::service& service,
179
 
      const asio::io_service::id& id)
180
 
  {
181
 
    return service.id_ == &id;
182
 
  }
183
 
 
184
 
#if !defined(ASIO_NO_TYPEID)
185
 
  // Check if a service matches the given id.
186
 
  template <typename Service>
187
 
  static bool service_id_matches(
188
 
      const asio::io_service::service& service,
189
 
      const asio::detail::service_id<Service>& /*id*/)
190
 
  {
191
 
    return service.type_info_ != 0 && *service.type_info_ == typeid(Service);
192
 
  }
193
 
#endif // !defined(ASIO_NO_TYPEID)
194
 
 
195
 
  // Mutex to protect access to internal data.
196
 
  mutable asio::detail::mutex mutex_;
197
 
 
198
 
  // The owner of this service registry and the services it contains.
199
 
  asio::io_service& owner_;
200
 
 
201
 
  // The first service in the list of contained services.
202
 
  asio::io_service::service* first_service_;
203
 
};
204
 
 
205
 
} // namespace detail
206
 
} // namespace asio
207
 
 
208
 
#include "asio/detail/pop_options.hpp"
209
 
 
210
 
#endif // ASIO_DETAIL_SERVICE_REGISTRY_HPP