1 | // |
2 | // basic_random_access_file.hpp |
3 | // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
4 | // |
5 | // Copyright (c) 2003-2024 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_BASIC_RANDOM_ACCESS_FILE_HPP |
12 | #define BOOST_ASIO_BASIC_RANDOM_ACCESS_FILE_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 | |
20 | #if defined(BOOST_ASIO_HAS_FILE) \ |
21 | || defined(GENERATING_DOCUMENTATION) |
22 | |
23 | #include <cstddef> |
24 | #include <boost/asio/async_result.hpp> |
25 | #include <boost/asio/basic_file.hpp> |
26 | #include <boost/asio/detail/handler_type_requirements.hpp> |
27 | #include <boost/asio/detail/non_const_lvalue.hpp> |
28 | #include <boost/asio/detail/throw_error.hpp> |
29 | #include <boost/asio/error.hpp> |
30 | |
31 | #include <boost/asio/detail/push_options.hpp> |
32 | |
33 | namespace boost { |
34 | namespace asio { |
35 | |
36 | #if !defined(BOOST_ASIO_BASIC_RANDOM_ACCESS_FILE_FWD_DECL) |
37 | #define BOOST_ASIO_BASIC_RANDOM_ACCESS_FILE_FWD_DECL |
38 | |
39 | // Forward declaration with defaulted arguments. |
40 | template <typename Executor = any_io_executor> |
41 | class basic_random_access_file; |
42 | |
43 | #endif // !defined(BOOST_ASIO_BASIC_RANDOM_ACCESS_FILE_FWD_DECL) |
44 | |
45 | /// Provides random-access file functionality. |
46 | /** |
47 | * The basic_random_access_file class template provides asynchronous and |
48 | * blocking random-access file functionality. |
49 | * |
50 | * @par Thread Safety |
51 | * @e Distinct @e objects: Safe.@n |
52 | * @e Shared @e objects: Unsafe. |
53 | * |
54 | * Synchronous @c read_some_at and @c write_some_at operations are thread safe |
55 | * with respect to each other, if the underlying operating system calls are |
56 | * also thread safe. This means that it is permitted to perform concurrent |
57 | * calls to these synchronous operations on a single file object. Other |
58 | * synchronous operations, such as @c open or @c close, are not thread safe. |
59 | */ |
60 | template <typename Executor> |
61 | class basic_random_access_file |
62 | : public basic_file<Executor> |
63 | { |
64 | private: |
65 | class initiate_async_write_some_at; |
66 | class initiate_async_read_some_at; |
67 | |
68 | public: |
69 | /// The type of the executor associated with the object. |
70 | typedef Executor executor_type; |
71 | |
72 | /// Rebinds the file type to another executor. |
73 | template <typename Executor1> |
74 | struct rebind_executor |
75 | { |
76 | /// The file type when rebound to the specified executor. |
77 | typedef basic_random_access_file<Executor1> other; |
78 | }; |
79 | |
80 | /// The native representation of a file. |
81 | #if defined(GENERATING_DOCUMENTATION) |
82 | typedef implementation_defined native_handle_type; |
83 | #else |
84 | typedef typename basic_file<Executor>::native_handle_type native_handle_type; |
85 | #endif |
86 | |
87 | /// Construct a basic_random_access_file without opening it. |
88 | /** |
89 | * This constructor initialises a file without opening it. The file needs to |
90 | * be opened before data can be read from or or written to it. |
91 | * |
92 | * @param ex The I/O executor that the file will use, by default, to |
93 | * dispatch handlers for any asynchronous operations performed on the file. |
94 | */ |
95 | explicit basic_random_access_file(const executor_type& ex) |
96 | : basic_file<Executor>(ex) |
97 | { |
98 | } |
99 | |
100 | /// Construct a basic_random_access_file without opening it. |
101 | /** |
102 | * This constructor initialises a file without opening it. The file needs to |
103 | * be opened before data can be read from or or written to it. |
104 | * |
105 | * @param context An execution context which provides the I/O executor that |
106 | * the file will use, by default, to dispatch handlers for any asynchronous |
107 | * operations performed on the file. |
108 | */ |
109 | template <typename ExecutionContext> |
110 | explicit basic_random_access_file(ExecutionContext& context, |
111 | constraint_t< |
112 | is_convertible<ExecutionContext&, execution_context&>::value, |
113 | defaulted_constraint |
114 | > = defaulted_constraint()) |
115 | : basic_file<Executor>(context) |
116 | { |
117 | } |
118 | |
119 | /// Construct and open a basic_random_access_file. |
120 | /** |
121 | * This constructor initialises and opens a file. |
122 | * |
123 | * @param ex The I/O executor that the file will use, by default, to |
124 | * dispatch handlers for any asynchronous operations performed on the file. |
125 | * |
126 | * @param path The path name identifying the file to be opened. |
127 | * |
128 | * @param open_flags A set of flags that determine how the file should be |
129 | * opened. |
130 | * |
131 | * @throws boost::system::system_error Thrown on failure. |
132 | */ |
133 | basic_random_access_file(const executor_type& ex, |
134 | const char* path, file_base::flags open_flags) |
135 | : basic_file<Executor>(ex, path, open_flags) |
136 | { |
137 | } |
138 | |
139 | /// Construct and open a basic_random_access_file. |
140 | /** |
141 | * This constructor initialises and opens a file. |
142 | * |
143 | * @param context An execution context which provides the I/O executor that |
144 | * the file will use, by default, to dispatch handlers for any asynchronous |
145 | * operations performed on the file. |
146 | * |
147 | * @param path The path name identifying the file to be opened. |
148 | * |
149 | * @param open_flags A set of flags that determine how the file should be |
150 | * opened. |
151 | * |
152 | * @throws boost::system::system_error Thrown on failure. |
153 | */ |
154 | template <typename ExecutionContext> |
155 | basic_random_access_file(ExecutionContext& context, |
156 | const char* path, file_base::flags open_flags, |
157 | constraint_t< |
158 | is_convertible<ExecutionContext&, execution_context&>::value, |
159 | defaulted_constraint |
160 | > = defaulted_constraint()) |
161 | : basic_file<Executor>(context, path, open_flags) |
162 | { |
163 | } |
164 | |
165 | /// Construct and open a basic_random_access_file. |
166 | /** |
167 | * This constructor initialises and opens a file. |
168 | * |
169 | * @param ex The I/O executor that the file will use, by default, to |
170 | * dispatch handlers for any asynchronous operations performed on the file. |
171 | * |
172 | * @param path The path name identifying the file to be opened. |
173 | * |
174 | * @param open_flags A set of flags that determine how the file should be |
175 | * opened. |
176 | * |
177 | * @throws boost::system::system_error Thrown on failure. |
178 | */ |
179 | basic_random_access_file(const executor_type& ex, |
180 | const std::string& path, file_base::flags open_flags) |
181 | : basic_file<Executor>(ex, path, open_flags) |
182 | { |
183 | } |
184 | |
185 | /// Construct and open a basic_random_access_file. |
186 | /** |
187 | * This constructor initialises and opens a file. |
188 | * |
189 | * @param context An execution context which provides the I/O executor that |
190 | * the file will use, by default, to dispatch handlers for any asynchronous |
191 | * operations performed on the file. |
192 | * |
193 | * @param path The path name identifying the file to be opened. |
194 | * |
195 | * @param open_flags A set of flags that determine how the file should be |
196 | * opened. |
197 | * |
198 | * @throws boost::system::system_error Thrown on failure. |
199 | */ |
200 | template <typename ExecutionContext> |
201 | basic_random_access_file(ExecutionContext& context, |
202 | const std::string& path, file_base::flags open_flags, |
203 | constraint_t< |
204 | is_convertible<ExecutionContext&, execution_context&>::value, |
205 | defaulted_constraint |
206 | > = defaulted_constraint()) |
207 | : basic_file<Executor>(context, path, open_flags) |
208 | { |
209 | } |
210 | |
211 | /// Construct a basic_random_access_file on an existing native file. |
212 | /** |
213 | * This constructor initialises a random-access file object to hold an |
214 | * existing native file. |
215 | * |
216 | * @param ex The I/O executor that the file will use, by default, to |
217 | * dispatch handlers for any asynchronous operations performed on the file. |
218 | * |
219 | * @param native_file The new underlying file implementation. |
220 | * |
221 | * @throws boost::system::system_error Thrown on failure. |
222 | */ |
223 | basic_random_access_file(const executor_type& ex, |
224 | const native_handle_type& native_file) |
225 | : basic_file<Executor>(ex, native_file) |
226 | { |
227 | } |
228 | |
229 | /// Construct a basic_random_access_file on an existing native file. |
230 | /** |
231 | * This constructor initialises a random-access file object to hold an |
232 | * existing native file. |
233 | * |
234 | * @param context An execution context which provides the I/O executor that |
235 | * the file will use, by default, to dispatch handlers for any asynchronous |
236 | * operations performed on the file. |
237 | * |
238 | * @param native_file The new underlying file implementation. |
239 | * |
240 | * @throws boost::system::system_error Thrown on failure. |
241 | */ |
242 | template <typename ExecutionContext> |
243 | basic_random_access_file(ExecutionContext& context, |
244 | const native_handle_type& native_file, |
245 | constraint_t< |
246 | is_convertible<ExecutionContext&, execution_context&>::value, |
247 | defaulted_constraint |
248 | > = defaulted_constraint()) |
249 | : basic_file<Executor>(context, native_file) |
250 | { |
251 | } |
252 | |
253 | /// Move-construct a basic_random_access_file from another. |
254 | /** |
255 | * This constructor moves a random-access file from one object to another. |
256 | * |
257 | * @param other The other basic_random_access_file object from which the move |
258 | * will occur. |
259 | * |
260 | * @note Following the move, the moved-from object is in the same state as if |
261 | * constructed using the @c basic_random_access_file(const executor_type&) |
262 | * constructor. |
263 | */ |
264 | basic_random_access_file(basic_random_access_file&& other) noexcept |
265 | : basic_file<Executor>(std::move(other)) |
266 | { |
267 | } |
268 | |
269 | /// Move-assign a basic_random_access_file from another. |
270 | /** |
271 | * This assignment operator moves a random-access file from one object to |
272 | * another. |
273 | * |
274 | * @param other The other basic_random_access_file object from which the move |
275 | * will occur. |
276 | * |
277 | * @note Following the move, the moved-from object is in the same state as if |
278 | * constructed using the @c basic_random_access_file(const executor_type&) |
279 | * constructor. |
280 | */ |
281 | basic_random_access_file& operator=(basic_random_access_file&& other) |
282 | { |
283 | basic_file<Executor>::operator=(std::move(other)); |
284 | return *this; |
285 | } |
286 | |
287 | /// Move-construct a basic_random_access_file from a file of another executor |
288 | /// type. |
289 | /** |
290 | * This constructor moves a random-access file from one object to another. |
291 | * |
292 | * @param other The other basic_random_access_file object from which the move |
293 | * will occur. |
294 | * |
295 | * @note Following the move, the moved-from object is in the same state as if |
296 | * constructed using the @c basic_random_access_file(const executor_type&) |
297 | * constructor. |
298 | */ |
299 | template <typename Executor1> |
300 | basic_random_access_file(basic_random_access_file<Executor1>&& other, |
301 | constraint_t< |
302 | is_convertible<Executor1, Executor>::value, |
303 | defaulted_constraint |
304 | > = defaulted_constraint()) |
305 | : basic_file<Executor>(std::move(other)) |
306 | { |
307 | } |
308 | |
309 | /// Move-assign a basic_random_access_file from a file of another executor |
310 | /// type. |
311 | /** |
312 | * This assignment operator moves a random-access file from one object to |
313 | * another. |
314 | * |
315 | * @param other The other basic_random_access_file object from which the move |
316 | * will occur. |
317 | * |
318 | * @note Following the move, the moved-from object is in the same state as if |
319 | * constructed using the @c basic_random_access_file(const executor_type&) |
320 | * constructor. |
321 | */ |
322 | template <typename Executor1> |
323 | constraint_t< |
324 | is_convertible<Executor1, Executor>::value, |
325 | basic_random_access_file& |
326 | > operator=(basic_random_access_file<Executor1>&& other) |
327 | { |
328 | basic_file<Executor>::operator=(std::move(other)); |
329 | return *this; |
330 | } |
331 | |
332 | /// Destroys the file. |
333 | /** |
334 | * This function destroys the file, cancelling any outstanding asynchronous |
335 | * operations associated with the file as if by calling @c cancel. |
336 | */ |
337 | ~basic_random_access_file() |
338 | { |
339 | } |
340 | |
341 | /// Write some data to the handle at the specified offset. |
342 | /** |
343 | * This function is used to write data to the random-access handle. The |
344 | * function call will block until one or more bytes of the data has been |
345 | * written successfully, or until an error occurs. |
346 | * |
347 | * @param offset The offset at which the data will be written. |
348 | * |
349 | * @param buffers One or more data buffers to be written to the handle. |
350 | * |
351 | * @returns The number of bytes written. |
352 | * |
353 | * @throws boost::system::system_error Thrown on failure. An error code of |
354 | * boost::asio::error::eof indicates that the end of the file was reached. |
355 | * |
356 | * @note The write_some_at operation may not write all of the data. Consider |
357 | * using the @ref write_at function if you need to ensure that all data is |
358 | * written before the blocking operation completes. |
359 | * |
360 | * @par Example |
361 | * To write a single data buffer use the @ref buffer function as follows: |
362 | * @code |
363 | * handle.write_some_at(42, boost::asio::buffer(data, size)); |
364 | * @endcode |
365 | * See the @ref buffer documentation for information on writing multiple |
366 | * buffers in one go, and how to use it with arrays, boost::array or |
367 | * std::vector. |
368 | */ |
369 | template <typename ConstBufferSequence> |
370 | std::size_t write_some_at(uint64_t offset, |
371 | const ConstBufferSequence& buffers) |
372 | { |
373 | boost::system::error_code ec; |
374 | std::size_t s = this->impl_.get_service().write_some_at( |
375 | this->impl_.get_implementation(), offset, buffers, ec); |
376 | boost::asio::detail::throw_error(ec, "write_some_at" ); |
377 | return s; |
378 | } |
379 | |
380 | /// Write some data to the handle at the specified offset. |
381 | /** |
382 | * This function is used to write data to the random-access handle. The |
383 | * function call will block until one or more bytes of the data has been |
384 | * written successfully, or until an error occurs. |
385 | * |
386 | * @param offset The offset at which the data will be written. |
387 | * |
388 | * @param buffers One or more data buffers to be written to the handle. |
389 | * |
390 | * @param ec Set to indicate what error occurred, if any. |
391 | * |
392 | * @returns The number of bytes written. Returns 0 if an error occurred. |
393 | * |
394 | * @note The write_some operation may not write all of the data to the |
395 | * file. Consider using the @ref write_at function if you need to ensure that |
396 | * all data is written before the blocking operation completes. |
397 | */ |
398 | template <typename ConstBufferSequence> |
399 | std::size_t write_some_at(uint64_t offset, |
400 | const ConstBufferSequence& buffers, boost::system::error_code& ec) |
401 | { |
402 | return this->impl_.get_service().write_some_at( |
403 | this->impl_.get_implementation(), offset, buffers, ec); |
404 | } |
405 | |
406 | /// Start an asynchronous write at the specified offset. |
407 | /** |
408 | * This function is used to asynchronously write data to the random-access |
409 | * handle. It is an initiating function for an @ref asynchronous_operation, |
410 | * and always returns immediately. |
411 | * |
412 | * @param offset The offset at which the data will be written. |
413 | * |
414 | * @param buffers One or more data buffers to be written to the handle. |
415 | * Although the buffers object may be copied as necessary, ownership of the |
416 | * underlying memory blocks is retained by the caller, which must guarantee |
417 | * that they remain valid until the completion handler is called. |
418 | * |
419 | * @param token The @ref completion_token that will be used to produce a |
420 | * completion handler, which will be called when the write completes. |
421 | * Potential completion tokens include @ref use_future, @ref use_awaitable, |
422 | * @ref yield_context, or a function object with the correct completion |
423 | * signature. The function signature of the completion handler must be: |
424 | * @code void handler( |
425 | * const boost::system::error_code& error, // Result of operation. |
426 | * std::size_t bytes_transferred // Number of bytes written. |
427 | * ); @endcode |
428 | * Regardless of whether the asynchronous operation completes immediately or |
429 | * not, the completion handler will not be invoked from within this function. |
430 | * On immediate completion, invocation of the handler will be performed in a |
431 | * manner equivalent to using boost::asio::post(). |
432 | * |
433 | * @par Completion Signature |
434 | * @code void(boost::system::error_code, std::size_t) @endcode |
435 | * |
436 | * @note The write operation may not write all of the data to the file. |
437 | * Consider using the @ref async_write_at function if you need to ensure that |
438 | * all data is written before the asynchronous operation completes. |
439 | * |
440 | * @par Example |
441 | * To write a single data buffer use the @ref buffer function as follows: |
442 | * @code |
443 | * handle.async_write_some_at(42, boost::asio::buffer(data, size), handler); |
444 | * @endcode |
445 | * See the @ref buffer documentation for information on writing multiple |
446 | * buffers in one go, and how to use it with arrays, boost::array or |
447 | * std::vector. |
448 | * |
449 | * @par Per-Operation Cancellation |
450 | * This asynchronous operation supports cancellation for the following |
451 | * boost::asio::cancellation_type values: |
452 | * |
453 | * @li @c cancellation_type::terminal |
454 | * |
455 | * @li @c cancellation_type::partial |
456 | * |
457 | * @li @c cancellation_type::total |
458 | */ |
459 | template <typename ConstBufferSequence, |
460 | BOOST_ASIO_COMPLETION_TOKEN_FOR(void (boost::system::error_code, |
461 | std::size_t)) WriteToken = default_completion_token_t<executor_type>> |
462 | auto async_write_some_at(uint64_t offset, const ConstBufferSequence& buffers, |
463 | WriteToken&& token = default_completion_token_t<executor_type>()) |
464 | -> decltype( |
465 | async_initiate<WriteToken, |
466 | void (boost::system::error_code, std::size_t)>( |
467 | declval<initiate_async_write_some_at>(), token, offset, buffers)) |
468 | { |
469 | return async_initiate<WriteToken, |
470 | void (boost::system::error_code, std::size_t)>( |
471 | initiate_async_write_some_at(this), token, offset, buffers); |
472 | } |
473 | |
474 | /// Read some data from the handle at the specified offset. |
475 | /** |
476 | * This function is used to read data from the random-access handle. The |
477 | * function call will block until one or more bytes of data has been read |
478 | * successfully, or until an error occurs. |
479 | * |
480 | * @param offset The offset at which the data will be read. |
481 | * |
482 | * @param buffers One or more buffers into which the data will be read. |
483 | * |
484 | * @returns The number of bytes read. |
485 | * |
486 | * @throws boost::system::system_error Thrown on failure. An error code of |
487 | * boost::asio::error::eof indicates that the end of the file was reached. |
488 | * |
489 | * @note The read_some operation may not read all of the requested number of |
490 | * bytes. Consider using the @ref read_at function if you need to ensure that |
491 | * the requested amount of data is read before the blocking operation |
492 | * completes. |
493 | * |
494 | * @par Example |
495 | * To read into a single data buffer use the @ref buffer function as follows: |
496 | * @code |
497 | * handle.read_some_at(42, boost::asio::buffer(data, size)); |
498 | * @endcode |
499 | * See the @ref buffer documentation for information on reading into multiple |
500 | * buffers in one go, and how to use it with arrays, boost::array or |
501 | * std::vector. |
502 | */ |
503 | template <typename MutableBufferSequence> |
504 | std::size_t read_some_at(uint64_t offset, |
505 | const MutableBufferSequence& buffers) |
506 | { |
507 | boost::system::error_code ec; |
508 | std::size_t s = this->impl_.get_service().read_some_at( |
509 | this->impl_.get_implementation(), offset, buffers, ec); |
510 | boost::asio::detail::throw_error(ec, "read_some_at" ); |
511 | return s; |
512 | } |
513 | |
514 | /// Read some data from the handle at the specified offset. |
515 | /** |
516 | * This function is used to read data from the random-access handle. The |
517 | * function call will block until one or more bytes of data has been read |
518 | * successfully, or until an error occurs. |
519 | * |
520 | * @param offset The offset at which the data will be read. |
521 | * |
522 | * @param buffers One or more buffers into which the data will be read. |
523 | * |
524 | * @param ec Set to indicate what error occurred, if any. |
525 | * |
526 | * @returns The number of bytes read. Returns 0 if an error occurred. |
527 | * |
528 | * @note The read_some operation may not read all of the requested number of |
529 | * bytes. Consider using the @ref read_at function if you need to ensure that |
530 | * the requested amount of data is read before the blocking operation |
531 | * completes. |
532 | */ |
533 | template <typename MutableBufferSequence> |
534 | std::size_t read_some_at(uint64_t offset, |
535 | const MutableBufferSequence& buffers, boost::system::error_code& ec) |
536 | { |
537 | return this->impl_.get_service().read_some_at( |
538 | this->impl_.get_implementation(), offset, buffers, ec); |
539 | } |
540 | |
541 | /// Start an asynchronous read at the specified offset. |
542 | /** |
543 | * This function is used to asynchronously read data from the random-access |
544 | * handle. It is an initiating function for an @ref asynchronous_operation, |
545 | * and always returns immediately. |
546 | * |
547 | * @param offset The offset at which the data will be read. |
548 | * |
549 | * @param buffers One or more buffers into which the data will be read. |
550 | * Although the buffers object may be copied as necessary, ownership of the |
551 | * underlying memory blocks is retained by the caller, which must guarantee |
552 | * that they remain valid until the completion handler is called. |
553 | * |
554 | * @param token The @ref completion_token that will be used to produce a |
555 | * completion handler, which will be called when the read completes. |
556 | * Potential completion tokens include @ref use_future, @ref use_awaitable, |
557 | * @ref yield_context, or a function object with the correct completion |
558 | * signature. The function signature of the completion handler must be: |
559 | * @code void handler( |
560 | * const boost::system::error_code& error, // Result of operation. |
561 | * std::size_t bytes_transferred // Number of bytes read. |
562 | * ); @endcode |
563 | * Regardless of whether the asynchronous operation completes immediately or |
564 | * not, the completion handler will not be invoked from within this function. |
565 | * On immediate completion, invocation of the handler will be performed in a |
566 | * manner equivalent to using boost::asio::post(). |
567 | * |
568 | * @par Completion Signature |
569 | * @code void(boost::system::error_code, std::size_t) @endcode |
570 | * |
571 | * @note The read operation may not read all of the requested number of bytes. |
572 | * Consider using the @ref async_read_at function if you need to ensure that |
573 | * the requested amount of data is read before the asynchronous operation |
574 | * completes. |
575 | * |
576 | * @par Example |
577 | * To read into a single data buffer use the @ref buffer function as follows: |
578 | * @code |
579 | * handle.async_read_some_at(42, boost::asio::buffer(data, size), handler); |
580 | * @endcode |
581 | * See the @ref buffer documentation for information on reading into multiple |
582 | * buffers in one go, and how to use it with arrays, boost::array or |
583 | * std::vector. |
584 | * |
585 | * @par Per-Operation Cancellation |
586 | * This asynchronous operation supports cancellation for the following |
587 | * boost::asio::cancellation_type values: |
588 | * |
589 | * @li @c cancellation_type::terminal |
590 | * |
591 | * @li @c cancellation_type::partial |
592 | * |
593 | * @li @c cancellation_type::total |
594 | */ |
595 | template <typename MutableBufferSequence, |
596 | BOOST_ASIO_COMPLETION_TOKEN_FOR(void (boost::system::error_code, |
597 | std::size_t)) ReadToken = default_completion_token_t<executor_type>> |
598 | auto async_read_some_at(uint64_t offset, const MutableBufferSequence& buffers, |
599 | ReadToken&& token = default_completion_token_t<executor_type>()) |
600 | -> decltype( |
601 | async_initiate<ReadToken, |
602 | void (boost::system::error_code, std::size_t)>( |
603 | declval<initiate_async_read_some_at>(), token, offset, buffers)) |
604 | { |
605 | return async_initiate<ReadToken, |
606 | void (boost::system::error_code, std::size_t)>( |
607 | initiate_async_read_some_at(this), token, offset, buffers); |
608 | } |
609 | |
610 | private: |
611 | // Disallow copying and assignment. |
612 | basic_random_access_file(const basic_random_access_file&) = delete; |
613 | basic_random_access_file& operator=( |
614 | const basic_random_access_file&) = delete; |
615 | |
616 | class initiate_async_write_some_at |
617 | { |
618 | public: |
619 | typedef Executor executor_type; |
620 | |
621 | explicit initiate_async_write_some_at(basic_random_access_file* self) |
622 | : self_(self) |
623 | { |
624 | } |
625 | |
626 | const executor_type& get_executor() const noexcept |
627 | { |
628 | return self_->get_executor(); |
629 | } |
630 | |
631 | template <typename WriteHandler, typename ConstBufferSequence> |
632 | void operator()(WriteHandler&& handler, |
633 | uint64_t offset, const ConstBufferSequence& buffers) const |
634 | { |
635 | // If you get an error on the following line it means that your handler |
636 | // does not meet the documented type requirements for a WriteHandler. |
637 | BOOST_ASIO_WRITE_HANDLER_CHECK(WriteHandler, handler) type_check; |
638 | |
639 | detail::non_const_lvalue<WriteHandler> handler2(handler); |
640 | self_->impl_.get_service().async_write_some_at( |
641 | self_->impl_.get_implementation(), offset, buffers, |
642 | handler2.value, self_->impl_.get_executor()); |
643 | } |
644 | |
645 | private: |
646 | basic_random_access_file* self_; |
647 | }; |
648 | |
649 | class initiate_async_read_some_at |
650 | { |
651 | public: |
652 | typedef Executor executor_type; |
653 | |
654 | explicit initiate_async_read_some_at(basic_random_access_file* self) |
655 | : self_(self) |
656 | { |
657 | } |
658 | |
659 | const executor_type& get_executor() const noexcept |
660 | { |
661 | return self_->get_executor(); |
662 | } |
663 | |
664 | template <typename ReadHandler, typename MutableBufferSequence> |
665 | void operator()(ReadHandler&& handler, |
666 | uint64_t offset, const MutableBufferSequence& buffers) const |
667 | { |
668 | // If you get an error on the following line it means that your handler |
669 | // does not meet the documented type requirements for a ReadHandler. |
670 | BOOST_ASIO_READ_HANDLER_CHECK(ReadHandler, handler) type_check; |
671 | |
672 | detail::non_const_lvalue<ReadHandler> handler2(handler); |
673 | self_->impl_.get_service().async_read_some_at( |
674 | self_->impl_.get_implementation(), offset, buffers, |
675 | handler2.value, self_->impl_.get_executor()); |
676 | } |
677 | |
678 | private: |
679 | basic_random_access_file* self_; |
680 | }; |
681 | }; |
682 | |
683 | } // namespace asio |
684 | } // namespace boost |
685 | |
686 | #include <boost/asio/detail/pop_options.hpp> |
687 | |
688 | #endif // defined(BOOST_ASIO_HAS_FILE) |
689 | // || defined(GENERATING_DOCUMENTATION) |
690 | |
691 | #endif // BOOST_ASIO_BASIC_RANDOM_ACCESS_FILE_HPP |
692 | |