1 // 2 // io_object_impl.hpp 3 // ~~~~~~~~~~~~~~~~~~ 4 // 5 // Copyright (c) 2003-2021 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(int,const executor_type & ex)47 explicit io_object_impl(int, 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(int,int,ExecutionContext & context)57 explicit io_object_impl(int, int, ExecutionContext& context) 58 : service_(&boost::asio::use_service<IoObjectService>(context)), 59 executor_(context.get_executor()) 60 { 61 service_->construct(implementation_); 62 } 63 64 #if defined(BOOST_ASIO_HAS_MOVE) 65 // Move-construct an I/O object. io_object_impl(io_object_impl && other)66 io_object_impl(io_object_impl&& other) 67 : service_(&other.get_service()), 68 executor_(other.get_executor()) 69 { 70 service_->move_construct(implementation_, other.implementation_); 71 } 72 73 // Perform a converting move-construction of an I/O object. 74 template <typename IoObjectService1, typename Executor1> io_object_impl(io_object_impl<IoObjectService1,Executor1> && other)75 io_object_impl(io_object_impl<IoObjectService1, Executor1>&& other) 76 : service_(&boost::asio::use_service<IoObjectService>( 77 io_object_impl::get_context(other.get_executor()))), 78 executor_(other.get_executor()) 79 { 80 service_->converting_move_construct(implementation_, 81 other.get_service(), other.get_implementation()); 82 } 83 #endif // defined(BOOST_ASIO_HAS_MOVE) 84 85 // Destructor. ~io_object_impl()86 ~io_object_impl() 87 { 88 service_->destroy(implementation_); 89 } 90 91 #if defined(BOOST_ASIO_HAS_MOVE) 92 // Move-assign an I/O object. operator =(io_object_impl && other)93 io_object_impl& operator=(io_object_impl&& other) 94 { 95 if (this != &other) 96 { 97 service_->move_assign(implementation_, 98 *other.service_, other.implementation_); 99 executor_.~executor_type(); 100 new (&executor_) executor_type(other.executor_); 101 service_ = other.service_; 102 } 103 return *this; 104 } 105 #endif // defined(BOOST_ASIO_HAS_MOVE) 106 107 // Get the executor associated with the object. get_executor()108 const executor_type& get_executor() BOOST_ASIO_NOEXCEPT 109 { 110 return executor_; 111 } 112 113 // Get the service associated with the I/O object. get_service()114 service_type& get_service() 115 { 116 return *service_; 117 } 118 119 // Get the service associated with the I/O object. get_service() const120 const service_type& get_service() const 121 { 122 return *service_; 123 } 124 125 // Get the underlying implementation of the I/O object. get_implementation()126 implementation_type& get_implementation() 127 { 128 return implementation_; 129 } 130 131 // Get the underlying implementation of the I/O object. get_implementation() const132 const implementation_type& get_implementation() const 133 { 134 return implementation_; 135 } 136 137 private: 138 // Helper function to get an executor's context. 139 template <typename T> get_context(const T & t,typename enable_if<execution::is_executor<T>::value>::type * =0)140 static execution_context& get_context(const T& t, 141 typename enable_if<execution::is_executor<T>::value>::type* = 0) 142 { 143 return boost::asio::query(t, execution::context); 144 } 145 146 // Helper function to get an executor's context. 147 template <typename T> get_context(const T & t,typename enable_if<!execution::is_executor<T>::value>::type * =0)148 static execution_context& get_context(const T& t, 149 typename enable_if<!execution::is_executor<T>::value>::type* = 0) 150 { 151 return t.context(); 152 } 153 154 // Disallow copying and copy assignment. 155 io_object_impl(const io_object_impl&); 156 io_object_impl& operator=(const io_object_impl&); 157 158 // The service associated with the I/O object. 159 service_type* service_; 160 161 // The underlying implementation of the I/O object. 162 implementation_type implementation_; 163 164 // The associated executor. 165 executor_type executor_; 166 }; 167 168 } // namespace detail 169 } // namespace asio 170 } // namespace boost 171 172 #include <boost/asio/detail/pop_options.hpp> 173 174 #endif // BOOST_ASIO_DETAIL_IO_OBJECT_IMPL_HPP 175