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 
20 namespace asio {
21 
22 namespace 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  */
49 template <typename IoObjectService,
50     bool Movable = detail::service_has_move<IoObjectService>::value>
51 class basic_io_object
52 {
53 public:
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 
73 protected:
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 
131 private:
132   basic_io_object(const basic_io_object&);
133   basic_io_object& operator=(const basic_io_object&);
134 };
135 
136 // Specialisation for movable objects.
137 template <typename IoObjectService>
138 class basic_io_object<IoObjectService, true>
139 {
140 public:
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 
149 protected:
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 
197 private:
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