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