]> git.proxmox.com Git - ceph.git/blob - ceph/src/boost/boost/asio/buffer_registration.hpp
update ceph source to reef 18.1.2
[ceph.git] / ceph / src / boost / boost / asio / buffer_registration.hpp
1 //
2 // buffer_registration.hpp
3 // ~~~~~~~~~~~~~~~~~~~~~~~
4 //
5 // Copyright (c) 2003-2022 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_BUFFER_REGISTRATION_HPP
12 #define BOOST_ASIO_BUFFER_REGISTRATION_HPP
13
14 #if defined(_MSC_VER) && (_MSC_VER >= 1200)
15 # pragma once
16 #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
17
18 #include <boost/asio/detail/config.hpp>
19 #include <iterator>
20 #include <vector>
21 #include <boost/asio/detail/memory.hpp>
22 #include <boost/asio/execution/context.hpp>
23 #include <boost/asio/execution/executor.hpp>
24 #include <boost/asio/execution_context.hpp>
25 #include <boost/asio/is_executor.hpp>
26 #include <boost/asio/query.hpp>
27 #include <boost/asio/registered_buffer.hpp>
28
29 #if defined(BOOST_ASIO_HAS_IO_URING)
30 # include <boost/asio/detail/scheduler.hpp>
31 # include <boost/asio/detail/io_uring_service.hpp>
32 #endif // defined(BOOST_ASIO_HAS_IO_URING)
33
34 #if defined(BOOST_ASIO_HAS_MOVE)
35 # include <utility>
36 #endif // defined(BOOST_ASIO_HAS_MOVE)
37
38 #include <boost/asio/detail/push_options.hpp>
39
40 namespace boost {
41 namespace asio {
42 namespace detail {
43
44 class buffer_registration_base
45 {
46 protected:
47 static mutable_registered_buffer make_buffer(const mutable_buffer& b,
48 const void* scope, int index) BOOST_ASIO_NOEXCEPT
49 {
50 return mutable_registered_buffer(b, registered_buffer_id(scope, index));
51 }
52 };
53
54 } // namespace detail
55
56 /// Automatically registers and unregistered buffers with an execution context.
57 /**
58 * For portability, applications should assume that only one registration is
59 * permitted per execution context.
60 */
61 template <typename MutableBufferSequence,
62 typename Allocator = std::allocator<void> >
63 class buffer_registration
64 : detail::buffer_registration_base
65 {
66 public:
67 /// The allocator type used for allocating storage for the buffers container.
68 typedef Allocator allocator_type;
69
70 #if defined(GENERATING_DOCUMENTATION)
71 /// The type of an iterator over the registered buffers.
72 typedef unspecified iterator;
73
74 /// The type of a const iterator over the registered buffers.
75 typedef unspecified const_iterator;
76 #else // defined(GENERATING_DOCUMENTATION)
77 typedef std::vector<mutable_registered_buffer>::const_iterator iterator;
78 typedef std::vector<mutable_registered_buffer>::const_iterator const_iterator;
79 #endif // defined(GENERATING_DOCUMENTATION)
80
81 /// Register buffers with an executor's execution context.
82 template <typename Executor>
83 buffer_registration(const Executor& ex,
84 const MutableBufferSequence& buffer_sequence,
85 const allocator_type& alloc = allocator_type(),
86 typename constraint<
87 is_executor<Executor>::value || execution::is_executor<Executor>::value
88 >::type = 0)
89 : buffer_sequence_(buffer_sequence),
90 buffers_(
91 BOOST_ASIO_REBIND_ALLOC(allocator_type,
92 mutable_registered_buffer)(alloc))
93 {
94 init_buffers(buffer_registration::get_context(ex),
95 boost::asio::buffer_sequence_begin(buffer_sequence_),
96 boost::asio::buffer_sequence_end(buffer_sequence_));
97 }
98
99 /// Register buffers with an execution context.
100 template <typename ExecutionContext>
101 buffer_registration(ExecutionContext& ctx,
102 const MutableBufferSequence& buffer_sequence,
103 const allocator_type& alloc = allocator_type(),
104 typename constraint<
105 is_convertible<ExecutionContext&, execution_context&>::value
106 >::type = 0)
107 : buffer_sequence_(buffer_sequence),
108 buffers_(
109 BOOST_ASIO_REBIND_ALLOC(allocator_type,
110 mutable_registered_buffer)(alloc))
111 {
112 init_buffers(ctx,
113 boost::asio::buffer_sequence_begin(buffer_sequence_),
114 boost::asio::buffer_sequence_end(buffer_sequence_));
115 }
116
117 #if defined(BOOST_ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)
118 /// Move constructor.
119 buffer_registration(buffer_registration&& other) BOOST_ASIO_NOEXCEPT
120 : buffer_sequence_(std::move(other.buffer_sequence_)),
121 buffers_(std::move(other.buffers_))
122 {
123 #if defined(BOOST_ASIO_HAS_IO_URING)
124 service_ = other.service_;
125 other.service_ = 0;
126 #endif // defined(BOOST_ASIO_HAS_IO_URING)
127 }
128 #endif // defined(BOOST_ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)
129
130 /// Unregisters the buffers.
131 ~buffer_registration()
132 {
133 #if defined(BOOST_ASIO_HAS_IO_URING)
134 if (service_)
135 service_->unregister_buffers();
136 #endif // defined(BOOST_ASIO_HAS_IO_URING)
137 }
138
139 #if defined(BOOST_ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)
140 /// Move assignment.
141 buffer_registration& operator=(
142 buffer_registration&& other) BOOST_ASIO_NOEXCEPT
143 {
144 if (this != &other)
145 {
146 buffer_sequence_ = std::move(other.buffer_sequence_);
147 buffers_ = std::move(other.buffers_);
148 #if defined(BOOST_ASIO_HAS_IO_URING)
149 if (service_)
150 service_->unregister_buffers();
151 service_ = other.service_;
152 other.service_ = 0;
153 #endif // defined(BOOST_ASIO_HAS_IO_URING)
154 }
155 return *this;
156 }
157 #endif // defined(BOOST_ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)
158
159 /// Get the number of registered buffers.
160 std::size_t size() const BOOST_ASIO_NOEXCEPT
161 {
162 return buffers_.size();
163 }
164
165 /// Get the begin iterator for the sequence of registered buffers.
166 const_iterator begin() const BOOST_ASIO_NOEXCEPT
167 {
168 return buffers_.begin();
169 }
170
171 /// Get the begin iterator for the sequence of registered buffers.
172 const_iterator cbegin() const BOOST_ASIO_NOEXCEPT
173 {
174 return buffers_.cbegin();
175 }
176
177 /// Get the end iterator for the sequence of registered buffers.
178 const_iterator end() const BOOST_ASIO_NOEXCEPT
179 {
180 return buffers_.end();
181 }
182
183 /// Get the end iterator for the sequence of registered buffers.
184 const_iterator cend() const BOOST_ASIO_NOEXCEPT
185 {
186 return buffers_.cend();
187 }
188
189 /// Get the buffer at the specified index.
190 const mutable_registered_buffer& operator[](std::size_t i) BOOST_ASIO_NOEXCEPT
191 {
192 return buffers_[i];
193 }
194
195 /// Get the buffer at the specified index.
196 const mutable_registered_buffer& at(std::size_t i) BOOST_ASIO_NOEXCEPT
197 {
198 return buffers_.at(i);
199 }
200
201 private:
202 // Disallow copying and assignment.
203 buffer_registration(const buffer_registration&) BOOST_ASIO_DELETED;
204 buffer_registration& operator=(const buffer_registration&) BOOST_ASIO_DELETED;
205
206 // Helper function to get an executor's context.
207 template <typename T>
208 static execution_context& get_context(const T& t,
209 typename enable_if<execution::is_executor<T>::value>::type* = 0)
210 {
211 return boost::asio::query(t, execution::context);
212 }
213
214 // Helper function to get an executor's context.
215 template <typename T>
216 static execution_context& get_context(const T& t,
217 typename enable_if<!execution::is_executor<T>::value>::type* = 0)
218 {
219 return t.context();
220 }
221
222 // Helper function to initialise the container of buffers.
223 template <typename Iterator>
224 void init_buffers(execution_context& ctx, Iterator begin, Iterator end)
225 {
226 std::size_t n = std::distance(begin, end);
227 buffers_.resize(n);
228
229 #if defined(BOOST_ASIO_HAS_IO_URING)
230 service_ = &use_service<detail::io_uring_service>(ctx);
231 std::vector<iovec,
232 BOOST_ASIO_REBIND_ALLOC(allocator_type, iovec)> iovecs(n,
233 BOOST_ASIO_REBIND_ALLOC(allocator_type, iovec)(
234 buffers_.get_allocator()));
235 #endif // defined(BOOST_ASIO_HAS_IO_URING)
236
237 Iterator iter = begin;
238 for (int index = 0; iter != end; ++index, ++iter)
239 {
240 mutable_buffer b(*iter);
241 std::size_t i = static_cast<std::size_t>(index);
242 buffers_[i] = this->make_buffer(b, &ctx, index);
243
244 #if defined(BOOST_ASIO_HAS_IO_URING)
245 iovecs[i].iov_base = buffers_[i].data();
246 iovecs[i].iov_len = buffers_[i].size();
247 #endif // defined(BOOST_ASIO_HAS_IO_URING)
248 }
249
250 #if defined(BOOST_ASIO_HAS_IO_URING)
251 if (n > 0)
252 {
253 service_->register_buffers(&iovecs[0],
254 static_cast<unsigned>(iovecs.size()));
255 }
256 #endif // defined(BOOST_ASIO_HAS_IO_URING)
257 }
258
259 MutableBufferSequence buffer_sequence_;
260 std::vector<mutable_registered_buffer,
261 BOOST_ASIO_REBIND_ALLOC(allocator_type,
262 mutable_registered_buffer)> buffers_;
263 #if defined(BOOST_ASIO_HAS_IO_URING)
264 detail::io_uring_service* service_;
265 #endif // defined(BOOST_ASIO_HAS_IO_URING)
266 };
267
268 #if defined(BOOST_ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)
269 /// Register buffers with an execution context.
270 template <typename Executor, typename MutableBufferSequence>
271 BOOST_ASIO_NODISCARD inline
272 buffer_registration<MutableBufferSequence>
273 register_buffers(const Executor& ex,
274 const MutableBufferSequence& buffer_sequence,
275 typename constraint<
276 is_executor<Executor>::value || execution::is_executor<Executor>::value
277 >::type = 0)
278 {
279 return buffer_registration<MutableBufferSequence>(ex, buffer_sequence);
280 }
281
282 /// Register buffers with an execution context.
283 template <typename Executor, typename MutableBufferSequence, typename Allocator>
284 BOOST_ASIO_NODISCARD inline
285 buffer_registration<MutableBufferSequence, Allocator>
286 register_buffers(const Executor& ex,
287 const MutableBufferSequence& buffer_sequence, const Allocator& alloc,
288 typename constraint<
289 is_executor<Executor>::value || execution::is_executor<Executor>::value
290 >::type = 0)
291 {
292 return buffer_registration<MutableBufferSequence, Allocator>(
293 ex, buffer_sequence, alloc);
294 }
295
296 /// Register buffers with an execution context.
297 template <typename ExecutionContext, typename MutableBufferSequence>
298 BOOST_ASIO_NODISCARD inline
299 buffer_registration<MutableBufferSequence>
300 register_buffers(ExecutionContext& ctx,
301 const MutableBufferSequence& buffer_sequence,
302 typename constraint<
303 is_convertible<ExecutionContext&, execution_context&>::value
304 >::type = 0)
305 {
306 return buffer_registration<MutableBufferSequence>(ctx, buffer_sequence);
307 }
308
309 /// Register buffers with an execution context.
310 template <typename ExecutionContext,
311 typename MutableBufferSequence, typename Allocator>
312 BOOST_ASIO_NODISCARD inline
313 buffer_registration<MutableBufferSequence, Allocator>
314 register_buffers(ExecutionContext& ctx,
315 const MutableBufferSequence& buffer_sequence, const Allocator& alloc,
316 typename constraint<
317 is_convertible<ExecutionContext&, execution_context&>::value
318 >::type = 0)
319 {
320 return buffer_registration<MutableBufferSequence, Allocator>(
321 ctx, buffer_sequence, alloc);
322 }
323 #endif // defined(BOOST_ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)
324
325 } // namespace asio
326 } // namespace boost
327
328 #include <boost/asio/detail/pop_options.hpp>
329
330 #endif // BOOST_ASIO_BUFFER_REGISTRATION_HPP