1 // 2 // io_object_impl.hpp 3 // ~~~~~~~~~~~~~~~~~~ 4 // 5 // Copyright (c) 2003-2020 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_IO_OBJECT_IMPL_HPP 12 #define BOOST_ASIO_DETAIL_IO_OBJECT_IMPL_HPP 13 14 #if defined(_MSC_VER) && (_MSC_VER >= 1200) 15 # pragma once 16 #endif // defined(_MSC_VER) && (_MSC_VER >= 1200) 17 18 #include <new> 19 #include <boost/asio/detail/config.hpp> 20 #include <boost/asio/detail/type_traits.hpp> 21 #include <boost/asio/execution/executor.hpp> 22 #include <boost/asio/execution/context.hpp> 23 #include <boost/asio/io_context.hpp> 24 #include <boost/asio/query.hpp> 25 26 #include <boost/asio/detail/push_options.hpp> 27 28 namespace boost { 29 namespace asio { 30 namespace detail { 31 32 template <typename IoObjectService, 33 typename Executor = io_context::executor_type> 34 class io_object_impl 35 { 36 public: 37 // The type of the service that will be used to provide I/O operations. 38 typedef IoObjectService service_type; 39 40 // The underlying implementation type of I/O object. 41 typedef typename service_type::implementation_type implementation_type; 42 43 // The type of the executor associated with the object. 44 typedef Executor executor_type; 45 46 // Construct an I/O object using an executor. io_object_impl(const executor_type & ex)47 explicit io_object_impl(const executor_type& ex) 48 : service_(&boost::asio::use_service<IoObjectService>( 49 io_object_impl::get_context(ex))), 50 executor_(ex) 51 { 52 service_->construct(implementation_); 53 } 54 55 // Construct an I/O object using an execution context. 56 template <typename ExecutionContext> io_object_impl(ExecutionContext & context,typename enable_if<is_convertible<ExecutionContext &,execution_context &>::value>::type * =0)57 explicit io_object_impl(ExecutionContext& context, 58 typename enable_if<is_convertible< 59 ExecutionContext&, execution_context&>::value>::type* = 0) 60 : service_(&boost::asio::use_service<IoObjectService>(context)), 61 executor_(context.get_executor()) 62 { 63 service_->construct(implementation_); 64 } 65 66 #if defined(BOOST_ASIO_HAS_MOVE) 67 // Move-construct an I/O object. io_object_impl(io_object_impl && other)68 io_object_impl(io_object_impl&& other) 69 : service_(&other.get_service()), 70 executor_(other.get_executor()) 71 { 72 service_->move_construct(implementation_, other.implementation_); 73 } 74 75 // Perform a converting move-construction of an I/O object. 76 template <typename IoObjectService1, typename Executor1> io_object_impl(io_object_impl<IoObjectService1,Executor1> && other)77 io_object_impl(io_object_impl<IoObjectService1, Executor1>&& other) 78 : service_(&boost::asio::use_service<IoObjectService>( 79 io_object_impl::get_context(other.get_executor()))), 80 executor_(other.get_executor()) 81 { 82 service_->converting_move_construct(implementation_, 83 other.get_service(), other.get_implementation()); 84 } 85 #endif // defined(BOOST_ASIO_HAS_MOVE) 86 87 // Destructor. ~io_object_impl()88 ~io_object_impl() 89 { 90 service_->destroy(implementation_); 91 } 92 93 #if defined(BOOST_ASIO_HAS_MOVE) 94 // Move-assign an I/O object. operator =(io_object_impl && other)95 io_object_impl& operator=(io_object_impl&& other) 96 { 97 if (this != &other) 98 { 99 service_->move_assign(implementation_, 100 *other.service_, other.implementation_); 101 executor_.~executor_type(); 102 new (&executor_) executor_type( 103 std::move(other.executor_)); 104 service_ = other.service_; 105 } 106 return *this; 107 } 108 #endif // defined(BOOST_ASIO_HAS_MOVE) 109 110 // Get the executor associated with the object. get_executor()111 const executor_type& get_executor() BOOST_ASIO_NOEXCEPT 112 { 113 return executor_; 114 } 115 116 // Get the service associated with the I/O object. get_service()117 service_type& get_service() 118 { 119 return *service_; 120 } 121 122 // Get the service associated with the I/O object. get_service() const123 const service_type& get_service() const 124 { 125 return *service_; 126 } 127 128 // Get the underlying implementation of the I/O object. get_implementation()129 implementation_type& get_implementation() 130 { 131 return implementation_; 132 } 133 134 // Get the underlying implementation of the I/O object. get_implementation() const135 const implementation_type& get_implementation() const 136 { 137 return implementation_; 138 } 139 140 private: 141 // Helper function to get an executor's context. 142 template <typename T> get_context(const T & t,typename enable_if<execution::is_executor<T>::value>::type * =0)143 static execution_context& get_context(const T& t, 144 typename enable_if<execution::is_executor<T>::value>::type* = 0) 145 { 146 return boost::asio::query(t, execution::context); 147 } 148 149 // Helper function to get an executor's context. 150 template <typename T> get_context(const T & t,typename enable_if<!execution::is_executor<T>::value>::type * =0)151 static execution_context& get_context(const T& t, 152 typename enable_if<!execution::is_executor<T>::value>::type* = 0) 153 { 154 return t.context(); 155 } 156 157 // Disallow copying and copy assignment. 158 io_object_impl(const io_object_impl&); 159 io_object_impl& operator=(const io_object_impl&); 160 161 // The service associated with the I/O object. 162 service_type* service_; 163 164 // The underlying implementation of the I/O object. 165 implementation_type implementation_; 166 167 // The associated executor. 168 executor_type executor_; 169 }; 170 171 } // namespace detail 172 } // namespace asio 173 } // namespace boost 174 175 #include <boost/asio/detail/pop_options.hpp> 176 177 #endif // BOOST_ASIO_DETAIL_IO_OBJECT_IMPL_HPP 178