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