1//
2// basic_io_object.hpp
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 ASIO_BASIC_IO_OBJECT_HPP
12#define ASIO_BASIC_IO_OBJECT_HPP
13
14
15#include "asio/detail/config.hpp"
16#include "asio/io_service.hpp"
17
18#include "asio/detail/push_options.hpp"
19
20namespace asio {
21
22namespace detail
23{
24  // Type trait used to determine whether a service supports move.
25  template <typename IoObjectService>
26  class service_has_move
27  {
28  private:
29    typedef IoObjectService service_type;
30    typedef typename service_type::implementation_type implementation_type;
31
32    template <typename T, typename U>
33    static auto eval(T* t, U* u) -> decltype(t->move_construct(*u, *u), char());
34    static char (&eval(...))[2];
35
36  public:
37    static const bool value =
38      sizeof(service_has_move::eval(
39        static_cast<service_type*>(0),
40        static_cast<implementation_type*>(0))) == 1;
41  };
42}
43
44/// Base class for all I/O objects.
45/**
46 * @note All I/O objects are non-copyable. However, when using C++0x, certain
47 * I/O objects do support move construction and move assignment.
48 */
49template <typename IoObjectService,
50    bool Movable = detail::service_has_move<IoObjectService>::value>
51class basic_io_object
52{
53public:
54  /// The type of the service that will be used to provide I/O operations.
55  typedef IoObjectService service_type;
56
57  /// The underlying implementation type of I/O object.
58  typedef typename service_type::implementation_type implementation_type;
59
60  /// Get the io_service associated with the object.
61  /**
62   * This function may be used to obtain the io_service object that the I/O
63   * object uses to dispatch handlers for asynchronous operations.
64   *
65   * @return A reference to the io_service object that the I/O object will use
66   * to dispatch handlers. Ownership is not transferred to the caller.
67   */
68  asio::io_service& get_io_service()
69  {
70    return service.get_io_service();
71  }
72
73protected:
74  /// Construct a basic_io_object.
75  /**
76   * Performs:
77   * @code get_service().construct(get_implementation()); @endcode
78   */
79  explicit basic_io_object(asio::io_service& io_service)
80    : service(asio::use_service<IoObjectService>(io_service))
81  {
82    service.construct(implementation);
83  }
84
85
86  /// Protected destructor to prevent deletion through this type.
87  /**
88   * Performs:
89   * @code get_service().destroy(get_implementation()); @endcode
90   */
91  ~basic_io_object()
92  {
93    service.destroy(implementation);
94  }
95
96  /// Get the service associated with the I/O object.
97  service_type& get_service()
98  {
99    return service;
100  }
101
102  /// Get the service associated with the I/O object.
103  const service_type& get_service() const
104  {
105    return service;
106  }
107
108  /// (Deprecated: Use get_service().) The service associated with the I/O
109  /// object.
110  /**
111   * @note Available only for services that do not support movability.
112   */
113  service_type& service;
114
115  /// Get the underlying implementation of the I/O object.
116  implementation_type& get_implementation()
117  {
118    return implementation;
119  }
120
121  /// Get the underlying implementation of the I/O object.
122  const implementation_type& get_implementation() const
123  {
124    return implementation;
125  }
126
127  /// (Deprecated: Use get_implementation().) The underlying implementation of
128  /// the I/O object.
129  implementation_type implementation;
130
131private:
132  basic_io_object(const basic_io_object&);
133  basic_io_object& operator=(const basic_io_object&);
134};
135
136// Specialisation for movable objects.
137template <typename IoObjectService>
138class basic_io_object<IoObjectService, true>
139{
140public:
141  typedef IoObjectService service_type;
142  typedef typename service_type::implementation_type implementation_type;
143
144  asio::io_service& get_io_service()
145  {
146    return service_->get_io_service();
147  }
148
149protected:
150  explicit basic_io_object(asio::io_service& io_service)
151    : service_(&asio::use_service<IoObjectService>(io_service))
152  {
153    service_->construct(implementation);
154  }
155
156  basic_io_object(basic_io_object&& other)
157    : service_(&other.get_service())
158  {
159    service_->move_construct(implementation, other.implementation);
160  }
161
162  ~basic_io_object()
163  {
164    service_->destroy(implementation);
165  }
166
167  basic_io_object& operator=(basic_io_object&& other)
168  {
169    service_->move_assign(implementation,
170        *other.service_, other.implementation);
171    service_ = other.service_;
172    return *this;
173  }
174
175  service_type& get_service()
176  {
177    return *service_;
178  }
179
180  const service_type& get_service() const
181  {
182    return *service_;
183  }
184
185  implementation_type& get_implementation()
186  {
187    return implementation;
188  }
189
190  const implementation_type& get_implementation() const
191  {
192    return implementation;
193  }
194
195  implementation_type implementation;
196
197private:
198  basic_io_object(const basic_io_object&);
199  void operator=(const basic_io_object&);
200
201  IoObjectService* service_;
202};
203
204} // namespace asio
205
206#include "asio/detail/pop_options.hpp"
207
208#endif // ASIO_BASIC_IO_OBJECT_HPP
209