tidal-link 1.0.1 → 1.0.2
raw patch · 789 files changed
+58261/−10101 lines, 789 files
Files
- link/include/ableton/Link.ipp +23/−9
- link/include/ableton/discovery/AsioTypes.hpp +54/−0
- link/include/ableton/discovery/InterfaceScanner.hpp +3/−3
- link/include/ableton/discovery/IpInterface.hpp +130/−0
- link/include/ableton/discovery/IpV4Interface.hpp +0/−123
- link/include/ableton/discovery/NetworkByteStreamSerializable.hpp +1/−1
- link/include/ableton/discovery/Payload.hpp +5/−0
- link/include/ableton/discovery/PeerGateway.hpp +4/−4
- link/include/ableton/discovery/PeerGateways.hpp +12/−15
- link/include/ableton/discovery/Service.hpp +1/−1
- link/include/ableton/discovery/UdpMessenger.hpp +38/−16
- link/include/ableton/discovery/test/Interface.hpp +9/−11
- link/include/ableton/discovery/test/Socket.hpp +9/−11
- link/include/ableton/link/Controller.hpp +4/−11
- link/include/ableton/link/Gateway.hpp +1/−1
- link/include/ableton/link/Measurement.hpp +16/−6
- link/include/ableton/link/MeasurementEndpointV4.hpp +9/−3
- link/include/ableton/link/MeasurementEndpointV6.hpp +75/−0
- link/include/ableton/link/MeasurementService.hpp +3/−3
- link/include/ableton/link/PeerState.hpp +15/−9
- link/include/ableton/link/Peers.hpp +7/−7
- link/include/ableton/link/PingResponder.hpp +6/−6
- link/include/ableton/link/SessionState.hpp +1/−0
- link/include/ableton/platforms/Config.hpp +11/−9
- link/include/ableton/platforms/asio/AsioTimer.hpp +9/−6
- link/include/ableton/platforms/asio/AsioWrapper.hpp +11/−7
- link/include/ableton/platforms/asio/Context.hpp +73/−27
- link/include/ableton/platforms/asio/LockFreeCallbackDispatcher.hpp +2/−2
- link/include/ableton/platforms/asio/Socket.hpp +20/−20
- link/include/ableton/platforms/asio/Util.hpp +0/−43
- link/include/ableton/platforms/darwin/Clock.hpp +3/−0
- link/include/ableton/platforms/esp32/Context.hpp +68/−33
- link/include/ableton/platforms/esp32/ScanIpIfAddrs.hpp +3/−3
- link/include/ableton/platforms/linux/Clock.hpp +2/−6
- link/include/ableton/platforms/linux/ThreadFactory.hpp +2/−2
- link/include/ableton/platforms/posix/ScanIpIfAddrs.hpp +32/−16
- link/include/ableton/platforms/windows/ScanIpIfAddrs.hpp +35/−10
- link/include/ableton/test/serial_io/Context.hpp +4/−4
- link/include/ableton/test/serial_io/Fixture.hpp +3/−3
- link/modules/asio-standalone/asio/include/asio.hpp +35/−1
- link/modules/asio-standalone/asio/include/asio/any_completion_executor.hpp +342/−0
- link/modules/asio-standalone/asio/include/asio/any_completion_handler.hpp +762/−0
- link/modules/asio-standalone/asio/include/asio/any_io_executor.hpp +299/−11
- link/modules/asio-standalone/asio/include/asio/append.hpp +78/−0
- link/modules/asio-standalone/asio/include/asio/as_tuple.hpp +139/−0
- link/modules/asio-standalone/asio/include/asio/associated_allocator.hpp +129/−21
- link/modules/asio-standalone/asio/include/asio/associated_cancellation_slot.hpp +238/−0
- link/modules/asio-standalone/asio/include/asio/associated_executor.hpp +103/−16
- link/modules/asio-standalone/asio/include/asio/associated_immediate_executor.hpp +297/−0
- link/modules/asio-standalone/asio/include/asio/associator.hpp +35/−0
- link/modules/asio-standalone/asio/include/asio/async_result.hpp +1596/−507
- link/modules/asio-standalone/asio/include/asio/awaitable.hpp +11/−2
- link/modules/asio-standalone/asio/include/asio/basic_datagram_socket.hpp +306/−125
- link/modules/asio-standalone/asio/include/asio/basic_deadline_timer.hpp +50/−28
- link/modules/asio-standalone/asio/include/asio/basic_file.hpp +829/−0
- link/modules/asio-standalone/asio/include/asio/basic_io_object.hpp +1/−1
- link/modules/asio-standalone/asio/include/asio/basic_random_access_file.hpp +701/−0
- link/modules/asio-standalone/asio/include/asio/basic_raw_socket.hpp +308/−127
- link/modules/asio-standalone/asio/include/asio/basic_readable_pipe.hpp +635/−0
- link/modules/asio-standalone/asio/include/asio/basic_seq_packet_socket.hpp +130/−56
- link/modules/asio-standalone/asio/include/asio/basic_serial_port.hpp +143/−50
- link/modules/asio-standalone/asio/include/asio/basic_signal_set.hpp +120/−37
- link/modules/asio-standalone/asio/include/asio/basic_socket.hpp +102/−49
- link/modules/asio-standalone/asio/include/asio/basic_socket_acceptor.hpp +455/−201
- link/modules/asio-standalone/asio/include/asio/basic_socket_iostream.hpp +1/−1
- link/modules/asio-standalone/asio/include/asio/basic_socket_streambuf.hpp +1/−1
- link/modules/asio-standalone/asio/include/asio/basic_stream_file.hpp +754/−0
- link/modules/asio-standalone/asio/include/asio/basic_stream_socket.hpp +229/−93
- link/modules/asio-standalone/asio/include/asio/basic_streambuf.hpp +1/−1
- link/modules/asio-standalone/asio/include/asio/basic_streambuf_fwd.hpp +1/−1
- link/modules/asio-standalone/asio/include/asio/basic_waitable_timer.hpp +55/−33
- link/modules/asio-standalone/asio/include/asio/basic_writable_pipe.hpp +631/−0
- link/modules/asio-standalone/asio/include/asio/bind_allocator.hpp +733/−0
- link/modules/asio-standalone/asio/include/asio/bind_cancellation_slot.hpp +736/−0
- link/modules/asio-standalone/asio/include/asio/bind_executor.hpp +230/−24
- link/modules/asio-standalone/asio/include/asio/bind_immediate_executor.hpp +736/−0
- link/modules/asio-standalone/asio/include/asio/buffer.hpp +479/−66
- link/modules/asio-standalone/asio/include/asio/buffer_registration.hpp +328/−0
- link/modules/asio-standalone/asio/include/asio/buffered_read_stream.hpp +43/−10
- link/modules/asio-standalone/asio/include/asio/buffered_read_stream_fwd.hpp +1/−1
- link/modules/asio-standalone/asio/include/asio/buffered_stream.hpp +39/−10
- link/modules/asio-standalone/asio/include/asio/buffered_stream_fwd.hpp +1/−1
- link/modules/asio-standalone/asio/include/asio/buffered_write_stream.hpp +43/−10
- link/modules/asio-standalone/asio/include/asio/buffered_write_stream_fwd.hpp +1/−1
- link/modules/asio-standalone/asio/include/asio/buffers_iterator.hpp +1/−1
- link/modules/asio-standalone/asio/include/asio/cancellation_signal.hpp +305/−0
- link/modules/asio-standalone/asio/include/asio/cancellation_state.hpp +235/−0
- link/modules/asio-standalone/asio/include/asio/cancellation_type.hpp +174/−0
- link/modules/asio-standalone/asio/include/asio/co_spawn.hpp +73/−21
- link/modules/asio-standalone/asio/include/asio/completion_condition.hpp +1/−1
- link/modules/asio-standalone/asio/include/asio/compose.hpp +408/−13
- link/modules/asio-standalone/asio/include/asio/connect.hpp +206/−75
- link/modules/asio-standalone/asio/include/asio/connect_pipe.hpp +83/−0
- link/modules/asio-standalone/asio/include/asio/consign.hpp +88/−0
- link/modules/asio-standalone/asio/include/asio/coroutine.hpp +1/−1
- link/modules/asio-standalone/asio/include/asio/deadline_timer.hpp +1/−1
- link/modules/asio-standalone/asio/include/asio/defer.hpp +134/−42
- link/modules/asio-standalone/asio/include/asio/deferred.hpp +802/−0
- link/modules/asio-standalone/asio/include/asio/detached.hpp +8/−7
- link/modules/asio-standalone/asio/include/asio/detail/array.hpp +1/−1
- link/modules/asio-standalone/asio/include/asio/detail/array_fwd.hpp +1/−1
- link/modules/asio-standalone/asio/include/asio/detail/assert.hpp +1/−1
- link/modules/asio-standalone/asio/include/asio/detail/atomic_count.hpp +4/−1
- link/modules/asio-standalone/asio/include/asio/detail/base_from_cancellation_state.hpp +163/−0
- link/modules/asio-standalone/asio/include/asio/detail/base_from_completion_cond.hpp +1/−1
- link/modules/asio-standalone/asio/include/asio/detail/bind_handler.hpp +276/−65
- link/modules/asio-standalone/asio/include/asio/detail/blocking_executor_op.hpp +2/−1
- link/modules/asio-standalone/asio/include/asio/detail/buffer_resize_guard.hpp +1/−1
- link/modules/asio-standalone/asio/include/asio/detail/buffer_sequence_adapter.hpp +192/−1
- link/modules/asio-standalone/asio/include/asio/detail/buffered_stream_storage.hpp +1/−1
- link/modules/asio-standalone/asio/include/asio/detail/bulk_executor_op.hpp +2/−1
- link/modules/asio-standalone/asio/include/asio/detail/call_stack.hpp +1/−1
- link/modules/asio-standalone/asio/include/asio/detail/chrono.hpp +1/−1
- link/modules/asio-standalone/asio/include/asio/detail/chrono_time_traits.hpp +1/−1
- link/modules/asio-standalone/asio/include/asio/detail/completion_handler.hpp +1/−1
- link/modules/asio-standalone/asio/include/asio/detail/composed_work.hpp +328/−0
- link/modules/asio-standalone/asio/include/asio/detail/concurrency_hint.hpp +1/−1
- link/modules/asio-standalone/asio/include/asio/detail/conditionally_enabled_event.hpp +1/−1
- link/modules/asio-standalone/asio/include/asio/detail/conditionally_enabled_mutex.hpp +1/−1
- link/modules/asio-standalone/asio/include/asio/detail/config.hpp +566/−79
- link/modules/asio-standalone/asio/include/asio/detail/consuming_buffers.hpp +38/−1
- link/modules/asio-standalone/asio/include/asio/detail/cstddef.hpp +1/−1
- link/modules/asio-standalone/asio/include/asio/detail/cstdint.hpp +3/−1
- link/modules/asio-standalone/asio/include/asio/detail/date_time_fwd.hpp +1/−1
- link/modules/asio-standalone/asio/include/asio/detail/deadline_timer_service.hpp +41/−1
- link/modules/asio-standalone/asio/include/asio/detail/dependent_type.hpp +1/−1
- link/modules/asio-standalone/asio/include/asio/detail/descriptor_ops.hpp +42/−2
- link/modules/asio-standalone/asio/include/asio/detail/descriptor_read_op.hpp +41/−1
- link/modules/asio-standalone/asio/include/asio/detail/descriptor_write_op.hpp +40/−1
- link/modules/asio-standalone/asio/include/asio/detail/dev_poll_reactor.hpp +37/−7
- link/modules/asio-standalone/asio/include/asio/detail/epoll_reactor.hpp +36/−7
- link/modules/asio-standalone/asio/include/asio/detail/event.hpp +1/−1
- link/modules/asio-standalone/asio/include/asio/detail/eventfd_select_interrupter.hpp +1/−1
- link/modules/asio-standalone/asio/include/asio/detail/exception.hpp +40/−0
- link/modules/asio-standalone/asio/include/asio/detail/executor_function.hpp +3/−2
- link/modules/asio-standalone/asio/include/asio/detail/executor_op.hpp +2/−1
- link/modules/asio-standalone/asio/include/asio/detail/fd_set_adapter.hpp +1/−1
- link/modules/asio-standalone/asio/include/asio/detail/fenced_block.hpp +1/−1
- link/modules/asio-standalone/asio/include/asio/detail/functional.hpp +7/−1
- link/modules/asio-standalone/asio/include/asio/detail/future.hpp +1/−1
- link/modules/asio-standalone/asio/include/asio/detail/gcc_arm_fenced_block.hpp +1/−1
- link/modules/asio-standalone/asio/include/asio/detail/gcc_hppa_fenced_block.hpp +1/−1
- link/modules/asio-standalone/asio/include/asio/detail/gcc_sync_fenced_block.hpp +1/−1
- link/modules/asio-standalone/asio/include/asio/detail/gcc_x86_fenced_block.hpp +2/−2
- link/modules/asio-standalone/asio/include/asio/detail/global.hpp +1/−1
- link/modules/asio-standalone/asio/include/asio/detail/handler_alloc_helpers.hpp +16/−12
- link/modules/asio-standalone/asio/include/asio/detail/handler_cont_helpers.hpp +1/−1
- link/modules/asio-standalone/asio/include/asio/detail/handler_invoke_helpers.hpp +1/−1
- link/modules/asio-standalone/asio/include/asio/detail/handler_tracking.hpp +1/−1
- link/modules/asio-standalone/asio/include/asio/detail/handler_type_requirements.hpp +22/−19
- link/modules/asio-standalone/asio/include/asio/detail/handler_work.hpp +155/−28
- link/modules/asio-standalone/asio/include/asio/detail/hash_map.hpp +1/−1
- link/modules/asio-standalone/asio/include/asio/detail/impl/buffer_sequence_adapter.ipp +1/−1
- link/modules/asio-standalone/asio/include/asio/detail/impl/descriptor_ops.ipp +367/−5
- link/modules/asio-standalone/asio/include/asio/detail/impl/dev_poll_reactor.hpp +21/−1
- link/modules/asio-standalone/asio/include/asio/detail/impl/dev_poll_reactor.ipp +27/−4
- link/modules/asio-standalone/asio/include/asio/detail/impl/epoll_reactor.hpp +21/−1
- link/modules/asio-standalone/asio/include/asio/detail/impl/epoll_reactor.ipp +47/−8
- link/modules/asio-standalone/asio/include/asio/detail/impl/eventfd_select_interrupter.ipp +10/−8
- link/modules/asio-standalone/asio/include/asio/detail/impl/handler_tracking.ipp +4/−2
- link/modules/asio-standalone/asio/include/asio/detail/impl/io_uring_descriptor_service.ipp +205/−0
- link/modules/asio-standalone/asio/include/asio/detail/impl/io_uring_file_service.ipp +140/−0
- link/modules/asio-standalone/asio/include/asio/detail/impl/io_uring_service.hpp +112/−0
- link/modules/asio-standalone/asio/include/asio/detail/impl/io_uring_service.ipp +909/−0
- link/modules/asio-standalone/asio/include/asio/detail/impl/io_uring_socket_service_base.ipp +249/−0
- link/modules/asio-standalone/asio/include/asio/detail/impl/kqueue_reactor.hpp +21/−1
- link/modules/asio-standalone/asio/include/asio/detail/impl/kqueue_reactor.ipp +44/−6
- link/modules/asio-standalone/asio/include/asio/detail/impl/null_event.ipp +1/−1
- link/modules/asio-standalone/asio/include/asio/detail/impl/pipe_select_interrupter.ipp +1/−1
- link/modules/asio-standalone/asio/include/asio/detail/impl/posix_event.ipp +8/−4
- link/modules/asio-standalone/asio/include/asio/detail/impl/posix_mutex.ipp +1/−1
- link/modules/asio-standalone/asio/include/asio/detail/impl/posix_serial_port_service.ipp +168/−0
- link/modules/asio-standalone/asio/include/asio/detail/impl/posix_thread.ipp +1/−1
- link/modules/asio-standalone/asio/include/asio/detail/impl/posix_tss_ptr.ipp +1/−1
- link/modules/asio-standalone/asio/include/asio/detail/impl/reactive_descriptor_service.ipp +16/−9
- link/modules/asio-standalone/asio/include/asio/detail/impl/reactive_serial_port_service.ipp +0/−149
- link/modules/asio-standalone/asio/include/asio/detail/impl/reactive_socket_service_base.ipp +29/−19
- link/modules/asio-standalone/asio/include/asio/detail/impl/resolver_service_base.ipp +1/−1
- link/modules/asio-standalone/asio/include/asio/detail/impl/scheduler.ipp +25/−4
- link/modules/asio-standalone/asio/include/asio/detail/impl/select_reactor.hpp +25/−1
- link/modules/asio-standalone/asio/include/asio/detail/impl/select_reactor.ipp +67/−5
- link/modules/asio-standalone/asio/include/asio/detail/impl/service_registry.hpp +1/−1
- link/modules/asio-standalone/asio/include/asio/detail/impl/service_registry.ipp +1/−1
- link/modules/asio-standalone/asio/include/asio/detail/impl/signal_set_service.ipp +162/−6
- link/modules/asio-standalone/asio/include/asio/detail/impl/socket_ops.ipp +147/−132
- link/modules/asio-standalone/asio/include/asio/detail/impl/socket_select_interrupter.ipp +4/−4
- link/modules/asio-standalone/asio/include/asio/detail/impl/strand_executor_service.hpp +24/−42
- link/modules/asio-standalone/asio/include/asio/detail/impl/strand_executor_service.ipp +25/−1
- link/modules/asio-standalone/asio/include/asio/detail/impl/strand_service.hpp +3/−33
- link/modules/asio-standalone/asio/include/asio/detail/impl/strand_service.ipp +29/−5
- link/modules/asio-standalone/asio/include/asio/detail/impl/thread_context.ipp +35/−0
- link/modules/asio-standalone/asio/include/asio/detail/impl/throw_error.ipp +20/−10
- link/modules/asio-standalone/asio/include/asio/detail/impl/timer_queue_ptime.ipp +7/−1
- link/modules/asio-standalone/asio/include/asio/detail/impl/timer_queue_set.ipp +1/−1
- link/modules/asio-standalone/asio/include/asio/detail/impl/win_event.ipp +1/−1
- link/modules/asio-standalone/asio/include/asio/detail/impl/win_iocp_file_service.ipp +265/−0
- link/modules/asio-standalone/asio/include/asio/detail/impl/win_iocp_handle_service.ipp +95/−1
- link/modules/asio-standalone/asio/include/asio/detail/impl/win_iocp_io_context.hpp +18/−1
- link/modules/asio-standalone/asio/include/asio/detail/impl/win_iocp_io_context.ipp +14/−2
- link/modules/asio-standalone/asio/include/asio/detail/impl/win_iocp_serial_port_service.ipp +9/−1
- link/modules/asio-standalone/asio/include/asio/detail/impl/win_iocp_socket_service_base.ipp +46/−26
- link/modules/asio-standalone/asio/include/asio/detail/impl/win_mutex.ipp +1/−1
- link/modules/asio-standalone/asio/include/asio/detail/impl/win_object_handle_service.ipp +5/−1
- link/modules/asio-standalone/asio/include/asio/detail/impl/win_static_mutex.ipp +1/−1
- link/modules/asio-standalone/asio/include/asio/detail/impl/win_thread.ipp +1/−1
- link/modules/asio-standalone/asio/include/asio/detail/impl/win_tss_ptr.ipp +1/−1
- link/modules/asio-standalone/asio/include/asio/detail/impl/winrt_ssocket_service_base.ipp +4/−4
- link/modules/asio-standalone/asio/include/asio/detail/impl/winrt_timer_scheduler.hpp +1/−1
- link/modules/asio-standalone/asio/include/asio/detail/impl/winrt_timer_scheduler.ipp +1/−1
- link/modules/asio-standalone/asio/include/asio/detail/impl/winsock_init.ipp +1/−1
- link/modules/asio-standalone/asio/include/asio/detail/initiate_defer.hpp +252/−0
- link/modules/asio-standalone/asio/include/asio/detail/initiate_dispatch.hpp +229/−0
- link/modules/asio-standalone/asio/include/asio/detail/initiate_post.hpp +252/−0
- link/modules/asio-standalone/asio/include/asio/detail/io_control.hpp +1/−1
- link/modules/asio-standalone/asio/include/asio/detail/io_object_impl.hpp +14/−8
- link/modules/asio-standalone/asio/include/asio/detail/io_uring_descriptor_read_at_op.hpp +195/−0
- link/modules/asio-standalone/asio/include/asio/detail/io_uring_descriptor_read_op.hpp +190/−0
- link/modules/asio-standalone/asio/include/asio/detail/io_uring_descriptor_service.hpp +687/−0
- link/modules/asio-standalone/asio/include/asio/detail/io_uring_descriptor_write_at_op.hpp +189/−0
- link/modules/asio-standalone/asio/include/asio/detail/io_uring_descriptor_write_op.hpp +185/−0
- link/modules/asio-standalone/asio/include/asio/detail/io_uring_file_service.hpp +261/−0
- link/modules/asio-standalone/asio/include/asio/detail/io_uring_null_buffers_op.hpp +115/−0
- link/modules/asio-standalone/asio/include/asio/detail/io_uring_operation.hpp +84/−0
- link/modules/asio-standalone/asio/include/asio/detail/io_uring_service.hpp +319/−0
- link/modules/asio-standalone/asio/include/asio/detail/io_uring_socket_accept_op.hpp +285/−0
- link/modules/asio-standalone/asio/include/asio/detail/io_uring_socket_connect_op.hpp +141/−0
- link/modules/asio-standalone/asio/include/asio/detail/io_uring_socket_recv_op.hpp +205/−0
- link/modules/asio-standalone/asio/include/asio/detail/io_uring_socket_recvfrom_op.hpp +206/−0
- link/modules/asio-standalone/asio/include/asio/detail/io_uring_socket_recvmsg_op.hpp +192/−0
- link/modules/asio-standalone/asio/include/asio/detail/io_uring_socket_send_op.hpp +191/−0
- link/modules/asio-standalone/asio/include/asio/detail/io_uring_socket_sendto_op.hpp +194/−0
- link/modules/asio-standalone/asio/include/asio/detail/io_uring_socket_service.hpp +631/−0
- link/modules/asio-standalone/asio/include/asio/detail/io_uring_socket_service_base.hpp +663/−0
- link/modules/asio-standalone/asio/include/asio/detail/io_uring_wait_op.hpp +113/−0
- link/modules/asio-standalone/asio/include/asio/detail/is_buffer_sequence.hpp +27/−1
- link/modules/asio-standalone/asio/include/asio/detail/is_executor.hpp +1/−1
- link/modules/asio-standalone/asio/include/asio/detail/keyword_tss_ptr.hpp +1/−1
- link/modules/asio-standalone/asio/include/asio/detail/kqueue_reactor.hpp +37/−8
- link/modules/asio-standalone/asio/include/asio/detail/local_free_on_block_exit.hpp +1/−1
- link/modules/asio-standalone/asio/include/asio/detail/macos_fenced_block.hpp +1/−1
- link/modules/asio-standalone/asio/include/asio/detail/memory.hpp +95/−1
- link/modules/asio-standalone/asio/include/asio/detail/mutex.hpp +1/−1
- link/modules/asio-standalone/asio/include/asio/detail/non_const_lvalue.hpp +1/−1
- link/modules/asio-standalone/asio/include/asio/detail/noncopyable.hpp +1/−1
- link/modules/asio-standalone/asio/include/asio/detail/null_event.hpp +1/−1
- link/modules/asio-standalone/asio/include/asio/detail/null_fenced_block.hpp +1/−1
- link/modules/asio-standalone/asio/include/asio/detail/null_global.hpp +1/−1
- link/modules/asio-standalone/asio/include/asio/detail/null_mutex.hpp +1/−5
- link/modules/asio-standalone/asio/include/asio/detail/null_reactor.hpp +19/−4
- link/modules/asio-standalone/asio/include/asio/detail/null_signal_blocker.hpp +1/−1
- link/modules/asio-standalone/asio/include/asio/detail/null_socket_service.hpp +1/−1
- link/modules/asio-standalone/asio/include/asio/detail/null_static_mutex.hpp +1/−1
- link/modules/asio-standalone/asio/include/asio/detail/null_thread.hpp +1/−1
- link/modules/asio-standalone/asio/include/asio/detail/null_tss_ptr.hpp +1/−1
- link/modules/asio-standalone/asio/include/asio/detail/object_pool.hpp +1/−1
- link/modules/asio-standalone/asio/include/asio/detail/old_win_sdk_compat.hpp +1/−1
- link/modules/asio-standalone/asio/include/asio/detail/op_queue.hpp +1/−1
- link/modules/asio-standalone/asio/include/asio/detail/operation.hpp +1/−1
- link/modules/asio-standalone/asio/include/asio/detail/pipe_select_interrupter.hpp +1/−1
- link/modules/asio-standalone/asio/include/asio/detail/pop_options.hpp +17/−1
- link/modules/asio-standalone/asio/include/asio/detail/posix_event.hpp +1/−1
- link/modules/asio-standalone/asio/include/asio/detail/posix_fd_set_adapter.hpp +1/−1
- link/modules/asio-standalone/asio/include/asio/detail/posix_global.hpp +1/−1
- link/modules/asio-standalone/asio/include/asio/detail/posix_mutex.hpp +1/−1
- link/modules/asio-standalone/asio/include/asio/detail/posix_serial_port_service.hpp +249/−0
- link/modules/asio-standalone/asio/include/asio/detail/posix_signal_blocker.hpp +1/−1
- link/modules/asio-standalone/asio/include/asio/detail/posix_static_mutex.hpp +1/−1
- link/modules/asio-standalone/asio/include/asio/detail/posix_thread.hpp +1/−1
- link/modules/asio-standalone/asio/include/asio/detail/posix_tss_ptr.hpp +1/−1
- link/modules/asio-standalone/asio/include/asio/detail/push_options.hpp +45/−2
- link/modules/asio-standalone/asio/include/asio/detail/reactive_descriptor_service.hpp +176/−26
- link/modules/asio-standalone/asio/include/asio/detail/reactive_null_buffers_op.hpp +35/−1
- link/modules/asio-standalone/asio/include/asio/detail/reactive_serial_port_service.hpp +0/−237
- link/modules/asio-standalone/asio/include/asio/detail/reactive_socket_accept_op.hpp +87/−1
- link/modules/asio-standalone/asio/include/asio/detail/reactive_socket_connect_op.hpp +41/−1
- link/modules/asio-standalone/asio/include/asio/detail/reactive_socket_recv_op.hpp +40/−1
- link/modules/asio-standalone/asio/include/asio/detail/reactive_socket_recvfrom_op.hpp +41/−1
- link/modules/asio-standalone/asio/include/asio/detail/reactive_socket_recvmsg_op.hpp +41/−1
- link/modules/asio-standalone/asio/include/asio/detail/reactive_socket_send_op.hpp +41/−1
- link/modules/asio-standalone/asio/include/asio/detail/reactive_socket_sendto_op.hpp +40/−1
- link/modules/asio-standalone/asio/include/asio/detail/reactive_socket_service.hpp +127/−20
- link/modules/asio-standalone/asio/include/asio/detail/reactive_socket_service_base.hpp +239/−30
- link/modules/asio-standalone/asio/include/asio/detail/reactive_wait_op.hpp +35/−1
- link/modules/asio-standalone/asio/include/asio/detail/reactor.hpp +27/−5
- link/modules/asio-standalone/asio/include/asio/detail/reactor_fwd.hpp +0/−40
- link/modules/asio-standalone/asio/include/asio/detail/reactor_op.hpp +5/−1
- link/modules/asio-standalone/asio/include/asio/detail/reactor_op_queue.hpp +45/−1
- link/modules/asio-standalone/asio/include/asio/detail/recycling_allocator.hpp +4/−5
- link/modules/asio-standalone/asio/include/asio/detail/regex_fwd.hpp +11/−2
- link/modules/asio-standalone/asio/include/asio/detail/resolve_endpoint_op.hpp +4/−3
- link/modules/asio-standalone/asio/include/asio/detail/resolve_op.hpp +1/−1
- link/modules/asio-standalone/asio/include/asio/detail/resolve_query_op.hpp +4/−3
- link/modules/asio-standalone/asio/include/asio/detail/resolver_service.hpp +9/−7
- link/modules/asio-standalone/asio/include/asio/detail/resolver_service_base.hpp +16/−1
- link/modules/asio-standalone/asio/include/asio/detail/scheduler.hpp +17/−8
- link/modules/asio-standalone/asio/include/asio/detail/scheduler_operation.hpp +1/−1
- link/modules/asio-standalone/asio/include/asio/detail/scheduler_task.hpp +49/−0
- link/modules/asio-standalone/asio/include/asio/detail/scheduler_thread_info.hpp +1/−1
- link/modules/asio-standalone/asio/include/asio/detail/scoped_lock.hpp +1/−1
- link/modules/asio-standalone/asio/include/asio/detail/scoped_ptr.hpp +1/−1
- link/modules/asio-standalone/asio/include/asio/detail/select_interrupter.hpp +1/−1
- link/modules/asio-standalone/asio/include/asio/detail/select_reactor.hpp +59/−6
- link/modules/asio-standalone/asio/include/asio/detail/service_registry.hpp +1/−1
- link/modules/asio-standalone/asio/include/asio/detail/signal_blocker.hpp +1/−1
- link/modules/asio-standalone/asio/include/asio/detail/signal_handler.hpp +1/−1
- link/modules/asio-standalone/asio/include/asio/detail/signal_init.hpp +1/−1
- link/modules/asio-standalone/asio/include/asio/detail/signal_op.hpp +5/−1
- link/modules/asio-standalone/asio/include/asio/detail/signal_set_service.hpp +67/−4
- link/modules/asio-standalone/asio/include/asio/detail/socket_holder.hpp +1/−1
- link/modules/asio-standalone/asio/include/asio/detail/socket_ops.hpp +37/−45
- link/modules/asio-standalone/asio/include/asio/detail/socket_option.hpp +1/−1
- link/modules/asio-standalone/asio/include/asio/detail/socket_select_interrupter.hpp +1/−1
- link/modules/asio-standalone/asio/include/asio/detail/socket_types.hpp +12/−1
- link/modules/asio-standalone/asio/include/asio/detail/solaris_fenced_block.hpp +1/−1
- link/modules/asio-standalone/asio/include/asio/detail/source_location.hpp +1/−1
- link/modules/asio-standalone/asio/include/asio/detail/static_mutex.hpp +1/−1
- link/modules/asio-standalone/asio/include/asio/detail/std_event.hpp +2/−2
- link/modules/asio-standalone/asio/include/asio/detail/std_fenced_block.hpp +1/−1
- link/modules/asio-standalone/asio/include/asio/detail/std_global.hpp +1/−1
- link/modules/asio-standalone/asio/include/asio/detail/std_mutex.hpp +1/−1
- link/modules/asio-standalone/asio/include/asio/detail/std_static_mutex.hpp +1/−1
- link/modules/asio-standalone/asio/include/asio/detail/std_thread.hpp +1/−1
- link/modules/asio-standalone/asio/include/asio/detail/strand_executor_service.hpp +8/−1
- link/modules/asio-standalone/asio/include/asio/detail/strand_service.hpp +4/−5
- link/modules/asio-standalone/asio/include/asio/detail/string_view.hpp +1/−1
- link/modules/asio-standalone/asio/include/asio/detail/thread.hpp +5/−5
- link/modules/asio-standalone/asio/include/asio/detail/thread_context.hpp +10/−1
- link/modules/asio-standalone/asio/include/asio/detail/thread_group.hpp +5/−1
- link/modules/asio-standalone/asio/include/asio/detail/thread_info_base.hpp +102/−31
- link/modules/asio-standalone/asio/include/asio/detail/throw_error.hpp +18/−9
- link/modules/asio-standalone/asio/include/asio/detail/throw_exception.hpp +7/−3
- link/modules/asio-standalone/asio/include/asio/detail/timer_queue.hpp +31/−2
- link/modules/asio-standalone/asio/include/asio/detail/timer_queue_base.hpp +1/−1
- link/modules/asio-standalone/asio/include/asio/detail/timer_queue_ptime.hpp +5/−1
- link/modules/asio-standalone/asio/include/asio/detail/timer_queue_set.hpp +1/−1
- link/modules/asio-standalone/asio/include/asio/detail/timer_scheduler.hpp +3/−1
- link/modules/asio-standalone/asio/include/asio/detail/timer_scheduler_fwd.hpp +3/−1
- link/modules/asio-standalone/asio/include/asio/detail/tss_ptr.hpp +1/−1
- link/modules/asio-standalone/asio/include/asio/detail/type_traits.hpp +17/−1
- link/modules/asio-standalone/asio/include/asio/detail/utility.hpp +83/−0
- link/modules/asio-standalone/asio/include/asio/detail/variadic_templates.hpp +1/−1
- link/modules/asio-standalone/asio/include/asio/detail/wait_handler.hpp +1/−1
- link/modules/asio-standalone/asio/include/asio/detail/wait_op.hpp +6/−2
- link/modules/asio-standalone/asio/include/asio/detail/win_event.hpp +1/−1
- link/modules/asio-standalone/asio/include/asio/detail/win_fd_set_adapter.hpp +1/−1
- link/modules/asio-standalone/asio/include/asio/detail/win_fenced_block.hpp +1/−1
- link/modules/asio-standalone/asio/include/asio/detail/win_global.hpp +1/−1
- link/modules/asio-standalone/asio/include/asio/detail/win_iocp_file_service.hpp +287/−0
- link/modules/asio-standalone/asio/include/asio/detail/win_iocp_handle_read_op.hpp +4/−1
- link/modules/asio-standalone/asio/include/asio/detail/win_iocp_handle_service.hpp +105/−9
- link/modules/asio-standalone/asio/include/asio/detail/win_iocp_handle_write_op.hpp +7/−2
- link/modules/asio-standalone/asio/include/asio/detail/win_iocp_io_context.hpp +10/−5
- link/modules/asio-standalone/asio/include/asio/detail/win_iocp_null_buffers_op.hpp +4/−1
- link/modules/asio-standalone/asio/include/asio/detail/win_iocp_operation.hpp +11/−11
- link/modules/asio-standalone/asio/include/asio/detail/win_iocp_overlapped_op.hpp +7/−2
- link/modules/asio-standalone/asio/include/asio/detail/win_iocp_overlapped_ptr.hpp +1/−1
- link/modules/asio-standalone/asio/include/asio/detail/win_iocp_serial_port_service.hpp +2/−1
- link/modules/asio-standalone/asio/include/asio/detail/win_iocp_socket_accept_op.hpp +35/−3
- link/modules/asio-standalone/asio/include/asio/detail/win_iocp_socket_connect_op.hpp +5/−1
- link/modules/asio-standalone/asio/include/asio/detail/win_iocp_socket_recv_op.hpp +4/−1
- link/modules/asio-standalone/asio/include/asio/detail/win_iocp_socket_recvfrom_op.hpp +4/−1
- link/modules/asio-standalone/asio/include/asio/detail/win_iocp_socket_recvmsg_op.hpp +4/−1
- link/modules/asio-standalone/asio/include/asio/detail/win_iocp_socket_send_op.hpp +4/−1
- link/modules/asio-standalone/asio/include/asio/detail/win_iocp_socket_service.hpp +124/−22
- link/modules/asio-standalone/asio/include/asio/detail/win_iocp_socket_service_base.hpp +253/−23
- link/modules/asio-standalone/asio/include/asio/detail/win_iocp_thread_info.hpp +1/−1
- link/modules/asio-standalone/asio/include/asio/detail/win_iocp_wait_op.hpp +4/−1
- link/modules/asio-standalone/asio/include/asio/detail/win_mutex.hpp +1/−1
- link/modules/asio-standalone/asio/include/asio/detail/win_object_handle_service.hpp +1/−1
- link/modules/asio-standalone/asio/include/asio/detail/win_static_mutex.hpp +1/−1
- link/modules/asio-standalone/asio/include/asio/detail/win_thread.hpp +1/−1
- link/modules/asio-standalone/asio/include/asio/detail/win_tss_ptr.hpp +1/−1
- link/modules/asio-standalone/asio/include/asio/detail/winapp_thread.hpp +1/−1
- link/modules/asio-standalone/asio/include/asio/detail/wince_thread.hpp +1/−1
- link/modules/asio-standalone/asio/include/asio/detail/winrt_async_manager.hpp +1/−1
- link/modules/asio-standalone/asio/include/asio/detail/winrt_async_op.hpp +1/−1
- link/modules/asio-standalone/asio/include/asio/detail/winrt_resolve_op.hpp +2/−1
- link/modules/asio-standalone/asio/include/asio/detail/winrt_resolver_service.hpp +1/−1
- link/modules/asio-standalone/asio/include/asio/detail/winrt_socket_connect_op.hpp +2/−1
- link/modules/asio-standalone/asio/include/asio/detail/winrt_socket_recv_op.hpp +2/−1
- link/modules/asio-standalone/asio/include/asio/detail/winrt_socket_send_op.hpp +2/−1
- link/modules/asio-standalone/asio/include/asio/detail/winrt_ssocket_service.hpp +1/−1
- link/modules/asio-standalone/asio/include/asio/detail/winrt_ssocket_service_base.hpp +1/−1
- link/modules/asio-standalone/asio/include/asio/detail/winrt_timer_scheduler.hpp +1/−1
- link/modules/asio-standalone/asio/include/asio/detail/winrt_utils.hpp +1/−1
- link/modules/asio-standalone/asio/include/asio/detail/winsock_init.hpp +1/−1
- link/modules/asio-standalone/asio/include/asio/detail/work_dispatcher.hpp +15/−6
- link/modules/asio-standalone/asio/include/asio/detail/wrapped_handler.hpp +1/−1
- link/modules/asio-standalone/asio/include/asio/dispatch.hpp +122/−41
- link/modules/asio-standalone/asio/include/asio/error.hpp +36/−1
- link/modules/asio-standalone/asio/include/asio/error_code.hpp +1/−1
- link/modules/asio-standalone/asio/include/asio/execution.hpp +1/−1
- link/modules/asio-standalone/asio/include/asio/execution/allocator.hpp +126/−19
- link/modules/asio-standalone/asio/include/asio/execution/any_executor.hpp +648/−249
- link/modules/asio-standalone/asio/include/asio/execution/bad_executor.hpp +1/−1
- link/modules/asio-standalone/asio/include/asio/execution/blocking.hpp +332/−83
- link/modules/asio-standalone/asio/include/asio/execution/blocking_adaptation.hpp +263/−70
- link/modules/asio-standalone/asio/include/asio/execution/bulk_execute.hpp +57/−45
- link/modules/asio-standalone/asio/include/asio/execution/bulk_guarantee.hpp +324/−90
- link/modules/asio-standalone/asio/include/asio/execution/connect.hpp +44/−36
- link/modules/asio-standalone/asio/include/asio/execution/context.hpp +73/−14
- link/modules/asio-standalone/asio/include/asio/execution/context_as.hpp +40/−9
- link/modules/asio-standalone/asio/include/asio/execution/detail/as_invocable.hpp +1/−1
- link/modules/asio-standalone/asio/include/asio/execution/detail/as_operation.hpp +5/−1
- link/modules/asio-standalone/asio/include/asio/execution/detail/as_receiver.hpp +1/−1
- link/modules/asio-standalone/asio/include/asio/execution/detail/bulk_sender.hpp +1/−1
- link/modules/asio-standalone/asio/include/asio/execution/detail/submit_receiver.hpp +1/−1
- link/modules/asio-standalone/asio/include/asio/execution/detail/void_receiver.hpp +1/−1
- link/modules/asio-standalone/asio/include/asio/execution/execute.hpp +76/−50
- link/modules/asio-standalone/asio/include/asio/execution/executor.hpp +50/−26
- link/modules/asio-standalone/asio/include/asio/execution/impl/bad_executor.ipp +1/−1
- link/modules/asio-standalone/asio/include/asio/execution/impl/receiver_invocation_error.ipp +1/−1
- link/modules/asio-standalone/asio/include/asio/execution/invocable_archetype.hpp +1/−1
- link/modules/asio-standalone/asio/include/asio/execution/mapping.hpp +325/−82
- link/modules/asio-standalone/asio/include/asio/execution/occupancy.hpp +73/−14
- link/modules/asio-standalone/asio/include/asio/execution/operation_state.hpp +6/−1
- link/modules/asio-standalone/asio/include/asio/execution/outstanding_work.hpp +249/−70
- link/modules/asio-standalone/asio/include/asio/execution/prefer_only.hpp +7/−3
- link/modules/asio-standalone/asio/include/asio/execution/receiver.hpp +6/−1
- link/modules/asio-standalone/asio/include/asio/execution/receiver_invocation_error.hpp +1/−1
- link/modules/asio-standalone/asio/include/asio/execution/relationship.hpp +248/−70
- link/modules/asio-standalone/asio/include/asio/execution/schedule.hpp +19/−17
- link/modules/asio-standalone/asio/include/asio/execution/scheduler.hpp +6/−1
- link/modules/asio-standalone/asio/include/asio/execution/sender.hpp +6/−1
- link/modules/asio-standalone/asio/include/asio/execution/set_done.hpp +12/−10
- link/modules/asio-standalone/asio/include/asio/execution/set_error.hpp +12/−10
- link/modules/asio-standalone/asio/include/asio/execution/set_value.hpp +12/−10
- link/modules/asio-standalone/asio/include/asio/execution/start.hpp +12/−10
- link/modules/asio-standalone/asio/include/asio/execution/submit.hpp +26/−21
- link/modules/asio-standalone/asio/include/asio/execution_context.hpp +1/−1
- link/modules/asio-standalone/asio/include/asio/executor.hpp +1/−1
- link/modules/asio-standalone/asio/include/asio/executor_work_guard.hpp +130/−50
- link/modules/asio-standalone/asio/include/asio/experimental/append.hpp +36/−0
- link/modules/asio-standalone/asio/include/asio/experimental/as_single.hpp +136/−0
- link/modules/asio-standalone/asio/include/asio/experimental/as_tuple.hpp +36/−0
- link/modules/asio-standalone/asio/include/asio/experimental/awaitable_operators.hpp +536/−0
- link/modules/asio-standalone/asio/include/asio/experimental/basic_channel.hpp +491/−0
- link/modules/asio-standalone/asio/include/asio/experimental/basic_concurrent_channel.hpp +491/−0
- link/modules/asio-standalone/asio/include/asio/experimental/cancellation_condition.hpp +155/−0
- link/modules/asio-standalone/asio/include/asio/experimental/channel.hpp +70/−0
- link/modules/asio-standalone/asio/include/asio/experimental/channel_error.hpp +84/−0
- link/modules/asio-standalone/asio/include/asio/experimental/channel_traits.hpp +301/−0
- link/modules/asio-standalone/asio/include/asio/experimental/co_composed.hpp +144/−0
- link/modules/asio-standalone/asio/include/asio/experimental/co_spawn.hpp +187/−0
- link/modules/asio-standalone/asio/include/asio/experimental/concurrent_channel.hpp +70/−0
- link/modules/asio-standalone/asio/include/asio/experimental/coro.hpp +293/−0
- link/modules/asio-standalone/asio/include/asio/experimental/coro_traits.hpp +228/−0
- link/modules/asio-standalone/asio/include/asio/experimental/deferred.hpp +36/−0
- link/modules/asio-standalone/asio/include/asio/experimental/detail/channel_handler.hpp +80/−0
- link/modules/asio-standalone/asio/include/asio/experimental/detail/channel_message.hpp +129/−0
- link/modules/asio-standalone/asio/include/asio/experimental/detail/channel_operation.hpp +284/−0
- link/modules/asio-standalone/asio/include/asio/experimental/detail/channel_payload.hpp +139/−0
- link/modules/asio-standalone/asio/include/asio/experimental/detail/channel_receive_op.hpp +120/−0
- link/modules/asio-standalone/asio/include/asio/experimental/detail/channel_send_functions.hpp +144/−0
- link/modules/asio-standalone/asio/include/asio/experimental/detail/channel_send_op.hpp +148/−0
- link/modules/asio-standalone/asio/include/asio/experimental/detail/channel_service.hpp +677/−0
- link/modules/asio-standalone/asio/include/asio/experimental/detail/coro_completion_handler.hpp +169/−0
- link/modules/asio-standalone/asio/include/asio/experimental/detail/coro_promise_allocator.hpp +141/−0
- link/modules/asio-standalone/asio/include/asio/experimental/detail/has_signature.hpp +54/−0
- link/modules/asio-standalone/asio/include/asio/experimental/detail/impl/channel_service.hpp +612/−0
- link/modules/asio-standalone/asio/include/asio/experimental/detail/partial_promise.hpp +197/−0
- link/modules/asio-standalone/asio/include/asio/experimental/impl/as_single.hpp +239/−0
- link/modules/asio-standalone/asio/include/asio/experimental/impl/channel_error.ipp +61/−0
- link/modules/asio-standalone/asio/include/asio/experimental/impl/co_composed.hpp +1175/−0
- link/modules/asio-standalone/asio/include/asio/experimental/impl/coro.hpp +1222/−0
- link/modules/asio-standalone/asio/include/asio/experimental/impl/parallel_group.hpp +792/−0
- link/modules/asio-standalone/asio/include/asio/experimental/impl/promise.hpp +254/−0
- link/modules/asio-standalone/asio/include/asio/experimental/impl/use_coro.hpp +214/−0
- link/modules/asio-standalone/asio/include/asio/experimental/impl/use_promise.hpp +66/−0
- link/modules/asio-standalone/asio/include/asio/experimental/parallel_group.hpp +461/−0
- link/modules/asio-standalone/asio/include/asio/experimental/prepend.hpp +36/−0
- link/modules/asio-standalone/asio/include/asio/experimental/promise.hpp +224/−0
- link/modules/asio-standalone/asio/include/asio/experimental/use_coro.hpp +195/−0
- link/modules/asio-standalone/asio/include/asio/experimental/use_promise.hpp +111/−0
- link/modules/asio-standalone/asio/include/asio/file_base.hpp +166/−0
- link/modules/asio-standalone/asio/include/asio/generic/basic_endpoint.hpp +1/−1
- link/modules/asio-standalone/asio/include/asio/generic/datagram_protocol.hpp +1/−1
- link/modules/asio-standalone/asio/include/asio/generic/detail/endpoint.hpp +1/−1
- link/modules/asio-standalone/asio/include/asio/generic/detail/impl/endpoint.ipp +1/−1
- link/modules/asio-standalone/asio/include/asio/generic/raw_protocol.hpp +1/−1
- link/modules/asio-standalone/asio/include/asio/generic/seq_packet_protocol.hpp +1/−1
- link/modules/asio-standalone/asio/include/asio/generic/stream_protocol.hpp +1/−1
- link/modules/asio-standalone/asio/include/asio/handler_alloc_hook.hpp +1/−1
- link/modules/asio-standalone/asio/include/asio/handler_continuation_hook.hpp +1/−1
- link/modules/asio-standalone/asio/include/asio/handler_invoke_hook.hpp +1/−1
- link/modules/asio-standalone/asio/include/asio/high_resolution_timer.hpp +1/−1
- link/modules/asio-standalone/asio/include/asio/impl/any_completion_executor.ipp +130/−0
- link/modules/asio-standalone/asio/include/asio/impl/any_io_executor.ipp +141/−0
- link/modules/asio-standalone/asio/include/asio/impl/append.hpp +225/−0
- link/modules/asio-standalone/asio/include/asio/impl/as_tuple.hpp +320/−0
- link/modules/asio-standalone/asio/include/asio/impl/awaitable.hpp +785/−26
- link/modules/asio-standalone/asio/include/asio/impl/buffered_read_stream.hpp +50/−50
- link/modules/asio-standalone/asio/include/asio/impl/buffered_write_stream.hpp +50/−50
- link/modules/asio-standalone/asio/include/asio/impl/cancellation_signal.ipp +96/−0
- link/modules/asio-standalone/asio/include/asio/impl/co_spawn.hpp +127/−26
- link/modules/asio-standalone/asio/include/asio/impl/compose.hpp +0/−635
- link/modules/asio-standalone/asio/include/asio/impl/connect.hpp +170/−127
- link/modules/asio-standalone/asio/include/asio/impl/connect_pipe.hpp +73/−0
- link/modules/asio-standalone/asio/include/asio/impl/connect_pipe.ipp +149/−0
- link/modules/asio-standalone/asio/include/asio/impl/consign.hpp +202/−0
- link/modules/asio-standalone/asio/include/asio/impl/defer.hpp +0/−248
- link/modules/asio-standalone/asio/include/asio/impl/deferred.hpp +156/−0
- link/modules/asio-standalone/asio/include/asio/impl/detached.hpp +1/−1
- link/modules/asio-standalone/asio/include/asio/impl/dispatch.hpp +0/−243
- link/modules/asio-standalone/asio/include/asio/impl/error.ipp +1/−1
- link/modules/asio-standalone/asio/include/asio/impl/error_code.ipp +1/−1
- link/modules/asio-standalone/asio/include/asio/impl/execution_context.hpp +1/−1
- link/modules/asio-standalone/asio/include/asio/impl/execution_context.ipp +1/−1
- link/modules/asio-standalone/asio/include/asio/impl/executor.hpp +1/−2
- link/modules/asio-standalone/asio/include/asio/impl/executor.ipp +1/−1
- link/modules/asio-standalone/asio/include/asio/impl/handler_alloc_hook.ipp +6/−5
- link/modules/asio-standalone/asio/include/asio/impl/io_context.hpp +57/−47
- link/modules/asio-standalone/asio/include/asio/impl/io_context.ipp +2/−1
- link/modules/asio-standalone/asio/include/asio/impl/multiple_exceptions.ipp +1/−1
- link/modules/asio-standalone/asio/include/asio/impl/post.hpp +0/−248
- link/modules/asio-standalone/asio/include/asio/impl/prepend.hpp +225/−0
- link/modules/asio-standalone/asio/include/asio/impl/read.hpp +275/−201
- link/modules/asio-standalone/asio/include/asio/impl/read_at.hpp +141/−111
- link/modules/asio-standalone/asio/include/asio/impl/read_until.hpp +498/−378
- link/modules/asio-standalone/asio/include/asio/impl/redirect_error.hpp +302/−58
- link/modules/asio-standalone/asio/include/asio/impl/serial_port_base.hpp +1/−1
- link/modules/asio-standalone/asio/include/asio/impl/serial_port_base.ipp +1/−1
- link/modules/asio-standalone/asio/include/asio/impl/spawn.hpp +1606/−516
- link/modules/asio-standalone/asio/include/asio/impl/src.hpp +13/−2
- link/modules/asio-standalone/asio/include/asio/impl/system_context.hpp +1/−1
- link/modules/asio-standalone/asio/include/asio/impl/system_context.ipp +1/−1
- link/modules/asio-standalone/asio/include/asio/impl/system_executor.hpp +1/−2
- link/modules/asio-standalone/asio/include/asio/impl/thread_pool.hpp +6/−2
- link/modules/asio-standalone/asio/include/asio/impl/thread_pool.ipp +5/−4
- link/modules/asio-standalone/asio/include/asio/impl/use_awaitable.hpp +43/−21
- link/modules/asio-standalone/asio/include/asio/impl/use_future.hpp +28/−3
- link/modules/asio-standalone/asio/include/asio/impl/write.hpp +235/−186
- link/modules/asio-standalone/asio/include/asio/impl/write_at.hpp +117/−96
- link/modules/asio-standalone/asio/include/asio/io_context.hpp +126/−122
- link/modules/asio-standalone/asio/include/asio/io_context_strand.hpp +15/−3
- link/modules/asio-standalone/asio/include/asio/io_service.hpp +1/−1
- link/modules/asio-standalone/asio/include/asio/io_service_strand.hpp +1/−1
- link/modules/asio-standalone/asio/include/asio/ip/address.hpp +23/−1
- link/modules/asio-standalone/asio/include/asio/ip/address_v4.hpp +98/−3
- link/modules/asio-standalone/asio/include/asio/ip/address_v4_iterator.hpp +1/−1
- link/modules/asio-standalone/asio/include/asio/ip/address_v4_range.hpp +1/−1
- link/modules/asio-standalone/asio/include/asio/ip/address_v6.hpp +81/−6
- link/modules/asio-standalone/asio/include/asio/ip/address_v6_iterator.hpp +1/−1
- link/modules/asio-standalone/asio/include/asio/ip/address_v6_range.hpp +1/−1
- link/modules/asio-standalone/asio/include/asio/ip/bad_address_cast.hpp +1/−1
- link/modules/asio-standalone/asio/include/asio/ip/basic_endpoint.hpp +32/−5
- link/modules/asio-standalone/asio/include/asio/ip/basic_resolver.hpp +180/−68
- link/modules/asio-standalone/asio/include/asio/ip/basic_resolver_entry.hpp +1/−1
- link/modules/asio-standalone/asio/include/asio/ip/basic_resolver_iterator.hpp +1/−1
- link/modules/asio-standalone/asio/include/asio/ip/basic_resolver_query.hpp +1/−1
- link/modules/asio-standalone/asio/include/asio/ip/basic_resolver_results.hpp +1/−1
- link/modules/asio-standalone/asio/include/asio/ip/detail/endpoint.hpp +1/−1
- link/modules/asio-standalone/asio/include/asio/ip/detail/impl/endpoint.ipp +1/−1
- link/modules/asio-standalone/asio/include/asio/ip/detail/socket_option.hpp +1/−1
- link/modules/asio-standalone/asio/include/asio/ip/host_name.hpp +1/−1
- link/modules/asio-standalone/asio/include/asio/ip/icmp.hpp +1/−1
- link/modules/asio-standalone/asio/include/asio/ip/impl/address.hpp +1/−1
- link/modules/asio-standalone/asio/include/asio/ip/impl/address.ipp +1/−1
- link/modules/asio-standalone/asio/include/asio/ip/impl/address_v4.hpp +1/−1
- link/modules/asio-standalone/asio/include/asio/ip/impl/address_v4.ipp +1/−1
- link/modules/asio-standalone/asio/include/asio/ip/impl/address_v6.hpp +1/−1
- link/modules/asio-standalone/asio/include/asio/ip/impl/address_v6.ipp +2/−2
- link/modules/asio-standalone/asio/include/asio/ip/impl/basic_endpoint.hpp +1/−1
- link/modules/asio-standalone/asio/include/asio/ip/impl/host_name.ipp +1/−1
- link/modules/asio-standalone/asio/include/asio/ip/impl/network_v4.hpp +1/−1
- link/modules/asio-standalone/asio/include/asio/ip/impl/network_v4.ipp +4/−2
- link/modules/asio-standalone/asio/include/asio/ip/impl/network_v6.hpp +1/−1
- link/modules/asio-standalone/asio/include/asio/ip/impl/network_v6.ipp +4/−2
- link/modules/asio-standalone/asio/include/asio/ip/multicast.hpp +1/−1
- link/modules/asio-standalone/asio/include/asio/ip/network_v4.hpp +2/−2
- link/modules/asio-standalone/asio/include/asio/ip/network_v6.hpp +1/−1
- link/modules/asio-standalone/asio/include/asio/ip/resolver_base.hpp +1/−1
- link/modules/asio-standalone/asio/include/asio/ip/resolver_query_base.hpp +1/−1
- link/modules/asio-standalone/asio/include/asio/ip/tcp.hpp +1/−1
- link/modules/asio-standalone/asio/include/asio/ip/udp.hpp +1/−1
- link/modules/asio-standalone/asio/include/asio/ip/unicast.hpp +1/−1
- link/modules/asio-standalone/asio/include/asio/ip/v6_only.hpp +2/−2
- link/modules/asio-standalone/asio/include/asio/is_applicable_property.hpp +1/−1
- link/modules/asio-standalone/asio/include/asio/is_contiguous_iterator.hpp +45/−0
- link/modules/asio-standalone/asio/include/asio/is_executor.hpp +1/−1
- link/modules/asio-standalone/asio/include/asio/is_read_buffered.hpp +1/−1
- link/modules/asio-standalone/asio/include/asio/is_write_buffered.hpp +1/−1
- link/modules/asio-standalone/asio/include/asio/local/basic_endpoint.hpp +1/−1
- link/modules/asio-standalone/asio/include/asio/local/connect_pair.hpp +1/−1
- link/modules/asio-standalone/asio/include/asio/local/datagram_protocol.hpp +1/−1
- link/modules/asio-standalone/asio/include/asio/local/detail/endpoint.hpp +1/−1
- link/modules/asio-standalone/asio/include/asio/local/detail/impl/endpoint.ipp +3/−8
- link/modules/asio-standalone/asio/include/asio/local/seq_packet_protocol.hpp +84/−0
- link/modules/asio-standalone/asio/include/asio/local/stream_protocol.hpp +1/−1
- link/modules/asio-standalone/asio/include/asio/multiple_exceptions.hpp +1/−1
- link/modules/asio-standalone/asio/include/asio/packaged_task.hpp +1/−1
- link/modules/asio-standalone/asio/include/asio/placeholders.hpp +1/−1
- link/modules/asio-standalone/asio/include/asio/posix/basic_descriptor.hpp +111/−27
- link/modules/asio-standalone/asio/include/asio/posix/basic_stream_descriptor.hpp +136/−37
- link/modules/asio-standalone/asio/include/asio/posix/descriptor.hpp +1/−1
- link/modules/asio-standalone/asio/include/asio/posix/descriptor_base.hpp +1/−1
- link/modules/asio-standalone/asio/include/asio/posix/stream_descriptor.hpp +1/−1
- link/modules/asio-standalone/asio/include/asio/post.hpp +134/−42
- link/modules/asio-standalone/asio/include/asio/prefer.hpp +235/−157
- link/modules/asio-standalone/asio/include/asio/prepend.hpp +78/−0
- link/modules/asio-standalone/asio/include/asio/query.hpp +79/−51
- link/modules/asio-standalone/asio/include/asio/random_access_file.hpp +35/−0
- link/modules/asio-standalone/asio/include/asio/read.hpp +381/−189
- link/modules/asio-standalone/asio/include/asio/read_at.hpp +154/−53
- link/modules/asio-standalone/asio/include/asio/read_until.hpp +529/−226
- link/modules/asio-standalone/asio/include/asio/readable_pipe.hpp +35/−0
- link/modules/asio-standalone/asio/include/asio/recycling_allocator.hpp +138/−0
- link/modules/asio-standalone/asio/include/asio/redirect_error.hpp +3/−3
- link/modules/asio-standalone/asio/include/asio/registered_buffer.hpp +356/−0
- link/modules/asio-standalone/asio/include/asio/require.hpp +136/−89
- link/modules/asio-standalone/asio/include/asio/require_concept.hpp +100/−58
- link/modules/asio-standalone/asio/include/asio/serial_port.hpp +1/−1
- link/modules/asio-standalone/asio/include/asio/serial_port_base.hpp +1/−1
- link/modules/asio-standalone/asio/include/asio/signal_set.hpp +1/−1
- link/modules/asio-standalone/asio/include/asio/signal_set_base.hpp +182/−0
- link/modules/asio-standalone/asio/include/asio/socket_base.hpp +1/−1
- link/modules/asio-standalone/asio/include/asio/spawn.hpp +654/−92
- link/modules/asio-standalone/asio/include/asio/ssl.hpp +1/−1
- link/modules/asio-standalone/asio/include/asio/ssl/context.hpp +4/−1
- link/modules/asio-standalone/asio/include/asio/ssl/context_base.hpp +24/−24
- link/modules/asio-standalone/asio/include/asio/ssl/detail/buffered_handshake_op.hpp +2/−2
- link/modules/asio-standalone/asio/include/asio/ssl/detail/engine.hpp +9/−1
- link/modules/asio-standalone/asio/include/asio/ssl/detail/handshake_op.hpp +2/−2
- link/modules/asio-standalone/asio/include/asio/ssl/detail/impl/engine.ipp +33/−1
- link/modules/asio-standalone/asio/include/asio/ssl/detail/impl/openssl_init.ipp +7/−3
- link/modules/asio-standalone/asio/include/asio/ssl/detail/io.hpp +44/−24
- link/modules/asio-standalone/asio/include/asio/ssl/detail/openssl_init.hpp +1/−1
- link/modules/asio-standalone/asio/include/asio/ssl/detail/openssl_types.hpp +1/−1
- link/modules/asio-standalone/asio/include/asio/ssl/detail/password_callback.hpp +1/−1
- link/modules/asio-standalone/asio/include/asio/ssl/detail/read_op.hpp +2/−2
- link/modules/asio-standalone/asio/include/asio/ssl/detail/shutdown_op.hpp +3/−3
- link/modules/asio-standalone/asio/include/asio/ssl/detail/stream_core.hpp +53/−1
- link/modules/asio-standalone/asio/include/asio/ssl/detail/verify_callback.hpp +1/−1
- link/modules/asio-standalone/asio/include/asio/ssl/detail/write_op.hpp +2/−2
- link/modules/asio-standalone/asio/include/asio/ssl/error.hpp +1/−1
- link/modules/asio-standalone/asio/include/asio/ssl/host_name_verification.hpp +1/−1
- link/modules/asio-standalone/asio/include/asio/ssl/impl/context.hpp +1/−1
- link/modules/asio-standalone/asio/include/asio/ssl/impl/context.ipp +154/−71
- link/modules/asio-standalone/asio/include/asio/ssl/impl/error.ipp +25/−3
- link/modules/asio-standalone/asio/include/asio/ssl/impl/host_name_verification.ipp +1/−1
- link/modules/asio-standalone/asio/include/asio/ssl/impl/rfc2818_verification.ipp +1/−1
- link/modules/asio-standalone/asio/include/asio/ssl/impl/src.hpp +1/−1
- link/modules/asio-standalone/asio/include/asio/ssl/rfc2818_verification.hpp +1/−1
- link/modules/asio-standalone/asio/include/asio/ssl/stream.hpp +226/−53
- link/modules/asio-standalone/asio/include/asio/ssl/stream_base.hpp +1/−1
- link/modules/asio-standalone/asio/include/asio/ssl/verify_context.hpp +1/−1
- link/modules/asio-standalone/asio/include/asio/ssl/verify_mode.hpp +1/−1
- link/modules/asio-standalone/asio/include/asio/static_thread_pool.hpp +1/−1
- link/modules/asio-standalone/asio/include/asio/steady_timer.hpp +1/−1
- link/modules/asio-standalone/asio/include/asio/strand.hpp +77/−30
- link/modules/asio-standalone/asio/include/asio/stream_file.hpp +35/−0
- link/modules/asio-standalone/asio/include/asio/streambuf.hpp +1/−1
- link/modules/asio-standalone/asio/include/asio/system_context.hpp +1/−1
- link/modules/asio-standalone/asio/include/asio/system_error.hpp +1/−1
- link/modules/asio-standalone/asio/include/asio/system_executor.hpp +18/−9
- link/modules/asio-standalone/asio/include/asio/system_timer.hpp +1/−1
- link/modules/asio-standalone/asio/include/asio/this_coro.hpp +236/−1
- link/modules/asio-standalone/asio/include/asio/thread.hpp +1/−1
- link/modules/asio-standalone/asio/include/asio/thread_pool.hpp +48/−14
- link/modules/asio-standalone/asio/include/asio/time_traits.hpp +1/−1
- link/modules/asio-standalone/asio/include/asio/traits/bulk_execute_free.hpp +1/−1
- link/modules/asio-standalone/asio/include/asio/traits/bulk_execute_member.hpp +1/−1
- link/modules/asio-standalone/asio/include/asio/traits/connect_free.hpp +1/−1
- link/modules/asio-standalone/asio/include/asio/traits/connect_member.hpp +1/−1
- link/modules/asio-standalone/asio/include/asio/traits/equality_comparable.hpp +7/−3
- link/modules/asio-standalone/asio/include/asio/traits/execute_free.hpp +1/−1
- link/modules/asio-standalone/asio/include/asio/traits/execute_member.hpp +1/−1
- link/modules/asio-standalone/asio/include/asio/traits/prefer_free.hpp +1/−1
- link/modules/asio-standalone/asio/include/asio/traits/prefer_member.hpp +1/−1
- link/modules/asio-standalone/asio/include/asio/traits/query_free.hpp +1/−1
- link/modules/asio-standalone/asio/include/asio/traits/query_member.hpp +1/−1
- link/modules/asio-standalone/asio/include/asio/traits/query_static_constexpr_member.hpp +1/−1
- link/modules/asio-standalone/asio/include/asio/traits/require_concept_free.hpp +1/−1
- link/modules/asio-standalone/asio/include/asio/traits/require_concept_member.hpp +1/−1
- link/modules/asio-standalone/asio/include/asio/traits/require_free.hpp +1/−1
- link/modules/asio-standalone/asio/include/asio/traits/require_member.hpp +1/−1
- link/modules/asio-standalone/asio/include/asio/traits/schedule_free.hpp +1/−1
- link/modules/asio-standalone/asio/include/asio/traits/schedule_member.hpp +1/−1
- link/modules/asio-standalone/asio/include/asio/traits/set_done_free.hpp +1/−1
- link/modules/asio-standalone/asio/include/asio/traits/set_done_member.hpp +1/−1
- link/modules/asio-standalone/asio/include/asio/traits/set_error_free.hpp +1/−1
- link/modules/asio-standalone/asio/include/asio/traits/set_error_member.hpp +1/−1
- link/modules/asio-standalone/asio/include/asio/traits/set_value_free.hpp +1/−1
- link/modules/asio-standalone/asio/include/asio/traits/set_value_member.hpp +1/−1
- link/modules/asio-standalone/asio/include/asio/traits/start_free.hpp +1/−1
- link/modules/asio-standalone/asio/include/asio/traits/start_member.hpp +1/−1
- link/modules/asio-standalone/asio/include/asio/traits/static_query.hpp +1/−1
- link/modules/asio-standalone/asio/include/asio/traits/static_require.hpp +1/−1
- link/modules/asio-standalone/asio/include/asio/traits/static_require_concept.hpp +3/−2
- link/modules/asio-standalone/asio/include/asio/traits/submit_free.hpp +1/−1
- link/modules/asio-standalone/asio/include/asio/traits/submit_member.hpp +1/−1
- link/modules/asio-standalone/asio/include/asio/ts/buffer.hpp +1/−1
- link/modules/asio-standalone/asio/include/asio/ts/executor.hpp +1/−1
- link/modules/asio-standalone/asio/include/asio/ts/internet.hpp +1/−1
- link/modules/asio-standalone/asio/include/asio/ts/io_context.hpp +1/−1
- link/modules/asio-standalone/asio/include/asio/ts/net.hpp +1/−1
- link/modules/asio-standalone/asio/include/asio/ts/netfwd.hpp +3/−11
- link/modules/asio-standalone/asio/include/asio/ts/socket.hpp +1/−1
- link/modules/asio-standalone/asio/include/asio/ts/timer.hpp +1/−1
- link/modules/asio-standalone/asio/include/asio/unyield.hpp +1/−1
- link/modules/asio-standalone/asio/include/asio/use_awaitable.hpp +13/−15
- link/modules/asio-standalone/asio/include/asio/use_future.hpp +10/−7
- link/modules/asio-standalone/asio/include/asio/uses_executor.hpp +1/−1
- link/modules/asio-standalone/asio/include/asio/version.hpp +2/−2
- link/modules/asio-standalone/asio/include/asio/wait_traits.hpp +1/−1
- link/modules/asio-standalone/asio/include/asio/windows/basic_object_handle.hpp +81/−23
- link/modules/asio-standalone/asio/include/asio/windows/basic_overlapped_handle.hpp +110/−11
- link/modules/asio-standalone/asio/include/asio/windows/basic_random_access_handle.hpp +125/−36
- link/modules/asio-standalone/asio/include/asio/windows/basic_stream_handle.hpp +122/−35
- link/modules/asio-standalone/asio/include/asio/windows/object_handle.hpp +1/−1
- link/modules/asio-standalone/asio/include/asio/windows/overlapped_handle.hpp +1/−1
- link/modules/asio-standalone/asio/include/asio/windows/overlapped_ptr.hpp +9/−9
- link/modules/asio-standalone/asio/include/asio/windows/random_access_handle.hpp +1/−1
- link/modules/asio-standalone/asio/include/asio/windows/stream_handle.hpp +1/−1
- link/modules/asio-standalone/asio/include/asio/writable_pipe.hpp +35/−0
- link/modules/asio-standalone/asio/include/asio/write.hpp +376/−184
- link/modules/asio-standalone/asio/include/asio/write_at.hpp +156/−53
- link/modules/asio-standalone/asio/include/asio/yield.hpp +1/−1
- link/modules/asio-standalone/asio/src/examples/cpp03/chat/chat_message.hpp +6/−3
- link/modules/asio-standalone/asio/src/examples/cpp03/http/server/connection.hpp +1/−1
- link/modules/asio-standalone/asio/src/examples/cpp03/http/server/connection_manager.hpp +1/−1
- link/modules/asio-standalone/asio/src/examples/cpp03/http/server/header.hpp +1/−1
- link/modules/asio-standalone/asio/src/examples/cpp03/http/server/mime_types.hpp +1/−1
- link/modules/asio-standalone/asio/src/examples/cpp03/http/server/reply.hpp +1/−1
- link/modules/asio-standalone/asio/src/examples/cpp03/http/server/request.hpp +1/−1
- link/modules/asio-standalone/asio/src/examples/cpp03/http/server/request_handler.hpp +1/−1
- link/modules/asio-standalone/asio/src/examples/cpp03/http/server/request_parser.hpp +1/−1
- link/modules/asio-standalone/asio/src/examples/cpp03/http/server/server.hpp +1/−1
- link/modules/asio-standalone/asio/src/examples/cpp03/http/server2/connection.hpp +1/−1
- link/modules/asio-standalone/asio/src/examples/cpp03/http/server2/header.hpp +1/−1
- link/modules/asio-standalone/asio/src/examples/cpp03/http/server2/io_context_pool.hpp +5/−3
- link/modules/asio-standalone/asio/src/examples/cpp03/http/server2/mime_types.hpp +1/−1
- link/modules/asio-standalone/asio/src/examples/cpp03/http/server2/reply.hpp +1/−1
- link/modules/asio-standalone/asio/src/examples/cpp03/http/server2/request.hpp +1/−1
- link/modules/asio-standalone/asio/src/examples/cpp03/http/server2/request_handler.hpp +1/−1
- link/modules/asio-standalone/asio/src/examples/cpp03/http/server2/request_parser.hpp +1/−1
- link/modules/asio-standalone/asio/src/examples/cpp03/http/server2/server.hpp +1/−1
- link/modules/asio-standalone/asio/src/examples/cpp03/http/server3/connection.hpp +1/−1
- link/modules/asio-standalone/asio/src/examples/cpp03/http/server3/header.hpp +1/−1
- link/modules/asio-standalone/asio/src/examples/cpp03/http/server3/mime_types.hpp +1/−1
- link/modules/asio-standalone/asio/src/examples/cpp03/http/server3/reply.hpp +1/−1
- link/modules/asio-standalone/asio/src/examples/cpp03/http/server3/request.hpp +1/−1
- link/modules/asio-standalone/asio/src/examples/cpp03/http/server3/request_handler.hpp +1/−1
- link/modules/asio-standalone/asio/src/examples/cpp03/http/server3/request_parser.hpp +1/−1
- link/modules/asio-standalone/asio/src/examples/cpp03/http/server3/server.hpp +1/−1
- link/modules/asio-standalone/asio/src/examples/cpp03/http/server4/file_handler.hpp +1/−1
- link/modules/asio-standalone/asio/src/examples/cpp03/http/server4/header.hpp +1/−1
- link/modules/asio-standalone/asio/src/examples/cpp03/http/server4/mime_types.hpp +1/−1
- link/modules/asio-standalone/asio/src/examples/cpp03/http/server4/reply.hpp +1/−1
- link/modules/asio-standalone/asio/src/examples/cpp03/http/server4/request.hpp +1/−1
- link/modules/asio-standalone/asio/src/examples/cpp03/http/server4/request_parser.hpp +1/−1
- link/modules/asio-standalone/asio/src/examples/cpp03/http/server4/server.hpp +1/−1
- link/modules/asio-standalone/asio/src/examples/cpp03/icmp/icmp_header.hpp +1/−1
- link/modules/asio-standalone/asio/src/examples/cpp03/icmp/ipv4_header.hpp +1/−1
- link/modules/asio-standalone/asio/src/examples/cpp03/porthopper/protocol.hpp +1/−1
- link/modules/asio-standalone/asio/src/examples/cpp03/serialization/connection.hpp +1/−1
- link/modules/asio-standalone/asio/src/examples/cpp03/serialization/stock.hpp +1/−1
- link/modules/asio-standalone/asio/src/examples/cpp03/services/basic_logger.hpp +1/−1
- link/modules/asio-standalone/asio/src/examples/cpp03/services/logger.hpp +1/−1
- link/modules/asio-standalone/asio/src/examples/cpp03/services/logger_service.hpp +8/−8
- link/modules/asio-standalone/asio/src/examples/cpp03/socks4/socks4.hpp +1/−1
- link/modules/asio-standalone/asio/src/examples/cpp11/chat/chat_message.hpp +3/−3
- link/modules/asio-standalone/asio/src/examples/cpp11/handler_tracking/custom_tracking.hpp +1/−1
- link/modules/asio-standalone/asio/src/examples/cpp11/http/server/connection.hpp +1/−1
- link/modules/asio-standalone/asio/src/examples/cpp11/http/server/connection_manager.hpp +1/−1
- link/modules/asio-standalone/asio/src/examples/cpp11/http/server/header.hpp +1/−1
- link/modules/asio-standalone/asio/src/examples/cpp11/http/server/mime_types.hpp +1/−1
- link/modules/asio-standalone/asio/src/examples/cpp11/http/server/reply.hpp +1/−1
- link/modules/asio-standalone/asio/src/examples/cpp11/http/server/request.hpp +1/−1
- link/modules/asio-standalone/asio/src/examples/cpp11/http/server/request_handler.hpp +1/−1
- link/modules/asio-standalone/asio/src/examples/cpp11/http/server/request_parser.hpp +1/−1
- link/modules/asio-standalone/asio/src/examples/cpp11/http/server/server.hpp +1/−1
- link/modules/asio-standalone/asio/src/examples/cpp11/socks4/socks4.hpp +1/−1
- link/modules/asio-standalone/asio/src/examples/cpp11/type_erasure/line_reader.hpp +48/−0
- link/modules/asio-standalone/asio/src/examples/cpp11/type_erasure/sleep.hpp +35/−0
- link/modules/asio-standalone/asio/src/examples/cpp11/type_erasure/stdin_line_reader.hpp +30/−0
- link/modules/asio-standalone/asio/src/examples/cpp20/type_erasure/line_reader.hpp +39/−0
- link/modules/asio-standalone/asio/src/examples/cpp20/type_erasure/sleep.hpp +32/−0
- link/modules/asio-standalone/asio/src/examples/cpp20/type_erasure/stdin_line_reader.hpp +30/−0
- link/modules/asio-standalone/asio/src/tests/latency/allocator.hpp +1/−1
- link/modules/asio-standalone/asio/src/tests/latency/high_res_clock.hpp +1/−1
- link/modules/asio-standalone/asio/src/tests/performance/handler_allocator.hpp +1/−1
- link/modules/asio-standalone/asio/src/tests/unit/archetypes/async_ops.hpp +1/−1
- link/modules/asio-standalone/asio/src/tests/unit/archetypes/async_result.hpp +69/−7
- link/modules/asio-standalone/asio/src/tests/unit/archetypes/gettable_socket_option.hpp +1/−1
- link/modules/asio-standalone/asio/src/tests/unit/archetypes/io_control_command.hpp +1/−1
- link/modules/asio-standalone/asio/src/tests/unit/archetypes/settable_socket_option.hpp +1/−1
- link/modules/asio-standalone/asio/src/tests/unit/unit_test.hpp +1/−1
- tidal-link.cabal +2/−2
link/include/ableton/Link.ipp view
@@ -225,19 +225,33 @@ forceBeatAtTime(beat, time, quantum); } -template <typename Clock>-inline void BasicLink<Clock>::SessionState::forceBeatAtTime(- const double beat, const std::chrono::microseconds time, const double quantum)+inline void forceBeatAtTimeImpl(link::Timeline& timeline,+ const link::Beats beat,+ const std::chrono::microseconds time,+ const link::Beats quantum) { // There are two components to the beat adjustment: a phase shift // and a beat magnitude adjustment.- const auto curBeatAtTime = link::Beats{beatAtTime(time, quantum)};- const auto closestInPhase =- link::closestPhaseMatch(curBeatAtTime, link::Beats{beat}, link::Beats{quantum});- mState.timeline = shiftClientTimeline(mState.timeline, closestInPhase - curBeatAtTime);+ const auto curBeatAtTime = link::toPhaseEncodedBeats(timeline, time, quantum);+ const auto closestInPhase = link::closestPhaseMatch(curBeatAtTime, beat, quantum);+ timeline = shiftClientTimeline(timeline, closestInPhase - curBeatAtTime); // Now adjust the magnitude- mState.timeline.beatOrigin =- mState.timeline.beatOrigin + (link::Beats{beat} - closestInPhase);+ timeline.beatOrigin = timeline.beatOrigin + beat - closestInPhase;+}++template <typename Clock>+inline void BasicLink<Clock>::SessionState::forceBeatAtTime(+ const double beat, std::chrono::microseconds time, const double quantum)+{+ forceBeatAtTimeImpl(mState.timeline, link::Beats{beat}, time, link::Beats{quantum});++ // Due to quantization errors the resulting BeatTime at 'time' after forcing can be+ // bigger than 'beat' which then violates intended behavior of the API and can lead+ // i.e. to missing a downbeat. Thus we have to shift the timeline forwards.+ if (beatAtTime(time, quantum) > beat)+ {+ forceBeatAtTimeImpl(mState.timeline, link::Beats{beat}, ++time, link::Beats{quantum});+ } } template <typename Clock>
+ link/include/ableton/discovery/AsioTypes.hpp view
@@ -0,0 +1,54 @@+/* Copyright 2023, Ableton AG, Berlin. All rights reserved.+ *+ * This program is free software: you can redistribute it and/or modify+ * it under the terms of the GNU General Public License as published by+ * the Free Software Foundation, either version 2 of the License, or+ * (at your option) any later version.+ *+ * This program is distributed in the hope that it will be useful,+ * but WITHOUT ANY WARRANTY; without even the implied warranty of+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the+ * GNU General Public License for more details.+ *+ * You should have received a copy of the GNU General Public License+ * along with this program. If not, see <http://www.gnu.org/licenses/>.+ *+ * If you would like to incorporate Link into a proprietary software application,+ * please contact <link-devs@ableton.com>.+ */++#pragma once++#include <ableton/platforms/asio/AsioWrapper.hpp>++namespace ableton+{+namespace discovery+{++using IpAddress = LINK_ASIO_NAMESPACE::ip::address;+using IpAddressV4 = LINK_ASIO_NAMESPACE::ip::address_v4;+using IpAddressV6 = LINK_ASIO_NAMESPACE::ip::address_v6;+using UdpSocket = LINK_ASIO_NAMESPACE::ip::udp::socket;+using UdpEndpoint = LINK_ASIO_NAMESPACE::ip::udp::endpoint;++template <typename AsioAddrType>+AsioAddrType makeAddress(const char* pAddr)+{+ using namespace std;+ typename AsioAddrType::bytes_type bytes;+ copy(pAddr, pAddr + bytes.size(), begin(bytes));+ return AsioAddrType{bytes};+}++template <typename AsioAddrType>+AsioAddrType makeAddress(const char* pAddr, uint32_t scopeId)+{+ using namespace std;+ typename AsioAddrType::bytes_type bytes;+ copy(pAddr, pAddr + bytes.size(), begin(bytes));+ return AsioAddrType{bytes, scopeId};+}++} // namespace discovery+} // namespace ableton
link/include/ableton/discovery/InterfaceScanner.hpp view
@@ -19,7 +19,7 @@ #pragma once -#include <ableton/platforms/asio/AsioWrapper.hpp>+#include <ableton/discovery/AsioTypes.hpp> #include <ableton/util/Injected.hpp> #include <chrono> #include <vector>@@ -29,7 +29,7 @@ namespace discovery { -// Callback takes a range of asio::ip:address which is+// Callback takes a range of IpAddress which is // guaranteed to be sorted and unique template <typename Callback, typename IoContext> class InterfaceScanner@@ -64,7 +64,7 @@ using namespace std; debug(mIo->log()) << "Scanning network interfaces"; // Rescan the hardware for available network interface addresses- vector<asio::ip::address> addrs = mIo->scanNetworkInterfaces();+ vector<IpAddress> addrs = mIo->scanNetworkInterfaces(); // Sort and unique them to guarantee consistent comparison sort(begin(addrs), end(addrs)); addrs.erase(unique(begin(addrs), end(addrs)), end(addrs));
+ link/include/ableton/discovery/IpInterface.hpp view
@@ -0,0 +1,130 @@+/* Copyright 2016, Ableton AG, Berlin. All rights reserved.+ *+ * This program is free software: you can redistribute it and/or modify+ * it under the terms of the GNU General Public License as published by+ * the Free Software Foundation, either version 2 of the License, or+ * (at your option) any later version.+ *+ * This program is distributed in the hope that it will be useful,+ * but WITHOUT ANY WARRANTY; without even the implied warranty of+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the+ * GNU General Public License for more details.+ *+ * You should have received a copy of the GNU General Public License+ * along with this program. If not, see <http://www.gnu.org/licenses/>.+ *+ * If you would like to incorporate Link into a proprietary software application,+ * please contact <link-devs@ableton.com>.+ */++#pragma once++#include <ableton/discovery/AsioTypes.hpp>+#include <ableton/util/Injected.hpp>++namespace ableton+{+namespace discovery+{++inline UdpEndpoint multicastEndpointV4()+{+ return {IpAddressV4::from_string("224.76.78.75"), 20808};+}++inline UdpEndpoint multicastEndpointV6(uint64_t scopeId)+{+ // This is a non-permanently-assigned link-local multicast address (RFC4291)+ return {+ ::LINK_ASIO_NAMESPACE::ip::make_address("ff12::8080%" + std::to_string(scopeId)),+ 20808};+}++// Type tags for dispatching between unicast and multicast packets+struct MulticastTag+{+};+struct UnicastTag+{+};++template <typename IoContext, std::size_t MaxPacketSize>+class IpInterface+{+public:+ using Socket = typename util::Injected<IoContext>::type::template Socket<MaxPacketSize>;++ IpInterface(util::Injected<IoContext> io, const IpAddress& addr)+ : mIo(std::move(io))+ , mMulticastReceiveSocket(mIo->template openMulticastSocket<MaxPacketSize>(addr))+ , mSendSocket(mIo->template openUnicastSocket<MaxPacketSize>(addr))+ {+ }++ IpInterface(const IpInterface&) = delete;+ IpInterface& operator=(const IpInterface&) = delete;++ IpInterface(IpInterface&& rhs)+ : mIo(std::move(rhs.mIo))+ , mMulticastReceiveSocket(std::move(rhs.mMulticastReceiveSocket))+ , mSendSocket(std::move(rhs.mSendSocket))+ {+ }+++ std::size_t send(+ const uint8_t* const pData, const size_t numBytes, const UdpEndpoint& to)+ {+ return mSendSocket.send(pData, numBytes, to);+ }++ template <typename Handler>+ void receive(Handler handler, UnicastTag)+ {+ mSendSocket.receive(SocketReceiver<UnicastTag, Handler>{std::move(handler)});+ }++ template <typename Handler>+ void receive(Handler handler, MulticastTag)+ {+ mMulticastReceiveSocket.receive(+ SocketReceiver<MulticastTag, Handler>(std::move(handler)));+ }++ UdpEndpoint endpoint() const+ {+ return mSendSocket.endpoint();+ }++private:+ template <typename Tag, typename Handler>+ struct SocketReceiver+ {+ SocketReceiver(Handler handler)+ : mHandler(std::move(handler))+ {+ }++ template <typename It>+ void operator()(const UdpEndpoint& from, const It messageBegin, const It messageEnd)+ {+ mHandler(Tag{}, from, messageBegin, messageEnd);+ }++ Handler mHandler;+ };++ util::Injected<IoContext> mIo;+ Socket mMulticastReceiveSocket;+ Socket mSendSocket;+};++template <std::size_t MaxPacketSize, typename IoContext>+IpInterface<IoContext, MaxPacketSize> makeIpInterface(+ util::Injected<IoContext> io, const IpAddress& addr)+{+ return {std::move(io), addr};+}++} // namespace discovery+} // namespace ableton
− link/include/ableton/discovery/IpV4Interface.hpp
@@ -1,123 +0,0 @@-/* Copyright 2016, Ableton AG, Berlin. All rights reserved.- *- * This program is free software: you can redistribute it and/or modify- * it under the terms of the GNU General Public License as published by- * the Free Software Foundation, either version 2 of the License, or- * (at your option) any later version.- *- * This program is distributed in the hope that it will be useful,- * but WITHOUT ANY WARRANTY; without even the implied warranty of- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the- * GNU General Public License for more details.- *- * You should have received a copy of the GNU General Public License- * along with this program. If not, see <http://www.gnu.org/licenses/>.- *- * If you would like to incorporate Link into a proprietary software application,- * please contact <link-devs@ableton.com>.- */--#pragma once--#include <ableton/platforms/asio/AsioWrapper.hpp>-#include <ableton/util/Injected.hpp>--namespace ableton-{-namespace discovery-{--inline asio::ip::udp::endpoint multicastEndpoint()-{- return {asio::ip::address_v4::from_string("224.76.78.75"), 20808};-}--// Type tags for dispatching between unicast and multicast packets-struct MulticastTag-{-};-struct UnicastTag-{-};--template <typename IoContext, std::size_t MaxPacketSize>-class IpV4Interface-{-public:- using Socket = typename util::Injected<IoContext>::type::template Socket<MaxPacketSize>;-- IpV4Interface(util::Injected<IoContext> io, const asio::ip::address_v4& addr)- : mIo(std::move(io))- , mMulticastReceiveSocket(mIo->template openMulticastSocket<MaxPacketSize>(addr))- , mSendSocket(mIo->template openUnicastSocket<MaxPacketSize>(addr))- {- }-- IpV4Interface(const IpV4Interface&) = delete;- IpV4Interface& operator=(const IpV4Interface&) = delete;-- IpV4Interface(IpV4Interface&& rhs)- : mIo(std::move(rhs.mIo))- , mMulticastReceiveSocket(std::move(rhs.mMulticastReceiveSocket))- , mSendSocket(std::move(rhs.mSendSocket))- {- }--- std::size_t send(- const uint8_t* const pData, const size_t numBytes, const asio::ip::udp::endpoint& to)- {- return mSendSocket.send(pData, numBytes, to);- }-- template <typename Handler>- void receive(Handler handler, UnicastTag)- {- mSendSocket.receive(SocketReceiver<UnicastTag, Handler>{std::move(handler)});- }-- template <typename Handler>- void receive(Handler handler, MulticastTag)- {- mMulticastReceiveSocket.receive(- SocketReceiver<MulticastTag, Handler>(std::move(handler)));- }-- asio::ip::udp::endpoint endpoint() const- {- return mSendSocket.endpoint();- }--private:- template <typename Tag, typename Handler>- struct SocketReceiver- {- SocketReceiver(Handler handler)- : mHandler(std::move(handler))- {- }-- template <typename It>- void operator()(- const asio::ip::udp::endpoint& from, const It messageBegin, const It messageEnd)- {- mHandler(Tag{}, from, messageBegin, messageEnd);- }-- Handler mHandler;- };-- util::Injected<IoContext> mIo;- Socket mMulticastReceiveSocket;- Socket mSendSocket;-};--template <std::size_t MaxPacketSize, typename IoContext>-IpV4Interface<IoContext, MaxPacketSize> makeIpV4Interface(- util::Injected<IoContext> io, const asio::ip::address_v4& addr)-{- return {std::move(io), addr};-}--} // namespace discovery-} // namespace ableton
link/include/ableton/discovery/NetworkByteStreamSerializable.hpp view
@@ -19,7 +19,7 @@ #pragma once -#include <ableton/platforms/asio/AsioWrapper.hpp>+#include <ableton/discovery/AsioTypes.hpp> #if defined(LINK_PLATFORM_MACOSX) #include <ableton/platforms/darwin/Darwin.hpp> #elif defined(LINK_PLATFORM_LINUX)
link/include/ableton/discovery/Payload.hpp view
@@ -82,6 +82,11 @@ template <typename It> friend It toNetworkByteStream(const PayloadEntry& entry, It out) {+ // Don't serialize Entry if its value is of size zero+ if (sizeInByteStream(entry.value) == 0)+ {+ return out;+ } return toNetworkByteStream( entry.value, toNetworkByteStream(entry.header, std::move(out))); }
link/include/ableton/discovery/PeerGateway.hpp view
@@ -216,7 +216,7 @@ // IpV4 gateway types template <typename StateQuery, typename IoContext> using IpV4Messenger = UdpMessenger<- IpV4Interface<typename util::Injected<IoContext>::type&, v1::kMaxMessageSize>,+ IpInterface<typename util::Injected<IoContext>::type&, v1::kMaxMessageSize>, StateQuery, IoContext>; @@ -226,11 +226,11 @@ PeerObserver, IoContext>; -// Factory function to bind a PeerGateway to an IpV4Interface with the given address.+// Factory function to bind a PeerGateway to an IpInterface with the given address. template <typename PeerObserver, typename NodeState, typename IoContext> IpV4Gateway<PeerObserver, NodeState, IoContext> makeIpV4Gateway( util::Injected<IoContext> io,- const asio::ip::address_v4& addr,+ const IpAddress& addr, util::Injected<PeerObserver> observer, NodeState state) {@@ -240,7 +240,7 @@ const uint8_t ttl = 5; const uint8_t ttlRatio = 20; - auto iface = makeIpV4Interface<v1::kMaxMessageSize>(injectRef(*io), addr);+ auto iface = makeIpInterface<v1::kMaxMessageSize>(injectRef(*io), addr); auto messenger = makeUdpMessenger( injectVal(std::move(iface)), std::move(state), injectRef(*io), ttl, ttlRatio);
link/include/ableton/discovery/PeerGateways.hpp view
@@ -19,8 +19,8 @@ #pragma once +#include <ableton/discovery/AsioTypes.hpp> #include <ableton/discovery/InterfaceScanner.hpp>-#include <ableton/platforms/asio/AsioWrapper.hpp> #include <map> namespace ableton@@ -28,16 +28,17 @@ namespace discovery { -// GatewayFactory must have an operator()(NodeState, IoRef, asio::ip::address)+// GatewayFactory must have an operator()(NodeState, IoRef, IpAddress) // that constructs a new PeerGateway on a given interface address. template <typename NodeState, typename GatewayFactory, typename IoContext> class PeerGateways { public: using IoType = typename util::Injected<IoContext>::type;- using Gateway = typename std::result_of<GatewayFactory(- NodeState, util::Injected<IoType&>, asio::ip::address)>::type;- using GatewayMap = std::map<asio::ip::address, Gateway>;+ using Gateway = decltype(std::declval<GatewayFactory>()(std::declval<NodeState>(),+ std::declval<util::Injected<IoType&>>(),+ std::declval<IpAddress>()));+ using GatewayMap = std::map<IpAddress, Gateway>; PeerGateways(const std::chrono::seconds rescanPeriod, NodeState state,@@ -86,7 +87,7 @@ // If a gateway has become non-responsive or is throwing exceptions, // this method can be invoked to either fix it or discard it.- void repairGateway(const asio::ip::address& gatewayAddr)+ void repairGateway(const IpAddress& gatewayAddr) { if (mpScannerCallback->mGateways.erase(gatewayAddr)) {@@ -111,18 +112,18 @@ { using namespace std; // Get the set of current addresses.- vector<asio::ip::address> curAddrs;+ vector<IpAddress> curAddrs; curAddrs.reserve(mGateways.size()); transform(std::begin(mGateways), std::end(mGateways), back_inserter(curAddrs), [](const typename GatewayMap::value_type& vt) { return vt.first; }); // Now use set_difference to determine the set of addresses that // are new and the set of cur addresses that are no longer there- vector<asio::ip::address> newAddrs;+ vector<IpAddress> newAddrs; set_difference(std::begin(range), std::end(range), std::begin(curAddrs), std::end(curAddrs), back_inserter(newAddrs)); - vector<asio::ip::address> staleAddrs;+ vector<IpAddress> staleAddrs; set_difference(std::begin(curAddrs), std::end(curAddrs), std::begin(range), std::end(range), back_inserter(staleAddrs)); @@ -137,12 +138,8 @@ { try {- // Only handle v4 for now- if (addr.is_v4())- {- info(mIo.log()) << "initializing peer gateway on interface " << addr;- mGateways.emplace(addr, mFactory(mState, util::injectRef(mIo), addr.to_v4()));- }+ info(mIo.log()) << "initializing peer gateway on interface " << addr;+ mGateways.emplace(addr, mFactory(mState, util::injectRef(mIo), addr)); } catch (const runtime_error& e) {
link/include/ableton/discovery/Service.hpp view
@@ -59,7 +59,7 @@ // Repair the gateway with the given address if possible. Its // sockets may have been closed, for example, and the gateway needs // to be regenerated.- void repairGateway(const asio::ip::address& gatewayAddr)+ void repairGateway(const IpAddress& gatewayAddr) { mGateways.repairGateway(gatewayAddr); }
link/include/ableton/discovery/UdpMessenger.hpp view
@@ -19,10 +19,10 @@ #pragma once -#include <ableton/discovery/IpV4Interface.hpp>+#include <ableton/discovery/AsioTypes.hpp>+#include <ableton/discovery/IpInterface.hpp> #include <ableton/discovery/MessageTypes.hpp> #include <ableton/discovery/v1/Messages.hpp>-#include <ableton/platforms/asio/AsioWrapper.hpp> #include <ableton/util/Injected.hpp> #include <ableton/util/SafeAsyncHandler.hpp> #include <algorithm>@@ -37,15 +37,23 @@ // interface through which the sending failed. struct UdpSendException : std::runtime_error {- UdpSendException(const std::runtime_error& e, asio::ip::address ifAddr)+ UdpSendException(const std::runtime_error& e, IpAddress ifAddr) : std::runtime_error(e.what()) , interfaceAddr(std::move(ifAddr)) { } - asio::ip::address interfaceAddr;+ IpAddress interfaceAddr; }; +template <typename Interface>+UdpEndpoint ipV6Endpoint(Interface& iface, const UdpEndpoint& endpoint)+{+ auto v6Address = endpoint.address().to_v6();+ v6Address.scope_id(iface.endpoint().address().to_v6().scope_id());+ return {v6Address, endpoint.port()};+}+ // Throws UdpSendException template <typename Interface, typename NodeId, typename Payload> void sendUdpMessage(Interface& iface,@@ -53,7 +61,7 @@ const uint8_t ttl, const v1::MessageType messageType, const Payload& payload,- const asio::ip::udp::endpoint& to)+ const UdpEndpoint& to) { using namespace std; v1::MessageBuffer buffer;@@ -176,8 +184,16 @@ void sendByeBye() {- sendUdpMessage(- *mInterface, mState.ident(), 0, v1::kByeBye, makePayload(), multicastEndpoint());+ if (mInterface->endpoint().address().is_v4())+ {+ sendUdpMessage(*mInterface, mState.ident(), 0, v1::kByeBye, makePayload(),+ multicastEndpointV4());+ }+ if (mInterface->endpoint().address().is_v6())+ {+ sendUdpMessage(*mInterface, mState.ident(), 0, v1::kByeBye, makePayload(),+ multicastEndpointV6(mInterface->endpoint().address().to_v6().scope_id()));+ } } void updateState(NodeState state)@@ -213,21 +229,29 @@ if (delay < milliseconds{1}) { debug(mIo->log()) << "Broadcasting state";- sendPeerState(v1::kAlive, multicastEndpoint());+ if (mInterface->endpoint().address().is_v4())+ {+ sendPeerState(v1::kAlive, multicastEndpointV4());+ }+ if (mInterface->endpoint().address().is_v6())+ {+ sendPeerState(v1::kAlive,+ multicastEndpointV6(mInterface->endpoint().address().to_v6().scope_id()));+ } } } - void sendPeerState(- const v1::MessageType messageType, const asio::ip::udp::endpoint& to)+ void sendPeerState(const v1::MessageType messageType, const UdpEndpoint& to) { sendUdpMessage( *mInterface, mState.ident(), mTtl, messageType, toPayload(mState), to); mLastBroadcastTime = mTimer.now(); } - void sendResponse(const asio::ip::udp::endpoint& to)+ void sendResponse(const UdpEndpoint& to) {- sendPeerState(v1::kResponse, to);+ const auto endpoint = to.address().is_v4() ? to : ipV6Endpoint(*mInterface, to);+ sendPeerState(v1::kResponse, endpoint); } template <typename Tag>@@ -237,10 +261,8 @@ } template <typename Tag, typename It>- void operator()(Tag tag,- const asio::ip::udp::endpoint& from,- const It messageBegin,- const It messageEnd)+ void operator()(+ Tag tag, const UdpEndpoint& from, const It messageBegin, const It messageEnd) { auto result = v1::parseMessageHeader<NodeId>(messageBegin, messageEnd);
link/include/ableton/discovery/test/Interface.hpp view
@@ -31,9 +31,8 @@ class Interface { public:- void send(const uint8_t* const bytes,- const size_t numBytes,- const asio::ip::udp::endpoint& endpoint)+ void send(+ const uint8_t* const bytes, const size_t numBytes, const UdpEndpoint& endpoint) { sentMessages.push_back( std::make_pair(std::vector<uint8_t>{bytes, bytes + numBytes}, endpoint));@@ -42,31 +41,30 @@ template <typename Callback, typename Tag> void receive(Callback callback, Tag tag) {- mCallback = [callback, tag](const asio::ip::udp::endpoint& from,- const std::vector<uint8_t>& buffer) {+ mCallback = [callback, tag](+ const UdpEndpoint& from, const std::vector<uint8_t>& buffer) { callback(tag, from, begin(buffer), end(buffer)); }; } template <typename It>- void incomingMessage(- const asio::ip::udp::endpoint& from, It messageBegin, It messageEnd)+ void incomingMessage(const UdpEndpoint& from, It messageBegin, It messageEnd) { std::vector<uint8_t> buffer{messageBegin, messageEnd}; mCallback(from, buffer); } - asio::ip::udp::endpoint endpoint() const+ UdpEndpoint endpoint() const {- return asio::ip::udp::endpoint({}, 0);+ return UdpEndpoint({}, 0); } - using SentMessage = std::pair<std::vector<uint8_t>, asio::ip::udp::endpoint>;+ using SentMessage = std::pair<std::vector<uint8_t>, UdpEndpoint>; std::vector<SentMessage> sentMessages; private: using ReceiveCallback =- std::function<void(const asio::ip::udp::endpoint&, const std::vector<uint8_t>&)>;+ std::function<void(const UdpEndpoint&, const std::vector<uint8_t>&)>; ReceiveCallback mCallback; };
link/include/ableton/discovery/test/Socket.hpp view
@@ -19,7 +19,7 @@ #pragma once -#include <ableton/platforms/asio/AsioWrapper.hpp>+#include <ableton/discovery/AsioTypes.hpp> #include <ableton/util/Log.hpp> #include <ableton/util/test/IoService.hpp> @@ -37,12 +37,12 @@ { } - friend void configureUnicastSocket(Socket&, const asio::ip::address_v4&)+ friend void configureUnicastSocket(Socket&, const IpAddressV4&) { } std::size_t send(- const uint8_t* const pData, const size_t numBytes, const asio::ip::udp::endpoint& to)+ const uint8_t* const pData, const size_t numBytes, const discovery::UdpEndpoint& to) { sentMessages.push_back( std::make_pair(std::vector<uint8_t>{pData, pData + numBytes}, to));@@ -52,31 +52,29 @@ template <typename Handler> void receive(Handler handler) {- mCallback = [handler](const asio::ip::udp::endpoint& from,- const std::vector<uint8_t>& buffer) {+ mCallback = [handler](const UdpEndpoint& from, const std::vector<uint8_t>& buffer) { handler(from, begin(buffer), end(buffer)); }; } template <typename It>- void incomingMessage(- const asio::ip::udp::endpoint& from, It messageBegin, It messageEnd)+ void incomingMessage(const UdpEndpoint& from, It messageBegin, It messageEnd) { std::vector<uint8_t> buffer{messageBegin, messageEnd}; mCallback(from, buffer); } - asio::ip::udp::endpoint endpoint() const+ UdpEndpoint endpoint() const {- return asio::ip::udp::endpoint({}, 0);+ return UdpEndpoint({}, 0); } - using SentMessage = std::pair<std::vector<uint8_t>, asio::ip::udp::endpoint>;+ using SentMessage = std::pair<std::vector<uint8_t>, UdpEndpoint>; std::vector<SentMessage> sentMessages; private: using ReceiveCallback =- std::function<void(const asio::ip::udp::endpoint&, const std::vector<uint8_t>&)>;+ std::function<void(const UdpEndpoint&, const std::vector<uint8_t>&)>; ReceiveCallback mCallback; };
link/include/ableton/link/Controller.hpp view
@@ -717,18 +717,11 @@ { GatewayPtr operator()(std::pair<NodeState, GhostXForm> state, util::Injected<IoType&> io,- const asio::ip::address& addr)+ const discovery::IpAddress& addr) {- if (addr.is_v4())- {- return GatewayPtr{new ControllerGateway{std::move(io), addr.to_v4(),- util::injectVal(makeGatewayObserver(mController.mPeers, addr)),- std::move(state.first), std::move(state.second), mController.mClock}};- }- else- {- throw std::runtime_error("Could not create peer gateway on non-ipV4 address");- }+ return GatewayPtr{new ControllerGateway{std::move(io), addr,+ util::injectVal(makeGatewayObserver(mController.mPeers, addr)),+ std::move(state.first), std::move(state.second), mController.mClock}}; } Controller& mController;
link/include/ableton/link/Gateway.hpp view
@@ -33,7 +33,7 @@ { public: Gateway(util::Injected<IoContext> io,- asio::ip::address_v4 addr,+ discovery::IpAddress addr, util::Injected<PeerObserver> observer, NodeState nodeState, GhostXForm ghostXForm,
link/include/ableton/link/Measurement.hpp view
@@ -45,7 +45,7 @@ Measurement(const PeerState& state, Callback callback,- asio::ip::address_v4 address,+ discovery::IpAddress address, Clock clock, util::Injected<IoContext> io) : mIo(std::move(io))@@ -69,12 +69,11 @@ Impl(const PeerState& state, Callback callback,- asio::ip::address_v4 address,+ discovery::IpAddress address, Clock clock, util::Injected<IoContext> io) : mSocket(io->template openUnicastSocket<v1::kMaxMessageSize>(address)) , mSessionId(state.nodeState.sessionId)- , mEndpoint(state.endpoint) , mCallback(std::move(callback)) , mClock(std::move(clock)) , mTimer(io->makeTimer())@@ -82,6 +81,17 @@ , mLog(channel(io->log(), "Measurement on gateway@" + address.to_string())) , mSuccess(false) {+ if (state.endpoint.address().is_v4())+ {+ mEndpoint = state.endpoint;+ }+ else+ {+ auto v6Address = state.endpoint.address().to_v6();+ v6Address.scope_id(address.to_v6().scope_id());+ mEndpoint = {v6Address, state.endpoint.port()};+ }+ const auto ht = HostTime{mClock.micros()}; sendPing(mEndpoint, discovery::makePayload(ht)); resetTimer();@@ -117,7 +127,7 @@ // Operator to handle incoming messages on the interface template <typename It> void operator()(- const asio::ip::udp::endpoint& from, const It messageBegin, const It messageEnd)+ const discovery::UdpEndpoint& from, const It messageBegin, const It messageEnd) { using namespace std; const auto result = v1::parseMessageHeader(messageBegin, messageEnd);@@ -197,7 +207,7 @@ } template <typename Payload>- void sendPing(asio::ip::udp::endpoint to, const Payload& payload)+ void sendPing(discovery::UdpEndpoint to, const Payload& payload) { v1::MessageBuffer buffer; const auto msgBegin = std::begin(buffer);@@ -232,7 +242,7 @@ Socket mSocket; SessionId mSessionId;- asio::ip::udp::endpoint mEndpoint;+ discovery::UdpEndpoint mEndpoint; std::vector<double> mData; Callback mCallback; Clock mClock;
link/include/ableton/link/MeasurementEndpointV4.hpp view
@@ -19,8 +19,9 @@ #pragma once +#include <ableton/discovery/AsioTypes.hpp> #include <ableton/discovery/NetworkByteStreamSerializable.hpp>-#include <ableton/platforms/asio/AsioWrapper.hpp>+#include <cassert> namespace ableton {@@ -35,6 +36,10 @@ // Model the NetworkByteStreamSerializable concept friend std::uint32_t sizeInByteStream(const MeasurementEndpointV4 mep) {+ if (mep.ep.address().is_v6())+ {+ return 0;+ } return discovery::sizeInByteStream( static_cast<std::uint32_t>(mep.ep.address().to_v4().to_ulong())) + discovery::sizeInByteStream(mep.ep.port());@@ -43,6 +48,7 @@ template <typename It> friend It toNetworkByteStream(const MeasurementEndpointV4 mep, It out) {+ assert(mep.ep.address().is_v4()); return discovery::toNetworkByteStream(mep.ep.port(), discovery::toNetworkByteStream( static_cast<std::uint32_t>(mep.ep.address().to_v4().to_ulong()), std::move(out)));@@ -58,11 +64,11 @@ std::move(addrRes.second), end); return make_pair( MeasurementEndpointV4{- {asio::ip::address_v4{std::move(addrRes.first)}, std::move(portRes.first)}},+ {discovery::IpAddressV4{std::move(addrRes.first)}, std::move(portRes.first)}}, std::move(portRes.second)); } - asio::ip::udp::endpoint ep;+ discovery::UdpEndpoint ep; }; } // namespace link
+ link/include/ableton/link/MeasurementEndpointV6.hpp view
@@ -0,0 +1,75 @@+/* Copyright 2023, Ableton AG, Berlin. All rights reserved.+ *+ * This program is free software: you can redistribute it and/or modify+ * it under the terms of the GNU General Public License as published by+ * the Free Software Foundation, either version 2 of the License, or+ * (at your option) any later version.+ *+ * This program is distributed in the hope that it will be useful,+ * but WITHOUT ANY WARRANTY; without even the implied warranty of+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the+ * GNU General Public License for more details.+ *+ * You should have received a copy of the GNU General Public License+ * along with this program. If not, see <http://www.gnu.org/licenses/>.+ *+ * If you would like to incorporate Link into a proprietary software application,+ * please contact <link-devs@ableton.com>.+ */++#pragma once++#include <ableton/discovery/NetworkByteStreamSerializable.hpp>+#include <ableton/platforms/asio/AsioWrapper.hpp>+#include <cassert>++namespace ableton+{+namespace link+{++struct MeasurementEndpointV6+{+ static const std::int32_t key = 'mep6';+ static_assert(key == 0x6d657036, "Unexpected byte order");++ // Model the NetworkByteStreamSerializable concept+ friend std::uint32_t sizeInByteStream(const MeasurementEndpointV6 mep)+ {+ if (mep.ep.address().is_v4())+ {+ return 0;+ }+ return discovery::sizeInByteStream(mep.ep.address().to_v6().to_bytes())+ + discovery::sizeInByteStream(mep.ep.port());+ }++ template <typename It>+ friend It toNetworkByteStream(const MeasurementEndpointV6 mep, It out)+ {+ assert(mep.ep.address().is_v6());+ return discovery::toNetworkByteStream(+ mep.ep.port(), discovery::toNetworkByteStream(+ mep.ep.address().to_v6().to_bytes(), std::move(out)));+ }++ template <typename It>+ static std::pair<MeasurementEndpointV6, It> fromNetworkByteStream(It begin, It end)+ {+ using namespace std;+ auto addrRes =+ discovery::Deserialize<discovery::IpAddressV6::bytes_type>::fromNetworkByteStream(+ std::move(begin), end);+ auto portRes = discovery::Deserialize<std::uint16_t>::fromNetworkByteStream(+ std::move(addrRes.second), end);+ return make_pair(+ MeasurementEndpointV6{+ {discovery::IpAddressV6{std::move(addrRes.first)}, std::move(portRes.first)}},+ std::move(portRes.second));+ }++ discovery::UdpEndpoint ep;+};++} // namespace link+} // namespace ableton
link/include/ableton/link/MeasurementService.hpp view
@@ -42,7 +42,7 @@ using IoType = util::Injected<IoContext>; using MeasurementInstance = Measurement<Clock, IoContext>; - MeasurementService(asio::ip::address_v4 address,+ MeasurementService(discovery::IpAddress address, SessionId sessionId, GhostXForm ghostXForm, Clock clock,@@ -65,7 +65,7 @@ mPingResponder.updateNodeState(sessionId, xform); } - asio::ip::udp::endpoint endpoint() const+ discovery::UdpEndpoint endpoint() const { return mPingResponder.endpoint(); }@@ -77,7 +77,7 @@ using namespace std; const auto nodeId = state.nodeState.nodeId;- auto addr = mPingResponder.endpoint().address().to_v4();+ auto addr = mPingResponder.endpoint().address(); auto callback = CompletionCallback<Handler>{*this, nodeId, handler}; try
link/include/ableton/link/PeerState.hpp view
@@ -21,6 +21,7 @@ #include <ableton/discovery/Payload.hpp> #include <ableton/link/MeasurementEndpointV4.hpp>+#include <ableton/link/MeasurementEndpointV6.hpp> #include <ableton/link/NodeState.hpp> namespace ableton@@ -61,12 +62,16 @@ return lhs.nodeState == rhs.nodeState && lhs.endpoint == rhs.endpoint; } - friend auto toPayload(const PeerState& state)- -> decltype(std::declval<NodeState::Payload>()- + discovery::makePayload(MeasurementEndpointV4{{}}))+ friend auto toPayload(const PeerState& state) -> decltype(+ std::declval<NodeState::Payload>() + discovery::makePayload(MeasurementEndpointV4{{}})+ + discovery::makePayload(MeasurementEndpointV6{{}})) {+ // This implements a switch if either an IPv4 or IPv6 endpoint is serialized.+ // MeasurementEndpoints that contain an endpoint that does not match the IP protocol+ // version return a sizeInByteStream() of zero and won't be serialized. return toPayload(state.nodeState)- + discovery::makePayload(MeasurementEndpointV4{state.endpoint});+ + discovery::makePayload(MeasurementEndpointV4{state.endpoint})+ + discovery::makePayload(MeasurementEndpointV6{state.endpoint}); } template <typename It>@@ -75,15 +80,16 @@ using namespace std; auto peerState = PeerState{NodeState::fromPayload(std::move(id), begin, end), {}}; - discovery::parsePayload<MeasurementEndpointV4>(- std::move(begin), std::move(end), [&peerState](MeasurementEndpointV4 me4) {- peerState.endpoint = std::move(me4.ep);- });+ discovery::parsePayload<MeasurementEndpointV4, MeasurementEndpointV6>(+ std::move(begin), std::move(end),+ [&peerState](MeasurementEndpointV4 me4) { peerState.endpoint = std::move(me4.ep); },+ [&peerState](+ MeasurementEndpointV6 me6) { peerState.endpoint = std::move(me6.ep); }); return peerState; } NodeState nodeState;- asio::ip::udp::endpoint endpoint;+ discovery::UdpEndpoint endpoint; }; } // namespace link
link/include/ableton/link/Peers.hpp view
@@ -47,7 +47,7 @@ struct Impl; public:- using Peer = std::pair<PeerState, asio::ip::address>;+ using Peer = std::pair<PeerState, discovery::IpAddress>; Peers(util::Injected<IoContext> io, SessionMembershipCallback membership,@@ -119,7 +119,7 @@ using GatewayObserverNodeState = PeerState; using GatewayObserverNodeId = NodeId; - GatewayObserver(std::shared_ptr<Impl> pImpl, asio::ip::address addr)+ GatewayObserver(std::shared_ptr<Impl> pImpl, discovery::IpAddress addr) : mpImpl(std::move(pImpl)) , mAddr(std::move(addr)) {@@ -165,11 +165,11 @@ } std::shared_ptr<Impl> mpImpl;- asio::ip::address mAddr;+ discovery::IpAddress mAddr; }; // Factory function for the gateway observer- friend GatewayObserver makeGatewayObserver(Peers& peers, asio::ip::address addr)+ friend GatewayObserver makeGatewayObserver(Peers& peers, discovery::IpAddress addr) { return GatewayObserver{peers.mpImpl, std::move(addr)}; }@@ -188,7 +188,7 @@ { } - void sawPeerOnGateway(PeerState peerState, asio::ip::address gatewayAddr)+ void sawPeerOnGateway(PeerState peerState, discovery::IpAddress gatewayAddr) { using namespace std; @@ -255,7 +255,7 @@ } } - void peerLeftGateway(const NodeId& nodeId, const asio::ip::address& gatewayAddr)+ void peerLeftGateway(const NodeId& nodeId, const discovery::IpAddress& gatewayAddr) { using namespace std; @@ -276,7 +276,7 @@ } } - void gatewayClosed(const asio::ip::address& gatewayAddr)+ void gatewayClosed(const discovery::IpAddress& gatewayAddr) { using namespace std;
link/include/ableton/link/PingResponder.hpp view
@@ -40,7 +40,7 @@ using Socket = typename IoType::type::template Socket<v1::kMaxMessageSize>; public:- PingResponder(asio::ip::address_v4 address,+ PingResponder(discovery::IpAddress address, SessionId sessionId, GhostXForm ghostXForm, Clock clock,@@ -64,12 +64,12 @@ mpImpl->mGhostXForm = std::move(xform); } - asio::ip::udp::endpoint endpoint() const+ discovery::UdpEndpoint endpoint() const { return mpImpl->mSocket.endpoint(); } - asio::ip::address address() const+ discovery::IpAddress address() const { return endpoint().address(); }@@ -82,7 +82,7 @@ private: struct Impl : std::enable_shared_from_this<Impl> {- Impl(asio::ip::address_v4 address,+ Impl(discovery::IpAddress address, SessionId sessionId, GhostXForm ghostXForm, Clock clock,@@ -102,7 +102,7 @@ // Operator to handle incoming messages on the interface template <typename It>- void operator()(const asio::ip::udp::endpoint& from, const It begin, const It end)+ void operator()(const discovery::UdpEndpoint& from, const It begin, const It end) { using namespace discovery; @@ -136,7 +136,7 @@ } template <typename It>- void reply(It begin, It end, const asio::ip::udp::endpoint& to)+ void reply(It begin, It end, const discovery::UdpEndpoint& to) { using namespace discovery;
link/include/ableton/link/SessionState.hpp view
@@ -23,6 +23,7 @@ #include <ableton/link/StartStopState.hpp> #include <ableton/link/Timeline.hpp> #include <ableton/link/TripleBuffer.hpp>+#include <mutex> namespace ableton {
link/include/ableton/platforms/Config.hpp view
@@ -62,31 +62,33 @@ using Clock = platforms::windows::Clock; using Random = platforms::stl::Random; #if defined(LINK_WINDOWS_SETTHREADDESCRIPTION)-using IoContext = platforms::asio::Context<platforms::windows::ScanIpIfAddrs,- util::NullLog,- platforms::windows::ThreadFactory>;+using IoContext =+ platforms::LINK_ASIO_NAMESPACE::Context<platforms::windows::ScanIpIfAddrs,+ util::NullLog,+ platforms::windows::ThreadFactory>; #else using IoContext =- platforms::asio::Context<platforms::windows::ScanIpIfAddrs, util::NullLog>;+ platforms::LINK_ASIO_NAMESPACE::Context<platforms::windows::ScanIpIfAddrs,+ util::NullLog>; #endif #elif defined(LINK_PLATFORM_MACOSX) using Clock = platforms::darwin::Clock;-using IoContext = platforms::asio::Context<platforms::posix::ScanIpIfAddrs,+using IoContext = platforms::LINK_ASIO_NAMESPACE::Context<platforms::posix::ScanIpIfAddrs, util::NullLog, platforms::darwin::ThreadFactory>; using Random = platforms::stl::Random; #elif defined(LINK_PLATFORM_LINUX)-using Clock = platforms::linux::ClockMonotonicRaw;+using Clock = platforms::linux_::ClockMonotonicRaw; using Random = platforms::stl::Random; #ifdef __linux__-using IoContext = platforms::asio::Context<platforms::posix::ScanIpIfAddrs,+using IoContext = platforms::LINK_ASIO_NAMESPACE::Context<platforms::posix::ScanIpIfAddrs, util::NullLog,- platforms::linux::ThreadFactory>;+ platforms::linux_::ThreadFactory>; #else using IoContext =- platforms::asio::Context<platforms::posix::ScanIpIfAddrs, util::NullLog>;+ platforms::LINK_ASIO_NAMESPACE::Context<platforms::posix::ScanIpIfAddrs, util::NullLog>; #endif #elif defined(ESP_PLATFORM)
link/include/ableton/platforms/asio/AsioTimer.hpp view
@@ -27,7 +27,7 @@ { namespace platforms {-namespace asio+namespace LINK_ASIO_NAMESPACE { // This implementation is based on the boost::asio::system_timer concept.@@ -41,11 +41,14 @@ class AsioTimer { public:- using ErrorCode = ::asio::error_code;+ using ErrorCode = ::LINK_ASIO_NAMESPACE::error_code; using TimePoint = std::chrono::system_clock::time_point;+ using IoService = ::LINK_ASIO_NAMESPACE::io_service;+ using SystemTimer = ::LINK_ASIO_NAMESPACE::system_timer; - AsioTimer(::asio::io_service& io)- : mpTimer(new ::asio::system_timer(io))++ AsioTimer(IoService& io)+ : mpTimer(new SystemTimer(io)) , mpAsyncHandler(std::make_shared<AsyncHandler>()) { }@@ -123,10 +126,10 @@ std::function<void(const ErrorCode)> mpHandler; }; - std::unique_ptr<::asio::system_timer> mpTimer;+ std::unique_ptr<SystemTimer> mpTimer; std::shared_ptr<AsyncHandler> mpAsyncHandler; }; -} // namespace asio+} // namespace LINK_ASIO_NAMESPACE } // namespace platforms } // namespace ableton
link/include/ableton/platforms/asio/AsioWrapper.hpp view
@@ -26,12 +26,19 @@ * by Link. */ -#if !defined(ESP_PLATFORM)+#if defined(ESP_PLATFORM)++#define LINK_ASIO_NAMESPACE asio++#else+ #pragma push_macro("ASIO_STANDALONE")-#define ASIO_STANDALONE 1 #pragma push_macro("ASIO_NO_TYPEID") #define ASIO_NO_TYPEID 1+#define asio link_asio_1_28_0+#define LINK_ASIO_NAMESPACE link_asio_1_28_0+#define ASIO_STANDALONE 1 #endif #if defined(LINK_PLATFORM_WINDOWS)@@ -75,11 +82,6 @@ #pragma pop_macro("INCL_EXTRA_HTON_FUNCTIONS") #endif -#if !defined(ESP_PLATFORM)-#pragma pop_macro("ASIO_STANDALONE")-#pragma pop_macro("ASIO_NO_TYPEID")-#endif- #if defined(_MSC_VER) #pragma warning(pop) #undef _SCL_SECURE_NO_WARNINGS@@ -88,3 +90,5 @@ #if defined(__clang__) #pragma clang diagnostic pop #endif++#undef asio
link/include/ableton/platforms/asio/Context.hpp view
@@ -19,9 +19,8 @@ #pragma once -#include <ableton/discovery/IpV4Interface.hpp>+#include <ableton/discovery/IpInterface.hpp> #include <ableton/platforms/asio/AsioTimer.hpp>-#include <ableton/platforms/asio/AsioWrapper.hpp> #include <ableton/platforms/asio/LockFreeCallbackDispatcher.hpp> #include <ableton/platforms/asio/Socket.hpp> #include <thread>@@ -31,7 +30,7 @@ { namespace platforms {-namespace asio+namespace LINK_ASIO_NAMESPACE { namespace {@@ -51,7 +50,7 @@ class Context { public:- using Timer = AsioTimer;+ using Timer = LINK_ASIO_NAMESPACE::AsioTimer; using Log = LogT; template <typename Handler, typename Duration>@@ -59,7 +58,9 @@ LockFreeCallbackDispatcher<Handler, Duration, ThreadFactoryT>; template <std::size_t BufferSize>- using Socket = asio::Socket<BufferSize>;+ using Socket = Socket<BufferSize>;+ using IoService = ::LINK_ASIO_NAMESPACE::io_service;+ using Work = IoService::work; Context() : Context(DefaultHandler{})@@ -68,11 +69,11 @@ template <typename ExceptionHandler> explicit Context(ExceptionHandler exceptHandler)- : mpService(new ::asio::io_service())- , mpWork(new ::asio::io_service::work(*mpService))+ : mpService(new IoService())+ , mpWork(new Work(*mpService)) { mThread = ThreadFactoryT::makeThread("Link Main",- [](::asio::io_service& service, ExceptionHandler handler) {+ [](IoService& service, ExceptionHandler handler) { for (;;) { try@@ -121,34 +122,79 @@ template <std::size_t BufferSize>- Socket<BufferSize> openUnicastSocket(const ::asio::ip::address_v4& addr)+ Socket<BufferSize> openUnicastSocket(const discovery::IpAddress addr) {- auto socket = Socket<BufferSize>{*mpService};+ auto socket =+ addr.is_v4() ? Socket<BufferSize>{*mpService, ::LINK_ASIO_NAMESPACE::ip::udp::v4()}+ : Socket<BufferSize>{*mpService, ::LINK_ASIO_NAMESPACE::ip::udp::v6()}; socket.mpImpl->mSocket.set_option(- ::asio::ip::multicast::enable_loopback(addr.is_loopback()));- socket.mpImpl->mSocket.set_option(::asio::ip::multicast::outbound_interface(addr));- socket.mpImpl->mSocket.bind(::asio::ip::udp::endpoint{addr, 0});+ ::LINK_ASIO_NAMESPACE::ip::multicast::enable_loopback(addr.is_loopback()));+ if (addr.is_v4())+ {+ socket.mpImpl->mSocket.set_option(+ ::LINK_ASIO_NAMESPACE::ip::multicast::outbound_interface(addr.to_v4()));+ socket.mpImpl->mSocket.bind(+ ::LINK_ASIO_NAMESPACE::ip::udp::endpoint{addr.to_v4(), 0});+ }+ else if (addr.is_v6())+ {+ const auto scopeId = addr.to_v6().scope_id();+ socket.mpImpl->mSocket.set_option(+ ::LINK_ASIO_NAMESPACE::ip::multicast::outbound_interface(+ static_cast<unsigned int>(scopeId)));+ socket.mpImpl->mSocket.bind(+ ::LINK_ASIO_NAMESPACE::ip::udp::endpoint{addr.to_v6(), 0});+ }+ else+ {+ throw(std::runtime_error("Unknown Protocol"));+ } return socket; } template <std::size_t BufferSize>- Socket<BufferSize> openMulticastSocket(const ::asio::ip::address_v4& addr)+ Socket<BufferSize> openMulticastSocket(const discovery::IpAddress& addr) {- auto socket = Socket<BufferSize>{*mpService};- socket.mpImpl->mSocket.set_option(::asio::ip::udp::socket::reuse_address(true));+ auto socket =+ addr.is_v4() ? Socket<BufferSize>{*mpService, ::LINK_ASIO_NAMESPACE::ip::udp::v4()}+ : Socket<BufferSize>{*mpService, ::LINK_ASIO_NAMESPACE::ip::udp::v6()};+ socket.mpImpl->mSocket.set_option(- ::asio::socket_base::broadcast(!addr.is_loopback()));+ ::LINK_ASIO_NAMESPACE::ip::udp::socket::reuse_address(true)); socket.mpImpl->mSocket.set_option(- ::asio::ip::multicast::enable_loopback(addr.is_loopback()));- socket.mpImpl->mSocket.set_option(::asio::ip::multicast::outbound_interface(addr));- socket.mpImpl->mSocket.bind({::asio::ip::address::from_string("0.0.0.0"),- discovery::multicastEndpoint().port()});- socket.mpImpl->mSocket.set_option(::asio::ip::multicast::join_group(- discovery::multicastEndpoint().address().to_v4(), addr));+ ::LINK_ASIO_NAMESPACE::socket_base::broadcast(!addr.is_loopback()));+ socket.mpImpl->mSocket.set_option(+ ::LINK_ASIO_NAMESPACE::ip::multicast::enable_loopback(addr.is_loopback()));++ if (addr.is_v4())+ {+ socket.mpImpl->mSocket.set_option(+ ::LINK_ASIO_NAMESPACE::ip::multicast::outbound_interface(addr.to_v4()));+ socket.mpImpl->mSocket.bind({::LINK_ASIO_NAMESPACE::ip::address_v4::any(),+ discovery::multicastEndpointV4().port()});+ socket.mpImpl->mSocket.set_option(::LINK_ASIO_NAMESPACE::ip::multicast::join_group(+ discovery::multicastEndpointV4().address().to_v4(), addr.to_v4()));+ }+ else if (addr.is_v6())+ {+ const auto scopeId = addr.to_v6().scope_id();+ socket.mpImpl->mSocket.set_option(+ ::LINK_ASIO_NAMESPACE::ip::multicast::outbound_interface(+ static_cast<unsigned int>(scopeId)));+ const auto multicastEndpoint = discovery::multicastEndpointV6(scopeId);+ socket.mpImpl->mSocket.bind(+ {::LINK_ASIO_NAMESPACE::ip::address_v6::any(), multicastEndpoint.port()});+ socket.mpImpl->mSocket.set_option(::LINK_ASIO_NAMESPACE::ip::multicast::join_group(+ multicastEndpoint.address().to_v6(), scopeId));+ }+ else+ {+ throw(std::runtime_error("Unknown Protocol"));+ } return socket; } - std::vector<::asio::ip::address> scanNetworkInterfaces()+ std::vector<discovery::IpAddress> scanNetworkInterfaces() { return mScanIpIfAddrs(); }@@ -184,13 +230,13 @@ } }; - std::unique_ptr<::asio::io_service> mpService;- std::unique_ptr<::asio::io_service::work> mpWork;+ std::unique_ptr<::LINK_ASIO_NAMESPACE::io_service> mpService;+ std::unique_ptr<::LINK_ASIO_NAMESPACE::io_service::work> mpWork; std::thread mThread; Log mLog; ScanIpIfAddrs mScanIpIfAddrs; }; -} // namespace asio+} // namespace LINK_ASIO_NAMESPACE } // namespace platforms } // namespace ableton
link/include/ableton/platforms/asio/LockFreeCallbackDispatcher.hpp view
@@ -27,7 +27,7 @@ { namespace platforms {-namespace asio+namespace LINK_ASIO_NAMESPACE { // Utility to signal invocation of a callback on another thread in a lock free manner.@@ -83,6 +83,6 @@ std::thread mThread; }; -} // namespace asio+} // namespace LINK_ASIO_NAMESPACE } // namespace platforms } // namespace ableton
link/include/ableton/platforms/asio/Socket.hpp view
@@ -19,7 +19,7 @@ #pragma once -#include <ableton/platforms/asio/AsioWrapper.hpp>+#include <ableton/discovery/AsioTypes.hpp> #include <ableton/util/SafeAsyncHandler.hpp> #include <array> #include <cassert>@@ -28,14 +28,14 @@ { namespace platforms {-namespace asio+namespace LINK_ASIO_NAMESPACE { template <std::size_t MaxPacketSize> struct Socket {- Socket(::asio::io_service& io)- : mpImpl(std::make_shared<Impl>(io))+ Socket(::LINK_ASIO_NAMESPACE::io_service& io, ::LINK_ASIO_NAMESPACE::ip::udp protocol)+ : mpImpl(std::make_shared<Impl>(io, protocol)) { } @@ -47,12 +47,11 @@ { } - std::size_t send(const uint8_t* const pData,- const size_t numBytes,- const ::asio::ip::udp::endpoint& to)+ std::size_t send(+ const uint8_t* const pData, const size_t numBytes, const discovery::UdpEndpoint& to) { assert(numBytes < MaxPacketSize);- return mpImpl->mSocket.send_to(::asio::buffer(pData, numBytes), to);+ return mpImpl->mSocket.send_to(::LINK_ASIO_NAMESPACE::buffer(pData, numBytes), to); } template <typename Handler>@@ -60,19 +59,19 @@ { mpImpl->mHandler = std::move(handler); mpImpl->mSocket.async_receive_from(- ::asio::buffer(mpImpl->mReceiveBuffer, MaxPacketSize), mpImpl->mSenderEndpoint,- util::makeAsyncSafe(mpImpl));+ ::LINK_ASIO_NAMESPACE::buffer(mpImpl->mReceiveBuffer, MaxPacketSize),+ mpImpl->mSenderEndpoint, util::makeAsyncSafe(mpImpl)); } - ::asio::ip::udp::endpoint endpoint() const+ discovery::UdpEndpoint endpoint() const { return mpImpl->mSocket.local_endpoint(); } struct Impl {- Impl(::asio::io_service& io)- : mSocket(io, ::asio::ip::udp::v4())+ Impl(::LINK_ASIO_NAMESPACE::io_service& io, ::LINK_ASIO_NAMESPACE::ip::udp protocol)+ : mSocket(io, protocol) { } @@ -80,12 +79,13 @@ { // Ignore error codes in shutdown and close as the socket may // have already been forcibly closed- ::asio::error_code ec;- mSocket.shutdown(::asio::ip::udp::socket::shutdown_both, ec);+ ::LINK_ASIO_NAMESPACE::error_code ec;+ mSocket.shutdown(::LINK_ASIO_NAMESPACE::ip::udp::socket::shutdown_both, ec); mSocket.close(ec); } - void operator()(const ::asio::error_code& error, const std::size_t numBytes)+ void operator()(+ const ::LINK_ASIO_NAMESPACE::error_code& error, const std::size_t numBytes) { if (!error && numBytes > 0 && numBytes <= MaxPacketSize) {@@ -94,17 +94,17 @@ } } - ::asio::ip::udp::socket mSocket;- ::asio::ip::udp::endpoint mSenderEndpoint;+ discovery::UdpSocket mSocket;+ discovery::UdpEndpoint mSenderEndpoint; using Buffer = std::array<uint8_t, MaxPacketSize>; Buffer mReceiveBuffer; using ByteIt = typename Buffer::const_iterator;- std::function<void(const ::asio::ip::udp::endpoint&, ByteIt, ByteIt)> mHandler;+ std::function<void(const discovery::UdpEndpoint&, ByteIt, ByteIt)> mHandler; }; std::shared_ptr<Impl> mpImpl; }; -} // namespace asio+} // namespace LINK_ASIO_NAMESPACE } // namespace platforms } // namespace ableton
− link/include/ableton/platforms/asio/Util.hpp
@@ -1,43 +0,0 @@-/* Copyright 2016, Ableton AG, Berlin. All rights reserved.- *- * This program is free software: you can redistribute it and/or modify- * it under the terms of the GNU General Public License as published by- * the Free Software Foundation, either version 2 of the License, or- * (at your option) any later version.- *- * This program is distributed in the hope that it will be useful,- * but WITHOUT ANY WARRANTY; without even the implied warranty of- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the- * GNU General Public License for more details.- *- * You should have received a copy of the GNU General Public License- * along with this program. If not, see <http://www.gnu.org/licenses/>.- *- * If you would like to incorporate Link into a proprietary software application,- * please contact <link-devs@ableton.com>.- */--#pragma once--#include <algorithm>--namespace ableton-{-namespace platforms-{-namespace asio-{--// Utility for making v4 or v6 ip addresses from raw bytes in network byte-order-template <typename AsioAddrType>-AsioAddrType makeAddress(const char* pAddr)-{- using namespace std;- typename AsioAddrType::bytes_type bytes;- copy(pAddr, pAddr + bytes.size(), begin(bytes));- return AsioAddrType{bytes};-}--} // namespace asio-} // namespace platforms-} // namespace ableton
link/include/ableton/platforms/darwin/Clock.hpp view
@@ -19,6 +19,7 @@ #pragma once +#include <cassert> #include <chrono> #include <mach/mach_time.h> @@ -49,6 +50,8 @@ Ticks microsToTicks(const Micros micros) const {+ // Negative Micros can not be represented in Ticks+ assert(micros.count() >= 0); return static_cast<Ticks>(micros.count() / mTicksToMicros); }
link/include/ableton/platforms/esp32/Context.hpp view
@@ -19,12 +19,12 @@ #pragma once -#include <ableton/discovery/IpV4Interface.hpp>+#include <ableton/discovery/AsioTypes.hpp>+#include <ableton/discovery/IpInterface.hpp> #include <ableton/platforms/asio/AsioTimer.hpp>-#include <ableton/platforms/asio/AsioWrapper.hpp> #include <ableton/platforms/asio/Socket.hpp> #include <ableton/platforms/esp32/LockFreeCallbackDispatcher.hpp>-#include <driver/timer.h>+#include <driver/gptimer.h> #include <freertos/FreeRTOS.h> #include <freertos/task.h> @@ -40,7 +40,6 @@ { class ServiceRunner {- static void run(void* userParams) { auto runner = static_cast<ServiceRunner*>(userParams);@@ -60,11 +59,7 @@ static void IRAM_ATTR timerIsr(void* userParam) { static BaseType_t xHigherPriorityTaskWoken = pdFALSE;-- timer_group_clr_intr_status_in_isr(TIMER_GROUP_0, TIMER_1);- timer_group_enable_alarm_in_isr(TIMER_GROUP_0, TIMER_1);-- vTaskNotifyGiveFromISR(userParam, &xHigherPriorityTaskWoken);+ vTaskNotifyGiveFromISR(*((TaskHandle_t*)userParam), &xHigherPriorityTaskWoken); if (xHigherPriorityTaskWoken) { portYIELD_FROM_ISR();@@ -79,24 +74,21 @@ xTaskCreatePinnedToCore(run, "link", 8192, this, 2 | portPRIVILEGE_BIT, &mTaskHandle, LINK_ESP_TASK_CORE_ID); - timer_config_t config = {.alarm_en = TIMER_ALARM_EN,- .counter_en = TIMER_PAUSE,- .intr_type = TIMER_INTR_LEVEL,- .counter_dir = TIMER_COUNT_UP,- .auto_reload = TIMER_AUTORELOAD_EN,- .divider = 80};-- timer_init(TIMER_GROUP_0, TIMER_1, &config);- timer_set_counter_value(TIMER_GROUP_0, TIMER_1, 0);- timer_set_alarm_value(TIMER_GROUP_0, TIMER_1, 100);- timer_enable_intr(TIMER_GROUP_0, TIMER_1);- timer_isr_register(TIMER_GROUP_0, TIMER_1, &timerIsr, mTaskHandle, 0, nullptr);+ const esp_timer_create_args_t timerArgs = {+ .callback = &timerIsr,+ .arg = (void*)&mTaskHandle,+ .dispatch_method = ESP_TIMER_TASK,+ .name = "link",+ .skip_unhandled_events = true,+ }; - timer_start(TIMER_GROUP_0, TIMER_1);+ ESP_ERROR_CHECK(esp_timer_create(&timerArgs, &mTimer));+ ESP_ERROR_CHECK(esp_timer_start_periodic(mTimer, 100)); } ~ServiceRunner() {+ esp_timer_delete(mTimer); vTaskDelete(mTaskHandle); } @@ -113,6 +105,7 @@ private: TaskHandle_t mTaskHandle;+ esp_timer_handle_t mTimer; std::unique_ptr<::asio::io_service> mpService; std::unique_ptr<::asio::io_service::work> mpWork; };@@ -150,30 +143,72 @@ } template <std::size_t BufferSize>- Socket<BufferSize> openUnicastSocket(const ::asio::ip::address_v4& addr)+ Socket<BufferSize> openUnicastSocket(const ::asio::ip::address& addr) {- auto socket = Socket<BufferSize>{serviceRunner().service()};+ auto socket =+ addr.is_v4() ? Socket<BufferSize>{serviceRunner().service(), ::asio::ip::udp::v4()}+ : Socket<BufferSize>{serviceRunner().service(), ::asio::ip::udp::v6()}; socket.mpImpl->mSocket.set_option( ::asio::ip::multicast::enable_loopback(addr.is_loopback()));- socket.mpImpl->mSocket.set_option(::asio::ip::multicast::outbound_interface(addr));- socket.mpImpl->mSocket.bind(::asio::ip::udp::endpoint{addr, 0});+ if (addr.is_v4())+ {+ socket.mpImpl->mSocket.set_option(+ ::asio::ip::multicast::outbound_interface(addr.to_v4()));+ socket.mpImpl->mSocket.bind(+ ::LINK_ASIO_NAMESPACE::ip::udp::endpoint{addr.to_v4(), 0});+ }+ else if (addr.is_v6())+ {+ const auto scopeId = addr.to_v6().scope_id();+ socket.mpImpl->mSocket.set_option(+ ::asio::ip::multicast::outbound_interface(static_cast<unsigned int>(scopeId)));+ socket.mpImpl->mSocket.bind(+ ::LINK_ASIO_NAMESPACE::ip::udp::endpoint{addr.to_v6(), 0});+ }+ else+ {+ throw(std::runtime_error("Unknown Protocol"));+ } return socket; } template <std::size_t BufferSize>- Socket<BufferSize> openMulticastSocket(const ::asio::ip::address_v4& addr)+ Socket<BufferSize> openMulticastSocket(const ::asio::ip::address& addr) {- auto socket = Socket<BufferSize>{serviceRunner().service()};+ auto socket =+ addr.is_v4() ? Socket<BufferSize>{serviceRunner().service(), ::asio::ip::udp::v4()}+ : Socket<BufferSize>{serviceRunner().service(), ::asio::ip::udp::v6()};+ socket.mpImpl->mSocket.set_option(::asio::ip::udp::socket::reuse_address(true)); socket.mpImpl->mSocket.set_option( ::asio::socket_base::broadcast(!addr.is_loopback())); socket.mpImpl->mSocket.set_option( ::asio::ip::multicast::enable_loopback(addr.is_loopback()));- socket.mpImpl->mSocket.set_option(::asio::ip::multicast::outbound_interface(addr));- socket.mpImpl->mSocket.bind({::asio::ip::address::from_string("0.0.0.0"),- discovery::multicastEndpoint().port()});- socket.mpImpl->mSocket.set_option(::asio::ip::multicast::join_group(- discovery::multicastEndpoint().address().to_v4(), addr));++ if (addr.is_v4())+ {+ socket.mpImpl->mSocket.set_option(+ ::asio::ip::multicast::outbound_interface(addr.to_v4()));+ socket.mpImpl->mSocket.bind(+ {::asio::ip::address_v4::any(), discovery::multicastEndpointV4().port()});+ socket.mpImpl->mSocket.set_option(::asio::ip::multicast::join_group(+ discovery::multicastEndpointV4().address().to_v4(), addr.to_v4()));+ }+ else if (addr.is_v6())+ {+ const auto scopeId = addr.to_v6().scope_id();+ socket.mpImpl->mSocket.set_option(+ ::asio::ip::multicast::outbound_interface(static_cast<unsigned int>(scopeId)));+ const auto multicastEndpoint = discovery::multicastEndpointV6(scopeId);+ socket.mpImpl->mSocket.bind(+ {::asio::ip::address_v6::any(), multicastEndpoint.port()});+ socket.mpImpl->mSocket.set_option(+ ::asio::ip::multicast::join_group(multicastEndpoint.address().to_v6(), scopeId));+ }+ else+ {+ throw(std::runtime_error("Unknown Protocol"));+ } return socket; }
link/include/ableton/platforms/esp32/ScanIpIfAddrs.hpp view
@@ -17,7 +17,7 @@ #pragma once -#include <ableton/platforms/asio/AsioWrapper.hpp>+#include <ableton/discovery/AsioTypes.hpp> #include <arpa/inet.h> #include <esp_netif.h> #include <net/if.h>@@ -33,9 +33,9 @@ // ESP32 implementation of ip interface address scanner struct ScanIpIfAddrs {- std::vector<::asio::ip::address> operator()()+ std::vector<discovery::IpAddress> operator()() {- std::vector<::asio::ip::address> addrs;+ std::vector<discovery::IpAddress> addrs; // Get first network interface esp_netif_t* esp_netif = esp_netif_next(NULL); while (esp_netif)
link/include/ableton/platforms/linux/Clock.hpp view
@@ -28,15 +28,11 @@ namespace platforms { -#ifdef linux-#undef linux-#endif- #if defined(__FreeBSD_kernel__) #define CLOCK_MONOTONIC_RAW CLOCK_MONOTONIC #endif -namespace linux+namespace linux_ { template <clockid_t CLOCK>@@ -55,6 +51,6 @@ using ClockMonotonic = Clock<CLOCK_MONOTONIC>; using ClockMonotonicRaw = Clock<CLOCK_MONOTONIC_RAW>; -} // namespace linux+} // namespace linux_ } // namespace platforms } // namespace ableton
link/include/ableton/platforms/linux/ThreadFactory.hpp view
@@ -26,7 +26,7 @@ { namespace platforms {-namespace linux+namespace linux_ { struct ThreadFactory@@ -40,6 +40,6 @@ } }; -} // namespace linux+} // namespace linux_ } // namespace platforms } // namespace ableton
link/include/ableton/platforms/posix/ScanIpIfAddrs.hpp view
@@ -19,11 +19,12 @@ #pragma once -#include <ableton/platforms/asio/AsioWrapper.hpp>-#include <ableton/platforms/asio/Util.hpp>+#include <ableton/discovery/AsioTypes.hpp> #include <arpa/inet.h> #include <ifaddrs.h>+#include <map> #include <net/if.h>+#include <string> #include <vector> namespace ableton@@ -75,34 +76,49 @@ { // Scan active network interfaces and return corresponding addresses // for all ip-based interfaces.- std::vector<::asio::ip::address> operator()()+ std::vector<discovery::IpAddress> operator()() {- std::vector<::asio::ip::address> addrs;+ std::vector<discovery::IpAddress> addrs;+ std::map<std::string, discovery::IpAddress> IpInterfaceNames; detail::GetIfAddrs getIfAddrs;- getIfAddrs.withIfAddrs([&addrs](const struct ifaddrs& interfaces) {+ getIfAddrs.withIfAddrs([&addrs, &IpInterfaceNames](const struct ifaddrs& interfaces) { const struct ifaddrs* interface; for (interface = &interfaces; interface; interface = interface->ifa_next) { auto addr = reinterpret_cast<const struct sockaddr_in*>(interface->ifa_addr);- if (addr && interface->ifa_flags & IFF_UP)+ if (addr && interface->ifa_flags & IFF_RUNNING && addr->sin_family == AF_INET) {- if (addr->sin_family == AF_INET)- {- auto bytes = reinterpret_cast<const char*>(&addr->sin_addr);- addrs.emplace_back(asio::makeAddress<::asio::ip::address_v4>(bytes));- }- else if (addr->sin_family == AF_INET6)+ auto bytes = reinterpret_cast<const char*>(&addr->sin_addr);+ auto address = discovery::makeAddress<discovery::IpAddressV4>(bytes);+ addrs.emplace_back(std::move(address));+ IpInterfaceNames.insert(std::make_pair(interface->ifa_name, address));+ }+ }+ });++ getIfAddrs.withIfAddrs([&addrs, &IpInterfaceNames](const struct ifaddrs& interfaces) {+ const struct ifaddrs* interface;+ for (interface = &interfaces; interface; interface = interface->ifa_next)+ {+ auto addr = reinterpret_cast<const struct sockaddr_in*>(interface->ifa_addr);+ if (addr && interface->ifa_flags & IFF_RUNNING && addr->sin_family == AF_INET6)+ {+ auto addr6 = reinterpret_cast<const struct sockaddr_in6*>(addr);+ auto bytes = reinterpret_cast<const char*>(&addr6->sin6_addr);+ auto scopeId = addr6->sin6_scope_id;+ auto address = discovery::makeAddress<discovery::IpAddressV6>(bytes, scopeId);+ if (IpInterfaceNames.find(interface->ifa_name) != IpInterfaceNames.end()+ && !address.is_loopback() && address.is_link_local()) {- auto addr6 = reinterpret_cast<const struct sockaddr_in6*>(addr);- auto bytes = reinterpret_cast<const char*>(&addr6->sin6_addr);- addrs.emplace_back(asio::makeAddress<::asio::ip::address_v6>(bytes));+ addrs.emplace_back(std::move(address)); } } } });+ return addrs;- }+ }; }; } // namespace posix
link/include/ableton/platforms/windows/ScanIpIfAddrs.hpp view
@@ -19,10 +19,11 @@ #pragma once -#include <ableton/platforms/asio/AsioWrapper.hpp>-#include <ableton/platforms/asio/Util.hpp>+#include <ableton/discovery/AsioTypes.hpp> #include <iphlpapi.h>+#include <map> #include <stdio.h>+#include <string> #include <vector> #include <winsock2.h> #include <ws2tcpip.h>@@ -99,12 +100,13 @@ { // Scan active network interfaces and return corresponding addresses // for all ip-based interfaces.- std::vector<::asio::ip::address> operator()()+ std::vector<discovery::IpAddress> operator()() {- std::vector<::asio::ip::address> addrs;+ std::vector<discovery::IpAddress> addrs;+ std::map<std::string, discovery::IpAddress> IpInterfaceNames; detail::GetIfAddrs getIfAddrs;- getIfAddrs.withIfAddrs([&addrs](const IP_ADAPTER_ADDRESSES& interfaces) {+ getIfAddrs.withIfAddrs([&](const IP_ADAPTER_ADDRESSES& interfaces) { const IP_ADAPTER_ADDRESSES* networkInterface; for (networkInterface = &interfaces; networkInterface; networkInterface = networkInterface->Next)@@ -119,18 +121,41 @@ SOCKADDR_IN* addr4 = reinterpret_cast<SOCKADDR_IN*>(address->Address.lpSockaddr); auto bytes = reinterpret_cast<const char*>(&addr4->sin_addr);- addrs.emplace_back(asio::makeAddress<::asio::ip::address_v4>(bytes));+ auto ipv4address = discovery::makeAddress<discovery::IpAddressV4>(bytes);+ addrs.emplace_back(ipv4address);+ IpInterfaceNames.insert(+ std::make_pair(networkInterface->AdapterName, ipv4address)); }- else if (AF_INET6 == family)+ }+ }+ });++ getIfAddrs.withIfAddrs([&](const IP_ADAPTER_ADDRESSES& interfaces) {+ const IP_ADAPTER_ADDRESSES* networkInterface;+ for (networkInterface = &interfaces; networkInterface;+ networkInterface = networkInterface->Next)+ {+ for (IP_ADAPTER_UNICAST_ADDRESS* address = networkInterface->FirstUnicastAddress;+ NULL != address; address = address->Next)+ {+ auto family = address->Address.lpSockaddr->sa_family;+ if (AF_INET6 == family+ && IpInterfaceNames.find(networkInterface->AdapterName)+ != IpInterfaceNames.end()) {- SOCKADDR_IN6* addr6 =+ SOCKADDR_IN6* sockAddr = reinterpret_cast<SOCKADDR_IN6*>(address->Address.lpSockaddr);- auto bytes = reinterpret_cast<const char*>(&addr6->sin6_addr);- addrs.emplace_back(asio::makeAddress<::asio::ip::address_v6>(bytes));+ auto bytes = reinterpret_cast<const char*>(&sockAddr->sin6_addr);+ auto addr6 = discovery::makeAddress<discovery::IpAddressV6>(bytes);+ if (!addr6.is_loopback() && addr6.is_link_local())+ {+ addrs.emplace_back(addr6);+ } } } } });+ return addrs; } };
link/include/ableton/test/serial_io/Context.hpp view
@@ -19,7 +19,7 @@ #pragma once -#include <ableton/platforms/asio/AsioWrapper.hpp>+#include <ableton/discovery/AsioTypes.hpp> #include <ableton/test/serial_io/SchedulerTree.hpp> #include <ableton/test/serial_io/Timer.hpp> #include <ableton/util/Log.hpp>@@ -37,7 +37,7 @@ { public: Context(const SchedulerTree::TimePoint& now,- const std::vector<::asio::ip::address>& ifAddrs,+ const std::vector<discovery::IpAddress>& ifAddrs, std::shared_ptr<SchedulerTree> pScheduler) : mNow(now) , mIfAddrs(ifAddrs)@@ -91,14 +91,14 @@ return mLog; } - std::vector<::asio::ip::address> scanNetworkInterfaces()+ std::vector<discovery::IpAddress> scanNetworkInterfaces() { return mIfAddrs; } private: const SchedulerTree::TimePoint& mNow;- const std::vector<::asio::ip::address>& mIfAddrs;+ const std::vector<discovery::IpAddress>& mIfAddrs; std::shared_ptr<SchedulerTree> mpScheduler; Log mLog; SchedulerTree::TimerId mNextTimerId;
link/include/ableton/test/serial_io/Fixture.hpp view
@@ -19,7 +19,7 @@ #pragma once -#include <ableton/platforms/asio/AsioWrapper.hpp>+#include <ableton/discovery/AsioTypes.hpp> #include <ableton/test/serial_io/Context.hpp> #include <chrono> #include <memory>@@ -50,7 +50,7 @@ Fixture(Fixture&&) = delete; Fixture& operator=(Fixture&&) = delete; - void setNetworkInterfaces(std::vector<::asio::ip::address> ifAddrs)+ void setNetworkInterfaces(std::vector<discovery::IpAddress> ifAddrs) { mIfAddrs = std::move(ifAddrs); }@@ -84,7 +84,7 @@ private: std::shared_ptr<SchedulerTree> mpScheduler; SchedulerTree::TimePoint mNow;- std::vector<::asio::ip::address> mIfAddrs;+ std::vector<discovery::IpAddress> mIfAddrs; }; } // namespace serial_io
link/modules/asio-standalone/asio/include/asio.hpp view
@@ -2,7 +2,7 @@ // asio.hpp // ~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -15,14 +15,25 @@ # pragma once #endif // defined(_MSC_VER) && (_MSC_VER >= 1200) +#include "asio/any_completion_executor.hpp"+#include "asio/any_completion_handler.hpp"+#include "asio/any_io_executor.hpp"+#include "asio/append.hpp"+#include "asio/as_tuple.hpp" #include "asio/associated_allocator.hpp"+#include "asio/associated_cancellation_slot.hpp" #include "asio/associated_executor.hpp"+#include "asio/associated_immediate_executor.hpp"+#include "asio/associator.hpp" #include "asio/async_result.hpp" #include "asio/awaitable.hpp" #include "asio/basic_datagram_socket.hpp" #include "asio/basic_deadline_timer.hpp"+#include "asio/basic_file.hpp" #include "asio/basic_io_object.hpp"+#include "asio/basic_random_access_file.hpp" #include "asio/basic_raw_socket.hpp"+#include "asio/basic_readable_pipe.hpp" #include "asio/basic_seq_packet_socket.hpp" #include "asio/basic_serial_port.hpp" #include "asio/basic_signal_set.hpp"@@ -30,11 +41,17 @@ #include "asio/basic_socket_acceptor.hpp" #include "asio/basic_socket_iostream.hpp" #include "asio/basic_socket_streambuf.hpp"+#include "asio/basic_stream_file.hpp" #include "asio/basic_stream_socket.hpp" #include "asio/basic_streambuf.hpp" #include "asio/basic_waitable_timer.hpp"+#include "asio/basic_writable_pipe.hpp"+#include "asio/bind_allocator.hpp"+#include "asio/bind_cancellation_slot.hpp" #include "asio/bind_executor.hpp"+#include "asio/bind_immediate_executor.hpp" #include "asio/buffer.hpp"+#include "asio/buffer_registration.hpp" #include "asio/buffered_read_stream_fwd.hpp" #include "asio/buffered_read_stream.hpp" #include "asio/buffered_stream_fwd.hpp"@@ -42,13 +59,19 @@ #include "asio/buffered_write_stream_fwd.hpp" #include "asio/buffered_write_stream.hpp" #include "asio/buffers_iterator.hpp"+#include "asio/cancellation_signal.hpp"+#include "asio/cancellation_state.hpp"+#include "asio/cancellation_type.hpp" #include "asio/co_spawn.hpp" #include "asio/completion_condition.hpp" #include "asio/compose.hpp" #include "asio/connect.hpp"+#include "asio/connect_pipe.hpp"+#include "asio/consign.hpp" #include "asio/coroutine.hpp" #include "asio/deadline_timer.hpp" #include "asio/defer.hpp"+#include "asio/deferred.hpp" #include "asio/detached.hpp" #include "asio/dispatch.hpp" #include "asio/error.hpp"@@ -84,6 +107,7 @@ #include "asio/execution_context.hpp" #include "asio/executor.hpp" #include "asio/executor_work_guard.hpp"+#include "asio/file_base.hpp" #include "asio/generic/basic_endpoint.hpp" #include "asio/generic/datagram_protocol.hpp" #include "asio/generic/raw_protocol.hpp"@@ -122,12 +146,14 @@ #include "asio/ip/unicast.hpp" #include "asio/ip/v6_only.hpp" #include "asio/is_applicable_property.hpp"+#include "asio/is_contiguous_iterator.hpp" #include "asio/is_executor.hpp" #include "asio/is_read_buffered.hpp" #include "asio/is_write_buffered.hpp" #include "asio/local/basic_endpoint.hpp" #include "asio/local/connect_pair.hpp" #include "asio/local/datagram_protocol.hpp"+#include "asio/local/seq_packet_protocol.hpp" #include "asio/local/stream_protocol.hpp" #include "asio/multiple_exceptions.hpp" #include "asio/packaged_task.hpp"@@ -139,20 +165,27 @@ #include "asio/posix/stream_descriptor.hpp" #include "asio/post.hpp" #include "asio/prefer.hpp"+#include "asio/prepend.hpp" #include "asio/query.hpp"+#include "asio/random_access_file.hpp" #include "asio/read.hpp" #include "asio/read_at.hpp" #include "asio/read_until.hpp"+#include "asio/readable_pipe.hpp"+#include "asio/recycling_allocator.hpp" #include "asio/redirect_error.hpp"+#include "asio/registered_buffer.hpp" #include "asio/require.hpp" #include "asio/require_concept.hpp" #include "asio/serial_port.hpp" #include "asio/serial_port_base.hpp" #include "asio/signal_set.hpp"+#include "asio/signal_set_base.hpp" #include "asio/socket_base.hpp" #include "asio/static_thread_pool.hpp" #include "asio/steady_timer.hpp" #include "asio/strand.hpp"+#include "asio/stream_file.hpp" #include "asio/streambuf.hpp" #include "asio/system_context.hpp" #include "asio/system_error.hpp"@@ -176,6 +209,7 @@ #include "asio/windows/overlapped_ptr.hpp" #include "asio/windows/random_access_handle.hpp" #include "asio/windows/stream_handle.hpp"+#include "asio/writable_pipe.hpp" #include "asio/write.hpp" #include "asio/write_at.hpp"
+ link/modules/asio-standalone/asio/include/asio/any_completion_executor.hpp view
@@ -0,0 +1,342 @@+//+// any_completion_executor.hpp+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com)+//+// Distributed under the Boost Software License, Version 1.0. (See accompanying+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)+//++#ifndef ASIO_ANY_COMPLETION_EXECUTOR_HPP+#define ASIO_ANY_COMPLETION_EXECUTOR_HPP++#if defined(_MSC_VER) && (_MSC_VER >= 1200)+# pragma once+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)++#include "asio/detail/config.hpp"+#if defined(ASIO_USE_TS_EXECUTOR_AS_DEFAULT)+# include "asio/executor.hpp"+#else // defined(ASIO_USE_TS_EXECUTOR_AS_DEFAULT)+# include "asio/execution.hpp"+#endif // defined(ASIO_USE_TS_EXECUTOR_AS_DEFAULT)++#include "asio/detail/push_options.hpp"++namespace asio {++#if defined(ASIO_USE_TS_EXECUTOR_AS_DEFAULT)++typedef executor any_completion_executor;++#else // defined(ASIO_USE_TS_EXECUTOR_AS_DEFAULT)++/// Polymorphic executor type for use with I/O objects.+/**+ * The @c any_completion_executor type is a polymorphic executor that supports+ * the set of properties required for the execution of completion handlers. It+ * is defined as the execution::any_executor class template parameterised as+ * follows:+ * @code execution::any_executor<+ * execution::prefer_only<execution::outstanding_work_t::tracked_t>,+ * execution::prefer_only<execution::outstanding_work_t::untracked_t>+ * execution::prefer_only<execution::relationship_t::fork_t>,+ * execution::prefer_only<execution::relationship_t::continuation_t>+ * > @endcode+ */+class any_completion_executor :+#if defined(GENERATING_DOCUMENTATION)+ public execution::any_executor<...>+#else // defined(GENERATING_DOCUMENTATION)+ public execution::any_executor<+ execution::prefer_only<execution::outstanding_work_t::tracked_t>,+ execution::prefer_only<execution::outstanding_work_t::untracked_t>,+ execution::prefer_only<execution::relationship_t::fork_t>,+ execution::prefer_only<execution::relationship_t::continuation_t>+ >+#endif // defined(GENERATING_DOCUMENTATION)+{+public:+#if !defined(GENERATING_DOCUMENTATION)+ typedef execution::any_executor<+ execution::prefer_only<execution::outstanding_work_t::tracked_t>,+ execution::prefer_only<execution::outstanding_work_t::untracked_t>,+ execution::prefer_only<execution::relationship_t::fork_t>,+ execution::prefer_only<execution::relationship_t::continuation_t>+ > base_type;++ typedef void supportable_properties_type(+ execution::prefer_only<execution::outstanding_work_t::tracked_t>,+ execution::prefer_only<execution::outstanding_work_t::untracked_t>,+ execution::prefer_only<execution::relationship_t::fork_t>,+ execution::prefer_only<execution::relationship_t::continuation_t>+ );+#endif // !defined(GENERATING_DOCUMENTATION)++ /// Default constructor.+ ASIO_DECL any_completion_executor() ASIO_NOEXCEPT;++ /// Construct in an empty state. Equivalent effects to default constructor.+ ASIO_DECL any_completion_executor(nullptr_t) ASIO_NOEXCEPT;++ /// Copy constructor.+ ASIO_DECL any_completion_executor(+ const any_completion_executor& e) ASIO_NOEXCEPT;++#if defined(ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)+ /// Move constructor.+ ASIO_DECL any_completion_executor(+ any_completion_executor&& e) ASIO_NOEXCEPT;+#endif // defined(ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)++ /// Construct to point to the same target as another any_executor.+#if defined(GENERATING_DOCUMENTATION)+ template <class... OtherSupportableProperties>+ any_completion_executor(+ execution::any_executor<OtherSupportableProperties...> e);+#else // defined(GENERATING_DOCUMENTATION)+ template <typename OtherAnyExecutor>+ any_completion_executor(OtherAnyExecutor e,+ typename constraint<+ conditional<+ !is_same<OtherAnyExecutor, any_completion_executor>::value+ && is_base_of<execution::detail::any_executor_base,+ OtherAnyExecutor>::value,+ typename execution::detail::supportable_properties<+ 0, supportable_properties_type>::template+ is_valid_target<OtherAnyExecutor>,+ false_type+ >::type::value+ >::type = 0)+ : base_type(ASIO_MOVE_CAST(OtherAnyExecutor)(e))+ {+ }+#endif // defined(GENERATING_DOCUMENTATION)++ /// Construct to point to the same target as another any_executor.+#if defined(GENERATING_DOCUMENTATION)+ template <class... OtherSupportableProperties>+ any_completion_executor(std::nothrow_t,+ execution::any_executor<OtherSupportableProperties...> e);+#else // defined(GENERATING_DOCUMENTATION)+ template <typename OtherAnyExecutor>+ any_completion_executor(std::nothrow_t, OtherAnyExecutor e,+ typename constraint<+ conditional<+ !is_same<OtherAnyExecutor, any_completion_executor>::value+ && is_base_of<execution::detail::any_executor_base,+ OtherAnyExecutor>::value,+ typename execution::detail::supportable_properties<+ 0, supportable_properties_type>::template+ is_valid_target<OtherAnyExecutor>,+ false_type+ >::type::value+ >::type = 0) ASIO_NOEXCEPT+ : base_type(std::nothrow, ASIO_MOVE_CAST(OtherAnyExecutor)(e))+ {+ }+#endif // defined(GENERATING_DOCUMENTATION)++ /// Construct to point to the same target as another any_executor.+ ASIO_DECL any_completion_executor(std::nothrow_t,+ const any_completion_executor& e) ASIO_NOEXCEPT;++#if defined(ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)+ /// Construct to point to the same target as another any_executor.+ ASIO_DECL any_completion_executor(std::nothrow_t,+ any_completion_executor&& e) ASIO_NOEXCEPT;+#endif // defined(ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)++ /// Construct a polymorphic wrapper for the specified executor.+#if defined(GENERATING_DOCUMENTATION)+ template <ASIO_EXECUTION_EXECUTOR Executor>+ any_completion_executor(Executor e);+#else // defined(GENERATING_DOCUMENTATION)+ template <ASIO_EXECUTION_EXECUTOR Executor>+ any_completion_executor(Executor e,+ typename constraint<+ conditional<+ !is_same<Executor, any_completion_executor>::value+ && !is_base_of<execution::detail::any_executor_base,+ Executor>::value,+ execution::detail::is_valid_target_executor<+ Executor, supportable_properties_type>,+ false_type+ >::type::value+ >::type = 0)+ : base_type(ASIO_MOVE_CAST(Executor)(e))+ {+ }+#endif // defined(GENERATING_DOCUMENTATION)++ /// Construct a polymorphic wrapper for the specified executor.+#if defined(GENERATING_DOCUMENTATION)+ template <ASIO_EXECUTION_EXECUTOR Executor>+ any_completion_executor(std::nothrow_t, Executor e);+#else // defined(GENERATING_DOCUMENTATION)+ template <ASIO_EXECUTION_EXECUTOR Executor>+ any_completion_executor(std::nothrow_t, Executor e,+ typename constraint<+ conditional<+ !is_same<Executor, any_completion_executor>::value+ && !is_base_of<execution::detail::any_executor_base,+ Executor>::value,+ execution::detail::is_valid_target_executor<+ Executor, supportable_properties_type>,+ false_type+ >::type::value+ >::type = 0) ASIO_NOEXCEPT+ : base_type(std::nothrow, ASIO_MOVE_CAST(Executor)(e))+ {+ }+#endif // defined(GENERATING_DOCUMENTATION)++ /// Assignment operator.+ ASIO_DECL any_completion_executor& operator=(+ const any_completion_executor& e) ASIO_NOEXCEPT;++#if defined(ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)+ /// Move assignment operator.+ ASIO_DECL any_completion_executor& operator=(+ any_completion_executor&& e) ASIO_NOEXCEPT;+#endif // defined(ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)++ /// Assignment operator that sets the polymorphic wrapper to the empty state.+ ASIO_DECL any_completion_executor& operator=(nullptr_t);++ /// Destructor.+ ASIO_DECL ~any_completion_executor();++ /// Swap targets with another polymorphic wrapper.+ ASIO_DECL void swap(any_completion_executor& other) ASIO_NOEXCEPT;++ /// Obtain a polymorphic wrapper with the specified property.+ /**+ * Do not call this function directly. It is intended for use with the+ * asio::require and asio::prefer customisation points.+ *+ * For example:+ * @code any_completion_executor ex = ...;+ * auto ex2 = asio::require(ex, execution::relationship.fork); @endcode+ */+ template <typename Property>+ any_completion_executor require(const Property& p,+ typename constraint<+ traits::require_member<const base_type&, const Property&>::is_valid+ >::type = 0) const+ {+ return static_cast<const base_type&>(*this).require(p);+ }++ /// Obtain a polymorphic wrapper with the specified property.+ /**+ * Do not call this function directly. It is intended for use with the+ * asio::prefer customisation point.+ *+ * For example:+ * @code any_completion_executor ex = ...;+ * auto ex2 = asio::prefer(ex, execution::relationship.fork); @endcode+ */+ template <typename Property>+ any_completion_executor prefer(const Property& p,+ typename constraint<+ traits::prefer_member<const base_type&, const Property&>::is_valid+ >::type = 0) const+ {+ return static_cast<const base_type&>(*this).prefer(p);+ }+};++#if !defined(GENERATING_DOCUMENTATION)++template <>+ASIO_DECL any_completion_executor any_completion_executor::prefer(+ const execution::outstanding_work_t::tracked_t&, int) const;++template <>+ASIO_DECL any_completion_executor any_completion_executor::prefer(+ const execution::outstanding_work_t::untracked_t&, int) const;++template <>+ASIO_DECL any_completion_executor any_completion_executor::prefer(+ const execution::relationship_t::fork_t&, int) const;++template <>+ASIO_DECL any_completion_executor any_completion_executor::prefer(+ const execution::relationship_t::continuation_t&, int) const;++namespace traits {++#if !defined(ASIO_HAS_DEDUCED_EQUALITY_COMPARABLE_TRAIT)++template <>+struct equality_comparable<any_completion_executor>+{+ static const bool is_valid = true;+ static const bool is_noexcept = true;+};++#endif // !defined(ASIO_HAS_DEDUCED_EQUALITY_COMPARABLE_TRAIT)++#if !defined(ASIO_HAS_DEDUCED_EXECUTE_MEMBER_TRAIT)++template <typename F>+struct execute_member<any_completion_executor, F>+{+ static const bool is_valid = true;+ static const bool is_noexcept = false;+ typedef void result_type;+};++#endif // !defined(ASIO_HAS_DEDUCED_EXECUTE_MEMBER_TRAIT)++#if !defined(ASIO_HAS_DEDUCED_QUERY_MEMBER_TRAIT)++template <typename Prop>+struct query_member<any_completion_executor, Prop> :+ query_member<any_completion_executor::base_type, Prop>+{+};++#endif // !defined(ASIO_HAS_DEDUCED_QUERY_MEMBER_TRAIT)++#if !defined(ASIO_HAS_DEDUCED_REQUIRE_MEMBER_TRAIT)++template <typename Prop>+struct require_member<any_completion_executor, Prop> :+ require_member<any_completion_executor::base_type, Prop>+{+ typedef any_completion_executor result_type;+};++#endif // !defined(ASIO_HAS_DEDUCED_REQUIRE_MEMBER_TRAIT)++#if !defined(ASIO_HAS_DEDUCED_PREFER_MEMBER_TRAIT)++template <typename Prop>+struct prefer_member<any_completion_executor, Prop> :+ prefer_member<any_completion_executor::base_type, Prop>+{+ typedef any_completion_executor result_type;+};++#endif // !defined(ASIO_HAS_DEDUCED_PREFER_MEMBER_TRAIT)++} // namespace traits++#endif // !defined(GENERATING_DOCUMENTATION)++#endif // defined(ASIO_USE_TS_EXECUTOR_AS_DEFAULT)++} // namespace asio++#include "asio/detail/pop_options.hpp"++#if defined(ASIO_HEADER_ONLY) \+ && !defined(ASIO_USE_TS_EXECUTOR_AS_DEFAULT)+# include "asio/impl/any_completion_executor.ipp"+#endif // defined(ASIO_HEADER_ONLY)+ // && !defined(ASIO_USE_TS_EXECUTOR_AS_DEFAULT)++#endif // ASIO_ANY_COMPLETION_EXECUTOR_HPP
+ link/modules/asio-standalone/asio/include/asio/any_completion_handler.hpp view
@@ -0,0 +1,762 @@+//+// any_completion_handler.hpp+// ~~~~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com)+//+// Distributed under the Boost Software License, Version 1.0. (See accompanying+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)+//++#ifndef ASIO_ANY_COMPLETION_HANDLER_HPP+#define ASIO_ANY_COMPLETION_HANDLER_HPP++#include "asio/detail/config.hpp"++#if (defined(ASIO_HAS_STD_TUPLE) \+ && defined(ASIO_HAS_MOVE) \+ && defined(ASIO_HAS_VARIADIC_TEMPLATES)) \+ || defined(GENERATING_DOCUMENTATION)++#include <cstring>+#include <functional>+#include <memory>+#include <utility>+#include "asio/any_completion_executor.hpp"+#include "asio/associated_allocator.hpp"+#include "asio/associated_cancellation_slot.hpp"+#include "asio/associated_executor.hpp"+#include "asio/cancellation_state.hpp"+#include "asio/recycling_allocator.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {+namespace detail {++class any_completion_handler_impl_base+{+public:+ template <typename S>+ explicit any_completion_handler_impl_base(S&& slot)+ : cancel_state_(ASIO_MOVE_CAST(S)(slot), enable_total_cancellation())+ {+ }++ cancellation_slot get_cancellation_slot() const ASIO_NOEXCEPT+ {+ return cancel_state_.slot();+ }++private:+ cancellation_state cancel_state_;+};++template <typename Handler>+class any_completion_handler_impl :+ public any_completion_handler_impl_base+{+public:+ template <typename S, typename H>+ any_completion_handler_impl(S&& slot, H&& h)+ : any_completion_handler_impl_base(ASIO_MOVE_CAST(S)(slot)),+ handler_(ASIO_MOVE_CAST(H)(h))+ {+ }++ struct uninit_deleter+ {+ typename std::allocator_traits<+ associated_allocator_t<Handler,+ asio::recycling_allocator<void>>>::template+ rebind_alloc<any_completion_handler_impl> alloc;++ void operator()(any_completion_handler_impl* ptr)+ {+ std::allocator_traits<decltype(alloc)>::deallocate(alloc, ptr, 1);+ }+ };++ struct deleter+ {+ typename std::allocator_traits<+ associated_allocator_t<Handler,+ asio::recycling_allocator<void>>>::template+ rebind_alloc<any_completion_handler_impl> alloc;++ void operator()(any_completion_handler_impl* ptr)+ {+ std::allocator_traits<decltype(alloc)>::destroy(alloc, ptr);+ std::allocator_traits<decltype(alloc)>::deallocate(alloc, ptr, 1);+ }+ };++ template <typename S, typename H>+ static any_completion_handler_impl* create(S&& slot, H&& h)+ {+ uninit_deleter d{+ (get_associated_allocator)(h,+ asio::recycling_allocator<void>())};++ std::unique_ptr<any_completion_handler_impl, uninit_deleter> uninit_ptr(+ std::allocator_traits<decltype(d.alloc)>::allocate(d.alloc, 1), d);++ any_completion_handler_impl* ptr =+ new (uninit_ptr.get()) any_completion_handler_impl(+ ASIO_MOVE_CAST(S)(slot), ASIO_MOVE_CAST(H)(h));++ uninit_ptr.release();+ return ptr;+ }++ void destroy()+ {+ deleter d{+ (get_associated_allocator)(handler_,+ asio::recycling_allocator<void>())};++ d(this);+ }++ any_completion_executor executor(+ const any_completion_executor& candidate) const ASIO_NOEXCEPT+ {+ return any_completion_executor(std::nothrow,+ (get_associated_executor)(handler_, candidate));+ }++ void* allocate(std::size_t size, std::size_t align) const+ {+ typename std::allocator_traits<+ associated_allocator_t<Handler,+ asio::recycling_allocator<void>>>::template+ rebind_alloc<unsigned char> alloc(+ (get_associated_allocator)(handler_,+ asio::recycling_allocator<void>()));++ std::size_t space = size + align - 1;+ unsigned char* base =+ std::allocator_traits<decltype(alloc)>::allocate(+ alloc, space + sizeof(std::ptrdiff_t));++ void* p = base;+ if (detail::align(align, size, p, space))+ {+ std::ptrdiff_t off = static_cast<unsigned char*>(p) - base;+ std::memcpy(static_cast<unsigned char*>(p) + size, &off, sizeof(off));+ return p;+ }++ std::bad_alloc ex;+ asio::detail::throw_exception(ex);+ return nullptr;+ }++ void deallocate(void* p, std::size_t size, std::size_t align) const+ {+ if (p)+ {+ typename std::allocator_traits<+ associated_allocator_t<Handler,+ asio::recycling_allocator<void>>>::template+ rebind_alloc<unsigned char> alloc(+ (get_associated_allocator)(handler_,+ asio::recycling_allocator<void>()));++ std::ptrdiff_t off;+ std::memcpy(&off, static_cast<unsigned char*>(p) + size, sizeof(off));+ unsigned char* base = static_cast<unsigned char*>(p) - off;++ std::allocator_traits<decltype(alloc)>::deallocate(+ alloc, base, size + align -1 + sizeof(std::ptrdiff_t));+ }+ }++ template <typename... Args>+ void call(Args&&... args)+ {+ deleter d{+ (get_associated_allocator)(handler_,+ asio::recycling_allocator<void>())};++ std::unique_ptr<any_completion_handler_impl, deleter> ptr(this, d);+ Handler handler(ASIO_MOVE_CAST(Handler)(handler_));+ ptr.reset();++ ASIO_MOVE_CAST(Handler)(handler)(+ ASIO_MOVE_CAST(Args)(args)...);+ }++private:+ Handler handler_;+};++template <typename Signature>+class any_completion_handler_call_fn;++template <typename R, typename... Args>+class any_completion_handler_call_fn<R(Args...)>+{+public:+ using type = void(*)(any_completion_handler_impl_base*, Args...);++ constexpr any_completion_handler_call_fn(type fn)+ : call_fn_(fn)+ {+ }++ void call(any_completion_handler_impl_base* impl, Args... args) const+ {+ call_fn_(impl, ASIO_MOVE_CAST(Args)(args)...);+ }++ template <typename Handler>+ static void impl(any_completion_handler_impl_base* impl, Args... args)+ {+ static_cast<any_completion_handler_impl<Handler>*>(impl)->call(+ ASIO_MOVE_CAST(Args)(args)...);+ }++private:+ type call_fn_;+};++template <typename... Signatures>+class any_completion_handler_call_fns;++template <typename Signature>+class any_completion_handler_call_fns<Signature> :+ public any_completion_handler_call_fn<Signature>+{+public:+ using any_completion_handler_call_fn<+ Signature>::any_completion_handler_call_fn;+ using any_completion_handler_call_fn<Signature>::call;+};++template <typename Signature, typename... Signatures>+class any_completion_handler_call_fns<Signature, Signatures...> :+ public any_completion_handler_call_fn<Signature>,+ public any_completion_handler_call_fns<Signatures...>+{+public:+ template <typename CallFn, typename... CallFns>+ constexpr any_completion_handler_call_fns(CallFn fn, CallFns... fns)+ : any_completion_handler_call_fn<Signature>(fn),+ any_completion_handler_call_fns<Signatures...>(fns...)+ {+ }++ using any_completion_handler_call_fn<Signature>::call;+ using any_completion_handler_call_fns<Signatures...>::call;+};++class any_completion_handler_destroy_fn+{+public:+ using type = void(*)(any_completion_handler_impl_base*);++ constexpr any_completion_handler_destroy_fn(type fn)+ : destroy_fn_(fn)+ {+ }++ void destroy(any_completion_handler_impl_base* impl) const+ {+ destroy_fn_(impl);+ }++ template <typename Handler>+ static void impl(any_completion_handler_impl_base* impl)+ {+ static_cast<any_completion_handler_impl<Handler>*>(impl)->destroy();+ }++private:+ type destroy_fn_;+};++class any_completion_handler_executor_fn+{+public:+ using type = any_completion_executor(*)(+ any_completion_handler_impl_base*, const any_completion_executor&);++ constexpr any_completion_handler_executor_fn(type fn)+ : executor_fn_(fn)+ {+ }++ any_completion_executor executor(any_completion_handler_impl_base* impl,+ const any_completion_executor& candidate) const+ {+ return executor_fn_(impl, candidate);+ }++ template <typename Handler>+ static any_completion_executor impl(any_completion_handler_impl_base* impl,+ const any_completion_executor& candidate)+ {+ return static_cast<any_completion_handler_impl<Handler>*>(impl)->executor(+ candidate);+ }++private:+ type executor_fn_;+};++class any_completion_handler_allocate_fn+{+public:+ using type = void*(*)(any_completion_handler_impl_base*,+ std::size_t, std::size_t);++ constexpr any_completion_handler_allocate_fn(type fn)+ : allocate_fn_(fn)+ {+ }++ void* allocate(any_completion_handler_impl_base* impl,+ std::size_t size, std::size_t align) const+ {+ return allocate_fn_(impl, size, align);+ }++ template <typename Handler>+ static void* impl(any_completion_handler_impl_base* impl,+ std::size_t size, std::size_t align)+ {+ return static_cast<any_completion_handler_impl<Handler>*>(impl)->allocate(+ size, align);+ }++private:+ type allocate_fn_;+};++class any_completion_handler_deallocate_fn+{+public:+ using type = void(*)(any_completion_handler_impl_base*,+ void*, std::size_t, std::size_t);++ constexpr any_completion_handler_deallocate_fn(type fn)+ : deallocate_fn_(fn)+ {+ }++ void deallocate(any_completion_handler_impl_base* impl,+ void* p, std::size_t size, std::size_t align) const+ {+ deallocate_fn_(impl, p, size, align);+ }++ template <typename Handler>+ static void impl(any_completion_handler_impl_base* impl,+ void* p, std::size_t size, std::size_t align)+ {+ static_cast<any_completion_handler_impl<Handler>*>(impl)->deallocate(+ p, size, align);+ }++private:+ type deallocate_fn_;+};++template <typename... Signatures>+class any_completion_handler_fn_table+ : private any_completion_handler_destroy_fn,+ private any_completion_handler_executor_fn,+ private any_completion_handler_allocate_fn,+ private any_completion_handler_deallocate_fn,+ private any_completion_handler_call_fns<Signatures...>+{+public:+ template <typename... CallFns>+ constexpr any_completion_handler_fn_table(+ any_completion_handler_destroy_fn::type destroy_fn,+ any_completion_handler_executor_fn::type executor_fn,+ any_completion_handler_allocate_fn::type allocate_fn,+ any_completion_handler_deallocate_fn::type deallocate_fn,+ CallFns... call_fns)+ : any_completion_handler_destroy_fn(destroy_fn),+ any_completion_handler_executor_fn(executor_fn),+ any_completion_handler_allocate_fn(allocate_fn),+ any_completion_handler_deallocate_fn(deallocate_fn),+ any_completion_handler_call_fns<Signatures...>(call_fns...)+ {+ }++ using any_completion_handler_destroy_fn::destroy;+ using any_completion_handler_executor_fn::executor;+ using any_completion_handler_allocate_fn::allocate;+ using any_completion_handler_deallocate_fn::deallocate;+ using any_completion_handler_call_fns<Signatures...>::call;+};++template <typename Handler, typename... Signatures>+struct any_completion_handler_fn_table_instance+{+ static constexpr any_completion_handler_fn_table<Signatures...>+ value = any_completion_handler_fn_table<Signatures...>(+ &any_completion_handler_destroy_fn::impl<Handler>,+ &any_completion_handler_executor_fn::impl<Handler>,+ &any_completion_handler_allocate_fn::impl<Handler>,+ &any_completion_handler_deallocate_fn::impl<Handler>,+ &any_completion_handler_call_fn<Signatures>::template impl<Handler>...);+};++template <typename Handler, typename... Signatures>+constexpr any_completion_handler_fn_table<Signatures...>+any_completion_handler_fn_table_instance<Handler, Signatures...>::value;++} // namespace detail++template <typename... Signatures>+class any_completion_handler;++/// An allocator type that forwards memory allocation operations through an+/// instance of @c any_completion_handler.+template <typename T, typename... Signatures>+class any_completion_handler_allocator+{+private:+ template <typename...>+ friend class any_completion_handler;++ template <typename, typename...>+ friend class any_completion_handler_allocator;++ const detail::any_completion_handler_fn_table<Signatures...>* fn_table_;+ detail::any_completion_handler_impl_base* impl_;++ constexpr any_completion_handler_allocator(int,+ const any_completion_handler<Signatures...>& h) ASIO_NOEXCEPT+ : fn_table_(h.fn_table_),+ impl_(h.impl_)+ {+ }++public:+ /// The type of objects that may be allocated by the allocator.+ typedef T value_type;++ /// Rebinds an allocator to another value type.+ template <typename U>+ struct rebind+ {+ /// Specifies the type of the rebound allocator.+ typedef any_completion_handler_allocator<U, Signatures...> other;+ };++ /// Construct from another @c any_completion_handler_allocator.+ template <typename U>+ constexpr any_completion_handler_allocator(+ const any_completion_handler_allocator<U, Signatures...>& a)+ ASIO_NOEXCEPT+ : fn_table_(a.fn_table_),+ impl_(a.impl_)+ {+ }++ /// Equality operator.+ constexpr bool operator==(+ const any_completion_handler_allocator& other) const ASIO_NOEXCEPT+ {+ return fn_table_ == other.fn_table_ && impl_ == other.impl_;+ }++ /// Inequality operator.+ constexpr bool operator!=(+ const any_completion_handler_allocator& other) const ASIO_NOEXCEPT+ {+ return fn_table_ != other.fn_table_ || impl_ != other.impl_;+ }++ /// Allocate space for @c n objects of the allocator's value type.+ T* allocate(std::size_t n) const+ {+ return static_cast<T*>(+ fn_table_->allocate(+ impl_, sizeof(T) * n, alignof(T)));+ }++ /// Deallocate space for @c n objects of the allocator's value type.+ void deallocate(T* p, std::size_t n) const+ {+ fn_table_->deallocate(impl_, p, sizeof(T) * n, alignof(T));+ }+};++/// A protoco-allocator type that may be rebound to obtain an allocator that+/// forwards memory allocation operations through an instance of+/// @c any_completion_handler.+template <typename... Signatures>+class any_completion_handler_allocator<void, Signatures...>+{+private:+ template <typename...>+ friend class any_completion_handler;++ template <typename, typename...>+ friend class any_completion_handler_allocator;++ const detail::any_completion_handler_fn_table<Signatures...>* fn_table_;+ detail::any_completion_handler_impl_base* impl_;++ constexpr any_completion_handler_allocator(int,+ const any_completion_handler<Signatures...>& h) ASIO_NOEXCEPT+ : fn_table_(h.fn_table_),+ impl_(h.impl_)+ {+ }++public:+ /// @c void as no objects can be allocated through a proto-allocator.+ typedef void value_type;++ /// Rebinds an allocator to another value type.+ template <typename U>+ struct rebind+ {+ /// Specifies the type of the rebound allocator.+ typedef any_completion_handler_allocator<U, Signatures...> other;+ };++ /// Construct from another @c any_completion_handler_allocator.+ template <typename U>+ constexpr any_completion_handler_allocator(+ const any_completion_handler_allocator<U, Signatures...>& a)+ ASIO_NOEXCEPT+ : fn_table_(a.fn_table_),+ impl_(a.impl_)+ {+ }++ /// Equality operator.+ constexpr bool operator==(+ const any_completion_handler_allocator& other) const ASIO_NOEXCEPT+ {+ return fn_table_ == other.fn_table_ && impl_ == other.impl_;+ }++ /// Inequality operator.+ constexpr bool operator!=(+ const any_completion_handler_allocator& other) const ASIO_NOEXCEPT+ {+ return fn_table_ != other.fn_table_ || impl_ != other.impl_;+ }+};++/// Polymorphic wrapper for completion handlers.+/**+ * The @c any_completion_handler class template is a polymorphic wrapper for+ * completion handlers that propagates the associated executor, associated+ * allocator, and associated cancellation slot through a type-erasing interface.+ *+ * When using @c any_completion_handler, specify one or more completion+ * signatures as template parameters. These will dictate the arguments that may+ * be passed to the handler through the polymorphic interface.+ *+ * Typical uses for @c any_completion_handler include:+ *+ * @li Separate compilation of asynchronous operation implementations.+ *+ * @li Enabling interoperability between asynchronous operations and virtual+ * functions.+ */+template <typename... Signatures>+class any_completion_handler+{+#if !defined(GENERATING_DOCUMENTATION)+private:+ template <typename, typename...>+ friend class any_completion_handler_allocator;++ template <typename, typename>+ friend struct associated_executor;++ const detail::any_completion_handler_fn_table<Signatures...>* fn_table_;+ detail::any_completion_handler_impl_base* impl_;+#endif // !defined(GENERATING_DOCUMENTATION)++public:+ /// The associated allocator type.+ using allocator_type = any_completion_handler_allocator<void, Signatures...>;++ /// The associated cancellation slot type.+ using cancellation_slot_type = cancellation_slot;++ /// Construct an @c any_completion_handler in an empty state, without a target+ /// object.+ constexpr any_completion_handler()+ : fn_table_(nullptr),+ impl_(nullptr)+ {+ }++ /// Construct an @c any_completion_handler in an empty state, without a target+ /// object.+ constexpr any_completion_handler(nullptr_t)+ : fn_table_(nullptr),+ impl_(nullptr)+ {+ }++ /// Construct an @c any_completion_handler to contain the specified target.+ template <typename H, typename Handler = typename decay<H>::type>+ any_completion_handler(H&& h,+ typename constraint<+ !is_same<typename decay<H>::type, any_completion_handler>::value+ >::type = 0)+ : fn_table_(+ &detail::any_completion_handler_fn_table_instance<+ Handler, Signatures...>::value),+ impl_(detail::any_completion_handler_impl<Handler>::create(+ (get_associated_cancellation_slot)(h), ASIO_MOVE_CAST(H)(h)))+ {+ }++ /// Move-construct an @c any_completion_handler from another.+ /**+ * After the operation, the moved-from object @c other has no target.+ */+ any_completion_handler(any_completion_handler&& other) ASIO_NOEXCEPT+ : fn_table_(other.fn_table_),+ impl_(other.impl_)+ {+ other.fn_table_ = nullptr;+ other.impl_ = nullptr;+ }++ /// Move-assign an @c any_completion_handler from another.+ /**+ * After the operation, the moved-from object @c other has no target.+ */+ any_completion_handler& operator=(+ any_completion_handler&& other) ASIO_NOEXCEPT+ {+ any_completion_handler(+ ASIO_MOVE_CAST(any_completion_handler)(other)).swap(*this);+ return *this;+ }++ /// Assignment operator that sets the polymorphic wrapper to the empty state.+ any_completion_handler& operator=(nullptr_t) ASIO_NOEXCEPT+ {+ any_completion_handler().swap(*this);+ return *this;+ }++ /// Destructor.+ ~any_completion_handler()+ {+ if (impl_)+ fn_table_->destroy(impl_);+ }++ /// Test if the polymorphic wrapper is empty.+ constexpr explicit operator bool() const ASIO_NOEXCEPT+ {+ return impl_ != nullptr;+ }++ /// Test if the polymorphic wrapper is non-empty.+ constexpr bool operator!() const ASIO_NOEXCEPT+ {+ return impl_ == nullptr;+ }++ /// Swap the content of an @c any_completion_handler with another.+ void swap(any_completion_handler& other) ASIO_NOEXCEPT+ {+ std::swap(fn_table_, other.fn_table_);+ std::swap(impl_, other.impl_);+ }++ /// Get the associated allocator.+ allocator_type get_allocator() const ASIO_NOEXCEPT+ {+ return allocator_type(0, *this);+ }++ /// Get the associated cancellation slot.+ cancellation_slot_type get_cancellation_slot() const ASIO_NOEXCEPT+ {+ return impl_->get_cancellation_slot();+ }++ /// Function call operator.+ /**+ * Invokes target completion handler with the supplied arguments.+ *+ * This function may only be called once, as the target handler is moved from.+ * The polymorphic wrapper is left in an empty state.+ *+ * Throws @c std::bad_function_call if the polymorphic wrapper is empty.+ */+ template <typename... Args>+ auto operator()(Args&&... args)+ -> decltype(fn_table_->call(impl_, ASIO_MOVE_CAST(Args)(args)...))+ {+ if (detail::any_completion_handler_impl_base* impl = impl_)+ {+ impl_ = nullptr;+ return fn_table_->call(impl, ASIO_MOVE_CAST(Args)(args)...);+ }+ std::bad_function_call ex;+ asio::detail::throw_exception(ex);+ }++ /// Equality operator.+ friend constexpr bool operator==(+ const any_completion_handler& a, nullptr_t) ASIO_NOEXCEPT+ {+ return a.impl_ == nullptr;+ }++ /// Equality operator.+ friend constexpr bool operator==(+ nullptr_t, const any_completion_handler& b) ASIO_NOEXCEPT+ {+ return nullptr == b.impl_;+ }++ /// Inequality operator.+ friend constexpr bool operator!=(+ const any_completion_handler& a, nullptr_t) ASIO_NOEXCEPT+ {+ return a.impl_ != nullptr;+ }++ /// Inequality operator.+ friend constexpr bool operator!=(+ nullptr_t, const any_completion_handler& b) ASIO_NOEXCEPT+ {+ return nullptr != b.impl_;+ }+};++template <typename... Signatures, typename Candidate>+struct associated_executor<any_completion_handler<Signatures...>, Candidate>+{+ using type = any_completion_executor;++ static type get(const any_completion_handler<Signatures...>& handler,+ const Candidate& candidate = Candidate()) ASIO_NOEXCEPT+ {+ return handler.fn_table_->executor(handler.impl_,+ any_completion_executor(std::nothrow, candidate));+ }+};++} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // (defined(ASIO_HAS_STD_TUPLE)+ // && defined(ASIO_HAS_MOVE)+ // && defined(ASIO_HAS_VARIADIC_TEMPLATES))+ // || defined(GENERATING_DOCUMENTATION)++#endif // ASIO_ANY_COMPLETION_HANDLER_HPP
link/modules/asio-standalone/asio/include/asio/any_io_executor.hpp view
@@ -2,7 +2,7 @@ // any_io_executor.hpp // ~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -48,24 +48,312 @@ * execution::prefer_only<execution::relationship_t::continuation_t> * > @endcode */+class any_io_executor : #if defined(GENERATING_DOCUMENTATION)-typedef execution::any_executor<...> any_io_executor;+ public execution::any_executor<...> #else // defined(GENERATING_DOCUMENTATION)-typedef execution::any_executor<- execution::context_as_t<execution_context&>,- execution::blocking_t::never_t,- execution::prefer_only<execution::blocking_t::possibly_t>,- execution::prefer_only<execution::outstanding_work_t::tracked_t>,- execution::prefer_only<execution::outstanding_work_t::untracked_t>,- execution::prefer_only<execution::relationship_t::fork_t>,- execution::prefer_only<execution::relationship_t::continuation_t>- > any_io_executor;+ public execution::any_executor<+ execution::context_as_t<execution_context&>,+ execution::blocking_t::never_t,+ execution::prefer_only<execution::blocking_t::possibly_t>,+ execution::prefer_only<execution::outstanding_work_t::tracked_t>,+ execution::prefer_only<execution::outstanding_work_t::untracked_t>,+ execution::prefer_only<execution::relationship_t::fork_t>,+ execution::prefer_only<execution::relationship_t::continuation_t>+ > #endif // defined(GENERATING_DOCUMENTATION)+{+public:+#if !defined(GENERATING_DOCUMENTATION)+ typedef execution::any_executor<+ execution::context_as_t<execution_context&>,+ execution::blocking_t::never_t,+ execution::prefer_only<execution::blocking_t::possibly_t>,+ execution::prefer_only<execution::outstanding_work_t::tracked_t>,+ execution::prefer_only<execution::outstanding_work_t::untracked_t>,+ execution::prefer_only<execution::relationship_t::fork_t>,+ execution::prefer_only<execution::relationship_t::continuation_t>+ > base_type; + typedef void supportable_properties_type(+ execution::context_as_t<execution_context&>,+ execution::blocking_t::never_t,+ execution::prefer_only<execution::blocking_t::possibly_t>,+ execution::prefer_only<execution::outstanding_work_t::tracked_t>,+ execution::prefer_only<execution::outstanding_work_t::untracked_t>,+ execution::prefer_only<execution::relationship_t::fork_t>,+ execution::prefer_only<execution::relationship_t::continuation_t>+ );+#endif // !defined(GENERATING_DOCUMENTATION)++ /// Default constructor.+ ASIO_DECL any_io_executor() ASIO_NOEXCEPT;++ /// Construct in an empty state. Equivalent effects to default constructor.+ ASIO_DECL any_io_executor(nullptr_t) ASIO_NOEXCEPT;++ /// Copy constructor.+ ASIO_DECL any_io_executor(const any_io_executor& e) ASIO_NOEXCEPT;++#if defined(ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)+ /// Move constructor.+ ASIO_DECL any_io_executor(any_io_executor&& e) ASIO_NOEXCEPT;+#endif // defined(ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)++ /// Construct to point to the same target as another any_executor.+#if defined(GENERATING_DOCUMENTATION)+ template <class... OtherSupportableProperties>+ any_io_executor(execution::any_executor<OtherSupportableProperties...> e);+#else // defined(GENERATING_DOCUMENTATION)+ template <typename OtherAnyExecutor>+ any_io_executor(OtherAnyExecutor e,+ typename constraint<+ conditional<+ !is_same<OtherAnyExecutor, any_io_executor>::value+ && is_base_of<execution::detail::any_executor_base,+ OtherAnyExecutor>::value,+ typename execution::detail::supportable_properties<+ 0, supportable_properties_type>::template+ is_valid_target<OtherAnyExecutor>,+ false_type+ >::type::value+ >::type = 0)+ : base_type(ASIO_MOVE_CAST(OtherAnyExecutor)(e))+ {+ }+#endif // defined(GENERATING_DOCUMENTATION)++ /// Construct to point to the same target as another any_executor.+#if defined(GENERATING_DOCUMENTATION)+ template <class... OtherSupportableProperties>+ any_io_executor(std::nothrow_t,+ execution::any_executor<OtherSupportableProperties...> e);+#else // defined(GENERATING_DOCUMENTATION)+ template <typename OtherAnyExecutor>+ any_io_executor(std::nothrow_t, OtherAnyExecutor e,+ typename constraint<+ conditional<+ !is_same<OtherAnyExecutor, any_io_executor>::value+ && is_base_of<execution::detail::any_executor_base,+ OtherAnyExecutor>::value,+ typename execution::detail::supportable_properties<+ 0, supportable_properties_type>::template+ is_valid_target<OtherAnyExecutor>,+ false_type+ >::type::value+ >::type = 0) ASIO_NOEXCEPT+ : base_type(std::nothrow, ASIO_MOVE_CAST(OtherAnyExecutor)(e))+ {+ }+#endif // defined(GENERATING_DOCUMENTATION)++ /// Construct to point to the same target as another any_executor.+ ASIO_DECL any_io_executor(std::nothrow_t,+ const any_io_executor& e) ASIO_NOEXCEPT;++#if defined(ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)+ /// Construct to point to the same target as another any_executor.+ ASIO_DECL any_io_executor(std::nothrow_t,+ any_io_executor&& e) ASIO_NOEXCEPT;+#endif // defined(ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)++ /// Construct a polymorphic wrapper for the specified executor.+#if defined(GENERATING_DOCUMENTATION)+ template <ASIO_EXECUTION_EXECUTOR Executor>+ any_io_executor(Executor e);+#else // defined(GENERATING_DOCUMENTATION)+ template <ASIO_EXECUTION_EXECUTOR Executor>+ any_io_executor(Executor e,+ typename constraint<+ conditional<+ !is_same<Executor, any_io_executor>::value+ && !is_base_of<execution::detail::any_executor_base,+ Executor>::value,+ execution::detail::is_valid_target_executor<+ Executor, supportable_properties_type>,+ false_type+ >::type::value+ >::type = 0)+ : base_type(ASIO_MOVE_CAST(Executor)(e))+ {+ }+#endif // defined(GENERATING_DOCUMENTATION)++ /// Construct a polymorphic wrapper for the specified executor.+#if defined(GENERATING_DOCUMENTATION)+ template <ASIO_EXECUTION_EXECUTOR Executor>+ any_io_executor(std::nothrow_t, Executor e);+#else // defined(GENERATING_DOCUMENTATION)+ template <ASIO_EXECUTION_EXECUTOR Executor>+ any_io_executor(std::nothrow_t, Executor e,+ typename constraint<+ conditional<+ !is_same<Executor, any_io_executor>::value+ && !is_base_of<execution::detail::any_executor_base,+ Executor>::value,+ execution::detail::is_valid_target_executor<+ Executor, supportable_properties_type>,+ false_type+ >::type::value+ >::type = 0) ASIO_NOEXCEPT+ : base_type(std::nothrow, ASIO_MOVE_CAST(Executor)(e))+ {+ }+#endif // defined(GENERATING_DOCUMENTATION)++ /// Assignment operator.+ ASIO_DECL any_io_executor& operator=(+ const any_io_executor& e) ASIO_NOEXCEPT;++#if defined(ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)+ /// Move assignment operator.+ ASIO_DECL any_io_executor& operator=(+ any_io_executor&& e) ASIO_NOEXCEPT;+#endif // defined(ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)++ /// Assignment operator that sets the polymorphic wrapper to the empty state.+ ASIO_DECL any_io_executor& operator=(nullptr_t);++ /// Destructor.+ ASIO_DECL ~any_io_executor();++ /// Swap targets with another polymorphic wrapper.+ ASIO_DECL void swap(any_io_executor& other) ASIO_NOEXCEPT;++ /// Obtain a polymorphic wrapper with the specified property.+ /**+ * Do not call this function directly. It is intended for use with the+ * asio::require and asio::prefer customisation points.+ *+ * For example:+ * @code any_io_executor ex = ...;+ * auto ex2 = asio::require(ex, execution::blocking.possibly); @endcode+ */+ template <typename Property>+ any_io_executor require(const Property& p,+ typename constraint<+ traits::require_member<const base_type&, const Property&>::is_valid+ >::type = 0) const+ {+ return static_cast<const base_type&>(*this).require(p);+ }++ /// Obtain a polymorphic wrapper with the specified property.+ /**+ * Do not call this function directly. It is intended for use with the+ * asio::prefer customisation point.+ *+ * For example:+ * @code any_io_executor ex = ...;+ * auto ex2 = asio::prefer(ex, execution::blocking.possibly); @endcode+ */+ template <typename Property>+ any_io_executor prefer(const Property& p,+ typename constraint<+ traits::prefer_member<const base_type&, const Property&>::is_valid+ >::type = 0) const+ {+ return static_cast<const base_type&>(*this).prefer(p);+ }+};++#if !defined(GENERATING_DOCUMENTATION)++template <>+ASIO_DECL any_io_executor any_io_executor::require(+ const execution::blocking_t::never_t&, int) const;++template <>+ASIO_DECL any_io_executor any_io_executor::prefer(+ const execution::blocking_t::possibly_t&, int) const;++template <>+ASIO_DECL any_io_executor any_io_executor::prefer(+ const execution::outstanding_work_t::tracked_t&, int) const;++template <>+ASIO_DECL any_io_executor any_io_executor::prefer(+ const execution::outstanding_work_t::untracked_t&, int) const;++template <>+ASIO_DECL any_io_executor any_io_executor::prefer(+ const execution::relationship_t::fork_t&, int) const;++template <>+ASIO_DECL any_io_executor any_io_executor::prefer(+ const execution::relationship_t::continuation_t&, int) const;++namespace traits {++#if !defined(ASIO_HAS_DEDUCED_EQUALITY_COMPARABLE_TRAIT)++template <>+struct equality_comparable<any_io_executor>+{+ static const bool is_valid = true;+ static const bool is_noexcept = true;+};++#endif // !defined(ASIO_HAS_DEDUCED_EQUALITY_COMPARABLE_TRAIT)++#if !defined(ASIO_HAS_DEDUCED_EXECUTE_MEMBER_TRAIT)++template <typename F>+struct execute_member<any_io_executor, F>+{+ static const bool is_valid = true;+ static const bool is_noexcept = false;+ typedef void result_type;+};++#endif // !defined(ASIO_HAS_DEDUCED_EXECUTE_MEMBER_TRAIT)++#if !defined(ASIO_HAS_DEDUCED_QUERY_MEMBER_TRAIT)++template <typename Prop>+struct query_member<any_io_executor, Prop> :+ query_member<any_io_executor::base_type, Prop>+{+};++#endif // !defined(ASIO_HAS_DEDUCED_QUERY_MEMBER_TRAIT)++#if !defined(ASIO_HAS_DEDUCED_REQUIRE_MEMBER_TRAIT)++template <typename Prop>+struct require_member<any_io_executor, Prop> :+ require_member<any_io_executor::base_type, Prop>+{+ typedef any_io_executor result_type;+};++#endif // !defined(ASIO_HAS_DEDUCED_REQUIRE_MEMBER_TRAIT)++#if !defined(ASIO_HAS_DEDUCED_PREFER_MEMBER_TRAIT)++template <typename Prop>+struct prefer_member<any_io_executor, Prop> :+ prefer_member<any_io_executor::base_type, Prop>+{+ typedef any_io_executor result_type;+};++#endif // !defined(ASIO_HAS_DEDUCED_PREFER_MEMBER_TRAIT)++} // namespace traits++#endif // !defined(GENERATING_DOCUMENTATION)+ #endif // defined(ASIO_USE_TS_EXECUTOR_AS_DEFAULT) } // namespace asio #include "asio/detail/pop_options.hpp"++#if defined(ASIO_HEADER_ONLY) \+ && !defined(ASIO_USE_TS_EXECUTOR_AS_DEFAULT)+# include "asio/impl/any_io_executor.ipp"+#endif // defined(ASIO_HEADER_ONLY)+ // && !defined(ASIO_USE_TS_EXECUTOR_AS_DEFAULT) #endif // ASIO_ANY_IO_EXECUTOR_HPP
+ link/modules/asio-standalone/asio/include/asio/append.hpp view
@@ -0,0 +1,78 @@+//+// append.hpp+// ~~~~~~~~~~+//+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com)+//+// Distributed under the Boost Software License, Version 1.0. (See accompanying+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)+//++#ifndef ASIO_APPEND_HPP+#define ASIO_APPEND_HPP++#if defined(_MSC_VER) && (_MSC_VER >= 1200)+# pragma once+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)++#include "asio/detail/config.hpp"++#if (defined(ASIO_HAS_STD_TUPLE) \+ && defined(ASIO_HAS_VARIADIC_TEMPLATES)) \+ || defined(GENERATING_DOCUMENTATION)++#include <tuple>+#include "asio/detail/type_traits.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {++/// Completion token type used to specify that the completion handler+/// arguments should be passed additional values after the results of the+/// operation.+template <typename CompletionToken, typename... Values>+class append_t+{+public:+ /// Constructor.+ template <typename T, typename... V>+ ASIO_CONSTEXPR explicit append_t(+ ASIO_MOVE_ARG(T) completion_token,+ ASIO_MOVE_ARG(V)... values)+ : token_(ASIO_MOVE_CAST(T)(completion_token)),+ values_(ASIO_MOVE_CAST(V)(values)...)+ {+ }++//private:+ CompletionToken token_;+ std::tuple<Values...> values_;+};++/// Completion token type used to specify that the completion handler+/// arguments should be passed additional values after the results of the+/// operation.+template <typename CompletionToken, typename... Values>+ASIO_NODISCARD inline ASIO_CONSTEXPR append_t<+ typename decay<CompletionToken>::type, typename decay<Values>::type...>+append(ASIO_MOVE_ARG(CompletionToken) completion_token,+ ASIO_MOVE_ARG(Values)... values)+{+ return append_t<+ typename decay<CompletionToken>::type, typename decay<Values>::type...>(+ ASIO_MOVE_CAST(CompletionToken)(completion_token),+ ASIO_MOVE_CAST(Values)(values)...);+}++} // namespace asio++#include "asio/detail/pop_options.hpp"++#include "asio/impl/append.hpp"++#endif // (defined(ASIO_HAS_STD_TUPLE)+ // && defined(ASIO_HAS_VARIADIC_TEMPLATES))+ // || defined(GENERATING_DOCUMENTATION)++#endif // ASIO_APPEND_HPP
+ link/modules/asio-standalone/asio/include/asio/as_tuple.hpp view
@@ -0,0 +1,139 @@+//+// as_tuple.hpp+// ~~~~~~~~~~~~+//+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com)+//+// Distributed under the Boost Software License, Version 1.0. (See accompanying+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)+//++#ifndef ASIO_AS_TUPLE_HPP+#define ASIO_AS_TUPLE_HPP++#if defined(_MSC_VER) && (_MSC_VER >= 1200)+# pragma once+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)++#include "asio/detail/config.hpp"++#if (defined(ASIO_HAS_STD_TUPLE) \+ && defined(ASIO_HAS_VARIADIC_TEMPLATES)) \+ || defined(GENERATING_DOCUMENTATION)++#include "asio/detail/type_traits.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {++/// A @ref completion_token adapter used to specify that the completion handler+/// arguments should be combined into a single tuple argument.+/**+ * The as_tuple_t class is used to indicate that any arguments to the+ * completion handler should be combined and passed as a single tuple argument.+ * The arguments are first moved into a @c std::tuple and that tuple is then+ * passed to the completion handler.+ */+template <typename CompletionToken>+class as_tuple_t+{+public:+ /// Tag type used to prevent the "default" constructor from being used for+ /// conversions.+ struct default_constructor_tag {};++ /// Default constructor.+ /**+ * This constructor is only valid if the underlying completion token is+ * default constructible and move constructible. The underlying completion+ * token is itself defaulted as an argument to allow it to capture a source+ * location.+ */+ ASIO_CONSTEXPR as_tuple_t(+ default_constructor_tag = default_constructor_tag(),+ CompletionToken token = CompletionToken())+ : token_(ASIO_MOVE_CAST(CompletionToken)(token))+ {+ }++ /// Constructor.+ template <typename T>+ ASIO_CONSTEXPR explicit as_tuple_t(+ ASIO_MOVE_ARG(T) completion_token)+ : token_(ASIO_MOVE_CAST(T)(completion_token))+ {+ }++ /// Adapts an executor to add the @c as_tuple_t completion token as the+ /// default.+ template <typename InnerExecutor>+ struct executor_with_default : InnerExecutor+ {+ /// Specify @c as_tuple_t as the default completion token type.+ typedef as_tuple_t default_completion_token_type;++ /// Construct the adapted executor from the inner executor type.+ template <typename InnerExecutor1>+ executor_with_default(const InnerExecutor1& ex,+ typename constraint<+ conditional<+ !is_same<InnerExecutor1, executor_with_default>::value,+ is_convertible<InnerExecutor1, InnerExecutor>,+ false_type+ >::type::value+ >::type = 0) ASIO_NOEXCEPT+ : InnerExecutor(ex)+ {+ }+ };++ /// Type alias to adapt an I/O object to use @c as_tuple_t as its+ /// default completion token type.+#if defined(ASIO_HAS_ALIAS_TEMPLATES) \+ || defined(GENERATING_DOCUMENTATION)+ template <typename T>+ using as_default_on_t = typename T::template rebind_executor<+ executor_with_default<typename T::executor_type> >::other;+#endif // defined(ASIO_HAS_ALIAS_TEMPLATES)+ // || defined(GENERATING_DOCUMENTATION)++ /// Function helper to adapt an I/O object to use @c as_tuple_t as its+ /// default completion token type.+ template <typename T>+ static typename decay<T>::type::template rebind_executor<+ executor_with_default<typename decay<T>::type::executor_type>+ >::other+ as_default_on(ASIO_MOVE_ARG(T) object)+ {+ return typename decay<T>::type::template rebind_executor<+ executor_with_default<typename decay<T>::type::executor_type>+ >::other(ASIO_MOVE_CAST(T)(object));+ }++//private:+ CompletionToken token_;+};++/// Adapt a @ref completion_token to specify that the completion handler+/// arguments should be combined into a single tuple argument.+template <typename CompletionToken>+ASIO_NODISCARD inline+ASIO_CONSTEXPR as_tuple_t<typename decay<CompletionToken>::type>+as_tuple(ASIO_MOVE_ARG(CompletionToken) completion_token)+{+ return as_tuple_t<typename decay<CompletionToken>::type>(+ ASIO_MOVE_CAST(CompletionToken)(completion_token));+}++} // namespace asio++#include "asio/detail/pop_options.hpp"++#include "asio/impl/as_tuple.hpp"++#endif // (defined(ASIO_HAS_STD_TUPLE)+ // && defined(ASIO_HAS_VARIADIC_TEMPLATES))+ // || defined(GENERATING_DOCUMENTATION)++#endif // ASIO_AS_TUPLE_HPP
link/modules/asio-standalone/asio/include/asio/associated_allocator.hpp view
@@ -2,7 +2,7 @@ // associated_allocator.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -17,36 +17,81 @@ #include "asio/detail/config.hpp" #include <memory>+#include "asio/associator.hpp"+#include "asio/detail/functional.hpp" #include "asio/detail/type_traits.hpp" #include "asio/detail/push_options.hpp" namespace asio {++template <typename T, typename Allocator>+struct associated_allocator;+ namespace detail { -template <typename T, typename E, typename = void>+template <typename T, typename = void>+struct has_allocator_type : false_type+{+};++template <typename T>+struct has_allocator_type<T,+ typename void_type<typename T::allocator_type>::type>+ : true_type+{+};++template <typename T, typename A, typename = void, typename = void> struct associated_allocator_impl {- typedef E type;+ typedef void asio_associated_allocator_is_unspecialised; - static type get(const T&, const E& e) ASIO_NOEXCEPT+ typedef A type;++ static type get(const T&) ASIO_NOEXCEPT {- return e;+ return type(); }++ static const type& get(const T&, const A& a) ASIO_NOEXCEPT+ {+ return a;+ } }; -template <typename T, typename E>-struct associated_allocator_impl<T, E,+template <typename T, typename A>+struct associated_allocator_impl<T, A, typename void_type<typename T::allocator_type>::type> { typedef typename T::allocator_type type; - static type get(const T& t, const E&) ASIO_NOEXCEPT+ static ASIO_AUTO_RETURN_TYPE_PREFIX(type) get(+ const T& t) ASIO_NOEXCEPT+ ASIO_AUTO_RETURN_TYPE_SUFFIX((t.get_allocator())) { return t.get_allocator(); }++ static ASIO_AUTO_RETURN_TYPE_PREFIX(type) get(+ const T& t, const A&) ASIO_NOEXCEPT+ ASIO_AUTO_RETURN_TYPE_SUFFIX((t.get_allocator()))+ {+ return t.get_allocator();+ } }; +template <typename T, typename A>+struct associated_allocator_impl<T, A,+ typename enable_if<+ !has_allocator_type<T>::value+ >::type,+ typename void_type<+ typename associator<associated_allocator, T, A>::type+ >::type> : associator<associated_allocator, T, A>+{+};+ } // namespace detail /// Traits type used to obtain the allocator associated with an object.@@ -63,29 +108,32 @@ * Allocator requirements. * * @li Provide a noexcept static member function named @c get, callable as @c- * get(t) and with return type @c type.+ * get(t) and with return type @c type or a (possibly const) reference to @c+ * type. * * @li Provide a noexcept static member function named @c get, callable as @c- * get(t,a) and with return type @c type.+ * get(t,a) and with return type @c type or a (possibly const) reference to @c+ * type. */ template <typename T, typename Allocator = std::allocator<void> > struct associated_allocator+#if !defined(GENERATING_DOCUMENTATION)+ : detail::associated_allocator_impl<T, Allocator>+#endif // !defined(GENERATING_DOCUMENTATION) {+#if defined(GENERATING_DOCUMENTATION) /// If @c T has a nested type @c allocator_type, <tt>T::allocator_type</tt>. /// Otherwise @c Allocator.-#if defined(GENERATING_DOCUMENTATION) typedef see_below type;-#else // defined(GENERATING_DOCUMENTATION)- typedef typename detail::associated_allocator_impl<T, Allocator>::type type;-#endif // defined(GENERATING_DOCUMENTATION) /// If @c T has a nested type @c allocator_type, returns+ /// <tt>t.get_allocator()</tt>. Otherwise returns @c type().+ static decltype(auto) get(const T& t) ASIO_NOEXCEPT;++ /// If @c T has a nested type @c allocator_type, returns /// <tt>t.get_allocator()</tt>. Otherwise returns @c a.- static type get(const T& t,- const Allocator& a = Allocator()) ASIO_NOEXCEPT- {- return detail::associated_allocator_impl<T, Allocator>::get(t, a);- }+ static decltype(auto) get(const T& t, const Allocator& a) ASIO_NOEXCEPT;+#endif // defined(GENERATING_DOCUMENTATION) }; /// Helper function to obtain an object's associated allocator.@@ -93,7 +141,7 @@ * @returns <tt>associated_allocator<T>::get(t)</tt> */ template <typename T>-inline typename associated_allocator<T>::type+ASIO_NODISCARD inline typename associated_allocator<T>::type get_associated_allocator(const T& t) ASIO_NOEXCEPT { return associated_allocator<T>::get(t);@@ -104,8 +152,11 @@ * @returns <tt>associated_allocator<T, Allocator>::get(t, a)</tt> */ template <typename T, typename Allocator>-inline typename associated_allocator<T, Allocator>::type+ASIO_NODISCARD inline ASIO_AUTO_RETURN_TYPE_PREFIX2(+ typename associated_allocator<T, Allocator>::type) get_associated_allocator(const T& t, const Allocator& a) ASIO_NOEXCEPT+ ASIO_AUTO_RETURN_TYPE_SUFFIX((+ associated_allocator<T, Allocator>::get(t, a))) { return associated_allocator<T, Allocator>::get(t, a); }@@ -117,6 +168,63 @@ = typename associated_allocator<T, Allocator>::type; #endif // defined(ASIO_HAS_ALIAS_TEMPLATES)++namespace detail {++template <typename T, typename A, typename = void>+struct associated_allocator_forwarding_base+{+};++template <typename T, typename A>+struct associated_allocator_forwarding_base<T, A,+ typename enable_if<+ is_same<+ typename associated_allocator<T,+ A>::asio_associated_allocator_is_unspecialised,+ void+ >::value+ >::type>+{+ typedef void asio_associated_allocator_is_unspecialised;+};++} // namespace detail++#if defined(ASIO_HAS_STD_REFERENCE_WRAPPER) \+ || defined(GENERATING_DOCUMENTATION)++/// Specialisation of associated_allocator for @c std::reference_wrapper.+template <typename T, typename Allocator>+struct associated_allocator<reference_wrapper<T>, Allocator>+#if !defined(GENERATING_DOCUMENTATION)+ : detail::associated_allocator_forwarding_base<T, Allocator>+#endif // !defined(GENERATING_DOCUMENTATION)+{+ /// Forwards @c type to the associator specialisation for the unwrapped type+ /// @c T.+ typedef typename associated_allocator<T, Allocator>::type type;++ /// Forwards the request to get the allocator to the associator specialisation+ /// for the unwrapped type @c T.+ static type get(reference_wrapper<T> t) ASIO_NOEXCEPT+ {+ return associated_allocator<T, Allocator>::get(t.get());+ }++ /// Forwards the request to get the allocator to the associator specialisation+ /// for the unwrapped type @c T.+ static ASIO_AUTO_RETURN_TYPE_PREFIX(type) get(+ reference_wrapper<T> t, const Allocator& a) ASIO_NOEXCEPT+ ASIO_AUTO_RETURN_TYPE_SUFFIX((+ associated_allocator<T, Allocator>::get(t.get(), a)))+ {+ return associated_allocator<T, Allocator>::get(t.get(), a);+ }+};++#endif // defined(ASIO_HAS_STD_REFERENCE_WRAPPER)+ // || defined(GENERATING_DOCUMENTATION) } // namespace asio
+ link/modules/asio-standalone/asio/include/asio/associated_cancellation_slot.hpp view
@@ -0,0 +1,238 @@+//+// associated_cancellation_slot.hpp+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com)+//+// Distributed under the Boost Software License, Version 1.0. (See accompanying+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)+//++#ifndef ASIO_ASSOCIATED_CANCELLATION_SLOT_HPP+#define ASIO_ASSOCIATED_CANCELLATION_SLOT_HPP++#if defined(_MSC_VER) && (_MSC_VER >= 1200)+# pragma once+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)++#include "asio/detail/config.hpp"+#include "asio/associator.hpp"+#include "asio/cancellation_signal.hpp"+#include "asio/detail/functional.hpp"+#include "asio/detail/type_traits.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {++template <typename T, typename CancellationSlot>+struct associated_cancellation_slot;++namespace detail {++template <typename T, typename = void>+struct has_cancellation_slot_type : false_type+{+};++template <typename T>+struct has_cancellation_slot_type<T,+ typename void_type<typename T::cancellation_slot_type>::type>+ : true_type+{+};++template <typename T, typename S, typename = void, typename = void>+struct associated_cancellation_slot_impl+{+ typedef void asio_associated_cancellation_slot_is_unspecialised;++ typedef S type;++ static type get(const T&) ASIO_NOEXCEPT+ {+ return type();+ }++ static const type& get(const T&, const S& s) ASIO_NOEXCEPT+ {+ return s;+ }+};++template <typename T, typename S>+struct associated_cancellation_slot_impl<T, S,+ typename void_type<typename T::cancellation_slot_type>::type>+{+ typedef typename T::cancellation_slot_type type;++ static ASIO_AUTO_RETURN_TYPE_PREFIX(type) get(+ const T& t) ASIO_NOEXCEPT+ ASIO_AUTO_RETURN_TYPE_SUFFIX((t.get_cancellation_slot()))+ {+ return t.get_cancellation_slot();+ }++ static ASIO_AUTO_RETURN_TYPE_PREFIX(type) get(+ const T& t, const S&) ASIO_NOEXCEPT+ ASIO_AUTO_RETURN_TYPE_SUFFIX((t.get_cancellation_slot()))+ {+ return t.get_cancellation_slot();+ }+};++template <typename T, typename S>+struct associated_cancellation_slot_impl<T, S,+ typename enable_if<+ !has_cancellation_slot_type<T>::value+ >::type,+ typename void_type<+ typename associator<associated_cancellation_slot, T, S>::type+ >::type> : associator<associated_cancellation_slot, T, S>+{+};++} // namespace detail++/// Traits type used to obtain the cancellation_slot associated with an object.+/**+ * A program may specialise this traits type if the @c T template parameter in+ * the specialisation is a user-defined type. The template parameter @c+ * CancellationSlot shall be a type meeting the CancellationSlot requirements.+ *+ * Specialisations shall meet the following requirements, where @c t is a const+ * reference to an object of type @c T, and @c s is an object of type @c+ * CancellationSlot.+ *+ * @li Provide a nested typedef @c type that identifies a type meeting the+ * CancellationSlot requirements.+ *+ * @li Provide a noexcept static member function named @c get, callable as @c+ * get(t) and with return type @c type or a (possibly const) reference to @c+ * type.+ *+ * @li Provide a noexcept static member function named @c get, callable as @c+ * get(t,s) and with return type @c type or a (possibly const) reference to @c+ * type.+ */+template <typename T, typename CancellationSlot = cancellation_slot>+struct associated_cancellation_slot+#if !defined(GENERATING_DOCUMENTATION)+ : detail::associated_cancellation_slot_impl<T, CancellationSlot>+#endif // !defined(GENERATING_DOCUMENTATION)+{+#if defined(GENERATING_DOCUMENTATION)+ /// If @c T has a nested type @c cancellation_slot_type,+ /// <tt>T::cancellation_slot_type</tt>. Otherwise+ /// @c CancellationSlot.+ typedef see_below type;++ /// If @c T has a nested type @c cancellation_slot_type, returns+ /// <tt>t.get_cancellation_slot()</tt>. Otherwise returns @c type().+ static decltype(auto) get(const T& t) ASIO_NOEXCEPT;++ /// If @c T has a nested type @c cancellation_slot_type, returns+ /// <tt>t.get_cancellation_slot()</tt>. Otherwise returns @c s.+ static decltype(auto) get(const T& t,+ const CancellationSlot& s) ASIO_NOEXCEPT;+#endif // defined(GENERATING_DOCUMENTATION)+};++/// Helper function to obtain an object's associated cancellation_slot.+/**+ * @returns <tt>associated_cancellation_slot<T>::get(t)</tt>+ */+template <typename T>+ASIO_NODISCARD inline typename associated_cancellation_slot<T>::type+get_associated_cancellation_slot(const T& t) ASIO_NOEXCEPT+{+ return associated_cancellation_slot<T>::get(t);+}++/// Helper function to obtain an object's associated cancellation_slot.+/**+ * @returns <tt>associated_cancellation_slot<T,+ * CancellationSlot>::get(t, st)</tt>+ */+template <typename T, typename CancellationSlot>+ASIO_NODISCARD inline ASIO_AUTO_RETURN_TYPE_PREFIX2(+ typename associated_cancellation_slot<T, CancellationSlot>::type)+get_associated_cancellation_slot(const T& t,+ const CancellationSlot& st) ASIO_NOEXCEPT+ ASIO_AUTO_RETURN_TYPE_SUFFIX((+ associated_cancellation_slot<T, CancellationSlot>::get(t, st)))+{+ return associated_cancellation_slot<T, CancellationSlot>::get(t, st);+}++#if defined(ASIO_HAS_ALIAS_TEMPLATES)++template <typename T, typename CancellationSlot = cancellation_slot>+using associated_cancellation_slot_t =+ typename associated_cancellation_slot<T, CancellationSlot>::type;++#endif // defined(ASIO_HAS_ALIAS_TEMPLATES)++namespace detail {++template <typename T, typename S, typename = void>+struct associated_cancellation_slot_forwarding_base+{+};++template <typename T, typename S>+struct associated_cancellation_slot_forwarding_base<T, S,+ typename enable_if<+ is_same<+ typename associated_cancellation_slot<T,+ S>::asio_associated_cancellation_slot_is_unspecialised,+ void+ >::value+ >::type>+{+ typedef void asio_associated_cancellation_slot_is_unspecialised;+};++} // namespace detail++#if defined(ASIO_HAS_STD_REFERENCE_WRAPPER) \+ || defined(GENERATING_DOCUMENTATION)++/// Specialisation of associated_cancellation_slot for @c+/// std::reference_wrapper.+template <typename T, typename CancellationSlot>+struct associated_cancellation_slot<reference_wrapper<T>, CancellationSlot>+#if !defined(GENERATING_DOCUMENTATION)+ : detail::associated_cancellation_slot_forwarding_base<T, CancellationSlot>+#endif // !defined(GENERATING_DOCUMENTATION)+{+ /// Forwards @c type to the associator specialisation for the unwrapped type+ /// @c T.+ typedef typename associated_cancellation_slot<T, CancellationSlot>::type type;++ /// Forwards the request to get the cancellation slot to the associator+ /// specialisation for the unwrapped type @c T.+ static type get(reference_wrapper<T> t) ASIO_NOEXCEPT+ {+ return associated_cancellation_slot<T, CancellationSlot>::get(t.get());+ }++ /// Forwards the request to get the cancellation slot to the associator+ /// specialisation for the unwrapped type @c T.+ static ASIO_AUTO_RETURN_TYPE_PREFIX(type) get(reference_wrapper<T> t,+ const CancellationSlot& s) ASIO_NOEXCEPT+ ASIO_AUTO_RETURN_TYPE_SUFFIX((+ associated_cancellation_slot<T, CancellationSlot>::get(t.get(), s)))+ {+ return associated_cancellation_slot<T, CancellationSlot>::get(t.get(), s);+ }+};++#endif // defined(ASIO_HAS_STD_REFERENCE_WRAPPER)+ // || defined(GENERATING_DOCUMENTATION)++} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // ASIO_ASSOCIATED_CANCELLATION_SLOT_HPP
link/modules/asio-standalone/asio/include/asio/associated_executor.hpp view
@@ -2,7 +2,7 @@ // associated_executor.hpp // ~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -16,6 +16,8 @@ #endif // defined(_MSC_VER) && (_MSC_VER >= 1200) #include "asio/detail/config.hpp"+#include "asio/associator.hpp"+#include "asio/detail/functional.hpp" #include "asio/detail/type_traits.hpp" #include "asio/execution/executor.hpp" #include "asio/is_executor.hpp"@@ -24,17 +26,38 @@ #include "asio/detail/push_options.hpp" namespace asio {++template <typename T, typename Executor>+struct associated_executor;+ namespace detail { -template <typename T, typename E, typename = void>+template <typename T, typename = void>+struct has_executor_type : false_type+{+};++template <typename T>+struct has_executor_type<T,+ typename void_type<typename T::executor_type>::type>+ : true_type+{+};++template <typename T, typename E, typename = void, typename = void> struct associated_executor_impl { typedef void asio_associated_executor_is_unspecialised; typedef E type; - static type get(const T&, const E& e = E()) ASIO_NOEXCEPT+ static type get(const T&) ASIO_NOEXCEPT {+ return type();+ }++ static const type& get(const T&, const E& e) ASIO_NOEXCEPT+ { return e; } };@@ -45,12 +68,32 @@ { typedef typename T::executor_type type; - static type get(const T& t, const E& = E()) ASIO_NOEXCEPT+ static ASIO_AUTO_RETURN_TYPE_PREFIX(type) get(+ const T& t) ASIO_NOEXCEPT+ ASIO_AUTO_RETURN_TYPE_SUFFIX((t.get_executor())) { return t.get_executor(); }++ static ASIO_AUTO_RETURN_TYPE_PREFIX(type) get(+ const T& t, const E&) ASIO_NOEXCEPT+ ASIO_AUTO_RETURN_TYPE_SUFFIX((t.get_executor()))+ {+ return t.get_executor();+ } }; +template <typename T, typename E>+struct associated_executor_impl<T, E,+ typename enable_if<+ !has_executor_type<T>::value+ >::type,+ typename void_type<+ typename associator<associated_executor, T, E>::type+ >::type> : associator<associated_executor, T, E>+{+};+ } // namespace detail /// Traits type used to obtain the executor associated with an object.@@ -67,10 +110,12 @@ * Executor requirements. * * @li Provide a noexcept static member function named @c get, callable as @c- * get(t) and with return type @c type.+ * get(t) and with return type @c type or a (possibly const) reference to @c+ * type. * * @li Provide a noexcept static member function named @c get, callable as @c- * get(t,e) and with return type @c type.+ * get(t,e) and with return type @c type or a (possibly const) reference to @c+ * type. */ template <typename T, typename Executor = system_executor> struct associated_executor@@ -84,9 +129,12 @@ typedef see_below type; /// If @c T has a nested type @c executor_type, returns+ /// <tt>t.get_executor()</tt>. Otherwise returns @c type().+ static decltype(auto) get(const T& t) ASIO_NOEXCEPT;++ /// If @c T has a nested type @c executor_type, returns /// <tt>t.get_executor()</tt>. Otherwise returns @c ex.- static type get(const T& t,- const Executor& ex = Executor()) ASIO_NOEXCEPT;+ static decltype(auto) get(const T& t, const Executor& ex) ASIO_NOEXCEPT; #endif // defined(GENERATING_DOCUMENTATION) }; @@ -95,7 +143,7 @@ * @returns <tt>associated_executor<T>::get(t)</tt> */ template <typename T>-inline typename associated_executor<T>::type+ASIO_NODISCARD inline typename associated_executor<T>::type get_associated_executor(const T& t) ASIO_NOEXCEPT { return associated_executor<T>::get(t);@@ -106,11 +154,14 @@ * @returns <tt>associated_executor<T, Executor>::get(t, ex)</tt> */ template <typename T, typename Executor>-inline typename associated_executor<T, Executor>::type+ASIO_NODISCARD inline ASIO_AUTO_RETURN_TYPE_PREFIX2(+ typename associated_executor<T, Executor>::type) get_associated_executor(const T& t, const Executor& ex,- typename enable_if<+ typename constraint< is_executor<Executor>::value || execution::is_executor<Executor>::value- >::type* = 0) ASIO_NOEXCEPT+ >::type = 0) ASIO_NOEXCEPT+ ASIO_AUTO_RETURN_TYPE_SUFFIX((+ associated_executor<T, Executor>::get(t, ex))) { return associated_executor<T, Executor>::get(t, ex); }@@ -121,11 +172,11 @@ * ExecutionContext::executor_type>::get(t, ctx.get_executor())</tt> */ template <typename T, typename ExecutionContext>-inline typename associated_executor<T,- typename ExecutionContext::executor_type>::type+ASIO_NODISCARD inline typename associated_executor<T,+ typename ExecutionContext::executor_type>::type get_associated_executor(const T& t, ExecutionContext& ctx,- typename enable_if<is_convertible<ExecutionContext&,- execution_context&>::value>::type* = 0) ASIO_NOEXCEPT+ typename constraint<is_convertible<ExecutionContext&,+ execution_context&>::value>::type = 0) ASIO_NOEXCEPT { return associated_executor<T, typename ExecutionContext::executor_type>::get(t, ctx.get_executor());@@ -159,6 +210,42 @@ }; } // namespace detail++#if defined(ASIO_HAS_STD_REFERENCE_WRAPPER) \+ || defined(GENERATING_DOCUMENTATION)++/// Specialisation of associated_executor for @c std::reference_wrapper.+template <typename T, typename Executor>+struct associated_executor<reference_wrapper<T>, Executor>+#if !defined(GENERATING_DOCUMENTATION)+ : detail::associated_executor_forwarding_base<T, Executor>+#endif // !defined(GENERATING_DOCUMENTATION)+{+ /// Forwards @c type to the associator specialisation for the unwrapped type+ /// @c T.+ typedef typename associated_executor<T, Executor>::type type;++ /// Forwards the request to get the executor to the associator specialisation+ /// for the unwrapped type @c T.+ static type get(reference_wrapper<T> t) ASIO_NOEXCEPT+ {+ return associated_executor<T, Executor>::get(t.get());+ }++ /// Forwards the request to get the executor to the associator specialisation+ /// for the unwrapped type @c T.+ static ASIO_AUTO_RETURN_TYPE_PREFIX(type) get(+ reference_wrapper<T> t, const Executor& ex) ASIO_NOEXCEPT+ ASIO_AUTO_RETURN_TYPE_SUFFIX((+ associated_executor<T, Executor>::get(t.get(), ex)))+ {+ return associated_executor<T, Executor>::get(t.get(), ex);+ }+};++#endif // defined(ASIO_HAS_STD_REFERENCE_WRAPPER)+ // || defined(GENERATING_DOCUMENTATION)+ } // namespace asio #include "asio/detail/pop_options.hpp"
+ link/modules/asio-standalone/asio/include/asio/associated_immediate_executor.hpp view
@@ -0,0 +1,297 @@+//+// associated_immediate_executor.hpp+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com)+//+// Distributed under the Boost Software License, Version 1.0. (See accompanying+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)+//++#ifndef ASIO_ASSOCIATED_IMMEDIATE_EXECUTOR_HPP+#define ASIO_ASSOCIATED_IMMEDIATE_EXECUTOR_HPP++#if defined(_MSC_VER) && (_MSC_VER >= 1200)+# pragma once+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)++#include "asio/detail/config.hpp"+#include "asio/associator.hpp"+#include "asio/detail/functional.hpp"+#include "asio/detail/type_traits.hpp"+#include "asio/execution/blocking.hpp"+#include "asio/execution/executor.hpp"+#include "asio/execution_context.hpp"+#include "asio/is_executor.hpp"+#include "asio/require.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {++template <typename T, typename Executor>+struct associated_immediate_executor;++namespace detail {++template <typename T, typename = void>+struct has_immediate_executor_type : false_type+{+};++template <typename T>+struct has_immediate_executor_type<T,+ typename void_type<typename T::immediate_executor_type>::type>+ : true_type+{+};++template <typename E, typename = void, typename = void>+struct default_immediate_executor+{+ typedef typename require_result<E, execution::blocking_t::never_t>::type type;++ static type get(const E& e) ASIO_NOEXCEPT+ {+ return asio::require(e, execution::blocking.never);+ }+};++template <typename E>+struct default_immediate_executor<E,+ typename enable_if<+ !execution::is_executor<E>::value+ >::type,+ typename enable_if<+ is_executor<E>::value+ >::type>+{+ class type : public E+ {+ public:+ template <typename Executor1>+ explicit type(const Executor1& e,+ typename constraint<+ conditional<+ !is_same<Executor1, type>::value,+ is_convertible<Executor1, E>,+ false_type+ >::type::value+ >::type = 0) ASIO_NOEXCEPT+ : E(e)+ {+ }++ type(const type& other) ASIO_NOEXCEPT+ : E(static_cast<const E&>(other))+ {+ }++#if defined(ASIO_HAS_MOVE)+ type(type&& other) ASIO_NOEXCEPT+ : E(ASIO_MOVE_CAST(E)(other))+ {+ }+#endif // defined(ASIO_HAS_MOVE)++ template <typename Function, typename Allocator>+ void dispatch(ASIO_MOVE_ARG(Function) f, const Allocator& a) const+ {+ this->post(ASIO_MOVE_CAST(Function)(f), a);+ }++ friend bool operator==(const type& a, const type& b) ASIO_NOEXCEPT+ {+ return static_cast<const E&>(a) == static_cast<const E&>(b);+ }++ friend bool operator!=(const type& a, const type& b) ASIO_NOEXCEPT+ {+ return static_cast<const E&>(a) != static_cast<const E&>(b);+ }+ };++ static type get(const E& e) ASIO_NOEXCEPT+ {+ return type(e);+ }+};++template <typename T, typename E, typename = void, typename = void>+struct associated_immediate_executor_impl+{+ typedef void asio_associated_immediate_executor_is_unspecialised;++ typedef typename default_immediate_executor<E>::type type;++ static ASIO_AUTO_RETURN_TYPE_PREFIX(type) get(+ const T&, const E& e) ASIO_NOEXCEPT+ ASIO_AUTO_RETURN_TYPE_SUFFIX((default_immediate_executor<E>::get(e)))+ {+ return default_immediate_executor<E>::get(e);+ }+};++template <typename T, typename E>+struct associated_immediate_executor_impl<T, E,+ typename void_type<typename T::immediate_executor_type>::type>+{+ typedef typename T::immediate_executor_type type;++ static ASIO_AUTO_RETURN_TYPE_PREFIX(type) get(+ const T& t, const E&) ASIO_NOEXCEPT+ ASIO_AUTO_RETURN_TYPE_SUFFIX((t.get_immediate_executor()))+ {+ return t.get_immediate_executor();+ }+};++template <typename T, typename E>+struct associated_immediate_executor_impl<T, E,+ typename enable_if<+ !has_immediate_executor_type<T>::value+ >::type,+ typename void_type<+ typename associator<associated_immediate_executor, T, E>::type+ >::type> : associator<associated_immediate_executor, T, E>+{+};++} // namespace detail++/// Traits type used to obtain the immediate executor associated with an object.+/**+ * A program may specialise this traits type if the @c T template parameter in+ * the specialisation is a user-defined type. The template parameter @c+ * Executor shall be a type meeting the Executor requirements.+ *+ * Specialisations shall meet the following requirements, where @c t is a const+ * reference to an object of type @c T, and @c e is an object of type @c+ * Executor.+ *+ * @li Provide a nested typedef @c type that identifies a type meeting the+ * Executor requirements.+ *+ * @li Provide a noexcept static member function named @c get, callable as @c+ * get(t) and with return type @c type or a (possibly const) reference to @c+ * type.+ *+ * @li Provide a noexcept static member function named @c get, callable as @c+ * get(t,e) and with return type @c type or a (possibly const) reference to @c+ * type.+ */+template <typename T, typename Executor>+struct associated_immediate_executor+#if !defined(GENERATING_DOCUMENTATION)+ : detail::associated_immediate_executor_impl<T, Executor>+#endif // !defined(GENERATING_DOCUMENTATION)+{+#if defined(GENERATING_DOCUMENTATION)+ /// If @c T has a nested type @c immediate_executor_type,+ // <tt>T::immediate_executor_type</tt>. Otherwise @c Executor.+ typedef see_below type;++ /// If @c T has a nested type @c immediate_executor_type, returns+ /// <tt>t.get_immediate_executor()</tt>. Otherwise returns+ /// <tt>asio::require(ex, asio::execution::blocking.never)</tt>.+ static decltype(auto) get(const T& t, const Executor& ex) ASIO_NOEXCEPT;+#endif // defined(GENERATING_DOCUMENTATION)+};++/// Helper function to obtain an object's associated executor.+/**+ * @returns <tt>associated_immediate_executor<T, Executor>::get(t, ex)</tt>+ */+template <typename T, typename Executor>+ASIO_NODISCARD inline ASIO_AUTO_RETURN_TYPE_PREFIX2(+ typename associated_immediate_executor<T, Executor>::type)+get_associated_immediate_executor(const T& t, const Executor& ex,+ typename constraint<+ is_executor<Executor>::value || execution::is_executor<Executor>::value+ >::type = 0) ASIO_NOEXCEPT+ ASIO_AUTO_RETURN_TYPE_SUFFIX((+ associated_immediate_executor<T, Executor>::get(t, ex)))+{+ return associated_immediate_executor<T, Executor>::get(t, ex);+}++/// Helper function to obtain an object's associated executor.+/**+ * @returns <tt>associated_immediate_executor<T, typename+ * ExecutionContext::executor_type>::get(t, ctx.get_executor())</tt>+ */+template <typename T, typename ExecutionContext>+ASIO_NODISCARD inline typename associated_immediate_executor<T,+ typename ExecutionContext::executor_type>::type+get_associated_immediate_executor(const T& t, ExecutionContext& ctx,+ typename constraint<is_convertible<ExecutionContext&,+ execution_context&>::value>::type = 0) ASIO_NOEXCEPT+{+ return associated_immediate_executor<T,+ typename ExecutionContext::executor_type>::get(t, ctx.get_executor());+}++#if defined(ASIO_HAS_ALIAS_TEMPLATES)++template <typename T, typename Executor>+using associated_immediate_executor_t =+ typename associated_immediate_executor<T, Executor>::type;++#endif // defined(ASIO_HAS_ALIAS_TEMPLATES)++namespace detail {++template <typename T, typename E, typename = void>+struct associated_immediate_executor_forwarding_base+{+};++template <typename T, typename E>+struct associated_immediate_executor_forwarding_base<T, E,+ typename enable_if<+ is_same<+ typename associated_immediate_executor<T,+ E>::asio_associated_immediate_executor_is_unspecialised,+ void+ >::value+ >::type>+{+ typedef void asio_associated_immediate_executor_is_unspecialised;+};++} // namespace detail++#if defined(ASIO_HAS_STD_REFERENCE_WRAPPER) \+ || defined(GENERATING_DOCUMENTATION)++/// Specialisation of associated_immediate_executor for+/// @c std::reference_wrapper.+template <typename T, typename Executor>+struct associated_immediate_executor<reference_wrapper<T>, Executor>+#if !defined(GENERATING_DOCUMENTATION)+ : detail::associated_immediate_executor_forwarding_base<T, Executor>+#endif // !defined(GENERATING_DOCUMENTATION)+{+ /// Forwards @c type to the associator specialisation for the unwrapped type+ /// @c T.+ typedef typename associated_immediate_executor<T, Executor>::type type;++ /// Forwards the request to get the executor to the associator specialisation+ /// for the unwrapped type @c T.+ static ASIO_AUTO_RETURN_TYPE_PREFIX(type) get(+ reference_wrapper<T> t, const Executor& ex) ASIO_NOEXCEPT+ ASIO_AUTO_RETURN_TYPE_SUFFIX((+ associated_immediate_executor<T, Executor>::get(t.get(), ex)))+ {+ return associated_immediate_executor<T, Executor>::get(t.get(), ex);+ }+};++#endif // defined(ASIO_HAS_STD_REFERENCE_WRAPPER)+ // || defined(GENERATING_DOCUMENTATION)++} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // ASIO_ASSOCIATED_IMMEDIATE_EXECUTOR_HPP
+ link/modules/asio-standalone/asio/include/asio/associator.hpp view
@@ -0,0 +1,35 @@+//+// associator.hpp+// ~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com)+//+// Distributed under the Boost Software License, Version 1.0. (See accompanying+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)+//++#ifndef ASIO_ASSOCIATOR_HPP+#define ASIO_ASSOCIATOR_HPP++#if defined(_MSC_VER) && (_MSC_VER >= 1200)+# pragma once+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)++#include "asio/detail/config.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {++/// Used to generically specialise associators for a type.+template <template <typename, typename> class Associator,+ typename T, typename DefaultCandidate>+struct associator+{+};++} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // ASIO_ASSOCIATOR_HPP
link/modules/asio-standalone/asio/include/asio/async_result.hpp view
@@ -2,513 +2,1602 @@ // async_result.hpp // ~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)-//-// Distributed under the Boost Software License, Version 1.0. (See accompanying-// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)-//--#ifndef ASIO_ASYNC_RESULT_HPP-#define ASIO_ASYNC_RESULT_HPP--#if defined(_MSC_VER) && (_MSC_VER >= 1200)-# pragma once-#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)--#include "asio/detail/config.hpp"-#include "asio/detail/type_traits.hpp"-#include "asio/detail/variadic_templates.hpp"--#include "asio/detail/push_options.hpp"--namespace asio {--#if defined(ASIO_HAS_CONCEPTS) \- && defined(ASIO_HAS_VARIADIC_TEMPLATES) \- && defined(ASIO_HAS_DECLTYPE)--namespace detail {--template <typename T>-struct is_completion_signature : false_type-{-};--template <typename R, typename... Args>-struct is_completion_signature<R(Args...)> : true_type-{-};--template <typename T, typename... Args>-ASIO_CONCEPT callable_with = requires(T t, Args&&... args)-{- t(static_cast<Args&&>(args)...);-};--template <typename T, typename Signature>-struct is_completion_handler_for : false_type-{-};--template <typename T, typename R, typename... Args>-struct is_completion_handler_for<T, R(Args...)>- : integral_constant<bool, (callable_with<T, Args...>)>-{-};--} // namespace detail--template <typename T>-ASIO_CONCEPT completion_signature =- detail::is_completion_signature<T>::value;--#define ASIO_COMPLETION_SIGNATURE \- ::asio::completion_signature--template <typename T, typename Signature>-ASIO_CONCEPT completion_handler_for =- detail::is_completion_signature<Signature>::value- && detail::is_completion_handler_for<T, Signature>::value;--#define ASIO_COMPLETION_HANDLER_FOR(s) \- ::asio::completion_handler_for<s>--#else // defined(ASIO_HAS_CONCEPTS)- // && defined(ASIO_HAS_VARIADIC_TEMPLATES)- // && defined(ASIO_HAS_DECLTYPE)--#define ASIO_COMPLETION_SIGNATURE typename-#define ASIO_COMPLETION_HANDLER_FOR(s) typename--#endif // defined(ASIO_HAS_CONCEPTS)- // && defined(ASIO_HAS_VARIADIC_TEMPLATES)- // && defined(ASIO_HAS_DECLTYPE)--/// An interface for customising the behaviour of an initiating function.-/**- * The async_result traits class is used for determining:- *- * @li the concrete completion handler type to be called at the end of the- * asynchronous operation;- *- * @li the initiating function return type; and- *- * @li how the return value of the initiating function is obtained.- *- * The trait allows the handler and return types to be determined at the point- * where the specific completion handler signature is known.- *- * This template may be specialised for user-defined completion token types.- * The primary template assumes that the CompletionToken is the completion- * handler.- */-template <typename CompletionToken, ASIO_COMPLETION_SIGNATURE Signature>-class async_result-{-public:- /// The concrete completion handler type for the specific signature.- typedef CompletionToken completion_handler_type;-- /// The return type of the initiating function.- typedef void return_type;-- /// Construct an async result from a given handler.- /**- * When using a specalised async_result, the constructor has an opportunity- * to initialise some state associated with the completion handler, which is- * then returned from the initiating function.- */- explicit async_result(completion_handler_type& h)- {- (void)h;- }-- /// Obtain the value to be returned from the initiating function.- return_type get()- {- }--#if defined(GENERATING_DOCUMENTATION)-- /// Initiate the asynchronous operation that will produce the result, and- /// obtain the value to be returned from the initiating function.- template <typename Initiation, typename RawCompletionToken, typename... Args>- static return_type initiate(- ASIO_MOVE_ARG(Initiation) initiation,- ASIO_MOVE_ARG(RawCompletionToken) token,- ASIO_MOVE_ARG(Args)... args);--#elif defined(ASIO_HAS_VARIADIC_TEMPLATES)-- template <typename Initiation,- ASIO_COMPLETION_HANDLER_FOR(Signature) RawCompletionToken,- typename... Args>- static return_type initiate(- ASIO_MOVE_ARG(Initiation) initiation,- ASIO_MOVE_ARG(RawCompletionToken) token,- ASIO_MOVE_ARG(Args)... args)- {- ASIO_MOVE_CAST(Initiation)(initiation)(- ASIO_MOVE_CAST(RawCompletionToken)(token),- ASIO_MOVE_CAST(Args)(args)...);- }--#else // defined(ASIO_HAS_VARIADIC_TEMPLATES)-- template <typename Initiation,- ASIO_COMPLETION_HANDLER_FOR(Signature) RawCompletionToken>- static return_type initiate(- ASIO_MOVE_ARG(Initiation) initiation,- ASIO_MOVE_ARG(RawCompletionToken) token)- {- ASIO_MOVE_CAST(Initiation)(initiation)(- ASIO_MOVE_CAST(RawCompletionToken)(token));- }--#define ASIO_PRIVATE_INITIATE_DEF(n) \- template <typename Initiation, \- ASIO_COMPLETION_HANDLER_FOR(Signature) RawCompletionToken, \- ASIO_VARIADIC_TPARAMS(n)> \- static return_type initiate( \- ASIO_MOVE_ARG(Initiation) initiation, \- ASIO_MOVE_ARG(RawCompletionToken) token, \- ASIO_VARIADIC_MOVE_PARAMS(n)) \- { \- ASIO_MOVE_CAST(Initiation)(initiation)( \- ASIO_MOVE_CAST(RawCompletionToken)(token), \- ASIO_VARIADIC_MOVE_ARGS(n)); \- } \- /**/- ASIO_VARIADIC_GENERATE(ASIO_PRIVATE_INITIATE_DEF)-#undef ASIO_PRIVATE_INITIATE_DEF--#endif // defined(ASIO_HAS_VARIADIC_TEMPLATES)--private:- async_result(const async_result&) ASIO_DELETED;- async_result& operator=(const async_result&) ASIO_DELETED;-};--#if !defined(GENERATING_DOCUMENTATION)--template <ASIO_COMPLETION_SIGNATURE Signature>-class async_result<void, Signature>-{- // Empty.-};--#endif // !defined(GENERATING_DOCUMENTATION)--/// Helper template to deduce the handler type from a CompletionToken, capture-/// a local copy of the handler, and then create an async_result for the-/// handler.-template <typename CompletionToken, ASIO_COMPLETION_SIGNATURE Signature>-struct async_completion-{- /// The real handler type to be used for the asynchronous operation.- typedef typename asio::async_result<- typename decay<CompletionToken>::type,- Signature>::completion_handler_type completion_handler_type;--#if defined(ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)- /// Constructor.- /**- * The constructor creates the concrete completion handler and makes the link- * between the handler and the asynchronous result.- */- explicit async_completion(CompletionToken& token)- : completion_handler(static_cast<typename conditional<- is_same<CompletionToken, completion_handler_type>::value,- completion_handler_type&, CompletionToken&&>::type>(token)),- result(completion_handler)- {- }-#else // defined(ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)- explicit async_completion(typename decay<CompletionToken>::type& token)- : completion_handler(token),- result(completion_handler)- {- }-- explicit async_completion(const typename decay<CompletionToken>::type& token)- : completion_handler(token),- result(completion_handler)- {- }-#endif // defined(ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)-- /// A copy of, or reference to, a real handler object.-#if defined(ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)- typename conditional<- is_same<CompletionToken, completion_handler_type>::value,- completion_handler_type&, completion_handler_type>::type completion_handler;-#else // defined(ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)- completion_handler_type completion_handler;-#endif // defined(ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)-- /// The result of the asynchronous operation's initiating function.- async_result<typename decay<CompletionToken>::type, Signature> result;-};--namespace detail {--template <typename CompletionToken, typename Signature>-struct async_result_helper- : async_result<typename decay<CompletionToken>::type, Signature>-{-};--struct async_result_memfns_base-{- void initiate();-};--template <typename T>-struct async_result_memfns_derived- : T, async_result_memfns_base-{-};--template <typename T, T>-struct async_result_memfns_check-{-};--template <typename>-char (&async_result_initiate_memfn_helper(...))[2];--template <typename T>-char async_result_initiate_memfn_helper(- async_result_memfns_check<- void (async_result_memfns_base::*)(),- &async_result_memfns_derived<T>::initiate>*);--template <typename CompletionToken, typename Signature>-struct async_result_has_initiate_memfn- : integral_constant<bool, sizeof(async_result_initiate_memfn_helper<- async_result<typename decay<CompletionToken>::type, Signature>- >(0)) != 1>-{-};--} // namespace detail--#if defined(GENERATING_DOCUMENTATION)-# define ASIO_INITFN_RESULT_TYPE(ct, sig) \- void_or_deduced-#elif defined(_MSC_VER) && (_MSC_VER < 1500)-# define ASIO_INITFN_RESULT_TYPE(ct, sig) \- typename ::asio::detail::async_result_helper< \- ct, sig>::return_type-#define ASIO_HANDLER_TYPE(ct, sig) \- typename ::asio::detail::async_result_helper< \- ct, sig>::completion_handler_type-#else-# define ASIO_INITFN_RESULT_TYPE(ct, sig) \- typename ::asio::async_result< \- typename ::asio::decay<ct>::type, sig>::return_type-#define ASIO_HANDLER_TYPE(ct, sig) \- typename ::asio::async_result< \- typename ::asio::decay<ct>::type, sig>::completion_handler_type-#endif--#if defined(GENERATION_DOCUMENTATION)-# define ASIO_INITFN_AUTO_RESULT_TYPE(ct, sig) \- auto-#elif defined(ASIO_HAS_RETURN_TYPE_DEDUCTION)-# define ASIO_INITFN_AUTO_RESULT_TYPE(ct, sig) \- auto-#else-# define ASIO_INITFN_AUTO_RESULT_TYPE(ct, sig) \- ASIO_INITFN_RESULT_TYPE(ct, sig)-#endif--#if defined(GENERATION_DOCUMENTATION)-# define ASIO_INITFN_DEDUCED_RESULT_TYPE(ct, sig, expr) \- void_or_deduced-#elif defined(ASIO_HAS_DECLTYPE)-# define ASIO_INITFN_DEDUCED_RESULT_TYPE(ct, sig, expr) \- decltype expr-#else-# define ASIO_INITFN_DEDUCED_RESULT_TYPE(ct, sig, expr) \- ASIO_INITFN_RESULT_TYPE(ct, sig)-#endif--#if defined(GENERATING_DOCUMENTATION)--template <typename CompletionToken,- completion_signature Signature,- typename Initiation, typename... Args>-void_or_deduced async_initiate(- ASIO_MOVE_ARG(Initiation) initiation,- ASIO_NONDEDUCED_MOVE_ARG(CompletionToken),- ASIO_MOVE_ARG(Args)... args);--#elif defined(ASIO_HAS_VARIADIC_TEMPLATES)--template <typename CompletionToken,- ASIO_COMPLETION_SIGNATURE Signature,- typename Initiation, typename... Args>-inline typename enable_if<- detail::async_result_has_initiate_memfn<CompletionToken, Signature>::value,- ASIO_INITFN_DEDUCED_RESULT_TYPE(CompletionToken, Signature,- (async_result<typename decay<CompletionToken>::type,- Signature>::initiate(declval<ASIO_MOVE_ARG(Initiation)>(),- declval<ASIO_MOVE_ARG(CompletionToken)>(),- declval<ASIO_MOVE_ARG(Args)>()...)))>::type-async_initiate(ASIO_MOVE_ARG(Initiation) initiation,- ASIO_NONDEDUCED_MOVE_ARG(CompletionToken) token,- ASIO_MOVE_ARG(Args)... args)-{- return async_result<typename decay<CompletionToken>::type,- Signature>::initiate(ASIO_MOVE_CAST(Initiation)(initiation),- ASIO_MOVE_CAST(CompletionToken)(token),- ASIO_MOVE_CAST(Args)(args)...);-}--template <typename CompletionToken,- ASIO_COMPLETION_SIGNATURE Signature,- typename Initiation, typename... Args>-inline typename enable_if<- !detail::async_result_has_initiate_memfn<CompletionToken, Signature>::value,- ASIO_INITFN_RESULT_TYPE(CompletionToken, Signature)>::type-async_initiate(ASIO_MOVE_ARG(Initiation) initiation,- ASIO_NONDEDUCED_MOVE_ARG(CompletionToken) token,- ASIO_MOVE_ARG(Args)... args)-{- async_completion<CompletionToken, Signature> completion(token);-- ASIO_MOVE_CAST(Initiation)(initiation)(- ASIO_MOVE_CAST(ASIO_HANDLER_TYPE(CompletionToken,- Signature))(completion.completion_handler),- ASIO_MOVE_CAST(Args)(args)...);-- return completion.result.get();-}--#else // defined(ASIO_HAS_VARIADIC_TEMPLATES)--template <typename CompletionToken,- ASIO_COMPLETION_SIGNATURE Signature,- typename Initiation>-inline typename enable_if<- detail::async_result_has_initiate_memfn<CompletionToken, Signature>::value,- ASIO_INITFN_DEDUCED_RESULT_TYPE(CompletionToken, Signature,- (async_result<typename decay<CompletionToken>::type,- Signature>::initiate(declval<ASIO_MOVE_ARG(Initiation)>(),- declval<ASIO_MOVE_ARG(CompletionToken)>())))>::type-async_initiate(ASIO_MOVE_ARG(Initiation) initiation,- ASIO_NONDEDUCED_MOVE_ARG(CompletionToken) token)-{- return async_result<typename decay<CompletionToken>::type,- Signature>::initiate(ASIO_MOVE_CAST(Initiation)(initiation),- ASIO_MOVE_CAST(CompletionToken)(token));-}--template <typename CompletionToken,- ASIO_COMPLETION_SIGNATURE Signature,- typename Initiation>-inline typename enable_if<- !detail::async_result_has_initiate_memfn<CompletionToken, Signature>::value,- ASIO_INITFN_RESULT_TYPE(CompletionToken, Signature)>::type-async_initiate(ASIO_MOVE_ARG(Initiation) initiation,- ASIO_NONDEDUCED_MOVE_ARG(CompletionToken) token)-{- async_completion<CompletionToken, Signature> completion(token);-- ASIO_MOVE_CAST(Initiation)(initiation)(- ASIO_MOVE_CAST(ASIO_HANDLER_TYPE(CompletionToken,- Signature))(completion.completion_handler));-- return completion.result.get();-}--#define ASIO_PRIVATE_INITIATE_DEF(n) \- template <typename CompletionToken, \- ASIO_COMPLETION_SIGNATURE Signature, \- typename Initiation, ASIO_VARIADIC_TPARAMS(n)> \- inline typename enable_if< \- detail::async_result_has_initiate_memfn< \- CompletionToken, Signature>::value, \- ASIO_INITFN_DEDUCED_RESULT_TYPE(CompletionToken, Signature, \- (async_result<typename decay<CompletionToken>::type, \- Signature>::initiate(declval<ASIO_MOVE_ARG(Initiation)>(), \- declval<ASIO_MOVE_ARG(CompletionToken)>(), \- ASIO_VARIADIC_MOVE_DECLVAL(n))))>::type \- async_initiate(ASIO_MOVE_ARG(Initiation) initiation, \- ASIO_NONDEDUCED_MOVE_ARG(CompletionToken) token, \- ASIO_VARIADIC_MOVE_PARAMS(n)) \- { \- return async_result<typename decay<CompletionToken>::type, \- Signature>::initiate(ASIO_MOVE_CAST(Initiation)(initiation), \- ASIO_MOVE_CAST(CompletionToken)(token), \- ASIO_VARIADIC_MOVE_ARGS(n)); \- } \- \- template <typename CompletionToken, \- ASIO_COMPLETION_SIGNATURE Signature, \- typename Initiation, ASIO_VARIADIC_TPARAMS(n)> \- inline typename enable_if< \- !detail::async_result_has_initiate_memfn< \- CompletionToken, Signature>::value, \- ASIO_INITFN_RESULT_TYPE(CompletionToken, Signature)>::type \- async_initiate(ASIO_MOVE_ARG(Initiation) initiation, \- ASIO_NONDEDUCED_MOVE_ARG(CompletionToken) token, \- ASIO_VARIADIC_MOVE_PARAMS(n)) \- { \- async_completion<CompletionToken, Signature> completion(token); \- \- ASIO_MOVE_CAST(Initiation)(initiation)( \- ASIO_MOVE_CAST(ASIO_HANDLER_TYPE(CompletionToken, \- Signature))(completion.completion_handler), \- ASIO_VARIADIC_MOVE_ARGS(n)); \- \- return completion.result.get(); \- } \- /**/- ASIO_VARIADIC_GENERATE(ASIO_PRIVATE_INITIATE_DEF)-#undef ASIO_PRIVATE_INITIATE_DEF--#endif // defined(ASIO_HAS_VARIADIC_TEMPLATES)--#if defined(ASIO_HAS_CONCEPTS) \- && defined(ASIO_HAS_VARIADIC_TEMPLATES) \- && defined(ASIO_HAS_DECLTYPE)--namespace detail {--template <typename Signature>-struct initiation_archetype-{- template <completion_handler_for<Signature> CompletionHandler>- void operator()(CompletionHandler&&) const- {- }-};--} // namespace detail--template <typename T, typename Signature>-ASIO_CONCEPT completion_token_for =- detail::is_completion_signature<Signature>::value- &&- requires(T&& t)- {- async_initiate<T, Signature>(detail::initiation_archetype<Signature>{}, t);- };--#define ASIO_COMPLETION_TOKEN_FOR(s) \- ::asio::completion_token_for<s>--#else // defined(ASIO_HAS_CONCEPTS)- // && defined(ASIO_HAS_VARIADIC_TEMPLATES)- // && defined(ASIO_HAS_DECLTYPE)--#define ASIO_COMPLETION_TOKEN_FOR(s) typename--#endif // defined(ASIO_HAS_CONCEPTS)- // && defined(ASIO_HAS_VARIADIC_TEMPLATES)- // && defined(ASIO_HAS_DECLTYPE)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com)+//+// Distributed under the Boost Software License, Version 1.0. (See accompanying+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)+//++#ifndef ASIO_ASYNC_RESULT_HPP+#define ASIO_ASYNC_RESULT_HPP++#if defined(_MSC_VER) && (_MSC_VER >= 1200)+# pragma once+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)++#include "asio/detail/config.hpp"+#include "asio/detail/type_traits.hpp"+#include "asio/detail/variadic_templates.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {++#if defined(ASIO_HAS_CONCEPTS) \+ && defined(ASIO_HAS_VARIADIC_TEMPLATES) \+ && defined(ASIO_HAS_DECLTYPE)++namespace detail {++template <typename T>+struct is_completion_signature : false_type+{+};++template <typename R, typename... Args>+struct is_completion_signature<R(Args...)> : true_type+{+};++#if defined(ASIO_HAS_REF_QUALIFIED_FUNCTIONS)++template <typename R, typename... Args>+struct is_completion_signature<R(Args...) &> : true_type+{+};++template <typename R, typename... Args>+struct is_completion_signature<R(Args...) &&> : true_type+{+};++# if defined(ASIO_HAS_NOEXCEPT_FUNCTION_TYPE)++template <typename R, typename... Args>+struct is_completion_signature<R(Args...) noexcept> : true_type+{+};++template <typename R, typename... Args>+struct is_completion_signature<R(Args...) & noexcept> : true_type+{+};++template <typename R, typename... Args>+struct is_completion_signature<R(Args...) && noexcept> : true_type+{+};++# endif // defined(ASIO_HAS_NOEXCEPT_FUNCTION_TYPE)+#endif // defined(ASIO_HAS_REF_QUALIFIED_FUNCTIONS)++template <typename... T>+struct are_completion_signatures : false_type+{+};++template <typename T0>+struct are_completion_signatures<T0>+ : is_completion_signature<T0>+{+};++template <typename T0, typename... TN>+struct are_completion_signatures<T0, TN...>+ : integral_constant<bool, (+ is_completion_signature<T0>::value+ && are_completion_signatures<TN...>::value)>+{+};++template <typename T, typename... Args>+ASIO_CONCEPT callable_with = requires(T&& t, Args&&... args)+{+ static_cast<T&&>(t)(static_cast<Args&&>(args)...);+};++template <typename T, typename... Signatures>+struct is_completion_handler_for : false_type+{+};++template <typename T, typename R, typename... Args>+struct is_completion_handler_for<T, R(Args...)>+ : integral_constant<bool, (callable_with<T, Args...>)>+{+};++#if defined(ASIO_HAS_REF_QUALIFIED_FUNCTIONS)++template <typename T, typename R, typename... Args>+struct is_completion_handler_for<T, R(Args...) &>+ : integral_constant<bool, (callable_with<T&, Args...>)>+{+};++template <typename T, typename R, typename... Args>+struct is_completion_handler_for<T, R(Args...) &&>+ : integral_constant<bool, (callable_with<T&&, Args...>)>+{+};++# if defined(ASIO_HAS_NOEXCEPT_FUNCTION_TYPE)++template <typename T, typename R, typename... Args>+struct is_completion_handler_for<T, R(Args...) noexcept>+ : integral_constant<bool, (callable_with<T, Args...>)>+{+};++template <typename T, typename R, typename... Args>+struct is_completion_handler_for<T, R(Args...) & noexcept>+ : integral_constant<bool, (callable_with<T&, Args...>)>+{+};++template <typename T, typename R, typename... Args>+struct is_completion_handler_for<T, R(Args...) && noexcept>+ : integral_constant<bool, (callable_with<T&&, Args...>)>+{+};++# endif // defined(ASIO_HAS_NOEXCEPT_FUNCTION_TYPE)+#endif // defined(ASIO_HAS_REF_QUALIFIED_FUNCTIONS)++template <typename T, typename Signature0, typename... SignatureN>+struct is_completion_handler_for<T, Signature0, SignatureN...>+ : integral_constant<bool, (+ is_completion_handler_for<T, Signature0>::value+ && is_completion_handler_for<T, SignatureN...>::value)>+{+};++} // namespace detail++template <typename T>+ASIO_CONCEPT completion_signature =+ detail::is_completion_signature<T>::value;++#define ASIO_COMPLETION_SIGNATURE \+ ::asio::completion_signature++template <typename T, typename... Signatures>+ASIO_CONCEPT completion_handler_for =+ detail::are_completion_signatures<Signatures...>::value+ && detail::is_completion_handler_for<T, Signatures...>::value;++#define ASIO_COMPLETION_HANDLER_FOR(sig) \+ ::asio::completion_handler_for<sig>+#define ASIO_COMPLETION_HANDLER_FOR2(sig0, sig1) \+ ::asio::completion_handler_for<sig0, sig1>+#define ASIO_COMPLETION_HANDLER_FOR3(sig0, sig1, sig2) \+ ::asio::completion_handler_for<sig0, sig1, sig2>++#else // defined(ASIO_HAS_CONCEPTS)+ // && defined(ASIO_HAS_VARIADIC_TEMPLATES)+ // && defined(ASIO_HAS_DECLTYPE)++#define ASIO_COMPLETION_SIGNATURE typename+#define ASIO_COMPLETION_HANDLER_FOR(sig) typename+#define ASIO_COMPLETION_HANDLER_FOR2(sig0, sig1) typename+#define ASIO_COMPLETION_HANDLER_FOR3(sig0, sig1, sig2) typename++#endif // defined(ASIO_HAS_CONCEPTS)+ // && defined(ASIO_HAS_VARIADIC_TEMPLATES)+ // && defined(ASIO_HAS_DECLTYPE)++namespace detail {++template <typename T>+struct is_simple_completion_signature : false_type+{+};++template <typename T>+struct simple_completion_signature;++#if defined(ASIO_HAS_VARIADIC_TEMPLATES)++template <typename R, typename... Args>+struct is_simple_completion_signature<R(Args...)> : true_type+{+};++template <typename... Signatures>+struct are_simple_completion_signatures : false_type+{+};++template <typename Sig0>+struct are_simple_completion_signatures<Sig0>+ : is_simple_completion_signature<Sig0>+{+};++template <typename Sig0, typename... SigN>+struct are_simple_completion_signatures<Sig0, SigN...>+ : integral_constant<bool, (+ is_simple_completion_signature<Sig0>::value+ && are_simple_completion_signatures<SigN...>::value)>+{+};++template <typename R, typename... Args>+struct simple_completion_signature<R(Args...)>+{+ typedef R type(Args...);+};++#if defined(ASIO_HAS_REF_QUALIFIED_FUNCTIONS)++template <typename R, typename... Args>+struct simple_completion_signature<R(Args...) &>+{+ typedef R type(Args...);+};++template <typename R, typename... Args>+struct simple_completion_signature<R(Args...) &&>+{+ typedef R type(Args...);+};++# if defined(ASIO_HAS_NOEXCEPT_FUNCTION_TYPE)++template <typename R, typename... Args>+struct simple_completion_signature<R(Args...) noexcept>+{+ typedef R type(Args...);+};++template <typename R, typename... Args>+struct simple_completion_signature<R(Args...) & noexcept>+{+ typedef R type(Args...);+};++template <typename R, typename... Args>+struct simple_completion_signature<R(Args...) && noexcept>+{+ typedef R type(Args...);+};++# endif // defined(ASIO_HAS_NOEXCEPT_FUNCTION_TYPE)+#endif // defined(ASIO_HAS_REF_QUALIFIED_FUNCTIONS)++#else // defined(ASIO_HAS_VARIADIC_TEMPLATES)++template <typename R>+struct is_simple_completion_signature<R()> : true_type+{+};++#define ASIO_PRIVATE_SIMPLE_SIG_DEF(n) \+ template <typename R, ASIO_VARIADIC_TPARAMS(n)> \+ struct is_simple_completion_signature<R(ASIO_VARIADIC_TARGS(n))> \+ : true_type \+ { \+ }; \+ /**/+ ASIO_VARIADIC_GENERATE(ASIO_PRIVATE_SIMPLE_SIG_DEF)+#undef ASIO_PRIVATE_SIMPLE_SIG_DEF++template <typename Sig0 = void, typename Sig1 = void,+ typename Sig2 = void, typename = void>+struct are_simple_completion_signatures : false_type+{+};++template <typename Sig0>+struct are_simple_completion_signatures<Sig0>+ : is_simple_completion_signature<Sig0>+{+};++template <typename Sig0, typename Sig1>+struct are_simple_completion_signatures<Sig0, Sig1>+ : integral_constant<bool,+ (is_simple_completion_signature<Sig0>::value+ && is_simple_completion_signature<Sig1>::value)>+{+};++template <typename Sig0, typename Sig1, typename Sig2>+struct are_simple_completion_signatures<Sig0, Sig1, Sig2>+ : integral_constant<bool,+ (is_simple_completion_signature<Sig0>::value+ && is_simple_completion_signature<Sig1>::value+ && is_simple_completion_signature<Sig2>::value)>+{+};++template <>+struct simple_completion_signature<void>+{+ typedef void type;+};++template <typename R>+struct simple_completion_signature<R()>+{+ typedef R type();+};++#define ASIO_PRIVATE_SIMPLE_SIG_DEF(n) \+ template <typename R, ASIO_VARIADIC_TPARAMS(n)> \+ struct simple_completion_signature<R(ASIO_VARIADIC_TARGS(n))> \+ { \+ typedef R type(ASIO_VARIADIC_TARGS(n)); \+ }; \+ /**/+ ASIO_VARIADIC_GENERATE(ASIO_PRIVATE_SIMPLE_SIG_DEF)+#undef ASIO_PRIVATE_SIMPLE_SIG_DEF++#if defined(ASIO_HAS_REF_QUALIFIED_FUNCTIONS)++template <typename R>+struct simple_completion_signature<R() &>+{+ typedef R type();+};++template <typename R>+struct simple_completion_signature<R() &&>+{+ typedef R type();+};++#define ASIO_PRIVATE_SIMPLE_SIG_DEF(n) \+ template <typename R, ASIO_VARIADIC_TPARAMS(n)> \+ struct simple_completion_signature< \+ R(ASIO_VARIADIC_TARGS(n)) &> \+ { \+ typedef R type(ASIO_VARIADIC_TARGS(n)); \+ }; \+ \+ template <typename R, ASIO_VARIADIC_TPARAMS(n)> \+ struct simple_completion_signature< \+ R(ASIO_VARIADIC_TARGS(n)) &&> \+ { \+ typedef R type(ASIO_VARIADIC_TARGS(n)); \+ }; \+ /**/+ ASIO_VARIADIC_GENERATE(ASIO_PRIVATE_SIMPLE_SIG_DEF)+#undef ASIO_PRIVATE_SIMPLE_SIG_DEF++# if defined(ASIO_HAS_NOEXCEPT_FUNCTION_TYPE)++template <typename R>+struct simple_completion_signature<R() noexcept>+{+ typedef R type();+};++template <typename R>+struct simple_completion_signature<R() & noexcept>+{+ typedef R type();+};++template <typename R>+struct simple_completion_signature<R() && noexcept>+{+ typedef R type();+};++#define ASIO_PRIVATE_SIMPLE_SIG_DEF(n) \+ template <typename R, ASIO_VARIADIC_TPARAMS(n)> \+ struct simple_completion_signature< \+ R(ASIO_VARIADIC_TARGS(n)) noexcept> \+ { \+ typedef R type(ASIO_VARIADIC_TARGS(n)); \+ }; \+ \+ template <typename R, ASIO_VARIADIC_TPARAMS(n)> \+ struct simple_completion_signature< \+ R(ASIO_VARIADIC_TARGS(n)) & noexcept> \+ { \+ typedef R type(ASIO_VARIADIC_TARGS(n)); \+ }; \+ \+ template <typename R, ASIO_VARIADIC_TPARAMS(n)> \+ struct simple_completion_signature< \+ R(ASIO_VARIADIC_TARGS(n)) && noexcept> \+ { \+ typedef R type(ASIO_VARIADIC_TARGS(n)); \+ }; \+ /**/+ ASIO_VARIADIC_GENERATE(ASIO_PRIVATE_SIMPLE_SIG_DEF)+#undef ASIO_PRIVATE_SIMPLE_SIG_DEF++# endif // defined(ASIO_HAS_NOEXCEPT_FUNCTION_TYPE)+#endif // defined(ASIO_HAS_REF_QUALIFIED_FUNCTIONS)++#endif // defined(ASIO_HAS_VARIADIC_TEMPLATES)++#if defined(ASIO_HAS_VARIADIC_TEMPLATES) \+ || defined(GENERATING_DOCUMENTATION)++# define ASIO_COMPLETION_SIGNATURES_TPARAMS \+ ASIO_COMPLETION_SIGNATURE... Signatures++# define ASIO_COMPLETION_SIGNATURES_TSPECPARAMS \+ ASIO_COMPLETION_SIGNATURE... Signatures++# define ASIO_COMPLETION_SIGNATURES_TARGS Signatures...++# define ASIO_COMPLETION_SIGNATURES_TSIMPLEARGS \+ typename asio::detail::simple_completion_signature< \+ Signatures>::type...++#else // defined(ASIO_HAS_VARIADIC_TEMPLATES)+ // || defined(GENERATING_DOCUMENTATION)++# define ASIO_COMPLETION_SIGNATURES_TPARAMS \+ typename Sig0 = void, \+ typename Sig1 = void, \+ typename Sig2 = void++# define ASIO_COMPLETION_SIGNATURES_TSPECPARAMS \+ typename Sig0, \+ typename Sig1, \+ typename Sig2++# define ASIO_COMPLETION_SIGNATURES_TARGS Sig0, Sig1, Sig2++# define ASIO_COMPLETION_SIGNATURES_TSIMPLEARGS \+ typename ::asio::detail::simple_completion_signature<Sig0>::type, \+ typename ::asio::detail::simple_completion_signature<Sig1>::type, \+ typename ::asio::detail::simple_completion_signature<Sig2>::type++#endif // defined(ASIO_HAS_VARIADIC_TEMPLATES)+ // || defined(GENERATING_DOCUMENTATION)++template <typename CompletionToken, ASIO_COMPLETION_SIGNATURES_TPARAMS>+class completion_handler_async_result+{+public:+ typedef CompletionToken completion_handler_type;+ typedef void return_type;++ explicit completion_handler_async_result(completion_handler_type&)+ {+ }++ return_type get()+ {+ }++#if defined(ASIO_HAS_VARIADIC_TEMPLATES)++ template <typename Initiation,+ ASIO_COMPLETION_HANDLER_FOR(Signatures...) RawCompletionToken,+ typename... Args>+ static return_type initiate(+ ASIO_MOVE_ARG(Initiation) initiation,+ ASIO_MOVE_ARG(RawCompletionToken) token,+ ASIO_MOVE_ARG(Args)... args)+ {+ ASIO_MOVE_CAST(Initiation)(initiation)(+ ASIO_MOVE_CAST(RawCompletionToken)(token),+ ASIO_MOVE_CAST(Args)(args)...);+ }++#else // defined(ASIO_HAS_VARIADIC_TEMPLATES)++ template <typename Initiation, typename RawCompletionToken>+ static return_type initiate(+ ASIO_MOVE_ARG(Initiation) initiation,+ ASIO_MOVE_ARG(RawCompletionToken) token)+ {+ ASIO_MOVE_CAST(Initiation)(initiation)(+ ASIO_MOVE_CAST(RawCompletionToken)(token));+ }++#define ASIO_PRIVATE_INITIATE_DEF(n) \+ template <typename Initiation, \+ typename RawCompletionToken, \+ ASIO_VARIADIC_TPARAMS(n)> \+ static return_type initiate( \+ ASIO_MOVE_ARG(Initiation) initiation, \+ ASIO_MOVE_ARG(RawCompletionToken) token, \+ ASIO_VARIADIC_MOVE_PARAMS(n)) \+ { \+ ASIO_MOVE_CAST(Initiation)(initiation)( \+ ASIO_MOVE_CAST(RawCompletionToken)(token), \+ ASIO_VARIADIC_MOVE_ARGS(n)); \+ } \+ /**/+ ASIO_VARIADIC_GENERATE(ASIO_PRIVATE_INITIATE_DEF)+#undef ASIO_PRIVATE_INITIATE_DEF++#endif // defined(ASIO_HAS_VARIADIC_TEMPLATES)++private:+ completion_handler_async_result(+ const completion_handler_async_result&) ASIO_DELETED;+ completion_handler_async_result& operator=(+ const completion_handler_async_result&) ASIO_DELETED;+};++} // namespace detail++#if defined(GENERATING_DOCUMENTATION)++/// An interface for customising the behaviour of an initiating function.+/**+ * The async_result traits class is used for determining:+ *+ * @li the concrete completion handler type to be called at the end of the+ * asynchronous operation;+ *+ * @li the initiating function return type; and+ *+ * @li how the return value of the initiating function is obtained.+ *+ * The trait allows the handler and return types to be determined at the point+ * where the specific completion handler signature is known.+ *+ * This template may be specialised for user-defined completion token types.+ * The primary template assumes that the CompletionToken is the completion+ * handler.+ */+template <typename CompletionToken, ASIO_COMPLETION_SIGNATURES_TPARAMS>+class async_result+{+public:+ /// The concrete completion handler type for the specific signature.+ typedef CompletionToken completion_handler_type;++ /// The return type of the initiating function.+ typedef void return_type;++ /// Construct an async result from a given handler.+ /**+ * When using a specalised async_result, the constructor has an opportunity+ * to initialise some state associated with the completion handler, which is+ * then returned from the initiating function.+ */+ explicit async_result(completion_handler_type& h);++ /// Obtain the value to be returned from the initiating function.+ return_type get();++ /// Initiate the asynchronous operation that will produce the result, and+ /// obtain the value to be returned from the initiating function.+ template <typename Initiation, typename RawCompletionToken, typename... Args>+ static return_type initiate(+ ASIO_MOVE_ARG(Initiation) initiation,+ ASIO_MOVE_ARG(RawCompletionToken) token,+ ASIO_MOVE_ARG(Args)... args);++private:+ async_result(const async_result&) ASIO_DELETED;+ async_result& operator=(const async_result&) ASIO_DELETED;+};++#else // defined(GENERATING_DOCUMENTATION)++#if defined(ASIO_HAS_REF_QUALIFIED_FUNCTIONS)++template <typename CompletionToken, ASIO_COMPLETION_SIGNATURES_TPARAMS>+class async_result :+ public conditional<+ detail::are_simple_completion_signatures<+ ASIO_COMPLETION_SIGNATURES_TARGS>::value,+ detail::completion_handler_async_result<+ CompletionToken, ASIO_COMPLETION_SIGNATURES_TARGS>,+ async_result<CompletionToken,+ ASIO_COMPLETION_SIGNATURES_TSIMPLEARGS>+ >::type+{+public:+ typedef typename conditional<+ detail::are_simple_completion_signatures<+ ASIO_COMPLETION_SIGNATURES_TARGS>::value,+ detail::completion_handler_async_result<+ CompletionToken, ASIO_COMPLETION_SIGNATURES_TARGS>,+ async_result<CompletionToken,+ ASIO_COMPLETION_SIGNATURES_TSIMPLEARGS>+ >::type base_type;++ using base_type::base_type;++private:+ async_result(const async_result&) ASIO_DELETED;+ async_result& operator=(const async_result&) ASIO_DELETED;+};++#else // defined(ASIO_HAS_REF_QUALIFIED_FUNCTIONS)++template <typename CompletionToken, ASIO_COMPLETION_SIGNATURES_TPARAMS>+class async_result :+ public detail::completion_handler_async_result<+ CompletionToken, ASIO_COMPLETION_SIGNATURES_TARGS>+{+public:+ explicit async_result(CompletionToken& h)+ : detail::completion_handler_async_result<+ CompletionToken, ASIO_COMPLETION_SIGNATURES_TARGS>(h)+ {+ }++private:+ async_result(const async_result&) ASIO_DELETED;+ async_result& operator=(const async_result&) ASIO_DELETED;+};++#endif // defined(ASIO_HAS_REF_QUALIFIED_FUNCTIONS)++template <ASIO_COMPLETION_SIGNATURES_TSPECPARAMS>+class async_result<void, ASIO_COMPLETION_SIGNATURES_TARGS>+{+ // Empty.+};++#endif // defined(GENERATING_DOCUMENTATION)++/// Helper template to deduce the handler type from a CompletionToken, capture+/// a local copy of the handler, and then create an async_result for the+/// handler.+template <typename CompletionToken, ASIO_COMPLETION_SIGNATURES_TPARAMS>+struct async_completion+{+ /// The real handler type to be used for the asynchronous operation.+ typedef typename asio::async_result<+ typename decay<CompletionToken>::type,+ ASIO_COMPLETION_SIGNATURES_TARGS>::completion_handler_type+ completion_handler_type;++#if defined(ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)+ /// Constructor.+ /**+ * The constructor creates the concrete completion handler and makes the link+ * between the handler and the asynchronous result.+ */+ explicit async_completion(CompletionToken& token)+ : completion_handler(static_cast<typename conditional<+ is_same<CompletionToken, completion_handler_type>::value,+ completion_handler_type&, CompletionToken&&>::type>(token)),+ result(completion_handler)+ {+ }+#else // defined(ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)+ explicit async_completion(typename decay<CompletionToken>::type& token)+ : completion_handler(token),+ result(completion_handler)+ {+ }++ explicit async_completion(const typename decay<CompletionToken>::type& token)+ : completion_handler(token),+ result(completion_handler)+ {+ }+#endif // defined(ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)++ /// A copy of, or reference to, a real handler object.+#if defined(ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)+ typename conditional<+ is_same<CompletionToken, completion_handler_type>::value,+ completion_handler_type&, completion_handler_type>::type completion_handler;+#else // defined(ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)+ completion_handler_type completion_handler;+#endif // defined(ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)++ /// The result of the asynchronous operation's initiating function.+ async_result<typename decay<CompletionToken>::type,+ ASIO_COMPLETION_SIGNATURES_TARGS> result;+};++namespace detail {++template <typename CompletionToken, ASIO_COMPLETION_SIGNATURES_TPARAMS>+struct async_result_helper+ : async_result<typename decay<CompletionToken>::type,+ ASIO_COMPLETION_SIGNATURES_TARGS>+{+};++struct async_result_memfns_base+{+ void initiate();+};++template <typename T>+struct async_result_memfns_derived+ : T, async_result_memfns_base+{+};++template <typename T, T>+struct async_result_memfns_check+{+};++template <typename>+char (&async_result_initiate_memfn_helper(...))[2];++template <typename T>+char async_result_initiate_memfn_helper(+ async_result_memfns_check<+ void (async_result_memfns_base::*)(),+ &async_result_memfns_derived<T>::initiate>*);++template <typename CompletionToken, ASIO_COMPLETION_SIGNATURES_TPARAMS>+struct async_result_has_initiate_memfn+ : integral_constant<bool, sizeof(async_result_initiate_memfn_helper<+ async_result<typename decay<CompletionToken>::type,+ ASIO_COMPLETION_SIGNATURES_TARGS>+ >(0)) != 1>+{+};++} // namespace detail++#if defined(GENERATING_DOCUMENTATION)+# define ASIO_INITFN_RESULT_TYPE(ct, sig) \+ void_or_deduced+# define ASIO_INITFN_RESULT_TYPE2(ct, sig0, sig1) \+ void_or_deduced+# define ASIO_INITFN_RESULT_TYPE3(ct, sig0, sig1, sig2) \+ void_or_deduced+#elif defined(_MSC_VER) && (_MSC_VER < 1500)+# define ASIO_INITFN_RESULT_TYPE(ct, sig) \+ typename ::asio::detail::async_result_helper< \+ ct, sig>::return_type+# define ASIO_INITFN_RESULT_TYPE2(ct, sig0, sig1) \+ typename ::asio::detail::async_result_helper< \+ ct, sig0, sig1>::return_type+# define ASIO_INITFN_RESULT_TYPE3(ct, sig0, sig1, sig2) \+ typename ::asio::detail::async_result_helper< \+ ct, sig0, sig1, sig2>::return_type+#define ASIO_HANDLER_TYPE(ct, sig) \+ typename ::asio::detail::async_result_helper< \+ ct, sig>::completion_handler_type+#define ASIO_HANDLER_TYPE2(ct, sig0, sig1) \+ typename ::asio::detail::async_result_helper< \+ ct, sig0, sig1>::completion_handler_type+#define ASIO_HANDLER_TYPE3(ct, sig0, sig1, sig2) \+ typename ::asio::detail::async_result_helper< \+ ct, sig0, sig1, sig2>::completion_handler_type+#else+# define ASIO_INITFN_RESULT_TYPE(ct, sig) \+ typename ::asio::async_result< \+ typename ::asio::decay<ct>::type, sig>::return_type+# define ASIO_INITFN_RESULT_TYPE2(ct, sig0, sig1) \+ typename ::asio::async_result< \+ typename ::asio::decay<ct>::type, sig0, sig1>::return_type+# define ASIO_INITFN_RESULT_TYPE3(ct, sig0, sig1, sig2) \+ typename ::asio::async_result< \+ typename ::asio::decay<ct>::type, sig0, sig1, sig2>::return_type+#define ASIO_HANDLER_TYPE(ct, sig) \+ typename ::asio::async_result< \+ typename ::asio::decay<ct>::type, sig>::completion_handler_type+#define ASIO_HANDLER_TYPE2(ct, sig0, sig1) \+ typename ::asio::async_result< \+ typename ::asio::decay<ct>::type, \+ sig0, sig1>::completion_handler_type+#define ASIO_HANDLER_TYPE3(ct, sig0, sig1, sig2) \+ typename ::asio::async_result< \+ typename ::asio::decay<ct>::type, \+ sig0, sig1, sig2>::completion_handler_type+#endif++#if defined(GENERATING_DOCUMENTATION)+# define ASIO_INITFN_AUTO_RESULT_TYPE(ct, sig) \+ auto+# define ASIO_INITFN_AUTO_RESULT_TYPE2(ct, sig0, sig1) \+ auto+# define ASIO_INITFN_AUTO_RESULT_TYPE3(ct, sig0, sig1, sig2) \+ auto+#elif defined(ASIO_HAS_RETURN_TYPE_DEDUCTION)+# define ASIO_INITFN_AUTO_RESULT_TYPE(ct, sig) \+ auto+# define ASIO_INITFN_AUTO_RESULT_TYPE2(ct, sig0, sig1) \+ auto+# define ASIO_INITFN_AUTO_RESULT_TYPE3(ct, sig0, sig1, sig2) \+ auto+#else+# define ASIO_INITFN_AUTO_RESULT_TYPE(ct, sig) \+ ASIO_INITFN_RESULT_TYPE(ct, sig)+# define ASIO_INITFN_AUTO_RESULT_TYPE2(ct, sig0, sig1) \+ ASIO_INITFN_RESULT_TYPE2(ct, sig0, sig1)+# define ASIO_INITFN_AUTO_RESULT_TYPE3(ct, sig0, sig1, sig2) \+ ASIO_INITFN_RESULT_TYPE3(ct, sig0, sig1, sig2)+#endif++#if defined(GENERATING_DOCUMENTATION)+# define ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX(ct, sig) \+ auto+# define ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX2(ct, sig0, sig1) \+ auto+# define ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX3(ct, sig0, sig1, sig2) \+ auto+# define ASIO_INITFN_AUTO_RESULT_TYPE_SUFFIX(expr)+#elif defined(ASIO_HAS_RETURN_TYPE_DEDUCTION)+# define ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX(ct, sig) \+ auto+# define ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX2(ct, sig0, sig1) \+ auto+# define ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX3(ct, sig0, sig1, sig2) \+ auto+# define ASIO_INITFN_AUTO_RESULT_TYPE_SUFFIX(expr)+#elif defined(ASIO_HAS_DECLTYPE)+# define ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX(ct, sig) \+ auto+# define ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX2(ct, sig0, sig1) \+ auto+# define ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX3(ct, sig0, sig1, sig2) \+ auto+# define ASIO_INITFN_AUTO_RESULT_TYPE_SUFFIX(expr) -> decltype expr+#else+# define ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX(ct, sig) \+ ASIO_INITFN_RESULT_TYPE(ct, sig)+# define ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX2(ct, sig0, sig1) \+ ASIO_INITFN_RESULT_TYPE2(ct, sig0, sig1)+# define ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX3(ct, sig0, sig1, sig2) \+ ASIO_INITFN_RESULT_TYPE3(ct, sig0, sig1, sig2)+# define ASIO_INITFN_AUTO_RESULT_TYPE_SUFFIX(expr)+#endif++#if defined(GENERATING_DOCUMENTATION)+# define ASIO_INITFN_DEDUCED_RESULT_TYPE(ct, sig, expr) \+ void_or_deduced+# define ASIO_INITFN_DEDUCED_RESULT_TYPE2(ct, sig0, sig1, expr) \+ void_or_deduced+# define ASIO_INITFN_DEDUCED_RESULT_TYPE3(ct, sig0, sig1, sig2, expr) \+ void_or_deduced+#elif defined(ASIO_HAS_DECLTYPE)+# define ASIO_INITFN_DEDUCED_RESULT_TYPE(ct, sig, expr) \+ decltype expr+# define ASIO_INITFN_DEDUCED_RESULT_TYPE2(ct, sig0, sig1, expr) \+ decltype expr+# define ASIO_INITFN_DEDUCED_RESULT_TYPE3(ct, sig0, sig1, sig2, expr) \+ decltype expr+#else+# define ASIO_INITFN_DEDUCED_RESULT_TYPE(ct, sig, expr) \+ ASIO_INITFN_RESULT_TYPE(ct, sig)+# define ASIO_INITFN_DEDUCED_RESULT_TYPE2(ct, sig0, sig1, expr) \+ ASIO_INITFN_RESULT_TYPE2(ct, sig0, sig1)+# define ASIO_INITFN_DEDUCED_RESULT_TYPE3(ct, sig0, sig1, sig2, expr) \+ ASIO_INITFN_RESULT_TYPE3(ct, sig0, sig1, sig2)+#endif++#if defined(GENERATING_DOCUMENTATION)++template <typename CompletionToken,+ completion_signature... Signatures,+ typename Initiation, typename... Args>+void_or_deduced async_initiate(+ ASIO_MOVE_ARG(Initiation) initiation,+ ASIO_NONDEDUCED_MOVE_ARG(CompletionToken),+ ASIO_MOVE_ARG(Args)... args);++#elif defined(ASIO_HAS_VARIADIC_TEMPLATES)++template <typename CompletionToken,+ ASIO_COMPLETION_SIGNATURE... Signatures,+ typename Initiation, typename... Args>+inline typename constraint<+ detail::async_result_has_initiate_memfn<+ CompletionToken, Signatures...>::value,+ ASIO_INITFN_DEDUCED_RESULT_TYPE(CompletionToken, Signatures...,+ (async_result<typename decay<CompletionToken>::type,+ Signatures...>::initiate(declval<ASIO_MOVE_ARG(Initiation)>(),+ declval<ASIO_MOVE_ARG(CompletionToken)>(),+ declval<ASIO_MOVE_ARG(Args)>()...)))>::type+async_initiate(ASIO_MOVE_ARG(Initiation) initiation,+ ASIO_NONDEDUCED_MOVE_ARG(CompletionToken) token,+ ASIO_MOVE_ARG(Args)... args)+{+ return async_result<typename decay<CompletionToken>::type,+ Signatures...>::initiate(ASIO_MOVE_CAST(Initiation)(initiation),+ ASIO_MOVE_CAST(CompletionToken)(token),+ ASIO_MOVE_CAST(Args)(args)...);+}++template <typename CompletionToken,+ ASIO_COMPLETION_SIGNATURE... Signatures,+ typename Initiation, typename... Args>+inline typename constraint<+ !detail::async_result_has_initiate_memfn<+ CompletionToken, Signatures...>::value,+ ASIO_INITFN_RESULT_TYPE(CompletionToken, Signatures...)>::type+async_initiate(ASIO_MOVE_ARG(Initiation) initiation,+ ASIO_NONDEDUCED_MOVE_ARG(CompletionToken) token,+ ASIO_MOVE_ARG(Args)... args)+{+ async_completion<CompletionToken, Signatures...> completion(token);++ ASIO_MOVE_CAST(Initiation)(initiation)(+ ASIO_MOVE_CAST(ASIO_HANDLER_TYPE(CompletionToken,+ Signatures...))(completion.completion_handler),+ ASIO_MOVE_CAST(Args)(args)...);++ return completion.result.get();+}++#else // defined(ASIO_HAS_VARIADIC_TEMPLATES)++template <typename CompletionToken,+ ASIO_COMPLETION_SIGNATURE Sig0,+ typename Initiation>+inline typename constraint<+ detail::async_result_has_initiate_memfn<+ CompletionToken, Sig0>::value,+ ASIO_INITFN_DEDUCED_RESULT_TYPE(CompletionToken, Sig0,+ (async_result<typename decay<CompletionToken>::type,+ Sig0>::initiate(declval<ASIO_MOVE_ARG(Initiation)>(),+ declval<ASIO_MOVE_ARG(CompletionToken)>())))>::type+async_initiate(ASIO_MOVE_ARG(Initiation) initiation,+ ASIO_NONDEDUCED_MOVE_ARG(CompletionToken) token)+{+ return async_result<typename decay<CompletionToken>::type,+ Sig0>::initiate(ASIO_MOVE_CAST(Initiation)(initiation),+ ASIO_MOVE_CAST(CompletionToken)(token));+}++template <typename CompletionToken,+ ASIO_COMPLETION_SIGNATURE Sig0,+ ASIO_COMPLETION_SIGNATURE Sig1,+ typename Initiation>+inline typename constraint<+ detail::async_result_has_initiate_memfn<+ CompletionToken, Sig0, Sig1>::value,+ ASIO_INITFN_DEDUCED_RESULT_TYPE2(CompletionToken, Sig0, Sig1,+ (async_result<typename decay<CompletionToken>::type,+ Sig0, Sig1>::initiate(declval<ASIO_MOVE_ARG(Initiation)>(),+ declval<ASIO_MOVE_ARG(CompletionToken)>())))>::type+async_initiate(ASIO_MOVE_ARG(Initiation) initiation,+ ASIO_NONDEDUCED_MOVE_ARG(CompletionToken) token)+{+ return async_result<typename decay<CompletionToken>::type,+ Sig0, Sig1>::initiate(ASIO_MOVE_CAST(Initiation)(initiation),+ ASIO_MOVE_CAST(CompletionToken)(token));+}++template <typename CompletionToken,+ ASIO_COMPLETION_SIGNATURE Sig0,+ ASIO_COMPLETION_SIGNATURE Sig1,+ ASIO_COMPLETION_SIGNATURE Sig2,+ typename Initiation>+inline typename constraint<+ detail::async_result_has_initiate_memfn<+ CompletionToken, Sig0, Sig1, Sig2>::value,+ ASIO_INITFN_DEDUCED_RESULT_TYPE3(CompletionToken, Sig0, Sig1, Sig2,+ (async_result<typename decay<CompletionToken>::type,+ Sig0, Sig1, Sig2>::initiate(declval<ASIO_MOVE_ARG(Initiation)>(),+ declval<ASIO_MOVE_ARG(CompletionToken)>())))>::type+async_initiate(ASIO_MOVE_ARG(Initiation) initiation,+ ASIO_NONDEDUCED_MOVE_ARG(CompletionToken) token)+{+ return async_result<typename decay<CompletionToken>::type,+ Sig0, Sig1, Sig2>::initiate(ASIO_MOVE_CAST(Initiation)(initiation),+ ASIO_MOVE_CAST(CompletionToken)(token));+}++template <typename CompletionToken,+ ASIO_COMPLETION_SIGNATURE Sig0,+ typename Initiation>+inline typename constraint<+ !detail::async_result_has_initiate_memfn<+ CompletionToken, Sig0>::value,+ ASIO_INITFN_RESULT_TYPE(CompletionToken, Sig0)>::type+async_initiate(ASIO_MOVE_ARG(Initiation) initiation,+ ASIO_NONDEDUCED_MOVE_ARG(CompletionToken) token)+{+ async_completion<CompletionToken, Sig0> completion(token);++ ASIO_MOVE_CAST(Initiation)(initiation)(+ ASIO_MOVE_CAST(ASIO_HANDLER_TYPE(CompletionToken,+ Sig0))(completion.completion_handler));++ return completion.result.get();+}++template <typename CompletionToken,+ ASIO_COMPLETION_SIGNATURE Sig0,+ ASIO_COMPLETION_SIGNATURE Sig1,+ typename Initiation>+inline typename constraint<+ !detail::async_result_has_initiate_memfn<+ CompletionToken, Sig0, Sig1>::value,+ ASIO_INITFN_RESULT_TYPE2(CompletionToken, Sig0, Sig1)>::type+async_initiate(ASIO_MOVE_ARG(Initiation) initiation,+ ASIO_NONDEDUCED_MOVE_ARG(CompletionToken) token)+{+ async_completion<CompletionToken, Sig0, Sig1> completion(token);++ ASIO_MOVE_CAST(Initiation)(initiation)(+ ASIO_MOVE_CAST(ASIO_HANDLER_TYPE2(CompletionToken,+ Sig0, Sig1))(completion.completion_handler));++ return completion.result.get();+}++template <typename CompletionToken,+ ASIO_COMPLETION_SIGNATURE Sig0,+ ASIO_COMPLETION_SIGNATURE Sig1,+ ASIO_COMPLETION_SIGNATURE Sig2,+ typename Initiation>+inline typename constraint<+ !detail::async_result_has_initiate_memfn<+ CompletionToken, Sig0, Sig1, Sig2>::value,+ ASIO_INITFN_RESULT_TYPE3(CompletionToken, Sig0, Sig1, Sig2)>::type+async_initiate(ASIO_MOVE_ARG(Initiation) initiation,+ ASIO_NONDEDUCED_MOVE_ARG(CompletionToken) token)+{+ async_completion<CompletionToken, Sig0, Sig1, Sig2> completion(token);++ ASIO_MOVE_CAST(Initiation)(initiation)(+ ASIO_MOVE_CAST(ASIO_HANDLER_TYPE3(CompletionToken,+ Sig0, Sig1, Sig2))(completion.completion_handler));++ return completion.result.get();+}++#define ASIO_PRIVATE_INITIATE_DEF(n) \+ template <typename CompletionToken, \+ ASIO_COMPLETION_SIGNATURE Sig0, \+ typename Initiation, ASIO_VARIADIC_TPARAMS(n)> \+ inline typename constraint< \+ detail::async_result_has_initiate_memfn< \+ CompletionToken, Sig0>::value, \+ ASIO_INITFN_DEDUCED_RESULT_TYPE( \+ CompletionToken, Sig0, \+ (async_result<typename decay<CompletionToken>::type, \+ Sig0>::initiate( \+ declval<ASIO_MOVE_ARG(Initiation)>(), \+ declval<ASIO_MOVE_ARG(CompletionToken)>(), \+ ASIO_VARIADIC_MOVE_DECLVAL(n))))>::type \+ async_initiate(ASIO_MOVE_ARG(Initiation) initiation, \+ ASIO_NONDEDUCED_MOVE_ARG(CompletionToken) token, \+ ASIO_VARIADIC_MOVE_PARAMS(n)) \+ { \+ return async_result<typename decay<CompletionToken>::type, \+ Sig0>::initiate( \+ ASIO_MOVE_CAST(Initiation)(initiation), \+ ASIO_MOVE_CAST(CompletionToken)(token), \+ ASIO_VARIADIC_MOVE_ARGS(n)); \+ } \+ \+ template <typename CompletionToken, \+ ASIO_COMPLETION_SIGNATURE Sig0, \+ ASIO_COMPLETION_SIGNATURE Sig1, \+ typename Initiation, ASIO_VARIADIC_TPARAMS(n)> \+ inline typename constraint< \+ detail::async_result_has_initiate_memfn< \+ CompletionToken, Sig0, Sig1>::value, \+ ASIO_INITFN_DEDUCED_RESULT_TYPE2( \+ CompletionToken, Sig0, Sig1, \+ (async_result<typename decay<CompletionToken>::type, \+ Sig0, Sig1>::initiate( \+ declval<ASIO_MOVE_ARG(Initiation)>(), \+ declval<ASIO_MOVE_ARG(CompletionToken)>(), \+ ASIO_VARIADIC_MOVE_DECLVAL(n))))>::type \+ async_initiate(ASIO_MOVE_ARG(Initiation) initiation, \+ ASIO_NONDEDUCED_MOVE_ARG(CompletionToken) token, \+ ASIO_VARIADIC_MOVE_PARAMS(n)) \+ { \+ return async_result<typename decay<CompletionToken>::type, \+ Sig0, Sig1>::initiate( \+ ASIO_MOVE_CAST(Initiation)(initiation), \+ ASIO_MOVE_CAST(CompletionToken)(token), \+ ASIO_VARIADIC_MOVE_ARGS(n)); \+ } \+ \+ template <typename CompletionToken, \+ ASIO_COMPLETION_SIGNATURE Sig0, \+ ASIO_COMPLETION_SIGNATURE Sig1, \+ ASIO_COMPLETION_SIGNATURE Sig2, \+ typename Initiation, ASIO_VARIADIC_TPARAMS(n)> \+ inline typename constraint< \+ detail::async_result_has_initiate_memfn< \+ CompletionToken, Sig0, Sig1, Sig2>::value, \+ ASIO_INITFN_DEDUCED_RESULT_TYPE3( \+ CompletionToken, Sig0, Sig1, Sig2, \+ (async_result<typename decay<CompletionToken>::type, \+ Sig0, Sig1, Sig2>::initiate( \+ declval<ASIO_MOVE_ARG(Initiation)>(), \+ declval<ASIO_MOVE_ARG(CompletionToken)>(), \+ ASIO_VARIADIC_MOVE_DECLVAL(n))))>::type \+ async_initiate(ASIO_MOVE_ARG(Initiation) initiation, \+ ASIO_NONDEDUCED_MOVE_ARG(CompletionToken) token, \+ ASIO_VARIADIC_MOVE_PARAMS(n)) \+ { \+ return async_result<typename decay<CompletionToken>::type, \+ Sig0, Sig1, Sig2>::initiate( \+ ASIO_MOVE_CAST(Initiation)(initiation), \+ ASIO_MOVE_CAST(CompletionToken)(token), \+ ASIO_VARIADIC_MOVE_ARGS(n)); \+ } \+ \+ template <typename CompletionToken, \+ ASIO_COMPLETION_SIGNATURE Sig0, \+ typename Initiation, ASIO_VARIADIC_TPARAMS(n)> \+ inline typename constraint< \+ !detail::async_result_has_initiate_memfn< \+ CompletionToken, Sig0>::value, \+ ASIO_INITFN_RESULT_TYPE(CompletionToken, Sig0)>::type \+ async_initiate(ASIO_MOVE_ARG(Initiation) initiation, \+ ASIO_NONDEDUCED_MOVE_ARG(CompletionToken) token, \+ ASIO_VARIADIC_MOVE_PARAMS(n)) \+ { \+ async_completion<CompletionToken, \+ Sig0> completion(token); \+ \+ ASIO_MOVE_CAST(Initiation)(initiation)( \+ ASIO_MOVE_CAST(ASIO_HANDLER_TYPE(CompletionToken, \+ Sig0))(completion.completion_handler), \+ ASIO_VARIADIC_MOVE_ARGS(n)); \+ \+ return completion.result.get(); \+ } \+ \+ template <typename CompletionToken, \+ ASIO_COMPLETION_SIGNATURE Sig0, \+ ASIO_COMPLETION_SIGNATURE Sig1, \+ typename Initiation, ASIO_VARIADIC_TPARAMS(n)> \+ inline typename constraint< \+ !detail::async_result_has_initiate_memfn< \+ CompletionToken, Sig0, Sig1>::value, \+ ASIO_INITFN_RESULT_TYPE2(CompletionToken, Sig0, Sig1)>::type \+ async_initiate(ASIO_MOVE_ARG(Initiation) initiation, \+ ASIO_NONDEDUCED_MOVE_ARG(CompletionToken) token, \+ ASIO_VARIADIC_MOVE_PARAMS(n)) \+ { \+ async_completion<CompletionToken, \+ Sig0, Sig1> completion(token); \+ \+ ASIO_MOVE_CAST(Initiation)(initiation)( \+ ASIO_MOVE_CAST(ASIO_HANDLER_TYPE2(CompletionToken, \+ Sig0, Sig1))(completion.completion_handler), \+ ASIO_VARIADIC_MOVE_ARGS(n)); \+ \+ return completion.result.get(); \+ } \+ \+ template <typename CompletionToken, \+ ASIO_COMPLETION_SIGNATURE Sig0, \+ ASIO_COMPLETION_SIGNATURE Sig1, \+ ASIO_COMPLETION_SIGNATURE Sig2, \+ typename Initiation, ASIO_VARIADIC_TPARAMS(n)> \+ inline typename constraint< \+ !detail::async_result_has_initiate_memfn< \+ CompletionToken, Sig0, Sig1, Sig2>::value, \+ ASIO_INITFN_RESULT_TYPE3(CompletionToken, Sig0, Sig1, Sig2)>::type \+ async_initiate(ASIO_MOVE_ARG(Initiation) initiation, \+ ASIO_NONDEDUCED_MOVE_ARG(CompletionToken) token, \+ ASIO_VARIADIC_MOVE_PARAMS(n)) \+ { \+ async_completion<CompletionToken, \+ Sig0, Sig1, Sig2> completion(token); \+ \+ ASIO_MOVE_CAST(Initiation)(initiation)( \+ ASIO_MOVE_CAST(ASIO_HANDLER_TYPE3(CompletionToken, \+ Sig0, Sig1, Sig2))(completion.completion_handler), \+ ASIO_VARIADIC_MOVE_ARGS(n)); \+ \+ return completion.result.get(); \+ } \+ /**/+ ASIO_VARIADIC_GENERATE(ASIO_PRIVATE_INITIATE_DEF)+#undef ASIO_PRIVATE_INITIATE_DEF++#endif // defined(ASIO_HAS_VARIADIC_TEMPLATES)++#if defined(ASIO_HAS_CONCEPTS) \+ && defined(ASIO_HAS_VARIADIC_TEMPLATES) \+ && defined(ASIO_HAS_DECLTYPE)++namespace detail {++template <typename... Signatures>+struct initiation_archetype+{+ template <completion_handler_for<Signatures...> CompletionHandler>+ void operator()(CompletionHandler&&) const+ {+ }+};++} // namespace detail++template <typename T, typename... Signatures>+ASIO_CONCEPT completion_token_for =+ detail::are_completion_signatures<Signatures...>::value+ &&+ requires(T&& t)+ {+ async_initiate<T, Signatures...>(+ detail::initiation_archetype<Signatures...>{}, t);+ };++#define ASIO_COMPLETION_TOKEN_FOR(sig) \+ ::asio::completion_token_for<sig>+#define ASIO_COMPLETION_TOKEN_FOR2(sig0, sig1) \+ ::asio::completion_token_for<sig0, sig1>+#define ASIO_COMPLETION_TOKEN_FOR3(sig0, sig1, sig2) \+ ::asio::completion_token_for<sig0, sig1, sig2>++#else // defined(ASIO_HAS_CONCEPTS)+ // && defined(ASIO_HAS_VARIADIC_TEMPLATES)+ // && defined(ASIO_HAS_DECLTYPE)++#define ASIO_COMPLETION_TOKEN_FOR(sig) typename+#define ASIO_COMPLETION_TOKEN_FOR2(sig0, sig1) typename+#define ASIO_COMPLETION_TOKEN_FOR3(sig0, sig1, sig2) typename++#endif // defined(ASIO_HAS_CONCEPTS)+ // && defined(ASIO_HAS_VARIADIC_TEMPLATES)+ // && defined(ASIO_HAS_DECLTYPE)++namespace detail {++struct async_operation_probe {};+struct async_operation_probe_result {};++template <typename Call, typename = void>+struct is_async_operation_call : false_type+{+};++template <typename Call>+struct is_async_operation_call<Call,+ typename void_type<+ typename enable_if<+ is_same<+ typename result_of<Call>::type,+ async_operation_probe_result+ >::value+ >::type+ >::type> : true_type+{+};++} // namespace detail++#if !defined(GENERATING_DOCUMENTATION)+#if defined(ASIO_HAS_VARIADIC_TEMPLATES)++template <typename... Signatures>+class async_result<detail::async_operation_probe, Signatures...>+{+public:+ typedef detail::async_operation_probe_result return_type;++ template <typename Initiation, typename... InitArgs>+ static return_type initiate(ASIO_MOVE_ARG(Initiation),+ detail::async_operation_probe, ASIO_MOVE_ARG(InitArgs)...)+ {+ return return_type();+ }+};++#else // defined(ASIO_HAS_VARIADIC_TEMPLATES)++namespace detail {++struct async_result_probe_base+{+ typedef detail::async_operation_probe_result return_type;++ template <typename Initiation>+ static return_type initiate(ASIO_MOVE_ARG(Initiation),+ detail::async_operation_probe)+ {+ return return_type();+ }++#define ASIO_PRIVATE_INITIATE_DEF(n) \+ template <typename Initiation, ASIO_VARIADIC_TPARAMS(n)> \+ static return_type initiate(ASIO_MOVE_ARG(Initiation), \+ detail::async_operation_probe, \+ ASIO_VARIADIC_UNNAMED_MOVE_PARAMS(n)) \+ { \+ return return_type(); \+ } \+ /**/+ ASIO_VARIADIC_GENERATE(ASIO_PRIVATE_INITIATE_DEF)+#undef ASIO_PRIVATE_INITIATE_DEF+};++} // namespace detail++template <typename Sig0>+class async_result<detail::async_operation_probe, Sig0>+ : public detail::async_result_probe_base {};++template <typename Sig0, typename Sig1>+class async_result<detail::async_operation_probe, Sig0, Sig1>+ : public detail::async_result_probe_base {};++template <typename Sig0, typename Sig1, typename Sig2>+class async_result<detail::async_operation_probe, Sig0, Sig1, Sig2>+ : public detail::async_result_probe_base {};++#endif // defined(ASIO_HAS_VARIADIC_TEMPLATES)+#endif // !defined(GENERATING_DOCUMENTATION)++#if defined(GENERATING_DOCUMENTATION)++/// The is_async_operation trait detects whether a type @c T and arguments+/// @c Args... may be used to initiate an asynchronous operation.+/**+ * Class template @c is_async_operation is a trait is derived from @c true_type+ * if the expression <tt>T(Args..., token)</tt> initiates an asynchronous+ * operation, where @c token is an unspecified completion token type. Otherwise,+ * @c is_async_operation is derived from @c false_type.+ */+template <typename T, typename... Args>+struct is_async_operation : integral_constant<bool, automatically_determined>+{+};++#elif defined(ASIO_HAS_VARIADIC_TEMPLATES)++template <typename T, typename... Args>+struct is_async_operation :+ detail::is_async_operation_call<+ T(Args..., detail::async_operation_probe)>+{+};++#else // defined(ASIO_HAS_VARIADIC_TEMPLATES)++template <typename T, typename = void, typename = void, typename = void,+ typename = void, typename = void, typename = void, typename = void,+ typename = void, typename = void>+struct is_async_operation;++template <typename T>+struct is_async_operation<T> :+ detail::is_async_operation_call<+ T(detail::async_operation_probe)>+{+};++#define ASIO_PRIVATE_IS_ASYNC_OP_DEF(n) \+ template <typename T, ASIO_VARIADIC_TPARAMS(n)> \+ struct is_async_operation<T, ASIO_VARIADIC_TARGS(n)> : \+ detail::is_async_operation_call< \+ T(ASIO_VARIADIC_TARGS(n), detail::async_operation_probe)> \+ { \+ }; \+ /**/+ ASIO_VARIADIC_GENERATE(ASIO_PRIVATE_IS_ASYNC_OP_DEF)+#undef ASIO_PRIVATE_IS_ASYNC_OP_DEF++#endif // defined(ASIO_HAS_VARIADIC_TEMPLATES)++#if defined(ASIO_HAS_CONCEPTS) \+ && defined(ASIO_HAS_VARIADIC_TEMPLATES)++template <typename T, typename... Args>+ASIO_CONCEPT async_operation = is_async_operation<T, Args...>::value;++#define ASIO_ASYNC_OPERATION(t) \+ ::asio::async_operation<t>+#define ASIO_ASYNC_OPERATION1(t, a0) \+ ::asio::async_operation<t, a0>+#define ASIO_ASYNC_OPERATION2(t, a0, a1) \+ ::asio::async_operation<t, a0, a1>+#define ASIO_ASYNC_OPERATION3(t, a0, a1, a2) \+ ::asio::async_operation<t, a0, a1, a2>++#else // defined(ASIO_HAS_CONCEPTS)+ // && defined(ASIO_HAS_VARIADIC_TEMPLATES)++#define ASIO_ASYNC_OPERATION(t) typename+#define ASIO_ASYNC_OPERATION1(t, a0) typename+#define ASIO_ASYNC_OPERATION2(t, a0, a1) typename+#define ASIO_ASYNC_OPERATION3(t, a0, a1, a2) typename++#endif // defined(ASIO_HAS_CONCEPTS)+ // && defined(ASIO_HAS_VARIADIC_TEMPLATES)++namespace detail {++struct completion_signature_probe {};++#if defined(ASIO_HAS_VARIADIC_TEMPLATES)++template <typename... T>+struct completion_signature_probe_result+{+ template <template <typename...> class Op>+ struct apply+ {+ typedef Op<T...> type;+ };+};++template <typename T>+struct completion_signature_probe_result<T>+{+ typedef T type;++ template <template <typename...> class Op>+ struct apply+ {+ typedef Op<T> type;+ };+};++template <>+struct completion_signature_probe_result<void>+{+ template <template <typename...> class Op>+ struct apply+ {+ typedef Op<> type;+ };+};++#else // defined(ASIO_HAS_VARIADIC_TEMPLATES)++template <typename T>+struct completion_signature_probe_result+{+ typedef T type;+};++template <>+struct completion_signature_probe_result<void>+{+};++#endif // defined(ASIO_HAS_VARIADIC_TEMPLATES)++} // namespace detail++#if !defined(GENERATING_DOCUMENTATION)+#if defined(ASIO_HAS_VARIADIC_TEMPLATES)++template <typename... Signatures>+class async_result<detail::completion_signature_probe, Signatures...>+{+public:+ typedef detail::completion_signature_probe_result<Signatures...> return_type;++ template <typename Initiation, typename... InitArgs>+ static return_type initiate(ASIO_MOVE_ARG(Initiation),+ detail::completion_signature_probe, ASIO_MOVE_ARG(InitArgs)...)+ {+ return return_type();+ }+};++template <typename Signature>+class async_result<detail::completion_signature_probe, Signature>+{+public:+ typedef detail::completion_signature_probe_result<Signature> return_type;++ template <typename Initiation, typename... InitArgs>+ static return_type initiate(ASIO_MOVE_ARG(Initiation),+ detail::completion_signature_probe, ASIO_MOVE_ARG(InitArgs)...)+ {+ return return_type();+ }+};++#else // defined(ASIO_HAS_VARIADIC_TEMPLATES)++namespace detail {++template <typename Signature>+class async_result_sig_probe_base+{+public:+ typedef detail::completion_signature_probe_result<Signature> return_type;++ template <typename Initiation>+ static return_type initiate(ASIO_MOVE_ARG(Initiation),+ detail::async_operation_probe)+ {+ return return_type();+ }++#define ASIO_PRIVATE_INITIATE_DEF(n) \+ template <typename Initiation, ASIO_VARIADIC_TPARAMS(n)> \+ static return_type initiate(ASIO_MOVE_ARG(Initiation), \+ detail::completion_signature_probe, \+ ASIO_VARIADIC_UNNAMED_MOVE_PARAMS(n)) \+ { \+ return return_type(); \+ } \+ /**/+ ASIO_VARIADIC_GENERATE(ASIO_PRIVATE_INITIATE_DEF)+#undef ASIO_PRIVATE_INITIATE_DEF+};++} // namespace detail++template <>+class async_result<detail::completion_signature_probe>+ : public detail::async_result_sig_probe_base<void> {};++template <typename Sig0>+class async_result<detail::completion_signature_probe, Sig0>+ : public detail::async_result_sig_probe_base<Sig0> {};++template <typename Sig0, typename Sig1>+class async_result<detail::completion_signature_probe, Sig0, Sig1>+ : public detail::async_result_sig_probe_base<void> {};++template <typename Sig0, typename Sig1, typename Sig2>+class async_result<detail::completion_signature_probe, Sig0, Sig1, Sig2>+ : public detail::async_result_sig_probe_base<void> {};++#endif // defined(ASIO_HAS_VARIADIC_TEMPLATES)+#endif // !defined(GENERATING_DOCUMENTATION)++#if defined(GENERATING_DOCUMENTATION)++/// The completion_signature_of trait determines the completion signature+/// of an asynchronous operation.+/**+ * Class template @c completion_signature_of is a trait with a member type+ * alias @c type that denotes the completion signature of the asynchronous+ * operation initiated by the expression <tt>T(Args..., token)</tt> operation,+ * where @c token is an unspecified completion token type. If the asynchronous+ * operation does not have exactly one completion signature, the instantion of+ * the trait is well-formed but the member type alias @c type is omitted. If+ * the expression <tt>T(Args..., token)</tt> is not an asynchronous operation+ * then use of the trait is ill-formed.+ */+template <typename T, typename... Args>+struct completion_signature_of+{+ typedef automatically_determined type;+};++template <typename T, typename... Args>+using completion_signature_of_t =+ typename completion_signature_of<T, Args...>::type;++#elif defined(ASIO_HAS_VARIADIC_TEMPLATES)++template <typename T, typename... Args>+struct completion_signature_of :+ result_of<T(Args..., detail::completion_signature_probe)>::type+{+};++#if defined(ASIO_HAS_ALIAS_TEMPLATES)+template <typename T, typename... Args>+using completion_signature_of_t =+ typename completion_signature_of<T, Args...>::type;+#endif // defined(ASIO_HAS_ALIAS_TEMPLATES)++#else // defined(ASIO_HAS_VARIADIC_TEMPLATES)++template <typename T, typename = void, typename = void, typename = void,+ typename = void, typename = void, typename = void, typename = void,+ typename = void, typename = void>+struct completion_signature_of;++template <typename T>+struct completion_signature_of<T> :+ result_of<T(detail::completion_signature_probe)>::type+{+};++#define ASIO_PRIVATE_COMPLETION_SIG_OF_DEF(n) \+ template <typename T, ASIO_VARIADIC_TPARAMS(n)> \+ struct completion_signature_of<T, ASIO_VARIADIC_TARGS(n)> : \+ result_of< \+ T(ASIO_VARIADIC_TARGS(n), \+ detail::completion_signature_probe)>::type \+ { \+ }; \+ /**/+ ASIO_VARIADIC_GENERATE(ASIO_PRIVATE_COMPLETION_SIG_OF_DEF)+#undef ASIO_PRIVATE_COMPLETION_SIG_OF_DEF++#endif // defined(ASIO_HAS_VARIADIC_TEMPLATES) namespace detail {
link/modules/asio-standalone/asio/include/asio/awaitable.hpp view
@@ -2,7 +2,7 @@ // awaitable.hpp // ~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -25,6 +25,7 @@ # include <experimental/coroutine> #endif // defined(ASIO_HAS_STD_COROUTINE) +#include <utility> #include "asio/any_io_executor.hpp" #include "asio/detail/push_options.hpp"@@ -47,7 +48,7 @@ /// The return type of a coroutine or asynchronous operation. template <typename T, typename Executor = any_io_executor>-class awaitable+class ASIO_NODISCARD awaitable { public: /// The type of the awaited value.@@ -73,6 +74,14 @@ { if (frame_) frame_->destroy();+ }++ /// Move assignment.+ awaitable& operator=(awaitable&& other) noexcept+ {+ if (this != &other)+ frame_ = std::exchange(other.frame_, nullptr);+ return *this; } /// Checks if the awaitable refers to a future result.
link/modules/asio-standalone/asio/include/asio/basic_datagram_socket.hpp view
@@ -2,7 +2,7 @@ // basic_datagram_socket.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -45,11 +45,24 @@ * @par Thread Safety * @e Distinct @e objects: Safe.@n * @e Shared @e objects: Unsafe.+ *+ * Synchronous @c send, @c send_to, @c receive, @c receive_from, @c connect,+ * and @c shutdown operations are thread safe with respect to each other, if+ * the underlying operating system calls are also thread safe. This means that+ * it is permitted to perform concurrent calls to these synchronous operations+ * on a single socket object. Other synchronous operations, such as @c open or+ * @c close, are not thread safe. */ template <typename Protocol, typename Executor> class basic_datagram_socket : public basic_socket<Protocol, Executor> {+private:+ class initiate_async_send;+ class initiate_async_send_to;+ class initiate_async_receive;+ class initiate_async_receive_from;+ public: /// The type of the executor associated with the object. typedef Executor executor_type;@@ -100,9 +113,9 @@ */ template <typename ExecutionContext> explicit basic_datagram_socket(ExecutionContext& context,- typename enable_if<+ typename constraint< is_convertible<ExecutionContext&, execution_context&>::value- >::type* = 0)+ >::type = 0) : basic_socket<Protocol, Executor>(context) { }@@ -138,9 +151,10 @@ template <typename ExecutionContext> basic_datagram_socket(ExecutionContext& context, const protocol_type& protocol,- typename enable_if<- is_convertible<ExecutionContext&, execution_context&>::value- >::type* = 0)+ typename constraint<+ is_convertible<ExecutionContext&, execution_context&>::value,+ defaulted_constraint+ >::type = defaulted_constraint()) : basic_socket<Protocol, Executor>(context, protocol) { }@@ -184,9 +198,9 @@ template <typename ExecutionContext> basic_datagram_socket(ExecutionContext& context, const endpoint_type& endpoint,- typename enable_if<+ typename constraint< is_convertible<ExecutionContext&, execution_context&>::value- >::type* = 0)+ >::type = 0) : basic_socket<Protocol, Executor>(context, endpoint) { }@@ -229,9 +243,9 @@ template <typename ExecutionContext> basic_datagram_socket(ExecutionContext& context, const protocol_type& protocol, const native_handle_type& native_socket,- typename enable_if<+ typename constraint< is_convertible<ExecutionContext&, execution_context&>::value- >::type* = 0)+ >::type = 0) : basic_socket<Protocol, Executor>(context, protocol, native_socket) { }@@ -285,10 +299,10 @@ */ template <typename Protocol1, typename Executor1> basic_datagram_socket(basic_datagram_socket<Protocol1, Executor1>&& other,- typename enable_if<+ typename constraint< is_convertible<Protocol1, Protocol>::value && is_convertible<Executor1, Executor>::value- >::type* = 0)+ >::type = 0) : basic_socket<Protocol, Executor>(std::move(other)) { }@@ -307,7 +321,7 @@ * constructor. */ template <typename Protocol1, typename Executor1>- typename enable_if<+ typename constraint< is_convertible<Protocol1, Protocol>::value && is_convertible<Executor1, Executor>::value, basic_datagram_socket&@@ -415,25 +429,31 @@ /// Start an asynchronous send on a connected socket. /** * This function is used to asynchronously send data on the datagram socket.- * The function call always returns immediately.+ * It is an initiating function for an @ref asynchronous_operation, and always+ * returns immediately. * * @param buffers One or more data buffers to be sent on the socket. Although * the buffers object may be copied as necessary, ownership of the underlying * memory blocks is retained by the caller, which must guarantee that they- * remain valid until the handler is called.+ * remain valid until the completion handler is called. *- * @param handler The handler to be called when the send operation completes.- * Copies will be made of the handler as required. The function signature of- * the handler must be:+ * @param token The @ref completion_token that will be used to produce a+ * completion handler, which will be called when the send completes. Potential+ * completion tokens include @ref use_future, @ref use_awaitable, @ref+ * yield_context, or a function object with the correct completion signature.+ * The function signature of the completion handler must be: * @code void handler( * const asio::error_code& error, // Result of operation.- * std::size_t bytes_transferred // Number of bytes sent.+ * std::size_t bytes_transferred // Number of bytes sent. * ); @endcode * Regardless of whether the asynchronous operation completes immediately or- * not, the handler will not be invoked from within this function. On- * immediate completion, invocation of the handler will be performed in a+ * not, the completion handler will not be invoked from within this function.+ * On immediate completion, invocation of the handler will be performed in a * manner equivalent to using asio::post(). *+ * @par Completion Signature+ * @code void(asio::error_code, std::size_t) @endcode+ * * @note The async_send operation can only be used with a connected socket. * Use the async_send_to function to send data on an unconnected datagram * socket.@@ -446,65 +466,100 @@ * See the @ref buffer documentation for information on sending multiple * buffers in one go, and how to use it with arrays, boost::array or * std::vector.+ *+ * @par Per-Operation Cancellation+ * On POSIX or Windows operating systems, this asynchronous operation supports+ * cancellation for the following asio::cancellation_type values:+ *+ * @li @c cancellation_type::terminal+ *+ * @li @c cancellation_type::partial+ *+ * @li @c cancellation_type::total */ template <typename ConstBufferSequence, ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code,- std::size_t)) WriteHandler+ std::size_t)) WriteToken ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(executor_type)>- ASIO_INITFN_AUTO_RESULT_TYPE(WriteHandler,+ ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX(WriteToken, void (asio::error_code, std::size_t)) async_send(const ConstBufferSequence& buffers,- ASIO_MOVE_ARG(WriteHandler) handler+ ASIO_MOVE_ARG(WriteToken) token ASIO_DEFAULT_COMPLETION_TOKEN(executor_type))+ ASIO_INITFN_AUTO_RESULT_TYPE_SUFFIX((+ async_initiate<WriteToken,+ void (asio::error_code, std::size_t)>(+ declval<initiate_async_send>(), token,+ buffers, socket_base::message_flags(0)))) {- return async_initiate<WriteHandler,+ return async_initiate<WriteToken, void (asio::error_code, std::size_t)>(- initiate_async_send(this), handler,+ initiate_async_send(this), token, buffers, socket_base::message_flags(0)); } /// Start an asynchronous send on a connected socket. /** * This function is used to asynchronously send data on the datagram socket.- * The function call always returns immediately.+ * It is an initiating function for an @ref asynchronous_operation, and always+ * returns immediately. * * @param buffers One or more data buffers to be sent on the socket. Although * the buffers object may be copied as necessary, ownership of the underlying * memory blocks is retained by the caller, which must guarantee that they- * remain valid until the handler is called.+ * remain valid until the completion handler is called. * * @param flags Flags specifying how the send call is to be made. *- * @param handler The handler to be called when the send operation completes.- * Copies will be made of the handler as required. The function signature of- * the handler must be:+ * @param token The @ref completion_token that will be used to produce a+ * completion handler, which will be called when the send completes. Potential+ * completion tokens include @ref use_future, @ref use_awaitable, @ref+ * yield_context, or a function object with the correct completion signature.+ * The function signature of the completion handler must be: * @code void handler( * const asio::error_code& error, // Result of operation.- * std::size_t bytes_transferred // Number of bytes sent.+ * std::size_t bytes_transferred // Number of bytes sent. * ); @endcode * Regardless of whether the asynchronous operation completes immediately or- * not, the handler will not be invoked from within this function. On- * immediate completion, invocation of the handler will be performed in a+ * not, the completion handler will not be invoked from within this function.+ * On immediate completion, invocation of the handler will be performed in a * manner equivalent to using asio::post(). *+ * @par Completion Signature+ * @code void(asio::error_code, std::size_t) @endcode+ * * @note The async_send operation can only be used with a connected socket. * Use the async_send_to function to send data on an unconnected datagram * socket.+ *+ * @par Per-Operation Cancellation+ * On POSIX or Windows operating systems, this asynchronous operation supports+ * cancellation for the following asio::cancellation_type values:+ *+ * @li @c cancellation_type::terminal+ *+ * @li @c cancellation_type::partial+ *+ * @li @c cancellation_type::total */ template <typename ConstBufferSequence, ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code,- std::size_t)) WriteHandler+ std::size_t)) WriteToken ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(executor_type)>- ASIO_INITFN_AUTO_RESULT_TYPE(WriteHandler,+ ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX(WriteToken, void (asio::error_code, std::size_t)) async_send(const ConstBufferSequence& buffers, socket_base::message_flags flags,- ASIO_MOVE_ARG(WriteHandler) handler+ ASIO_MOVE_ARG(WriteToken) token ASIO_DEFAULT_COMPLETION_TOKEN(executor_type))+ ASIO_INITFN_AUTO_RESULT_TYPE_SUFFIX((+ async_initiate<WriteToken,+ void (asio::error_code, std::size_t)>(+ declval<initiate_async_send>(), token, buffers, flags))) {- return async_initiate<WriteHandler,+ return async_initiate<WriteToken, void (asio::error_code, std::size_t)>(- initiate_async_send(this), handler, buffers, flags);+ initiate_async_send(this), token, buffers, flags); } /// Send a datagram to the specified endpoint.@@ -598,28 +653,34 @@ /// Start an asynchronous send. /** * This function is used to asynchronously send a datagram to the specified- * remote endpoint. The function call always returns immediately.+ * remote endpoint. It is an initiating function for an @ref+ * asynchronous_operation, and always returns immediately. * * @param buffers One or more data buffers to be sent to the remote endpoint. * Although the buffers object may be copied as necessary, ownership of the * underlying memory blocks is retained by the caller, which must guarantee- * that they remain valid until the handler is called.+ * that they remain valid until the completion handler is called. * * @param destination The remote endpoint to which the data will be sent. * Copies will be made of the endpoint as required. *- * @param handler The handler to be called when the send operation completes.- * Copies will be made of the handler as required. The function signature of- * the handler must be:+ * @param token The @ref completion_token that will be used to produce a+ * completion handler, which will be called when the send completes. Potential+ * completion tokens include @ref use_future, @ref use_awaitable, @ref+ * yield_context, or a function object with the correct completion signature.+ * The function signature of the completion handler must be: * @code void handler( * const asio::error_code& error, // Result of operation.- * std::size_t bytes_transferred // Number of bytes sent.+ * std::size_t bytes_transferred // Number of bytes sent. * ); @endcode * Regardless of whether the asynchronous operation completes immediately or- * not, the handler will not be invoked from within this function. On- * immediate completion, invocation of the handler will be performed in a+ * not, the completion handler will not be invoked from within this function.+ * On immediate completion, invocation of the handler will be performed in a * manner equivalent to using asio::post(). *+ * @par Completion Signature+ * @code void(asio::error_code, std::size_t) @endcode+ * * @par Example * To send a single data buffer use the @ref buffer function as follows: * @code@@ -631,65 +692,102 @@ * See the @ref buffer documentation for information on sending multiple * buffers in one go, and how to use it with arrays, boost::array or * std::vector.+ *+ * @par Per-Operation Cancellation+ * On POSIX or Windows operating systems, this asynchronous operation supports+ * cancellation for the following asio::cancellation_type values:+ *+ * @li @c cancellation_type::terminal+ *+ * @li @c cancellation_type::partial+ *+ * @li @c cancellation_type::total */ template <typename ConstBufferSequence, ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code,- std::size_t)) WriteHandler+ std::size_t)) WriteToken ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(executor_type)>- ASIO_INITFN_AUTO_RESULT_TYPE(WriteHandler,+ ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX(WriteToken, void (asio::error_code, std::size_t)) async_send_to(const ConstBufferSequence& buffers, const endpoint_type& destination,- ASIO_MOVE_ARG(WriteHandler) handler+ ASIO_MOVE_ARG(WriteToken) token ASIO_DEFAULT_COMPLETION_TOKEN(executor_type))+ ASIO_INITFN_AUTO_RESULT_TYPE_SUFFIX((+ async_initiate<WriteToken,+ void (asio::error_code, std::size_t)>(+ declval<initiate_async_send_to>(), token, buffers,+ destination, socket_base::message_flags(0)))) {- return async_initiate<WriteHandler,+ return async_initiate<WriteToken, void (asio::error_code, std::size_t)>(- initiate_async_send_to(this), handler, buffers,+ initiate_async_send_to(this), token, buffers, destination, socket_base::message_flags(0)); } /// Start an asynchronous send. /** * This function is used to asynchronously send a datagram to the specified- * remote endpoint. The function call always returns immediately.+ * remote endpoint. It is an initiating function for an @ref+ * asynchronous_operation, and always returns immediately. * * @param buffers One or more data buffers to be sent to the remote endpoint. * Although the buffers object may be copied as necessary, ownership of the * underlying memory blocks is retained by the caller, which must guarantee- * that they remain valid until the handler is called.+ * that they remain valid until the completion handler is called. * * @param flags Flags specifying how the send call is to be made. * * @param destination The remote endpoint to which the data will be sent. * Copies will be made of the endpoint as required. *- * @param handler The handler to be called when the send operation completes.- * Copies will be made of the handler as required. The function signature of- * the handler must be:+ * @param token The @ref completion_token that will be used to produce a+ * completion handler, which will be called when the send completes. Potential+ * completion tokens include @ref use_future, @ref use_awaitable, @ref+ * yield_context, or a function object with the correct completion signature.+ * The function signature of the completion handler must be: * @code void handler( * const asio::error_code& error, // Result of operation.- * std::size_t bytes_transferred // Number of bytes sent.+ * std::size_t bytes_transferred // Number of bytes sent. * ); @endcode * Regardless of whether the asynchronous operation completes immediately or- * not, the handler will not be invoked from within this function. On- * immediate completion, invocation of the handler will be performed in a+ * not, the completion handler will not be invoked from within this function.+ * On immediate completion, invocation of the handler will be performed in a * manner equivalent to using asio::post().+ *+ * @par Completion Signature+ * @code void(asio::error_code, std::size_t) @endcode+ *+ * @par Per-Operation Cancellation+ * On POSIX or Windows operating systems, this asynchronous operation supports+ * cancellation for the following asio::cancellation_type values:+ *+ * @li @c cancellation_type::terminal+ *+ * @li @c cancellation_type::partial+ *+ * @li @c cancellation_type::total */ template <typename ConstBufferSequence, ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code,- std::size_t)) WriteHandler+ std::size_t)) WriteToken ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(executor_type)>- ASIO_INITFN_AUTO_RESULT_TYPE(WriteHandler,+ ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX(WriteToken, void (asio::error_code, std::size_t)) async_send_to(const ConstBufferSequence& buffers, const endpoint_type& destination, socket_base::message_flags flags,- ASIO_MOVE_ARG(WriteHandler) handler+ ASIO_MOVE_ARG(WriteToken) token ASIO_DEFAULT_COMPLETION_TOKEN(executor_type))+ ASIO_INITFN_AUTO_RESULT_TYPE_SUFFIX((+ async_initiate<WriteToken,+ void (asio::error_code, std::size_t)>(+ declval<initiate_async_send_to>(), token,+ buffers, destination, flags))) {- return async_initiate<WriteHandler,+ return async_initiate<WriteToken, void (asio::error_code, std::size_t)>(- initiate_async_send_to(this), handler, buffers, destination, flags);+ initiate_async_send_to(this), token,+ buffers, destination, flags); } /// Receive some data on a connected socket.@@ -784,25 +882,31 @@ /// Start an asynchronous receive on a connected socket. /** * This function is used to asynchronously receive data from the datagram- * socket. The function call always returns immediately.+ * socket. It is an initiating function for an @ref asynchronous_operation,+ * and always returns immediately. * * @param buffers One or more buffers into which the data will be received. * Although the buffers object may be copied as necessary, ownership of the * underlying memory blocks is retained by the caller, which must guarantee- * that they remain valid until the handler is called.+ * that they remain valid until the completion handler is called. *- * @param handler The handler to be called when the receive operation- * completes. Copies will be made of the handler as required. The function- * signature of the handler must be:+ * @param token The @ref completion_token that will be used to produce a+ * completion handler, which will be called when the receive completes.+ * Potential completion tokens include @ref use_future, @ref use_awaitable,+ * @ref yield_context, or a function object with the correct completion+ * signature. The function signature of the completion handler must be: * @code void handler( * const asio::error_code& error, // Result of operation.- * std::size_t bytes_transferred // Number of bytes received.+ * std::size_t bytes_transferred // Number of bytes received. * ); @endcode * Regardless of whether the asynchronous operation completes immediately or- * not, the handler will not be invoked from within this function. On- * immediate completion, invocation of the handler will be performed in a+ * not, the completion handler will not be invoked from within this function.+ * On immediate completion, invocation of the handler will be performed in a * manner equivalent to using asio::post(). *+ * @par Completion Signature+ * @code void(asio::error_code, std::size_t) @endcode+ * * @note The async_receive operation can only be used with a connected socket. * Use the async_receive_from function to receive data on an unconnected * datagram socket.@@ -816,65 +920,100 @@ * See the @ref buffer documentation for information on receiving into * multiple buffers in one go, and how to use it with arrays, boost::array or * std::vector.+ *+ * @par Per-Operation Cancellation+ * On POSIX or Windows operating systems, this asynchronous operation supports+ * cancellation for the following asio::cancellation_type values:+ *+ * @li @c cancellation_type::terminal+ *+ * @li @c cancellation_type::partial+ *+ * @li @c cancellation_type::total */ template <typename MutableBufferSequence, ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code,- std::size_t)) ReadHandler+ std::size_t)) ReadToken ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(executor_type)>- ASIO_INITFN_AUTO_RESULT_TYPE(ReadHandler,+ ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX(ReadToken, void (asio::error_code, std::size_t)) async_receive(const MutableBufferSequence& buffers,- ASIO_MOVE_ARG(ReadHandler) handler+ ASIO_MOVE_ARG(ReadToken) token ASIO_DEFAULT_COMPLETION_TOKEN(executor_type))+ ASIO_INITFN_AUTO_RESULT_TYPE_SUFFIX((+ async_initiate<ReadToken,+ void (asio::error_code, std::size_t)>(+ declval<initiate_async_receive>(), token,+ buffers, socket_base::message_flags(0)))) {- return async_initiate<ReadHandler,+ return async_initiate<ReadToken, void (asio::error_code, std::size_t)>(- initiate_async_receive(this), handler,+ initiate_async_receive(this), token, buffers, socket_base::message_flags(0)); } /// Start an asynchronous receive on a connected socket. /** * This function is used to asynchronously receive data from the datagram- * socket. The function call always returns immediately.+ * socket. It is an initiating function for an @ref asynchronous_operation,+ * and always returns immediately. * * @param buffers One or more buffers into which the data will be received. * Although the buffers object may be copied as necessary, ownership of the * underlying memory blocks is retained by the caller, which must guarantee- * that they remain valid until the handler is called.+ * that they remain valid until the completion handler is called. * * @param flags Flags specifying how the receive call is to be made. *- * @param handler The handler to be called when the receive operation- * completes. Copies will be made of the handler as required. The function- * signature of the handler must be:+ * @param token The @ref completion_token that will be used to produce a+ * completion handler, which will be called when the receive completes.+ * Potential completion tokens include @ref use_future, @ref use_awaitable,+ * @ref yield_context, or a function object with the correct completion+ * signature. The function signature of the completion handler must be: * @code void handler( * const asio::error_code& error, // Result of operation.- * std::size_t bytes_transferred // Number of bytes received.+ * std::size_t bytes_transferred // Number of bytes received. * ); @endcode * Regardless of whether the asynchronous operation completes immediately or- * not, the handler will not be invoked from within this function. On- * immediate completion, invocation of the handler will be performed in a+ * not, the completion handler will not be invoked from within this function.+ * On immediate completion, invocation of the handler will be performed in a * manner equivalent to using asio::post(). *+ * @par Completion Signature+ * @code void(asio::error_code, std::size_t) @endcode+ * * @note The async_receive operation can only be used with a connected socket. * Use the async_receive_from function to receive data on an unconnected * datagram socket.+ *+ * @par Per-Operation Cancellation+ * On POSIX or Windows operating systems, this asynchronous operation supports+ * cancellation for the following asio::cancellation_type values:+ *+ * @li @c cancellation_type::terminal+ *+ * @li @c cancellation_type::partial+ *+ * @li @c cancellation_type::total */ template <typename MutableBufferSequence, ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code,- std::size_t)) ReadHandler+ std::size_t)) ReadToken ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(executor_type)>- ASIO_INITFN_AUTO_RESULT_TYPE(ReadHandler,+ ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX(ReadToken, void (asio::error_code, std::size_t)) async_receive(const MutableBufferSequence& buffers, socket_base::message_flags flags,- ASIO_MOVE_ARG(ReadHandler) handler+ ASIO_MOVE_ARG(ReadToken) token ASIO_DEFAULT_COMPLETION_TOKEN(executor_type))+ ASIO_INITFN_AUTO_RESULT_TYPE_SUFFIX((+ async_initiate<ReadToken,+ void (asio::error_code, std::size_t)>(+ declval<initiate_async_receive>(), token, buffers, flags))) {- return async_initiate<ReadHandler,+ return async_initiate<ReadToken, void (asio::error_code, std::size_t)>(- initiate_async_receive(this), handler, buffers, flags);+ initiate_async_receive(this), token, buffers, flags); } /// Receive a datagram with the endpoint of the sender.@@ -968,31 +1107,37 @@ /// Start an asynchronous receive. /**- * This function is used to asynchronously receive a datagram. The function- * call always returns immediately.+ * This function is used to asynchronously receive a datagram. It is an+ * initiating function for an @ref asynchronous_operation, and always returns+ * immediately. * * @param buffers One or more buffers into which the data will be received. * Although the buffers object may be copied as necessary, ownership of the * underlying memory blocks is retained by the caller, which must guarantee- * that they remain valid until the handler is called.+ * that they remain valid until the completion handler is called. * * @param sender_endpoint An endpoint object that receives the endpoint of * the remote sender of the datagram. Ownership of the sender_endpoint object * is retained by the caller, which must guarantee that it is valid until the- * handler is called.+ * completion handler is called. *- * @param handler The handler to be called when the receive operation- * completes. Copies will be made of the handler as required. The function- * signature of the handler must be:+ * @param token The @ref completion_token that will be used to produce a+ * completion handler, which will be called when the receive completes.+ * Potential completion tokens include @ref use_future, @ref use_awaitable,+ * @ref yield_context, or a function object with the correct completion+ * signature. The function signature of the completion handler must be: * @code void handler( * const asio::error_code& error, // Result of operation.- * std::size_t bytes_transferred // Number of bytes received.+ * std::size_t bytes_transferred // Number of bytes received. * ); @endcode * Regardless of whether the asynchronous operation completes immediately or- * not, the handler will not be invoked from within this function. On- * immediate completion, invocation of the handler will be performed in a+ * not, the completion handler will not be invoked from within this function.+ * On immediate completion, invocation of the handler will be performed in a * manner equivalent to using asio::post(). *+ * @par Completion Signature+ * @code void(asio::error_code, std::size_t) @endcode+ * * @par Example * To receive into a single data buffer use the @ref buffer function as * follows:@@ -1001,67 +1146,103 @@ * See the @ref buffer documentation for information on receiving into * multiple buffers in one go, and how to use it with arrays, boost::array or * std::vector.+ *+ * @par Per-Operation Cancellation+ * On POSIX or Windows operating systems, this asynchronous operation supports+ * cancellation for the following asio::cancellation_type values:+ *+ * @li @c cancellation_type::terminal+ *+ * @li @c cancellation_type::partial+ *+ * @li @c cancellation_type::total */ template <typename MutableBufferSequence, ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code,- std::size_t)) ReadHandler+ std::size_t)) ReadToken ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(executor_type)>- ASIO_INITFN_AUTO_RESULT_TYPE(ReadHandler,+ ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX(ReadToken, void (asio::error_code, std::size_t)) async_receive_from(const MutableBufferSequence& buffers, endpoint_type& sender_endpoint,- ASIO_MOVE_ARG(ReadHandler) handler+ ASIO_MOVE_ARG(ReadToken) token ASIO_DEFAULT_COMPLETION_TOKEN(executor_type))+ ASIO_INITFN_AUTO_RESULT_TYPE_SUFFIX((+ async_initiate<ReadToken,+ void (asio::error_code, std::size_t)>(+ declval<initiate_async_receive_from>(), token, buffers,+ &sender_endpoint, socket_base::message_flags(0)))) {- return async_initiate<ReadHandler,+ return async_initiate<ReadToken, void (asio::error_code, std::size_t)>(- initiate_async_receive_from(this), handler, buffers,+ initiate_async_receive_from(this), token, buffers, &sender_endpoint, socket_base::message_flags(0)); } /// Start an asynchronous receive. /**- * This function is used to asynchronously receive a datagram. The function- * call always returns immediately.+ * This function is used to asynchronously receive a datagram. It is an+ * initiating function for an @ref asynchronous_operation, and always returns+ * immediately. * * @param buffers One or more buffers into which the data will be received. * Although the buffers object may be copied as necessary, ownership of the * underlying memory blocks is retained by the caller, which must guarantee- * that they remain valid until the handler is called.+ * that they remain valid until the completion handler is called. * * @param sender_endpoint An endpoint object that receives the endpoint of * the remote sender of the datagram. Ownership of the sender_endpoint object * is retained by the caller, which must guarantee that it is valid until the- * handler is called.+ * completion handler is called. * * @param flags Flags specifying how the receive call is to be made. *- * @param handler The handler to be called when the receive operation- * completes. Copies will be made of the handler as required. The function- * signature of the handler must be:+ * @param token The @ref completion_token that will be used to produce a+ * completion handler, which will be called when the receive completes.+ * Potential completion tokens include @ref use_future, @ref use_awaitable,+ * @ref yield_context, or a function object with the correct completion+ * signature. The function signature of the completion handler must be: * @code void handler( * const asio::error_code& error, // Result of operation.- * std::size_t bytes_transferred // Number of bytes received.+ * std::size_t bytes_transferred // Number of bytes received. * ); @endcode * Regardless of whether the asynchronous operation completes immediately or- * not, the handler will not be invoked from within this function. On- * immediate completion, invocation of the handler will be performed in a+ * not, the completion handler will not be invoked from within this function.+ * On immediate completion, invocation of the handler will be performed in a * manner equivalent to using asio::post().+ *+ * @par Completion Signature+ * @code void(asio::error_code, std::size_t) @endcode+ *+ * @par Per-Operation Cancellation+ * On POSIX or Windows operating systems, this asynchronous operation supports+ * cancellation for the following asio::cancellation_type values:+ *+ * @li @c cancellation_type::terminal+ *+ * @li @c cancellation_type::partial+ *+ * @li @c cancellation_type::total */ template <typename MutableBufferSequence, ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code,- std::size_t)) ReadHandler+ std::size_t)) ReadToken ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(executor_type)>- ASIO_INITFN_AUTO_RESULT_TYPE(ReadHandler,+ ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX(ReadToken, void (asio::error_code, std::size_t)) async_receive_from(const MutableBufferSequence& buffers, endpoint_type& sender_endpoint, socket_base::message_flags flags,- ASIO_MOVE_ARG(ReadHandler) handler+ ASIO_MOVE_ARG(ReadToken) token ASIO_DEFAULT_COMPLETION_TOKEN(executor_type))+ ASIO_INITFN_AUTO_RESULT_TYPE_SUFFIX((+ async_initiate<ReadToken,+ void (asio::error_code, std::size_t)>(+ declval<initiate_async_receive_from>(), token,+ buffers, &sender_endpoint, flags))) {- return async_initiate<ReadHandler,+ return async_initiate<ReadToken, void (asio::error_code, std::size_t)>(- initiate_async_receive_from(this), handler,+ initiate_async_receive_from(this), token, buffers, &sender_endpoint, flags); } @@ -1081,7 +1262,7 @@ { } - executor_type get_executor() const ASIO_NOEXCEPT+ const executor_type& get_executor() const ASIO_NOEXCEPT { return self_->get_executor(); }@@ -1115,7 +1296,7 @@ { } - executor_type get_executor() const ASIO_NOEXCEPT+ const executor_type& get_executor() const ASIO_NOEXCEPT { return self_->get_executor(); }@@ -1149,7 +1330,7 @@ { } - executor_type get_executor() const ASIO_NOEXCEPT+ const executor_type& get_executor() const ASIO_NOEXCEPT { return self_->get_executor(); }@@ -1183,7 +1364,7 @@ { } - executor_type get_executor() const ASIO_NOEXCEPT+ const executor_type& get_executor() const ASIO_NOEXCEPT { return self_->get_executor(); }
link/modules/asio-standalone/asio/include/asio/basic_deadline_timer.hpp view
@@ -2,7 +2,7 @@ // basic_deadline_timer.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -128,6 +128,9 @@ typename Executor = any_io_executor> class basic_deadline_timer {+private:+ class initiate_async_wait;+ public: /// The type of the executor associated with the object. typedef Executor executor_type;@@ -159,7 +162,7 @@ * dispatch handlers for any asynchronous operations performed on the timer. */ explicit basic_deadline_timer(const executor_type& ex)- : impl_(ex)+ : impl_(0, ex) { } @@ -175,10 +178,10 @@ */ template <typename ExecutionContext> explicit basic_deadline_timer(ExecutionContext& context,- typename enable_if<+ typename constraint< is_convertible<ExecutionContext&, execution_context&>::value- >::type* = 0)- : impl_(context)+ >::type = 0)+ : impl_(0, 0, context) { } @@ -193,7 +196,7 @@ * as an absolute time. */ basic_deadline_timer(const executor_type& ex, const time_type& expiry_time)- : impl_(ex)+ : impl_(0, ex) { asio::error_code ec; impl_.get_service().expires_at(impl_.get_implementation(), expiry_time, ec);@@ -213,10 +216,10 @@ */ template <typename ExecutionContext> basic_deadline_timer(ExecutionContext& context, const time_type& expiry_time,- typename enable_if<+ typename constraint< is_convertible<ExecutionContext&, execution_context&>::value- >::type* = 0)- : impl_(context)+ >::type = 0)+ : impl_(0, 0, context) { asio::error_code ec; impl_.get_service().expires_at(impl_.get_implementation(), expiry_time, ec);@@ -235,7 +238,7 @@ */ basic_deadline_timer(const executor_type& ex, const duration_type& expiry_time)- : impl_(ex)+ : impl_(0, ex) { asio::error_code ec; impl_.get_service().expires_from_now(@@ -257,10 +260,10 @@ template <typename ExecutionContext> basic_deadline_timer(ExecutionContext& context, const duration_type& expiry_time,- typename enable_if<+ typename constraint< is_convertible<ExecutionContext&, execution_context&>::value- >::type* = 0)- : impl_(context)+ >::type = 0)+ : impl_(0, 0, context) { asio::error_code ec; impl_.get_service().expires_from_now(@@ -314,7 +317,7 @@ } /// Get the executor associated with the object.- executor_type get_executor() ASIO_NOEXCEPT+ const executor_type& get_executor() ASIO_NOEXCEPT { return impl_.get_executor(); }@@ -607,38 +610,57 @@ /// Start an asynchronous wait on the timer. /** * This function may be used to initiate an asynchronous wait against the- * timer. It always returns immediately.+ * timer. It is an initiating function for an @ref asynchronous_operation,+ * and always returns immediately. *- * For each call to async_wait(), the supplied handler will be called exactly- * once. The handler will be called when:+ * For each call to async_wait(), the completion handler will be called+ * exactly once. The completion handler will be called when: * * @li The timer has expired. * * @li The timer was cancelled, in which case the handler is passed the error * code asio::error::operation_aborted. *- * @param handler The handler to be called when the timer expires. Copies- * will be made of the handler as required. The function signature of the- * handler must be:+ * @param token The @ref completion_token that will be used to produce a+ * completion handler, which will be called when the timer expires. Potential+ * completion tokens include @ref use_future, @ref use_awaitable, @ref+ * yield_context, or a function object with the correct completion signature.+ * The function signature of the completion handler must be: * @code void handler( * const asio::error_code& error // Result of operation. * ); @endcode * Regardless of whether the asynchronous operation completes immediately or- * not, the handler will not be invoked from within this function. On- * immediate completion, invocation of the handler will be performed in a+ * not, the completion handler will not be invoked from within this function.+ * On immediate completion, invocation of the handler will be performed in a * manner equivalent to using asio::post().+ *+ * @par Completion Signature+ * @code void(asio::error_code) @endcode+ *+ * @par Per-Operation Cancellation+ * This asynchronous operation supports cancellation for the following+ * asio::cancellation_type values:+ *+ * @li @c cancellation_type::terminal+ *+ * @li @c cancellation_type::partial+ *+ * @li @c cancellation_type::total */ template < ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code))- WaitHandler ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(executor_type)>- ASIO_INITFN_AUTO_RESULT_TYPE(WaitHandler,+ WaitToken ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(executor_type)>+ ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX(WaitToken, void (asio::error_code)) async_wait(- ASIO_MOVE_ARG(WaitHandler) handler+ ASIO_MOVE_ARG(WaitToken) token ASIO_DEFAULT_COMPLETION_TOKEN(executor_type))+ ASIO_INITFN_AUTO_RESULT_TYPE_SUFFIX((+ async_initiate<WaitToken, void (asio::error_code)>(+ declval<initiate_async_wait>(), token))) {- return async_initiate<WaitHandler, void (asio::error_code)>(- initiate_async_wait(this), handler);+ return async_initiate<WaitToken, void (asio::error_code)>(+ initiate_async_wait(this), token); } private:@@ -657,7 +679,7 @@ { } - executor_type get_executor() const ASIO_NOEXCEPT+ const executor_type& get_executor() const ASIO_NOEXCEPT { return self_->get_executor(); }
+ link/modules/asio-standalone/asio/include/asio/basic_file.hpp view
@@ -0,0 +1,829 @@+//+// basic_file.hpp+// ~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com)+//+// Distributed under the Boost Software License, Version 1.0. (See accompanying+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)+//++#ifndef ASIO_BASIC_FILE_HPP+#define ASIO_BASIC_FILE_HPP++#if defined(_MSC_VER) && (_MSC_VER >= 1200)+# pragma once+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)++#include "asio/detail/config.hpp"++#if defined(ASIO_HAS_FILE) \+ || defined(GENERATING_DOCUMENTATION)++#include <string>+#include "asio/any_io_executor.hpp"+#include "asio/async_result.hpp"+#include "asio/detail/cstdint.hpp"+#include "asio/detail/handler_type_requirements.hpp"+#include "asio/detail/io_object_impl.hpp"+#include "asio/detail/non_const_lvalue.hpp"+#include "asio/detail/throw_error.hpp"+#include "asio/detail/type_traits.hpp"+#include "asio/error.hpp"+#include "asio/execution_context.hpp"+#include "asio/post.hpp"+#include "asio/file_base.hpp"+#if defined(ASIO_HAS_IOCP)+# include "asio/detail/win_iocp_file_service.hpp"+#elif defined(ASIO_HAS_IO_URING)+# include "asio/detail/io_uring_file_service.hpp"+#endif++#if defined(ASIO_HAS_MOVE)+# include <utility>+#endif // defined(ASIO_HAS_MOVE)++#include "asio/detail/push_options.hpp"++namespace asio {++#if !defined(ASIO_BASIC_FILE_FWD_DECL)+#define ASIO_BASIC_FILE_FWD_DECL++// Forward declaration with defaulted arguments.+template <typename Executor = any_io_executor>+class basic_file;++#endif // !defined(ASIO_BASIC_FILE_FWD_DECL)++/// Provides file functionality.+/**+ * The basic_file class template provides functionality that is common to both+ * stream-oriented and random-access files.+ *+ * @par Thread Safety+ * @e Distinct @e objects: Safe.@n+ * @e Shared @e objects: Unsafe.+ */+template <typename Executor>+class basic_file+ : public file_base+{+public:+ /// The type of the executor associated with the object.+ typedef Executor executor_type;++ /// Rebinds the file type to another executor.+ template <typename Executor1>+ struct rebind_executor+ {+ /// The file type when rebound to the specified executor.+ typedef basic_file<Executor1> other;+ };++ /// The native representation of a file.+#if defined(GENERATING_DOCUMENTATION)+ typedef implementation_defined native_handle_type;+#elif defined(ASIO_HAS_IOCP)+ typedef detail::win_iocp_file_service::native_handle_type native_handle_type;+#elif defined(ASIO_HAS_IO_URING)+ typedef detail::io_uring_file_service::native_handle_type native_handle_type;+#endif++ /// Construct a basic_file without opening it.+ /**+ * This constructor initialises a file without opening it.+ *+ * @param ex The I/O executor that the file will use, by default, to+ * dispatch handlers for any asynchronous operations performed on the file.+ */+ explicit basic_file(const executor_type& ex)+ : impl_(0, ex)+ {+ }++ /// Construct a basic_file without opening it.+ /**+ * This constructor initialises a file without opening it.+ *+ * @param context An execution context which provides the I/O executor that+ * the file will use, by default, to dispatch handlers for any asynchronous+ * operations performed on the file.+ */+ template <typename ExecutionContext>+ explicit basic_file(ExecutionContext& context,+ typename constraint<+ is_convertible<ExecutionContext&, execution_context&>::value,+ defaulted_constraint+ >::type = defaulted_constraint())+ : impl_(0, 0, context)+ {+ }++ /// Construct and open a basic_file.+ /**+ * This constructor initialises a file and opens it.+ *+ * @param ex The I/O executor that the file will use, by default, to+ * dispatch handlers for any asynchronous operations performed on the file.+ *+ * @param path The path name identifying the file to be opened.+ *+ * @param open_flags A set of flags that determine how the file should be+ * opened.+ */+ explicit basic_file(const executor_type& ex,+ const char* path, file_base::flags open_flags)+ : impl_(0, ex)+ {+ asio::error_code ec;+ impl_.get_service().open(impl_.get_implementation(), path, open_flags, ec);+ asio::detail::throw_error(ec, "open");+ }++ /// Construct a basic_file without opening it.+ /**+ * This constructor initialises a file and opens it.+ *+ * @param context An execution context which provides the I/O executor that+ * the file will use, by default, to dispatch handlers for any asynchronous+ * operations performed on the file.+ *+ * @param path The path name identifying the file to be opened.+ *+ * @param open_flags A set of flags that determine how the file should be+ * opened.+ */+ template <typename ExecutionContext>+ explicit basic_file(ExecutionContext& context,+ const char* path, file_base::flags open_flags,+ typename constraint<+ is_convertible<ExecutionContext&, execution_context&>::value,+ defaulted_constraint+ >::type = defaulted_constraint())+ : impl_(0, 0, context)+ {+ asio::error_code ec;+ impl_.get_service().open(impl_.get_implementation(), path, open_flags, ec);+ asio::detail::throw_error(ec, "open");+ }++ /// Construct and open a basic_file.+ /**+ * This constructor initialises a file and opens it.+ *+ * @param ex The I/O executor that the file will use, by default, to+ * dispatch handlers for any asynchronous operations performed on the file.+ *+ * @param path The path name identifying the file to be opened.+ *+ * @param open_flags A set of flags that determine how the file should be+ * opened.+ */+ explicit basic_file(const executor_type& ex,+ const std::string& path, file_base::flags open_flags)+ : impl_(0, ex)+ {+ asio::error_code ec;+ impl_.get_service().open(impl_.get_implementation(),+ path.c_str(), open_flags, ec);+ asio::detail::throw_error(ec, "open");+ }++ /// Construct a basic_file without opening it.+ /**+ * This constructor initialises a file and opens it.+ *+ * @param context An execution context which provides the I/O executor that+ * the file will use, by default, to dispatch handlers for any asynchronous+ * operations performed on the file.+ *+ * @param path The path name identifying the file to be opened.+ *+ * @param open_flags A set of flags that determine how the file should be+ * opened.+ */+ template <typename ExecutionContext>+ explicit basic_file(ExecutionContext& context,+ const std::string& path, file_base::flags open_flags,+ typename constraint<+ is_convertible<ExecutionContext&, execution_context&>::value,+ defaulted_constraint+ >::type = defaulted_constraint())+ : impl_(0, 0, context)+ {+ asio::error_code ec;+ impl_.get_service().open(impl_.get_implementation(),+ path.c_str(), open_flags, ec);+ asio::detail::throw_error(ec, "open");+ }++ /// Construct a basic_file on an existing native file handle.+ /**+ * This constructor initialises a file object to hold an existing native file.+ *+ * @param ex The I/O executor that the file will use, by default, to+ * dispatch handlers for any asynchronous operations performed on the file.+ *+ * @param native_file A native file handle.+ *+ * @throws asio::system_error Thrown on failure.+ */+ basic_file(const executor_type& ex, const native_handle_type& native_file)+ : impl_(0, ex)+ {+ asio::error_code ec;+ impl_.get_service().assign(+ impl_.get_implementation(), native_file, ec);+ asio::detail::throw_error(ec, "assign");+ }++ /// Construct a basic_file on an existing native file.+ /**+ * This constructor initialises a file object to hold an existing native file.+ *+ * @param context An execution context which provides the I/O executor that+ * the file will use, by default, to dispatch handlers for any asynchronous+ * operations performed on the file.+ *+ * @param native_file A native file.+ *+ * @throws asio::system_error Thrown on failure.+ */+ template <typename ExecutionContext>+ basic_file(ExecutionContext& context, const native_handle_type& native_file,+ typename constraint<+ is_convertible<ExecutionContext&, execution_context&>::value,+ defaulted_constraint+ >::type = defaulted_constraint())+ : impl_(0, 0, context)+ {+ asio::error_code ec;+ impl_.get_service().assign(+ impl_.get_implementation(), native_file, ec);+ asio::detail::throw_error(ec, "assign");+ }++#if defined(ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)+ /// Move-construct a basic_file from another.+ /**+ * This constructor moves a file from one object to another.+ *+ * @param other The other basic_file object from which the move will+ * occur.+ *+ * @note Following the move, the moved-from object is in the same state as if+ * constructed using the @c basic_file(const executor_type&) constructor.+ */+ basic_file(basic_file&& other) ASIO_NOEXCEPT+ : impl_(std::move(other.impl_))+ {+ }++ /// Move-assign a basic_file from another.+ /**+ * This assignment operator moves a file from one object to another.+ *+ * @param other The other basic_file object from which the move will+ * occur.+ *+ * @note Following the move, the moved-from object is in the same state as if+ * constructed using the @c basic_file(const executor_type&) constructor.+ */+ basic_file& operator=(basic_file&& other)+ {+ impl_ = std::move(other.impl_);+ return *this;+ }++ // All files have access to each other's implementations.+ template <typename Executor1>+ friend class basic_file;++ /// Move-construct a basic_file from a file of another executor type.+ /**+ * This constructor moves a file from one object to another.+ *+ * @param other The other basic_file object from which the move will+ * occur.+ *+ * @note Following the move, the moved-from object is in the same state as if+ * constructed using the @c basic_file(const executor_type&) constructor.+ */+ template <typename Executor1>+ basic_file(basic_file<Executor1>&& other,+ typename constraint<+ is_convertible<Executor1, Executor>::value,+ defaulted_constraint+ >::type = defaulted_constraint())+ : impl_(std::move(other.impl_))+ {+ }++ /// Move-assign a basic_file from a file of another executor type.+ /**+ * This assignment operator moves a file from one object to another.+ *+ * @param other The other basic_file object from which the move will+ * occur.+ *+ * @note Following the move, the moved-from object is in the same state as if+ * constructed using the @c basic_file(const executor_type&) constructor.+ */+ template <typename Executor1>+ typename constraint<+ is_convertible<Executor1, Executor>::value,+ basic_file&+ >::type operator=(basic_file<Executor1>&& other)+ {+ basic_file tmp(std::move(other));+ impl_ = std::move(tmp.impl_);+ return *this;+ }+#endif // defined(ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)++ /// Get the executor associated with the object.+ const executor_type& get_executor() ASIO_NOEXCEPT+ {+ return impl_.get_executor();+ }++ /// Open the file using the specified path.+ /**+ * This function opens the file so that it will use the specified path.+ *+ * @param path The path name identifying the file to be opened.+ *+ * @param open_flags A set of flags that determine how the file should be+ * opened.+ *+ * @throws asio::system_error Thrown on failure.+ *+ * @par Example+ * @code+ * asio::stream_file file(my_context);+ * file.open("/path/to/my/file", asio::stream_file::read_only);+ * @endcode+ */+ void open(const char* path, file_base::flags open_flags)+ {+ asio::error_code ec;+ impl_.get_service().open(impl_.get_implementation(), path, open_flags, ec);+ asio::detail::throw_error(ec, "open");+ }++ /// Open the file using the specified path.+ /**+ * This function opens the file so that it will use the specified path.+ *+ * @param path The path name identifying the file to be opened.+ *+ * @param open_flags A set of flags that determine how the file should be+ * opened.+ *+ * @param ec Set to indicate what error occurred, if any.+ *+ * @par Example+ * @code+ * asio::stream_file file(my_context);+ * asio::error_code ec;+ * file.open("/path/to/my/file", asio::stream_file::read_only, ec);+ * if (ec)+ * {+ * // An error occurred.+ * }+ * @endcode+ */+ ASIO_SYNC_OP_VOID open(const char* path,+ file_base::flags open_flags, asio::error_code& ec)+ {+ impl_.get_service().open(impl_.get_implementation(), path, open_flags, ec);+ ASIO_SYNC_OP_VOID_RETURN(ec);+ }++ /// Open the file using the specified path.+ /**+ * This function opens the file so that it will use the specified path.+ *+ * @param path The path name identifying the file to be opened.+ *+ * @param open_flags A set of flags that determine how the file should be+ * opened.+ *+ * @throws asio::system_error Thrown on failure.+ *+ * @par Example+ * @code+ * asio::stream_file file(my_context);+ * file.open("/path/to/my/file", asio::stream_file::read_only);+ * @endcode+ */+ void open(const std::string& path, file_base::flags open_flags)+ {+ asio::error_code ec;+ impl_.get_service().open(impl_.get_implementation(),+ path.c_str(), open_flags, ec);+ asio::detail::throw_error(ec, "open");+ }++ /// Open the file using the specified path.+ /**+ * This function opens the file so that it will use the specified path.+ *+ * @param path The path name identifying the file to be opened.+ *+ * @param open_flags A set of flags that determine how the file should be+ * opened.+ *+ * @param ec Set to indicate what error occurred, if any.+ *+ * @par Example+ * @code+ * asio::stream_file file(my_context);+ * asio::error_code ec;+ * file.open("/path/to/my/file", asio::stream_file::read_only, ec);+ * if (ec)+ * {+ * // An error occurred.+ * }+ * @endcode+ */+ ASIO_SYNC_OP_VOID open(const std::string& path,+ file_base::flags open_flags, asio::error_code& ec)+ {+ impl_.get_service().open(impl_.get_implementation(),+ path.c_str(), open_flags, ec);+ ASIO_SYNC_OP_VOID_RETURN(ec);+ }++ /// Assign an existing native file to the file.+ /*+ * This function opens the file to hold an existing native file.+ *+ * @param native_file A native file.+ *+ * @throws asio::system_error Thrown on failure.+ */+ void assign(const native_handle_type& native_file)+ {+ asio::error_code ec;+ impl_.get_service().assign(+ impl_.get_implementation(), native_file, ec);+ asio::detail::throw_error(ec, "assign");+ }++ /// Assign an existing native file to the file.+ /*+ * This function opens the file to hold an existing native file.+ *+ * @param native_file A native file.+ *+ * @param ec Set to indicate what error occurred, if any.+ */+ ASIO_SYNC_OP_VOID assign(const native_handle_type& native_file,+ asio::error_code& ec)+ {+ impl_.get_service().assign(+ impl_.get_implementation(), native_file, ec);+ ASIO_SYNC_OP_VOID_RETURN(ec);+ }++ /// Determine whether the file is open.+ bool is_open() const+ {+ return impl_.get_service().is_open(impl_.get_implementation());+ }++ /// Close the file.+ /**+ * This function is used to close the file. Any asynchronous read or write+ * operations will be cancelled immediately, and will complete with the+ * asio::error::operation_aborted error.+ *+ * @throws asio::system_error Thrown on failure. Note that, even if+ * the function indicates an error, the underlying descriptor is closed.+ */+ void close()+ {+ asio::error_code ec;+ impl_.get_service().close(impl_.get_implementation(), ec);+ asio::detail::throw_error(ec, "close");+ }++ /// Close the file.+ /**+ * This function is used to close the file. Any asynchronous read or write+ * operations will be cancelled immediately, and will complete with the+ * asio::error::operation_aborted error.+ *+ * @param ec Set to indicate what error occurred, if any. Note that, even if+ * the function indicates an error, the underlying descriptor is closed.+ *+ * @par Example+ * @code+ * asio::stream_file file(my_context);+ * ...+ * asio::error_code ec;+ * file.close(ec);+ * if (ec)+ * {+ * // An error occurred.+ * }+ * @endcode+ */+ ASIO_SYNC_OP_VOID close(asio::error_code& ec)+ {+ impl_.get_service().close(impl_.get_implementation(), ec);+ ASIO_SYNC_OP_VOID_RETURN(ec);+ }++ /// Release ownership of the underlying native file.+ /**+ * This function causes all outstanding asynchronous read and write+ * operations to finish immediately, and the handlers for cancelled+ * operations will be passed the asio::error::operation_aborted error.+ * Ownership of the native file is then transferred to the caller.+ *+ * @throws asio::system_error Thrown on failure.+ *+ * @note This function is unsupported on Windows versions prior to Windows+ * 8.1, and will fail with asio::error::operation_not_supported on+ * these platforms.+ */+#if defined(ASIO_MSVC) && (ASIO_MSVC >= 1400) \+ && (!defined(_WIN32_WINNT) || _WIN32_WINNT < 0x0603)+ __declspec(deprecated("This function always fails with "+ "operation_not_supported when used on Windows versions "+ "prior to Windows 8.1."))+#endif+ native_handle_type release()+ {+ asio::error_code ec;+ native_handle_type s = impl_.get_service().release(+ impl_.get_implementation(), ec);+ asio::detail::throw_error(ec, "release");+ return s;+ }++ /// Release ownership of the underlying native file.+ /**+ * This function causes all outstanding asynchronous read and write+ * operations to finish immediately, and the handlers for cancelled+ * operations will be passed the asio::error::operation_aborted error.+ * Ownership of the native file is then transferred to the caller.+ *+ * @param ec Set to indicate what error occurred, if any.+ *+ * @note This function is unsupported on Windows versions prior to Windows+ * 8.1, and will fail with asio::error::operation_not_supported on+ * these platforms.+ */+#if defined(ASIO_MSVC) && (ASIO_MSVC >= 1400) \+ && (!defined(_WIN32_WINNT) || _WIN32_WINNT < 0x0603)+ __declspec(deprecated("This function always fails with "+ "operation_not_supported when used on Windows versions "+ "prior to Windows 8.1."))+#endif+ native_handle_type release(asio::error_code& ec)+ {+ return impl_.get_service().release(impl_.get_implementation(), ec);+ }++ /// Get the native file representation.+ /**+ * This function may be used to obtain the underlying representation of the+ * file. This is intended to allow access to native file functionality+ * that is not otherwise provided.+ */+ native_handle_type native_handle()+ {+ return impl_.get_service().native_handle(impl_.get_implementation());+ }++ /// Cancel all asynchronous operations associated with the file.+ /**+ * This function causes all outstanding asynchronous read and write+ * operations to finish immediately, and the handlers for cancelled+ * operations will be passed the asio::error::operation_aborted error.+ *+ * @throws asio::system_error Thrown on failure.+ *+ * @note Calls to cancel() will always fail with+ * asio::error::operation_not_supported when run on Windows XP, Windows+ * Server 2003, and earlier versions of Windows, unless+ * ASIO_ENABLE_CANCELIO is defined. However, the CancelIo function has+ * two issues that should be considered before enabling its use:+ *+ * @li It will only cancel asynchronous operations that were initiated in the+ * current thread.+ *+ * @li It can appear to complete without error, but the request to cancel the+ * unfinished operations may be silently ignored by the operating system.+ * Whether it works or not seems to depend on the drivers that are installed.+ *+ * For portable cancellation, consider using the close() function to+ * simultaneously cancel the outstanding operations and close the file.+ *+ * When running on Windows Vista, Windows Server 2008, and later, the+ * CancelIoEx function is always used. This function does not have the+ * problems described above.+ */+#if defined(ASIO_MSVC) && (ASIO_MSVC >= 1400) \+ && (!defined(_WIN32_WINNT) || _WIN32_WINNT < 0x0600) \+ && !defined(ASIO_ENABLE_CANCELIO)+ __declspec(deprecated("By default, this function always fails with "+ "operation_not_supported when used on Windows XP, Windows Server 2003, "+ "or earlier. Consult documentation for details."))+#endif+ void cancel()+ {+ asio::error_code ec;+ impl_.get_service().cancel(impl_.get_implementation(), ec);+ asio::detail::throw_error(ec, "cancel");+ }++ /// Cancel all asynchronous operations associated with the file.+ /**+ * This function causes all outstanding asynchronous read and write+ * operations to finish immediately, and the handlers for cancelled+ * operations will be passed the asio::error::operation_aborted error.+ *+ * @param ec Set to indicate what error occurred, if any.+ *+ * @note Calls to cancel() will always fail with+ * asio::error::operation_not_supported when run on Windows XP, Windows+ * Server 2003, and earlier versions of Windows, unless+ * ASIO_ENABLE_CANCELIO is defined. However, the CancelIo function has+ * two issues that should be considered before enabling its use:+ *+ * @li It will only cancel asynchronous operations that were initiated in the+ * current thread.+ *+ * @li It can appear to complete without error, but the request to cancel the+ * unfinished operations may be silently ignored by the operating system.+ * Whether it works or not seems to depend on the drivers that are installed.+ *+ * For portable cancellation, consider using the close() function to+ * simultaneously cancel the outstanding operations and close the file.+ *+ * When running on Windows Vista, Windows Server 2008, and later, the+ * CancelIoEx function is always used. This function does not have the+ * problems described above.+ */+#if defined(ASIO_MSVC) && (ASIO_MSVC >= 1400) \+ && (!defined(_WIN32_WINNT) || _WIN32_WINNT < 0x0600) \+ && !defined(ASIO_ENABLE_CANCELIO)+ __declspec(deprecated("By default, this function always fails with "+ "operation_not_supported when used on Windows XP, Windows Server 2003, "+ "or earlier. Consult documentation for details."))+#endif+ ASIO_SYNC_OP_VOID cancel(asio::error_code& ec)+ {+ impl_.get_service().cancel(impl_.get_implementation(), ec);+ ASIO_SYNC_OP_VOID_RETURN(ec);+ }++ /// Get the size of the file.+ /**+ * This function determines the size of the file, in bytes.+ *+ * @throws asio::system_error Thrown on failure.+ */+ uint64_t size() const+ {+ asio::error_code ec;+ uint64_t s = impl_.get_service().size(impl_.get_implementation(), ec);+ asio::detail::throw_error(ec, "size");+ return s;+ }++ /// Get the size of the file.+ /**+ * This function determines the size of the file, in bytes.+ *+ * @param ec Set to indicate what error occurred, if any.+ */+ uint64_t size(asio::error_code& ec) const+ {+ return impl_.get_service().size(impl_.get_implementation(), ec);+ }++ /// Alter the size of the file.+ /**+ * This function resizes the file to the specified size, in bytes. If the+ * current file size exceeds @c n then any extra data is discarded. If the+ * current size is less than @c n then the file is extended and filled with+ * zeroes.+ *+ * @param n The new size for the file.+ *+ * @throws asio::system_error Thrown on failure.+ */+ void resize(uint64_t n)+ {+ asio::error_code ec;+ impl_.get_service().resize(impl_.get_implementation(), n, ec);+ asio::detail::throw_error(ec, "resize");+ }++ /// Alter the size of the file.+ /**+ * This function resizes the file to the specified size, in bytes. If the+ * current file size exceeds @c n then any extra data is discarded. If the+ * current size is less than @c n then the file is extended and filled with+ * zeroes.+ *+ * @param n The new size for the file.+ *+ * @param ec Set to indicate what error occurred, if any.+ */+ ASIO_SYNC_OP_VOID resize(uint64_t n, asio::error_code& ec)+ {+ impl_.get_service().resize(impl_.get_implementation(), n, ec);+ ASIO_SYNC_OP_VOID_RETURN(ec);+ }++ /// Synchronise the file to disk.+ /**+ * This function synchronises the file data and metadata to disk. Note that+ * the semantics of this synchronisation vary between operation systems.+ *+ * @throws asio::system_error Thrown on failure.+ */+ void sync_all()+ {+ asio::error_code ec;+ impl_.get_service().sync_all(impl_.get_implementation(), ec);+ asio::detail::throw_error(ec, "sync_all");+ }++ /// Synchronise the file to disk.+ /**+ * This function synchronises the file data and metadata to disk. Note that+ * the semantics of this synchronisation vary between operation systems.+ *+ * @param ec Set to indicate what error occurred, if any.+ */+ ASIO_SYNC_OP_VOID sync_all(asio::error_code& ec)+ {+ impl_.get_service().sync_all(impl_.get_implementation(), ec);+ ASIO_SYNC_OP_VOID_RETURN(ec);+ }++ /// Synchronise the file data to disk.+ /**+ * This function synchronises the file data to disk. Note that the semantics+ * of this synchronisation vary between operation systems.+ *+ * @throws asio::system_error Thrown on failure.+ */+ void sync_data()+ {+ asio::error_code ec;+ impl_.get_service().sync_data(impl_.get_implementation(), ec);+ asio::detail::throw_error(ec, "sync_data");+ }++ /// Synchronise the file data to disk.+ /**+ * This function synchronises the file data to disk. Note that the semantics+ * of this synchronisation vary between operation systems.+ *+ * @param ec Set to indicate what error occurred, if any.+ */+ ASIO_SYNC_OP_VOID sync_data(asio::error_code& ec)+ {+ impl_.get_service().sync_data(impl_.get_implementation(), ec);+ ASIO_SYNC_OP_VOID_RETURN(ec);+ }++protected:+ /// Protected destructor to prevent deletion through this type.+ /**+ * This function destroys the file, cancelling any outstanding asynchronous+ * operations associated with the file as if by calling @c cancel.+ */+ ~basic_file()+ {+ }++#if defined(ASIO_HAS_IOCP)+ detail::io_object_impl<detail::win_iocp_file_service, Executor> impl_;+#elif defined(ASIO_HAS_IO_URING)+ detail::io_object_impl<detail::io_uring_file_service, Executor> impl_;+#endif++private:+ // Disallow copying and assignment.+ basic_file(const basic_file&) ASIO_DELETED;+ basic_file& operator=(const basic_file&) ASIO_DELETED;+};++} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // defined(ASIO_HAS_FILE)+ // || defined(GENERATING_DOCUMENTATION)++#endif // ASIO_BASIC_FILE_HPP
link/modules/asio-standalone/asio/include/asio/basic_io_object.hpp view
@@ -2,7 +2,7 @@ // basic_io_object.hpp // ~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+ link/modules/asio-standalone/asio/include/asio/basic_random_access_file.hpp view
@@ -0,0 +1,701 @@+//+// basic_random_access_file.hpp+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com)+//+// Distributed under the Boost Software License, Version 1.0. (See accompanying+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)+//++#ifndef ASIO_BASIC_RANDOM_ACCESS_FILE_HPP+#define ASIO_BASIC_RANDOM_ACCESS_FILE_HPP++#if defined(_MSC_VER) && (_MSC_VER >= 1200)+# pragma once+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)++#include "asio/detail/config.hpp"++#if defined(ASIO_HAS_FILE) \+ || defined(GENERATING_DOCUMENTATION)++#include <cstddef>+#include "asio/async_result.hpp"+#include "asio/basic_file.hpp"+#include "asio/detail/handler_type_requirements.hpp"+#include "asio/detail/non_const_lvalue.hpp"+#include "asio/detail/throw_error.hpp"+#include "asio/error.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {++#if !defined(ASIO_BASIC_RANDOM_ACCESS_FILE_FWD_DECL)+#define ASIO_BASIC_RANDOM_ACCESS_FILE_FWD_DECL++// Forward declaration with defaulted arguments.+template <typename Executor = any_io_executor>+class basic_random_access_file;++#endif // !defined(ASIO_BASIC_RANDOM_ACCESS_FILE_FWD_DECL)++/// Provides random-access file functionality.+/**+ * The basic_random_access_file class template provides asynchronous and+ * blocking random-access file functionality.+ *+ * @par Thread Safety+ * @e Distinct @e objects: Safe.@n+ * @e Shared @e objects: Unsafe.+ *+ * Synchronous @c read_some_at and @c write_some_at operations are thread safe+ * with respect to each other, if the underlying operating system calls are+ * also thread safe. This means that it is permitted to perform concurrent+ * calls to these synchronous operations on a single file object. Other+ * synchronous operations, such as @c open or @c close, are not thread safe.+ */+template <typename Executor>+class basic_random_access_file+ : public basic_file<Executor>+{+private:+ class initiate_async_write_some_at;+ class initiate_async_read_some_at;++public:+ /// The type of the executor associated with the object.+ typedef Executor executor_type;++ /// Rebinds the file type to another executor.+ template <typename Executor1>+ struct rebind_executor+ {+ /// The file type when rebound to the specified executor.+ typedef basic_random_access_file<Executor1> other;+ };++ /// The native representation of a file.+#if defined(GENERATING_DOCUMENTATION)+ typedef implementation_defined native_handle_type;+#else+ typedef typename basic_file<Executor>::native_handle_type native_handle_type;+#endif++ /// Construct a basic_random_access_file without opening it.+ /**+ * This constructor initialises a file without opening it. The file needs to+ * be opened before data can be read from or or written to it.+ *+ * @param ex The I/O executor that the file will use, by default, to+ * dispatch handlers for any asynchronous operations performed on the file.+ */+ explicit basic_random_access_file(const executor_type& ex)+ : basic_file<Executor>(ex)+ {+ }++ /// Construct a basic_random_access_file without opening it.+ /**+ * This constructor initialises a file without opening it. The file needs to+ * be opened before data can be read from or or written to it.+ *+ * @param context An execution context which provides the I/O executor that+ * the file will use, by default, to dispatch handlers for any asynchronous+ * operations performed on the file.+ */+ template <typename ExecutionContext>+ explicit basic_random_access_file(ExecutionContext& context,+ typename constraint<+ is_convertible<ExecutionContext&, execution_context&>::value,+ defaulted_constraint+ >::type = defaulted_constraint())+ : basic_file<Executor>(context)+ {+ }++ /// Construct and open a basic_random_access_file.+ /**+ * This constructor initialises and opens a file.+ *+ * @param ex The I/O executor that the file will use, by default, to+ * dispatch handlers for any asynchronous operations performed on the file.+ *+ * @param path The path name identifying the file to be opened.+ *+ * @param open_flags A set of flags that determine how the file should be+ * opened.+ *+ * @throws asio::system_error Thrown on failure.+ */+ basic_random_access_file(const executor_type& ex,+ const char* path, file_base::flags open_flags)+ : basic_file<Executor>(ex, path, open_flags)+ {+ }++ /// Construct and open a basic_random_access_file.+ /**+ * This constructor initialises and opens a file.+ *+ * @param context An execution context which provides the I/O executor that+ * the file will use, by default, to dispatch handlers for any asynchronous+ * operations performed on the file.+ *+ * @param path The path name identifying the file to be opened.+ *+ * @param open_flags A set of flags that determine how the file should be+ * opened.+ *+ * @throws asio::system_error Thrown on failure.+ */+ template <typename ExecutionContext>+ basic_random_access_file(ExecutionContext& context,+ const char* path, file_base::flags open_flags,+ typename constraint<+ is_convertible<ExecutionContext&, execution_context&>::value,+ defaulted_constraint+ >::type = defaulted_constraint())+ : basic_file<Executor>(context, path, open_flags)+ {+ }++ /// Construct and open a basic_random_access_file.+ /**+ * This constructor initialises and opens a file.+ *+ * @param ex The I/O executor that the file will use, by default, to+ * dispatch handlers for any asynchronous operations performed on the file.+ *+ * @param path The path name identifying the file to be opened.+ *+ * @param open_flags A set of flags that determine how the file should be+ * opened.+ *+ * @throws asio::system_error Thrown on failure.+ */+ basic_random_access_file(const executor_type& ex,+ const std::string& path, file_base::flags open_flags)+ : basic_file<Executor>(ex, path, open_flags)+ {+ }++ /// Construct and open a basic_random_access_file.+ /**+ * This constructor initialises and opens a file.+ *+ * @param context An execution context which provides the I/O executor that+ * the file will use, by default, to dispatch handlers for any asynchronous+ * operations performed on the file.+ *+ * @param path The path name identifying the file to be opened.+ *+ * @param open_flags A set of flags that determine how the file should be+ * opened.+ *+ * @throws asio::system_error Thrown on failure.+ */+ template <typename ExecutionContext>+ basic_random_access_file(ExecutionContext& context,+ const std::string& path, file_base::flags open_flags,+ typename constraint<+ is_convertible<ExecutionContext&, execution_context&>::value,+ defaulted_constraint+ >::type = defaulted_constraint())+ : basic_file<Executor>(context, path, open_flags)+ {+ }++ /// Construct a basic_random_access_file on an existing native file.+ /**+ * This constructor initialises a random-access file object to hold an+ * existing native file.+ *+ * @param ex The I/O executor that the file will use, by default, to+ * dispatch handlers for any asynchronous operations performed on the file.+ *+ * @param native_file The new underlying file implementation.+ *+ * @throws asio::system_error Thrown on failure.+ */+ basic_random_access_file(const executor_type& ex,+ const native_handle_type& native_file)+ : basic_file<Executor>(ex, native_file)+ {+ }++ /// Construct a basic_random_access_file on an existing native file.+ /**+ * This constructor initialises a random-access file object to hold an+ * existing native file.+ *+ * @param context An execution context which provides the I/O executor that+ * the file will use, by default, to dispatch handlers for any asynchronous+ * operations performed on the file.+ *+ * @param native_file The new underlying file implementation.+ *+ * @throws asio::system_error Thrown on failure.+ */+ template <typename ExecutionContext>+ basic_random_access_file(ExecutionContext& context,+ const native_handle_type& native_file,+ typename constraint<+ is_convertible<ExecutionContext&, execution_context&>::value,+ defaulted_constraint+ >::type = defaulted_constraint())+ : basic_file<Executor>(context, native_file)+ {+ }++#if defined(ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)+ /// Move-construct a basic_random_access_file from another.+ /**+ * This constructor moves a random-access file from one object to another.+ *+ * @param other The other basic_random_access_file object from which the move+ * will occur.+ *+ * @note Following the move, the moved-from object is in the same state as if+ * constructed using the @c basic_random_access_file(const executor_type&)+ * constructor.+ */+ basic_random_access_file(basic_random_access_file&& other) ASIO_NOEXCEPT+ : basic_file<Executor>(std::move(other))+ {+ }++ /// Move-assign a basic_random_access_file from another.+ /**+ * This assignment operator moves a random-access file from one object to+ * another.+ *+ * @param other The other basic_random_access_file object from which the move+ * will occur.+ *+ * @note Following the move, the moved-from object is in the same state as if+ * constructed using the @c basic_random_access_file(const executor_type&)+ * constructor.+ */+ basic_random_access_file& operator=(basic_random_access_file&& other)+ {+ basic_file<Executor>::operator=(std::move(other));+ return *this;+ }++ /// Move-construct a basic_random_access_file from a file of another executor+ /// type.+ /**+ * This constructor moves a random-access file from one object to another.+ *+ * @param other The other basic_random_access_file object from which the move+ * will occur.+ *+ * @note Following the move, the moved-from object is in the same state as if+ * constructed using the @c basic_random_access_file(const executor_type&)+ * constructor.+ */+ template <typename Executor1>+ basic_random_access_file(basic_random_access_file<Executor1>&& other,+ typename constraint<+ is_convertible<Executor1, Executor>::value,+ defaulted_constraint+ >::type = defaulted_constraint())+ : basic_file<Executor>(std::move(other))+ {+ }++ /// Move-assign a basic_random_access_file from a file of another executor+ /// type.+ /**+ * This assignment operator moves a random-access file from one object to+ * another.+ *+ * @param other The other basic_random_access_file object from which the move+ * will occur.+ *+ * @note Following the move, the moved-from object is in the same state as if+ * constructed using the @c basic_random_access_file(const executor_type&)+ * constructor.+ */+ template <typename Executor1>+ typename constraint<+ is_convertible<Executor1, Executor>::value,+ basic_random_access_file&+ >::type operator=(basic_random_access_file<Executor1>&& other)+ {+ basic_file<Executor>::operator=(std::move(other));+ return *this;+ }+#endif // defined(ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)++ /// Destroys the file.+ /**+ * This function destroys the file, cancelling any outstanding asynchronous+ * operations associated with the file as if by calling @c cancel.+ */+ ~basic_random_access_file()+ {+ }++ /// Write some data to the handle at the specified offset.+ /**+ * This function is used to write data to the random-access handle. The+ * function call will block until one or more bytes of the data has been+ * written successfully, or until an error occurs.+ *+ * @param offset The offset at which the data will be written.+ *+ * @param buffers One or more data buffers to be written to the handle.+ *+ * @returns The number of bytes written.+ *+ * @throws asio::system_error Thrown on failure. An error code of+ * asio::error::eof indicates that the end of the file was reached.+ *+ * @note The write_some_at operation may not write all of the data. Consider+ * using the @ref write_at function if you need to ensure that all data is+ * written before the blocking operation completes.+ *+ * @par Example+ * To write a single data buffer use the @ref buffer function as follows:+ * @code+ * handle.write_some_at(42, asio::buffer(data, size));+ * @endcode+ * See the @ref buffer documentation for information on writing multiple+ * buffers in one go, and how to use it with arrays, boost::array or+ * std::vector.+ */+ template <typename ConstBufferSequence>+ std::size_t write_some_at(uint64_t offset,+ const ConstBufferSequence& buffers)+ {+ asio::error_code ec;+ std::size_t s = this->impl_.get_service().write_some_at(+ this->impl_.get_implementation(), offset, buffers, ec);+ asio::detail::throw_error(ec, "write_some_at");+ return s;+ }++ /// Write some data to the handle at the specified offset.+ /**+ * This function is used to write data to the random-access handle. The+ * function call will block until one or more bytes of the data has been+ * written successfully, or until an error occurs.+ *+ * @param offset The offset at which the data will be written.+ *+ * @param buffers One or more data buffers to be written to the handle.+ *+ * @param ec Set to indicate what error occurred, if any.+ *+ * @returns The number of bytes written. Returns 0 if an error occurred.+ *+ * @note The write_some operation may not write all of the data to the+ * file. Consider using the @ref write_at function if you need to ensure that+ * all data is written before the blocking operation completes.+ */+ template <typename ConstBufferSequence>+ std::size_t write_some_at(uint64_t offset,+ const ConstBufferSequence& buffers, asio::error_code& ec)+ {+ return this->impl_.get_service().write_some_at(+ this->impl_.get_implementation(), offset, buffers, ec);+ }++ /// Start an asynchronous write at the specified offset.+ /**+ * This function is used to asynchronously write data to the random-access+ * handle. It is an initiating function for an @ref asynchronous_operation,+ * and always returns immediately.+ *+ * @param offset The offset at which the data will be written.+ *+ * @param buffers One or more data buffers to be written to the handle.+ * Although the buffers object may be copied as necessary, ownership of the+ * underlying memory blocks is retained by the caller, which must guarantee+ * that they remain valid until the completion handler is called.+ *+ * @param token The @ref completion_token that will be used to produce a+ * completion handler, which will be called when the write completes.+ * Potential completion tokens include @ref use_future, @ref use_awaitable,+ * @ref yield_context, or a function object with the correct completion+ * signature. The function signature of the completion handler must be:+ * @code void handler(+ * const asio::error_code& error, // Result of operation.+ * std::size_t bytes_transferred // Number of bytes written.+ * ); @endcode+ * Regardless of whether the asynchronous operation completes immediately or+ * not, the completion handler will not be invoked from within this function.+ * On immediate completion, invocation of the handler will be performed in a+ * manner equivalent to using asio::post().+ *+ * @par Completion Signature+ * @code void(asio::error_code, std::size_t) @endcode+ *+ * @note The write operation may not write all of the data to the file.+ * Consider using the @ref async_write_at function if you need to ensure that+ * all data is written before the asynchronous operation completes.+ *+ * @par Example+ * To write a single data buffer use the @ref buffer function as follows:+ * @code+ * handle.async_write_some_at(42, asio::buffer(data, size), handler);+ * @endcode+ * See the @ref buffer documentation for information on writing multiple+ * buffers in one go, and how to use it with arrays, boost::array or+ * std::vector.+ *+ * @par Per-Operation Cancellation+ * This asynchronous operation supports cancellation for the following+ * asio::cancellation_type values:+ *+ * @li @c cancellation_type::terminal+ *+ * @li @c cancellation_type::partial+ *+ * @li @c cancellation_type::total+ */+ template <typename ConstBufferSequence,+ ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code,+ std::size_t)) WriteToken+ ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(executor_type)>+ ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX(WriteToken,+ void (asio::error_code, std::size_t))+ async_write_some_at(uint64_t offset,+ const ConstBufferSequence& buffers,+ ASIO_MOVE_ARG(WriteToken) token+ ASIO_DEFAULT_COMPLETION_TOKEN(executor_type))+ ASIO_INITFN_AUTO_RESULT_TYPE_SUFFIX((+ async_initiate<WriteToken,+ void (asio::error_code, std::size_t)>(+ declval<initiate_async_write_some_at>(), token, offset, buffers)))+ {+ return async_initiate<WriteToken,+ void (asio::error_code, std::size_t)>(+ initiate_async_write_some_at(this), token, offset, buffers);+ }++ /// Read some data from the handle at the specified offset.+ /**+ * This function is used to read data from the random-access handle. The+ * function call will block until one or more bytes of data has been read+ * successfully, or until an error occurs.+ *+ * @param offset The offset at which the data will be read.+ *+ * @param buffers One or more buffers into which the data will be read.+ *+ * @returns The number of bytes read.+ *+ * @throws asio::system_error Thrown on failure. An error code of+ * asio::error::eof indicates that the end of the file was reached.+ *+ * @note The read_some operation may not read all of the requested number of+ * bytes. Consider using the @ref read_at function if you need to ensure that+ * the requested amount of data is read before the blocking operation+ * completes.+ *+ * @par Example+ * To read into a single data buffer use the @ref buffer function as follows:+ * @code+ * handle.read_some_at(42, asio::buffer(data, size));+ * @endcode+ * See the @ref buffer documentation for information on reading into multiple+ * buffers in one go, and how to use it with arrays, boost::array or+ * std::vector.+ */+ template <typename MutableBufferSequence>+ std::size_t read_some_at(uint64_t offset,+ const MutableBufferSequence& buffers)+ {+ asio::error_code ec;+ std::size_t s = this->impl_.get_service().read_some_at(+ this->impl_.get_implementation(), offset, buffers, ec);+ asio::detail::throw_error(ec, "read_some_at");+ return s;+ }++ /// Read some data from the handle at the specified offset.+ /**+ * This function is used to read data from the random-access handle. The+ * function call will block until one or more bytes of data has been read+ * successfully, or until an error occurs.+ *+ * @param offset The offset at which the data will be read.+ *+ * @param buffers One or more buffers into which the data will be read.+ *+ * @param ec Set to indicate what error occurred, if any.+ *+ * @returns The number of bytes read. Returns 0 if an error occurred.+ *+ * @note The read_some operation may not read all of the requested number of+ * bytes. Consider using the @ref read_at function if you need to ensure that+ * the requested amount of data is read before the blocking operation+ * completes.+ */+ template <typename MutableBufferSequence>+ std::size_t read_some_at(uint64_t offset,+ const MutableBufferSequence& buffers, asio::error_code& ec)+ {+ return this->impl_.get_service().read_some_at(+ this->impl_.get_implementation(), offset, buffers, ec);+ }++ /// Start an asynchronous read at the specified offset.+ /**+ * This function is used to asynchronously read data from the random-access+ * handle. It is an initiating function for an @ref asynchronous_operation,+ * and always returns immediately.+ *+ * @param offset The offset at which the data will be read.+ *+ * @param buffers One or more buffers into which the data will be read.+ * Although the buffers object may be copied as necessary, ownership of the+ * underlying memory blocks is retained by the caller, which must guarantee+ * that they remain valid until the completion handler is called.+ *+ * @param token The @ref completion_token that will be used to produce a+ * completion handler, which will be called when the read completes.+ * Potential completion tokens include @ref use_future, @ref use_awaitable,+ * @ref yield_context, or a function object with the correct completion+ * signature. The function signature of the completion handler must be:+ * @code void handler(+ * const asio::error_code& error, // Result of operation.+ * std::size_t bytes_transferred // Number of bytes read.+ * ); @endcode+ * Regardless of whether the asynchronous operation completes immediately or+ * not, the completion handler will not be invoked from within this function.+ * On immediate completion, invocation of the handler will be performed in a+ * manner equivalent to using asio::post().+ *+ * @par Completion Signature+ * @code void(asio::error_code, std::size_t) @endcode+ *+ * @note The read operation may not read all of the requested number of bytes.+ * Consider using the @ref async_read_at function if you need to ensure that+ * the requested amount of data is read before the asynchronous operation+ * completes.+ *+ * @par Example+ * To read into a single data buffer use the @ref buffer function as follows:+ * @code+ * handle.async_read_some_at(42, asio::buffer(data, size), handler);+ * @endcode+ * See the @ref buffer documentation for information on reading into multiple+ * buffers in one go, and how to use it with arrays, boost::array or+ * std::vector.+ *+ * @par Per-Operation Cancellation+ * This asynchronous operation supports cancellation for the following+ * asio::cancellation_type values:+ *+ * @li @c cancellation_type::terminal+ *+ * @li @c cancellation_type::partial+ *+ * @li @c cancellation_type::total+ */+ template <typename MutableBufferSequence,+ ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code,+ std::size_t)) ReadToken+ ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(executor_type)>+ ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX(ReadToken,+ void (asio::error_code, std::size_t))+ async_read_some_at(uint64_t offset,+ const MutableBufferSequence& buffers,+ ASIO_MOVE_ARG(ReadToken) token+ ASIO_DEFAULT_COMPLETION_TOKEN(executor_type))+ ASIO_INITFN_AUTO_RESULT_TYPE_SUFFIX((+ async_initiate<ReadToken,+ void (asio::error_code, std::size_t)>(+ declval<initiate_async_read_some_at>(), token, offset, buffers)))+ {+ return async_initiate<ReadToken,+ void (asio::error_code, std::size_t)>(+ initiate_async_read_some_at(this), token, offset, buffers);+ }++private:+ // Disallow copying and assignment.+ basic_random_access_file(const basic_random_access_file&) ASIO_DELETED;+ basic_random_access_file& operator=(+ const basic_random_access_file&) ASIO_DELETED;++ class initiate_async_write_some_at+ {+ public:+ typedef Executor executor_type;++ explicit initiate_async_write_some_at(basic_random_access_file* self)+ : self_(self)+ {+ }++ const executor_type& get_executor() const ASIO_NOEXCEPT+ {+ return self_->get_executor();+ }++ template <typename WriteHandler, typename ConstBufferSequence>+ void operator()(ASIO_MOVE_ARG(WriteHandler) handler,+ uint64_t offset, const ConstBufferSequence& buffers) const+ {+ // If you get an error on the following line it means that your handler+ // does not meet the documented type requirements for a WriteHandler.+ ASIO_WRITE_HANDLER_CHECK(WriteHandler, handler) type_check;++ detail::non_const_lvalue<WriteHandler> handler2(handler);+ self_->impl_.get_service().async_write_some_at(+ self_->impl_.get_implementation(), offset, buffers,+ handler2.value, self_->impl_.get_executor());+ }++ private:+ basic_random_access_file* self_;+ };++ class initiate_async_read_some_at+ {+ public:+ typedef Executor executor_type;++ explicit initiate_async_read_some_at(basic_random_access_file* self)+ : self_(self)+ {+ }++ const executor_type& get_executor() const ASIO_NOEXCEPT+ {+ return self_->get_executor();+ }++ template <typename ReadHandler, typename MutableBufferSequence>+ void operator()(ASIO_MOVE_ARG(ReadHandler) handler,+ uint64_t offset, const MutableBufferSequence& buffers) const+ {+ // If you get an error on the following line it means that your handler+ // does not meet the documented type requirements for a ReadHandler.+ ASIO_READ_HANDLER_CHECK(ReadHandler, handler) type_check;++ detail::non_const_lvalue<ReadHandler> handler2(handler);+ self_->impl_.get_service().async_read_some_at(+ self_->impl_.get_implementation(), offset, buffers,+ handler2.value, self_->impl_.get_executor());+ }++ private:+ basic_random_access_file* self_;+ };+};++} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // defined(ASIO_HAS_FILE)+ // || defined(GENERATING_DOCUMENTATION)++#endif // ASIO_BASIC_RANDOM_ACCESS_FILE_HPP
link/modules/asio-standalone/asio/include/asio/basic_raw_socket.hpp view
@@ -2,7 +2,7 @@ // basic_raw_socket.hpp // ~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -45,11 +45,24 @@ * @par Thread Safety * @e Distinct @e objects: Safe.@n * @e Shared @e objects: Unsafe.+ *+ * Synchronous @c send, @c send_to, @c receive, @c receive_from, @c connect,+ * and @c shutdown operations are thread safe with respect to each other, if+ * the underlying operating system calls are also thread safe. This means that+ * it is permitted to perform concurrent calls to these synchronous operations+ * on a single socket object. Other synchronous operations, such as @c open or+ * @c close, are not thread safe. */ template <typename Protocol, typename Executor> class basic_raw_socket : public basic_socket<Protocol, Executor> {+private:+ class initiate_async_send;+ class initiate_async_send_to;+ class initiate_async_receive;+ class initiate_async_receive_from;+ public: /// The type of the executor associated with the object. typedef Executor executor_type;@@ -100,9 +113,9 @@ */ template <typename ExecutionContext> explicit basic_raw_socket(ExecutionContext& context,- typename enable_if<+ typename constraint< is_convertible<ExecutionContext&, execution_context&>::value- >::type* = 0)+ >::type = 0) : basic_socket<Protocol, Executor>(context) { }@@ -137,9 +150,10 @@ */ template <typename ExecutionContext> basic_raw_socket(ExecutionContext& context, const protocol_type& protocol,- typename enable_if<- is_convertible<ExecutionContext&, execution_context&>::value- >::type* = 0)+ typename constraint<+ is_convertible<ExecutionContext&, execution_context&>::value,+ defaulted_constraint+ >::type = defaulted_constraint()) : basic_socket<Protocol, Executor>(context, protocol) { }@@ -182,9 +196,9 @@ */ template <typename ExecutionContext> basic_raw_socket(ExecutionContext& context, const endpoint_type& endpoint,- typename enable_if<+ typename constraint< is_convertible<ExecutionContext&, execution_context&>::value- >::type* = 0)+ >::type = 0) : basic_socket<Protocol, Executor>(context, endpoint) { }@@ -227,9 +241,9 @@ template <typename ExecutionContext> basic_raw_socket(ExecutionContext& context, const protocol_type& protocol, const native_handle_type& native_socket,- typename enable_if<+ typename constraint< is_convertible<ExecutionContext&, execution_context&>::value- >::type* = 0)+ >::type = 0) : basic_socket<Protocol, Executor>(context, protocol, native_socket) { }@@ -282,10 +296,10 @@ */ template <typename Protocol1, typename Executor1> basic_raw_socket(basic_raw_socket<Protocol1, Executor1>&& other,- typename enable_if<+ typename constraint< is_convertible<Protocol1, Protocol>::value && is_convertible<Executor1, Executor>::value- >::type* = 0)+ >::type = 0) : basic_socket<Protocol, Executor>(std::move(other)) { }@@ -302,7 +316,7 @@ * constructor. */ template <typename Protocol1, typename Executor1>- typename enable_if<+ typename constraint< is_convertible<Protocol1, Protocol>::value && is_convertible<Executor1, Executor>::value, basic_raw_socket&@@ -406,26 +420,32 @@ /// Start an asynchronous send on a connected socket. /**- * This function is used to send data on the raw socket. The function call- * will block until the data has been sent successfully or an error occurs.+ * This function is used to asynchronously send data on the raw socket. It is+ * an initiating function for an @ref asynchronous_operation, and always+ * returns immediately. * * @param buffers One or more data buffers to be sent on the socket. Although * the buffers object may be copied as necessary, ownership of the underlying * memory blocks is retained by the caller, which must guarantee that they- * remain valid until the handler is called.+ * remain valid until the completion handler is called. *- * @param handler The handler to be called when the send operation completes.- * Copies will be made of the handler as required. The function signature of- * the handler must be:+ * @param token The @ref completion_token that will be used to produce a+ * completion handler, which will be called when the send completes.+ * Potential completion tokens include @ref use_future, @ref use_awaitable,+ * @ref yield_context, or a function object with the correct completion+ * signature. The function signature of the completion handler must be: * @code void handler( * const asio::error_code& error, // Result of operation.- * std::size_t bytes_transferred // Number of bytes sent.+ * std::size_t bytes_transferred // Number of bytes sent. * ); @endcode * Regardless of whether the asynchronous operation completes immediately or- * not, the handler will not be invoked from within this function. On- * immediate completion, invocation of the handler will be performed in a+ * not, the completion handler will not be invoked from within this function.+ * On immediate completion, invocation of the handler will be performed in a * manner equivalent to using asio::post(). *+ * @par Completion Signature+ * @code void(asio::error_code, std::size_t) @endcode+ * * @note The async_send operation can only be used with a connected socket. * Use the async_send_to function to send data on an unconnected raw * socket.@@ -438,65 +458,100 @@ * See the @ref buffer documentation for information on sending multiple * buffers in one go, and how to use it with arrays, boost::array or * std::vector.+ *+ * @par Per-Operation Cancellation+ * On POSIX or Windows operating systems, this asynchronous operation supports+ * cancellation for the following asio::cancellation_type values:+ *+ * @li @c cancellation_type::terminal+ *+ * @li @c cancellation_type::partial+ *+ * @li @c cancellation_type::total */ template <typename ConstBufferSequence, ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code,- std::size_t)) WriteHandler+ std::size_t)) WriteToken ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(executor_type)>- ASIO_INITFN_AUTO_RESULT_TYPE(WriteHandler,+ ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX(WriteToken, void (asio::error_code, std::size_t)) async_send(const ConstBufferSequence& buffers,- ASIO_MOVE_ARG(WriteHandler) handler+ ASIO_MOVE_ARG(WriteToken) token ASIO_DEFAULT_COMPLETION_TOKEN(executor_type))+ ASIO_INITFN_AUTO_RESULT_TYPE_SUFFIX((+ async_initiate<WriteToken,+ void (asio::error_code, std::size_t)>(+ declval<initiate_async_send>(), token,+ buffers, socket_base::message_flags(0)))) {- return async_initiate<WriteHandler,+ return async_initiate<WriteToken, void (asio::error_code, std::size_t)>(- initiate_async_send(this), handler,+ initiate_async_send(this), token, buffers, socket_base::message_flags(0)); } /// Start an asynchronous send on a connected socket. /**- * This function is used to send data on the raw socket. The function call- * will block until the data has been sent successfully or an error occurs.+ * This function is used to asynchronously send data on the raw socket. It is+ * an initiating function for an @ref asynchronous_operation, and always+ * returns immediately. * * @param buffers One or more data buffers to be sent on the socket. Although * the buffers object may be copied as necessary, ownership of the underlying * memory blocks is retained by the caller, which must guarantee that they- * remain valid until the handler is called.+ * remain valid until the completion handler is called. * * @param flags Flags specifying how the send call is to be made. *- * @param handler The handler to be called when the send operation completes.- * Copies will be made of the handler as required. The function signature of- * the handler must be:+ * @param token The @ref completion_token that will be used to produce a+ * completion handler, which will be called when the send completes.+ * Potential completion tokens include @ref use_future, @ref use_awaitable,+ * @ref yield_context, or a function object with the correct completion+ * signature. The function signature of the completion handler must be: * @code void handler( * const asio::error_code& error, // Result of operation.- * std::size_t bytes_transferred // Number of bytes sent.+ * std::size_t bytes_transferred // Number of bytes sent. * ); @endcode * Regardless of whether the asynchronous operation completes immediately or- * not, the handler will not be invoked from within this function. On- * immediate completion, invocation of the handler will be performed in a+ * not, the completion handler will not be invoked from within this function.+ * On immediate completion, invocation of the handler will be performed in a * manner equivalent to using asio::post(). *+ * @par Completion Signature+ * @code void(asio::error_code, std::size_t) @endcode+ * * @note The async_send operation can only be used with a connected socket. * Use the async_send_to function to send data on an unconnected raw * socket.+ *+ * @par Per-Operation Cancellation+ * On POSIX or Windows operating systems, this asynchronous operation supports+ * cancellation for the following asio::cancellation_type values:+ *+ * @li @c cancellation_type::terminal+ *+ * @li @c cancellation_type::partial+ *+ * @li @c cancellation_type::total */ template <typename ConstBufferSequence, ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code,- std::size_t)) WriteHandler+ std::size_t)) WriteToken ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(executor_type)>- ASIO_INITFN_AUTO_RESULT_TYPE(WriteHandler,+ ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX(WriteToken, void (asio::error_code, std::size_t)) async_send(const ConstBufferSequence& buffers, socket_base::message_flags flags,- ASIO_MOVE_ARG(WriteHandler) handler+ ASIO_MOVE_ARG(WriteToken) token ASIO_DEFAULT_COMPLETION_TOKEN(executor_type))+ ASIO_INITFN_AUTO_RESULT_TYPE_SUFFIX((+ async_initiate<WriteToken,+ void (asio::error_code, std::size_t)>(+ declval<initiate_async_send>(), token, buffers, flags))) {- return async_initiate<WriteHandler,+ return async_initiate<WriteToken, void (asio::error_code, std::size_t)>(- initiate_async_send(this), handler, buffers, flags);+ initiate_async_send(this), token, buffers, flags); } /// Send raw data to the specified endpoint.@@ -590,28 +645,34 @@ /// Start an asynchronous send. /** * This function is used to asynchronously send raw data to the specified- * remote endpoint. The function call always returns immediately.+ * remote endpoint. It is an initiating function for an @ref+ * asynchronous_operation, and always returns immediately. * * @param buffers One or more data buffers to be sent to the remote endpoint. * Although the buffers object may be copied as necessary, ownership of the * underlying memory blocks is retained by the caller, which must guarantee- * that they remain valid until the handler is called.+ * that they remain valid until the completion handler is called. * * @param destination The remote endpoint to which the data will be sent. * Copies will be made of the endpoint as required. *- * @param handler The handler to be called when the send operation completes.- * Copies will be made of the handler as required. The function signature of- * the handler must be:+ * @param token The @ref completion_token that will be used to produce a+ * completion handler, which will be called when the send completes.+ * Potential completion tokens include @ref use_future, @ref use_awaitable,+ * @ref yield_context, or a function object with the correct completion+ * signature. The function signature of the completion handler must be: * @code void handler( * const asio::error_code& error, // Result of operation.- * std::size_t bytes_transferred // Number of bytes sent.+ * std::size_t bytes_transferred // Number of bytes sent. * ); @endcode * Regardless of whether the asynchronous operation completes immediately or- * not, the handler will not be invoked from within this function. On- * immediate completion, invocation of the handler will be performed in a+ * not, the completion handler will not be invoked from within this function.+ * On immediate completion, invocation of the handler will be performed in a * manner equivalent to using asio::post(). *+ * @par Completion Signature+ * @code void(asio::error_code, std::size_t) @endcode+ * * @par Example * To send a single data buffer use the @ref buffer function as follows: * @code@@ -623,65 +684,102 @@ * See the @ref buffer documentation for information on sending multiple * buffers in one go, and how to use it with arrays, boost::array or * std::vector.+ *+ * @par Per-Operation Cancellation+ * On POSIX or Windows operating systems, this asynchronous operation supports+ * cancellation for the following asio::cancellation_type values:+ *+ * @li @c cancellation_type::terminal+ *+ * @li @c cancellation_type::partial+ *+ * @li @c cancellation_type::total */ template <typename ConstBufferSequence, ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code,- std::size_t)) WriteHandler+ std::size_t)) WriteToken ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(executor_type)>- ASIO_INITFN_AUTO_RESULT_TYPE(WriteHandler,+ ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX(WriteToken, void (asio::error_code, std::size_t)) async_send_to(const ConstBufferSequence& buffers, const endpoint_type& destination,- ASIO_MOVE_ARG(WriteHandler) handler+ ASIO_MOVE_ARG(WriteToken) token ASIO_DEFAULT_COMPLETION_TOKEN(executor_type))+ ASIO_INITFN_AUTO_RESULT_TYPE_SUFFIX((+ async_initiate<WriteToken,+ void (asio::error_code, std::size_t)>(+ declval<initiate_async_send_to>(), token, buffers,+ destination, socket_base::message_flags(0)))) {- return async_initiate<WriteHandler,+ return async_initiate<WriteToken, void (asio::error_code, std::size_t)>(- initiate_async_send_to(this), handler, buffers,+ initiate_async_send_to(this), token, buffers, destination, socket_base::message_flags(0)); } /// Start an asynchronous send. /** * This function is used to asynchronously send raw data to the specified- * remote endpoint. The function call always returns immediately.+ * remote endpoint. It is an initiating function for an @ref+ * asynchronous_operation, and always returns immediately. * * @param buffers One or more data buffers to be sent to the remote endpoint. * Although the buffers object may be copied as necessary, ownership of the * underlying memory blocks is retained by the caller, which must guarantee- * that they remain valid until the handler is called.+ * that they remain valid until the completion handler is called. * * @param flags Flags specifying how the send call is to be made. * * @param destination The remote endpoint to which the data will be sent. * Copies will be made of the endpoint as required. *- * @param handler The handler to be called when the send operation completes.- * Copies will be made of the handler as required. The function signature of- * the handler must be:+ * @param token The @ref completion_token that will be used to produce a+ * completion handler, which will be called when the send completes.+ * Potential completion tokens include @ref use_future, @ref use_awaitable,+ * @ref yield_context, or a function object with the correct completion+ * signature. The function signature of the completion handler must be: * @code void handler( * const asio::error_code& error, // Result of operation.- * std::size_t bytes_transferred // Number of bytes sent.+ * std::size_t bytes_transferred // Number of bytes sent. * ); @endcode * Regardless of whether the asynchronous operation completes immediately or- * not, the handler will not be invoked from within this function. On- * immediate completion, invocation of the handler will be performed in a+ * not, the completion handler will not be invoked from within this function.+ * On immediate completion, invocation of the handler will be performed in a * manner equivalent to using asio::post().+ *+ * @par Completion Signature+ * @code void(asio::error_code, std::size_t) @endcode+ *+ * @par Per-Operation Cancellation+ * On POSIX or Windows operating systems, this asynchronous operation supports+ * cancellation for the following asio::cancellation_type values:+ *+ * @li @c cancellation_type::terminal+ *+ * @li @c cancellation_type::partial+ *+ * @li @c cancellation_type::total */ template <typename ConstBufferSequence, ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code,- std::size_t)) WriteHandler+ std::size_t)) WriteToken ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(executor_type)>- ASIO_INITFN_AUTO_RESULT_TYPE(WriteHandler,+ ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX(WriteToken, void (asio::error_code, std::size_t)) async_send_to(const ConstBufferSequence& buffers, const endpoint_type& destination, socket_base::message_flags flags,- ASIO_MOVE_ARG(WriteHandler) handler+ ASIO_MOVE_ARG(WriteToken) token ASIO_DEFAULT_COMPLETION_TOKEN(executor_type))+ ASIO_INITFN_AUTO_RESULT_TYPE_SUFFIX((+ async_initiate<WriteToken,+ void (asio::error_code, std::size_t)>(+ declval<initiate_async_send_to>(), token,+ buffers, destination, flags))) {- return async_initiate<WriteHandler,+ return async_initiate<WriteToken, void (asio::error_code, std::size_t)>(- initiate_async_send_to(this), handler, buffers, destination, flags);+ initiate_async_send_to(this), token,+ buffers, destination, flags); } /// Receive some data on a connected socket.@@ -776,25 +874,31 @@ /// Start an asynchronous receive on a connected socket. /** * This function is used to asynchronously receive data from the raw- * socket. The function call always returns immediately.+ * socket. It is an initiating function for an @ref asynchronous_operation,+ * and always returns immediately. * * @param buffers One or more buffers into which the data will be received. * Although the buffers object may be copied as necessary, ownership of the * underlying memory blocks is retained by the caller, which must guarantee- * that they remain valid until the handler is called.+ * that they remain valid until the completion handler is called. *- * @param handler The handler to be called when the receive operation- * completes. Copies will be made of the handler as required. The function- * signature of the handler must be:+ * @param token The @ref completion_token that will be used to produce a+ * completion handler, which will be called when the receive completes.+ * Potential completion tokens include @ref use_future, @ref use_awaitable,+ * @ref yield_context, or a function object with the correct completion+ * signature. The function signature of the completion handler must be: * @code void handler( * const asio::error_code& error, // Result of operation.- * std::size_t bytes_transferred // Number of bytes received.+ * std::size_t bytes_transferred // Number of bytes received. * ); @endcode * Regardless of whether the asynchronous operation completes immediately or- * not, the handler will not be invoked from within this function. On- * immediate completion, invocation of the handler will be performed in a+ * not, the completion handler will not be invoked from within this function.+ * On immediate completion, invocation of the handler will be performed in a * manner equivalent to using asio::post(). *+ * @par Completion Signature+ * @code void(asio::error_code, std::size_t) @endcode+ * * @note The async_receive operation can only be used with a connected socket. * Use the async_receive_from function to receive data on an unconnected * raw socket.@@ -808,65 +912,100 @@ * See the @ref buffer documentation for information on receiving into * multiple buffers in one go, and how to use it with arrays, boost::array or * std::vector.+ *+ * @par Per-Operation Cancellation+ * On POSIX or Windows operating systems, this asynchronous operation supports+ * cancellation for the following asio::cancellation_type values:+ *+ * @li @c cancellation_type::terminal+ *+ * @li @c cancellation_type::partial+ *+ * @li @c cancellation_type::total */ template <typename MutableBufferSequence, ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code,- std::size_t)) ReadHandler+ std::size_t)) ReadToken ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(executor_type)>- ASIO_INITFN_AUTO_RESULT_TYPE(ReadHandler,+ ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX(ReadToken, void (asio::error_code, std::size_t)) async_receive(const MutableBufferSequence& buffers,- ASIO_MOVE_ARG(ReadHandler) handler+ ASIO_MOVE_ARG(ReadToken) token ASIO_DEFAULT_COMPLETION_TOKEN(executor_type))+ ASIO_INITFN_AUTO_RESULT_TYPE_SUFFIX((+ async_initiate<ReadToken,+ void (asio::error_code, std::size_t)>(+ declval<initiate_async_receive>(), token,+ buffers, socket_base::message_flags(0)))) {- return async_initiate<ReadHandler,+ return async_initiate<ReadToken, void (asio::error_code, std::size_t)>(- initiate_async_receive(this), handler,+ initiate_async_receive(this), token, buffers, socket_base::message_flags(0)); } /// Start an asynchronous receive on a connected socket. /** * This function is used to asynchronously receive data from the raw- * socket. The function call always returns immediately.+ * socket. It is an initiating function for an @ref asynchronous_operation,+ * and always returns immediately. * * @param buffers One or more buffers into which the data will be received. * Although the buffers object may be copied as necessary, ownership of the * underlying memory blocks is retained by the caller, which must guarantee- * that they remain valid until the handler is called.+ * that they remain valid until the completion handler is called. * * @param flags Flags specifying how the receive call is to be made. *- * @param handler The handler to be called when the receive operation- * completes. Copies will be made of the handler as required. The function- * signature of the handler must be:+ * @param token The @ref completion_token that will be used to produce a+ * completion handler, which will be called when the receive completes.+ * Potential completion tokens include @ref use_future, @ref use_awaitable,+ * @ref yield_context, or a function object with the correct completion+ * signature. The function signature of the completion handler must be: * @code void handler( * const asio::error_code& error, // Result of operation.- * std::size_t bytes_transferred // Number of bytes received.+ * std::size_t bytes_transferred // Number of bytes received. * ); @endcode * Regardless of whether the asynchronous operation completes immediately or- * not, the handler will not be invoked from within this function. On- * immediate completion, invocation of the handler will be performed in a+ * not, the completion handler will not be invoked from within this function.+ * On immediate completion, invocation of the handler will be performed in a * manner equivalent to using asio::post(). *+ * @par Completion Signature+ * @code void(asio::error_code, std::size_t) @endcode+ * * @note The async_receive operation can only be used with a connected socket. * Use the async_receive_from function to receive data on an unconnected * raw socket.+ *+ * @par Per-Operation Cancellation+ * On POSIX or Windows operating systems, this asynchronous operation supports+ * cancellation for the following asio::cancellation_type values:+ *+ * @li @c cancellation_type::terminal+ *+ * @li @c cancellation_type::partial+ *+ * @li @c cancellation_type::total */ template <typename MutableBufferSequence, ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code,- std::size_t)) ReadHandler+ std::size_t)) ReadToken ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(executor_type)>- ASIO_INITFN_AUTO_RESULT_TYPE(ReadHandler,+ ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX(ReadToken, void (asio::error_code, std::size_t)) async_receive(const MutableBufferSequence& buffers, socket_base::message_flags flags,- ASIO_MOVE_ARG(ReadHandler) handler+ ASIO_MOVE_ARG(ReadToken) token ASIO_DEFAULT_COMPLETION_TOKEN(executor_type))+ ASIO_INITFN_AUTO_RESULT_TYPE_SUFFIX((+ async_initiate<ReadToken,+ void (asio::error_code, std::size_t)>(+ declval<initiate_async_receive>(), token, buffers, flags))) {- return async_initiate<ReadHandler,+ return async_initiate<ReadToken, void (asio::error_code, std::size_t)>(- initiate_async_receive(this), handler, buffers, flags);+ initiate_async_receive(this), token, buffers, flags); } /// Receive raw data with the endpoint of the sender.@@ -960,31 +1099,37 @@ /// Start an asynchronous receive. /**- * This function is used to asynchronously receive raw data. The function- * call always returns immediately.+ * This function is used to asynchronously receive raw data. It is an+ * initiating function for an @ref asynchronous_operation, and always returns+ * immediately. * * @param buffers One or more buffers into which the data will be received. * Although the buffers object may be copied as necessary, ownership of the * underlying memory blocks is retained by the caller, which must guarantee- * that they remain valid until the handler is called.+ * that they remain valid until the completion handler is called. * * @param sender_endpoint An endpoint object that receives the endpoint of * the remote sender of the data. Ownership of the sender_endpoint object * is retained by the caller, which must guarantee that it is valid until the- * handler is called.+ * completion handler is called. *- * @param handler The handler to be called when the receive operation- * completes. Copies will be made of the handler as required. The function- * signature of the handler must be:+ * @param token The @ref completion_token that will be used to produce a+ * completion handler, which will be called when the receive completes.+ * Potential completion tokens include @ref use_future, @ref use_awaitable,+ * @ref yield_context, or a function object with the correct completion+ * signature. The function signature of the completion handler must be: * @code void handler( * const asio::error_code& error, // Result of operation.- * std::size_t bytes_transferred // Number of bytes received.+ * std::size_t bytes_transferred // Number of bytes received. * ); @endcode * Regardless of whether the asynchronous operation completes immediately or- * not, the handler will not be invoked from within this function. On- * immediate completion, invocation of the handler will be performed in a+ * not, the completion handler will not be invoked from within this function.+ * On immediate completion, invocation of the handler will be performed in a * manner equivalent to using asio::post(). *+ * @par Completion Signature+ * @code void(asio::error_code, std::size_t) @endcode+ * * @par Example * To receive into a single data buffer use the @ref buffer function as * follows:@@ -993,67 +1138,103 @@ * See the @ref buffer documentation for information on receiving into * multiple buffers in one go, and how to use it with arrays, boost::array or * std::vector.+ *+ * @par Per-Operation Cancellation+ * On POSIX or Windows operating systems, this asynchronous operation supports+ * cancellation for the following asio::cancellation_type values:+ *+ * @li @c cancellation_type::terminal+ *+ * @li @c cancellation_type::partial+ *+ * @li @c cancellation_type::total */ template <typename MutableBufferSequence, ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code,- std::size_t)) ReadHandler+ std::size_t)) ReadToken ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(executor_type)>- ASIO_INITFN_AUTO_RESULT_TYPE(ReadHandler,+ ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX(ReadToken, void (asio::error_code, std::size_t)) async_receive_from(const MutableBufferSequence& buffers, endpoint_type& sender_endpoint,- ASIO_MOVE_ARG(ReadHandler) handler+ ASIO_MOVE_ARG(ReadToken) token ASIO_DEFAULT_COMPLETION_TOKEN(executor_type))+ ASIO_INITFN_AUTO_RESULT_TYPE_SUFFIX((+ async_initiate<ReadToken,+ void (asio::error_code, std::size_t)>(+ declval<initiate_async_receive_from>(), token, buffers,+ &sender_endpoint, socket_base::message_flags(0)))) {- return async_initiate<ReadHandler,+ return async_initiate<ReadToken, void (asio::error_code, std::size_t)>(- initiate_async_receive_from(this), handler, buffers,+ initiate_async_receive_from(this), token, buffers, &sender_endpoint, socket_base::message_flags(0)); } /// Start an asynchronous receive. /**- * This function is used to asynchronously receive raw data. The function- * call always returns immediately.+ * This function is used to asynchronously receive raw data. It is an+ * initiating function for an @ref asynchronous_operation, and always returns+ * immediately. * * @param buffers One or more buffers into which the data will be received. * Although the buffers object may be copied as necessary, ownership of the * underlying memory blocks is retained by the caller, which must guarantee- * that they remain valid until the handler is called.+ * that they remain valid until the completion handler is called. * * @param sender_endpoint An endpoint object that receives the endpoint of * the remote sender of the data. Ownership of the sender_endpoint object * is retained by the caller, which must guarantee that it is valid until the- * handler is called.+ * completion handler is called. * * @param flags Flags specifying how the receive call is to be made. *- * @param handler The handler to be called when the receive operation- * completes. Copies will be made of the handler as required. The function- * signature of the handler must be:+ * @param token The @ref completion_token that will be used to produce a+ * completion handler, which will be called when the receive completes.+ * Potential completion tokens include @ref use_future, @ref use_awaitable,+ * @ref yield_context, or a function object with the correct completion+ * signature. The function signature of the completion handler must be: * @code void handler( * const asio::error_code& error, // Result of operation.- * std::size_t bytes_transferred // Number of bytes received.+ * std::size_t bytes_transferred // Number of bytes received. * ); @endcode * Regardless of whether the asynchronous operation completes immediately or- * not, the handler will not be invoked from within this function. On- * immediate completion, invocation of the handler will be performed in a+ * not, the completion handler will not be invoked from within this function.+ * On immediate completion, invocation of the handler will be performed in a * manner equivalent to using asio::post().+ *+ * @par Completion Signature+ * @code void(asio::error_code, std::size_t) @endcode+ *+ * @par Per-Operation Cancellation+ * On POSIX or Windows operating systems, this asynchronous operation supports+ * cancellation for the following asio::cancellation_type values:+ *+ * @li @c cancellation_type::terminal+ *+ * @li @c cancellation_type::partial+ *+ * @li @c cancellation_type::total */ template <typename MutableBufferSequence, ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code,- std::size_t)) ReadHandler+ std::size_t)) ReadToken ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(executor_type)>- ASIO_INITFN_AUTO_RESULT_TYPE(ReadHandler,+ ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX(ReadToken, void (asio::error_code, std::size_t)) async_receive_from(const MutableBufferSequence& buffers, endpoint_type& sender_endpoint, socket_base::message_flags flags,- ASIO_MOVE_ARG(ReadHandler) handler+ ASIO_MOVE_ARG(ReadToken) token ASIO_DEFAULT_COMPLETION_TOKEN(executor_type))+ ASIO_INITFN_AUTO_RESULT_TYPE_SUFFIX((+ async_initiate<ReadToken,+ void (asio::error_code, std::size_t)>(+ declval<initiate_async_receive_from>(), token,+ buffers, &sender_endpoint, flags))) {- return async_initiate<ReadHandler,+ return async_initiate<ReadToken, void (asio::error_code, std::size_t)>(- initiate_async_receive_from(this), handler,+ initiate_async_receive_from(this), token, buffers, &sender_endpoint, flags); } @@ -1072,7 +1253,7 @@ { } - executor_type get_executor() const ASIO_NOEXCEPT+ const executor_type& get_executor() const ASIO_NOEXCEPT { return self_->get_executor(); }@@ -1106,7 +1287,7 @@ { } - executor_type get_executor() const ASIO_NOEXCEPT+ const executor_type& get_executor() const ASIO_NOEXCEPT { return self_->get_executor(); }@@ -1140,7 +1321,7 @@ { } - executor_type get_executor() const ASIO_NOEXCEPT+ const executor_type& get_executor() const ASIO_NOEXCEPT { return self_->get_executor(); }@@ -1174,7 +1355,7 @@ { } - executor_type get_executor() const ASIO_NOEXCEPT+ const executor_type& get_executor() const ASIO_NOEXCEPT { return self_->get_executor(); }
+ link/modules/asio-standalone/asio/include/asio/basic_readable_pipe.hpp view
@@ -0,0 +1,635 @@+//+// basic_readable_pipe.hpp+// ~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com)+//+// Distributed under the Boost Software License, Version 1.0. (See accompanying+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)+//++#ifndef ASIO_BASIC_READABLE_PIPE_HPP+#define ASIO_BASIC_READABLE_PIPE_HPP++#if defined(_MSC_VER) && (_MSC_VER >= 1200)+# pragma once+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)++#include "asio/detail/config.hpp"++#if defined(ASIO_HAS_PIPE) \+ || defined(GENERATING_DOCUMENTATION)++#include <string>+#include "asio/any_io_executor.hpp"+#include "asio/async_result.hpp"+#include "asio/detail/handler_type_requirements.hpp"+#include "asio/detail/io_object_impl.hpp"+#include "asio/detail/non_const_lvalue.hpp"+#include "asio/detail/throw_error.hpp"+#include "asio/detail/type_traits.hpp"+#include "asio/error.hpp"+#include "asio/execution_context.hpp"+#if defined(ASIO_HAS_IOCP)+# include "asio/detail/win_iocp_handle_service.hpp"+#elif defined(ASIO_HAS_IO_URING_AS_DEFAULT)+# include "asio/detail/io_uring_descriptor_service.hpp"+#else+# include "asio/detail/reactive_descriptor_service.hpp"+#endif++#if defined(ASIO_HAS_MOVE)+# include <utility>+#endif // defined(ASIO_HAS_MOVE)++#include "asio/detail/push_options.hpp"++namespace asio {++/// Provides pipe functionality.+/**+ * The basic_readable_pipe class provides a wrapper over pipe+ * functionality.+ *+ * @par Thread Safety+ * @e Distinct @e objects: Safe.@n+ * @e Shared @e objects: Unsafe.+ */+template <typename Executor = any_io_executor>+class basic_readable_pipe+{+private:+ class initiate_async_read_some;++public:+ /// The type of the executor associated with the object.+ typedef Executor executor_type;++ /// Rebinds the pipe type to another executor.+ template <typename Executor1>+ struct rebind_executor+ {+ /// The pipe type when rebound to the specified executor.+ typedef basic_readable_pipe<Executor1> other;+ };++ /// The native representation of a pipe.+#if defined(GENERATING_DOCUMENTATION)+ typedef implementation_defined native_handle_type;+#elif defined(ASIO_HAS_IOCP)+ typedef detail::win_iocp_handle_service::native_handle_type+ native_handle_type;+#elif defined(ASIO_HAS_IO_URING_AS_DEFAULT)+ typedef detail::io_uring_descriptor_service::native_handle_type+ native_handle_type;+#else+ typedef detail::reactive_descriptor_service::native_handle_type+ native_handle_type;+#endif++ /// A basic_readable_pipe is always the lowest layer.+ typedef basic_readable_pipe lowest_layer_type;++ /// Construct a basic_readable_pipe without opening it.+ /**+ * This constructor creates a pipe without opening it.+ *+ * @param ex The I/O executor that the pipe will use, by default, to dispatch+ * handlers for any asynchronous operations performed on the pipe.+ */+ explicit basic_readable_pipe(const executor_type& ex)+ : impl_(0, ex)+ {+ }++ /// Construct a basic_readable_pipe without opening it.+ /**+ * This constructor creates a pipe without opening it.+ *+ * @param context An execution context which provides the I/O executor that+ * the pipe will use, by default, to dispatch handlers for any asynchronous+ * operations performed on the pipe.+ */+ template <typename ExecutionContext>+ explicit basic_readable_pipe(ExecutionContext& context,+ typename constraint<+ is_convertible<ExecutionContext&, execution_context&>::value,+ defaulted_constraint+ >::type = defaulted_constraint())+ : impl_(0, 0, context)+ {+ }++ /// Construct a basic_readable_pipe on an existing native pipe.+ /**+ * This constructor creates a pipe object to hold an existing native+ * pipe.+ *+ * @param ex The I/O executor that the pipe will use, by default, to+ * dispatch handlers for any asynchronous operations performed on the+ * pipe.+ *+ * @param native_pipe A native pipe.+ *+ * @throws asio::system_error Thrown on failure.+ */+ basic_readable_pipe(const executor_type& ex,+ const native_handle_type& native_pipe)+ : impl_(0, ex)+ {+ asio::error_code ec;+ impl_.get_service().assign(impl_.get_implementation(),+ native_pipe, ec);+ asio::detail::throw_error(ec, "assign");+ }++ /// Construct a basic_readable_pipe on an existing native pipe.+ /**+ * This constructor creates a pipe object to hold an existing native+ * pipe.+ *+ * @param context An execution context which provides the I/O executor that+ * the pipe will use, by default, to dispatch handlers for any+ * asynchronous operations performed on the pipe.+ *+ * @param native_pipe A native pipe.+ *+ * @throws asio::system_error Thrown on failure.+ */+ template <typename ExecutionContext>+ basic_readable_pipe(ExecutionContext& context,+ const native_handle_type& native_pipe,+ typename constraint<+ is_convertible<ExecutionContext&, execution_context&>::value+ >::type = 0)+ : impl_(0, 0, context)+ {+ asio::error_code ec;+ impl_.get_service().assign(impl_.get_implementation(),+ native_pipe, ec);+ asio::detail::throw_error(ec, "assign");+ }++#if defined(ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)+ /// Move-construct a basic_readable_pipe from another.+ /**+ * This constructor moves a pipe from one object to another.+ *+ * @param other The other basic_readable_pipe object from which the move will+ * occur.+ *+ * @note Following the move, the moved-from object is in the same state as if+ * constructed using the @c basic_readable_pipe(const executor_type&)+ * constructor.+ */+ basic_readable_pipe(basic_readable_pipe&& other)+ : impl_(std::move(other.impl_))+ {+ }++ /// Move-assign a basic_readable_pipe from another.+ /**+ * This assignment operator moves a pipe from one object to another.+ *+ * @param other The other basic_readable_pipe object from which the move will+ * occur.+ *+ * @note Following the move, the moved-from object is in the same state as if+ * constructed using the @c basic_readable_pipe(const executor_type&)+ * constructor.+ */+ basic_readable_pipe& operator=(basic_readable_pipe&& other)+ {+ impl_ = std::move(other.impl_);+ return *this;+ }++ // All pipes have access to each other's implementations.+ template <typename Executor1>+ friend class basic_readable_pipe;++ /// Move-construct a basic_readable_pipe from a pipe of another executor type.+ /**+ * This constructor moves a pipe from one object to another.+ *+ * @param other The other basic_readable_pipe object from which the move will+ * occur.+ *+ * @note Following the move, the moved-from object is in the same state as if+ * constructed using the @c basic_readable_pipe(const executor_type&)+ * constructor.+ */+ template <typename Executor1>+ basic_readable_pipe(basic_readable_pipe<Executor1>&& other,+ typename constraint<+ is_convertible<Executor1, Executor>::value,+ defaulted_constraint+ >::type = defaulted_constraint())+ : impl_(std::move(other.impl_))+ {+ }++ /// Move-assign a basic_readable_pipe from a pipe of another executor type.+ /**+ * This assignment operator moves a pipe from one object to another.+ *+ * @param other The other basic_readable_pipe object from which the move will+ * occur.+ *+ * @note Following the move, the moved-from object is in the same state as if+ * constructed using the @c basic_readable_pipe(const executor_type&)+ * constructor.+ */+ template <typename Executor1>+ typename constraint<+ is_convertible<Executor1, Executor>::value,+ basic_readable_pipe&+ >::type operator=(basic_readable_pipe<Executor1>&& other)+ {+ basic_readable_pipe tmp(std::move(other));+ impl_ = std::move(tmp.impl_);+ return *this;+ }+#endif // defined(ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)++ /// Destroys the pipe.+ /**+ * This function destroys the pipe, cancelling any outstanding+ * asynchronous wait operations associated with the pipe as if by+ * calling @c cancel.+ */+ ~basic_readable_pipe()+ {+ }++ /// Get the executor associated with the object.+ const executor_type& get_executor() ASIO_NOEXCEPT+ {+ return impl_.get_executor();+ }++ /// Get a reference to the lowest layer.+ /**+ * This function returns a reference to the lowest layer in a stack of+ * layers. Since a basic_readable_pipe cannot contain any further layers, it+ * simply returns a reference to itself.+ *+ * @return A reference to the lowest layer in the stack of layers. Ownership+ * is not transferred to the caller.+ */+ lowest_layer_type& lowest_layer()+ {+ return *this;+ }++ /// Get a const reference to the lowest layer.+ /**+ * This function returns a const reference to the lowest layer in a stack of+ * layers. Since a basic_readable_pipe cannot contain any further layers, it+ * simply returns a reference to itself.+ *+ * @return A const reference to the lowest layer in the stack of layers.+ * Ownership is not transferred to the caller.+ */+ const lowest_layer_type& lowest_layer() const+ {+ return *this;+ }++ /// Assign an existing native pipe to the pipe.+ /*+ * This function opens the pipe to hold an existing native pipe.+ *+ * @param native_pipe A native pipe.+ *+ * @throws asio::system_error Thrown on failure.+ */+ void assign(const native_handle_type& native_pipe)+ {+ asio::error_code ec;+ impl_.get_service().assign(impl_.get_implementation(), native_pipe, ec);+ asio::detail::throw_error(ec, "assign");+ }++ /// Assign an existing native pipe to the pipe.+ /*+ * This function opens the pipe to hold an existing native pipe.+ *+ * @param native_pipe A native pipe.+ *+ * @param ec Set to indicate what error occurred, if any.+ */+ ASIO_SYNC_OP_VOID assign(const native_handle_type& native_pipe,+ asio::error_code& ec)+ {+ impl_.get_service().assign(impl_.get_implementation(), native_pipe, ec);+ ASIO_SYNC_OP_VOID_RETURN(ec);+ }++ /// Determine whether the pipe is open.+ bool is_open() const+ {+ return impl_.get_service().is_open(impl_.get_implementation());+ }++ /// Close the pipe.+ /**+ * This function is used to close the pipe. Any asynchronous read operations+ * will be cancelled immediately, and will complete with the+ * asio::error::operation_aborted error.+ *+ * @throws asio::system_error Thrown on failure.+ */+ void close()+ {+ asio::error_code ec;+ impl_.get_service().close(impl_.get_implementation(), ec);+ asio::detail::throw_error(ec, "close");+ }++ /// Close the pipe.+ /**+ * This function is used to close the pipe. Any asynchronous read operations+ * will be cancelled immediately, and will complete with the+ * asio::error::operation_aborted error.+ *+ * @param ec Set to indicate what error occurred, if any.+ */+ ASIO_SYNC_OP_VOID close(asio::error_code& ec)+ {+ impl_.get_service().close(impl_.get_implementation(), ec);+ ASIO_SYNC_OP_VOID_RETURN(ec);+ }++ /// Release ownership of the underlying native pipe.+ /**+ * This function causes all outstanding asynchronous read operations to+ * finish immediately, and the handlers for cancelled operations will be+ * passed the asio::error::operation_aborted error. Ownership of the+ * native pipe is then transferred to the caller.+ *+ * @throws asio::system_error Thrown on failure.+ *+ * @note This function is unsupported on Windows versions prior to Windows+ * 8.1, and will fail with asio::error::operation_not_supported on+ * these platforms.+ */+#if defined(ASIO_MSVC) && (ASIO_MSVC >= 1400) \+ && (!defined(_WIN32_WINNT) || _WIN32_WINNT < 0x0603)+ __declspec(deprecated("This function always fails with "+ "operation_not_supported when used on Windows versions "+ "prior to Windows 8.1."))+#endif+ native_handle_type release()+ {+ asio::error_code ec;+ native_handle_type s = impl_.get_service().release(+ impl_.get_implementation(), ec);+ asio::detail::throw_error(ec, "release");+ return s;+ }++ /// Release ownership of the underlying native pipe.+ /**+ * This function causes all outstanding asynchronous read operations to+ * finish immediately, and the handlers for cancelled operations will be+ * passed the asio::error::operation_aborted error. Ownership of the+ * native pipe is then transferred to the caller.+ *+ * @param ec Set to indicate what error occurred, if any.+ *+ * @note This function is unsupported on Windows versions prior to Windows+ * 8.1, and will fail with asio::error::operation_not_supported on+ * these platforms.+ */+#if defined(ASIO_MSVC) && (ASIO_MSVC >= 1400) \+ && (!defined(_WIN32_WINNT) || _WIN32_WINNT < 0x0603)+ __declspec(deprecated("This function always fails with "+ "operation_not_supported when used on Windows versions "+ "prior to Windows 8.1."))+#endif+ native_handle_type release(asio::error_code& ec)+ {+ return impl_.get_service().release(impl_.get_implementation(), ec);+ }++ /// Get the native pipe representation.+ /**+ * This function may be used to obtain the underlying representation of the+ * pipe. This is intended to allow access to native pipe+ * functionality that is not otherwise provided.+ */+ native_handle_type native_handle()+ {+ return impl_.get_service().native_handle(impl_.get_implementation());+ }++ /// Cancel all asynchronous operations associated with the pipe.+ /**+ * This function causes all outstanding asynchronous read operations to finish+ * immediately, and the handlers for cancelled operations will be passed the+ * asio::error::operation_aborted error.+ *+ * @throws asio::system_error Thrown on failure.+ */+ void cancel()+ {+ asio::error_code ec;+ impl_.get_service().cancel(impl_.get_implementation(), ec);+ asio::detail::throw_error(ec, "cancel");+ }++ /// Cancel all asynchronous operations associated with the pipe.+ /**+ * This function causes all outstanding asynchronous read operations to finish+ * immediately, and the handlers for cancelled operations will be passed the+ * asio::error::operation_aborted error.+ *+ * @param ec Set to indicate what error occurred, if any.+ */+ ASIO_SYNC_OP_VOID cancel(asio::error_code& ec)+ {+ impl_.get_service().cancel(impl_.get_implementation(), ec);+ ASIO_SYNC_OP_VOID_RETURN(ec);+ }++ /// Read some data from the pipe.+ /**+ * This function is used to read data from the pipe. The function call will+ * block until one or more bytes of data has been read successfully, or until+ * an error occurs.+ *+ * @param buffers One or more buffers into which the data will be read.+ *+ * @returns The number of bytes read.+ *+ * @throws asio::system_error Thrown on failure. An error code of+ * asio::error::eof indicates that the connection was closed by the+ * peer.+ *+ * @note The read_some operation may not read all of the requested number of+ * bytes. Consider using the @ref read function if you need to ensure that+ * the requested amount of data is read before the blocking operation+ * completes.+ *+ * @par Example+ * To read into a single data buffer use the @ref buffer function as follows:+ * @code+ * basic_readable_pipe.read_some(asio::buffer(data, size));+ * @endcode+ * See the @ref buffer documentation for information on reading into multiple+ * buffers in one go, and how to use it with arrays, boost::array or+ * std::vector.+ */+ template <typename MutableBufferSequence>+ std::size_t read_some(const MutableBufferSequence& buffers)+ {+ asio::error_code ec;+ std::size_t s = impl_.get_service().read_some(+ impl_.get_implementation(), buffers, ec);+ asio::detail::throw_error(ec, "read_some");+ return s;+ }++ /// Read some data from the pipe.+ /**+ * This function is used to read data from the pipe. The function call will+ * block until one or more bytes of data has been read successfully, or until+ * an error occurs.+ *+ * @param buffers One or more buffers into which the data will be read.+ *+ * @param ec Set to indicate what error occurred, if any.+ *+ * @returns The number of bytes read. Returns 0 if an error occurred.+ *+ * @note The read_some operation may not read all of the requested number of+ * bytes. Consider using the @ref read function if you need to ensure that+ * the requested amount of data is read before the blocking operation+ * completes.+ */+ template <typename MutableBufferSequence>+ std::size_t read_some(const MutableBufferSequence& buffers,+ asio::error_code& ec)+ {+ return impl_.get_service().read_some(+ impl_.get_implementation(), buffers, ec);+ }++ /// Start an asynchronous read.+ /**+ * This function is used to asynchronously read data from the pipe. It is an+ * initiating function for an @ref asynchronous_operation, and always returns+ * immediately.+ *+ * @param buffers One or more buffers into which the data will be read.+ * Although the buffers object may be copied as necessary, ownership of the+ * underlying memory blocks is retained by the caller, which must guarantee+ * that they remain valid until the completion handler is called.+ *+ * @param token The @ref completion_token that will be used to produce a+ * completion handler, which will be called when the read completes.+ * Potential completion tokens include @ref use_future, @ref use_awaitable,+ * @ref yield_context, or a function object with the correct completion+ * signature. The function signature of the completion handler must be:+ * @code void handler(+ * const asio::error_code& error, // Result of operation.+ * std::size_t bytes_transferred // Number of bytes read.+ * ); @endcode+ * Regardless of whether the asynchronous operation completes immediately or+ * not, the completion handler will not be invoked from within this function.+ * On immediate completion, invocation of the handler will be performed in a+ * manner equivalent to using asio::post().+ *+ * @par Completion Signature+ * @code void(asio::error_code, std::size_t) @endcode+ *+ * @note The read operation may not read all of the requested number of bytes.+ * Consider using the @ref async_read function if you need to ensure that the+ * requested amount of data is read before the asynchronous operation+ * completes.+ *+ * @par Example+ * To read into a single data buffer use the @ref buffer function as follows:+ * @code+ * basic_readable_pipe.async_read_some(+ * asio::buffer(data, size), handler);+ * @endcode+ * See the @ref buffer documentation for information on reading into multiple+ * buffers in one go, and how to use it with arrays, boost::array or+ * std::vector.+ */+ template <typename MutableBufferSequence,+ ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code,+ std::size_t)) ReadToken+ ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(executor_type)>+ ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX(ReadToken,+ void (asio::error_code, std::size_t))+ async_read_some(const MutableBufferSequence& buffers,+ ASIO_MOVE_ARG(ReadToken) token+ ASIO_DEFAULT_COMPLETION_TOKEN(executor_type))+ ASIO_INITFN_AUTO_RESULT_TYPE_SUFFIX((+ async_initiate<ReadToken,+ void (asio::error_code, std::size_t)>(+ declval<initiate_async_read_some>(), token, buffers)))+ {+ return async_initiate<ReadToken,+ void (asio::error_code, std::size_t)>(+ initiate_async_read_some(this), token, buffers);+ }++private:+ // Disallow copying and assignment.+ basic_readable_pipe(const basic_readable_pipe&) ASIO_DELETED;+ basic_readable_pipe& operator=(const basic_readable_pipe&) ASIO_DELETED;++ class initiate_async_read_some+ {+ public:+ typedef Executor executor_type;++ explicit initiate_async_read_some(basic_readable_pipe* self)+ : self_(self)+ {+ }++ const executor_type& get_executor() const ASIO_NOEXCEPT+ {+ return self_->get_executor();+ }++ template <typename ReadHandler, typename MutableBufferSequence>+ void operator()(ASIO_MOVE_ARG(ReadHandler) handler,+ const MutableBufferSequence& buffers) const+ {+ // If you get an error on the following line it means that your handler+ // does not meet the documented type requirements for a ReadHandler.+ ASIO_READ_HANDLER_CHECK(ReadHandler, handler) type_check;++ detail::non_const_lvalue<ReadHandler> handler2(handler);+ self_->impl_.get_service().async_read_some(+ self_->impl_.get_implementation(), buffers,+ handler2.value, self_->impl_.get_executor());+ }++ private:+ basic_readable_pipe* self_;+ };++#if defined(ASIO_HAS_IOCP)+ detail::io_object_impl<detail::win_iocp_handle_service, Executor> impl_;+#elif defined(ASIO_HAS_IO_URING_AS_DEFAULT)+ detail::io_object_impl<detail::io_uring_descriptor_service, Executor> impl_;+#else+ detail::io_object_impl<detail::reactive_descriptor_service, Executor> impl_;+#endif+};++} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // defined(ASIO_HAS_PIPE)+ // || defined(GENERATING_DOCUMENTATION)++#endif // ASIO_BASIC_READABLE_PIPE_HPP
link/modules/asio-standalone/asio/include/asio/basic_seq_packet_socket.hpp view
@@ -2,7 +2,7 @@ // basic_seq_packet_socket.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -43,11 +43,22 @@ * @par Thread Safety * @e Distinct @e objects: Safe.@n * @e Shared @e objects: Unsafe.+ *+ * Synchronous @c send, @c receive, @c connect, and @c shutdown operations are+ * thread safe with respect to each other, if the underlying operating system+ * calls are also thread safe. This means that it is permitted to perform+ * concurrent calls to these synchronous operations on a single socket object.+ * Other synchronous operations, such as @c open or @c close, are not thread+ * safe. */ template <typename Protocol, typename Executor> class basic_seq_packet_socket : public basic_socket<Protocol, Executor> {+private:+ class initiate_async_send;+ class initiate_async_receive_with_flags;+ public: /// The type of the executor associated with the object. typedef Executor executor_type;@@ -100,9 +111,9 @@ */ template <typename ExecutionContext> explicit basic_seq_packet_socket(ExecutionContext& context,- typename enable_if<+ typename constraint< is_convertible<ExecutionContext&, execution_context&>::value- >::type* = 0)+ >::type = 0) : basic_socket<Protocol, Executor>(context) { }@@ -143,9 +154,10 @@ template <typename ExecutionContext> basic_seq_packet_socket(ExecutionContext& context, const protocol_type& protocol,- typename enable_if<- is_convertible<ExecutionContext&, execution_context&>::value- >::type* = 0)+ typename constraint<+ is_convertible<ExecutionContext&, execution_context&>::value,+ defaulted_constraint+ >::type = defaulted_constraint()) : basic_socket<Protocol, Executor>(context, protocol) { }@@ -190,9 +202,9 @@ template <typename ExecutionContext> basic_seq_packet_socket(ExecutionContext& context, const endpoint_type& endpoint,- typename enable_if<+ typename constraint< is_convertible<ExecutionContext&, execution_context&>::value- >::type* = 0)+ >::type = 0) : basic_socket<Protocol, Executor>(context, endpoint) { }@@ -235,9 +247,9 @@ template <typename ExecutionContext> basic_seq_packet_socket(ExecutionContext& context, const protocol_type& protocol, const native_handle_type& native_socket,- typename enable_if<+ typename constraint< is_convertible<ExecutionContext&, execution_context&>::value- >::type* = 0)+ >::type = 0) : basic_socket<Protocol, Executor>(context, protocol, native_socket) { }@@ -293,10 +305,10 @@ */ template <typename Protocol1, typename Executor1> basic_seq_packet_socket(basic_seq_packet_socket<Protocol1, Executor1>&& other,- typename enable_if<+ typename constraint< is_convertible<Protocol1, Protocol>::value && is_convertible<Executor1, Executor>::value- >::type* = 0)+ >::type = 0) : basic_socket<Protocol, Executor>(std::move(other)) { }@@ -315,7 +327,7 @@ * constructor. */ template <typename Protocol1, typename Executor1>- typename enable_if<+ typename constraint< is_convertible<Protocol1, Protocol>::value && is_convertible<Executor1, Executor>::value, basic_seq_packet_socket&@@ -398,27 +410,33 @@ /// Start an asynchronous send. /** * This function is used to asynchronously send data on the sequenced packet- * socket. The function call always returns immediately.+ * socket. It is an initiating function for an @ref asynchronous_operation,+ * and always returns immediately. * * @param buffers One or more data buffers to be sent on the socket. Although * the buffers object may be copied as necessary, ownership of the underlying * memory blocks is retained by the caller, which must guarantee that they- * remain valid until the handler is called.+ * remain valid until the completion handler is called. * * @param flags Flags specifying how the send call is to be made. *- * @param handler The handler to be called when the send operation completes.- * Copies will be made of the handler as required. The function signature of- * the handler must be:+ * @param token The @ref completion_token that will be used to produce a+ * completion handler, which will be called when the send completes.+ * Potential completion tokens include @ref use_future, @ref use_awaitable,+ * @ref yield_context, or a function object with the correct completion+ * signature. The function signature of the completion handler must be: * @code void handler( * const asio::error_code& error, // Result of operation.- * std::size_t bytes_transferred // Number of bytes sent.+ * std::size_t bytes_transferred // Number of bytes sent. * ); @endcode * Regardless of whether the asynchronous operation completes immediately or- * not, the handler will not be invoked from within this function. On- * immediate completion, invocation of the handler will be performed in a+ * not, the completion handler will not be invoked from within this function.+ * On immediate completion, invocation of the handler will be performed in a * manner equivalent to using asio::post(). *+ * @par Completion Signature+ * @code void(asio::error_code, std::size_t) @endcode+ * * @par Example * To send a single data buffer use the @ref buffer function as follows: * @code@@ -427,21 +445,35 @@ * See the @ref buffer documentation for information on sending multiple * buffers in one go, and how to use it with arrays, boost::array or * std::vector.+ *+ * @par Per-Operation Cancellation+ * On POSIX or Windows operating systems, this asynchronous operation supports+ * cancellation for the following asio::cancellation_type values:+ *+ * @li @c cancellation_type::terminal+ *+ * @li @c cancellation_type::partial+ *+ * @li @c cancellation_type::total */ template <typename ConstBufferSequence, ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code,- std::size_t)) WriteHandler+ std::size_t)) WriteToken ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(executor_type)>- ASIO_INITFN_AUTO_RESULT_TYPE(WriteHandler,+ ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX(WriteToken, void (asio::error_code, std::size_t)) async_send(const ConstBufferSequence& buffers, socket_base::message_flags flags,- ASIO_MOVE_ARG(WriteHandler) handler+ ASIO_MOVE_ARG(WriteToken) token ASIO_DEFAULT_COMPLETION_TOKEN(executor_type))+ ASIO_INITFN_AUTO_RESULT_TYPE_SUFFIX((+ async_initiate<WriteToken,+ void (asio::error_code, std::size_t)>(+ declval<initiate_async_send>(), token, buffers, flags))) {- return async_initiate<WriteHandler,+ return async_initiate<WriteToken, void (asio::error_code, std::size_t)>(- initiate_async_send(this), handler, buffers, flags);+ initiate_async_send(this), token, buffers, flags); } /// Receive some data on the socket.@@ -566,31 +598,37 @@ /// Start an asynchronous receive. /** * This function is used to asynchronously receive data from the sequenced- * packet socket. The function call always returns immediately.+ * packet socket. It is an initiating function for an @ref+ * asynchronous_operation, and always returns immediately. * * @param buffers One or more buffers into which the data will be received. * Although the buffers object may be copied as necessary, ownership of the * underlying memory blocks is retained by the caller, which must guarantee- * that they remain valid until the handler is called.+ * that they remain valid until the completion handler is called. * * @param out_flags Once the asynchronous operation completes, contains flags * associated with the received data. For example, if the * socket_base::message_end_of_record bit is set then the received data marks * the end of a record. The caller must guarantee that the referenced- * variable remains valid until the handler is called.+ * variable remains valid until the completion handler is called. *- * @param handler The handler to be called when the receive operation- * completes. Copies will be made of the handler as required. The function- * signature of the handler must be:+ * @param token The @ref completion_token that will be used to produce a+ * completion handler, which will be called when the receive completes.+ * Potential completion tokens include @ref use_future, @ref use_awaitable,+ * @ref yield_context, or a function object with the correct completion+ * signature. The function signature of the completion handler must be: * @code void handler( * const asio::error_code& error, // Result of operation.- * std::size_t bytes_transferred // Number of bytes received.+ * std::size_t bytes_transferred // Number of bytes received. * ); @endcode * Regardless of whether the asynchronous operation completes immediately or- * not, the handler will not be invoked from within this function. On- * immediate completion, invocation of the handler will be performed in a+ * not, the completion handler will not be invoked from within this function.+ * On immediate completion, invocation of the handler will be performed in a * manner equivalent to using asio::post(). *+ * @par Completion Signature+ * @code void(asio::error_code, std::size_t) @endcode+ * * @par Example * To receive into a single data buffer use the @ref buffer function as * follows:@@ -600,33 +638,49 @@ * See the @ref buffer documentation for information on receiving into * multiple buffers in one go, and how to use it with arrays, boost::array or * std::vector.+ *+ * @par Per-Operation Cancellation+ * On POSIX or Windows operating systems, this asynchronous operation supports+ * cancellation for the following asio::cancellation_type values:+ *+ * @li @c cancellation_type::terminal+ *+ * @li @c cancellation_type::partial+ *+ * @li @c cancellation_type::total */ template <typename MutableBufferSequence, ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code,- std::size_t)) ReadHandler+ std::size_t)) ReadToken ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(executor_type)>- ASIO_INITFN_AUTO_RESULT_TYPE(ReadHandler,+ ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX(ReadToken, void (asio::error_code, std::size_t)) async_receive(const MutableBufferSequence& buffers, socket_base::message_flags& out_flags,- ASIO_MOVE_ARG(ReadHandler) handler+ ASIO_MOVE_ARG(ReadToken) token ASIO_DEFAULT_COMPLETION_TOKEN(executor_type))+ ASIO_INITFN_AUTO_RESULT_TYPE_SUFFIX((+ async_initiate<ReadToken,+ void (asio::error_code, std::size_t)>(+ declval<initiate_async_receive_with_flags>(), token,+ buffers, socket_base::message_flags(0), &out_flags))) {- return async_initiate<ReadHandler,+ return async_initiate<ReadToken, void (asio::error_code, std::size_t)>(- initiate_async_receive_with_flags(this), handler,+ initiate_async_receive_with_flags(this), token, buffers, socket_base::message_flags(0), &out_flags); } /// Start an asynchronous receive. /** * This function is used to asynchronously receive data from the sequenced- * data socket. The function call always returns immediately.+ * data socket. It is an initiating function for an @ref+ * asynchronous_operation, and always returns immediately. * * @param buffers One or more buffers into which the data will be received. * Although the buffers object may be copied as necessary, ownership of the * underlying memory blocks is retained by the caller, which must guarantee- * that they remain valid until the handler is called.+ * that they remain valid until the completion handler is called. * * @param in_flags Flags specifying how the receive call is to be made. *@@ -634,20 +688,25 @@ * associated with the received data. For example, if the * socket_base::message_end_of_record bit is set then the received data marks * the end of a record. The caller must guarantee that the referenced- * variable remains valid until the handler is called.+ * variable remains valid until the completion handler is called. *- * @param handler The handler to be called when the receive operation- * completes. Copies will be made of the handler as required. The function- * signature of the handler must be:+ * @param token The @ref completion_token that will be used to produce a+ * completion handler, which will be called when the receive completes.+ * Potential completion tokens include @ref use_future, @ref use_awaitable,+ * @ref yield_context, or a function object with the correct completion+ * signature. The function signature of the completion handler must be: * @code void handler( * const asio::error_code& error, // Result of operation.- * std::size_t bytes_transferred // Number of bytes received.+ * std::size_t bytes_transferred // Number of bytes received. * ); @endcode * Regardless of whether the asynchronous operation completes immediately or- * not, the handler will not be invoked from within this function. On- * immediate completion, invocation of the handler will be performed in a+ * not, the completion handler will not be invoked from within this function.+ * On immediate completion, invocation of the handler will be performed in a * manner equivalent to using asio::post(). *+ * @par Completion Signature+ * @code void(asio::error_code, std::size_t) @endcode+ * * @par Example * To receive into a single data buffer use the @ref buffer function as * follows:@@ -659,23 +718,38 @@ * See the @ref buffer documentation for information on receiving into * multiple buffers in one go, and how to use it with arrays, boost::array or * std::vector.+ *+ * @par Per-Operation Cancellation+ * On POSIX or Windows operating systems, this asynchronous operation supports+ * cancellation for the following asio::cancellation_type values:+ *+ * @li @c cancellation_type::terminal+ *+ * @li @c cancellation_type::partial+ *+ * @li @c cancellation_type::total */ template <typename MutableBufferSequence, ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code,- std::size_t)) ReadHandler+ std::size_t)) ReadToken ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(executor_type)>- ASIO_INITFN_AUTO_RESULT_TYPE(ReadHandler,+ ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX(ReadToken, void (asio::error_code, std::size_t)) async_receive(const MutableBufferSequence& buffers, socket_base::message_flags in_flags, socket_base::message_flags& out_flags,- ASIO_MOVE_ARG(ReadHandler) handler+ ASIO_MOVE_ARG(ReadToken) token ASIO_DEFAULT_COMPLETION_TOKEN(executor_type))+ ASIO_INITFN_AUTO_RESULT_TYPE_SUFFIX((+ async_initiate<ReadToken,+ void (asio::error_code, std::size_t)>(+ declval<initiate_async_receive_with_flags>(),+ token, buffers, in_flags, &out_flags))) {- return async_initiate<ReadHandler,+ return async_initiate<ReadToken, void (asio::error_code, std::size_t)>( initiate_async_receive_with_flags(this),- handler, buffers, in_flags, &out_flags);+ token, buffers, in_flags, &out_flags); } private:@@ -694,7 +768,7 @@ { } - executor_type get_executor() const ASIO_NOEXCEPT+ const executor_type& get_executor() const ASIO_NOEXCEPT { return self_->get_executor(); }@@ -728,7 +802,7 @@ { } - executor_type get_executor() const ASIO_NOEXCEPT+ const executor_type& get_executor() const ASIO_NOEXCEPT { return self_->get_executor(); }
link/modules/asio-standalone/asio/include/asio/basic_serial_port.hpp view
@@ -2,7 +2,7 @@ // basic_serial_port.hpp // ~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // Copyright (c) 2008 Rep Invariant Systems, Inc. (info@repinvariant.com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying@@ -35,7 +35,7 @@ #if defined(ASIO_HAS_IOCP) # include "asio/detail/win_iocp_serial_port_service.hpp" #else-# include "asio/detail/reactive_serial_port_service.hpp"+# include "asio/detail/posix_serial_port_service.hpp" #endif #if defined(ASIO_HAS_MOVE)@@ -59,6 +59,10 @@ class basic_serial_port : public serial_port_base {+private:+ class initiate_async_write_some;+ class initiate_async_read_some;+ public: /// The type of the executor associated with the object. typedef Executor executor_type;@@ -78,7 +82,7 @@ typedef detail::win_iocp_serial_port_service::native_handle_type native_handle_type; #else- typedef detail::reactive_serial_port_service::native_handle_type+ typedef detail::posix_serial_port_service::native_handle_type native_handle_type; #endif @@ -94,7 +98,7 @@ * serial port. */ explicit basic_serial_port(const executor_type& ex)- : impl_(ex)+ : impl_(0, ex) { } @@ -108,11 +112,11 @@ */ template <typename ExecutionContext> explicit basic_serial_port(ExecutionContext& context,- typename enable_if<+ typename constraint< is_convertible<ExecutionContext&, execution_context&>::value,- basic_serial_port- >::type* = 0)- : impl_(context)+ defaulted_constraint+ >::type = defaulted_constraint())+ : impl_(0, 0, context) { } @@ -129,7 +133,7 @@ * port. */ basic_serial_port(const executor_type& ex, const char* device)- : impl_(ex)+ : impl_(0, ex) { asio::error_code ec; impl_.get_service().open(impl_.get_implementation(), device, ec);@@ -150,10 +154,10 @@ */ template <typename ExecutionContext> basic_serial_port(ExecutionContext& context, const char* device,- typename enable_if<+ typename constraint< is_convertible<ExecutionContext&, execution_context&>::value- >::type* = 0)- : impl_(context)+ >::type = 0)+ : impl_(0, 0, context) { asio::error_code ec; impl_.get_service().open(impl_.get_implementation(), device, ec);@@ -173,7 +177,7 @@ * port. */ basic_serial_port(const executor_type& ex, const std::string& device)- : impl_(ex)+ : impl_(0, ex) { asio::error_code ec; impl_.get_service().open(impl_.get_implementation(), device, ec);@@ -194,10 +198,10 @@ */ template <typename ExecutionContext> basic_serial_port(ExecutionContext& context, const std::string& device,- typename enable_if<+ typename constraint< is_convertible<ExecutionContext&, execution_context&>::value- >::type* = 0)- : impl_(context)+ >::type = 0)+ : impl_(0, 0, context) { asio::error_code ec; impl_.get_service().open(impl_.get_implementation(), device, ec);@@ -219,7 +223,7 @@ */ basic_serial_port(const executor_type& ex, const native_handle_type& native_serial_port)- : impl_(ex)+ : impl_(0, ex) { asio::error_code ec; impl_.get_service().assign(impl_.get_implementation(),@@ -243,10 +247,10 @@ template <typename ExecutionContext> basic_serial_port(ExecutionContext& context, const native_handle_type& native_serial_port,- typename enable_if<+ typename constraint< is_convertible<ExecutionContext&, execution_context&>::value- >::type* = 0)- : impl_(context)+ >::type = 0)+ : impl_(0, 0, context) { asio::error_code ec; impl_.get_service().assign(impl_.get_implementation(),@@ -287,6 +291,55 @@ impl_ = std::move(other.impl_); return *this; }++ // All serial ports have access to each other's implementations.+ template <typename Executor1>+ friend class basic_serial_port;++ /// Move-construct a basic_serial_port from a serial port of another executor+ /// type.+ /**+ * This constructor moves a serial port from one object to another.+ *+ * @param other The other basic_serial_port object from which the move will+ * occur.+ *+ * @note Following the move, the moved-from object is in the same state as if+ * constructed using the @c basic_serial_port(const executor_type&)+ * constructor.+ */+ template <typename Executor1>+ basic_serial_port(basic_serial_port<Executor1>&& other,+ typename constraint<+ is_convertible<Executor1, Executor>::value,+ defaulted_constraint+ >::type = defaulted_constraint())+ : impl_(std::move(other.impl_))+ {+ }++ /// Move-assign a basic_serial_port from a serial port of another executor+ /// type.+ /**+ * This assignment operator moves a serial port from one object to another.+ *+ * @param other The other basic_serial_port object from which the move will+ * occur.+ *+ * @note Following the move, the moved-from object is in the same state as if+ * constructed using the @c basic_serial_port(const executor_type&)+ * constructor.+ */+ template <typename Executor1>+ typename constraint<+ is_convertible<Executor1, Executor>::value,+ basic_serial_port&+ >::type operator=(basic_serial_port<Executor1>&& other)+ {+ basic_serial_port tmp(std::move(other));+ impl_ = std::move(tmp.impl_);+ return *this;+ } #endif // defined(ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION) /// Destroys the serial port.@@ -300,7 +353,7 @@ } /// Get the executor associated with the object.- executor_type get_executor() ASIO_NOEXCEPT+ const executor_type& get_executor() ASIO_NOEXCEPT { return impl_.get_executor(); }@@ -656,25 +709,31 @@ /// Start an asynchronous write. /** * This function is used to asynchronously write data to the serial port.- * The function call always returns immediately.+ * It is an initiating function for an @ref asynchronous_operation, and always+ * returns immediately. * * @param buffers One or more data buffers to be written to the serial port. * Although the buffers object may be copied as necessary, ownership of the * underlying memory blocks is retained by the caller, which must guarantee- * that they remain valid until the handler is called.+ * that they remain valid until the completion handler is called. *- * @param handler The handler to be called when the write operation completes.- * Copies will be made of the handler as required. The function signature of- * the handler must be:+ * @param token The @ref completion_token that will be used to produce a+ * completion handler, which will be called when the write completes.+ * Potential completion tokens include @ref use_future, @ref use_awaitable,+ * @ref yield_context, or a function object with the correct completion+ * signature. The function signature of the completion handler must be: * @code void handler( * const asio::error_code& error, // Result of operation.- * std::size_t bytes_transferred // Number of bytes written.+ * std::size_t bytes_transferred // Number of bytes written. * ); @endcode * Regardless of whether the asynchronous operation completes immediately or- * not, the handler will not be invoked from within this function. On- * immediate completion, invocation of the handler will be performed in a+ * not, the completion handler will not be invoked from within this function.+ * On immediate completion, invocation of the handler will be performed in a * manner equivalent to using asio::post(). *+ * @par Completion Signature+ * @code void(asio::error_code, std::size_t) @endcode+ * * @note The write operation may not transmit all of the data to the peer. * Consider using the @ref async_write function if you need to ensure that all * data is written before the asynchronous operation completes.@@ -688,20 +747,34 @@ * See the @ref buffer documentation for information on writing multiple * buffers in one go, and how to use it with arrays, boost::array or * std::vector.+ *+ * @par Per-Operation Cancellation+ * On POSIX or Windows operating systems, this asynchronous operation supports+ * cancellation for the following asio::cancellation_type values:+ *+ * @li @c cancellation_type::terminal+ *+ * @li @c cancellation_type::partial+ *+ * @li @c cancellation_type::total */ template <typename ConstBufferSequence, ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code,- std::size_t)) WriteHandler+ std::size_t)) WriteToken ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(executor_type)>- ASIO_INITFN_AUTO_RESULT_TYPE(WriteHandler,+ ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX(WriteToken, void (asio::error_code, std::size_t)) async_write_some(const ConstBufferSequence& buffers,- ASIO_MOVE_ARG(WriteHandler) handler+ ASIO_MOVE_ARG(WriteToken) token ASIO_DEFAULT_COMPLETION_TOKEN(executor_type))+ ASIO_INITFN_AUTO_RESULT_TYPE_SUFFIX((+ async_initiate<WriteToken,+ void (asio::error_code, std::size_t)>(+ declval<initiate_async_write_some>(), token, buffers))) {- return async_initiate<WriteHandler,+ return async_initiate<WriteToken, void (asio::error_code, std::size_t)>(- initiate_async_write_some(this), handler, buffers);+ initiate_async_write_some(this), token, buffers); } /// Read some data from the serial port.@@ -770,25 +843,31 @@ /// Start an asynchronous read. /** * This function is used to asynchronously read data from the serial port.- * The function call always returns immediately.+ * It is an initiating function for an @ref asynchronous_operation, and always+ * returns immediately. * * @param buffers One or more buffers into which the data will be read. * Although the buffers object may be copied as necessary, ownership of the * underlying memory blocks is retained by the caller, which must guarantee- * that they remain valid until the handler is called.+ * that they remain valid until the completion handler is called. *- * @param handler The handler to be called when the read operation completes.- * Copies will be made of the handler as required. The function signature of- * the handler must be:+ * @param token The @ref completion_token that will be used to produce a+ * completion handler, which will be called when the read completes.+ * Potential completion tokens include @ref use_future, @ref use_awaitable,+ * @ref yield_context, or a function object with the correct completion+ * signature. The function signature of the completion handler must be: * @code void handler( * const asio::error_code& error, // Result of operation.- * std::size_t bytes_transferred // Number of bytes read.+ * std::size_t bytes_transferred // Number of bytes read. * ); @endcode * Regardless of whether the asynchronous operation completes immediately or- * not, the handler will not be invoked from within this function. On- * immediate completion, invocation of the handler will be performed in a+ * not, the completion handler will not be invoked from within this function.+ * On immediate completion, invocation of the handler will be performed in a * manner equivalent to using asio::post(). *+ * @par Completion Signature+ * @code void(asio::error_code, std::size_t) @endcode+ * * @note The read operation may not read all of the requested number of bytes. * Consider using the @ref async_read function if you need to ensure that the * requested amount of data is read before the asynchronous operation@@ -803,20 +882,34 @@ * See the @ref buffer documentation for information on reading into multiple * buffers in one go, and how to use it with arrays, boost::array or * std::vector.+ *+ * @par Per-Operation Cancellation+ * On POSIX or Windows operating systems, this asynchronous operation supports+ * cancellation for the following asio::cancellation_type values:+ *+ * @li @c cancellation_type::terminal+ *+ * @li @c cancellation_type::partial+ *+ * @li @c cancellation_type::total */ template <typename MutableBufferSequence, ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code,- std::size_t)) ReadHandler+ std::size_t)) ReadToken ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(executor_type)>- ASIO_INITFN_AUTO_RESULT_TYPE(ReadHandler,+ ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX(ReadToken, void (asio::error_code, std::size_t)) async_read_some(const MutableBufferSequence& buffers,- ASIO_MOVE_ARG(ReadHandler) handler+ ASIO_MOVE_ARG(ReadToken) token ASIO_DEFAULT_COMPLETION_TOKEN(executor_type))+ ASIO_INITFN_AUTO_RESULT_TYPE_SUFFIX((+ async_initiate<ReadToken,+ void (asio::error_code, std::size_t)>(+ declval<initiate_async_read_some>(), token, buffers))) {- return async_initiate<ReadHandler,+ return async_initiate<ReadToken, void (asio::error_code, std::size_t)>(- initiate_async_read_some(this), handler, buffers);+ initiate_async_read_some(this), token, buffers); } private:@@ -834,7 +927,7 @@ { } - executor_type get_executor() const ASIO_NOEXCEPT+ const executor_type& get_executor() const ASIO_NOEXCEPT { return self_->get_executor(); }@@ -867,7 +960,7 @@ { } - executor_type get_executor() const ASIO_NOEXCEPT+ const executor_type& get_executor() const ASIO_NOEXCEPT { return self_->get_executor(); }@@ -893,7 +986,7 @@ #if defined(ASIO_HAS_IOCP) detail::io_object_impl<detail::win_iocp_serial_port_service, Executor> impl_; #else- detail::io_object_impl<detail::reactive_serial_port_service, Executor> impl_;+ detail::io_object_impl<detail::posix_serial_port_service, Executor> impl_; #endif };
link/modules/asio-standalone/asio/include/asio/basic_signal_set.hpp view
@@ -2,7 +2,7 @@ // basic_signal_set.hpp // ~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -27,7 +27,10 @@ #include "asio/detail/type_traits.hpp" #include "asio/error.hpp" #include "asio/execution_context.hpp"+#include "asio/signal_set_base.hpp" +#include "asio/detail/push_options.hpp"+ namespace asio { /// Provides signal functionality.@@ -91,8 +94,11 @@ * least one thread. */ template <typename Executor = any_io_executor>-class basic_signal_set+class basic_signal_set : public signal_set_base {+private:+ class initiate_async_wait;+ public: /// The type of the executor associated with the object. typedef Executor executor_type;@@ -114,7 +120,7 @@ * signal set. */ explicit basic_signal_set(const executor_type& ex)- : impl_(ex)+ : impl_(0, ex) { } @@ -128,10 +134,11 @@ */ template <typename ExecutionContext> explicit basic_signal_set(ExecutionContext& context,- typename enable_if<- is_convertible<ExecutionContext&, execution_context&>::value- >::type* = 0)- : impl_(context)+ typename constraint<+ is_convertible<ExecutionContext&, execution_context&>::value,+ defaulted_constraint+ >::type = defaulted_constraint())+ : impl_(0, 0, context) { } @@ -150,7 +157,7 @@ * signals.add(signal_number_1); @endcode */ basic_signal_set(const executor_type& ex, int signal_number_1)- : impl_(ex)+ : impl_(0, ex) { asio::error_code ec; impl_.get_service().add(impl_.get_implementation(), signal_number_1, ec);@@ -173,10 +180,11 @@ */ template <typename ExecutionContext> basic_signal_set(ExecutionContext& context, int signal_number_1,- typename enable_if<- is_convertible<ExecutionContext&, execution_context&>::value- >::type* = 0)- : impl_(context)+ typename constraint<+ is_convertible<ExecutionContext&, execution_context&>::value,+ defaulted_constraint+ >::type = defaulted_constraint())+ : impl_(0, 0, context) { asio::error_code ec; impl_.get_service().add(impl_.get_implementation(), signal_number_1, ec);@@ -202,7 +210,7 @@ */ basic_signal_set(const executor_type& ex, int signal_number_1, int signal_number_2)- : impl_(ex)+ : impl_(0, ex) { asio::error_code ec; impl_.get_service().add(impl_.get_implementation(), signal_number_1, ec);@@ -231,10 +239,11 @@ template <typename ExecutionContext> basic_signal_set(ExecutionContext& context, int signal_number_1, int signal_number_2,- typename enable_if<- is_convertible<ExecutionContext&, execution_context&>::value- >::type* = 0)- : impl_(context)+ typename constraint<+ is_convertible<ExecutionContext&, execution_context&>::value,+ defaulted_constraint+ >::type = defaulted_constraint())+ : impl_(0, 0, context) { asio::error_code ec; impl_.get_service().add(impl_.get_implementation(), signal_number_1, ec);@@ -265,7 +274,7 @@ */ basic_signal_set(const executor_type& ex, int signal_number_1, int signal_number_2, int signal_number_3)- : impl_(ex)+ : impl_(0, ex) { asio::error_code ec; impl_.get_service().add(impl_.get_implementation(), signal_number_1, ec);@@ -299,10 +308,11 @@ template <typename ExecutionContext> basic_signal_set(ExecutionContext& context, int signal_number_1, int signal_number_2, int signal_number_3,- typename enable_if<- is_convertible<ExecutionContext&, execution_context&>::value- >::type* = 0)- : impl_(context)+ typename constraint<+ is_convertible<ExecutionContext&, execution_context&>::value,+ defaulted_constraint+ >::type = defaulted_constraint())+ : impl_(0, 0, context) { asio::error_code ec; impl_.get_service().add(impl_.get_implementation(), signal_number_1, ec);@@ -324,7 +334,7 @@ } /// Get the executor associated with the object.- executor_type get_executor() ASIO_NOEXCEPT+ const executor_type& get_executor() ASIO_NOEXCEPT { return impl_.get_executor(); }@@ -361,6 +371,58 @@ ASIO_SYNC_OP_VOID_RETURN(ec); } + /// Add a signal to a signal_set with the specified flags.+ /**+ * This function adds the specified signal to the set. It has no effect if the+ * signal is already in the set.+ *+ * Flags other than flags::dont_care require OS support for the @c sigaction+ * call, and this function will fail with @c error::operation_not_supported if+ * this is unavailable.+ *+ * The specified flags will conflict with a prior, active registration of the+ * same signal, if either specified a flags value other than flags::dont_care.+ * In this case, the @c add will fail with @c error::invalid_argument.+ *+ * @param signal_number The signal to be added to the set.+ *+ * @param f Flags to modify the behaviour of the specified signal.+ *+ * @throws asio::system_error Thrown on failure.+ */+ void add(int signal_number, flags_t f)+ {+ asio::error_code ec;+ impl_.get_service().add(impl_.get_implementation(), signal_number, f, ec);+ asio::detail::throw_error(ec, "add");+ }++ /// Add a signal to a signal_set with the specified flags.+ /**+ * This function adds the specified signal to the set. It has no effect if the+ * signal is already in the set.+ *+ * Flags other than flags::dont_care require OS support for the @c sigaction+ * call, and this function will fail with @c error::operation_not_supported if+ * this is unavailable.+ *+ * The specified flags will conflict with a prior, active registration of the+ * same signal, if either specified a flags value other than flags::dont_care.+ * In this case, the @c add will fail with @c error::invalid_argument.+ *+ * @param signal_number The signal to be added to the set.+ *+ * @param f Flags to modify the behaviour of the specified signal.+ *+ * @param ec Set to indicate what error occurred, if any.+ */+ ASIO_SYNC_OP_VOID add(int signal_number, flags_t f,+ asio::error_code& ec)+ {+ impl_.get_service().add(impl_.get_implementation(), signal_number, f, ec);+ ASIO_SYNC_OP_VOID_RETURN(ec);+ }+ /// Remove a signal from a signal_set. /** * This function removes the specified signal from the set. It has no effect@@ -488,39 +550,58 @@ /// Start an asynchronous operation to wait for a signal to be delivered. /** * This function may be used to initiate an asynchronous wait against the- * signal set. It always returns immediately.+ * signal set. It is an initiating function for an @ref+ * asynchronous_operation, and always returns immediately. *- * For each call to async_wait(), the supplied handler will be called exactly- * once. The handler will be called when:+ * For each call to async_wait(), the completion handler will be called+ * exactly once. The completion handler will be called when: * * @li One of the registered signals in the signal set occurs; or * * @li The signal set was cancelled, in which case the handler is passed the * error code asio::error::operation_aborted. *- * @param handler The handler to be called when the signal occurs. Copies- * will be made of the handler as required. The function signature of the- * handler must be:+ * @param token The @ref completion_token that will be used to produce a+ * completion handler, which will be called when the wait completes.+ * Potential completion tokens include @ref use_future, @ref use_awaitable,+ * @ref yield_context, or a function object with the correct completion+ * signature. The function signature of the completion handler must be: * @code void handler( * const asio::error_code& error, // Result of operation. * int signal_number // Indicates which signal occurred. * ); @endcode * Regardless of whether the asynchronous operation completes immediately or- * not, the handler will not be invoked from within this function. On- * immediate completion, invocation of the handler will be performed in a+ * not, the completion handler will not be invoked from within this function.+ * On immediate completion, invocation of the handler will be performed in a * manner equivalent to using asio::post().+ *+ * @par Completion Signature+ * @code void(asio::error_code, int) @endcode+ *+ * @par Per-Operation Cancellation+ * This asynchronous operation supports cancellation for the following+ * asio::cancellation_type values:+ *+ * @li @c cancellation_type::terminal+ *+ * @li @c cancellation_type::partial+ *+ * @li @c cancellation_type::total */ template < ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code, int))- SignalHandler ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(executor_type)>- ASIO_INITFN_AUTO_RESULT_TYPE(SignalHandler,+ SignalToken ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(executor_type)>+ ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX(SignalToken, void (asio::error_code, int)) async_wait(- ASIO_MOVE_ARG(SignalHandler) handler+ ASIO_MOVE_ARG(SignalToken) token ASIO_DEFAULT_COMPLETION_TOKEN(executor_type))+ ASIO_INITFN_AUTO_RESULT_TYPE_SUFFIX((+ async_initiate<SignalToken, void (asio::error_code, int)>(+ declval<initiate_async_wait>(), token))) {- return async_initiate<SignalHandler, void (asio::error_code, int)>(- initiate_async_wait(this), handler);+ return async_initiate<SignalToken, void (asio::error_code, int)>(+ initiate_async_wait(this), token); } private:@@ -538,7 +619,7 @@ { } - executor_type get_executor() const ASIO_NOEXCEPT+ const executor_type& get_executor() const ASIO_NOEXCEPT { return self_->get_executor(); }@@ -564,5 +645,7 @@ }; } // namespace asio++#include "asio/detail/pop_options.hpp" #endif // ASIO_BASIC_SIGNAL_SET_HPP
link/modules/asio-standalone/asio/include/asio/basic_socket.hpp view
@@ -2,7 +2,7 @@ // basic_socket.hpp // ~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -32,6 +32,8 @@ # include "asio/detail/null_socket_service.hpp" #elif defined(ASIO_HAS_IOCP) # include "asio/detail/win_iocp_socket_service.hpp"+#elif defined(ASIO_HAS_IO_URING_AS_DEFAULT)+# include "asio/detail/io_uring_socket_service.hpp" #else # include "asio/detail/reactive_socket_service.hpp" #endif@@ -66,6 +68,10 @@ class basic_socket : public socket_base {+private:+ class initiate_async_connect;+ class initiate_async_wait;+ public: /// The type of the executor associated with the object. typedef Executor executor_type;@@ -87,6 +93,9 @@ #elif defined(ASIO_HAS_IOCP) typedef typename detail::win_iocp_socket_service< Protocol>::native_handle_type native_handle_type;+#elif defined(ASIO_HAS_IO_URING_AS_DEFAULT)+ typedef typename detail::io_uring_socket_service<+ Protocol>::native_handle_type native_handle_type; #else typedef typename detail::reactive_socket_service< Protocol>::native_handle_type native_handle_type;@@ -111,7 +120,7 @@ * dispatch handlers for any asynchronous operations performed on the socket. */ explicit basic_socket(const executor_type& ex)- : impl_(ex)+ : impl_(0, ex) { } @@ -125,10 +134,10 @@ */ template <typename ExecutionContext> explicit basic_socket(ExecutionContext& context,- typename enable_if<+ typename constraint< is_convertible<ExecutionContext&, execution_context&>::value- >::type* = 0)- : impl_(context)+ >::type = 0)+ : impl_(0, 0, context) { } @@ -144,7 +153,7 @@ * @throws asio::system_error Thrown on failure. */ basic_socket(const executor_type& ex, const protocol_type& protocol)- : impl_(ex)+ : impl_(0, ex) { asio::error_code ec; impl_.get_service().open(impl_.get_implementation(), protocol, ec);@@ -165,10 +174,11 @@ */ template <typename ExecutionContext> basic_socket(ExecutionContext& context, const protocol_type& protocol,- typename enable_if<- is_convertible<ExecutionContext&, execution_context&>::value- >::type* = 0)- : impl_(context)+ typename constraint<+ is_convertible<ExecutionContext&, execution_context&>::value,+ defaulted_constraint+ >::type = defaulted_constraint())+ : impl_(0, 0, context) { asio::error_code ec; impl_.get_service().open(impl_.get_implementation(), protocol, ec);@@ -191,7 +201,7 @@ * @throws asio::system_error Thrown on failure. */ basic_socket(const executor_type& ex, const endpoint_type& endpoint)- : impl_(ex)+ : impl_(0, ex) { asio::error_code ec; const protocol_type protocol = endpoint.protocol();@@ -219,10 +229,10 @@ */ template <typename ExecutionContext> basic_socket(ExecutionContext& context, const endpoint_type& endpoint,- typename enable_if<+ typename constraint< is_convertible<ExecutionContext&, execution_context&>::value- >::type* = 0)- : impl_(context)+ >::type = 0)+ : impl_(0, 0, context) { asio::error_code ec; const protocol_type protocol = endpoint.protocol();@@ -247,7 +257,7 @@ */ basic_socket(const executor_type& ex, const protocol_type& protocol, const native_handle_type& native_socket)- : impl_(ex)+ : impl_(0, ex) { asio::error_code ec; impl_.get_service().assign(impl_.get_implementation(),@@ -272,10 +282,10 @@ template <typename ExecutionContext> basic_socket(ExecutionContext& context, const protocol_type& protocol, const native_handle_type& native_socket,- typename enable_if<+ typename constraint< is_convertible<ExecutionContext&, execution_context&>::value- >::type* = 0)- : impl_(context)+ >::type = 0)+ : impl_(0, 0, context) { asio::error_code ec; impl_.get_service().assign(impl_.get_implementation(),@@ -331,10 +341,10 @@ */ template <typename Protocol1, typename Executor1> basic_socket(basic_socket<Protocol1, Executor1>&& other,- typename enable_if<+ typename constraint< is_convertible<Protocol1, Protocol>::value && is_convertible<Executor1, Executor>::value- >::type* = 0)+ >::type = 0) : impl_(std::move(other.impl_)) { }@@ -350,11 +360,11 @@ * constructed using the @c basic_socket(const executor_type&) constructor. */ template <typename Protocol1, typename Executor1>- typename enable_if<+ typename constraint< is_convertible<Protocol1, Protocol>::value && is_convertible<Executor1, Executor>::value, basic_socket&- >::type operator=(basic_socket<Protocol1, Executor1> && other)+ >::type operator=(basic_socket<Protocol1, Executor1>&& other) { basic_socket tmp(std::move(other)); impl_ = std::move(tmp.impl_);@@ -363,7 +373,7 @@ #endif // defined(ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION) /// Get the executor associated with the object.- executor_type get_executor() ASIO_NOEXCEPT+ const executor_type& get_executor() ASIO_NOEXCEPT { return impl_.get_executor(); }@@ -901,7 +911,8 @@ /// Start an asynchronous connect. /** * This function is used to asynchronously connect a socket to the specified- * remote endpoint. The function call always returns immediately.+ * remote endpoint. It is an initiating function for an @ref+ * asynchronous_operation, and always returns immediately. * * The socket is automatically opened if it is not already open. If the * connect fails, and the socket was automatically opened, the socket is@@ -910,17 +921,22 @@ * @param peer_endpoint The remote endpoint to which the socket will be * connected. Copies will be made of the endpoint object as required. *- * @param handler The handler to be called when the connection operation- * completes. Copies will be made of the handler as required. The function- * signature of the handler must be:+ * @param token The @ref completion_token that will be used to produce a+ * completion handler, which will be called when the connect completes.+ * Potential completion tokens include @ref use_future, @ref use_awaitable,+ * @ref yield_context, or a function object with the correct completion+ * signature. The function signature of the completion handler must be: * @code void handler(- * const asio::error_code& error // Result of operation+ * const asio::error_code& error // Result of operation. * ); @endcode * Regardless of whether the asynchronous operation completes immediately or- * not, the handler will not be invoked from within this function. On- * immediate completion, invocation of the handler will be performed in a+ * not, the completion handler will not be invoked from within this function.+ * On immediate completion, invocation of the handler will be performed in a * manner equivalent to using asio::post(). *+ * @par Completion Signature+ * @code void(asio::error_code) @endcode+ * * @par Example * @code * void connect_handler(const asio::error_code& error)@@ -938,15 +954,29 @@ * asio::ip::address::from_string("1.2.3.4"), 12345); * socket.async_connect(endpoint, connect_handler); * @endcode+ *+ * @par Per-Operation Cancellation+ * On POSIX or Windows operating systems, this asynchronous operation supports+ * cancellation for the following asio::cancellation_type values:+ *+ * @li @c cancellation_type::terminal+ *+ * @li @c cancellation_type::partial+ *+ * @li @c cancellation_type::total */ template < ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code))- ConnectHandler ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(executor_type)>- ASIO_INITFN_AUTO_RESULT_TYPE(ConnectHandler,+ ConnectToken ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(executor_type)>+ ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX(ConnectToken, void (asio::error_code)) async_connect(const endpoint_type& peer_endpoint,- ASIO_MOVE_ARG(ConnectHandler) handler+ ASIO_MOVE_ARG(ConnectToken) token ASIO_DEFAULT_COMPLETION_TOKEN(executor_type))+ ASIO_INITFN_AUTO_RESULT_TYPE_SUFFIX((+ async_initiate<ConnectToken, void (asio::error_code)>(+ declval<initiate_async_connect>(), token,+ peer_endpoint, declval<asio::error_code&>()))) { asio::error_code open_ec; if (!is_open())@@ -955,8 +985,8 @@ impl_.get_service().open(impl_.get_implementation(), protocol, open_ec); } - return async_initiate<ConnectHandler, void (asio::error_code)>(- initiate_async_connect(this), handler, peer_endpoint, open_ec);+ return async_initiate<ConnectToken, void (asio::error_code)>(+ initiate_async_connect(this), token, peer_endpoint, open_ec); } /// Set an option on the socket.@@ -1740,21 +1770,28 @@ /// write, or to have pending error conditions. /** * This function is used to perform an asynchronous wait for a socket to enter- * a ready to read, write or error condition state.+ * a ready to read, write or error condition state. It is an initiating+ * function for an @ref asynchronous_operation, and always returns+ * immediately. * * @param w Specifies the desired socket state. *- * @param handler The handler to be called when the wait operation completes.- * Copies will be made of the handler as required. The function signature of- * the handler must be:+ * @param token The @ref completion_token that will be used to produce a+ * completion handler, which will be called when the wait completes. Potential+ * completion tokens include @ref use_future, @ref use_awaitable, @ref+ * yield_context, or a function object with the correct completion signature.+ * The function signature of the completion handler must be: * @code void handler(- * const asio::error_code& error // Result of operation+ * const asio::error_code& error // Result of operation. * ); @endcode * Regardless of whether the asynchronous operation completes immediately or- * not, the handler will not be invoked from within this function. On- * immediate completion, invocation of the handler will be performed in a+ * not, the completion handler will not be invoked from within this function.+ * On immediate completion, invocation of the handler will be performed in a * manner equivalent to using asio::post(). *+ * @par Completion Signature+ * @code void(asio::error_code) @endcode+ * * @par Example * @code * void wait_handler(const asio::error_code& error)@@ -1771,18 +1808,31 @@ * ... * socket.async_wait(asio::ip::tcp::socket::wait_read, wait_handler); * @endcode+ *+ * @par Per-Operation Cancellation+ * On POSIX or Windows operating systems, this asynchronous operation supports+ * cancellation for the following asio::cancellation_type values:+ *+ * @li @c cancellation_type::terminal+ *+ * @li @c cancellation_type::partial+ *+ * @li @c cancellation_type::total */ template < ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code))- WaitHandler ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(executor_type)>- ASIO_INITFN_AUTO_RESULT_TYPE(WaitHandler,+ WaitToken ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(executor_type)>+ ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX(WaitToken, void (asio::error_code)) async_wait(wait_type w,- ASIO_MOVE_ARG(WaitHandler) handler+ ASIO_MOVE_ARG(WaitToken) token ASIO_DEFAULT_COMPLETION_TOKEN(executor_type))+ ASIO_INITFN_AUTO_RESULT_TYPE_SUFFIX((+ async_initiate<WaitToken, void (asio::error_code)>(+ declval<initiate_async_wait>(), token, w))) {- return async_initiate<WaitHandler, void (asio::error_code)>(- initiate_async_wait(this), handler, w);+ return async_initiate<WaitToken, void (asio::error_code)>(+ initiate_async_wait(this), token, w); } protected:@@ -1801,6 +1851,9 @@ #elif defined(ASIO_HAS_IOCP) detail::io_object_impl< detail::win_iocp_socket_service<Protocol>, Executor> impl_;+#elif defined(ASIO_HAS_IO_URING_AS_DEFAULT)+ detail::io_object_impl<+ detail::io_uring_socket_service<Protocol>, Executor> impl_; #else detail::io_object_impl< detail::reactive_socket_service<Protocol>, Executor> impl_;@@ -1821,7 +1874,7 @@ { } - executor_type get_executor() const ASIO_NOEXCEPT+ const executor_type& get_executor() const ASIO_NOEXCEPT { return self_->get_executor(); }@@ -1864,7 +1917,7 @@ { } - executor_type get_executor() const ASIO_NOEXCEPT+ const executor_type& get_executor() const ASIO_NOEXCEPT { return self_->get_executor(); }
link/modules/asio-standalone/asio/include/asio/basic_socket_acceptor.hpp view
@@ -2,7 +2,7 @@ // basic_socket_acceptor.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -31,6 +31,8 @@ # include "asio/detail/null_socket_service.hpp" #elif defined(ASIO_HAS_IOCP) # include "asio/detail/win_iocp_socket_service.hpp"+#elif defined(ASIO_HAS_IO_URING_AS_DEFAULT)+# include "asio/detail/io_uring_socket_service.hpp" #else # include "asio/detail/reactive_socket_service.hpp" #endif@@ -61,6 +63,12 @@ * @e Distinct @e objects: Safe.@n * @e Shared @e objects: Unsafe. *+ * Synchronous @c accept operations are thread safe, if the underlying+ * operating system calls are also thread safe. This means that it is permitted+ * to perform concurrent calls to synchronous @c accept operations on a single+ * socket object. Other synchronous operations, such as @c open or @c close, are+ * not thread safe.+ * * @par Example * Opening a socket acceptor with the SO_REUSEADDR option enabled: * @code@@ -76,6 +84,11 @@ class basic_socket_acceptor : public socket_base {+private:+ class initiate_async_wait;+ class initiate_async_accept;+ class initiate_async_move_accept;+ public: /// The type of the executor associated with the object. typedef Executor executor_type;@@ -97,6 +110,9 @@ #elif defined(ASIO_HAS_IOCP) typedef typename detail::win_iocp_socket_service< Protocol>::native_handle_type native_handle_type;+#elif defined(ASIO_HAS_IO_URING_AS_DEFAULT)+ typedef typename detail::io_uring_socket_service<+ Protocol>::native_handle_type native_handle_type; #else typedef typename detail::reactive_socket_service< Protocol>::native_handle_type native_handle_type;@@ -119,7 +135,7 @@ * acceptor. */ explicit basic_socket_acceptor(const executor_type& ex)- : impl_(ex)+ : impl_(0, ex) { } @@ -135,10 +151,10 @@ */ template <typename ExecutionContext> explicit basic_socket_acceptor(ExecutionContext& context,- typename enable_if<+ typename constraint< is_convertible<ExecutionContext&, execution_context&>::value- >::type* = 0)- : impl_(context)+ >::type = 0)+ : impl_(0, 0, context) { } @@ -155,7 +171,7 @@ * @throws asio::system_error Thrown on failure. */ basic_socket_acceptor(const executor_type& ex, const protocol_type& protocol)- : impl_(ex)+ : impl_(0, ex) { asio::error_code ec; impl_.get_service().open(impl_.get_implementation(), protocol, ec);@@ -177,10 +193,11 @@ template <typename ExecutionContext> basic_socket_acceptor(ExecutionContext& context, const protocol_type& protocol,- typename enable_if<- is_convertible<ExecutionContext&, execution_context&>::value- >::type* = 0)- : impl_(context)+ typename constraint<+ is_convertible<ExecutionContext&, execution_context&>::value,+ defaulted_constraint+ >::type = defaulted_constraint())+ : impl_(0, 0, context) { asio::error_code ec; impl_.get_service().open(impl_.get_implementation(), protocol, ec);@@ -216,7 +233,7 @@ */ basic_socket_acceptor(const executor_type& ex, const endpoint_type& endpoint, bool reuse_addr = true)- : impl_(ex)+ : impl_(0, ex) { asio::error_code ec; const protocol_type protocol = endpoint.protocol();@@ -265,10 +282,10 @@ template <typename ExecutionContext> basic_socket_acceptor(ExecutionContext& context, const endpoint_type& endpoint, bool reuse_addr = true,- typename enable_if<+ typename constraint< is_convertible<ExecutionContext&, execution_context&>::value- >::type* = 0)- : impl_(context)+ >::type = 0)+ : impl_(0, 0, context) { asio::error_code ec; const protocol_type protocol = endpoint.protocol();@@ -304,7 +321,7 @@ */ basic_socket_acceptor(const executor_type& ex, const protocol_type& protocol, const native_handle_type& native_acceptor)- : impl_(ex)+ : impl_(0, ex) { asio::error_code ec; impl_.get_service().assign(impl_.get_implementation(),@@ -330,10 +347,10 @@ template <typename ExecutionContext> basic_socket_acceptor(ExecutionContext& context, const protocol_type& protocol, const native_handle_type& native_acceptor,- typename enable_if<+ typename constraint< is_convertible<ExecutionContext&, execution_context&>::value- >::type* = 0)- : impl_(context)+ >::type = 0)+ : impl_(0, 0, context) { asio::error_code ec; impl_.get_service().assign(impl_.get_implementation(),@@ -393,10 +410,10 @@ */ template <typename Protocol1, typename Executor1> basic_socket_acceptor(basic_socket_acceptor<Protocol1, Executor1>&& other,- typename enable_if<+ typename constraint< is_convertible<Protocol1, Protocol>::value && is_convertible<Executor1, Executor>::value- >::type* = 0)+ >::type = 0) : impl_(std::move(other.impl_)) { }@@ -414,7 +431,7 @@ * constructor. */ template <typename Protocol1, typename Executor1>- typename enable_if<+ typename constraint< is_convertible<Protocol1, Protocol>::value && is_convertible<Executor1, Executor>::value, basic_socket_acceptor&@@ -437,7 +454,7 @@ } /// Get the executor associated with the object.- executor_type get_executor() ASIO_NOEXCEPT+ const executor_type& get_executor() ASIO_NOEXCEPT { return impl_.get_executor(); }@@ -1184,21 +1201,28 @@ /// write, or to have pending error conditions. /** * This function is used to perform an asynchronous wait for an acceptor to- * enter a ready to read, write or error condition state.+ * enter a ready to read, write or error condition state. It is an initiating+ * function for an @ref asynchronous_operation, and always returns+ * immediately. * * @param w Specifies the desired acceptor state. *- * @param handler The handler to be called when the wait operation completes.- * Copies will be made of the handler as required. The function signature of- * the handler must be:+ * @param token The @ref completion_token that will be used to produce a+ * completion handler, which will be called when the wait completes.+ * Potential completion tokens include @ref use_future, @ref use_awaitable,+ * @ref yield_context, or a function object with the correct completion+ * signature. The function signature of the completion handler must be: * @code void handler(- * const asio::error_code& error // Result of operation+ * const asio::error_code& error // Result of operation. * ); @endcode * Regardless of whether the asynchronous operation completes immediately or- * not, the handler will not be invoked from within this function. On- * immediate completion, invocation of the handler will be performed in a+ * not, the completion handler will not be invoked from within this function.+ * On immediate completion, invocation of the handler will be performed in a * manner equivalent to using asio::post(). *+ * @par Completion Signature+ * @code void(asio::error_code) @endcode+ * * @par Example * @code * void wait_handler(const asio::error_code& error)@@ -1217,18 +1241,31 @@ * asio::ip::tcp::acceptor::wait_read, * wait_handler); * @endcode+ *+ * @par Per-Operation Cancellation+ * On POSIX or Windows operating systems, this asynchronous operation supports+ * cancellation for the following asio::cancellation_type values:+ *+ * @li @c cancellation_type::terminal+ *+ * @li @c cancellation_type::partial+ *+ * @li @c cancellation_type::total */ template < ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code))- WaitHandler ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(executor_type)>- ASIO_INITFN_AUTO_RESULT_TYPE(WaitHandler,+ WaitToken ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(executor_type)>+ ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX(WaitToken, void (asio::error_code)) async_wait(wait_type w,- ASIO_MOVE_ARG(WaitHandler) handler+ ASIO_MOVE_ARG(WaitToken) token ASIO_DEFAULT_COMPLETION_TOKEN(executor_type))+ ASIO_INITFN_AUTO_RESULT_TYPE_SUFFIX((+ async_initiate<WaitToken, void (asio::error_code)>(+ declval<initiate_async_wait>(), token, w))) {- return async_initiate<WaitHandler, void (asio::error_code)>(- initiate_async_wait(this), handler, w);+ return async_initiate<WaitToken, void (asio::error_code)>(+ initiate_async_wait(this), token, w); } #if !defined(ASIO_NO_EXTENSIONS)@@ -1252,9 +1289,9 @@ */ template <typename Protocol1, typename Executor1> void accept(basic_socket<Protocol1, Executor1>& peer,- typename enable_if<+ typename constraint< is_convertible<Protocol, Protocol1>::value- >::type* = 0)+ >::type = 0) { asio::error_code ec; impl_.get_service().accept(impl_.get_implementation(),@@ -1288,9 +1325,9 @@ template <typename Protocol1, typename Executor1> ASIO_SYNC_OP_VOID accept( basic_socket<Protocol1, Executor1>& peer, asio::error_code& ec,- typename enable_if<+ typename constraint< is_convertible<Protocol, Protocol1>::value- >::type* = 0)+ >::type = 0) { impl_.get_service().accept(impl_.get_implementation(), peer, static_cast<endpoint_type*>(0), ec);@@ -1300,23 +1337,30 @@ /// Start an asynchronous accept. /** * This function is used to asynchronously accept a new connection into a- * socket. The function call always returns immediately.+ * socket, and additionally obtain the endpoint of the remote peer. It is an+ * initiating function for an @ref asynchronous_operation, and always returns+ * immediately. * * @param peer The socket into which the new connection will be accepted. * Ownership of the peer object is retained by the caller, which must- * guarantee that it is valid until the handler is called.+ * guarantee that it is valid until the completion handler is called. *- * @param handler The handler to be called when the accept operation- * completes. Copies will be made of the handler as required. The function- * signature of the handler must be:+ * @param token The @ref completion_token that will be used to produce a+ * completion handler, which will be called when the accept completes.+ * Potential completion tokens include @ref use_future, @ref use_awaitable,+ * @ref yield_context, or a function object with the correct completion+ * signature. The function signature of the completion handler must be: * @code void handler( * const asio::error_code& error // Result of operation. * ); @endcode * Regardless of whether the asynchronous operation completes immediately or- * not, the handler will not be invoked from within this function. On- * immediate completion, invocation of the handler will be performed in a+ * not, the completion handler will not be invoked from within this function.+ * On immediate completion, invocation of the handler will be performed in a * manner equivalent to using asio::post(). *+ * @par Completion Signature+ * @code void(asio::error_code) @endcode+ * * @par Example * @code * void accept_handler(const asio::error_code& error)@@ -1334,21 +1378,35 @@ * asio::ip::tcp::socket socket(my_context); * acceptor.async_accept(socket, accept_handler); * @endcode+ *+ * @par Per-Operation Cancellation+ * On POSIX or Windows operating systems, this asynchronous operation supports+ * cancellation for the following asio::cancellation_type values:+ *+ * @li @c cancellation_type::terminal+ *+ * @li @c cancellation_type::partial+ *+ * @li @c cancellation_type::total */ template <typename Protocol1, typename Executor1, ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code))- AcceptHandler ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(executor_type)>- ASIO_INITFN_AUTO_RESULT_TYPE(AcceptHandler,+ AcceptToken ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(executor_type)>+ ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX(AcceptToken, void (asio::error_code)) async_accept(basic_socket<Protocol1, Executor1>& peer,- ASIO_MOVE_ARG(AcceptHandler) handler+ ASIO_MOVE_ARG(AcceptToken) token ASIO_DEFAULT_COMPLETION_TOKEN(executor_type),- typename enable_if<+ typename constraint< is_convertible<Protocol, Protocol1>::value- >::type* = 0)+ >::type = 0)+ ASIO_INITFN_AUTO_RESULT_TYPE_SUFFIX((+ async_initiate<AcceptToken, void (asio::error_code)>(+ declval<initiate_async_accept>(), token,+ &peer, static_cast<endpoint_type*>(0)))) {- return async_initiate<AcceptHandler, void (asio::error_code)>(- initiate_async_accept(this), handler,+ return async_initiate<AcceptToken, void (asio::error_code)>(+ initiate_async_accept(this), token, &peer, static_cast<endpoint_type*>(0)); } @@ -1425,41 +1483,60 @@ /// Start an asynchronous accept. /** * This function is used to asynchronously accept a new connection into a- * socket, and additionally obtain the endpoint of the remote peer. The- * function call always returns immediately.+ * socket, and additionally obtain the endpoint of the remote peer. It is an+ * initiating function for an @ref asynchronous_operation, and always returns+ * immediately. * * @param peer The socket into which the new connection will be accepted. * Ownership of the peer object is retained by the caller, which must- * guarantee that it is valid until the handler is called.+ * guarantee that it is valid until the completion handler is called. * * @param peer_endpoint An endpoint object into which the endpoint of the * remote peer will be written. Ownership of the peer_endpoint object is * retained by the caller, which must guarantee that it is valid until the * handler is called. *- * @param handler The handler to be called when the accept operation- * completes. Copies will be made of the handler as required. The function- * signature of the handler must be:+ * @param token The @ref completion_token that will be used to produce a+ * completion handler, which will be called when the accept completes.+ * Potential completion tokens include @ref use_future, @ref use_awaitable,+ * @ref yield_context, or a function object with the correct completion+ * signature. The function signature of the completion handler must be: * @code void handler( * const asio::error_code& error // Result of operation. * ); @endcode * Regardless of whether the asynchronous operation completes immediately or- * not, the handler will not be invoked from within this function. On- * immediate completion, invocation of the handler will be performed in a+ * not, the completion handler will not be invoked from within this function.+ * On immediate completion, invocation of the handler will be performed in a * manner equivalent to using asio::post().+ *+ * @par Completion Signature+ * @code void(asio::error_code) @endcode+ *+ * @par Per-Operation Cancellation+ * On POSIX or Windows operating systems, this asynchronous operation supports+ * cancellation for the following asio::cancellation_type values:+ *+ * @li @c cancellation_type::terminal+ *+ * @li @c cancellation_type::partial+ *+ * @li @c cancellation_type::total */ template <typename Executor1, ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code))- AcceptHandler ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(executor_type)>- ASIO_INITFN_AUTO_RESULT_TYPE(AcceptHandler,+ AcceptToken ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(executor_type)>+ ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX(AcceptToken, void (asio::error_code)) async_accept(basic_socket<protocol_type, Executor1>& peer, endpoint_type& peer_endpoint,- ASIO_MOVE_ARG(AcceptHandler) handler+ ASIO_MOVE_ARG(AcceptToken) token ASIO_DEFAULT_COMPLETION_TOKEN(executor_type))+ ASIO_INITFN_AUTO_RESULT_TYPE_SUFFIX((+ async_initiate<AcceptToken, void (asio::error_code)>(+ declval<initiate_async_accept>(), token, &peer, &peer_endpoint))) {- return async_initiate<AcceptHandler, void (asio::error_code)>(- initiate_async_accept(this), handler, &peer, &peer_endpoint);+ return async_initiate<AcceptToken, void (asio::error_code)>(+ initiate_async_accept(this), token, &peer, &peer_endpoint); } #endif // !defined(ASIO_NO_EXTENSIONS) @@ -1531,27 +1608,36 @@ /// Start an asynchronous accept. /**- * This function is used to asynchronously accept a new connection. The- * function call always returns immediately.+ * This function is used to asynchronously accept a new connection. It is an+ * initiating function for an @ref asynchronous_operation, and always returns+ * immediately. * * This overload requires that the Protocol template parameter satisfy the * AcceptableProtocol type requirements. *- * @param handler The handler to be called when the accept operation- * completes. Copies will be made of the handler as required. The function- * signature of the handler must be:+ * @param token The @ref completion_token that will be used to produce a+ * completion handler, which will be called when the accept completes.+ * Potential completion tokens include @ref use_future, @ref use_awaitable,+ * @ref yield_context, or a function object with the correct completion+ * signature. The function signature of the completion handler must be: * @code void handler( * // Result of operation. * const asio::error_code& error,+ * * // On success, the newly accepted socket. * typename Protocol::socket::template * rebind_executor<executor_type>::other peer * ); @endcode * Regardless of whether the asynchronous operation completes immediately or- * not, the handler will not be invoked from within this function. On- * immediate completion, invocation of the handler will be performed in a+ * not, the completion handler will not be invoked from within this function.+ * On immediate completion, invocation of the handler will be performed in a * manner equivalent to using asio::post(). *+ * @par Completion Signature+ * @code void(asio::error_code,+ * typename Protocol::socket::template+ * rebind_executor<executor_type>::other)) @endcode+ * * @par Example * @code * void accept_handler(const asio::error_code& error,@@ -1569,24 +1655,42 @@ * ... * acceptor.async_accept(accept_handler); * @endcode+ *+ * @par Per-Operation Cancellation+ * On POSIX or Windows operating systems, this asynchronous operation supports+ * cancellation for the following asio::cancellation_type values:+ *+ * @li @c cancellation_type::terminal+ *+ * @li @c cancellation_type::partial+ *+ * @li @c cancellation_type::total */ template < ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code, typename Protocol::socket::template rebind_executor<- executor_type>::other)) MoveAcceptHandler+ executor_type>::other)) MoveAcceptToken ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(executor_type)>- ASIO_INITFN_AUTO_RESULT_TYPE(MoveAcceptHandler,+ ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX(MoveAcceptToken, void (asio::error_code, typename Protocol::socket::template rebind_executor<executor_type>::other)) async_accept(- ASIO_MOVE_ARG(MoveAcceptHandler) handler+ ASIO_MOVE_ARG(MoveAcceptToken) token ASIO_DEFAULT_COMPLETION_TOKEN(executor_type))+ ASIO_INITFN_AUTO_RESULT_TYPE_SUFFIX((+ async_initiate<MoveAcceptToken,+ void (asio::error_code, typename Protocol::socket::template+ rebind_executor<executor_type>::other)>(+ declval<initiate_async_move_accept>(), token,+ declval<executor_type>(), static_cast<endpoint_type*>(0),+ static_cast<typename Protocol::socket::template+ rebind_executor<executor_type>::other*>(0)))) {- return async_initiate<MoveAcceptHandler,+ return async_initiate<MoveAcceptToken, void (asio::error_code, typename Protocol::socket::template rebind_executor<executor_type>::other)>(- initiate_async_move_accept(this), handler,+ initiate_async_move_accept(this), token, impl_.get_executor(), static_cast<endpoint_type*>(0), static_cast<typename Protocol::socket::template rebind_executor<executor_type>::other*>(0));@@ -1618,10 +1722,10 @@ template <typename Executor1> typename Protocol::socket::template rebind_executor<Executor1>::other accept(const Executor1& ex,- typename enable_if<+ typename constraint< is_executor<Executor1>::value || execution::is_executor<Executor1>::value- >::type* = 0)+ >::type = 0) { asio::error_code ec; typename Protocol::socket::template@@ -1658,9 +1762,9 @@ typename Protocol::socket::template rebind_executor< typename ExecutionContext::executor_type>::other accept(ExecutionContext& context,- typename enable_if<+ typename constraint< is_convertible<ExecutionContext&, execution_context&>::value- >::type* = 0)+ >::type = 0) { asio::error_code ec; typename Protocol::socket::template rebind_executor<@@ -1701,10 +1805,10 @@ template <typename Executor1> typename Protocol::socket::template rebind_executor<Executor1>::other accept(const Executor1& ex, asio::error_code& ec,- typename enable_if<+ typename constraint< is_executor<Executor1>::value || execution::is_executor<Executor1>::value- >::type* = 0)+ >::type = 0) { typename Protocol::socket::template rebind_executor<Executor1>::other peer(ex);@@ -1744,9 +1848,9 @@ typename Protocol::socket::template rebind_executor< typename ExecutionContext::executor_type>::other accept(ExecutionContext& context, asio::error_code& ec,- typename enable_if<+ typename constraint< is_convertible<ExecutionContext&, execution_context&>::value- >::type* = 0)+ >::type = 0) { typename Protocol::socket::template rebind_executor< typename ExecutionContext::executor_type>::other peer(context);@@ -1756,8 +1860,9 @@ /// Start an asynchronous accept. /**- * This function is used to asynchronously accept a new connection. The- * function call always returns immediately.+ * This function is used to asynchronously accept a new connection. It is an+ * initiating function for an @ref asynchronous_operation, and always returns+ * immediately. * * This overload requires that the Protocol template parameter satisfy the * AcceptableProtocol type requirements.@@ -1765,19 +1870,29 @@ * @param ex The I/O executor object to be used for the newly accepted * socket. *- * @param handler The handler to be called when the accept operation- * completes. Copies will be made of the handler as required. The function- * signature of the handler must be:+ * @param token The @ref completion_token that will be used to produce a+ * completion handler, which will be called when the accept completes.+ * Potential completion tokens include @ref use_future, @ref use_awaitable,+ * @ref yield_context, or a function object with the correct completion+ * signature. The function signature of the completion handler must be: * @code void handler(- * const asio::error_code& error, // Result of operation.+ * // Result of operation.+ * const asio::error_code& error,+ *+ * // On success, the newly accepted socket. * typename Protocol::socket::template rebind_executor<- * Executor1>::other peer // On success, the newly accepted socket.+ * Executor1>::other peer * ); @endcode * Regardless of whether the asynchronous operation completes immediately or- * not, the handler will not be invoked from within this function. On- * immediate completion, invocation of the handler will be performed in a+ * not, the completion handler will not be invoked from within this function.+ * On immediate completion, invocation of the handler will be performed in a * manner equivalent to using asio::post(). *+ * @par Completion Signature+ * @code void(asio::error_code,+ * typename Protocol::socket::template rebind_executor<+ * Executor1>::other)) @endcode+ * * @par Example * @code * void accept_handler(const asio::error_code& error,@@ -1795,38 +1910,60 @@ * ... * acceptor.async_accept(my_context2, accept_handler); * @endcode+ *+ * @par Per-Operation Cancellation+ * On POSIX or Windows operating systems, this asynchronous operation supports+ * cancellation for the following asio::cancellation_type values:+ *+ * @li @c cancellation_type::terminal+ *+ * @li @c cancellation_type::partial+ *+ * @li @c cancellation_type::total */ template <typename Executor1, ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code, typename Protocol::socket::template rebind_executor<- Executor1>::other)) MoveAcceptHandler- ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(executor_type)>- ASIO_INITFN_AUTO_RESULT_TYPE(MoveAcceptHandler,+ typename constraint<is_executor<Executor1>::value+ || execution::is_executor<Executor1>::value,+ Executor1>::type>::other)) MoveAcceptToken+ ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(executor_type)>+ ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX(MoveAcceptToken, void (asio::error_code, typename Protocol::socket::template rebind_executor< Executor1>::other)) async_accept(const Executor1& ex,- ASIO_MOVE_ARG(MoveAcceptHandler) handler+ ASIO_MOVE_ARG(MoveAcceptToken) token ASIO_DEFAULT_COMPLETION_TOKEN(executor_type),- typename enable_if<+ typename constraint< is_executor<Executor1>::value || execution::is_executor<Executor1>::value- >::type* = 0)+ >::type = 0)+ ASIO_INITFN_AUTO_RESULT_TYPE_SUFFIX((+ async_initiate<MoveAcceptToken,+ void (asio::error_code,+ typename Protocol::socket::template rebind_executor<+ Executor1>::other)>(+ declval<initiate_async_move_accept>(), token,+ ex, static_cast<endpoint_type*>(0),+ static_cast<typename Protocol::socket::template+ rebind_executor<Executor1>::other*>(0)))) {- typedef typename Protocol::socket::template rebind_executor<- Executor1>::other other_socket_type;-- return async_initiate<MoveAcceptHandler,- void (asio::error_code, other_socket_type)>(- initiate_async_move_accept(this), handler,- ex, static_cast<endpoint_type*>(0),- static_cast<other_socket_type*>(0));+ return async_initiate<MoveAcceptToken,+ void (asio::error_code,+ typename Protocol::socket::template rebind_executor<+ Executor1>::other)>(+ initiate_async_move_accept(this), token,+ ex, static_cast<endpoint_type*>(0),+ static_cast<typename Protocol::socket::template+ rebind_executor<Executor1>::other*>(0)); } /// Start an asynchronous accept. /**- * This function is used to asynchronously accept a new connection. The- * function call always returns immediately.+ * This function is used to asynchronously accept a new connection. It is an+ * initiating function for an @ref asynchronous_operation, and always returns+ * immediately. * * This overload requires that the Protocol template parameter satisfy the * AcceptableProtocol type requirements.@@ -1834,20 +1971,29 @@ * @param context The I/O execution context object to be used for the newly * accepted socket. *- * @param handler The handler to be called when the accept operation- * completes. Copies will be made of the handler as required. The function- * signature of the handler must be:+ * @param token The @ref completion_token that will be used to produce a+ * completion handler, which will be called when the accept completes.+ * Potential completion tokens include @ref use_future, @ref use_awaitable,+ * @ref yield_context, or a function object with the correct completion+ * signature. The function signature of the completion handler must be: * @code void handler(- * const asio::error_code& error, // Result of operation.+ * // Result of operation.+ * const asio::error_code& error,+ *+ * // On success, the newly accepted socket. * typename Protocol::socket::template rebind_executor< * typename ExecutionContext::executor_type>::other peer- * // On success, the newly accepted socket. * ); @endcode * Regardless of whether the asynchronous operation completes immediately or- * not, the handler will not be invoked from within this function. On- * immediate completion, invocation of the handler will be performed in a+ * not, the completion handler will not be invoked from within this function.+ * On immediate completion, invocation of the handler will be performed in a * manner equivalent to using asio::post(). *+ * @par Completion Signature+ * @code void(asio::error_code,+ * typename Protocol::socket::template rebind_executor<+ * typename ExecutionContext::executor_type>::other)) @endcode+ * * @par Example * @code * void accept_handler(const asio::error_code& error,@@ -1865,31 +2011,50 @@ * ... * acceptor.async_accept(my_context2, accept_handler); * @endcode+ *+ * @par Per-Operation Cancellation+ * On POSIX or Windows operating systems, this asynchronous operation supports+ * cancellation for the following asio::cancellation_type values:+ *+ * @li @c cancellation_type::terminal+ *+ * @li @c cancellation_type::partial+ *+ * @li @c cancellation_type::total */ template <typename ExecutionContext, ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code, typename Protocol::socket::template rebind_executor<- typename ExecutionContext::executor_type>::other)) MoveAcceptHandler+ typename ExecutionContext::executor_type>::other)) MoveAcceptToken ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(executor_type)>- ASIO_INITFN_AUTO_RESULT_TYPE(MoveAcceptHandler,+ ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX(MoveAcceptToken, void (asio::error_code, typename Protocol::socket::template rebind_executor< typename ExecutionContext::executor_type>::other)) async_accept(ExecutionContext& context,- ASIO_MOVE_ARG(MoveAcceptHandler) handler+ ASIO_MOVE_ARG(MoveAcceptToken) token ASIO_DEFAULT_COMPLETION_TOKEN(executor_type),- typename enable_if<+ typename constraint< is_convertible<ExecutionContext&, execution_context&>::value- >::type* = 0)+ >::type = 0)+ ASIO_INITFN_AUTO_RESULT_TYPE_SUFFIX((+ async_initiate<MoveAcceptToken,+ void (asio::error_code,+ typename Protocol::socket::template rebind_executor<+ typename ExecutionContext::executor_type>::other)>(+ declval<initiate_async_move_accept>(), token,+ context.get_executor(), static_cast<endpoint_type*>(0),+ static_cast<typename Protocol::socket::template rebind_executor<+ typename ExecutionContext::executor_type>::other*>(0)))) {- typedef typename Protocol::socket::template rebind_executor<- typename ExecutionContext::executor_type>::other other_socket_type;-- return async_initiate<MoveAcceptHandler,- void (asio::error_code, other_socket_type)>(- initiate_async_move_accept(this), handler,- context.get_executor(), static_cast<endpoint_type*>(0),- static_cast<other_socket_type*>(0));+ return async_initiate<MoveAcceptToken,+ void (asio::error_code,+ typename Protocol::socket::template rebind_executor<+ typename ExecutionContext::executor_type>::other)>(+ initiate_async_move_accept(this), token,+ context.get_executor(), static_cast<endpoint_type*>(0),+ static_cast<typename Protocol::socket::template rebind_executor<+ typename ExecutionContext::executor_type>::other*>(0)); } /// Accept a new connection.@@ -1969,8 +2134,9 @@ /// Start an asynchronous accept. /**- * This function is used to asynchronously accept a new connection. The- * function call always returns immediately.+ * This function is used to asynchronously accept a new connection. It is an+ * initiating function for an @ref asynchronous_operation, and always returns+ * immediately. * * This overload requires that the Protocol template parameter satisfy the * AcceptableProtocol type requirements.@@ -1978,23 +2144,31 @@ * @param peer_endpoint An endpoint object into which the endpoint of the * remote peer will be written. Ownership of the peer_endpoint object is * retained by the caller, which must guarantee that it is valid until the- * handler is called.+ * completion handler is called. *- * @param handler The handler to be called when the accept operation- * completes. Copies will be made of the handler as required. The function- * signature of the handler must be:+ * @param token The @ref completion_token that will be used to produce a+ * completion handler, which will be called when the accept completes.+ * Potential completion tokens include @ref use_future, @ref use_awaitable,+ * @ref yield_context, or a function object with the correct completion+ * signature. The function signature of the completion handler must be: * @code void handler( * // Result of operation. * const asio::error_code& error,+ * * // On success, the newly accepted socket. * typename Protocol::socket::template * rebind_executor<executor_type>::other peer * ); @endcode * Regardless of whether the asynchronous operation completes immediately or- * not, the handler will not be invoked from within this function. On- * immediate completion, invocation of the handler will be performed in a+ * not, the completion handler will not be invoked from within this function.+ * On immediate completion, invocation of the handler will be performed in a * manner equivalent to using asio::post(). *+ * @par Completion Signature+ * @code void(asio::error_code,+ * typename Protocol::socket::template+ * rebind_executor<executor_type>::other)) @endcode+ * * @par Example * @code * void accept_handler(const asio::error_code& error,@@ -2013,24 +2187,42 @@ * asio::ip::tcp::endpoint endpoint; * acceptor.async_accept(endpoint, accept_handler); * @endcode+ *+ * @par Per-Operation Cancellation+ * On POSIX or Windows operating systems, this asynchronous operation supports+ * cancellation for the following asio::cancellation_type values:+ *+ * @li @c cancellation_type::terminal+ *+ * @li @c cancellation_type::partial+ *+ * @li @c cancellation_type::total */ template < ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code, typename Protocol::socket::template rebind_executor<- executor_type>::other)) MoveAcceptHandler+ executor_type>::other)) MoveAcceptToken ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(executor_type)>- ASIO_INITFN_AUTO_RESULT_TYPE(MoveAcceptHandler,+ ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX(MoveAcceptToken, void (asio::error_code, typename Protocol::socket::template rebind_executor<executor_type>::other)) async_accept(endpoint_type& peer_endpoint,- ASIO_MOVE_ARG(MoveAcceptHandler) handler+ ASIO_MOVE_ARG(MoveAcceptToken) token ASIO_DEFAULT_COMPLETION_TOKEN(executor_type))+ ASIO_INITFN_AUTO_RESULT_TYPE_SUFFIX((+ async_initiate<MoveAcceptToken,+ void (asio::error_code, typename Protocol::socket::template+ rebind_executor<executor_type>::other)>(+ declval<initiate_async_move_accept>(), token,+ declval<executor_type>(), &peer_endpoint,+ static_cast<typename Protocol::socket::template+ rebind_executor<executor_type>::other*>(0)))) {- return async_initiate<MoveAcceptHandler,+ return async_initiate<MoveAcceptToken, void (asio::error_code, typename Protocol::socket::template rebind_executor<executor_type>::other)>(- initiate_async_move_accept(this), handler,+ initiate_async_move_accept(this), token, impl_.get_executor(), &peer_endpoint, static_cast<typename Protocol::socket::template rebind_executor<executor_type>::other*>(0));@@ -2067,10 +2259,10 @@ template <typename Executor1> typename Protocol::socket::template rebind_executor<Executor1>::other accept(const Executor1& ex, endpoint_type& peer_endpoint,- typename enable_if<+ typename constraint< is_executor<Executor1>::value || execution::is_executor<Executor1>::value- >::type* = 0)+ >::type = 0) { asio::error_code ec; typename Protocol::socket::template@@ -2113,9 +2305,9 @@ typename Protocol::socket::template rebind_executor< typename ExecutionContext::executor_type>::other accept(ExecutionContext& context, endpoint_type& peer_endpoint,- typename enable_if<+ typename constraint< is_convertible<ExecutionContext&, execution_context&>::value- >::type* = 0)+ >::type = 0) { asio::error_code ec; typename Protocol::socket::template rebind_executor<@@ -2163,10 +2355,10 @@ typename Protocol::socket::template rebind_executor<Executor1>::other accept(const executor_type& ex, endpoint_type& peer_endpoint, asio::error_code& ec,- typename enable_if<+ typename constraint< is_executor<Executor1>::value || execution::is_executor<Executor1>::value- >::type* = 0)+ >::type = 0) { typename Protocol::socket::template rebind_executor<Executor1>::other peer(ex);@@ -2213,9 +2405,9 @@ typename ExecutionContext::executor_type>::other accept(ExecutionContext& context, endpoint_type& peer_endpoint, asio::error_code& ec,- typename enable_if<+ typename constraint< is_convertible<ExecutionContext&, execution_context&>::value- >::type* = 0)+ >::type = 0) { typename Protocol::socket::template rebind_executor< typename ExecutionContext::executor_type>::other peer(context);@@ -2226,8 +2418,9 @@ /// Start an asynchronous accept. /**- * This function is used to asynchronously accept a new connection. The- * function call always returns immediately.+ * This function is used to asynchronously accept a new connection. It is an+ * initiating function for an @ref asynchronous_operation, and always returns+ * immediately. * * This overload requires that the Protocol template parameter satisfy the * AcceptableProtocol type requirements.@@ -2238,21 +2431,31 @@ * @param peer_endpoint An endpoint object into which the endpoint of the * remote peer will be written. Ownership of the peer_endpoint object is * retained by the caller, which must guarantee that it is valid until the- * handler is called.+ * completion handler is called. *- * @param handler The handler to be called when the accept operation- * completes. Copies will be made of the handler as required. The function- * signature of the handler must be:+ * @param token The @ref completion_token that will be used to produce a+ * completion handler, which will be called when the accept completes.+ * Potential completion tokens include @ref use_future, @ref use_awaitable,+ * @ref yield_context, or a function object with the correct completion+ * signature. The function signature of the completion handler must be: * @code void handler(- * const asio::error_code& error, // Result of operation.+ * // Result of operation.+ * const asio::error_code& error,+ *+ * // On success, the newly accepted socket. * typename Protocol::socket::template rebind_executor<- * Executor1>::other peer // On success, the newly accepted socket.+ * Executor1>::other peer * ); @endcode * Regardless of whether the asynchronous operation completes immediately or- * not, the handler will not be invoked from within this function. On- * immediate completion, invocation of the handler will be performed in a+ * not, the completion handler will not be invoked from within this function.+ * On immediate completion, invocation of the handler will be performed in a * manner equivalent to using asio::post(). *+ * @par Completion Signature+ * @code void(asio::error_code,+ * typename Protocol::socket::template rebind_executor<+ * Executor1>::other)) @endcode+ * * @par Example * @code * void accept_handler(const asio::error_code& error,@@ -2271,38 +2474,58 @@ * asio::ip::tcp::endpoint endpoint; * acceptor.async_accept(my_context2, endpoint, accept_handler); * @endcode+ *+ * @par Per-Operation Cancellation+ * On POSIX or Windows operating systems, this asynchronous operation supports+ * cancellation for the following asio::cancellation_type values:+ *+ * @li @c cancellation_type::terminal+ *+ * @li @c cancellation_type::partial+ *+ * @li @c cancellation_type::total */ template <typename Executor1, ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code, typename Protocol::socket::template rebind_executor<- Executor1>::other)) MoveAcceptHandler- ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(executor_type)>- ASIO_INITFN_AUTO_RESULT_TYPE(MoveAcceptHandler,+ typename constraint<is_executor<Executor1>::value+ || execution::is_executor<Executor1>::value,+ Executor1>::type>::other)) MoveAcceptToken+ ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(executor_type)>+ ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX(MoveAcceptToken, void (asio::error_code, typename Protocol::socket::template rebind_executor< Executor1>::other)) async_accept(const Executor1& ex, endpoint_type& peer_endpoint,- ASIO_MOVE_ARG(MoveAcceptHandler) handler+ ASIO_MOVE_ARG(MoveAcceptToken) token ASIO_DEFAULT_COMPLETION_TOKEN(executor_type),- typename enable_if<+ typename constraint< is_executor<Executor1>::value || execution::is_executor<Executor1>::value- >::type* = 0)+ >::type = 0)+ ASIO_INITFN_AUTO_RESULT_TYPE_SUFFIX((+ async_initiate<MoveAcceptToken,+ void (asio::error_code,+ typename Protocol::socket::template rebind_executor<+ Executor1>::other)>(+ declval<initiate_async_move_accept>(), token, ex, &peer_endpoint,+ static_cast<typename Protocol::socket::template+ rebind_executor<Executor1>::other*>(0)))) {- typedef typename Protocol::socket::template rebind_executor<- Executor1>::other other_socket_type;-- return async_initiate<MoveAcceptHandler,- void (asio::error_code, other_socket_type)>(- initiate_async_move_accept(this), handler,- ex, &peer_endpoint,- static_cast<other_socket_type*>(0));+ return async_initiate<MoveAcceptToken,+ void (asio::error_code,+ typename Protocol::socket::template rebind_executor<+ Executor1>::other)>(+ initiate_async_move_accept(this), token, ex, &peer_endpoint,+ static_cast<typename Protocol::socket::template+ rebind_executor<Executor1>::other*>(0)); } /// Start an asynchronous accept. /**- * This function is used to asynchronously accept a new connection. The- * function call always returns immediately.+ * This function is used to asynchronously accept a new connection. It is an+ * initiating function for an @ref asynchronous_operation, and always returns+ * immediately. * * This overload requires that the Protocol template parameter satisfy the * AcceptableProtocol type requirements.@@ -2313,22 +2536,31 @@ * @param peer_endpoint An endpoint object into which the endpoint of the * remote peer will be written. Ownership of the peer_endpoint object is * retained by the caller, which must guarantee that it is valid until the- * handler is called.+ * completion handler is called. *- * @param handler The handler to be called when the accept operation- * completes. Copies will be made of the handler as required. The function- * signature of the handler must be:+ * @param token The @ref completion_token that will be used to produce a+ * completion handler, which will be called when the accept completes.+ * Potential completion tokens include @ref use_future, @ref use_awaitable,+ * @ref yield_context, or a function object with the correct completion+ * signature. The function signature of the completion handler must be: * @code void handler(- * const asio::error_code& error, // Result of operation.+ * // Result of operation.+ * const asio::error_code& error,+ *+ * // On success, the newly accepted socket. * typename Protocol::socket::template rebind_executor< * typename ExecutionContext::executor_type>::other peer- * // On success, the newly accepted socket. * ); @endcode * Regardless of whether the asynchronous operation completes immediately or- * not, the handler will not be invoked from within this function. On- * immediate completion, invocation of the handler will be performed in a+ * not, the completion handler will not be invoked from within this function.+ * On immediate completion, invocation of the handler will be performed in a * manner equivalent to using asio::post(). *+ * @par Completion Signature+ * @code void(asio::error_code,+ * typename Protocol::socket::template rebind_executor<+ * typename ExecutionContext::executor_type>::other)) @endcode+ * * @par Example * @code * void accept_handler(const asio::error_code& error,@@ -2347,32 +2579,51 @@ * asio::ip::tcp::endpoint endpoint; * acceptor.async_accept(my_context2, endpoint, accept_handler); * @endcode+ *+ * @par Per-Operation Cancellation+ * On POSIX or Windows operating systems, this asynchronous operation supports+ * cancellation for the following asio::cancellation_type values:+ *+ * @li @c cancellation_type::terminal+ *+ * @li @c cancellation_type::partial+ *+ * @li @c cancellation_type::total */ template <typename ExecutionContext, ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code, typename Protocol::socket::template rebind_executor<- typename ExecutionContext::executor_type>::other)) MoveAcceptHandler+ typename ExecutionContext::executor_type>::other)) MoveAcceptToken ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(executor_type)>- ASIO_INITFN_AUTO_RESULT_TYPE(MoveAcceptHandler,+ ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX(MoveAcceptToken, void (asio::error_code, typename Protocol::socket::template rebind_executor< typename ExecutionContext::executor_type>::other)) async_accept(ExecutionContext& context, endpoint_type& peer_endpoint,- ASIO_MOVE_ARG(MoveAcceptHandler) handler+ ASIO_MOVE_ARG(MoveAcceptToken) token ASIO_DEFAULT_COMPLETION_TOKEN(executor_type),- typename enable_if<+ typename constraint< is_convertible<ExecutionContext&, execution_context&>::value- >::type* = 0)+ >::type = 0)+ ASIO_INITFN_AUTO_RESULT_TYPE_SUFFIX((+ async_initiate<MoveAcceptToken,+ void (asio::error_code,+ typename Protocol::socket::template rebind_executor<+ typename ExecutionContext::executor_type>::other)>(+ declval<initiate_async_move_accept>(), token,+ context.get_executor(), &peer_endpoint,+ static_cast<typename Protocol::socket::template rebind_executor<+ typename ExecutionContext::executor_type>::other*>(0)))) {- typedef typename Protocol::socket::template rebind_executor<- typename ExecutionContext::executor_type>::other other_socket_type;-- return async_initiate<MoveAcceptHandler,- void (asio::error_code, other_socket_type)>(- initiate_async_move_accept(this), handler,- context.get_executor(), &peer_endpoint,- static_cast<other_socket_type*>(0));+ return async_initiate<MoveAcceptToken,+ void (asio::error_code,+ typename Protocol::socket::template rebind_executor<+ typename ExecutionContext::executor_type>::other)>(+ initiate_async_move_accept(this), token,+ context.get_executor(), &peer_endpoint,+ static_cast<typename Protocol::socket::template rebind_executor<+ typename ExecutionContext::executor_type>::other*>(0)); } #endif // defined(ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION) @@ -2392,7 +2643,7 @@ { } - executor_type get_executor() const ASIO_NOEXCEPT+ const executor_type& get_executor() const ASIO_NOEXCEPT { return self_->get_executor(); }@@ -2424,7 +2675,7 @@ { } - executor_type get_executor() const ASIO_NOEXCEPT+ const executor_type& get_executor() const ASIO_NOEXCEPT { return self_->get_executor(); }@@ -2458,7 +2709,7 @@ { } - executor_type get_executor() const ASIO_NOEXCEPT+ const executor_type& get_executor() const ASIO_NOEXCEPT { return self_->get_executor(); }@@ -2488,6 +2739,9 @@ #elif defined(ASIO_HAS_IOCP) detail::io_object_impl< detail::win_iocp_socket_service<Protocol>, Executor> impl_;+#elif defined(ASIO_HAS_IO_URING_AS_DEFAULT)+ detail::io_object_impl<+ detail::io_uring_socket_service<Protocol>, Executor> impl_; #else detail::io_object_impl< detail::reactive_socket_service<Protocol>, Executor> impl_;
link/modules/asio-standalone/asio/include/asio/basic_socket_iostream.hpp view
@@ -2,7 +2,7 @@ // basic_socket_iostream.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/basic_socket_streambuf.hpp view
@@ -2,7 +2,7 @@ // basic_socket_streambuf.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+ link/modules/asio-standalone/asio/include/asio/basic_stream_file.hpp view
@@ -0,0 +1,754 @@+//+// basic_stream_file.hpp+// ~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com)+//+// Distributed under the Boost Software License, Version 1.0. (See accompanying+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)+//++#ifndef ASIO_BASIC_STREAM_FILE_HPP+#define ASIO_BASIC_STREAM_FILE_HPP++#if defined(_MSC_VER) && (_MSC_VER >= 1200)+# pragma once+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)++#include "asio/detail/config.hpp"++#if defined(ASIO_HAS_FILE) \+ || defined(GENERATING_DOCUMENTATION)++#include <cstddef>+#include "asio/async_result.hpp"+#include "asio/basic_file.hpp"+#include "asio/detail/handler_type_requirements.hpp"+#include "asio/detail/non_const_lvalue.hpp"+#include "asio/detail/throw_error.hpp"+#include "asio/error.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {++#if !defined(ASIO_BASIC_STREAM_FILE_FWD_DECL)+#define ASIO_BASIC_STREAM_FILE_FWD_DECL++// Forward declaration with defaulted arguments.+template <typename Executor = any_io_executor>+class basic_stream_file;++#endif // !defined(ASIO_BASIC_STREAM_FILE_FWD_DECL)++/// Provides stream-oriented file functionality.+/**+ * The basic_stream_file class template provides asynchronous and blocking+ * stream-oriented file functionality.+ *+ * @par Thread Safety+ * @e Distinct @e objects: Safe.@n+ * @e Shared @e objects: Unsafe.+ *+ * @par Concepts:+ * AsyncReadStream, AsyncWriteStream, Stream, SyncReadStream, SyncWriteStream.+ */+template <typename Executor>+class basic_stream_file+ : public basic_file<Executor>+{+private:+ class initiate_async_write_some;+ class initiate_async_read_some;++public:+ /// The type of the executor associated with the object.+ typedef Executor executor_type;++ /// Rebinds the file type to another executor.+ template <typename Executor1>+ struct rebind_executor+ {+ /// The file type when rebound to the specified executor.+ typedef basic_stream_file<Executor1> other;+ };++ /// The native representation of a file.+#if defined(GENERATING_DOCUMENTATION)+ typedef implementation_defined native_handle_type;+#else+ typedef typename basic_file<Executor>::native_handle_type native_handle_type;+#endif++ /// Construct a basic_stream_file without opening it.+ /**+ * This constructor initialises a file without opening it. The file needs to+ * be opened before data can be read from or or written to it.+ *+ * @param ex The I/O executor that the file will use, by default, to+ * dispatch handlers for any asynchronous operations performed on the file.+ */+ explicit basic_stream_file(const executor_type& ex)+ : basic_file<Executor>(ex)+ {+ this->impl_.get_service().set_is_stream(+ this->impl_.get_implementation(), true);+ }++ /// Construct a basic_stream_file without opening it.+ /**+ * This constructor initialises a file without opening it. The file needs to+ * be opened before data can be read from or or written to it.+ *+ * @param context An execution context which provides the I/O executor that+ * the file will use, by default, to dispatch handlers for any asynchronous+ * operations performed on the file.+ */+ template <typename ExecutionContext>+ explicit basic_stream_file(ExecutionContext& context,+ typename constraint<+ is_convertible<ExecutionContext&, execution_context&>::value,+ defaulted_constraint+ >::type = defaulted_constraint())+ : basic_file<Executor>(context)+ {+ this->impl_.get_service().set_is_stream(+ this->impl_.get_implementation(), true);+ }++ /// Construct and open a basic_stream_file.+ /**+ * This constructor initialises and opens a file.+ *+ * @param ex The I/O executor that the file will use, by default, to+ * dispatch handlers for any asynchronous operations performed on the file.+ *+ * @param path The path name identifying the file to be opened.+ *+ * @param open_flags A set of flags that determine how the file should be+ * opened.+ *+ * @throws asio::system_error Thrown on failure.+ */+ basic_stream_file(const executor_type& ex,+ const char* path, file_base::flags open_flags)+ : basic_file<Executor>(ex)+ {+ asio::error_code ec;+ this->impl_.get_service().set_is_stream(+ this->impl_.get_implementation(), true);+ this->impl_.get_service().open(+ this->impl_.get_implementation(),+ path, open_flags, ec);+ asio::detail::throw_error(ec, "open");+ }++ /// Construct and open a basic_stream_file.+ /**+ * This constructor initialises and opens a file.+ *+ * @param context An execution context which provides the I/O executor that+ * the file will use, by default, to dispatch handlers for any asynchronous+ * operations performed on the file.+ *+ * @param path The path name identifying the file to be opened.+ *+ * @param open_flags A set of flags that determine how the file should be+ * opened.+ *+ * @throws asio::system_error Thrown on failure.+ */+ template <typename ExecutionContext>+ basic_stream_file(ExecutionContext& context,+ const char* path, file_base::flags open_flags,+ typename constraint<+ is_convertible<ExecutionContext&, execution_context&>::value,+ defaulted_constraint+ >::type = defaulted_constraint())+ : basic_file<Executor>(context)+ {+ asio::error_code ec;+ this->impl_.get_service().set_is_stream(+ this->impl_.get_implementation(), true);+ this->impl_.get_service().open(+ this->impl_.get_implementation(),+ path, open_flags, ec);+ asio::detail::throw_error(ec, "open");+ }++ /// Construct and open a basic_stream_file.+ /**+ * This constructor initialises and opens a file.+ *+ * @param ex The I/O executor that the file will use, by default, to+ * dispatch handlers for any asynchronous operations performed on the file.+ *+ * @param path The path name identifying the file to be opened.+ *+ * @param open_flags A set of flags that determine how the file should be+ * opened.+ *+ * @throws asio::system_error Thrown on failure.+ */+ basic_stream_file(const executor_type& ex,+ const std::string& path, file_base::flags open_flags)+ : basic_file<Executor>(ex)+ {+ asio::error_code ec;+ this->impl_.get_service().set_is_stream(+ this->impl_.get_implementation(), true);+ this->impl_.get_service().open(+ this->impl_.get_implementation(),+ path.c_str(), open_flags, ec);+ asio::detail::throw_error(ec, "open");+ }++ /// Construct and open a basic_stream_file.+ /**+ * This constructor initialises and opens a file.+ *+ * @param context An execution context which provides the I/O executor that+ * the file will use, by default, to dispatch handlers for any asynchronous+ * operations performed on the file.+ *+ * @param path The path name identifying the file to be opened.+ *+ * @param open_flags A set of flags that determine how the file should be+ * opened.+ *+ * @throws asio::system_error Thrown on failure.+ */+ template <typename ExecutionContext>+ basic_stream_file(ExecutionContext& context,+ const std::string& path, file_base::flags open_flags,+ typename constraint<+ is_convertible<ExecutionContext&, execution_context&>::value,+ defaulted_constraint+ >::type = defaulted_constraint())+ : basic_file<Executor>(context)+ {+ asio::error_code ec;+ this->impl_.get_service().set_is_stream(+ this->impl_.get_implementation(), true);+ this->impl_.get_service().open(+ this->impl_.get_implementation(),+ path.c_str(), open_flags, ec);+ asio::detail::throw_error(ec, "open");+ }++ /// Construct a basic_stream_file on an existing native file.+ /**+ * This constructor initialises a stream file object to hold an existing+ * native file.+ *+ * @param ex The I/O executor that the file will use, by default, to+ * dispatch handlers for any asynchronous operations performed on the file.+ *+ * @param native_file The new underlying file implementation.+ *+ * @throws asio::system_error Thrown on failure.+ */+ basic_stream_file(const executor_type& ex,+ const native_handle_type& native_file)+ : basic_file<Executor>(ex, native_file)+ {+ this->impl_.get_service().set_is_stream(+ this->impl_.get_implementation(), true);+ }++ /// Construct a basic_stream_file on an existing native file.+ /**+ * This constructor initialises a stream file object to hold an existing+ * native file.+ *+ * @param context An execution context which provides the I/O executor that+ * the file will use, by default, to dispatch handlers for any asynchronous+ * operations performed on the file.+ *+ * @param native_file The new underlying file implementation.+ *+ * @throws asio::system_error Thrown on failure.+ */+ template <typename ExecutionContext>+ basic_stream_file(ExecutionContext& context,+ const native_handle_type& native_file,+ typename constraint<+ is_convertible<ExecutionContext&, execution_context&>::value,+ defaulted_constraint+ >::type = defaulted_constraint())+ : basic_file<Executor>(context, native_file)+ {+ this->impl_.get_service().set_is_stream(+ this->impl_.get_implementation(), true);+ }++#if defined(ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)+ /// Move-construct a basic_stream_file from another.+ /**+ * This constructor moves a stream file from one object to another.+ *+ * @param other The other basic_stream_file object from which the move+ * will occur.+ *+ * @note Following the move, the moved-from object is in the same state as if+ * constructed using the @c basic_stream_file(const executor_type&)+ * constructor.+ */+ basic_stream_file(basic_stream_file&& other) ASIO_NOEXCEPT+ : basic_file<Executor>(std::move(other))+ {+ }++ /// Move-assign a basic_stream_file from another.+ /**+ * This assignment operator moves a stream file from one object to another.+ *+ * @param other The other basic_stream_file object from which the move+ * will occur.+ *+ * @note Following the move, the moved-from object is in the same state as if+ * constructed using the @c basic_stream_file(const executor_type&)+ * constructor.+ */+ basic_stream_file& operator=(basic_stream_file&& other)+ {+ basic_file<Executor>::operator=(std::move(other));+ return *this;+ }++ /// Move-construct a basic_stream_file from a file of another executor+ /// type.+ /**+ * This constructor moves a stream file from one object to another.+ *+ * @param other The other basic_stream_file object from which the move+ * will occur.+ *+ * @note Following the move, the moved-from object is in the same state as if+ * constructed using the @c basic_stream_file(const executor_type&)+ * constructor.+ */+ template <typename Executor1>+ basic_stream_file(basic_stream_file<Executor1>&& other,+ typename constraint<+ is_convertible<Executor1, Executor>::value,+ defaulted_constraint+ >::type = defaulted_constraint())+ : basic_file<Executor>(std::move(other))+ {+ }++ /// Move-assign a basic_stream_file from a file of another executor type.+ /**+ * This assignment operator moves a stream file from one object to another.+ *+ * @param other The other basic_stream_file object from which the move+ * will occur.+ *+ * @note Following the move, the moved-from object is in the same state as if+ * constructed using the @c basic_stream_file(const executor_type&)+ * constructor.+ */+ template <typename Executor1>+ typename constraint<+ is_convertible<Executor1, Executor>::value,+ basic_stream_file&+ >::type operator=(basic_stream_file<Executor1>&& other)+ {+ basic_file<Executor>::operator=(std::move(other));+ return *this;+ }+#endif // defined(ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)++ /// Destroys the file.+ /**+ * This function destroys the file, cancelling any outstanding asynchronous+ * operations associated with the file as if by calling @c cancel.+ */+ ~basic_stream_file()+ {+ }++ /// Seek to a position in the file.+ /**+ * This function updates the current position in the file.+ *+ * @param offset The requested position in the file, relative to @c whence.+ *+ * @param whence One of @c seek_set, @c seek_cur or @c seek_end.+ *+ * @returns The new position relative to the beginning of the file.+ *+ * @throws asio::system_error Thrown on failure.+ */+ uint64_t seek(int64_t offset, file_base::seek_basis whence)+ {+ asio::error_code ec;+ uint64_t n = this->impl_.get_service().seek(+ this->impl_.get_implementation(), offset, whence, ec);+ asio::detail::throw_error(ec, "seek");+ return n;+ }++ /// Seek to a position in the file.+ /**+ * This function updates the current position in the file.+ *+ * @param offset The requested position in the file, relative to @c whence.+ *+ * @param whence One of @c seek_set, @c seek_cur or @c seek_end.+ *+ * @param ec Set to indicate what error occurred, if any.+ *+ * @returns The new position relative to the beginning of the file.+ */+ uint64_t seek(int64_t offset, file_base::seek_basis whence,+ asio::error_code& ec)+ {+ return this->impl_.get_service().seek(+ this->impl_.get_implementation(), offset, whence, ec);+ }++ /// Write some data to the file.+ /**+ * This function is used to write data to the stream file. The function call+ * will block until one or more bytes of the data has been written+ * successfully, or until an error occurs.+ *+ * @param buffers One or more data buffers to be written to the file.+ *+ * @returns The number of bytes written.+ *+ * @throws asio::system_error Thrown on failure. An error code of+ * asio::error::eof indicates that the end of the file was reached.+ *+ * @note The write_some operation may not transmit all of the data to the+ * peer. Consider using the @ref write function if you need to ensure that+ * all data is written before the blocking operation completes.+ *+ * @par Example+ * To write a single data buffer use the @ref buffer function as follows:+ * @code+ * file.write_some(asio::buffer(data, size));+ * @endcode+ * See the @ref buffer documentation for information on writing multiple+ * buffers in one go, and how to use it with arrays, boost::array or+ * std::vector.+ */+ template <typename ConstBufferSequence>+ std::size_t write_some(const ConstBufferSequence& buffers)+ {+ asio::error_code ec;+ std::size_t s = this->impl_.get_service().write_some(+ this->impl_.get_implementation(), buffers, ec);+ asio::detail::throw_error(ec, "write_some");+ return s;+ }++ /// Write some data to the file.+ /**+ * This function is used to write data to the stream file. The function call+ * will block until one or more bytes of the data has been written+ * successfully, or until an error occurs.+ *+ * @param buffers One or more data buffers to be written to the file.+ *+ * @param ec Set to indicate what error occurred, if any.+ *+ * @returns The number of bytes written. Returns 0 if an error occurred.+ *+ * @note The write_some operation may not transmit all of the data to the+ * peer. Consider using the @ref write function if you need to ensure that+ * all data is written before the blocking operation completes.+ */+ template <typename ConstBufferSequence>+ std::size_t write_some(const ConstBufferSequence& buffers,+ asio::error_code& ec)+ {+ return this->impl_.get_service().write_some(+ this->impl_.get_implementation(), buffers, ec);+ }++ /// Start an asynchronous write.+ /**+ * This function is used to asynchronously write data to the stream file.+ * It is an initiating function for an @ref asynchronous_operation, and always+ * returns immediately.+ *+ * @param buffers One or more data buffers to be written to the file.+ * Although the buffers object may be copied as necessary, ownership of the+ * underlying memory blocks is retained by the caller, which must guarantee+ * that they remain valid until the completion handler is called.+ *+ * @param token The @ref completion_token that will be used to produce a+ * completion handler, which will be called when the write completes.+ * Potential completion tokens include @ref use_future, @ref use_awaitable,+ * @ref yield_context, or a function object with the correct completion+ * signature. The function signature of the completion handler must be:+ * @code void handler(+ * const asio::error_code& error, // Result of operation.+ * std::size_t bytes_transferred // Number of bytes written.+ * ); @endcode+ * Regardless of whether the asynchronous operation completes immediately or+ * not, the completion handler will not be invoked from within this function.+ * On immediate completion, invocation of the handler will be performed in a+ * manner equivalent to using asio::post().+ *+ * @par Completion Signature+ * @code void(asio::error_code, std::size_t) @endcode+ *+ * @note The write operation may not transmit all of the data to the peer.+ * Consider using the @ref async_write function if you need to ensure that all+ * data is written before the asynchronous operation completes.+ *+ * @par Example+ * To write a single data buffer use the @ref buffer function as follows:+ * @code+ * file.async_write_some(asio::buffer(data, size), handler);+ * @endcode+ * See the @ref buffer documentation for information on writing multiple+ * buffers in one go, and how to use it with arrays, boost::array or+ * std::vector.+ *+ * @par Per-Operation Cancellation+ * On POSIX or Windows operating systems, this asynchronous operation supports+ * cancellation for the following asio::cancellation_type values:+ *+ * @li @c cancellation_type::terminal+ *+ * @li @c cancellation_type::partial+ *+ * @li @c cancellation_type::total+ */+ template <typename ConstBufferSequence,+ ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code,+ std::size_t)) WriteToken+ ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(executor_type)>+ ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX(WriteToken,+ void (asio::error_code, std::size_t))+ async_write_some(const ConstBufferSequence& buffers,+ ASIO_MOVE_ARG(WriteToken) token+ ASIO_DEFAULT_COMPLETION_TOKEN(executor_type))+ ASIO_INITFN_AUTO_RESULT_TYPE_SUFFIX((+ async_initiate<WriteToken,+ void (asio::error_code, std::size_t)>(+ declval<initiate_async_write_some>(), token, buffers)))+ {+ return async_initiate<WriteToken,+ void (asio::error_code, std::size_t)>(+ initiate_async_write_some(this), token, buffers);+ }++ /// Read some data from the file.+ /**+ * This function is used to read data from the stream file. The function+ * call will block until one or more bytes of data has been read successfully,+ * or until an error occurs.+ *+ * @param buffers One or more buffers into which the data will be read.+ *+ * @returns The number of bytes read.+ *+ * @throws asio::system_error Thrown on failure. An error code of+ * asio::error::eof indicates that the end of the file was reached.+ *+ * @note The read_some operation may not read all of the requested number of+ * bytes. Consider using the @ref read function if you need to ensure that+ * the requested amount of data is read before the blocking operation+ * completes.+ *+ * @par Example+ * To read into a single data buffer use the @ref buffer function as follows:+ * @code+ * file.read_some(asio::buffer(data, size));+ * @endcode+ * See the @ref buffer documentation for information on reading into multiple+ * buffers in one go, and how to use it with arrays, boost::array or+ * std::vector.+ */+ template <typename MutableBufferSequence>+ std::size_t read_some(const MutableBufferSequence& buffers)+ {+ asio::error_code ec;+ std::size_t s = this->impl_.get_service().read_some(+ this->impl_.get_implementation(), buffers, ec);+ asio::detail::throw_error(ec, "read_some");+ return s;+ }++ /// Read some data from the file.+ /**+ * This function is used to read data from the stream file. The function+ * call will block until one or more bytes of data has been read successfully,+ * or until an error occurs.+ *+ * @param buffers One or more buffers into which the data will be read.+ *+ * @param ec Set to indicate what error occurred, if any.+ *+ * @returns The number of bytes read. Returns 0 if an error occurred.+ *+ * @note The read_some operation may not read all of the requested number of+ * bytes. Consider using the @ref read function if you need to ensure that+ * the requested amount of data is read before the blocking operation+ * completes.+ */+ template <typename MutableBufferSequence>+ std::size_t read_some(const MutableBufferSequence& buffers,+ asio::error_code& ec)+ {+ return this->impl_.get_service().read_some(+ this->impl_.get_implementation(), buffers, ec);+ }++ /// Start an asynchronous read.+ /**+ * This function is used to asynchronously read data from the stream file.+ * It is an initiating function for an @ref asynchronous_operation, and always+ * returns immediately.+ *+ * @param buffers One or more buffers into which the data will be read.+ * Although the buffers object may be copied as necessary, ownership of the+ * underlying memory blocks is retained by the caller, which must guarantee+ * that they remain valid until the completion handler is called.+ *+ * @param token The @ref completion_token that will be used to produce a+ * completion handler, which will be called when the read completes.+ * Potential completion tokens include @ref use_future, @ref use_awaitable,+ * @ref yield_context, or a function object with the correct completion+ * signature. The function signature of the completion handler must be:+ * @code void handler(+ * const asio::error_code& error, // Result of operation.+ * std::size_t bytes_transferred // Number of bytes read.+ * ); @endcode+ * Regardless of whether the asynchronous operation completes immediately or+ * not, the completion handler will not be invoked from within this function.+ * On immediate completion, invocation of the handler will be performed in a+ * manner equivalent to using asio::post().+ *+ * @par Completion Signature+ * @code void(asio::error_code, std::size_t) @endcode+ *+ * @note The read operation may not read all of the requested number of bytes.+ * Consider using the @ref async_read function if you need to ensure that the+ * requested amount of data is read before the asynchronous operation+ * completes.+ *+ * @par Example+ * To read into a single data buffer use the @ref buffer function as follows:+ * @code+ * file.async_read_some(asio::buffer(data, size), handler);+ * @endcode+ * See the @ref buffer documentation for information on reading into multiple+ * buffers in one go, and how to use it with arrays, boost::array or+ * std::vector.+ *+ * @par Per-Operation Cancellation+ * On POSIX or Windows operating systems, this asynchronous operation supports+ * cancellation for the following asio::cancellation_type values:+ *+ * @li @c cancellation_type::terminal+ *+ * @li @c cancellation_type::partial+ *+ * @li @c cancellation_type::total+ */+ template <typename MutableBufferSequence,+ ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code,+ std::size_t)) ReadToken+ ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(executor_type)>+ ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX(ReadToken,+ void (asio::error_code, std::size_t))+ async_read_some(const MutableBufferSequence& buffers,+ ASIO_MOVE_ARG(ReadToken) token+ ASIO_DEFAULT_COMPLETION_TOKEN(executor_type))+ ASIO_INITFN_AUTO_RESULT_TYPE_SUFFIX((+ async_initiate<ReadToken,+ void (asio::error_code, std::size_t)>(+ declval<initiate_async_read_some>(), token, buffers)))+ {+ return async_initiate<ReadToken,+ void (asio::error_code, std::size_t)>(+ initiate_async_read_some(this), token, buffers);+ }++private:+ // Disallow copying and assignment.+ basic_stream_file(const basic_stream_file&) ASIO_DELETED;+ basic_stream_file& operator=(const basic_stream_file&) ASIO_DELETED;++ class initiate_async_write_some+ {+ public:+ typedef Executor executor_type;++ explicit initiate_async_write_some(basic_stream_file* self)+ : self_(self)+ {+ }++ const executor_type& get_executor() const ASIO_NOEXCEPT+ {+ return self_->get_executor();+ }++ template <typename WriteHandler, typename ConstBufferSequence>+ void operator()(ASIO_MOVE_ARG(WriteHandler) handler,+ const ConstBufferSequence& buffers) const+ {+ // If you get an error on the following line it means that your handler+ // does not meet the documented type requirements for a WriteHandler.+ ASIO_WRITE_HANDLER_CHECK(WriteHandler, handler) type_check;++ detail::non_const_lvalue<WriteHandler> handler2(handler);+ self_->impl_.get_service().async_write_some(+ self_->impl_.get_implementation(), buffers,+ handler2.value, self_->impl_.get_executor());+ }++ private:+ basic_stream_file* self_;+ };++ class initiate_async_read_some+ {+ public:+ typedef Executor executor_type;++ explicit initiate_async_read_some(basic_stream_file* self)+ : self_(self)+ {+ }++ const executor_type& get_executor() const ASIO_NOEXCEPT+ {+ return self_->get_executor();+ }++ template <typename ReadHandler, typename MutableBufferSequence>+ void operator()(ASIO_MOVE_ARG(ReadHandler) handler,+ const MutableBufferSequence& buffers) const+ {+ // If you get an error on the following line it means that your handler+ // does not meet the documented type requirements for a ReadHandler.+ ASIO_READ_HANDLER_CHECK(ReadHandler, handler) type_check;++ detail::non_const_lvalue<ReadHandler> handler2(handler);+ self_->impl_.get_service().async_read_some(+ self_->impl_.get_implementation(), buffers,+ handler2.value, self_->impl_.get_executor());+ }++ private:+ basic_stream_file* self_;+ };+};++} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // defined(ASIO_HAS_FILE)+ // || defined(GENERATING_DOCUMENTATION)++#endif // ASIO_BASIC_STREAM_FILE_HPP
link/modules/asio-standalone/asio/include/asio/basic_stream_socket.hpp view
@@ -2,7 +2,7 @@ // basic_stream_socket.hpp // ~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -46,6 +46,13 @@ * @e Distinct @e objects: Safe.@n * @e Shared @e objects: Unsafe. *+ * Synchronous @c send, @c receive, @c connect, and @c shutdown operations are+ * thread safe with respect to each other, if the underlying operating system+ * calls are also thread safe. This means that it is permitted to perform+ * concurrent calls to these synchronous operations on a single socket object.+ * Other synchronous operations, such as @c open or @c close, are not thread+ * safe.+ * * @par Concepts: * AsyncReadStream, AsyncWriteStream, Stream, SyncReadStream, SyncWriteStream. */@@ -53,6 +60,10 @@ class basic_stream_socket : public basic_socket<Protocol, Executor> {+private:+ class initiate_async_send;+ class initiate_async_receive;+ public: /// The type of the executor associated with the object. typedef Executor executor_type;@@ -105,9 +116,9 @@ */ template <typename ExecutionContext> explicit basic_stream_socket(ExecutionContext& context,- typename enable_if<+ typename constraint< is_convertible<ExecutionContext&, execution_context&>::value- >::type* = 0)+ >::type = 0) : basic_socket<Protocol, Executor>(context) { }@@ -144,9 +155,10 @@ */ template <typename ExecutionContext> basic_stream_socket(ExecutionContext& context, const protocol_type& protocol,- typename enable_if<- is_convertible<ExecutionContext&, execution_context&>::value- >::type* = 0)+ typename constraint<+ is_convertible<ExecutionContext&, execution_context&>::value,+ defaulted_constraint+ >::type = defaulted_constraint()) : basic_socket<Protocol, Executor>(context, protocol) { }@@ -189,9 +201,9 @@ */ template <typename ExecutionContext> basic_stream_socket(ExecutionContext& context, const endpoint_type& endpoint,- typename enable_if<+ typename constraint< is_convertible<ExecutionContext&, execution_context&>::value- >::type* = 0)+ >::type = 0) : basic_socket<Protocol, Executor>(context, endpoint) { }@@ -234,9 +246,9 @@ template <typename ExecutionContext> basic_stream_socket(ExecutionContext& context, const protocol_type& protocol, const native_handle_type& native_socket,- typename enable_if<+ typename constraint< is_convertible<ExecutionContext&, execution_context&>::value- >::type* = 0)+ >::type = 0) : basic_socket<Protocol, Executor>(context, protocol, native_socket) { }@@ -289,10 +301,10 @@ */ template <typename Protocol1, typename Executor1> basic_stream_socket(basic_stream_socket<Protocol1, Executor1>&& other,- typename enable_if<+ typename constraint< is_convertible<Protocol1, Protocol>::value && is_convertible<Executor1, Executor>::value- >::type* = 0)+ >::type = 0) : basic_socket<Protocol, Executor>(std::move(other)) { }@@ -309,7 +321,7 @@ * constructor. */ template <typename Protocol1, typename Executor1>- typename enable_if<+ typename constraint< is_convertible<Protocol1, Protocol>::value && is_convertible<Executor1, Executor>::value, basic_stream_socket&@@ -431,25 +443,31 @@ /// Start an asynchronous send. /** * This function is used to asynchronously send data on the stream socket.- * The function call always returns immediately.+ * It is an initiating function for an @ref asynchronous_operation, and always+ * returns immediately. * * @param buffers One or more data buffers to be sent on the socket. Although * the buffers object may be copied as necessary, ownership of the underlying * memory blocks is retained by the caller, which must guarantee that they- * remain valid until the handler is called.+ * remain valid until the completion handler is called. *- * @param handler The handler to be called when the send operation completes.- * Copies will be made of the handler as required. The function signature of- * the handler must be:+ * @param token The @ref completion_token that will be used to produce a+ * completion handler, which will be called when the send completes.+ * Potential completion tokens include @ref use_future, @ref use_awaitable,+ * @ref yield_context, or a function object with the correct completion+ * signature. The function signature of the completion handler must be: * @code void handler( * const asio::error_code& error, // Result of operation.- * std::size_t bytes_transferred // Number of bytes sent.+ * std::size_t bytes_transferred // Number of bytes sent. * ); @endcode * Regardless of whether the asynchronous operation completes immediately or- * not, the handler will not be invoked from within this function. On- * immediate completion, invocation of the handler will be performed in a+ * not, the completion handler will not be invoked from within this function.+ * On immediate completion, invocation of the handler will be performed in a * manner equivalent to using asio::post(). *+ * @par Completion Signature+ * @code void(asio::error_code, std::size_t) @endcode+ * * @note The send operation may not transmit all of the data to the peer. * Consider using the @ref async_write function if you need to ensure that all * data is written before the asynchronous operation completes.@@ -462,47 +480,68 @@ * See the @ref buffer documentation for information on sending multiple * buffers in one go, and how to use it with arrays, boost::array or * std::vector.+ *+ * @par Per-Operation Cancellation+ * On POSIX or Windows operating systems, this asynchronous operation supports+ * cancellation for the following asio::cancellation_type values:+ *+ * @li @c cancellation_type::terminal+ *+ * @li @c cancellation_type::partial+ *+ * @li @c cancellation_type::total */ template <typename ConstBufferSequence, ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code,- std::size_t)) WriteHandler+ std::size_t)) WriteToken ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(executor_type)>- ASIO_INITFN_AUTO_RESULT_TYPE(WriteHandler,+ ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX(WriteToken, void (asio::error_code, std::size_t)) async_send(const ConstBufferSequence& buffers,- ASIO_MOVE_ARG(WriteHandler) handler+ ASIO_MOVE_ARG(WriteToken) token ASIO_DEFAULT_COMPLETION_TOKEN(executor_type))+ ASIO_INITFN_AUTO_RESULT_TYPE_SUFFIX((+ async_initiate<WriteToken,+ void (asio::error_code, std::size_t)>(+ declval<initiate_async_send>(), token,+ buffers, socket_base::message_flags(0)))) {- return async_initiate<WriteHandler,+ return async_initiate<WriteToken, void (asio::error_code, std::size_t)>(- initiate_async_send(this), handler,+ initiate_async_send(this), token, buffers, socket_base::message_flags(0)); } /// Start an asynchronous send. /** * This function is used to asynchronously send data on the stream socket.- * The function call always returns immediately.+ * It is an initiating function for an @ref asynchronous_operation, and always+ * returns immediately. * * @param buffers One or more data buffers to be sent on the socket. Although * the buffers object may be copied as necessary, ownership of the underlying * memory blocks is retained by the caller, which must guarantee that they- * remain valid until the handler is called.+ * remain valid until the completion handler is called. * * @param flags Flags specifying how the send call is to be made. *- * @param handler The handler to be called when the send operation completes.- * Copies will be made of the handler as required. The function signature of- * the handler must be:+ * @param token The @ref completion_token that will be used to produce a+ * completion handler, which will be called when the send completes.+ * Potential completion tokens include @ref use_future, @ref use_awaitable,+ * @ref yield_context, or a function object with the correct completion+ * signature. The function signature of the completion handler must be: * @code void handler( * const asio::error_code& error, // Result of operation.- * std::size_t bytes_transferred // Number of bytes sent.+ * std::size_t bytes_transferred // Number of bytes sent. * ); @endcode * Regardless of whether the asynchronous operation completes immediately or- * not, the handler will not be invoked from within this function. On- * immediate completion, invocation of the handler will be performed in a+ * not, the completion handler will not be invoked from within this function.+ * On immediate completion, invocation of the handler will be performed in a * manner equivalent to using asio::post(). *+ * @par Completion Signature+ * @code void(asio::error_code, std::size_t) @endcode+ * * @note The send operation may not transmit all of the data to the peer. * Consider using the @ref async_write function if you need to ensure that all * data is written before the asynchronous operation completes.@@ -515,21 +554,35 @@ * See the @ref buffer documentation for information on sending multiple * buffers in one go, and how to use it with arrays, boost::array or * std::vector.+ *+ * @par Per-Operation Cancellation+ * On POSIX or Windows operating systems, this asynchronous operation supports+ * cancellation for the following asio::cancellation_type values:+ *+ * @li @c cancellation_type::terminal+ *+ * @li @c cancellation_type::partial+ *+ * @li @c cancellation_type::total */ template <typename ConstBufferSequence, ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code,- std::size_t)) WriteHandler+ std::size_t)) WriteToken ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(executor_type)>- ASIO_INITFN_AUTO_RESULT_TYPE(WriteHandler,+ ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX(WriteToken, void (asio::error_code, std::size_t)) async_send(const ConstBufferSequence& buffers, socket_base::message_flags flags,- ASIO_MOVE_ARG(WriteHandler) handler+ ASIO_MOVE_ARG(WriteToken) token ASIO_DEFAULT_COMPLETION_TOKEN(executor_type))+ ASIO_INITFN_AUTO_RESULT_TYPE_SUFFIX((+ async_initiate<WriteToken,+ void (asio::error_code, std::size_t)>(+ declval<initiate_async_send>(), token, buffers, flags))) {- return async_initiate<WriteHandler,+ return async_initiate<WriteToken, void (asio::error_code, std::size_t)>(- initiate_async_send(this), handler, buffers, flags);+ initiate_async_send(this), token, buffers, flags); } /// Receive some data on the socket.@@ -640,25 +693,31 @@ /// Start an asynchronous receive. /** * This function is used to asynchronously receive data from the stream- * socket. The function call always returns immediately.+ * socket. It is an initiating function for an @ref asynchronous_operation,+ * and always returns immediately. * * @param buffers One or more buffers into which the data will be received. * Although the buffers object may be copied as necessary, ownership of the * underlying memory blocks is retained by the caller, which must guarantee- * that they remain valid until the handler is called.+ * that they remain valid until the completion handler is called. *- * @param handler The handler to be called when the receive operation- * completes. Copies will be made of the handler as required. The function- * signature of the handler must be:+ * @param token The @ref completion_token that will be used to produce a+ * completion handler, which will be called when the receive completes.+ * Potential completion tokens include @ref use_future, @ref use_awaitable,+ * @ref yield_context, or a function object with the correct completion+ * signature. The function signature of the completion handler must be: * @code void handler( * const asio::error_code& error, // Result of operation.- * std::size_t bytes_transferred // Number of bytes received.+ * std::size_t bytes_transferred // Number of bytes received. * ); @endcode * Regardless of whether the asynchronous operation completes immediately or- * not, the handler will not be invoked from within this function. On- * immediate completion, invocation of the handler will be performed in a+ * not, the completion handler will not be invoked from within this function.+ * On immediate completion, invocation of the handler will be performed in a * manner equivalent to using asio::post(). *+ * @par Completion Signature+ * @code void(asio::error_code, std::size_t) @endcode+ * * @note The receive operation may not receive all of the requested number of * bytes. Consider using the @ref async_read function if you need to ensure * that the requested amount of data is received before the asynchronous@@ -673,47 +732,68 @@ * See the @ref buffer documentation for information on receiving into * multiple buffers in one go, and how to use it with arrays, boost::array or * std::vector.+ *+ * @par Per-Operation Cancellation+ * On POSIX or Windows operating systems, this asynchronous operation supports+ * cancellation for the following asio::cancellation_type values:+ *+ * @li @c cancellation_type::terminal+ *+ * @li @c cancellation_type::partial+ *+ * @li @c cancellation_type::total */ template <typename MutableBufferSequence, ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code,- std::size_t)) ReadHandler+ std::size_t)) ReadToken ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(executor_type)>- ASIO_INITFN_AUTO_RESULT_TYPE(ReadHandler,+ ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX(ReadToken, void (asio::error_code, std::size_t)) async_receive(const MutableBufferSequence& buffers,- ASIO_MOVE_ARG(ReadHandler) handler+ ASIO_MOVE_ARG(ReadToken) token ASIO_DEFAULT_COMPLETION_TOKEN(executor_type))+ ASIO_INITFN_AUTO_RESULT_TYPE_SUFFIX((+ async_initiate<ReadToken,+ void (asio::error_code, std::size_t)>(+ declval<initiate_async_receive>(), token,+ buffers, socket_base::message_flags(0)))) {- return async_initiate<ReadHandler,+ return async_initiate<ReadToken, void (asio::error_code, std::size_t)>(- initiate_async_receive(this), handler,+ initiate_async_receive(this), token, buffers, socket_base::message_flags(0)); } /// Start an asynchronous receive. /** * This function is used to asynchronously receive data from the stream- * socket. The function call always returns immediately.+ * socket. It is an initiating function for an @ref asynchronous_operation,+ * and always returns immediately. * * @param buffers One or more buffers into which the data will be received. * Although the buffers object may be copied as necessary, ownership of the * underlying memory blocks is retained by the caller, which must guarantee- * that they remain valid until the handler is called.+ * that they remain valid until the completion handler is called. * * @param flags Flags specifying how the receive call is to be made. *- * @param handler The handler to be called when the receive operation- * completes. Copies will be made of the handler as required. The function- * signature of the handler must be:+ * @param token The @ref completion_token that will be used to produce a+ * completion handler, which will be called when the receive completes.+ * Potential completion tokens include @ref use_future, @ref use_awaitable,+ * @ref yield_context, or a function object with the correct completion+ * signature. The function signature of the completion handler must be: * @code void handler( * const asio::error_code& error, // Result of operation.- * std::size_t bytes_transferred // Number of bytes received.+ * std::size_t bytes_transferred // Number of bytes received. * ); @endcode * Regardless of whether the asynchronous operation completes immediately or- * not, the handler will not be invoked from within this function. On- * immediate completion, invocation of the handler will be performed in a+ * not, the completion handler will not be invoked from within this function.+ * On immediate completion, invocation of the handler will be performed in a * manner equivalent to using asio::post(). *+ * @par Completion Signature+ * @code void(asio::error_code, std::size_t) @endcode+ * * @note The receive operation may not receive all of the requested number of * bytes. Consider using the @ref async_read function if you need to ensure * that the requested amount of data is received before the asynchronous@@ -728,21 +808,35 @@ * See the @ref buffer documentation for information on receiving into * multiple buffers in one go, and how to use it with arrays, boost::array or * std::vector.+ *+ * @par Per-Operation Cancellation+ * On POSIX or Windows operating systems, this asynchronous operation supports+ * cancellation for the following asio::cancellation_type values:+ *+ * @li @c cancellation_type::terminal+ *+ * @li @c cancellation_type::partial+ *+ * @li @c cancellation_type::total */ template <typename MutableBufferSequence, ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code,- std::size_t)) ReadHandler+ std::size_t)) ReadToken ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(executor_type)>- ASIO_INITFN_AUTO_RESULT_TYPE(ReadHandler,+ ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX(ReadToken, void (asio::error_code, std::size_t)) async_receive(const MutableBufferSequence& buffers, socket_base::message_flags flags,- ASIO_MOVE_ARG(ReadHandler) handler+ ASIO_MOVE_ARG(ReadToken) token ASIO_DEFAULT_COMPLETION_TOKEN(executor_type))+ ASIO_INITFN_AUTO_RESULT_TYPE_SUFFIX((+ async_initiate<ReadToken,+ void (asio::error_code, std::size_t)>(+ declval<initiate_async_receive>(), token, buffers, flags))) {- return async_initiate<ReadHandler,+ return async_initiate<ReadToken, void (asio::error_code, std::size_t)>(- initiate_async_receive(this), handler, buffers, flags);+ initiate_async_receive(this), token, buffers, flags); } /// Write some data to the socket.@@ -809,25 +903,31 @@ /// Start an asynchronous write. /** * This function is used to asynchronously write data to the stream socket.- * The function call always returns immediately.+ * It is an initiating function for an @ref asynchronous_operation, and always+ * returns immediately. * * @param buffers One or more data buffers to be written to the socket. * Although the buffers object may be copied as necessary, ownership of the * underlying memory blocks is retained by the caller, which must guarantee- * that they remain valid until the handler is called.+ * that they remain valid until the completion handler is called. *- * @param handler The handler to be called when the write operation completes.- * Copies will be made of the handler as required. The function signature of- * the handler must be:+ * @param token The @ref completion_token that will be used to produce a+ * completion handler, which will be called when the write completes.+ * Potential completion tokens include @ref use_future, @ref use_awaitable,+ * @ref yield_context, or a function object with the correct completion+ * signature. The function signature of the completion handler must be: * @code void handler( * const asio::error_code& error, // Result of operation.- * std::size_t bytes_transferred // Number of bytes written.+ * std::size_t bytes_transferred // Number of bytes written. * ); @endcode * Regardless of whether the asynchronous operation completes immediately or- * not, the handler will not be invoked from within this function. On- * immediate completion, invocation of the handler will be performed in a+ * not, the completion handler will not be invoked from within this function.+ * On immediate completion, invocation of the handler will be performed in a * manner equivalent to using asio::post(). *+ * @par Completion Signature+ * @code void(asio::error_code, std::size_t) @endcode+ * * @note The write operation may not transmit all of the data to the peer. * Consider using the @ref async_write function if you need to ensure that all * data is written before the asynchronous operation completes.@@ -840,20 +940,35 @@ * See the @ref buffer documentation for information on writing multiple * buffers in one go, and how to use it with arrays, boost::array or * std::vector.+ *+ * @par Per-Operation Cancellation+ * On POSIX or Windows operating systems, this asynchronous operation supports+ * cancellation for the following asio::cancellation_type values:+ *+ * @li @c cancellation_type::terminal+ *+ * @li @c cancellation_type::partial+ *+ * @li @c cancellation_type::total */ template <typename ConstBufferSequence, ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code,- std::size_t)) WriteHandler+ std::size_t)) WriteToken ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(executor_type)>- ASIO_INITFN_AUTO_RESULT_TYPE(WriteHandler,+ ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX(WriteToken, void (asio::error_code, std::size_t)) async_write_some(const ConstBufferSequence& buffers,- ASIO_MOVE_ARG(WriteHandler) handler+ ASIO_MOVE_ARG(WriteToken) token ASIO_DEFAULT_COMPLETION_TOKEN(executor_type))+ ASIO_INITFN_AUTO_RESULT_TYPE_SUFFIX((+ async_initiate<WriteToken,+ void (asio::error_code, std::size_t)>(+ declval<initiate_async_send>(), token,+ buffers, socket_base::message_flags(0)))) {- return async_initiate<WriteHandler,+ return async_initiate<WriteToken, void (asio::error_code, std::size_t)>(- initiate_async_send(this), handler,+ initiate_async_send(this), token, buffers, socket_base::message_flags(0)); } @@ -923,25 +1038,31 @@ /// Start an asynchronous read. /** * This function is used to asynchronously read data from the stream socket.- * The function call always returns immediately.+ * socket. It is an initiating function for an @ref asynchronous_operation,+ * and always returns immediately. * * @param buffers One or more buffers into which the data will be read. * Although the buffers object may be copied as necessary, ownership of the * underlying memory blocks is retained by the caller, which must guarantee- * that they remain valid until the handler is called.+ * that they remain valid until the completion handler is called. *- * @param handler The handler to be called when the read operation completes.- * Copies will be made of the handler as required. The function signature of- * the handler must be:+ * @param token The @ref completion_token that will be used to produce a+ * completion handler, which will be called when the read completes.+ * Potential completion tokens include @ref use_future, @ref use_awaitable,+ * @ref yield_context, or a function object with the correct completion+ * signature. The function signature of the completion handler must be: * @code void handler( * const asio::error_code& error, // Result of operation.- * std::size_t bytes_transferred // Number of bytes read.+ * std::size_t bytes_transferred // Number of bytes read. * ); @endcode * Regardless of whether the asynchronous operation completes immediately or- * not, the handler will not be invoked from within this function. On- * immediate completion, invocation of the handler will be performed in a+ * not, the completion handler will not be invoked from within this function.+ * On immediate completion, invocation of the handler will be performed in a * manner equivalent to using asio::post(). *+ * @par Completion Signature+ * @code void(asio::error_code, std::size_t) @endcode+ * * @note The read operation may not read all of the requested number of bytes. * Consider using the @ref async_read function if you need to ensure that the * requested amount of data is read before the asynchronous operation@@ -955,20 +1076,35 @@ * See the @ref buffer documentation for information on reading into multiple * buffers in one go, and how to use it with arrays, boost::array or * std::vector.+ *+ * @par Per-Operation Cancellation+ * On POSIX or Windows operating systems, this asynchronous operation supports+ * cancellation for the following asio::cancellation_type values:+ *+ * @li @c cancellation_type::terminal+ *+ * @li @c cancellation_type::partial+ *+ * @li @c cancellation_type::total */ template <typename MutableBufferSequence, ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code,- std::size_t)) ReadHandler+ std::size_t)) ReadToken ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(executor_type)>- ASIO_INITFN_AUTO_RESULT_TYPE(ReadHandler,+ ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX(ReadToken, void (asio::error_code, std::size_t)) async_read_some(const MutableBufferSequence& buffers,- ASIO_MOVE_ARG(ReadHandler) handler+ ASIO_MOVE_ARG(ReadToken) token ASIO_DEFAULT_COMPLETION_TOKEN(executor_type))+ ASIO_INITFN_AUTO_RESULT_TYPE_SUFFIX((+ async_initiate<ReadToken,+ void (asio::error_code, std::size_t)>(+ declval<initiate_async_receive>(), token,+ buffers, socket_base::message_flags(0)))) {- return async_initiate<ReadHandler,+ return async_initiate<ReadToken, void (asio::error_code, std::size_t)>(- initiate_async_receive(this), handler,+ initiate_async_receive(this), token, buffers, socket_base::message_flags(0)); } @@ -987,7 +1123,7 @@ { } - executor_type get_executor() const ASIO_NOEXCEPT+ const executor_type& get_executor() const ASIO_NOEXCEPT { return self_->get_executor(); }@@ -1021,7 +1157,7 @@ { } - executor_type get_executor() const ASIO_NOEXCEPT+ const executor_type& get_executor() const ASIO_NOEXCEPT { return self_->get_executor(); }
link/modules/asio-standalone/asio/include/asio/basic_streambuf.hpp view
@@ -2,7 +2,7 @@ // basic_streambuf.hpp // ~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/basic_streambuf_fwd.hpp view
@@ -2,7 +2,7 @@ // basic_streambuf_fwd.hpp // ~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/basic_waitable_timer.hpp view
@@ -2,7 +2,7 @@ // basic_waitable_timer.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -141,6 +141,9 @@ template <typename Clock, typename WaitTraits, typename Executor> class basic_waitable_timer {+private:+ class initiate_async_wait;+ public: /// The type of the executor associated with the object. typedef Executor executor_type;@@ -175,7 +178,7 @@ * dispatch handlers for any asynchronous operations performed on the timer. */ explicit basic_waitable_timer(const executor_type& ex)- : impl_(ex)+ : impl_(0, ex) { } @@ -191,10 +194,10 @@ */ template <typename ExecutionContext> explicit basic_waitable_timer(ExecutionContext& context,- typename enable_if<+ typename constraint< is_convertible<ExecutionContext&, execution_context&>::value- >::type* = 0)- : impl_(context)+ >::type = 0)+ : impl_(0, 0, context) { } @@ -209,7 +212,7 @@ * as an absolute time. */ basic_waitable_timer(const executor_type& ex, const time_point& expiry_time)- : impl_(ex)+ : impl_(0, ex) { asio::error_code ec; impl_.get_service().expires_at(impl_.get_implementation(), expiry_time, ec);@@ -230,10 +233,10 @@ template <typename ExecutionContext> explicit basic_waitable_timer(ExecutionContext& context, const time_point& expiry_time,- typename enable_if<+ typename constraint< is_convertible<ExecutionContext&, execution_context&>::value- >::type* = 0)- : impl_(context)+ >::type = 0)+ : impl_(0, 0, context) { asio::error_code ec; impl_.get_service().expires_at(impl_.get_implementation(), expiry_time, ec);@@ -251,7 +254,7 @@ * now. */ basic_waitable_timer(const executor_type& ex, const duration& expiry_time)- : impl_(ex)+ : impl_(0, ex) { asio::error_code ec; impl_.get_service().expires_after(@@ -273,10 +276,10 @@ template <typename ExecutionContext> explicit basic_waitable_timer(ExecutionContext& context, const duration& expiry_time,- typename enable_if<+ typename constraint< is_convertible<ExecutionContext&, execution_context&>::value- >::type* = 0)- : impl_(context)+ >::type = 0)+ : impl_(0, 0, context) { asio::error_code ec; impl_.get_service().expires_after(@@ -337,9 +340,9 @@ template <typename Executor1> basic_waitable_timer( basic_waitable_timer<Clock, WaitTraits, Executor1>&& other,- typename enable_if<- is_convertible<Executor1, Executor>::value- >::type* = 0)+ typename constraint<+ is_convertible<Executor1, Executor>::value+ >::type = 0) : impl_(std::move(other.impl_)) { }@@ -357,7 +360,7 @@ * constructor. */ template <typename Executor1>- typename enable_if<+ typename constraint< is_convertible<Executor1, Executor>::value, basic_waitable_timer& >::type operator=(basic_waitable_timer<Clock, WaitTraits, Executor1>&& other)@@ -378,7 +381,7 @@ } /// Get the executor associated with the object.- executor_type get_executor() ASIO_NOEXCEPT+ const executor_type& get_executor() ASIO_NOEXCEPT { return impl_.get_executor(); }@@ -726,38 +729,57 @@ /// Start an asynchronous wait on the timer. /** * This function may be used to initiate an asynchronous wait against the- * timer. It always returns immediately.+ * timer. It is an initiating function for an @ref asynchronous_operation,+ * and always returns immediately. *- * For each call to async_wait(), the supplied handler will be called exactly- * once. The handler will be called when:+ * For each call to async_wait(), the completion handler will be called+ * exactly once. The completion handler will be called when: * * @li The timer has expired. * * @li The timer was cancelled, in which case the handler is passed the error * code asio::error::operation_aborted. *- * @param handler The handler to be called when the timer expires. Copies- * will be made of the handler as required. The function signature of the- * handler must be:+ * @param token The @ref completion_token that will be used to produce a+ * completion handler, which will be called when the timer expires. Potential+ * completion tokens include @ref use_future, @ref use_awaitable, @ref+ * yield_context, or a function object with the correct completion signature.+ * The function signature of the completion handler must be: * @code void handler( * const asio::error_code& error // Result of operation. * ); @endcode * Regardless of whether the asynchronous operation completes immediately or- * not, the handler will not be invoked from within this function. On- * immediate completion, invocation of the handler will be performed in a+ * not, the completion handler will not be invoked from within this function.+ * On immediate completion, invocation of the handler will be performed in a * manner equivalent to using asio::post().+ *+ * @par Completion Signature+ * @code void(asio::error_code) @endcode+ *+ * @par Per-Operation Cancellation+ * This asynchronous operation supports cancellation for the following+ * asio::cancellation_type values:+ *+ * @li @c cancellation_type::terminal+ *+ * @li @c cancellation_type::partial+ *+ * @li @c cancellation_type::total */ template < ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code))- WaitHandler ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(executor_type)>- ASIO_INITFN_AUTO_RESULT_TYPE(WaitHandler,- void (asio::error_code))+ WaitToken ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(executor_type)>+ ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX(+ WaitToken, void (asio::error_code)) async_wait(- ASIO_MOVE_ARG(WaitHandler) handler+ ASIO_MOVE_ARG(WaitToken) token ASIO_DEFAULT_COMPLETION_TOKEN(executor_type))+ ASIO_INITFN_AUTO_RESULT_TYPE_SUFFIX((+ async_initiate<WaitToken, void (asio::error_code)>(+ declval<initiate_async_wait>(), token))) {- return async_initiate<WaitHandler, void (asio::error_code)>(- initiate_async_wait(this), handler);+ return async_initiate<WaitToken, void (asio::error_code)>(+ initiate_async_wait(this), token); } private:@@ -776,7 +798,7 @@ { } - executor_type get_executor() const ASIO_NOEXCEPT+ const executor_type& get_executor() const ASIO_NOEXCEPT { return self_->get_executor(); }
+ link/modules/asio-standalone/asio/include/asio/basic_writable_pipe.hpp view
@@ -0,0 +1,631 @@+//+// basic_writable_pipe.hpp+// ~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com)+//+// Distributed under the Boost Software License, Version 1.0. (See accompanying+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)+//++#ifndef ASIO_BASIC_WRITABLE_PIPE_HPP+#define ASIO_BASIC_WRITABLE_PIPE_HPP++#if defined(_MSC_VER) && (_MSC_VER >= 1200)+# pragma once+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)++#include "asio/detail/config.hpp"++#if defined(ASIO_HAS_PIPE) \+ || defined(GENERATING_DOCUMENTATION)++#include <string>+#include "asio/any_io_executor.hpp"+#include "asio/async_result.hpp"+#include "asio/detail/handler_type_requirements.hpp"+#include "asio/detail/io_object_impl.hpp"+#include "asio/detail/non_const_lvalue.hpp"+#include "asio/detail/throw_error.hpp"+#include "asio/detail/type_traits.hpp"+#include "asio/error.hpp"+#include "asio/execution_context.hpp"+#if defined(ASIO_HAS_IOCP)+# include "asio/detail/win_iocp_handle_service.hpp"+#elif defined(ASIO_HAS_IO_URING_AS_DEFAULT)+# include "asio/detail/io_uring_descriptor_service.hpp"+#else+# include "asio/detail/reactive_descriptor_service.hpp"+#endif++#if defined(ASIO_HAS_MOVE)+# include <utility>+#endif // defined(ASIO_HAS_MOVE)++#include "asio/detail/push_options.hpp"++namespace asio {++/// Provides pipe functionality.+/**+ * The basic_writable_pipe class provides a wrapper over pipe+ * functionality.+ *+ * @par Thread Safety+ * @e Distinct @e objects: Safe.@n+ * @e Shared @e objects: Unsafe.+ */+template <typename Executor = any_io_executor>+class basic_writable_pipe+{+private:+ class initiate_async_write_some;++public:+ /// The type of the executor associated with the object.+ typedef Executor executor_type;++ /// Rebinds the pipe type to another executor.+ template <typename Executor1>+ struct rebind_executor+ {+ /// The pipe type when rebound to the specified executor.+ typedef basic_writable_pipe<Executor1> other;+ };++ /// The native representation of a pipe.+#if defined(GENERATING_DOCUMENTATION)+ typedef implementation_defined native_handle_type;+#elif defined(ASIO_HAS_IOCP)+ typedef detail::win_iocp_handle_service::native_handle_type+ native_handle_type;+#elif defined(ASIO_HAS_IO_URING_AS_DEFAULT)+ typedef detail::io_uring_descriptor_service::native_handle_type+ native_handle_type;+#else+ typedef detail::reactive_descriptor_service::native_handle_type+ native_handle_type;+#endif++ /// A basic_writable_pipe is always the lowest layer.+ typedef basic_writable_pipe lowest_layer_type;++ /// Construct a basic_writable_pipe without opening it.+ /**+ * This constructor creates a pipe without opening it.+ *+ * @param ex The I/O executor that the pipe will use, by default, to dispatch+ * handlers for any asynchronous operations performed on the pipe.+ */+ explicit basic_writable_pipe(const executor_type& ex)+ : impl_(0, ex)+ {+ }++ /// Construct a basic_writable_pipe without opening it.+ /**+ * This constructor creates a pipe without opening it.+ *+ * @param context An execution context which provides the I/O executor that+ * the pipe will use, by default, to dispatch handlers for any asynchronous+ * operations performed on the pipe.+ */+ template <typename ExecutionContext>+ explicit basic_writable_pipe(ExecutionContext& context,+ typename constraint<+ is_convertible<ExecutionContext&, execution_context&>::value,+ defaulted_constraint+ >::type = defaulted_constraint())+ : impl_(0, 0, context)+ {+ }++ /// Construct a basic_writable_pipe on an existing native pipe.+ /**+ * This constructor creates a pipe object to hold an existing native+ * pipe.+ *+ * @param ex The I/O executor that the pipe will use, by default, to+ * dispatch handlers for any asynchronous operations performed on the+ * pipe.+ *+ * @param native_pipe A native pipe.+ *+ * @throws asio::system_error Thrown on failure.+ */+ basic_writable_pipe(const executor_type& ex,+ const native_handle_type& native_pipe)+ : impl_(0, ex)+ {+ asio::error_code ec;+ impl_.get_service().assign(impl_.get_implementation(),+ native_pipe, ec);+ asio::detail::throw_error(ec, "assign");+ }++ /// Construct a basic_writable_pipe on an existing native pipe.+ /**+ * This constructor creates a pipe object to hold an existing native+ * pipe.+ *+ * @param context An execution context which provides the I/O executor that+ * the pipe will use, by default, to dispatch handlers for any+ * asynchronous operations performed on the pipe.+ *+ * @param native_pipe A native pipe.+ *+ * @throws asio::system_error Thrown on failure.+ */+ template <typename ExecutionContext>+ basic_writable_pipe(ExecutionContext& context,+ const native_handle_type& native_pipe,+ typename constraint<+ is_convertible<ExecutionContext&, execution_context&>::value+ >::type = 0)+ : impl_(0, 0, context)+ {+ asio::error_code ec;+ impl_.get_service().assign(impl_.get_implementation(),+ native_pipe, ec);+ asio::detail::throw_error(ec, "assign");+ }++#if defined(ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)+ /// Move-construct a basic_writable_pipe from another.+ /**+ * This constructor moves a pipe from one object to another.+ *+ * @param other The other basic_writable_pipe object from which the move will+ * occur.+ *+ * @note Following the move, the moved-from object is in the same state as if+ * constructed using the @c basic_writable_pipe(const executor_type&)+ * constructor.+ */+ basic_writable_pipe(basic_writable_pipe&& other)+ : impl_(std::move(other.impl_))+ {+ }++ /// Move-assign a basic_writable_pipe from another.+ /**+ * This assignment operator moves a pipe from one object to another.+ *+ * @param other The other basic_writable_pipe object from which the move will+ * occur.+ *+ * @note Following the move, the moved-from object is in the same state as if+ * constructed using the @c basic_writable_pipe(const executor_type&)+ * constructor.+ */+ basic_writable_pipe& operator=(basic_writable_pipe&& other)+ {+ impl_ = std::move(other.impl_);+ return *this;+ }++ // All pipes have access to each other's implementations.+ template <typename Executor1>+ friend class basic_writable_pipe;++ /// Move-construct a basic_writable_pipe from a pipe of another executor type.+ /**+ * This constructor moves a pipe from one object to another.+ *+ * @param other The other basic_writable_pipe object from which the move will+ * occur.+ *+ * @note Following the move, the moved-from object is in the same state as if+ * constructed using the @c basic_writable_pipe(const executor_type&)+ * constructor.+ */+ template <typename Executor1>+ basic_writable_pipe(basic_writable_pipe<Executor1>&& other,+ typename constraint<+ is_convertible<Executor1, Executor>::value,+ defaulted_constraint+ >::type = defaulted_constraint())+ : impl_(std::move(other.impl_))+ {+ }++ /// Move-assign a basic_writable_pipe from a pipe of another executor type.+ /**+ * This assignment operator moves a pipe from one object to another.+ *+ * @param other The other basic_writable_pipe object from which the move will+ * occur.+ *+ * @note Following the move, the moved-from object is in the same state as if+ * constructed using the @c basic_writable_pipe(const executor_type&)+ * constructor.+ */+ template <typename Executor1>+ typename constraint<+ is_convertible<Executor1, Executor>::value,+ basic_writable_pipe&+ >::type operator=(basic_writable_pipe<Executor1>&& other)+ {+ basic_writable_pipe tmp(std::move(other));+ impl_ = std::move(tmp.impl_);+ return *this;+ }+#endif // defined(ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)++ /// Destroys the pipe.+ /**+ * This function destroys the pipe, cancelling any outstanding+ * asynchronous wait operations associated with the pipe as if by+ * calling @c cancel.+ */+ ~basic_writable_pipe()+ {+ }++ /// Get the executor associated with the object.+ const executor_type& get_executor() ASIO_NOEXCEPT+ {+ return impl_.get_executor();+ }++ /// Get a reference to the lowest layer.+ /**+ * This function returns a reference to the lowest layer in a stack of+ * layers. Since a basic_writable_pipe cannot contain any further layers, it+ * simply returns a reference to itself.+ *+ * @return A reference to the lowest layer in the stack of layers. Ownership+ * is not transferred to the caller.+ */+ lowest_layer_type& lowest_layer()+ {+ return *this;+ }++ /// Get a const reference to the lowest layer.+ /**+ * This function returns a const reference to the lowest layer in a stack of+ * layers. Since a basic_writable_pipe cannot contain any further layers, it+ * simply returns a reference to itself.+ *+ * @return A const reference to the lowest layer in the stack of layers.+ * Ownership is not transferred to the caller.+ */+ const lowest_layer_type& lowest_layer() const+ {+ return *this;+ }++ /// Assign an existing native pipe to the pipe.+ /*+ * This function opens the pipe to hold an existing native pipe.+ *+ * @param native_pipe A native pipe.+ *+ * @throws asio::system_error Thrown on failure.+ */+ void assign(const native_handle_type& native_pipe)+ {+ asio::error_code ec;+ impl_.get_service().assign(impl_.get_implementation(), native_pipe, ec);+ asio::detail::throw_error(ec, "assign");+ }++ /// Assign an existing native pipe to the pipe.+ /*+ * This function opens the pipe to hold an existing native pipe.+ *+ * @param native_pipe A native pipe.+ *+ * @param ec Set to indicate what error occurred, if any.+ */+ ASIO_SYNC_OP_VOID assign(const native_handle_type& native_pipe,+ asio::error_code& ec)+ {+ impl_.get_service().assign(impl_.get_implementation(), native_pipe, ec);+ ASIO_SYNC_OP_VOID_RETURN(ec);+ }++ /// Determine whether the pipe is open.+ bool is_open() const+ {+ return impl_.get_service().is_open(impl_.get_implementation());+ }++ /// Close the pipe.+ /**+ * This function is used to close the pipe. Any asynchronous write operations+ * will be cancelled immediately, and will complete with the+ * asio::error::operation_aborted error.+ *+ * @throws asio::system_error Thrown on failure.+ */+ void close()+ {+ asio::error_code ec;+ impl_.get_service().close(impl_.get_implementation(), ec);+ asio::detail::throw_error(ec, "close");+ }++ /// Close the pipe.+ /**+ * This function is used to close the pipe. Any asynchronous write operations+ * will be cancelled immediately, and will complete with the+ * asio::error::operation_aborted error.+ *+ * @param ec Set to indicate what error occurred, if any.+ */+ ASIO_SYNC_OP_VOID close(asio::error_code& ec)+ {+ impl_.get_service().close(impl_.get_implementation(), ec);+ ASIO_SYNC_OP_VOID_RETURN(ec);+ }++ /// Release ownership of the underlying native pipe.+ /**+ * This function causes all outstanding asynchronous write operations to+ * finish immediately, and the handlers for cancelled operations will be+ * passed the asio::error::operation_aborted error. Ownership of the+ * native pipe is then transferred to the caller.+ *+ * @throws asio::system_error Thrown on failure.+ *+ * @note This function is unsupported on Windows versions prior to Windows+ * 8.1, and will fail with asio::error::operation_not_supported on+ * these platforms.+ */+#if defined(ASIO_MSVC) && (ASIO_MSVC >= 1400) \+ && (!defined(_WIN32_WINNT) || _WIN32_WINNT < 0x0603)+ __declspec(deprecated("This function always fails with "+ "operation_not_supported when used on Windows versions "+ "prior to Windows 8.1."))+#endif+ native_handle_type release()+ {+ asio::error_code ec;+ native_handle_type s = impl_.get_service().release(+ impl_.get_implementation(), ec);+ asio::detail::throw_error(ec, "release");+ return s;+ }++ /// Release ownership of the underlying native pipe.+ /**+ * This function causes all outstanding asynchronous write operations to+ * finish immediately, and the handlers for cancelled operations will be+ * passed the asio::error::operation_aborted error. Ownership of the+ * native pipe is then transferred to the caller.+ *+ * @param ec Set to indicate what error occurred, if any.+ *+ * @note This function is unsupported on Windows versions prior to Windows+ * 8.1, and will fail with asio::error::operation_not_supported on+ * these platforms.+ */+#if defined(ASIO_MSVC) && (ASIO_MSVC >= 1400) \+ && (!defined(_WIN32_WINNT) || _WIN32_WINNT < 0x0603)+ __declspec(deprecated("This function always fails with "+ "operation_not_supported when used on Windows versions "+ "prior to Windows 8.1."))+#endif+ native_handle_type release(asio::error_code& ec)+ {+ return impl_.get_service().release(impl_.get_implementation(), ec);+ }++ /// Get the native pipe representation.+ /**+ * This function may be used to obtain the underlying representation of the+ * pipe. This is intended to allow access to native pipe+ * functionality that is not otherwise provided.+ */+ native_handle_type native_handle()+ {+ return impl_.get_service().native_handle(impl_.get_implementation());+ }++ /// Cancel all asynchronous operations associated with the pipe.+ /**+ * This function causes all outstanding asynchronous write operations to+ * finish immediately, and the handlers for cancelled operations will be+ * passed the asio::error::operation_aborted error.+ *+ * @throws asio::system_error Thrown on failure.+ */+ void cancel()+ {+ asio::error_code ec;+ impl_.get_service().cancel(impl_.get_implementation(), ec);+ asio::detail::throw_error(ec, "cancel");+ }++ /// Cancel all asynchronous operations associated with the pipe.+ /**+ * This function causes all outstanding asynchronous write operations to+ * finish immediately, and the handlers for cancelled operations will be+ * passed the asio::error::operation_aborted error.+ *+ * @param ec Set to indicate what error occurred, if any.+ */+ ASIO_SYNC_OP_VOID cancel(asio::error_code& ec)+ {+ impl_.get_service().cancel(impl_.get_implementation(), ec);+ ASIO_SYNC_OP_VOID_RETURN(ec);+ }++ /// Write some data to the pipe.+ /**+ * This function is used to write data to the pipe. The function call will+ * block until one or more bytes of the data has been written successfully,+ * or until an error occurs.+ *+ * @param buffers One or more data buffers to be written to the pipe.+ *+ * @returns The number of bytes written.+ *+ * @throws asio::system_error Thrown on failure. An error code of+ * asio::error::eof indicates that the connection was closed by the+ * peer.+ *+ * @note The write_some operation may not transmit all of the data to the+ * peer. Consider using the @ref write function if you need to ensure that+ * all data is written before the blocking operation completes.+ *+ * @par Example+ * To write a single data buffer use the @ref buffer function as follows:+ * @code+ * pipe.write_some(asio::buffer(data, size));+ * @endcode+ * See the @ref buffer documentation for information on writing multiple+ * buffers in one go, and how to use it with arrays, boost::array or+ * std::vector.+ */+ template <typename ConstBufferSequence>+ std::size_t write_some(const ConstBufferSequence& buffers)+ {+ asio::error_code ec;+ std::size_t s = impl_.get_service().write_some(+ impl_.get_implementation(), buffers, ec);+ asio::detail::throw_error(ec, "write_some");+ return s;+ }++ /// Write some data to the pipe.+ /**+ * This function is used to write data to the pipe. The function call will+ * block until one or more bytes of the data has been written successfully,+ * or until an error occurs.+ *+ * @param buffers One or more data buffers to be written to the pipe.+ *+ * @param ec Set to indicate what error occurred, if any.+ *+ * @returns The number of bytes written. Returns 0 if an error occurred.+ *+ * @note The write_some operation may not transmit all of the data to the+ * peer. Consider using the @ref write function if you need to ensure that+ * all data is written before the blocking operation completes.+ */+ template <typename ConstBufferSequence>+ std::size_t write_some(const ConstBufferSequence& buffers,+ asio::error_code& ec)+ {+ return impl_.get_service().write_some(+ impl_.get_implementation(), buffers, ec);+ }++ /// Start an asynchronous write.+ /**+ * This function is used to asynchronously write data to the pipe. It is an+ * initiating function for an @ref asynchronous_operation, and always returns+ * immediately.+ *+ * @param buffers One or more data buffers to be written to the pipe.+ * Although the buffers object may be copied as necessary, ownership of the+ * underlying memory blocks is retained by the caller, which must guarantee+ * that they remain valid until the completion handler is called.+ *+ * @param token The @ref completion_token that will be used to produce a+ * completion handler, which will be called when the write completes.+ * Potential completion tokens include @ref use_future, @ref use_awaitable,+ * @ref yield_context, or a function object with the correct completion+ * signature. The function signature of the completion handler must be:+ * @code void handler(+ * const asio::error_code& error, // Result of operation.+ * std::size_t bytes_transferred // Number of bytes written.+ * ); @endcode+ * Regardless of whether the asynchronous operation completes immediately or+ * not, the completion handler will not be invoked from within this function.+ * On immediate completion, invocation of the handler will be performed in a+ * manner equivalent to using asio::post().+ *+ * @par Completion Signature+ * @code void(asio::error_code, std::size_t) @endcode+ *+ * @note The write operation may not transmit all of the data to the peer.+ * Consider using the @ref async_write function if you need to ensure that all+ * data is written before the asynchronous operation completes.+ *+ * @par Example+ * To write a single data buffer use the @ref buffer function as follows:+ * @code+ * pipe.async_write_some(asio::buffer(data, size), handler);+ * @endcode+ * See the @ref buffer documentation for information on writing multiple+ * buffers in one go, and how to use it with arrays, boost::array or+ * std::vector.+ */+ template <typename ConstBufferSequence,+ ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code,+ std::size_t)) WriteToken+ ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(executor_type)>+ ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX(WriteToken,+ void (asio::error_code, std::size_t))+ async_write_some(const ConstBufferSequence& buffers,+ ASIO_MOVE_ARG(WriteToken) token+ ASIO_DEFAULT_COMPLETION_TOKEN(executor_type))+ ASIO_INITFN_AUTO_RESULT_TYPE_SUFFIX((+ async_initiate<WriteToken,+ void (asio::error_code, std::size_t)>(+ declval<initiate_async_write_some>(), token, buffers)))+ {+ return async_initiate<WriteToken,+ void (asio::error_code, std::size_t)>(+ initiate_async_write_some(this), token, buffers);+ }++private:+ // Disallow copying and assignment.+ basic_writable_pipe(const basic_writable_pipe&) ASIO_DELETED;+ basic_writable_pipe& operator=(const basic_writable_pipe&) ASIO_DELETED;++ class initiate_async_write_some+ {+ public:+ typedef Executor executor_type;++ explicit initiate_async_write_some(basic_writable_pipe* self)+ : self_(self)+ {+ }++ const executor_type& get_executor() const ASIO_NOEXCEPT+ {+ return self_->get_executor();+ }++ template <typename WriteHandler, typename ConstBufferSequence>+ void operator()(ASIO_MOVE_ARG(WriteHandler) handler,+ const ConstBufferSequence& buffers) const+ {+ // If you get an error on the following line it means that your handler+ // does not meet the documented type requirements for a WriteHandler.+ ASIO_WRITE_HANDLER_CHECK(WriteHandler, handler) type_check;++ detail::non_const_lvalue<WriteHandler> handler2(handler);+ self_->impl_.get_service().async_write_some(+ self_->impl_.get_implementation(), buffers,+ handler2.value, self_->impl_.get_executor());+ }++ private:+ basic_writable_pipe* self_;+ };++#if defined(ASIO_HAS_IOCP)+ detail::io_object_impl<detail::win_iocp_handle_service, Executor> impl_;+#elif defined(ASIO_HAS_IO_URING_AS_DEFAULT)+ detail::io_object_impl<detail::io_uring_descriptor_service, Executor> impl_;+#else+ detail::io_object_impl<detail::reactive_descriptor_service, Executor> impl_;+#endif+};++} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // defined(ASIO_HAS_PIPE)+ // || defined(GENERATING_DOCUMENTATION)++#endif // ASIO_BASIC_WRITABLE_PIPE_HPP
+ link/modules/asio-standalone/asio/include/asio/bind_allocator.hpp view
@@ -0,0 +1,733 @@+//+// bind_allocator.hpp+// ~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com)+//+// Distributed under the Boost Software License, Version 1.0. (See accompanying+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)+//++#ifndef ASIO_BIND_ALLOCATOR_HPP+#define ASIO_BIND_ALLOCATOR_HPP++#if defined(_MSC_VER) && (_MSC_VER >= 1200)+# pragma once+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)++#include "asio/detail/config.hpp"+#include "asio/detail/type_traits.hpp"+#include "asio/detail/variadic_templates.hpp"+#include "asio/associated_allocator.hpp"+#include "asio/associator.hpp"+#include "asio/async_result.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {+namespace detail {++// Helper to automatically define nested typedef result_type.++template <typename T, typename = void>+struct allocator_binder_result_type+{+protected:+ typedef void result_type_or_void;+};++template <typename T>+struct allocator_binder_result_type<T,+ typename void_type<typename T::result_type>::type>+{+ typedef typename T::result_type result_type;+protected:+ typedef result_type result_type_or_void;+};++template <typename R>+struct allocator_binder_result_type<R(*)()>+{+ typedef R result_type;+protected:+ typedef result_type result_type_or_void;+};++template <typename R>+struct allocator_binder_result_type<R(&)()>+{+ typedef R result_type;+protected:+ typedef result_type result_type_or_void;+};++template <typename R, typename A1>+struct allocator_binder_result_type<R(*)(A1)>+{+ typedef R result_type;+protected:+ typedef result_type result_type_or_void;+};++template <typename R, typename A1>+struct allocator_binder_result_type<R(&)(A1)>+{+ typedef R result_type;+protected:+ typedef result_type result_type_or_void;+};++template <typename R, typename A1, typename A2>+struct allocator_binder_result_type<R(*)(A1, A2)>+{+ typedef R result_type;+protected:+ typedef result_type result_type_or_void;+};++template <typename R, typename A1, typename A2>+struct allocator_binder_result_type<R(&)(A1, A2)>+{+ typedef R result_type;+protected:+ typedef result_type result_type_or_void;+};++// Helper to automatically define nested typedef argument_type.++template <typename T, typename = void>+struct allocator_binder_argument_type {};++template <typename T>+struct allocator_binder_argument_type<T,+ typename void_type<typename T::argument_type>::type>+{+ typedef typename T::argument_type argument_type;+};++template <typename R, typename A1>+struct allocator_binder_argument_type<R(*)(A1)>+{+ typedef A1 argument_type;+};++template <typename R, typename A1>+struct allocator_binder_argument_type<R(&)(A1)>+{+ typedef A1 argument_type;+};++// Helper to automatically define nested typedefs first_argument_type and+// second_argument_type.++template <typename T, typename = void>+struct allocator_binder_argument_types {};++template <typename T>+struct allocator_binder_argument_types<T,+ typename void_type<typename T::first_argument_type>::type>+{+ typedef typename T::first_argument_type first_argument_type;+ typedef typename T::second_argument_type second_argument_type;+};++template <typename R, typename A1, typename A2>+struct allocator_binder_argument_type<R(*)(A1, A2)>+{+ typedef A1 first_argument_type;+ typedef A2 second_argument_type;+};++template <typename R, typename A1, typename A2>+struct allocator_binder_argument_type<R(&)(A1, A2)>+{+ typedef A1 first_argument_type;+ typedef A2 second_argument_type;+};++// Helper to enable SFINAE on zero-argument operator() below.++template <typename T, typename = void>+struct allocator_binder_result_of0+{+ typedef void type;+};++template <typename T>+struct allocator_binder_result_of0<T,+ typename void_type<typename result_of<T()>::type>::type>+{+ typedef typename result_of<T()>::type type;+};++} // namespace detail++/// A call wrapper type to bind an allocator of type @c Allocator+/// to an object of type @c T.+template <typename T, typename Allocator>+class allocator_binder+#if !defined(GENERATING_DOCUMENTATION)+ : public detail::allocator_binder_result_type<T>,+ public detail::allocator_binder_argument_type<T>,+ public detail::allocator_binder_argument_types<T>+#endif // !defined(GENERATING_DOCUMENTATION)+{+public:+ /// The type of the target object.+ typedef T target_type;++ /// The type of the associated allocator.+ typedef Allocator allocator_type;++#if defined(GENERATING_DOCUMENTATION)+ /// The return type if a function.+ /**+ * The type of @c result_type is based on the type @c T of the wrapper's+ * target object:+ *+ * @li if @c T is a pointer to function type, @c result_type is a synonym for+ * the return type of @c T;+ *+ * @li if @c T is a class type with a member type @c result_type, then @c+ * result_type is a synonym for @c T::result_type;+ *+ * @li otherwise @c result_type is not defined.+ */+ typedef see_below result_type;++ /// The type of the function's argument.+ /**+ * The type of @c argument_type is based on the type @c T of the wrapper's+ * target object:+ *+ * @li if @c T is a pointer to a function type accepting a single argument,+ * @c argument_type is a synonym for the return type of @c T;+ *+ * @li if @c T is a class type with a member type @c argument_type, then @c+ * argument_type is a synonym for @c T::argument_type;+ *+ * @li otherwise @c argument_type is not defined.+ */+ typedef see_below argument_type;++ /// The type of the function's first argument.+ /**+ * The type of @c first_argument_type is based on the type @c T of the+ * wrapper's target object:+ *+ * @li if @c T is a pointer to a function type accepting two arguments, @c+ * first_argument_type is a synonym for the return type of @c T;+ *+ * @li if @c T is a class type with a member type @c first_argument_type,+ * then @c first_argument_type is a synonym for @c T::first_argument_type;+ *+ * @li otherwise @c first_argument_type is not defined.+ */+ typedef see_below first_argument_type;++ /// The type of the function's second argument.+ /**+ * The type of @c second_argument_type is based on the type @c T of the+ * wrapper's target object:+ *+ * @li if @c T is a pointer to a function type accepting two arguments, @c+ * second_argument_type is a synonym for the return type of @c T;+ *+ * @li if @c T is a class type with a member type @c first_argument_type,+ * then @c second_argument_type is a synonym for @c T::second_argument_type;+ *+ * @li otherwise @c second_argument_type is not defined.+ */+ typedef see_below second_argument_type;+#endif // defined(GENERATING_DOCUMENTATION)++ /// Construct an allocator wrapper for the specified object.+ /**+ * This constructor is only valid if the type @c T is constructible from type+ * @c U.+ */+ template <typename U>+ allocator_binder(const allocator_type& s,+ ASIO_MOVE_ARG(U) u)+ : allocator_(s),+ target_(ASIO_MOVE_CAST(U)(u))+ {+ }++ /// Copy constructor.+ allocator_binder(const allocator_binder& other)+ : allocator_(other.get_allocator()),+ target_(other.get())+ {+ }++ /// Construct a copy, but specify a different allocator.+ allocator_binder(const allocator_type& s,+ const allocator_binder& other)+ : allocator_(s),+ target_(other.get())+ {+ }++ /// Construct a copy of a different allocator wrapper type.+ /**+ * This constructor is only valid if the @c Allocator type is+ * constructible from type @c OtherAllocator, and the type @c T is+ * constructible from type @c U.+ */+ template <typename U, typename OtherAllocator>+ allocator_binder(+ const allocator_binder<U, OtherAllocator>& other)+ : allocator_(other.get_allocator()),+ target_(other.get())+ {+ }++ /// Construct a copy of a different allocator wrapper type, but+ /// specify a different allocator.+ /**+ * This constructor is only valid if the type @c T is constructible from type+ * @c U.+ */+ template <typename U, typename OtherAllocator>+ allocator_binder(const allocator_type& s,+ const allocator_binder<U, OtherAllocator>& other)+ : allocator_(s),+ target_(other.get())+ {+ }++#if defined(ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)++ /// Move constructor.+ allocator_binder(allocator_binder&& other)+ : allocator_(ASIO_MOVE_CAST(allocator_type)(+ other.get_allocator())),+ target_(ASIO_MOVE_CAST(T)(other.get()))+ {+ }++ /// Move construct the target object, but specify a different allocator.+ allocator_binder(const allocator_type& s,+ allocator_binder&& other)+ : allocator_(s),+ target_(ASIO_MOVE_CAST(T)(other.get()))+ {+ }++ /// Move construct from a different allocator wrapper type.+ template <typename U, typename OtherAllocator>+ allocator_binder(+ allocator_binder<U, OtherAllocator>&& other)+ : allocator_(ASIO_MOVE_CAST(OtherAllocator)(+ other.get_allocator())),+ target_(ASIO_MOVE_CAST(U)(other.get()))+ {+ }++ /// Move construct from a different allocator wrapper type, but+ /// specify a different allocator.+ template <typename U, typename OtherAllocator>+ allocator_binder(const allocator_type& s,+ allocator_binder<U, OtherAllocator>&& other)+ : allocator_(s),+ target_(ASIO_MOVE_CAST(U)(other.get()))+ {+ }++#endif // defined(ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)++ /// Destructor.+ ~allocator_binder()+ {+ }++ /// Obtain a reference to the target object.+ target_type& get() ASIO_NOEXCEPT+ {+ return target_;+ }++ /// Obtain a reference to the target object.+ const target_type& get() const ASIO_NOEXCEPT+ {+ return target_;+ }++ /// Obtain the associated allocator.+ allocator_type get_allocator() const ASIO_NOEXCEPT+ {+ return allocator_;+ }++#if defined(GENERATING_DOCUMENTATION)++ template <typename... Args> auto operator()(Args&& ...);+ template <typename... Args> auto operator()(Args&& ...) const;++#elif defined(ASIO_HAS_VARIADIC_TEMPLATES)++ /// Forwarding function call operator.+ template <typename... Args>+ typename result_of<T(Args...)>::type operator()(+ ASIO_MOVE_ARG(Args)... args)+ {+ return target_(ASIO_MOVE_CAST(Args)(args)...);+ }++ /// Forwarding function call operator.+ template <typename... Args>+ typename result_of<T(Args...)>::type operator()(+ ASIO_MOVE_ARG(Args)... args) const+ {+ return target_(ASIO_MOVE_CAST(Args)(args)...);+ }++#elif defined(ASIO_HAS_STD_TYPE_TRAITS) && !defined(_MSC_VER)++ typename detail::allocator_binder_result_of0<T>::type operator()()+ {+ return target_();+ }++ typename detail::allocator_binder_result_of0<T>::type+ operator()() const+ {+ return target_();+ }++#define ASIO_PRIVATE_BINDER_CALL_DEF(n) \+ template <ASIO_VARIADIC_TPARAMS(n)> \+ typename result_of<T(ASIO_VARIADIC_TARGS(n))>::type operator()( \+ ASIO_VARIADIC_MOVE_PARAMS(n)) \+ { \+ return target_(ASIO_VARIADIC_MOVE_ARGS(n)); \+ } \+ \+ template <ASIO_VARIADIC_TPARAMS(n)> \+ typename result_of<T(ASIO_VARIADIC_TARGS(n))>::type operator()( \+ ASIO_VARIADIC_MOVE_PARAMS(n)) const \+ { \+ return target_(ASIO_VARIADIC_MOVE_ARGS(n)); \+ } \+ /**/+ ASIO_VARIADIC_GENERATE(ASIO_PRIVATE_BINDER_CALL_DEF)+#undef ASIO_PRIVATE_BINDER_CALL_DEF++#else // defined(ASIO_HAS_STD_TYPE_TRAITS) && !defined(_MSC_VER)++ typedef typename detail::allocator_binder_result_type<+ T>::result_type_or_void result_type_or_void;++ result_type_or_void operator()()+ {+ return target_();+ }++ result_type_or_void operator()() const+ {+ return target_();+ }++#define ASIO_PRIVATE_BINDER_CALL_DEF(n) \+ template <ASIO_VARIADIC_TPARAMS(n)> \+ result_type_or_void operator()( \+ ASIO_VARIADIC_MOVE_PARAMS(n)) \+ { \+ return target_(ASIO_VARIADIC_MOVE_ARGS(n)); \+ } \+ \+ template <ASIO_VARIADIC_TPARAMS(n)> \+ result_type_or_void operator()( \+ ASIO_VARIADIC_MOVE_PARAMS(n)) const \+ { \+ return target_(ASIO_VARIADIC_MOVE_ARGS(n)); \+ } \+ /**/+ ASIO_VARIADIC_GENERATE(ASIO_PRIVATE_BINDER_CALL_DEF)+#undef ASIO_PRIVATE_BINDER_CALL_DEF++#endif // defined(ASIO_HAS_STD_TYPE_TRAITS) && !defined(_MSC_VER)++private:+ Allocator allocator_;+ T target_;+};++/// Associate an object of type @c T with an allocator of type+/// @c Allocator.+template <typename Allocator, typename T>+ASIO_NODISCARD inline allocator_binder<typename decay<T>::type, Allocator>+bind_allocator(const Allocator& s, ASIO_MOVE_ARG(T) t)+{+ return allocator_binder<+ typename decay<T>::type, Allocator>(+ s, ASIO_MOVE_CAST(T)(t));+}++#if !defined(GENERATING_DOCUMENTATION)++namespace detail {++template <typename TargetAsyncResult,+ typename Allocator, typename = void>+struct allocator_binder_async_result_completion_handler_type+{+};++template <typename TargetAsyncResult, typename Allocator>+struct allocator_binder_async_result_completion_handler_type<+ TargetAsyncResult, Allocator,+ typename void_type<+ typename TargetAsyncResult::completion_handler_type+ >::type>+{+ typedef allocator_binder<+ typename TargetAsyncResult::completion_handler_type, Allocator>+ completion_handler_type;+};++template <typename TargetAsyncResult, typename = void>+struct allocator_binder_async_result_return_type+{+};++template <typename TargetAsyncResult>+struct allocator_binder_async_result_return_type<+ TargetAsyncResult,+ typename void_type<+ typename TargetAsyncResult::return_type+ >::type>+{+ typedef typename TargetAsyncResult::return_type return_type;+};++} // namespace detail++template <typename T, typename Allocator, typename Signature>+class async_result<allocator_binder<T, Allocator>, Signature> :+ public detail::allocator_binder_async_result_completion_handler_type<+ async_result<T, Signature>, Allocator>,+ public detail::allocator_binder_async_result_return_type<+ async_result<T, Signature> >+{+public:+ explicit async_result(allocator_binder<T, Allocator>& b)+ : target_(b.get())+ {+ }++ typename async_result<T, Signature>::return_type get()+ {+ return target_.get();+ }++ template <typename Initiation>+ struct init_wrapper+ {+ template <typename Init>+ init_wrapper(const Allocator& allocator, ASIO_MOVE_ARG(Init) init)+ : allocator_(allocator),+ initiation_(ASIO_MOVE_CAST(Init)(init))+ {+ }++#if defined(ASIO_HAS_VARIADIC_TEMPLATES)++ template <typename Handler, typename... Args>+ void operator()(+ ASIO_MOVE_ARG(Handler) handler,+ ASIO_MOVE_ARG(Args)... args)+ {+ ASIO_MOVE_CAST(Initiation)(initiation_)(+ allocator_binder<+ typename decay<Handler>::type, Allocator>(+ allocator_, ASIO_MOVE_CAST(Handler)(handler)),+ ASIO_MOVE_CAST(Args)(args)...);+ }++ template <typename Handler, typename... Args>+ void operator()(+ ASIO_MOVE_ARG(Handler) handler,+ ASIO_MOVE_ARG(Args)... args) const+ {+ initiation_(+ allocator_binder<+ typename decay<Handler>::type, Allocator>(+ allocator_, ASIO_MOVE_CAST(Handler)(handler)),+ ASIO_MOVE_CAST(Args)(args)...);+ }++#else // defined(ASIO_HAS_VARIADIC_TEMPLATES)++ template <typename Handler>+ void operator()(+ ASIO_MOVE_ARG(Handler) handler)+ {+ ASIO_MOVE_CAST(Initiation)(initiation_)(+ allocator_binder<+ typename decay<Handler>::type, Allocator>(+ allocator_, ASIO_MOVE_CAST(Handler)(handler)));+ }++ template <typename Handler>+ void operator()(+ ASIO_MOVE_ARG(Handler) handler) const+ {+ initiation_(+ allocator_binder<+ typename decay<Handler>::type, Allocator>(+ allocator_, ASIO_MOVE_CAST(Handler)(handler)));+ }++#define ASIO_PRIVATE_INIT_WRAPPER_DEF(n) \+ template <typename Handler, ASIO_VARIADIC_TPARAMS(n)> \+ void operator()( \+ ASIO_MOVE_ARG(Handler) handler, \+ ASIO_VARIADIC_MOVE_PARAMS(n)) \+ { \+ ASIO_MOVE_CAST(Initiation)(initiation_)( \+ allocator_binder< \+ typename decay<Handler>::type, Allocator>( \+ allocator_, ASIO_MOVE_CAST(Handler)(handler)), \+ ASIO_VARIADIC_MOVE_ARGS(n)); \+ } \+ \+ template <typename Handler, ASIO_VARIADIC_TPARAMS(n)> \+ void operator()( \+ ASIO_MOVE_ARG(Handler) handler, \+ ASIO_VARIADIC_MOVE_PARAMS(n)) const \+ { \+ initiation_( \+ allocator_binder< \+ typename decay<Handler>::type, Allocator>( \+ allocator_, ASIO_MOVE_CAST(Handler)(handler)), \+ ASIO_VARIADIC_MOVE_ARGS(n)); \+ } \+ /**/+ ASIO_VARIADIC_GENERATE(ASIO_PRIVATE_INIT_WRAPPER_DEF)+#undef ASIO_PRIVATE_INIT_WRAPPER_DEF++#endif // defined(ASIO_HAS_VARIADIC_TEMPLATES)++ Allocator allocator_;+ Initiation initiation_;+ };++#if defined(ASIO_HAS_VARIADIC_TEMPLATES)++ template <typename Initiation, typename RawCompletionToken, typename... Args>+ static ASIO_INITFN_DEDUCED_RESULT_TYPE(T, Signature,+ (async_initiate<T, Signature>(+ declval<init_wrapper<typename decay<Initiation>::type> >(),+ declval<RawCompletionToken>().get(),+ declval<ASIO_MOVE_ARG(Args)>()...)))+ initiate(+ ASIO_MOVE_ARG(Initiation) initiation,+ ASIO_MOVE_ARG(RawCompletionToken) token,+ ASIO_MOVE_ARG(Args)... args)+ {+ return async_initiate<T, Signature>(+ init_wrapper<typename decay<Initiation>::type>(+ token.get_allocator(),+ ASIO_MOVE_CAST(Initiation)(initiation)),+ token.get(), ASIO_MOVE_CAST(Args)(args)...);+ }++#else // defined(ASIO_HAS_VARIADIC_TEMPLATES)++ template <typename Initiation, typename RawCompletionToken>+ static ASIO_INITFN_DEDUCED_RESULT_TYPE(T, Signature,+ (async_initiate<T, Signature>(+ declval<init_wrapper<typename decay<Initiation>::type> >(),+ declval<RawCompletionToken>().get())))+ initiate(+ ASIO_MOVE_ARG(Initiation) initiation,+ ASIO_MOVE_ARG(RawCompletionToken) token)+ {+ return async_initiate<T, Signature>(+ init_wrapper<typename decay<Initiation>::type>(+ token.get_allocator(),+ ASIO_MOVE_CAST(Initiation)(initiation)),+ token.get());+ }++#define ASIO_PRIVATE_INITIATE_DEF(n) \+ template <typename Initiation, typename RawCompletionToken, \+ ASIO_VARIADIC_TPARAMS(n)> \+ static ASIO_INITFN_DEDUCED_RESULT_TYPE(T, Signature, \+ (async_initiate<T, Signature>( \+ declval<init_wrapper<typename decay<Initiation>::type> >(), \+ declval<RawCompletionToken>().get(), \+ ASIO_VARIADIC_MOVE_DECLVAL(n)))) \+ initiate( \+ ASIO_MOVE_ARG(Initiation) initiation, \+ ASIO_MOVE_ARG(RawCompletionToken) token, \+ ASIO_VARIADIC_MOVE_PARAMS(n)) \+ { \+ return async_initiate<T, Signature>( \+ init_wrapper<typename decay<Initiation>::type>( \+ token.get_allocator(), \+ ASIO_MOVE_CAST(Initiation)(initiation)), \+ token.get(), ASIO_VARIADIC_MOVE_ARGS(n)); \+ } \+ /**/+ ASIO_VARIADIC_GENERATE(ASIO_PRIVATE_INITIATE_DEF)+#undef ASIO_PRIVATE_INITIATE_DEF++#endif // defined(ASIO_HAS_VARIADIC_TEMPLATES)++private:+ async_result(const async_result&) ASIO_DELETED;+ async_result& operator=(const async_result&) ASIO_DELETED;++ async_result<T, Signature> target_;+};++template <template <typename, typename> class Associator,+ typename T, typename Allocator, typename DefaultCandidate>+struct associator<Associator,+ allocator_binder<T, Allocator>,+ DefaultCandidate>+ : Associator<T, DefaultCandidate>+{+ static typename Associator<T, DefaultCandidate>::type+ get(const allocator_binder<T, Allocator>& b) ASIO_NOEXCEPT+ {+ return Associator<T, DefaultCandidate>::get(b.get());+ }++ static ASIO_AUTO_RETURN_TYPE_PREFIX2(+ typename Associator<T, DefaultCandidate>::type)+ get(const allocator_binder<T, Allocator>& b,+ const DefaultCandidate& c) ASIO_NOEXCEPT+ ASIO_AUTO_RETURN_TYPE_SUFFIX((+ Associator<T, DefaultCandidate>::get(b.get(), c)))+ {+ return Associator<T, DefaultCandidate>::get(b.get(), c);+ }+};++template <typename T, typename Allocator, typename Allocator1>+struct associated_allocator<+ allocator_binder<T, Allocator>,+ Allocator1>+{+ typedef Allocator type;++ static ASIO_AUTO_RETURN_TYPE_PREFIX(type) get(+ const allocator_binder<T, Allocator>& b,+ const Allocator1& = Allocator1()) ASIO_NOEXCEPT+ ASIO_AUTO_RETURN_TYPE_SUFFIX((b.get_allocator()))+ {+ return b.get_allocator();+ }+};++#endif // !defined(GENERATING_DOCUMENTATION)++} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // ASIO_BIND_ALLOCATOR_HPP
+ link/modules/asio-standalone/asio/include/asio/bind_cancellation_slot.hpp view
@@ -0,0 +1,736 @@+//+// bind_cancellation_slot.hpp+// ~~~~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com)+//+// Distributed under the Boost Software License, Version 1.0. (See accompanying+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)+//++#ifndef ASIO_BIND_CANCELLATION_SLOT_HPP+#define ASIO_BIND_CANCELLATION_SLOT_HPP++#if defined(_MSC_VER) && (_MSC_VER >= 1200)+# pragma once+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)++#include "asio/detail/config.hpp"+#include "asio/detail/type_traits.hpp"+#include "asio/detail/variadic_templates.hpp"+#include "asio/associated_cancellation_slot.hpp"+#include "asio/associator.hpp"+#include "asio/async_result.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {+namespace detail {++// Helper to automatically define nested typedef result_type.++template <typename T, typename = void>+struct cancellation_slot_binder_result_type+{+protected:+ typedef void result_type_or_void;+};++template <typename T>+struct cancellation_slot_binder_result_type<T,+ typename void_type<typename T::result_type>::type>+{+ typedef typename T::result_type result_type;+protected:+ typedef result_type result_type_or_void;+};++template <typename R>+struct cancellation_slot_binder_result_type<R(*)()>+{+ typedef R result_type;+protected:+ typedef result_type result_type_or_void;+};++template <typename R>+struct cancellation_slot_binder_result_type<R(&)()>+{+ typedef R result_type;+protected:+ typedef result_type result_type_or_void;+};++template <typename R, typename A1>+struct cancellation_slot_binder_result_type<R(*)(A1)>+{+ typedef R result_type;+protected:+ typedef result_type result_type_or_void;+};++template <typename R, typename A1>+struct cancellation_slot_binder_result_type<R(&)(A1)>+{+ typedef R result_type;+protected:+ typedef result_type result_type_or_void;+};++template <typename R, typename A1, typename A2>+struct cancellation_slot_binder_result_type<R(*)(A1, A2)>+{+ typedef R result_type;+protected:+ typedef result_type result_type_or_void;+};++template <typename R, typename A1, typename A2>+struct cancellation_slot_binder_result_type<R(&)(A1, A2)>+{+ typedef R result_type;+protected:+ typedef result_type result_type_or_void;+};++// Helper to automatically define nested typedef argument_type.++template <typename T, typename = void>+struct cancellation_slot_binder_argument_type {};++template <typename T>+struct cancellation_slot_binder_argument_type<T,+ typename void_type<typename T::argument_type>::type>+{+ typedef typename T::argument_type argument_type;+};++template <typename R, typename A1>+struct cancellation_slot_binder_argument_type<R(*)(A1)>+{+ typedef A1 argument_type;+};++template <typename R, typename A1>+struct cancellation_slot_binder_argument_type<R(&)(A1)>+{+ typedef A1 argument_type;+};++// Helper to automatically define nested typedefs first_argument_type and+// second_argument_type.++template <typename T, typename = void>+struct cancellation_slot_binder_argument_types {};++template <typename T>+struct cancellation_slot_binder_argument_types<T,+ typename void_type<typename T::first_argument_type>::type>+{+ typedef typename T::first_argument_type first_argument_type;+ typedef typename T::second_argument_type second_argument_type;+};++template <typename R, typename A1, typename A2>+struct cancellation_slot_binder_argument_type<R(*)(A1, A2)>+{+ typedef A1 first_argument_type;+ typedef A2 second_argument_type;+};++template <typename R, typename A1, typename A2>+struct cancellation_slot_binder_argument_type<R(&)(A1, A2)>+{+ typedef A1 first_argument_type;+ typedef A2 second_argument_type;+};++// Helper to enable SFINAE on zero-argument operator() below.++template <typename T, typename = void>+struct cancellation_slot_binder_result_of0+{+ typedef void type;+};++template <typename T>+struct cancellation_slot_binder_result_of0<T,+ typename void_type<typename result_of<T()>::type>::type>+{+ typedef typename result_of<T()>::type type;+};++} // namespace detail++/// A call wrapper type to bind a cancellation slot of type @c CancellationSlot+/// to an object of type @c T.+template <typename T, typename CancellationSlot>+class cancellation_slot_binder+#if !defined(GENERATING_DOCUMENTATION)+ : public detail::cancellation_slot_binder_result_type<T>,+ public detail::cancellation_slot_binder_argument_type<T>,+ public detail::cancellation_slot_binder_argument_types<T>+#endif // !defined(GENERATING_DOCUMENTATION)+{+public:+ /// The type of the target object.+ typedef T target_type;++ /// The type of the associated cancellation slot.+ typedef CancellationSlot cancellation_slot_type;++#if defined(GENERATING_DOCUMENTATION)+ /// The return type if a function.+ /**+ * The type of @c result_type is based on the type @c T of the wrapper's+ * target object:+ *+ * @li if @c T is a pointer to function type, @c result_type is a synonym for+ * the return type of @c T;+ *+ * @li if @c T is a class type with a member type @c result_type, then @c+ * result_type is a synonym for @c T::result_type;+ *+ * @li otherwise @c result_type is not defined.+ */+ typedef see_below result_type;++ /// The type of the function's argument.+ /**+ * The type of @c argument_type is based on the type @c T of the wrapper's+ * target object:+ *+ * @li if @c T is a pointer to a function type accepting a single argument,+ * @c argument_type is a synonym for the return type of @c T;+ *+ * @li if @c T is a class type with a member type @c argument_type, then @c+ * argument_type is a synonym for @c T::argument_type;+ *+ * @li otherwise @c argument_type is not defined.+ */+ typedef see_below argument_type;++ /// The type of the function's first argument.+ /**+ * The type of @c first_argument_type is based on the type @c T of the+ * wrapper's target object:+ *+ * @li if @c T is a pointer to a function type accepting two arguments, @c+ * first_argument_type is a synonym for the return type of @c T;+ *+ * @li if @c T is a class type with a member type @c first_argument_type,+ * then @c first_argument_type is a synonym for @c T::first_argument_type;+ *+ * @li otherwise @c first_argument_type is not defined.+ */+ typedef see_below first_argument_type;++ /// The type of the function's second argument.+ /**+ * The type of @c second_argument_type is based on the type @c T of the+ * wrapper's target object:+ *+ * @li if @c T is a pointer to a function type accepting two arguments, @c+ * second_argument_type is a synonym for the return type of @c T;+ *+ * @li if @c T is a class type with a member type @c first_argument_type,+ * then @c second_argument_type is a synonym for @c T::second_argument_type;+ *+ * @li otherwise @c second_argument_type is not defined.+ */+ typedef see_below second_argument_type;+#endif // defined(GENERATING_DOCUMENTATION)++ /// Construct a cancellation slot wrapper for the specified object.+ /**+ * This constructor is only valid if the type @c T is constructible from type+ * @c U.+ */+ template <typename U>+ cancellation_slot_binder(const cancellation_slot_type& s,+ ASIO_MOVE_ARG(U) u)+ : slot_(s),+ target_(ASIO_MOVE_CAST(U)(u))+ {+ }++ /// Copy constructor.+ cancellation_slot_binder(const cancellation_slot_binder& other)+ : slot_(other.get_cancellation_slot()),+ target_(other.get())+ {+ }++ /// Construct a copy, but specify a different cancellation slot.+ cancellation_slot_binder(const cancellation_slot_type& s,+ const cancellation_slot_binder& other)+ : slot_(s),+ target_(other.get())+ {+ }++ /// Construct a copy of a different cancellation slot wrapper type.+ /**+ * This constructor is only valid if the @c CancellationSlot type is+ * constructible from type @c OtherCancellationSlot, and the type @c T is+ * constructible from type @c U.+ */+ template <typename U, typename OtherCancellationSlot>+ cancellation_slot_binder(+ const cancellation_slot_binder<U, OtherCancellationSlot>& other)+ : slot_(other.get_cancellation_slot()),+ target_(other.get())+ {+ }++ /// Construct a copy of a different cancellation slot wrapper type, but+ /// specify a different cancellation slot.+ /**+ * This constructor is only valid if the type @c T is constructible from type+ * @c U.+ */+ template <typename U, typename OtherCancellationSlot>+ cancellation_slot_binder(const cancellation_slot_type& s,+ const cancellation_slot_binder<U, OtherCancellationSlot>& other)+ : slot_(s),+ target_(other.get())+ {+ }++#if defined(ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)++ /// Move constructor.+ cancellation_slot_binder(cancellation_slot_binder&& other)+ : slot_(ASIO_MOVE_CAST(cancellation_slot_type)(+ other.get_cancellation_slot())),+ target_(ASIO_MOVE_CAST(T)(other.get()))+ {+ }++ /// Move construct the target object, but specify a different cancellation+ /// slot.+ cancellation_slot_binder(const cancellation_slot_type& s,+ cancellation_slot_binder&& other)+ : slot_(s),+ target_(ASIO_MOVE_CAST(T)(other.get()))+ {+ }++ /// Move construct from a different cancellation slot wrapper type.+ template <typename U, typename OtherCancellationSlot>+ cancellation_slot_binder(+ cancellation_slot_binder<U, OtherCancellationSlot>&& other)+ : slot_(ASIO_MOVE_CAST(OtherCancellationSlot)(+ other.get_cancellation_slot())),+ target_(ASIO_MOVE_CAST(U)(other.get()))+ {+ }++ /// Move construct from a different cancellation slot wrapper type, but+ /// specify a different cancellation slot.+ template <typename U, typename OtherCancellationSlot>+ cancellation_slot_binder(const cancellation_slot_type& s,+ cancellation_slot_binder<U, OtherCancellationSlot>&& other)+ : slot_(s),+ target_(ASIO_MOVE_CAST(U)(other.get()))+ {+ }++#endif // defined(ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)++ /// Destructor.+ ~cancellation_slot_binder()+ {+ }++ /// Obtain a reference to the target object.+ target_type& get() ASIO_NOEXCEPT+ {+ return target_;+ }++ /// Obtain a reference to the target object.+ const target_type& get() const ASIO_NOEXCEPT+ {+ return target_;+ }++ /// Obtain the associated cancellation slot.+ cancellation_slot_type get_cancellation_slot() const ASIO_NOEXCEPT+ {+ return slot_;+ }++#if defined(GENERATING_DOCUMENTATION)++ template <typename... Args> auto operator()(Args&& ...);+ template <typename... Args> auto operator()(Args&& ...) const;++#elif defined(ASIO_HAS_VARIADIC_TEMPLATES)++ /// Forwarding function call operator.+ template <typename... Args>+ typename result_of<T(Args...)>::type operator()(+ ASIO_MOVE_ARG(Args)... args)+ {+ return target_(ASIO_MOVE_CAST(Args)(args)...);+ }++ /// Forwarding function call operator.+ template <typename... Args>+ typename result_of<T(Args...)>::type operator()(+ ASIO_MOVE_ARG(Args)... args) const+ {+ return target_(ASIO_MOVE_CAST(Args)(args)...);+ }++#elif defined(ASIO_HAS_STD_TYPE_TRAITS) && !defined(_MSC_VER)++ typename detail::cancellation_slot_binder_result_of0<T>::type operator()()+ {+ return target_();+ }++ typename detail::cancellation_slot_binder_result_of0<T>::type+ operator()() const+ {+ return target_();+ }++#define ASIO_PRIVATE_BINDER_CALL_DEF(n) \+ template <ASIO_VARIADIC_TPARAMS(n)> \+ typename result_of<T(ASIO_VARIADIC_TARGS(n))>::type operator()( \+ ASIO_VARIADIC_MOVE_PARAMS(n)) \+ { \+ return target_(ASIO_VARIADIC_MOVE_ARGS(n)); \+ } \+ \+ template <ASIO_VARIADIC_TPARAMS(n)> \+ typename result_of<T(ASIO_VARIADIC_TARGS(n))>::type operator()( \+ ASIO_VARIADIC_MOVE_PARAMS(n)) const \+ { \+ return target_(ASIO_VARIADIC_MOVE_ARGS(n)); \+ } \+ /**/+ ASIO_VARIADIC_GENERATE(ASIO_PRIVATE_BINDER_CALL_DEF)+#undef ASIO_PRIVATE_BINDER_CALL_DEF++#else // defined(ASIO_HAS_STD_TYPE_TRAITS) && !defined(_MSC_VER)++ typedef typename detail::cancellation_slot_binder_result_type<+ T>::result_type_or_void result_type_or_void;++ result_type_or_void operator()()+ {+ return target_();+ }++ result_type_or_void operator()() const+ {+ return target_();+ }++#define ASIO_PRIVATE_BINDER_CALL_DEF(n) \+ template <ASIO_VARIADIC_TPARAMS(n)> \+ result_type_or_void operator()( \+ ASIO_VARIADIC_MOVE_PARAMS(n)) \+ { \+ return target_(ASIO_VARIADIC_MOVE_ARGS(n)); \+ } \+ \+ template <ASIO_VARIADIC_TPARAMS(n)> \+ result_type_or_void operator()( \+ ASIO_VARIADIC_MOVE_PARAMS(n)) const \+ { \+ return target_(ASIO_VARIADIC_MOVE_ARGS(n)); \+ } \+ /**/+ ASIO_VARIADIC_GENERATE(ASIO_PRIVATE_BINDER_CALL_DEF)+#undef ASIO_PRIVATE_BINDER_CALL_DEF++#endif // defined(ASIO_HAS_STD_TYPE_TRAITS) && !defined(_MSC_VER)++private:+ CancellationSlot slot_;+ T target_;+};++/// Associate an object of type @c T with a cancellation slot of type+/// @c CancellationSlot.+template <typename CancellationSlot, typename T>+ASIO_NODISCARD inline+cancellation_slot_binder<typename decay<T>::type, CancellationSlot>+bind_cancellation_slot(const CancellationSlot& s, ASIO_MOVE_ARG(T) t)+{+ return cancellation_slot_binder<+ typename decay<T>::type, CancellationSlot>(+ s, ASIO_MOVE_CAST(T)(t));+}++#if !defined(GENERATING_DOCUMENTATION)++namespace detail {++template <typename TargetAsyncResult,+ typename CancellationSlot, typename = void>+struct cancellation_slot_binder_async_result_completion_handler_type+{+};++template <typename TargetAsyncResult, typename CancellationSlot>+struct cancellation_slot_binder_async_result_completion_handler_type<+ TargetAsyncResult, CancellationSlot,+ typename void_type<+ typename TargetAsyncResult::completion_handler_type+ >::type>+{+ typedef cancellation_slot_binder<+ typename TargetAsyncResult::completion_handler_type, CancellationSlot>+ completion_handler_type;+};++template <typename TargetAsyncResult, typename = void>+struct cancellation_slot_binder_async_result_return_type+{+};++template <typename TargetAsyncResult>+struct cancellation_slot_binder_async_result_return_type<+ TargetAsyncResult,+ typename void_type<+ typename TargetAsyncResult::return_type+ >::type>+{+ typedef typename TargetAsyncResult::return_type return_type;+};++} // namespace detail++template <typename T, typename CancellationSlot, typename Signature>+class async_result<cancellation_slot_binder<T, CancellationSlot>, Signature> :+ public detail::cancellation_slot_binder_async_result_completion_handler_type<+ async_result<T, Signature>, CancellationSlot>,+ public detail::cancellation_slot_binder_async_result_return_type<+ async_result<T, Signature> >+{+public:+ explicit async_result(cancellation_slot_binder<T, CancellationSlot>& b)+ : target_(b.get())+ {+ }++ typename async_result<T, Signature>::return_type get()+ {+ return target_.get();+ }++ template <typename Initiation>+ struct init_wrapper+ {+ template <typename Init>+ init_wrapper(const CancellationSlot& slot, ASIO_MOVE_ARG(Init) init)+ : slot_(slot),+ initiation_(ASIO_MOVE_CAST(Init)(init))+ {+ }++#if defined(ASIO_HAS_VARIADIC_TEMPLATES)++ template <typename Handler, typename... Args>+ void operator()(+ ASIO_MOVE_ARG(Handler) handler,+ ASIO_MOVE_ARG(Args)... args)+ {+ ASIO_MOVE_CAST(Initiation)(initiation_)(+ cancellation_slot_binder<+ typename decay<Handler>::type, CancellationSlot>(+ slot_, ASIO_MOVE_CAST(Handler)(handler)),+ ASIO_MOVE_CAST(Args)(args)...);+ }++ template <typename Handler, typename... Args>+ void operator()(+ ASIO_MOVE_ARG(Handler) handler,+ ASIO_MOVE_ARG(Args)... args) const+ {+ initiation_(+ cancellation_slot_binder<+ typename decay<Handler>::type, CancellationSlot>(+ slot_, ASIO_MOVE_CAST(Handler)(handler)),+ ASIO_MOVE_CAST(Args)(args)...);+ }++#else // defined(ASIO_HAS_VARIADIC_TEMPLATES)++ template <typename Handler>+ void operator()(+ ASIO_MOVE_ARG(Handler) handler)+ {+ ASIO_MOVE_CAST(Initiation)(initiation_)(+ cancellation_slot_binder<+ typename decay<Handler>::type, CancellationSlot>(+ slot_, ASIO_MOVE_CAST(Handler)(handler)));+ }++ template <typename Handler>+ void operator()(+ ASIO_MOVE_ARG(Handler) handler) const+ {+ initiation_(+ cancellation_slot_binder<+ typename decay<Handler>::type, CancellationSlot>(+ slot_, ASIO_MOVE_CAST(Handler)(handler)));+ }++#define ASIO_PRIVATE_INIT_WRAPPER_DEF(n) \+ template <typename Handler, ASIO_VARIADIC_TPARAMS(n)> \+ void operator()( \+ ASIO_MOVE_ARG(Handler) handler, \+ ASIO_VARIADIC_MOVE_PARAMS(n)) \+ { \+ ASIO_MOVE_CAST(Initiation)(initiation_)( \+ cancellation_slot_binder< \+ typename decay<Handler>::type, CancellationSlot>( \+ slot_, ASIO_MOVE_CAST(Handler)(handler)), \+ ASIO_VARIADIC_MOVE_ARGS(n)); \+ } \+ \+ template <typename Handler, ASIO_VARIADIC_TPARAMS(n)> \+ void operator()( \+ ASIO_MOVE_ARG(Handler) handler, \+ ASIO_VARIADIC_MOVE_PARAMS(n)) const \+ { \+ initiation_( \+ cancellation_slot_binder< \+ typename decay<Handler>::type, CancellationSlot>( \+ slot_, ASIO_MOVE_CAST(Handler)(handler)), \+ ASIO_VARIADIC_MOVE_ARGS(n)); \+ } \+ /**/+ ASIO_VARIADIC_GENERATE(ASIO_PRIVATE_INIT_WRAPPER_DEF)+#undef ASIO_PRIVATE_INIT_WRAPPER_DEF++#endif // defined(ASIO_HAS_VARIADIC_TEMPLATES)++ CancellationSlot slot_;+ Initiation initiation_;+ };++#if defined(ASIO_HAS_VARIADIC_TEMPLATES)++ template <typename Initiation, typename RawCompletionToken, typename... Args>+ static ASIO_INITFN_DEDUCED_RESULT_TYPE(T, Signature,+ (async_initiate<T, Signature>(+ declval<init_wrapper<typename decay<Initiation>::type> >(),+ declval<RawCompletionToken>().get(),+ declval<ASIO_MOVE_ARG(Args)>()...)))+ initiate(+ ASIO_MOVE_ARG(Initiation) initiation,+ ASIO_MOVE_ARG(RawCompletionToken) token,+ ASIO_MOVE_ARG(Args)... args)+ {+ return async_initiate<T, Signature>(+ init_wrapper<typename decay<Initiation>::type>(+ token.get_cancellation_slot(),+ ASIO_MOVE_CAST(Initiation)(initiation)),+ token.get(), ASIO_MOVE_CAST(Args)(args)...);+ }++#else // defined(ASIO_HAS_VARIADIC_TEMPLATES)++ template <typename Initiation, typename RawCompletionToken>+ static ASIO_INITFN_DEDUCED_RESULT_TYPE(T, Signature,+ (async_initiate<T, Signature>(+ declval<init_wrapper<typename decay<Initiation>::type> >(),+ declval<RawCompletionToken>().get())))+ initiate(+ ASIO_MOVE_ARG(Initiation) initiation,+ ASIO_MOVE_ARG(RawCompletionToken) token)+ {+ return async_initiate<T, Signature>(+ init_wrapper<typename decay<Initiation>::type>(+ token.get_cancellation_slot(),+ ASIO_MOVE_CAST(Initiation)(initiation)),+ token.get());+ }++#define ASIO_PRIVATE_INITIATE_DEF(n) \+ template <typename Initiation, typename RawCompletionToken, \+ ASIO_VARIADIC_TPARAMS(n)> \+ static ASIO_INITFN_DEDUCED_RESULT_TYPE(T, Signature, \+ (async_initiate<T, Signature>( \+ declval<init_wrapper<typename decay<Initiation>::type> >(), \+ declval<RawCompletionToken>().get(), \+ ASIO_VARIADIC_MOVE_DECLVAL(n)))) \+ initiate( \+ ASIO_MOVE_ARG(Initiation) initiation, \+ ASIO_MOVE_ARG(RawCompletionToken) token, \+ ASIO_VARIADIC_MOVE_PARAMS(n)) \+ { \+ return async_initiate<T, Signature>( \+ init_wrapper<typename decay<Initiation>::type>( \+ token.get_cancellation_slot(), \+ ASIO_MOVE_CAST(Initiation)(initiation)), \+ token.get(), ASIO_VARIADIC_MOVE_ARGS(n)); \+ } \+ /**/+ ASIO_VARIADIC_GENERATE(ASIO_PRIVATE_INITIATE_DEF)+#undef ASIO_PRIVATE_INITIATE_DEF++#endif // defined(ASIO_HAS_VARIADIC_TEMPLATES)++private:+ async_result(const async_result&) ASIO_DELETED;+ async_result& operator=(const async_result&) ASIO_DELETED;++ async_result<T, Signature> target_;+};++template <template <typename, typename> class Associator,+ typename T, typename CancellationSlot, typename DefaultCandidate>+struct associator<Associator,+ cancellation_slot_binder<T, CancellationSlot>,+ DefaultCandidate>+ : Associator<T, DefaultCandidate>+{+ static typename Associator<T, DefaultCandidate>::type+ get(const cancellation_slot_binder<T, CancellationSlot>& b)+ ASIO_NOEXCEPT+ {+ return Associator<T, DefaultCandidate>::get(b.get());+ }++ static ASIO_AUTO_RETURN_TYPE_PREFIX2(+ typename Associator<T, DefaultCandidate>::type)+ get(const cancellation_slot_binder<T, CancellationSlot>& b,+ const DefaultCandidate& c) ASIO_NOEXCEPT+ ASIO_AUTO_RETURN_TYPE_SUFFIX((+ Associator<T, DefaultCandidate>::get(b.get(), c)))+ {+ return Associator<T, DefaultCandidate>::get(b.get(), c);+ }+};++template <typename T, typename CancellationSlot, typename CancellationSlot1>+struct associated_cancellation_slot<+ cancellation_slot_binder<T, CancellationSlot>,+ CancellationSlot1>+{+ typedef CancellationSlot type;++ static ASIO_AUTO_RETURN_TYPE_PREFIX(type) get(+ const cancellation_slot_binder<T, CancellationSlot>& b,+ const CancellationSlot1& = CancellationSlot1()) ASIO_NOEXCEPT+ ASIO_AUTO_RETURN_TYPE_SUFFIX((b.get_cancellation_slot()))+ {+ return b.get_cancellation_slot();+ }+};++#endif // !defined(GENERATING_DOCUMENTATION)++} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // ASIO_BIND_CANCELLATION_SLOT_HPP
link/modules/asio-standalone/asio/include/asio/bind_executor.hpp view
@@ -2,7 +2,7 @@ // bind_executor.hpp // ~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -19,7 +19,7 @@ #include "asio/detail/type_traits.hpp" #include "asio/detail/variadic_templates.hpp" #include "asio/associated_executor.hpp"-#include "asio/associated_allocator.hpp"+#include "asio/associator.hpp" #include "asio/async_result.hpp" #include "asio/execution/executor.hpp" #include "asio/execution_context.hpp"@@ -486,11 +486,11 @@ /// Associate an object of type @c T with an executor of type @c Executor. template <typename Executor, typename T>-inline executor_binder<typename decay<T>::type, Executor>+ASIO_NODISCARD inline executor_binder<typename decay<T>::type, Executor> bind_executor(const Executor& ex, ASIO_MOVE_ARG(T) t,- typename enable_if<+ typename constraint< is_executor<Executor>::value || execution::is_executor<Executor>::value- >::type* = 0)+ >::type = 0) { return executor_binder<typename decay<T>::type, Executor>( executor_arg_t(), ex, ASIO_MOVE_CAST(T)(t));@@ -498,11 +498,11 @@ /// Associate an object of type @c T with an execution context's executor. template <typename ExecutionContext, typename T>-inline executor_binder<typename decay<T>::type,+ASIO_NODISCARD inline executor_binder<typename decay<T>::type, typename ExecutionContext::executor_type> bind_executor(ExecutionContext& ctx, ASIO_MOVE_ARG(T) t,- typename enable_if<is_convertible<- ExecutionContext&, execution_context&>::value>::type* = 0)+ typename constraint<is_convertible<+ ExecutionContext&, execution_context&>::value>::type = 0) { return executor_binder<typename decay<T>::type, typename ExecutionContext::executor_type>(@@ -515,42 +515,246 @@ struct uses_executor<executor_binder<T, Executor>, Executor> : true_type {}; -template <typename T, typename Executor, typename Signature>-class async_result<executor_binder<T, Executor>, Signature>+namespace detail {++template <typename TargetAsyncResult, typename Executor, typename = void>+class executor_binder_completion_handler_async_result { public:+ template <typename T>+ explicit executor_binder_completion_handler_async_result(T&)+ {+ }+};++template <typename TargetAsyncResult, typename Executor>+class executor_binder_completion_handler_async_result<+ TargetAsyncResult, Executor,+ typename void_type<+ typename TargetAsyncResult::completion_handler_type+ >::type>+{+public: typedef executor_binder<- typename async_result<T, Signature>::completion_handler_type, Executor>+ typename TargetAsyncResult::completion_handler_type, Executor> completion_handler_type; - typedef typename async_result<T, Signature>::return_type return_type;+ explicit executor_binder_completion_handler_async_result(+ typename TargetAsyncResult::completion_handler_type& handler)+ : target_(handler)+ {+ } + typename TargetAsyncResult::return_type get()+ {+ return target_.get();+ }++private:+ TargetAsyncResult target_;+};++template <typename TargetAsyncResult, typename = void>+struct executor_binder_async_result_return_type+{+};++template <typename TargetAsyncResult>+struct executor_binder_async_result_return_type<+ TargetAsyncResult,+ typename void_type<+ typename TargetAsyncResult::return_type+ >::type>+{+ typedef typename TargetAsyncResult::return_type return_type;+};++} // namespace detail++template <typename T, typename Executor, typename Signature>+class async_result<executor_binder<T, Executor>, Signature> :+ public detail::executor_binder_completion_handler_async_result<+ async_result<T, Signature>, Executor>,+ public detail::executor_binder_async_result_return_type<+ async_result<T, Signature> >+{+public: explicit async_result(executor_binder<T, Executor>& b)- : target_(b.get())+ : detail::executor_binder_completion_handler_async_result<+ async_result<T, Signature>, Executor>(b.get()) { } - return_type get()+ template <typename Initiation>+ struct init_wrapper {- return target_.get();+ template <typename Init>+ init_wrapper(const Executor& ex, ASIO_MOVE_ARG(Init) init)+ : ex_(ex),+ initiation_(ASIO_MOVE_CAST(Init)(init))+ {+ }++#if defined(ASIO_HAS_VARIADIC_TEMPLATES)++ template <typename Handler, typename... Args>+ void operator()(+ ASIO_MOVE_ARG(Handler) handler,+ ASIO_MOVE_ARG(Args)... args)+ {+ ASIO_MOVE_CAST(Initiation)(initiation_)(+ executor_binder<typename decay<Handler>::type, Executor>(+ executor_arg_t(), ex_, ASIO_MOVE_CAST(Handler)(handler)),+ ASIO_MOVE_CAST(Args)(args)...);+ }++ template <typename Handler, typename... Args>+ void operator()(+ ASIO_MOVE_ARG(Handler) handler,+ ASIO_MOVE_ARG(Args)... args) const+ {+ initiation_(+ executor_binder<typename decay<Handler>::type, Executor>(+ executor_arg_t(), ex_, ASIO_MOVE_CAST(Handler)(handler)),+ ASIO_MOVE_CAST(Args)(args)...);+ }++#else // defined(ASIO_HAS_VARIADIC_TEMPLATES)++ template <typename Handler>+ void operator()(+ ASIO_MOVE_ARG(Handler) handler)+ {+ ASIO_MOVE_CAST(Initiation)(initiation_)(+ executor_binder<typename decay<Handler>::type, Executor>(+ executor_arg_t(), ex_, ASIO_MOVE_CAST(Handler)(handler)));+ }++ template <typename Handler>+ void operator()(+ ASIO_MOVE_ARG(Handler) handler) const+ {+ initiation_(+ executor_binder<typename decay<Handler>::type, Executor>(+ executor_arg_t(), ex_, ASIO_MOVE_CAST(Handler)(handler)));+ }++#define ASIO_PRIVATE_INIT_WRAPPER_DEF(n) \+ template <typename Handler, ASIO_VARIADIC_TPARAMS(n)> \+ void operator()( \+ ASIO_MOVE_ARG(Handler) handler, \+ ASIO_VARIADIC_MOVE_PARAMS(n)) \+ { \+ ASIO_MOVE_CAST(Initiation)(initiation_)( \+ executor_binder<typename decay<Handler>::type, Executor>( \+ executor_arg_t(), ex_, ASIO_MOVE_CAST(Handler)(handler)), \+ ASIO_VARIADIC_MOVE_ARGS(n)); \+ } \+ \+ template <typename Handler, ASIO_VARIADIC_TPARAMS(n)> \+ void operator()( \+ ASIO_MOVE_ARG(Handler) handler, \+ ASIO_VARIADIC_MOVE_PARAMS(n)) const \+ { \+ initiation_( \+ executor_binder<typename decay<Handler>::type, Executor>( \+ executor_arg_t(), ex_, ASIO_MOVE_CAST(Handler)(handler)), \+ ASIO_VARIADIC_MOVE_ARGS(n)); \+ } \+ /**/+ ASIO_VARIADIC_GENERATE(ASIO_PRIVATE_INIT_WRAPPER_DEF)+#undef ASIO_PRIVATE_INIT_WRAPPER_DEF++#endif // defined(ASIO_HAS_VARIADIC_TEMPLATES)++ Executor ex_;+ Initiation initiation_;+ };++#if defined(ASIO_HAS_VARIADIC_TEMPLATES)++ template <typename Initiation, typename RawCompletionToken, typename... Args>+ static ASIO_INITFN_DEDUCED_RESULT_TYPE(T, Signature,+ (async_initiate<T, Signature>(+ declval<init_wrapper<typename decay<Initiation>::type> >(),+ declval<RawCompletionToken>().get(),+ declval<ASIO_MOVE_ARG(Args)>()...)))+ initiate(+ ASIO_MOVE_ARG(Initiation) initiation,+ ASIO_MOVE_ARG(RawCompletionToken) token,+ ASIO_MOVE_ARG(Args)... args)+ {+ return async_initiate<T, Signature>(+ init_wrapper<typename decay<Initiation>::type>(+ token.get_executor(), ASIO_MOVE_CAST(Initiation)(initiation)),+ token.get(), ASIO_MOVE_CAST(Args)(args)...); } +#else // defined(ASIO_HAS_VARIADIC_TEMPLATES)++ template <typename Initiation, typename RawCompletionToken>+ static ASIO_INITFN_DEDUCED_RESULT_TYPE(T, Signature,+ (async_initiate<T, Signature>(+ declval<init_wrapper<typename decay<Initiation>::type> >(),+ declval<RawCompletionToken>().get())))+ initiate(+ ASIO_MOVE_ARG(Initiation) initiation,+ ASIO_MOVE_ARG(RawCompletionToken) token)+ {+ return async_initiate<T, Signature>(+ init_wrapper<typename decay<Initiation>::type>(+ token.get_executor(), ASIO_MOVE_CAST(Initiation)(initiation)),+ token.get());+ }++#define ASIO_PRIVATE_INITIATE_DEF(n) \+ template <typename Initiation, typename RawCompletionToken, \+ ASIO_VARIADIC_TPARAMS(n)> \+ static ASIO_INITFN_DEDUCED_RESULT_TYPE(T, Signature, \+ (async_initiate<T, Signature>( \+ declval<init_wrapper<typename decay<Initiation>::type> >(), \+ declval<RawCompletionToken>().get(), \+ ASIO_VARIADIC_MOVE_DECLVAL(n)))) \+ initiate( \+ ASIO_MOVE_ARG(Initiation) initiation, \+ ASIO_MOVE_ARG(RawCompletionToken) token, \+ ASIO_VARIADIC_MOVE_PARAMS(n)) \+ { \+ return async_initiate<T, Signature>( \+ init_wrapper<typename decay<Initiation>::type>( \+ token.get_executor(), ASIO_MOVE_CAST(Initiation)(initiation)), \+ token.get(), ASIO_VARIADIC_MOVE_ARGS(n)); \+ } \+ /**/+ ASIO_VARIADIC_GENERATE(ASIO_PRIVATE_INITIATE_DEF)+#undef ASIO_PRIVATE_INITIATE_DEF++#endif // defined(ASIO_HAS_VARIADIC_TEMPLATES)+ private: async_result(const async_result&) ASIO_DELETED; async_result& operator=(const async_result&) ASIO_DELETED;-- async_result<T, Signature> target_; }; -template <typename T, typename Executor, typename Allocator>-struct associated_allocator<executor_binder<T, Executor>, Allocator>+template <template <typename, typename> class Associator,+ typename T, typename Executor, typename DefaultCandidate>+struct associator<Associator, executor_binder<T, Executor>, DefaultCandidate>+ : Associator<T, DefaultCandidate> {- typedef typename associated_allocator<T, Allocator>::type type;+ static typename Associator<T, DefaultCandidate>::type+ get(const executor_binder<T, Executor>& b) ASIO_NOEXCEPT+ {+ return Associator<T, DefaultCandidate>::get(b.get());+ } - static type get(const executor_binder<T, Executor>& b,- const Allocator& a = Allocator()) ASIO_NOEXCEPT+ static ASIO_AUTO_RETURN_TYPE_PREFIX2(+ typename Associator<T, DefaultCandidate>::type)+ get(const executor_binder<T, Executor>& b,+ const DefaultCandidate& c) ASIO_NOEXCEPT+ ASIO_AUTO_RETURN_TYPE_SUFFIX((+ Associator<T, DefaultCandidate>::get(b.get(), c))) {- return associated_allocator<T, Allocator>::get(b.get(), a);+ return Associator<T, DefaultCandidate>::get(b.get(), c); } }; @@ -559,8 +763,10 @@ { typedef Executor type; - static type get(const executor_binder<T, Executor>& b,+ static ASIO_AUTO_RETURN_TYPE_PREFIX(type) get(+ const executor_binder<T, Executor>& b, const Executor1& = Executor1()) ASIO_NOEXCEPT+ ASIO_AUTO_RETURN_TYPE_SUFFIX((b.get_executor())) { return b.get_executor(); }
+ link/modules/asio-standalone/asio/include/asio/bind_immediate_executor.hpp view
@@ -0,0 +1,736 @@+//+// bind_immediate_executor.hpp+// ~~~~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com)+//+// Distributed under the Boost Software License, Version 1.0. (See accompanying+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)+//++#ifndef ASIO_BIND_IMMEDIATE_EXECUTOR_HPP+#define ASIO_BIND_IMMEDIATE_EXECUTOR_HPP++#if defined(_MSC_VER) && (_MSC_VER >= 1200)+# pragma once+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)++#include "asio/detail/config.hpp"+#include "asio/detail/type_traits.hpp"+#include "asio/detail/variadic_templates.hpp"+#include "asio/associated_immediate_executor.hpp"+#include "asio/associator.hpp"+#include "asio/async_result.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {+namespace detail {++// Helper to automatically define nested typedef result_type.++template <typename T, typename = void>+struct immediate_executor_binder_result_type+{+protected:+ typedef void result_type_or_void;+};++template <typename T>+struct immediate_executor_binder_result_type<T,+ typename void_type<typename T::result_type>::type>+{+ typedef typename T::result_type result_type;+protected:+ typedef result_type result_type_or_void;+};++template <typename R>+struct immediate_executor_binder_result_type<R(*)()>+{+ typedef R result_type;+protected:+ typedef result_type result_type_or_void;+};++template <typename R>+struct immediate_executor_binder_result_type<R(&)()>+{+ typedef R result_type;+protected:+ typedef result_type result_type_or_void;+};++template <typename R, typename A1>+struct immediate_executor_binder_result_type<R(*)(A1)>+{+ typedef R result_type;+protected:+ typedef result_type result_type_or_void;+};++template <typename R, typename A1>+struct immediate_executor_binder_result_type<R(&)(A1)>+{+ typedef R result_type;+protected:+ typedef result_type result_type_or_void;+};++template <typename R, typename A1, typename A2>+struct immediate_executor_binder_result_type<R(*)(A1, A2)>+{+ typedef R result_type;+protected:+ typedef result_type result_type_or_void;+};++template <typename R, typename A1, typename A2>+struct immediate_executor_binder_result_type<R(&)(A1, A2)>+{+ typedef R result_type;+protected:+ typedef result_type result_type_or_void;+};++// Helper to automatically define nested typedef argument_type.++template <typename T, typename = void>+struct immediate_executor_binder_argument_type {};++template <typename T>+struct immediate_executor_binder_argument_type<T,+ typename void_type<typename T::argument_type>::type>+{+ typedef typename T::argument_type argument_type;+};++template <typename R, typename A1>+struct immediate_executor_binder_argument_type<R(*)(A1)>+{+ typedef A1 argument_type;+};++template <typename R, typename A1>+struct immediate_executor_binder_argument_type<R(&)(A1)>+{+ typedef A1 argument_type;+};++// Helper to automatically define nested typedefs first_argument_type and+// second_argument_type.++template <typename T, typename = void>+struct immediate_executor_binder_argument_types {};++template <typename T>+struct immediate_executor_binder_argument_types<T,+ typename void_type<typename T::first_argument_type>::type>+{+ typedef typename T::first_argument_type first_argument_type;+ typedef typename T::second_argument_type second_argument_type;+};++template <typename R, typename A1, typename A2>+struct immediate_executor_binder_argument_type<R(*)(A1, A2)>+{+ typedef A1 first_argument_type;+ typedef A2 second_argument_type;+};++template <typename R, typename A1, typename A2>+struct immediate_executor_binder_argument_type<R(&)(A1, A2)>+{+ typedef A1 first_argument_type;+ typedef A2 second_argument_type;+};++// Helper to enable SFINAE on zero-argument operator() below.++template <typename T, typename = void>+struct immediate_executor_binder_result_of0+{+ typedef void type;+};++template <typename T>+struct immediate_executor_binder_result_of0<T,+ typename void_type<typename result_of<T()>::type>::type>+{+ typedef typename result_of<T()>::type type;+};++} // namespace detail++/// A call wrapper type to bind a immediate executor of type @c Executor+/// to an object of type @c T.+template <typename T, typename Executor>+class immediate_executor_binder+#if !defined(GENERATING_DOCUMENTATION)+ : public detail::immediate_executor_binder_result_type<T>,+ public detail::immediate_executor_binder_argument_type<T>,+ public detail::immediate_executor_binder_argument_types<T>+#endif // !defined(GENERATING_DOCUMENTATION)+{+public:+ /// The type of the target object.+ typedef T target_type;++ /// The type of the associated immediate executor.+ typedef Executor immediate_executor_type;++#if defined(GENERATING_DOCUMENTATION)+ /// The return type if a function.+ /**+ * The type of @c result_type is based on the type @c T of the wrapper's+ * target object:+ *+ * @li if @c T is a pointer to function type, @c result_type is a synonym for+ * the return type of @c T;+ *+ * @li if @c T is a class type with a member type @c result_type, then @c+ * result_type is a synonym for @c T::result_type;+ *+ * @li otherwise @c result_type is not defined.+ */+ typedef see_below result_type;++ /// The type of the function's argument.+ /**+ * The type of @c argument_type is based on the type @c T of the wrapper's+ * target object:+ *+ * @li if @c T is a pointer to a function type accepting a single argument,+ * @c argument_type is a synonym for the return type of @c T;+ *+ * @li if @c T is a class type with a member type @c argument_type, then @c+ * argument_type is a synonym for @c T::argument_type;+ *+ * @li otherwise @c argument_type is not defined.+ */+ typedef see_below argument_type;++ /// The type of the function's first argument.+ /**+ * The type of @c first_argument_type is based on the type @c T of the+ * wrapper's target object:+ *+ * @li if @c T is a pointer to a function type accepting two arguments, @c+ * first_argument_type is a synonym for the return type of @c T;+ *+ * @li if @c T is a class type with a member type @c first_argument_type,+ * then @c first_argument_type is a synonym for @c T::first_argument_type;+ *+ * @li otherwise @c first_argument_type is not defined.+ */+ typedef see_below first_argument_type;++ /// The type of the function's second argument.+ /**+ * The type of @c second_argument_type is based on the type @c T of the+ * wrapper's target object:+ *+ * @li if @c T is a pointer to a function type accepting two arguments, @c+ * second_argument_type is a synonym for the return type of @c T;+ *+ * @li if @c T is a class type with a member type @c first_argument_type,+ * then @c second_argument_type is a synonym for @c T::second_argument_type;+ *+ * @li otherwise @c second_argument_type is not defined.+ */+ typedef see_below second_argument_type;+#endif // defined(GENERATING_DOCUMENTATION)++ /// Construct a immediate executor wrapper for the specified object.+ /**+ * This constructor is only valid if the type @c T is constructible from type+ * @c U.+ */+ template <typename U>+ immediate_executor_binder(const immediate_executor_type& e,+ ASIO_MOVE_ARG(U) u)+ : executor_(e),+ target_(ASIO_MOVE_CAST(U)(u))+ {+ }++ /// Copy constructor.+ immediate_executor_binder(const immediate_executor_binder& other)+ : executor_(other.get_immediate_executor()),+ target_(other.get())+ {+ }++ /// Construct a copy, but specify a different immediate executor.+ immediate_executor_binder(const immediate_executor_type& e,+ const immediate_executor_binder& other)+ : executor_(e),+ target_(other.get())+ {+ }++ /// Construct a copy of a different immediate executor wrapper type.+ /**+ * This constructor is only valid if the @c Executor type is+ * constructible from type @c OtherExecutor, and the type @c T is+ * constructible from type @c U.+ */+ template <typename U, typename OtherExecutor>+ immediate_executor_binder(+ const immediate_executor_binder<U, OtherExecutor>& other)+ : executor_(other.get_immediate_executor()),+ target_(other.get())+ {+ }++ /// Construct a copy of a different immediate executor wrapper type, but+ /// specify a different immediate executor.+ /**+ * This constructor is only valid if the type @c T is constructible from type+ * @c U.+ */+ template <typename U, typename OtherExecutor>+ immediate_executor_binder(const immediate_executor_type& e,+ const immediate_executor_binder<U, OtherExecutor>& other)+ : executor_(e),+ target_(other.get())+ {+ }++#if defined(ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)++ /// Move constructor.+ immediate_executor_binder(immediate_executor_binder&& other)+ : executor_(ASIO_MOVE_CAST(immediate_executor_type)(+ other.get_immediate_executor())),+ target_(ASIO_MOVE_CAST(T)(other.get()))+ {+ }++ /// Move construct the target object, but specify a different immediate+ /// executor.+ immediate_executor_binder(const immediate_executor_type& e,+ immediate_executor_binder&& other)+ : executor_(e),+ target_(ASIO_MOVE_CAST(T)(other.get()))+ {+ }++ /// Move construct from a different immediate executor wrapper type.+ template <typename U, typename OtherExecutor>+ immediate_executor_binder(+ immediate_executor_binder<U, OtherExecutor>&& other)+ : executor_(ASIO_MOVE_CAST(OtherExecutor)(+ other.get_immediate_executor())),+ target_(ASIO_MOVE_CAST(U)(other.get()))+ {+ }++ /// Move construct from a different immediate executor wrapper type, but+ /// specify a different immediate executor.+ template <typename U, typename OtherExecutor>+ immediate_executor_binder(const immediate_executor_type& e,+ immediate_executor_binder<U, OtherExecutor>&& other)+ : executor_(e),+ target_(ASIO_MOVE_CAST(U)(other.get()))+ {+ }++#endif // defined(ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)++ /// Destructor.+ ~immediate_executor_binder()+ {+ }++ /// Obtain a reference to the target object.+ target_type& get() ASIO_NOEXCEPT+ {+ return target_;+ }++ /// Obtain a reference to the target object.+ const target_type& get() const ASIO_NOEXCEPT+ {+ return target_;+ }++ /// Obtain the associated immediate executor.+ immediate_executor_type get_immediate_executor() const ASIO_NOEXCEPT+ {+ return executor_;+ }++#if defined(GENERATING_DOCUMENTATION)++ template <typename... Args> auto operator()(Args&& ...);+ template <typename... Args> auto operator()(Args&& ...) const;++#elif defined(ASIO_HAS_VARIADIC_TEMPLATES)++ /// Forwarding function call operator.+ template <typename... Args>+ typename result_of<T(Args...)>::type operator()(+ ASIO_MOVE_ARG(Args)... args)+ {+ return target_(ASIO_MOVE_CAST(Args)(args)...);+ }++ /// Forwarding function call operator.+ template <typename... Args>+ typename result_of<T(Args...)>::type operator()(+ ASIO_MOVE_ARG(Args)... args) const+ {+ return target_(ASIO_MOVE_CAST(Args)(args)...);+ }++#elif defined(ASIO_HAS_STD_TYPE_TRAITS) && !defined(_MSC_VER)++ typename detail::immediate_executor_binder_result_of0<T>::type operator()()+ {+ return target_();+ }++ typename detail::immediate_executor_binder_result_of0<T>::type+ operator()() const+ {+ return target_();+ }++#define ASIO_PRIVATE_BINDER_CALL_DEF(n) \+ template <ASIO_VARIADIC_TPARAMS(n)> \+ typename result_of<T(ASIO_VARIADIC_TARGS(n))>::type operator()( \+ ASIO_VARIADIC_MOVE_PARAMS(n)) \+ { \+ return target_(ASIO_VARIADIC_MOVE_ARGS(n)); \+ } \+ \+ template <ASIO_VARIADIC_TPARAMS(n)> \+ typename result_of<T(ASIO_VARIADIC_TARGS(n))>::type operator()( \+ ASIO_VARIADIC_MOVE_PARAMS(n)) const \+ { \+ return target_(ASIO_VARIADIC_MOVE_ARGS(n)); \+ } \+ /**/+ ASIO_VARIADIC_GENERATE(ASIO_PRIVATE_BINDER_CALL_DEF)+#undef ASIO_PRIVATE_BINDER_CALL_DEF++#else // defined(ASIO_HAS_STD_TYPE_TRAITS) && !defined(_MSC_VER)++ typedef typename detail::immediate_executor_binder_result_type<+ T>::result_type_or_void result_type_or_void;++ result_type_or_void operator()()+ {+ return target_();+ }++ result_type_or_void operator()() const+ {+ return target_();+ }++#define ASIO_PRIVATE_BINDER_CALL_DEF(n) \+ template <ASIO_VARIADIC_TPARAMS(n)> \+ result_type_or_void operator()( \+ ASIO_VARIADIC_MOVE_PARAMS(n)) \+ { \+ return target_(ASIO_VARIADIC_MOVE_ARGS(n)); \+ } \+ \+ template <ASIO_VARIADIC_TPARAMS(n)> \+ result_type_or_void operator()( \+ ASIO_VARIADIC_MOVE_PARAMS(n)) const \+ { \+ return target_(ASIO_VARIADIC_MOVE_ARGS(n)); \+ } \+ /**/+ ASIO_VARIADIC_GENERATE(ASIO_PRIVATE_BINDER_CALL_DEF)+#undef ASIO_PRIVATE_BINDER_CALL_DEF++#endif // defined(ASIO_HAS_STD_TYPE_TRAITS) && !defined(_MSC_VER)++private:+ Executor executor_;+ T target_;+};++/// Associate an object of type @c T with a immediate executor of type+/// @c Executor.+template <typename Executor, typename T>+ASIO_NODISCARD inline+immediate_executor_binder<typename decay<T>::type, Executor>+bind_immediate_executor(const Executor& e, ASIO_MOVE_ARG(T) t)+{+ return immediate_executor_binder<+ typename decay<T>::type, Executor>(+ e, ASIO_MOVE_CAST(T)(t));+}++#if !defined(GENERATING_DOCUMENTATION)++namespace detail {++template <typename TargetAsyncResult,+ typename Executor, typename = void>+struct immediate_executor_binder_async_result_completion_handler_type+{+};++template <typename TargetAsyncResult, typename Executor>+struct immediate_executor_binder_async_result_completion_handler_type<+ TargetAsyncResult, Executor,+ typename void_type<+ typename TargetAsyncResult::completion_handler_type+ >::type>+{+ typedef immediate_executor_binder<+ typename TargetAsyncResult::completion_handler_type, Executor>+ completion_handler_type;+};++template <typename TargetAsyncResult, typename = void>+struct immediate_executor_binder_async_result_return_type+{+};++template <typename TargetAsyncResult>+struct immediate_executor_binder_async_result_return_type<+ TargetAsyncResult,+ typename void_type<+ typename TargetAsyncResult::return_type+ >::type>+{+ typedef typename TargetAsyncResult::return_type return_type;+};++} // namespace detail++template <typename T, typename Executor, typename Signature>+class async_result<immediate_executor_binder<T, Executor>, Signature> :+ public detail::immediate_executor_binder_async_result_completion_handler_type<+ async_result<T, Signature>, Executor>,+ public detail::immediate_executor_binder_async_result_return_type<+ async_result<T, Signature> >+{+public:+ explicit async_result(immediate_executor_binder<T, Executor>& b)+ : target_(b.get())+ {+ }++ typename async_result<T, Signature>::return_type get()+ {+ return target_.get();+ }++ template <typename Initiation>+ struct init_wrapper+ {+ template <typename Init>+ init_wrapper(const Executor& e, ASIO_MOVE_ARG(Init) init)+ : executor_(e),+ initiation_(ASIO_MOVE_CAST(Init)(init))+ {+ }++#if defined(ASIO_HAS_VARIADIC_TEMPLATES)++ template <typename Handler, typename... Args>+ void operator()(+ ASIO_MOVE_ARG(Handler) handler,+ ASIO_MOVE_ARG(Args)... args)+ {+ ASIO_MOVE_CAST(Initiation)(initiation_)(+ immediate_executor_binder<+ typename decay<Handler>::type, Executor>(+ executor_, ASIO_MOVE_CAST(Handler)(handler)),+ ASIO_MOVE_CAST(Args)(args)...);+ }++ template <typename Handler, typename... Args>+ void operator()(+ ASIO_MOVE_ARG(Handler) handler,+ ASIO_MOVE_ARG(Args)... args) const+ {+ initiation_(+ immediate_executor_binder<+ typename decay<Handler>::type, Executor>(+ executor_, ASIO_MOVE_CAST(Handler)(handler)),+ ASIO_MOVE_CAST(Args)(args)...);+ }++#else // defined(ASIO_HAS_VARIADIC_TEMPLATES)++ template <typename Handler>+ void operator()(+ ASIO_MOVE_ARG(Handler) handler)+ {+ ASIO_MOVE_CAST(Initiation)(initiation_)(+ immediate_executor_binder<+ typename decay<Handler>::type, Executor>(+ executor_, ASIO_MOVE_CAST(Handler)(handler)));+ }++ template <typename Handler>+ void operator()(+ ASIO_MOVE_ARG(Handler) handler) const+ {+ initiation_(+ immediate_executor_binder<+ typename decay<Handler>::type, Executor>(+ executor_, ASIO_MOVE_CAST(Handler)(handler)));+ }++#define ASIO_PRIVATE_INIT_WRAPPER_DEF(n) \+ template <typename Handler, ASIO_VARIADIC_TPARAMS(n)> \+ void operator()( \+ ASIO_MOVE_ARG(Handler) handler, \+ ASIO_VARIADIC_MOVE_PARAMS(n)) \+ { \+ ASIO_MOVE_CAST(Initiation)(initiation_)( \+ immediate_executor_binder< \+ typename decay<Handler>::type, Executor>( \+ executor_, ASIO_MOVE_CAST(Handler)(handler)), \+ ASIO_VARIADIC_MOVE_ARGS(n)); \+ } \+ \+ template <typename Handler, ASIO_VARIADIC_TPARAMS(n)> \+ void operator()( \+ ASIO_MOVE_ARG(Handler) handler, \+ ASIO_VARIADIC_MOVE_PARAMS(n)) const \+ { \+ initiation_( \+ immediate_executor_binder< \+ typename decay<Handler>::type, Executor>( \+ executor_, ASIO_MOVE_CAST(Handler)(handler)), \+ ASIO_VARIADIC_MOVE_ARGS(n)); \+ } \+ /**/+ ASIO_VARIADIC_GENERATE(ASIO_PRIVATE_INIT_WRAPPER_DEF)+#undef ASIO_PRIVATE_INIT_WRAPPER_DEF++#endif // defined(ASIO_HAS_VARIADIC_TEMPLATES)++ Executor executor_;+ Initiation initiation_;+ };++#if defined(ASIO_HAS_VARIADIC_TEMPLATES)++ template <typename Initiation, typename RawCompletionToken, typename... Args>+ static ASIO_INITFN_DEDUCED_RESULT_TYPE(T, Signature,+ (async_initiate<T, Signature>(+ declval<init_wrapper<typename decay<Initiation>::type> >(),+ declval<RawCompletionToken>().get(),+ declval<ASIO_MOVE_ARG(Args)>()...)))+ initiate(+ ASIO_MOVE_ARG(Initiation) initiation,+ ASIO_MOVE_ARG(RawCompletionToken) token,+ ASIO_MOVE_ARG(Args)... args)+ {+ return async_initiate<T, Signature>(+ init_wrapper<typename decay<Initiation>::type>(+ token.get_immediate_executor(),+ ASIO_MOVE_CAST(Initiation)(initiation)),+ token.get(), ASIO_MOVE_CAST(Args)(args)...);+ }++#else // defined(ASIO_HAS_VARIADIC_TEMPLATES)++ template <typename Initiation, typename RawCompletionToken>+ static ASIO_INITFN_DEDUCED_RESULT_TYPE(T, Signature,+ (async_initiate<T, Signature>(+ declval<init_wrapper<typename decay<Initiation>::type> >(),+ declval<RawCompletionToken>().get())))+ initiate(+ ASIO_MOVE_ARG(Initiation) initiation,+ ASIO_MOVE_ARG(RawCompletionToken) token)+ {+ return async_initiate<T, Signature>(+ init_wrapper<typename decay<Initiation>::type>(+ token.get_immediate_executor(),+ ASIO_MOVE_CAST(Initiation)(initiation)),+ token.get());+ }++#define ASIO_PRIVATE_INITIATE_DEF(n) \+ template <typename Initiation, typename RawCompletionToken, \+ ASIO_VARIADIC_TPARAMS(n)> \+ static ASIO_INITFN_DEDUCED_RESULT_TYPE(T, Signature, \+ (async_initiate<T, Signature>( \+ declval<init_wrapper<typename decay<Initiation>::type> >(), \+ declval<RawCompletionToken>().get(), \+ ASIO_VARIADIC_MOVE_DECLVAL(n)))) \+ initiate( \+ ASIO_MOVE_ARG(Initiation) initiation, \+ ASIO_MOVE_ARG(RawCompletionToken) token, \+ ASIO_VARIADIC_MOVE_PARAMS(n)) \+ { \+ return async_initiate<T, Signature>( \+ init_wrapper<typename decay<Initiation>::type>( \+ token.get_immediate_executor(), \+ ASIO_MOVE_CAST(Initiation)(initiation)), \+ token.get(), ASIO_VARIADIC_MOVE_ARGS(n)); \+ } \+ /**/+ ASIO_VARIADIC_GENERATE(ASIO_PRIVATE_INITIATE_DEF)+#undef ASIO_PRIVATE_INITIATE_DEF++#endif // defined(ASIO_HAS_VARIADIC_TEMPLATES)++private:+ async_result(const async_result&) ASIO_DELETED;+ async_result& operator=(const async_result&) ASIO_DELETED;++ async_result<T, Signature> target_;+};++template <template <typename, typename> class Associator,+ typename T, typename Executor, typename DefaultCandidate>+struct associator<Associator,+ immediate_executor_binder<T, Executor>,+ DefaultCandidate>+ : Associator<T, DefaultCandidate>+{+ static typename Associator<T, DefaultCandidate>::type+ get(const immediate_executor_binder<T, Executor>& b)+ ASIO_NOEXCEPT+ {+ return Associator<T, DefaultCandidate>::get(b.get());+ }++ static ASIO_AUTO_RETURN_TYPE_PREFIX2(+ typename Associator<T, DefaultCandidate>::type)+ get(const immediate_executor_binder<T, Executor>& b,+ const DefaultCandidate& c) ASIO_NOEXCEPT+ ASIO_AUTO_RETURN_TYPE_SUFFIX((+ Associator<T, DefaultCandidate>::get(b.get(), c)))+ {+ return Associator<T, DefaultCandidate>::get(b.get(), c);+ }+};++template <typename T, typename Executor, typename Executor1>+struct associated_immediate_executor<+ immediate_executor_binder<T, Executor>,+ Executor1>+{+ typedef Executor type;++ static ASIO_AUTO_RETURN_TYPE_PREFIX(type) get(+ const immediate_executor_binder<T, Executor>& b,+ const Executor1& = Executor1()) ASIO_NOEXCEPT+ ASIO_AUTO_RETURN_TYPE_SUFFIX((b.get_immediate_executor()))+ {+ return b.get_immediate_executor();+ }+};++#endif // !defined(GENERATING_DOCUMENTATION)++} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // ASIO_BIND_IMMEDIATE_EXECUTOR_HPP
link/modules/asio-standalone/asio/include/asio/buffer.hpp view
@@ -2,7 +2,7 @@ // buffer.hpp // ~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -27,6 +27,7 @@ #include "asio/detail/string_view.hpp" #include "asio/detail/throw_exception.hpp" #include "asio/detail/type_traits.hpp"+#include "asio/is_contiguous_iterator.hpp" #if defined(ASIO_MSVC) && (ASIO_MSVC >= 1700) # if defined(_HAS_ITERATOR_DEBUGGING) && (_HAS_ITERATOR_DEBUGGING != 0)@@ -386,9 +387,9 @@ /// Get an iterator to the first element in a buffer sequence. template <typename MutableBuffer> inline const mutable_buffer* buffer_sequence_begin(const MutableBuffer& b,- typename enable_if<+ typename constraint< is_convertible<const MutableBuffer*, const mutable_buffer*>::value- >::type* = 0) ASIO_NOEXCEPT+ >::type = 0) ASIO_NOEXCEPT { return static_cast<const mutable_buffer*>(detail::addressof(b)); }@@ -396,9 +397,9 @@ /// Get an iterator to the first element in a buffer sequence. template <typename ConstBuffer> inline const const_buffer* buffer_sequence_begin(const ConstBuffer& b,- typename enable_if<+ typename constraint< is_convertible<const ConstBuffer*, const const_buffer*>::value- >::type* = 0) ASIO_NOEXCEPT+ >::type = 0) ASIO_NOEXCEPT { return static_cast<const const_buffer*>(detail::addressof(b)); }@@ -408,10 +409,10 @@ /// Get an iterator to the first element in a buffer sequence. template <typename C> inline auto buffer_sequence_begin(C& c,- typename enable_if<+ typename constraint< !is_convertible<const C*, const mutable_buffer*>::value && !is_convertible<const C*, const const_buffer*>::value- >::type* = 0) ASIO_NOEXCEPT -> decltype(c.begin())+ >::type = 0) ASIO_NOEXCEPT -> decltype(c.begin()) { return c.begin(); }@@ -419,10 +420,10 @@ /// Get an iterator to the first element in a buffer sequence. template <typename C> inline auto buffer_sequence_begin(const C& c,- typename enable_if<+ typename constraint< !is_convertible<const C*, const mutable_buffer*>::value && !is_convertible<const C*, const const_buffer*>::value- >::type* = 0) ASIO_NOEXCEPT -> decltype(c.begin())+ >::type = 0) ASIO_NOEXCEPT -> decltype(c.begin()) { return c.begin(); }@@ -431,20 +432,20 @@ template <typename C> inline typename C::iterator buffer_sequence_begin(C& c,- typename enable_if<+ typename constraint< !is_convertible<const C*, const mutable_buffer*>::value && !is_convertible<const C*, const const_buffer*>::value- >::type* = 0) ASIO_NOEXCEPT+ >::type = 0) ASIO_NOEXCEPT { return c.begin(); } template <typename C> inline typename C::const_iterator buffer_sequence_begin(const C& c,- typename enable_if<+ typename constraint< !is_convertible<const C*, const mutable_buffer*>::value && !is_convertible<const C*, const const_buffer*>::value- >::type* = 0) ASIO_NOEXCEPT+ >::type = 0) ASIO_NOEXCEPT { return c.begin(); }@@ -463,9 +464,9 @@ /// Get an iterator to one past the end element in a buffer sequence. template <typename MutableBuffer> inline const mutable_buffer* buffer_sequence_end(const MutableBuffer& b,- typename enable_if<+ typename constraint< is_convertible<const MutableBuffer*, const mutable_buffer*>::value- >::type* = 0) ASIO_NOEXCEPT+ >::type = 0) ASIO_NOEXCEPT { return static_cast<const mutable_buffer*>(detail::addressof(b)) + 1; }@@ -473,9 +474,9 @@ /// Get an iterator to one past the end element in a buffer sequence. template <typename ConstBuffer> inline const const_buffer* buffer_sequence_end(const ConstBuffer& b,- typename enable_if<+ typename constraint< is_convertible<const ConstBuffer*, const const_buffer*>::value- >::type* = 0) ASIO_NOEXCEPT+ >::type = 0) ASIO_NOEXCEPT { return static_cast<const const_buffer*>(detail::addressof(b)) + 1; }@@ -485,10 +486,10 @@ /// Get an iterator to one past the end element in a buffer sequence. template <typename C> inline auto buffer_sequence_end(C& c,- typename enable_if<+ typename constraint< !is_convertible<const C*, const mutable_buffer*>::value && !is_convertible<const C*, const const_buffer*>::value- >::type* = 0) ASIO_NOEXCEPT -> decltype(c.end())+ >::type = 0) ASIO_NOEXCEPT -> decltype(c.end()) { return c.end(); }@@ -496,10 +497,10 @@ /// Get an iterator to one past the end element in a buffer sequence. template <typename C> inline auto buffer_sequence_end(const C& c,- typename enable_if<+ typename constraint< !is_convertible<const C*, const mutable_buffer*>::value && !is_convertible<const C*, const const_buffer*>::value- >::type* = 0) ASIO_NOEXCEPT -> decltype(c.end())+ >::type = 0) ASIO_NOEXCEPT -> decltype(c.end()) { return c.end(); }@@ -508,20 +509,20 @@ template <typename C> inline typename C::iterator buffer_sequence_end(C& c,- typename enable_if<+ typename constraint< !is_convertible<const C*, const mutable_buffer*>::value && !is_convertible<const C*, const const_buffer*>::value- >::type* = 0) ASIO_NOEXCEPT+ >::type = 0) ASIO_NOEXCEPT { return c.end(); } template <typename C> inline typename C::const_iterator buffer_sequence_end(const C& c,- typename enable_if<+ typename constraint< !is_convertible<const C*, const mutable_buffer*>::value && !is_convertible<const C*, const const_buffer*>::value- >::type* = 0) ASIO_NOEXCEPT+ >::type = 0) ASIO_NOEXCEPT { return c.end(); }@@ -891,6 +892,25 @@ * bufs2.push_back(asio::buffer(d2)); * bufs2.push_back(asio::buffer(d3)); * bytes_transferred = sock.send(bufs2); @endcode+ *+ * @par Buffer Literals+ *+ * The `_buf` literal suffix, defined in namespace+ * <tt>asio::buffer_literals</tt>, may be used to create @c const_buffer+ * objects from string, binary integer, and hexadecimal integer literals.+ * For example:+ *+ * @code+ * using namespace asio::buffer_literals;+ *+ * asio::const_buffer b1 = "hello"_buf;+ * asio::const_buffer b2 = 0xdeadbeef_buf;+ * asio::const_buffer b3 = 0x0123456789abcdef0123456789abcdef_buf;+ * asio::const_buffer b4 = 0b1010101011001100_buf; @endcode+ *+ * Note that the memory associated with a buffer literal is valid for the+ * lifetime of the program. This means that the buffer can be safely used with+ * asynchronous operations. */ /*@{*/ @@ -906,7 +926,7 @@ /** * @returns <tt>mutable_buffer(b)</tt>. */-inline ASIO_MUTABLE_BUFFER buffer(+ASIO_NODISCARD inline ASIO_MUTABLE_BUFFER buffer( const mutable_buffer& b) ASIO_NOEXCEPT { return ASIO_MUTABLE_BUFFER(b);@@ -919,7 +939,8 @@ * b.data(), * min(b.size(), max_size_in_bytes)); @endcode */-inline ASIO_MUTABLE_BUFFER buffer(const mutable_buffer& b,+ASIO_NODISCARD inline ASIO_MUTABLE_BUFFER buffer(+ const mutable_buffer& b, std::size_t max_size_in_bytes) ASIO_NOEXCEPT { return ASIO_MUTABLE_BUFFER(@@ -936,7 +957,7 @@ /** * @returns <tt>const_buffer(b)</tt>. */-inline ASIO_CONST_BUFFER buffer(+ASIO_NODISCARD inline ASIO_CONST_BUFFER buffer( const const_buffer& b) ASIO_NOEXCEPT { return ASIO_CONST_BUFFER(b);@@ -949,7 +970,8 @@ * b.data(), * min(b.size(), max_size_in_bytes)); @endcode */-inline ASIO_CONST_BUFFER buffer(const const_buffer& b,+ASIO_NODISCARD inline ASIO_CONST_BUFFER buffer(+ const const_buffer& b, std::size_t max_size_in_bytes) ASIO_NOEXCEPT { return ASIO_CONST_BUFFER(b.data(),@@ -965,8 +987,8 @@ /** * @returns <tt>mutable_buffer(data, size_in_bytes)</tt>. */-inline ASIO_MUTABLE_BUFFER buffer(void* data,- std::size_t size_in_bytes) ASIO_NOEXCEPT+ASIO_NODISCARD inline ASIO_MUTABLE_BUFFER buffer(+ void* data, std::size_t size_in_bytes) ASIO_NOEXCEPT { return ASIO_MUTABLE_BUFFER(data, size_in_bytes); }@@ -975,8 +997,8 @@ /** * @returns <tt>const_buffer(data, size_in_bytes)</tt>. */-inline ASIO_CONST_BUFFER buffer(const void* data,- std::size_t size_in_bytes) ASIO_NOEXCEPT+ASIO_NODISCARD inline ASIO_CONST_BUFFER buffer(+ const void* data, std::size_t size_in_bytes) ASIO_NOEXCEPT { return ASIO_CONST_BUFFER(data, size_in_bytes); }@@ -989,7 +1011,8 @@ * N * sizeof(PodType)); @endcode */ template <typename PodType, std::size_t N>-inline ASIO_MUTABLE_BUFFER buffer(PodType (&data)[N]) ASIO_NOEXCEPT+ASIO_NODISCARD inline ASIO_MUTABLE_BUFFER buffer(+ PodType (&data)[N]) ASIO_NOEXCEPT { return ASIO_MUTABLE_BUFFER(data, N * sizeof(PodType)); }@@ -1002,7 +1025,8 @@ * min(N * sizeof(PodType), max_size_in_bytes)); @endcode */ template <typename PodType, std::size_t N>-inline ASIO_MUTABLE_BUFFER buffer(PodType (&data)[N],+ASIO_NODISCARD inline ASIO_MUTABLE_BUFFER buffer(+ PodType (&data)[N], std::size_t max_size_in_bytes) ASIO_NOEXCEPT { return ASIO_MUTABLE_BUFFER(data,@@ -1018,7 +1042,7 @@ * N * sizeof(PodType)); @endcode */ template <typename PodType, std::size_t N>-inline ASIO_CONST_BUFFER buffer(+ASIO_NODISCARD inline ASIO_CONST_BUFFER buffer( const PodType (&data)[N]) ASIO_NOEXCEPT { return ASIO_CONST_BUFFER(data, N * sizeof(PodType));@@ -1032,7 +1056,8 @@ * min(N * sizeof(PodType), max_size_in_bytes)); @endcode */ template <typename PodType, std::size_t N>-inline ASIO_CONST_BUFFER buffer(const PodType (&data)[N],+ASIO_NODISCARD inline ASIO_CONST_BUFFER buffer(+ const PodType (&data)[N], std::size_t max_size_in_bytes) ASIO_NOEXCEPT { return ASIO_CONST_BUFFER(data,@@ -1082,7 +1107,8 @@ } // namespace detail template <typename PodType, std::size_t N>-inline typename detail::buffer_types<PodType>::container_type+ASIO_NODISCARD inline+typename detail::buffer_types<PodType>::container_type buffer(boost::array<PodType, N>& data) ASIO_NOEXCEPT { typedef typename asio::detail::buffer_types<PodType>::buffer_type@@ -1094,7 +1120,8 @@ } template <typename PodType, std::size_t N>-inline typename detail::buffer_types<PodType>::container_type+ASIO_NODISCARD inline+typename detail::buffer_types<PodType>::container_type buffer(boost::array<PodType, N>& data, std::size_t max_size_in_bytes) ASIO_NOEXCEPT {@@ -1118,7 +1145,7 @@ * data.size() * sizeof(PodType)); @endcode */ template <typename PodType, std::size_t N>-inline ASIO_MUTABLE_BUFFER buffer(+ASIO_NODISCARD inline ASIO_MUTABLE_BUFFER buffer( boost::array<PodType, N>& data) ASIO_NOEXCEPT { return ASIO_MUTABLE_BUFFER(@@ -1133,7 +1160,8 @@ * min(data.size() * sizeof(PodType), max_size_in_bytes)); @endcode */ template <typename PodType, std::size_t N>-inline ASIO_MUTABLE_BUFFER buffer(boost::array<PodType, N>& data,+ASIO_NODISCARD inline ASIO_MUTABLE_BUFFER buffer(+ boost::array<PodType, N>& data, std::size_t max_size_in_bytes) ASIO_NOEXCEPT { return ASIO_MUTABLE_BUFFER(data.c_array(),@@ -1149,7 +1177,7 @@ * data.size() * sizeof(PodType)); @endcode */ template <typename PodType, std::size_t N>-inline ASIO_CONST_BUFFER buffer(+ASIO_NODISCARD inline ASIO_CONST_BUFFER buffer( boost::array<const PodType, N>& data) ASIO_NOEXCEPT { return ASIO_CONST_BUFFER(data.data(), data.size() * sizeof(PodType));@@ -1163,7 +1191,8 @@ * min(data.size() * sizeof(PodType), max_size_in_bytes)); @endcode */ template <typename PodType, std::size_t N>-inline ASIO_CONST_BUFFER buffer(boost::array<const PodType, N>& data,+ASIO_NODISCARD inline ASIO_CONST_BUFFER buffer(+ boost::array<const PodType, N>& data, std::size_t max_size_in_bytes) ASIO_NOEXCEPT { return ASIO_CONST_BUFFER(data.data(),@@ -1181,7 +1210,7 @@ * data.size() * sizeof(PodType)); @endcode */ template <typename PodType, std::size_t N>-inline ASIO_CONST_BUFFER buffer(+ASIO_NODISCARD inline ASIO_CONST_BUFFER buffer( const boost::array<PodType, N>& data) ASIO_NOEXCEPT { return ASIO_CONST_BUFFER(data.data(), data.size() * sizeof(PodType));@@ -1195,7 +1224,8 @@ * min(data.size() * sizeof(PodType), max_size_in_bytes)); @endcode */ template <typename PodType, std::size_t N>-inline ASIO_CONST_BUFFER buffer(const boost::array<PodType, N>& data,+ASIO_NODISCARD inline ASIO_CONST_BUFFER buffer(+ const boost::array<PodType, N>& data, std::size_t max_size_in_bytes) ASIO_NOEXCEPT { return ASIO_CONST_BUFFER(data.data(),@@ -1213,7 +1243,7 @@ * data.size() * sizeof(PodType)); @endcode */ template <typename PodType, std::size_t N>-inline ASIO_MUTABLE_BUFFER buffer(+ASIO_NODISCARD inline ASIO_MUTABLE_BUFFER buffer( std::array<PodType, N>& data) ASIO_NOEXCEPT { return ASIO_MUTABLE_BUFFER(data.data(), data.size() * sizeof(PodType));@@ -1227,7 +1257,8 @@ * min(data.size() * sizeof(PodType), max_size_in_bytes)); @endcode */ template <typename PodType, std::size_t N>-inline ASIO_MUTABLE_BUFFER buffer(std::array<PodType, N>& data,+ASIO_NODISCARD inline ASIO_MUTABLE_BUFFER buffer(+ std::array<PodType, N>& data, std::size_t max_size_in_bytes) ASIO_NOEXCEPT { return ASIO_MUTABLE_BUFFER(data.data(),@@ -1243,7 +1274,7 @@ * data.size() * sizeof(PodType)); @endcode */ template <typename PodType, std::size_t N>-inline ASIO_CONST_BUFFER buffer(+ASIO_NODISCARD inline ASIO_CONST_BUFFER buffer( std::array<const PodType, N>& data) ASIO_NOEXCEPT { return ASIO_CONST_BUFFER(data.data(), data.size() * sizeof(PodType));@@ -1257,7 +1288,8 @@ * min(data.size() * sizeof(PodType), max_size_in_bytes)); @endcode */ template <typename PodType, std::size_t N>-inline ASIO_CONST_BUFFER buffer(std::array<const PodType, N>& data,+ASIO_NODISCARD inline ASIO_CONST_BUFFER buffer(+ std::array<const PodType, N>& data, std::size_t max_size_in_bytes) ASIO_NOEXCEPT { return ASIO_CONST_BUFFER(data.data(),@@ -1273,7 +1305,7 @@ * data.size() * sizeof(PodType)); @endcode */ template <typename PodType, std::size_t N>-inline ASIO_CONST_BUFFER buffer(+ASIO_NODISCARD inline ASIO_CONST_BUFFER buffer( const std::array<PodType, N>& data) ASIO_NOEXCEPT { return ASIO_CONST_BUFFER(data.data(), data.size() * sizeof(PodType));@@ -1287,7 +1319,8 @@ * min(data.size() * sizeof(PodType), max_size_in_bytes)); @endcode */ template <typename PodType, std::size_t N>-inline ASIO_CONST_BUFFER buffer(const std::array<PodType, N>& data,+ASIO_NODISCARD inline ASIO_CONST_BUFFER buffer(+ const std::array<PodType, N>& data, std::size_t max_size_in_bytes) ASIO_NOEXCEPT { return ASIO_CONST_BUFFER(data.data(),@@ -1308,7 +1341,7 @@ * invalidate iterators. */ template <typename PodType, typename Allocator>-inline ASIO_MUTABLE_BUFFER buffer(+ASIO_NODISCARD inline ASIO_MUTABLE_BUFFER buffer( std::vector<PodType, Allocator>& data) ASIO_NOEXCEPT { return ASIO_MUTABLE_BUFFER(@@ -1332,7 +1365,8 @@ * invalidate iterators. */ template <typename PodType, typename Allocator>-inline ASIO_MUTABLE_BUFFER buffer(std::vector<PodType, Allocator>& data,+ASIO_NODISCARD inline ASIO_MUTABLE_BUFFER buffer(+ std::vector<PodType, Allocator>& data, std::size_t max_size_in_bytes) ASIO_NOEXCEPT { return ASIO_MUTABLE_BUFFER(data.size() ? &data[0] : 0,@@ -1357,7 +1391,7 @@ * invalidate iterators. */ template <typename PodType, typename Allocator>-inline ASIO_CONST_BUFFER buffer(+ASIO_NODISCARD inline ASIO_CONST_BUFFER buffer( const std::vector<PodType, Allocator>& data) ASIO_NOEXCEPT { return ASIO_CONST_BUFFER(@@ -1381,7 +1415,7 @@ * invalidate iterators. */ template <typename PodType, typename Allocator>-inline ASIO_CONST_BUFFER buffer(+ASIO_NODISCARD inline ASIO_CONST_BUFFER buffer( const std::vector<PodType, Allocator>& data, std::size_t max_size_in_bytes) ASIO_NOEXCEPT {@@ -1405,7 +1439,7 @@ * given string object. */ template <typename Elem, typename Traits, typename Allocator>-inline ASIO_MUTABLE_BUFFER buffer(+ASIO_NODISCARD inline ASIO_MUTABLE_BUFFER buffer( std::basic_string<Elem, Traits, Allocator>& data) ASIO_NOEXCEPT { return ASIO_MUTABLE_BUFFER(data.size() ? &data[0] : 0,@@ -1429,7 +1463,7 @@ * given string object. */ template <typename Elem, typename Traits, typename Allocator>-inline ASIO_MUTABLE_BUFFER buffer(+ASIO_NODISCARD inline ASIO_MUTABLE_BUFFER buffer( std::basic_string<Elem, Traits, Allocator>& data, std::size_t max_size_in_bytes) ASIO_NOEXCEPT {@@ -1452,7 +1486,7 @@ * given string object. */ template <typename Elem, typename Traits, typename Allocator>-inline ASIO_CONST_BUFFER buffer(+ASIO_NODISCARD inline ASIO_CONST_BUFFER buffer( const std::basic_string<Elem, Traits, Allocator>& data) ASIO_NOEXCEPT { return ASIO_CONST_BUFFER(data.data(), data.size() * sizeof(Elem)@@ -1475,7 +1509,7 @@ * given string object. */ template <typename Elem, typename Traits, typename Allocator>-inline ASIO_CONST_BUFFER buffer(+ASIO_NODISCARD inline ASIO_CONST_BUFFER buffer( const std::basic_string<Elem, Traits, Allocator>& data, std::size_t max_size_in_bytes) ASIO_NOEXCEPT {@@ -1493,13 +1527,13 @@ #if defined(ASIO_HAS_STRING_VIEW) \ || defined(GENERATING_DOCUMENTATION) -/// Create a new modifiable buffer that represents the given string_view.+/// Create a new non-modifiable buffer that represents the given string_view. /** * @returns <tt>mutable_buffer(data.size() ? &data[0] : 0, * data.size() * sizeof(Elem))</tt>. */ template <typename Elem, typename Traits>-inline ASIO_CONST_BUFFER buffer(+ASIO_NODISCARD inline ASIO_CONST_BUFFER buffer( basic_string_view<Elem, Traits> data) ASIO_NOEXCEPT { return ASIO_CONST_BUFFER(data.size() ? &data[0] : 0,@@ -1520,7 +1554,7 @@ * min(data.size() * sizeof(Elem), max_size_in_bytes)); @endcode */ template <typename Elem, typename Traits>-inline ASIO_CONST_BUFFER buffer(+ASIO_NODISCARD inline ASIO_CONST_BUFFER buffer( basic_string_view<Elem, Traits> data, std::size_t max_size_in_bytes) ASIO_NOEXCEPT {@@ -1538,6 +1572,215 @@ #endif // defined(ASIO_HAS_STRING_VIEW) // || defined(GENERATING_DOCUMENTATION) +/// Create a new modifiable buffer from a contiguous container.+/**+ * @returns A mutable_buffer value equivalent to:+ * @code mutable_buffer(+ * data.size() ? &data[0] : 0,+ * data.size() * sizeof(typename T::value_type)); @endcode+ */+template <typename T>+ASIO_NODISCARD inline ASIO_MUTABLE_BUFFER buffer(+ T& data,+ typename constraint<+ is_contiguous_iterator<typename T::iterator>::value,+ defaulted_constraint+ >::type = defaulted_constraint(),+ typename constraint<+ !is_convertible<T, const_buffer>::value,+ defaulted_constraint+ >::type = defaulted_constraint(),+ typename constraint<+ !is_convertible<T, mutable_buffer>::value,+ defaulted_constraint+ >::type = defaulted_constraint(),+ typename constraint<+ !is_const<+ typename remove_reference<+ typename std::iterator_traits<typename T::iterator>::reference+ >::type+ >::value,+ defaulted_constraint+ >::type = defaulted_constraint()) ASIO_NOEXCEPT+{+ return ASIO_MUTABLE_BUFFER(+ data.size() ? detail::to_address(data.begin()) : 0,+ data.size() * sizeof(typename T::value_type));+}++/// Create a new modifiable buffer from a contiguous container.+/**+ * @returns A mutable_buffer value equivalent to:+ * @code mutable_buffer(+ * data.size() ? &data[0] : 0,+ * min(+ * data.size() * sizeof(typename T::value_type),+ * max_size_in_bytes)); @endcode+ */+template <typename T>+ASIO_NODISCARD inline ASIO_MUTABLE_BUFFER buffer(+ T& data, std::size_t max_size_in_bytes,+ typename constraint<+ is_contiguous_iterator<typename T::iterator>::value,+ defaulted_constraint+ >::type = defaulted_constraint(),+ typename constraint<+ !is_convertible<T, const_buffer>::value,+ defaulted_constraint+ >::type = defaulted_constraint(),+ typename constraint<+ !is_convertible<T, mutable_buffer>::value,+ defaulted_constraint+ >::type = defaulted_constraint(),+ typename constraint<+ !is_const<+ typename remove_reference<+ typename std::iterator_traits<typename T::iterator>::reference+ >::type+ >::value,+ defaulted_constraint+ >::type = defaulted_constraint()) ASIO_NOEXCEPT+{+ return ASIO_MUTABLE_BUFFER(+ data.size() ? detail::to_address(data.begin()) : 0,+ data.size() * sizeof(typename T::value_type) < max_size_in_bytes+ ? data.size() * sizeof(typename T::value_type) : max_size_in_bytes);+}++/// Create a new non-modifiable buffer from a contiguous container.+/**+ * @returns A const_buffer value equivalent to:+ * @code const_buffer(+ * data.size() ? &data[0] : 0,+ * data.size() * sizeof(typename T::value_type)); @endcode+ */+template <typename T>+ASIO_NODISCARD inline ASIO_CONST_BUFFER buffer(+ T& data,+ typename constraint<+ is_contiguous_iterator<typename T::iterator>::value,+ defaulted_constraint+ >::type = defaulted_constraint(),+ typename constraint<+ !is_convertible<T, const_buffer>::value,+ defaulted_constraint+ >::type = defaulted_constraint(),+ typename constraint<+ !is_convertible<T, mutable_buffer>::value,+ defaulted_constraint+ >::type = defaulted_constraint(),+ typename constraint<+ is_const<+ typename remove_reference<+ typename std::iterator_traits<typename T::iterator>::reference+ >::type+ >::value,+ defaulted_constraint+ >::type = defaulted_constraint()) ASIO_NOEXCEPT+{+ return ASIO_CONST_BUFFER(+ data.size() ? detail::to_address(data.begin()) : 0,+ data.size() * sizeof(typename T::value_type));+}++/// Create a new non-modifiable buffer from a contiguous container.+/**+ * @returns A const_buffer value equivalent to:+ * @code const_buffer(+ * data.size() ? &data[0] : 0,+ * min(+ * data.size() * sizeof(typename T::value_type),+ * max_size_in_bytes)); @endcode+ */+template <typename T>+ASIO_NODISCARD inline ASIO_CONST_BUFFER buffer(+ T& data, std::size_t max_size_in_bytes,+ typename constraint<+ is_contiguous_iterator<typename T::iterator>::value,+ defaulted_constraint+ >::type = defaulted_constraint(),+ typename constraint<+ !is_convertible<T, const_buffer>::value,+ defaulted_constraint+ >::type = defaulted_constraint(),+ typename constraint<+ !is_convertible<T, mutable_buffer>::value,+ defaulted_constraint+ >::type = defaulted_constraint(),+ typename constraint<+ is_const<+ typename remove_reference<+ typename std::iterator_traits<typename T::iterator>::reference+ >::type+ >::value,+ defaulted_constraint+ >::type = defaulted_constraint()) ASIO_NOEXCEPT+{+ return ASIO_CONST_BUFFER(+ data.size() ? detail::to_address(data.begin()) : 0,+ data.size() * sizeof(typename T::value_type) < max_size_in_bytes+ ? data.size() * sizeof(typename T::value_type) : max_size_in_bytes);+}++/// Create a new non-modifiable buffer from a contiguous container.+/**+ * @returns A const_buffer value equivalent to:+ * @code const_buffer(+ * data.size() ? &data[0] : 0,+ * data.size() * sizeof(typename T::value_type)); @endcode+ */+template <typename T>+ASIO_NODISCARD inline ASIO_CONST_BUFFER buffer(+ const T& data,+ typename constraint<+ is_contiguous_iterator<typename T::const_iterator>::value,+ defaulted_constraint+ >::type = defaulted_constraint(),+ typename constraint<+ !is_convertible<T, const_buffer>::value,+ defaulted_constraint+ >::type = defaulted_constraint(),+ typename constraint<+ !is_convertible<T, mutable_buffer>::value,+ defaulted_constraint+ >::type = defaulted_constraint()) ASIO_NOEXCEPT+{+ return ASIO_CONST_BUFFER(+ data.size() ? detail::to_address(data.begin()) : 0,+ data.size() * sizeof(typename T::value_type));+}++/// Create a new non-modifiable buffer from a contiguous container.+/**+ * @returns A const_buffer value equivalent to:+ * @code const_buffer(+ * data.size() ? &data[0] : 0,+ * min(+ * data.size() * sizeof(typename T::value_type),+ * max_size_in_bytes)); @endcode+ */+template <typename T>+ASIO_NODISCARD inline ASIO_CONST_BUFFER buffer(+ const T& data, std::size_t max_size_in_bytes,+ typename constraint<+ is_contiguous_iterator<typename T::const_iterator>::value,+ defaulted_constraint+ >::type = defaulted_constraint(),+ typename constraint<+ !is_convertible<T, const_buffer>::value,+ defaulted_constraint+ >::type = defaulted_constraint(),+ typename constraint<+ !is_convertible<T, mutable_buffer>::value,+ defaulted_constraint+ >::type = defaulted_constraint()) ASIO_NOEXCEPT+{+ return ASIO_CONST_BUFFER(+ data.size() ? detail::to_address(data.begin()) : 0,+ data.size() * sizeof(typename T::value_type) < max_size_in_bytes+ ? data.size() * sizeof(typename T::value_type) : max_size_in_bytes);+}+ /*@}*/ /// Adapt a basic_string to the DynamicBuffer requirements.@@ -2096,7 +2339,8 @@ * @returns <tt>dynamic_string_buffer<Elem, Traits, Allocator>(data)</tt>. */ template <typename Elem, typename Traits, typename Allocator>-inline dynamic_string_buffer<Elem, Traits, Allocator> dynamic_buffer(+ASIO_NODISCARD inline+dynamic_string_buffer<Elem, Traits, Allocator> dynamic_buffer( std::basic_string<Elem, Traits, Allocator>& data) ASIO_NOEXCEPT { return dynamic_string_buffer<Elem, Traits, Allocator>(data);@@ -2108,7 +2352,8 @@ * max_size)</tt>. */ template <typename Elem, typename Traits, typename Allocator>-inline dynamic_string_buffer<Elem, Traits, Allocator> dynamic_buffer(+ASIO_NODISCARD inline+dynamic_string_buffer<Elem, Traits, Allocator> dynamic_buffer( std::basic_string<Elem, Traits, Allocator>& data, std::size_t max_size) ASIO_NOEXCEPT {@@ -2120,7 +2365,8 @@ * @returns <tt>dynamic_vector_buffer<Elem, Allocator>(data)</tt>. */ template <typename Elem, typename Allocator>-inline dynamic_vector_buffer<Elem, Allocator> dynamic_buffer(+ASIO_NODISCARD inline+dynamic_vector_buffer<Elem, Allocator> dynamic_buffer( std::vector<Elem, Allocator>& data) ASIO_NOEXCEPT { return dynamic_vector_buffer<Elem, Allocator>(data);@@ -2131,7 +2377,8 @@ * @returns <tt>dynamic_vector_buffer<Elem, Allocator>(data, max_size)</tt>. */ template <typename Elem, typename Allocator>-inline dynamic_vector_buffer<Elem, Allocator> dynamic_buffer(+ASIO_NODISCARD inline+dynamic_vector_buffer<Elem, Allocator> dynamic_buffer( std::vector<Elem, Allocator>& data, std::size_t max_size) ASIO_NOEXCEPT {@@ -2488,6 +2735,172 @@ #endif // defined(ASIO_NO_DYNAMIC_BUFFER_V1) { };++#if (defined(ASIO_HAS_USER_DEFINED_LITERALS) \+ && defined(ASIO_HAS_VARIADIC_TEMPLATES)) \+ || defined(GENERATING_DOCUMENTATION)++namespace buffer_literals {+namespace detail {++template <char... Chars>+struct chars {};++template <unsigned char... Bytes>+struct bytes {};++// Literal processor that converts binary literals to an array of bytes.++template <typename Bytes, char... Chars>+struct bin_literal;++template <unsigned char... Bytes>+struct bin_literal<bytes<Bytes...> >+{+ static const std::size_t size = sizeof...(Bytes);+ static const unsigned char data[sizeof...(Bytes)];+};++template <unsigned char... Bytes>+const unsigned char bin_literal<bytes<Bytes...> >::data[sizeof...(Bytes)]+ = { Bytes... };++template <unsigned char... Bytes, char Bit7, char Bit6, char Bit5,+ char Bit4, char Bit3, char Bit2, char Bit1, char Bit0, char... Chars>+struct bin_literal<bytes<Bytes...>, Bit7, Bit6,+ Bit5, Bit4, Bit3, Bit2, Bit1, Bit0, Chars...> :+ bin_literal<+ bytes<Bytes...,+ static_cast<unsigned char>(+ (Bit7 == '1' ? 0x80 : 0) |+ (Bit6 == '1' ? 0x40 : 0) |+ (Bit5 == '1' ? 0x20 : 0) |+ (Bit4 == '1' ? 0x10 : 0) |+ (Bit3 == '1' ? 0x08 : 0) |+ (Bit2 == '1' ? 0x04 : 0) |+ (Bit1 == '1' ? 0x02 : 0) |+ (Bit0 == '1' ? 0x01 : 0))+ >, Chars...> {};++template <unsigned char... Bytes, char... Chars>+struct bin_literal<bytes<Bytes...>, Chars...>+{+ static_assert(sizeof...(Chars) == 0,+ "number of digits in a binary buffer literal must be a multiple of 8");++ static const std::size_t size = 0;+ static const unsigned char data[1];+};++template <unsigned char... Bytes, char... Chars>+const unsigned char bin_literal<bytes<Bytes...>, Chars...>::data[1] = {};++// Literal processor that converts hexadecimal literals to an array of bytes.++template <typename Bytes, char... Chars>+struct hex_literal;++template <unsigned char... Bytes>+struct hex_literal<bytes<Bytes...> >+{+ static const std::size_t size = sizeof...(Bytes);+ static const unsigned char data[sizeof...(Bytes)];+};++template <unsigned char... Bytes>+const unsigned char hex_literal<bytes<Bytes...> >::data[sizeof...(Bytes)]+ = { Bytes... };++template <unsigned char... Bytes, char Hi, char Lo, char... Chars>+struct hex_literal<bytes<Bytes...>, Hi, Lo, Chars...> :+ hex_literal<+ bytes<Bytes...,+ static_cast<unsigned char>(+ Lo >= 'A' && Lo <= 'F' ? Lo - 'A' + 10 :+ (Lo >= 'a' && Lo <= 'f' ? Lo - 'a' + 10 : Lo - '0')) |+ ((static_cast<unsigned char>(+ Hi >= 'A' && Hi <= 'F' ? Hi - 'A' + 10 :+ (Hi >= 'a' && Hi <= 'f' ? Hi - 'a' + 10 : Hi - '0'))) << 4)+ >, Chars...> {};++template <unsigned char... Bytes, char Char>+struct hex_literal<bytes<Bytes...>, Char>+{+ static_assert(!Char,+ "a hexadecimal buffer literal must have an even number of digits");++ static const std::size_t size = 0;+ static const unsigned char data[1];+};++template <unsigned char... Bytes, char Char>+const unsigned char hex_literal<bytes<Bytes...>, Char>::data[1] = {};++// Helper template that removes digit separators and then passes the cleaned+// variadic pack of characters to the literal processor.++template <template <typename, char...> class Literal,+ typename Clean, char... Raw>+struct remove_separators;++template <template <typename, char...> class Literal,+ char... Clean, char... Raw>+struct remove_separators<Literal, chars<Clean...>, '\'', Raw...> :+ remove_separators<Literal, chars<Clean...>, Raw...> {};++template <template <typename, char...> class Literal,+ char... Clean, char C, char... Raw>+struct remove_separators<Literal, chars<Clean...>, C, Raw...> :+ remove_separators<Literal, chars<Clean..., C>, Raw...> {};++template <template <typename, char...> class Literal, char... Clean>+struct remove_separators<Literal, chars<Clean...> > :+ Literal<bytes<>, Clean...> {};++// Helper template to determine the literal type based on the prefix.++template <char... Chars>+struct literal;++template <char... Chars>+struct literal<'0', 'b', Chars...> :+ remove_separators<bin_literal, chars<>, Chars...>{};++template <char... Chars>+struct literal<'0', 'B', Chars...> :+ remove_separators<bin_literal, chars<>, Chars...>{};++template <char... Chars>+struct literal<'0', 'x', Chars...> :+ remove_separators<hex_literal, chars<>, Chars...>{};++template <char... Chars>+struct literal<'0', 'X', Chars...> :+ remove_separators<hex_literal, chars<>, Chars...>{};++} // namespace detail++/// Literal operator for creating const_buffer objects from string literals.+inline ASIO_CONST_BUFFER operator"" _buf(const char* data, std::size_t n)+{+ return ASIO_CONST_BUFFER(data, n);+}++/// Literal operator for creating const_buffer objects from unbounded binary or+/// hexadecimal integer literals.+template <char... Chars>+inline ASIO_CONST_BUFFER operator"" _buf()+{+ return ASIO_CONST_BUFFER(+ +detail::literal<Chars...>::data,+ detail::literal<Chars...>::size);+}++} // namespace buffer_literals++#endif // (defined(ASIO_HAS_USER_DEFINED_LITERALS)+ // && defined(ASIO_HAS_VARIADIC_TEMPLATES))+ // || defined(GENERATING_DOCUMENTATION) } // namespace asio
+ link/modules/asio-standalone/asio/include/asio/buffer_registration.hpp view
@@ -0,0 +1,328 @@+//+// buffer_registration.hpp+// ~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com)+//+// Distributed under the Boost Software License, Version 1.0. (See accompanying+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)+//++#ifndef ASIO_BUFFER_REGISTRATION_HPP+#define ASIO_BUFFER_REGISTRATION_HPP++#if defined(_MSC_VER) && (_MSC_VER >= 1200)+# pragma once+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)++#include "asio/detail/config.hpp"+#include <iterator>+#include <vector>+#include "asio/detail/memory.hpp"+#include "asio/execution/context.hpp"+#include "asio/execution/executor.hpp"+#include "asio/execution_context.hpp"+#include "asio/is_executor.hpp"+#include "asio/query.hpp"+#include "asio/registered_buffer.hpp"++#if defined(ASIO_HAS_IO_URING)+# include "asio/detail/scheduler.hpp"+# include "asio/detail/io_uring_service.hpp"+#endif // defined(ASIO_HAS_IO_URING)++#if defined(ASIO_HAS_MOVE)+# include <utility>+#endif // defined(ASIO_HAS_MOVE)++#include "asio/detail/push_options.hpp"++namespace asio {+namespace detail {++class buffer_registration_base+{+protected:+ static mutable_registered_buffer make_buffer(const mutable_buffer& b,+ const void* scope, int index) ASIO_NOEXCEPT+ {+ return mutable_registered_buffer(b, registered_buffer_id(scope, index));+ }+};++} // namespace detail++/// Automatically registers and unregistered buffers with an execution context.+/**+ * For portability, applications should assume that only one registration is+ * permitted per execution context.+ */+template <typename MutableBufferSequence,+ typename Allocator = std::allocator<void> >+class buffer_registration+ : detail::buffer_registration_base+{+public:+ /// The allocator type used for allocating storage for the buffers container.+ typedef Allocator allocator_type;++#if defined(GENERATING_DOCUMENTATION)+ /// The type of an iterator over the registered buffers.+ typedef unspecified iterator;++ /// The type of a const iterator over the registered buffers.+ typedef unspecified const_iterator;+#else // defined(GENERATING_DOCUMENTATION)+ typedef std::vector<mutable_registered_buffer>::const_iterator iterator;+ typedef std::vector<mutable_registered_buffer>::const_iterator const_iterator;+#endif // defined(GENERATING_DOCUMENTATION)++ /// Register buffers with an executor's execution context.+ template <typename Executor>+ buffer_registration(const Executor& ex,+ const MutableBufferSequence& buffer_sequence,+ const allocator_type& alloc = allocator_type(),+ typename constraint<+ is_executor<Executor>::value || execution::is_executor<Executor>::value+ >::type = 0)+ : buffer_sequence_(buffer_sequence),+ buffers_(+ ASIO_REBIND_ALLOC(allocator_type,+ mutable_registered_buffer)(alloc))+ {+ init_buffers(buffer_registration::get_context(ex),+ asio::buffer_sequence_begin(buffer_sequence_),+ asio::buffer_sequence_end(buffer_sequence_));+ }++ /// Register buffers with an execution context.+ template <typename ExecutionContext>+ buffer_registration(ExecutionContext& ctx,+ const MutableBufferSequence& buffer_sequence,+ const allocator_type& alloc = allocator_type(),+ typename constraint<+ is_convertible<ExecutionContext&, execution_context&>::value+ >::type = 0)+ : buffer_sequence_(buffer_sequence),+ buffers_(+ ASIO_REBIND_ALLOC(allocator_type,+ mutable_registered_buffer)(alloc))+ {+ init_buffers(ctx,+ asio::buffer_sequence_begin(buffer_sequence_),+ asio::buffer_sequence_end(buffer_sequence_));+ }++#if defined(ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)+ /// Move constructor.+ buffer_registration(buffer_registration&& other) ASIO_NOEXCEPT+ : buffer_sequence_(std::move(other.buffer_sequence_)),+ buffers_(std::move(other.buffers_))+ {+#if defined(ASIO_HAS_IO_URING)+ service_ = other.service_;+ other.service_ = 0;+#endif // defined(ASIO_HAS_IO_URING)+ }+#endif // defined(ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)++ /// Unregisters the buffers.+ ~buffer_registration()+ {+#if defined(ASIO_HAS_IO_URING)+ if (service_)+ service_->unregister_buffers();+#endif // defined(ASIO_HAS_IO_URING)+ }+ +#if defined(ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)+ /// Move assignment.+ buffer_registration& operator=(+ buffer_registration&& other) ASIO_NOEXCEPT+ {+ if (this != &other)+ {+ buffer_sequence_ = std::move(other.buffer_sequence_);+ buffers_ = std::move(other.buffers_);+#if defined(ASIO_HAS_IO_URING)+ if (service_)+ service_->unregister_buffers();+ service_ = other.service_;+ other.service_ = 0;+#endif // defined(ASIO_HAS_IO_URING)+ }+ return *this;+ }+#endif // defined(ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)++ /// Get the number of registered buffers.+ std::size_t size() const ASIO_NOEXCEPT+ {+ return buffers_.size();+ }++ /// Get the begin iterator for the sequence of registered buffers.+ const_iterator begin() const ASIO_NOEXCEPT+ {+ return buffers_.begin();+ }++ /// Get the begin iterator for the sequence of registered buffers.+ const_iterator cbegin() const ASIO_NOEXCEPT+ {+ return buffers_.cbegin();+ }++ /// Get the end iterator for the sequence of registered buffers.+ const_iterator end() const ASIO_NOEXCEPT+ {+ return buffers_.end();+ }++ /// Get the end iterator for the sequence of registered buffers.+ const_iterator cend() const ASIO_NOEXCEPT+ {+ return buffers_.cend();+ }++ /// Get the buffer at the specified index.+ const mutable_registered_buffer& operator[](std::size_t i) ASIO_NOEXCEPT+ {+ return buffers_[i];+ }++ /// Get the buffer at the specified index.+ const mutable_registered_buffer& at(std::size_t i) ASIO_NOEXCEPT+ {+ return buffers_.at(i);+ }++private:+ // Disallow copying and assignment.+ buffer_registration(const buffer_registration&) ASIO_DELETED;+ buffer_registration& operator=(const buffer_registration&) ASIO_DELETED;++ // Helper function to get an executor's context.+ template <typename T>+ static execution_context& get_context(const T& t,+ typename enable_if<execution::is_executor<T>::value>::type* = 0)+ {+ return asio::query(t, execution::context);+ }++ // Helper function to get an executor's context.+ template <typename T>+ static execution_context& get_context(const T& t,+ typename enable_if<!execution::is_executor<T>::value>::type* = 0)+ {+ return t.context();+ }++ // Helper function to initialise the container of buffers.+ template <typename Iterator>+ void init_buffers(execution_context& ctx, Iterator begin, Iterator end)+ {+ std::size_t n = std::distance(begin, end);+ buffers_.resize(n);++#if defined(ASIO_HAS_IO_URING)+ service_ = &use_service<detail::io_uring_service>(ctx);+ std::vector<iovec,+ ASIO_REBIND_ALLOC(allocator_type, iovec)> iovecs(n,+ ASIO_REBIND_ALLOC(allocator_type, iovec)(+ buffers_.get_allocator()));+#endif // defined(ASIO_HAS_IO_URING)++ Iterator iter = begin;+ for (int index = 0; iter != end; ++index, ++iter)+ {+ mutable_buffer b(*iter);+ std::size_t i = static_cast<std::size_t>(index);+ buffers_[i] = this->make_buffer(b, &ctx, index);++#if defined(ASIO_HAS_IO_URING)+ iovecs[i].iov_base = buffers_[i].data();+ iovecs[i].iov_len = buffers_[i].size();+#endif // defined(ASIO_HAS_IO_URING)+ }++#if defined(ASIO_HAS_IO_URING)+ if (n > 0)+ {+ service_->register_buffers(&iovecs[0],+ static_cast<unsigned>(iovecs.size()));+ }+#endif // defined(ASIO_HAS_IO_URING)+ }++ MutableBufferSequence buffer_sequence_;+ std::vector<mutable_registered_buffer,+ ASIO_REBIND_ALLOC(allocator_type,+ mutable_registered_buffer)> buffers_;+#if defined(ASIO_HAS_IO_URING)+ detail::io_uring_service* service_;+#endif // defined(ASIO_HAS_IO_URING)+};++#if defined(ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)+/// Register buffers with an execution context.+template <typename Executor, typename MutableBufferSequence>+ASIO_NODISCARD inline+buffer_registration<MutableBufferSequence>+register_buffers(const Executor& ex,+ const MutableBufferSequence& buffer_sequence,+ typename constraint<+ is_executor<Executor>::value || execution::is_executor<Executor>::value+ >::type = 0)+{+ return buffer_registration<MutableBufferSequence>(ex, buffer_sequence);+}++/// Register buffers with an execution context.+template <typename Executor, typename MutableBufferSequence, typename Allocator>+ASIO_NODISCARD inline+buffer_registration<MutableBufferSequence, Allocator>+register_buffers(const Executor& ex,+ const MutableBufferSequence& buffer_sequence, const Allocator& alloc,+ typename constraint<+ is_executor<Executor>::value || execution::is_executor<Executor>::value+ >::type = 0)+{+ return buffer_registration<MutableBufferSequence, Allocator>(+ ex, buffer_sequence, alloc);+}++/// Register buffers with an execution context.+template <typename ExecutionContext, typename MutableBufferSequence>+ASIO_NODISCARD inline+buffer_registration<MutableBufferSequence>+register_buffers(ExecutionContext& ctx,+ const MutableBufferSequence& buffer_sequence,+ typename constraint<+ is_convertible<ExecutionContext&, execution_context&>::value+ >::type = 0)+{+ return buffer_registration<MutableBufferSequence>(ctx, buffer_sequence);+}++/// Register buffers with an execution context.+template <typename ExecutionContext,+ typename MutableBufferSequence, typename Allocator>+ASIO_NODISCARD inline+buffer_registration<MutableBufferSequence, Allocator>+register_buffers(ExecutionContext& ctx,+ const MutableBufferSequence& buffer_sequence, const Allocator& alloc,+ typename constraint<+ is_convertible<ExecutionContext&, execution_context&>::value+ >::type = 0)+{+ return buffer_registration<MutableBufferSequence, Allocator>(+ ctx, buffer_sequence, alloc);+}+#endif // defined(ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)++} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // ASIO_BUFFER_REGISTRATION_HPP
link/modules/asio-standalone/asio/include/asio/buffered_read_stream.hpp view
@@ -2,7 +2,7 @@ // buffered_read_stream.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -30,7 +30,13 @@ #include "asio/detail/push_options.hpp" namespace asio {+namespace detail { +template <typename> class initiate_async_buffered_fill;+template <typename> class initiate_async_buffered_read_some;++} // namespace detail+ /// Adds buffering to the read-related operations of a stream. /** * The buffered_read_stream class template can be used to add buffering to the@@ -66,16 +72,17 @@ /// Construct, passing the specified argument to initialise the next layer. template <typename Arg>- explicit buffered_read_stream(Arg& a)- : next_layer_(a),+ explicit buffered_read_stream(ASIO_MOVE_OR_LVALUE_ARG(Arg) a)+ : next_layer_(ASIO_MOVE_OR_LVALUE(Arg)(a)), storage_(default_buffer_size) { } /// Construct, passing the specified argument to initialise the next layer. template <typename Arg>- buffered_read_stream(Arg& a, std::size_t buffer_size)- : next_layer_(a),+ buffered_read_stream(ASIO_MOVE_OR_LVALUE_ARG(Arg) a,+ std::size_t buffer_size)+ : next_layer_(ASIO_MOVE_OR_LVALUE(Arg)(a)), storage_(buffer_size) { }@@ -136,15 +143,23 @@ /// Start an asynchronous write. The data being written must be valid for the /// lifetime of the asynchronous operation.+ /**+ * @par Completion Signature+ * @code void(asio::error_code, std::size_t) @endcode+ */ template <typename ConstBufferSequence, ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code, std::size_t)) WriteHandler ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(executor_type)>- ASIO_INITFN_AUTO_RESULT_TYPE(WriteHandler,+ ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX(WriteHandler, void (asio::error_code, std::size_t)) async_write_some(const ConstBufferSequence& buffers, ASIO_MOVE_ARG(WriteHandler) handler ASIO_DEFAULT_COMPLETION_TOKEN(executor_type))+ ASIO_INITFN_AUTO_RESULT_TYPE_SUFFIX((+ declval<typename conditional<true, Stream&, WriteHandler>::type>()+ .async_write_some(buffers,+ ASIO_MOVE_CAST(WriteHandler)(handler)))) { return next_layer_.async_write_some(buffers, ASIO_MOVE_CAST(WriteHandler)(handler));@@ -159,15 +174,24 @@ std::size_t fill(asio::error_code& ec); /// Start an asynchronous fill.+ /**+ * @par Completion Signature+ * @code void(asio::error_code, std::size_t) @endcode+ */ template < ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code, std::size_t)) ReadHandler ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(executor_type)>- ASIO_INITFN_AUTO_RESULT_TYPE(ReadHandler,+ ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX(ReadHandler, void (asio::error_code, std::size_t)) async_fill( ASIO_MOVE_ARG(ReadHandler) handler- ASIO_DEFAULT_COMPLETION_TOKEN(executor_type));+ ASIO_DEFAULT_COMPLETION_TOKEN(executor_type))+ ASIO_INITFN_AUTO_RESULT_TYPE_SUFFIX((+ async_initiate<ReadHandler,+ void (asio::error_code, std::size_t)>(+ declval<detail::initiate_async_buffered_fill<Stream> >(),+ handler, declval<detail::buffered_stream_storage*>()))); /// Read some data from the stream. Returns the number of bytes read. Throws /// an exception on failure.@@ -182,15 +206,24 @@ /// Start an asynchronous read. The buffer into which the data will be read /// must be valid for the lifetime of the asynchronous operation.+ /**+ * @par Completion Signature+ * @code void(asio::error_code, std::size_t) @endcode+ */ template <typename MutableBufferSequence, ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code, std::size_t)) ReadHandler ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(executor_type)>- ASIO_INITFN_AUTO_RESULT_TYPE(ReadHandler,+ ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX(ReadHandler, void (asio::error_code, std::size_t)) async_read_some(const MutableBufferSequence& buffers, ASIO_MOVE_ARG(ReadHandler) handler- ASIO_DEFAULT_COMPLETION_TOKEN(executor_type));+ ASIO_DEFAULT_COMPLETION_TOKEN(executor_type))+ ASIO_INITFN_AUTO_RESULT_TYPE_SUFFIX((+ async_initiate<ReadHandler,+ void (asio::error_code, std::size_t)>(+ declval<detail::initiate_async_buffered_read_some<Stream> >(),+ handler, declval<detail::buffered_stream_storage*>(), buffers))); /// Peek at the incoming data on the stream. Returns the number of bytes read. /// Throws an exception on failure.
link/modules/asio-standalone/asio/include/asio/buffered_read_stream_fwd.hpp view
@@ -2,7 +2,7 @@ // buffered_read_stream_fwd.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/buffered_stream.hpp view
@@ -2,7 +2,7 @@ // buffered_stream.hpp // ~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -56,17 +56,17 @@ /// Construct, passing the specified argument to initialise the next layer. template <typename Arg>- explicit buffered_stream(Arg& a)- : inner_stream_impl_(a),+ explicit buffered_stream(ASIO_MOVE_OR_LVALUE_ARG(Arg) a)+ : inner_stream_impl_(ASIO_MOVE_OR_LVALUE(Arg)(a)), stream_impl_(inner_stream_impl_) { } /// Construct, passing the specified argument to initialise the next layer. template <typename Arg>- explicit buffered_stream(Arg& a, std::size_t read_buffer_size,- std::size_t write_buffer_size)- : inner_stream_impl_(a, write_buffer_size),+ explicit buffered_stream(ASIO_MOVE_OR_LVALUE_ARG(Arg) a,+ std::size_t read_buffer_size, std::size_t write_buffer_size)+ : inner_stream_impl_(ASIO_MOVE_OR_LVALUE(Arg)(a), write_buffer_size), stream_impl_(inner_stream_impl_, read_buffer_size) { }@@ -125,15 +125,22 @@ } /// Start an asynchronous flush.+ /**+ * @par Completion Signature+ * @code void(asio::error_code, std::size_t) @endcode+ */ template < ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code, std::size_t)) WriteHandler ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(executor_type)>- ASIO_INITFN_AUTO_RESULT_TYPE(WriteHandler,+ ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX(WriteHandler, void (asio::error_code, std::size_t)) async_flush( ASIO_MOVE_ARG(WriteHandler) handler ASIO_DEFAULT_COMPLETION_TOKEN(executor_type))+ ASIO_INITFN_AUTO_RESULT_TYPE_SUFFIX((+ declval<buffered_write_stream<Stream>&>().async_flush(+ ASIO_MOVE_CAST(WriteHandler)(handler)))) { return stream_impl_.next_layer().async_flush( ASIO_MOVE_CAST(WriteHandler)(handler));@@ -158,15 +165,22 @@ /// Start an asynchronous write. The data being written must be valid for the /// lifetime of the asynchronous operation.+ /**+ * @par Completion Signature+ * @code void(asio::error_code, std::size_t) @endcode+ */ template <typename ConstBufferSequence, ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code, std::size_t)) WriteHandler ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(executor_type)>- ASIO_INITFN_AUTO_RESULT_TYPE(WriteHandler,+ ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX(WriteHandler, void (asio::error_code, std::size_t)) async_write_some(const ConstBufferSequence& buffers, ASIO_MOVE_ARG(WriteHandler) handler ASIO_DEFAULT_COMPLETION_TOKEN(executor_type))+ ASIO_INITFN_AUTO_RESULT_TYPE_SUFFIX((+ declval<Stream&>().async_write_some(buffers,+ ASIO_MOVE_CAST(WriteHandler)(handler)))) { return stream_impl_.async_write_some(buffers, ASIO_MOVE_CAST(WriteHandler)(handler));@@ -187,15 +201,23 @@ } /// Start an asynchronous fill.+ /**+ * @par Completion Signature+ * @code void(asio::error_code, std::size_t) @endcode+ */ template < ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code, std::size_t)) ReadHandler ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(executor_type)>- ASIO_INITFN_AUTO_RESULT_TYPE(ReadHandler,+ ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX(ReadHandler, void (asio::error_code, std::size_t)) async_fill( ASIO_MOVE_ARG(ReadHandler) handler ASIO_DEFAULT_COMPLETION_TOKEN(executor_type))+ ASIO_INITFN_AUTO_RESULT_TYPE_SUFFIX((+ declval<buffered_read_stream<+ buffered_write_stream<Stream> >&>().async_fill(+ ASIO_MOVE_CAST(ReadHandler)(handler)))) { return stream_impl_.async_fill(ASIO_MOVE_CAST(ReadHandler)(handler)); }@@ -219,15 +241,22 @@ /// Start an asynchronous read. The buffer into which the data will be read /// must be valid for the lifetime of the asynchronous operation.+ /**+ * @par Completion Signature+ * @code void(asio::error_code, std::size_t) @endcode+ */ template <typename MutableBufferSequence, ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code, std::size_t)) ReadHandler ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(executor_type)>- ASIO_INITFN_AUTO_RESULT_TYPE(ReadHandler,+ ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX(ReadHandler, void (asio::error_code, std::size_t)) async_read_some(const MutableBufferSequence& buffers, ASIO_MOVE_ARG(ReadHandler) handler ASIO_DEFAULT_COMPLETION_TOKEN(executor_type))+ ASIO_INITFN_AUTO_RESULT_TYPE_SUFFIX((+ declval<Stream&>().async_read_some(buffers,+ ASIO_MOVE_CAST(ReadHandler)(handler)))) { return stream_impl_.async_read_some(buffers, ASIO_MOVE_CAST(ReadHandler)(handler));
link/modules/asio-standalone/asio/include/asio/buffered_stream_fwd.hpp view
@@ -2,7 +2,7 @@ // buffered_stream_fwd.hpp // ~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/buffered_write_stream.hpp view
@@ -2,7 +2,7 @@ // buffered_write_stream.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -30,7 +30,13 @@ #include "asio/detail/push_options.hpp" namespace asio {+namespace detail { +template <typename> class initiate_async_buffered_flush;+template <typename> class initiate_async_buffered_write_some;++} // namespace detail+ /// Adds buffering to the write-related operations of a stream. /** * The buffered_write_stream class template can be used to add buffering to the@@ -66,16 +72,17 @@ /// Construct, passing the specified argument to initialise the next layer. template <typename Arg>- explicit buffered_write_stream(Arg& a)- : next_layer_(a),+ explicit buffered_write_stream(ASIO_MOVE_OR_LVALUE_ARG(Arg) a)+ : next_layer_(ASIO_MOVE_OR_LVALUE(Arg)(a)), storage_(default_buffer_size) { } /// Construct, passing the specified argument to initialise the next layer. template <typename Arg>- buffered_write_stream(Arg& a, std::size_t buffer_size)- : next_layer_(a),+ buffered_write_stream(ASIO_MOVE_OR_LVALUE_ARG(Arg) a,+ std::size_t buffer_size)+ : next_layer_(ASIO_MOVE_OR_LVALUE(Arg)(a)), storage_(buffer_size) { }@@ -128,15 +135,24 @@ std::size_t flush(asio::error_code& ec); /// Start an asynchronous flush.+ /**+ * @par Completion Signature+ * @code void(asio::error_code, std::size_t) @endcode+ */ template < ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code, std::size_t)) WriteHandler ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(executor_type)>- ASIO_INITFN_AUTO_RESULT_TYPE(WriteHandler,+ ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX(WriteHandler, void (asio::error_code, std::size_t)) async_flush( ASIO_MOVE_ARG(WriteHandler) handler- ASIO_DEFAULT_COMPLETION_TOKEN(executor_type));+ ASIO_DEFAULT_COMPLETION_TOKEN(executor_type))+ ASIO_INITFN_AUTO_RESULT_TYPE_SUFFIX((+ async_initiate<WriteHandler,+ void (asio::error_code, std::size_t)>(+ declval<detail::initiate_async_buffered_flush<Stream> >(),+ handler, declval<detail::buffered_stream_storage*>()))); /// Write the given data to the stream. Returns the number of bytes written. /// Throws an exception on failure.@@ -151,15 +167,24 @@ /// Start an asynchronous write. The data being written must be valid for the /// lifetime of the asynchronous operation.+ /**+ * @par Completion Signature+ * @code void(asio::error_code, std::size_t) @endcode+ */ template <typename ConstBufferSequence, ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code, std::size_t)) WriteHandler ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(executor_type)>- ASIO_INITFN_AUTO_RESULT_TYPE(WriteHandler,+ ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX(WriteHandler, void (asio::error_code, std::size_t)) async_write_some(const ConstBufferSequence& buffers, ASIO_MOVE_ARG(WriteHandler) handler- ASIO_DEFAULT_COMPLETION_TOKEN(executor_type));+ ASIO_DEFAULT_COMPLETION_TOKEN(executor_type))+ ASIO_INITFN_AUTO_RESULT_TYPE_SUFFIX((+ async_initiate<WriteHandler,+ void (asio::error_code, std::size_t)>(+ declval<detail::initiate_async_buffered_write_some<Stream> >(),+ handler, declval<detail::buffered_stream_storage*>(), buffers))); /// Read some data from the stream. Returns the number of bytes read. Throws /// an exception on failure.@@ -180,15 +205,23 @@ /// Start an asynchronous read. The buffer into which the data will be read /// must be valid for the lifetime of the asynchronous operation.+ /**+ * @par Completion Signature+ * @code void(asio::error_code, std::size_t) @endcode+ */ template <typename MutableBufferSequence, ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code, std::size_t)) ReadHandler ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(executor_type)>- ASIO_INITFN_AUTO_RESULT_TYPE(ReadHandler,+ ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX(ReadHandler, void (asio::error_code, std::size_t)) async_read_some(const MutableBufferSequence& buffers, ASIO_MOVE_ARG(ReadHandler) handler ASIO_DEFAULT_COMPLETION_TOKEN(executor_type))+ ASIO_INITFN_AUTO_RESULT_TYPE_SUFFIX((+ declval<typename conditional<true, Stream&, ReadHandler>::type>()+ .async_read_some(buffers,+ ASIO_MOVE_CAST(ReadHandler)(handler)))) { return next_layer_.async_read_some(buffers, ASIO_MOVE_CAST(ReadHandler)(handler));
link/modules/asio-standalone/asio/include/asio/buffered_write_stream_fwd.hpp view
@@ -2,7 +2,7 @@ // buffered_write_stream_fwd.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/buffers_iterator.hpp view
@@ -2,7 +2,7 @@ // buffers_iterator.hpp // ~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+ link/modules/asio-standalone/asio/include/asio/cancellation_signal.hpp view
@@ -0,0 +1,305 @@+//+// cancellation_signal.hpp+// ~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com)+//+// Distributed under the Boost Software License, Version 1.0. (See accompanying+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)+//++#ifndef ASIO_CANCELLATION_SIGNAL_HPP+#define ASIO_CANCELLATION_SIGNAL_HPP++#if defined(_MSC_VER) && (_MSC_VER >= 1200)+# pragma once+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)++#include "asio/detail/config.hpp"+#include <cassert>+#include <new>+#include <utility>+#include "asio/cancellation_type.hpp"+#include "asio/detail/cstddef.hpp"+#include "asio/detail/type_traits.hpp"+#include "asio/detail/variadic_templates.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {+namespace detail {++class cancellation_handler_base+{+public:+ virtual void call(cancellation_type_t) = 0;+ virtual std::pair<void*, std::size_t> destroy() ASIO_NOEXCEPT = 0;++protected:+ ~cancellation_handler_base() {}+};++template <typename Handler>+class cancellation_handler+ : public cancellation_handler_base+{+public:+#if defined(ASIO_HAS_VARIADIC_TEMPLATES)+ template <typename... Args>+ cancellation_handler(std::size_t size, ASIO_MOVE_ARG(Args)... args)+ : handler_(ASIO_MOVE_CAST(Args)(args)...),+ size_(size)+ {+ }+#else // defined(ASIO_HAS_VARIADIC_TEMPLATES)+ cancellation_handler(std::size_t size)+ : handler_(),+ size_(size)+ {+ }++#define ASIO_PRIVATE_HANDLER_CTOR_DEF(n) \+ template <ASIO_VARIADIC_TPARAMS(n)> \+ cancellation_handler(std::size_t size, ASIO_VARIADIC_MOVE_PARAMS(n)) \+ : handler_(ASIO_VARIADIC_MOVE_ARGS(n)), \+ size_(size) \+ { \+ } \+ /**/+ ASIO_VARIADIC_GENERATE(ASIO_PRIVATE_HANDLER_CTOR_DEF)+#undef ASIO_PRIVATE_HANDLER_CTOR_DEF+#endif // defined(ASIO_HAS_VARIADIC_TEMPLATES)++ void call(cancellation_type_t type)+ {+ handler_(type);+ }++ std::pair<void*, std::size_t> destroy() ASIO_NOEXCEPT+ {+ std::pair<void*, std::size_t> mem(this, size_);+ this->cancellation_handler::~cancellation_handler();+ return mem;+ }++ Handler& handler() ASIO_NOEXCEPT+ {+ return handler_;+ }++private:+ ~cancellation_handler()+ {+ }++ Handler handler_;+ std::size_t size_;+};++} // namespace detail++class cancellation_slot;++/// A cancellation signal with a single slot.+class cancellation_signal+{+public:+ ASIO_CONSTEXPR cancellation_signal()+ : handler_(0)+ {+ }++ ASIO_DECL ~cancellation_signal();++ /// Emits the signal and causes invocation of the slot's handler, if any.+ void emit(cancellation_type_t type)+ {+ if (handler_)+ handler_->call(type);+ }++ /// Returns the single slot associated with the signal.+ /**+ * The signal object must remain valid for as long the slot may be used.+ * Destruction of the signal invalidates the slot.+ */+ cancellation_slot slot() ASIO_NOEXCEPT;++private:+ cancellation_signal(const cancellation_signal&) ASIO_DELETED;+ cancellation_signal& operator=(const cancellation_signal&) ASIO_DELETED;++ detail::cancellation_handler_base* handler_;+};++/// A slot associated with a cancellation signal.+class cancellation_slot+{+public:+ /// Creates a slot that is not connected to any cancellation signal.+ ASIO_CONSTEXPR cancellation_slot()+ : handler_(0)+ {+ }++#if defined(ASIO_HAS_VARIADIC_TEMPLATES) \+ || defined(GENERATING_DOCUMENTATION)+ /// Installs a handler into the slot, constructing the new object directly.+ /**+ * Destroys any existing handler in the slot, then installs the new handler,+ * constructing it with the supplied @c args.+ *+ * The handler is a function object to be called when the signal is emitted.+ * The signature of the handler must be+ * @code void handler(asio::cancellation_type_t); @endcode+ *+ * @param args Arguments to be passed to the @c CancellationHandler object's+ * constructor.+ *+ * @returns A reference to the newly installed handler.+ *+ * @note Handlers installed into the slot via @c emplace are not required to+ * be copy constructible or move constructible.+ */+ template <typename CancellationHandler, typename... Args>+ CancellationHandler& emplace(ASIO_MOVE_ARG(Args)... args)+ {+ typedef detail::cancellation_handler<CancellationHandler>+ cancellation_handler_type;+ auto_delete_helper del = { prepare_memory(+ sizeof(cancellation_handler_type),+ ASIO_ALIGNOF(CancellationHandler)) };+ cancellation_handler_type* handler_obj =+ new (del.mem.first) cancellation_handler_type(+ del.mem.second, ASIO_MOVE_CAST(Args)(args)...);+ del.mem.first = 0;+ *handler_ = handler_obj;+ return handler_obj->handler();+ }+#else // defined(ASIO_HAS_VARIADIC_TEMPLATES)+ // || defined(GENERATING_DOCUMENTATION)+ template <typename CancellationHandler>+ CancellationHandler& emplace()+ {+ typedef detail::cancellation_handler<CancellationHandler>+ cancellation_handler_type;+ auto_delete_helper del = { prepare_memory(+ sizeof(cancellation_handler_type),+ ASIO_ALIGNOF(CancellationHandler)) };+ cancellation_handler_type* handler_obj =+ new (del.mem.first) cancellation_handler_type(del.mem.second);+ del.mem.first = 0;+ *handler_ = handler_obj;+ return handler_obj->handler();+ }++#define ASIO_PRIVATE_HANDLER_EMPLACE_DEF(n) \+ template <typename CancellationHandler, ASIO_VARIADIC_TPARAMS(n)> \+ CancellationHandler& emplace(ASIO_VARIADIC_MOVE_PARAMS(n)) \+ { \+ typedef detail::cancellation_handler<CancellationHandler> \+ cancellation_handler_type; \+ auto_delete_helper del = { prepare_memory( \+ sizeof(cancellation_handler_type), \+ ASIO_ALIGNOF(CancellationHandler)) }; \+ cancellation_handler_type* handler_obj = \+ new (del.mem.first) cancellation_handler_type( \+ del.mem.second, ASIO_VARIADIC_MOVE_ARGS(n)); \+ del.mem.first = 0; \+ *handler_ = handler_obj; \+ return handler_obj->handler(); \+ } \+ /**/+ ASIO_VARIADIC_GENERATE(ASIO_PRIVATE_HANDLER_EMPLACE_DEF)+#undef ASIO_PRIVATE_HANDLER_EMPLACE_DEF+#endif // defined(ASIO_HAS_VARIADIC_TEMPLATES)++ /// Installs a handler into the slot.+ /**+ * Destroys any existing handler in the slot, then installs the new handler,+ * constructing it as a decay-copy of the supplied handler.+ *+ * The handler is a function object to be called when the signal is emitted.+ * The signature of the handler must be+ * @code void handler(asio::cancellation_type_t); @endcode+ *+ * @param handler The handler to be installed.+ *+ * @returns A reference to the newly installed handler.+ */+ template <typename CancellationHandler>+ typename decay<CancellationHandler>::type& assign(+ ASIO_MOVE_ARG(CancellationHandler) handler)+ {+ return this->emplace<typename decay<CancellationHandler>::type>(+ ASIO_MOVE_CAST(CancellationHandler)(handler));+ }++ /// Clears the slot.+ /**+ * Destroys any existing handler in the slot.+ */+ ASIO_DECL void clear();++ /// Returns whether the slot is connected to a signal.+ ASIO_CONSTEXPR bool is_connected() const ASIO_NOEXCEPT+ {+ return handler_ != 0;+ }++ /// Returns whether the slot is connected and has an installed handler.+ ASIO_CONSTEXPR bool has_handler() const ASIO_NOEXCEPT+ {+ return handler_ != 0 && *handler_ != 0;+ }++ /// Compare two slots for equality.+ friend ASIO_CONSTEXPR bool operator==(const cancellation_slot& lhs,+ const cancellation_slot& rhs) ASIO_NOEXCEPT+ {+ return lhs.handler_ == rhs.handler_;+ }++ /// Compare two slots for inequality.+ friend ASIO_CONSTEXPR bool operator!=(const cancellation_slot& lhs,+ const cancellation_slot& rhs) ASIO_NOEXCEPT+ {+ return lhs.handler_ != rhs.handler_;+ }++private:+ friend class cancellation_signal;++ ASIO_CONSTEXPR cancellation_slot(int,+ detail::cancellation_handler_base** handler)+ : handler_(handler)+ {+ }++ ASIO_DECL std::pair<void*, std::size_t> prepare_memory(+ std::size_t size, std::size_t align);++ struct auto_delete_helper+ {+ std::pair<void*, std::size_t> mem;++ ASIO_DECL ~auto_delete_helper();+ };++ detail::cancellation_handler_base** handler_;+};++inline cancellation_slot cancellation_signal::slot() ASIO_NOEXCEPT+{+ return cancellation_slot(0, &handler_);+}++} // namespace asio++#include "asio/detail/pop_options.hpp"++#if defined(ASIO_HEADER_ONLY)+# include "asio/impl/cancellation_signal.ipp"+#endif // defined(ASIO_HEADER_ONLY)++#endif // ASIO_CANCELLATION_SIGNAL_HPP
+ link/modules/asio-standalone/asio/include/asio/cancellation_state.hpp view
@@ -0,0 +1,235 @@+//+// cancellation_state.hpp+// ~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com)+//+// Distributed under the Boost Software License, Version 1.0. (See accompanying+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)+//++#ifndef ASIO_CANCELLATION_STATE_HPP+#define ASIO_CANCELLATION_STATE_HPP++#if defined(_MSC_VER) && (_MSC_VER >= 1200)+# pragma once+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)++#include "asio/detail/config.hpp"+#include <cassert>+#include <new>+#include <utility>+#include "asio/cancellation_signal.hpp"+#include "asio/detail/cstddef.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {++/// A simple cancellation signal propagation filter.+template <cancellation_type_t Mask>+struct cancellation_filter+{+ /// Returns <tt>type & Mask</tt>.+ cancellation_type_t operator()(+ cancellation_type_t type) const ASIO_NOEXCEPT+ {+ return type & Mask;+ }+};++/// A cancellation filter that disables cancellation.+typedef cancellation_filter<cancellation_type::none>+ disable_cancellation;++/// A cancellation filter that enables terminal cancellation only.+typedef cancellation_filter<cancellation_type::terminal>+ enable_terminal_cancellation;++#if defined(GENERATING_DOCUMENTATION)++/// A cancellation filter that enables terminal and partial cancellation.+typedef cancellation_filter<+ cancellation_type::terminal | cancellation_type::partial>+ enable_partial_cancellation;++/// A cancellation filter that enables terminal, partial and total cancellation.+typedef cancellation_filter<cancellation_type::terminal+ | cancellation_type::partial | cancellation_type::total>+ enable_total_cancellation;++#else // defined(GENERATING_DOCUMENTATION)++typedef cancellation_filter<+ static_cast<cancellation_type_t>(+ static_cast<unsigned int>(cancellation_type::terminal)+ | static_cast<unsigned int>(cancellation_type::partial))>+ enable_partial_cancellation;++typedef cancellation_filter<+ static_cast<cancellation_type_t>(+ static_cast<unsigned int>(cancellation_type::terminal)+ | static_cast<unsigned int>(cancellation_type::partial)+ | static_cast<unsigned int>(cancellation_type::total))>+ enable_total_cancellation;++#endif // defined(GENERATING_DOCUMENTATION)++/// A cancellation state is used for chaining signals and slots in compositions.+class cancellation_state+{+public:+ /// Construct a disconnected cancellation state.+ ASIO_CONSTEXPR cancellation_state() ASIO_NOEXCEPT+ : impl_(0)+ {+ }++ /// Construct and attach to a parent slot to create a new child slot.+ /**+ * Initialises the cancellation state so that it allows terminal cancellation+ * only. Equivalent to <tt>cancellation_state(slot,+ * enable_terminal_cancellation())</tt>.+ *+ * @param slot The parent cancellation slot to which the state will be+ * attached.+ */+ template <typename CancellationSlot>+ ASIO_CONSTEXPR explicit cancellation_state(CancellationSlot slot)+ : impl_(slot.is_connected() ? &slot.template emplace<impl<> >() : 0)+ {+ }++ /// Construct and attach to a parent slot to create a new child slot.+ /**+ * @param slot The parent cancellation slot to which the state will be+ * attached.+ *+ * @param filter A function object that is used to transform incoming+ * cancellation signals as they are received from the parent slot. This+ * function object must have the signature:+ * @code asio::cancellation_type_t filter(+ * asio::cancellation_type_t); @endcode+ *+ * The library provides the following pre-defined cancellation filters:+ *+ * @li asio::disable_cancellation+ * @li asio::enable_terminal_cancellation+ * @li asio::enable_partial_cancellation+ * @li asio::enable_total_cancellation+ */+ template <typename CancellationSlot, typename Filter>+ ASIO_CONSTEXPR cancellation_state(CancellationSlot slot, Filter filter)+ : impl_(slot.is_connected()+ ? &slot.template emplace<impl<Filter, Filter> >(filter, filter)+ : 0)+ {+ }++ /// Construct and attach to a parent slot to create a new child slot.+ /**+ * @param slot The parent cancellation slot to which the state will be+ * attached.+ *+ * @param in_filter A function object that is used to transform incoming+ * cancellation signals as they are received from the parent slot. This+ * function object must have the signature:+ * @code asio::cancellation_type_t in_filter(+ * asio::cancellation_type_t); @endcode+ *+ * @param out_filter A function object that is used to transform outcoming+ * cancellation signals as they are relayed to the child slot. This function+ * object must have the signature:+ * @code asio::cancellation_type_t out_filter(+ * asio::cancellation_type_t); @endcode+ *+ * The library provides the following pre-defined cancellation filters:+ *+ * @li asio::disable_cancellation+ * @li asio::enable_terminal_cancellation+ * @li asio::enable_partial_cancellation+ * @li asio::enable_total_cancellation+ */+ template <typename CancellationSlot, typename InFilter, typename OutFilter>+ ASIO_CONSTEXPR cancellation_state(CancellationSlot slot,+ InFilter in_filter, OutFilter out_filter)+ : impl_(slot.is_connected()+ ? &slot.template emplace<impl<InFilter, OutFilter> >(+ ASIO_MOVE_CAST(InFilter)(in_filter),+ ASIO_MOVE_CAST(OutFilter)(out_filter))+ : 0)+ {+ }++ /// Returns the single child slot associated with the state.+ /**+ * This sub-slot is used with the operations that are being composed.+ */+ ASIO_CONSTEXPR cancellation_slot slot() const ASIO_NOEXCEPT+ {+ return impl_ ? impl_->signal_.slot() : cancellation_slot();+ }++ /// Returns the cancellation types that have been triggered.+ cancellation_type_t cancelled() const ASIO_NOEXCEPT+ {+ return impl_ ? impl_->cancelled_ : cancellation_type_t();+ }++ /// Clears the specified cancellation types, if they have been triggered.+ void clear(cancellation_type_t mask = cancellation_type::all)+ ASIO_NOEXCEPT+ {+ if (impl_)+ impl_->cancelled_ &= ~mask;+ }++private:+ struct impl_base+ {+ impl_base()+ : cancelled_()+ {+ }++ cancellation_signal signal_;+ cancellation_type_t cancelled_;+ };++ template <+ typename InFilter = enable_terminal_cancellation,+ typename OutFilter = InFilter>+ struct impl : impl_base+ {+ impl()+ : in_filter_(),+ out_filter_()+ {+ }++ impl(InFilter in_filter, OutFilter out_filter)+ : in_filter_(ASIO_MOVE_CAST(InFilter)(in_filter)),+ out_filter_(ASIO_MOVE_CAST(OutFilter)(out_filter))+ {+ }++ void operator()(cancellation_type_t in)+ {+ this->cancelled_ = in_filter_(in);+ cancellation_type_t out = out_filter_(this->cancelled_);+ if (out != cancellation_type::none)+ this->signal_.emit(out);+ }++ InFilter in_filter_;+ OutFilter out_filter_;+ };++ impl_base* impl_;+};++} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // ASIO_CANCELLATION_STATE_HPP
+ link/modules/asio-standalone/asio/include/asio/cancellation_type.hpp view
@@ -0,0 +1,174 @@+//+// cancellation_type.hpp+// ~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com)+//+// Distributed under the Boost Software License, Version 1.0. (See accompanying+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)+//++#ifndef ASIO_CANCELLATION_TYPE_HPP+#define ASIO_CANCELLATION_TYPE_HPP++#if defined(_MSC_VER) && (_MSC_VER >= 1200)+# pragma once+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)++#include "asio/detail/config.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {++# if defined(GENERATING_DOCUMENTATION)++/// Enumeration representing the different types of cancellation that may+/// be requested from or implemented by an asynchronous operation.+enum cancellation_type+{+ /// Bitmask representing no types of cancellation.+ none = 0,++ /// Requests cancellation where, following a successful cancellation, the only+ /// safe operations on the I/O object are closure or destruction.+ terminal = 1,++ /// Requests cancellation where a successful cancellation may result in+ /// partial side effects or no side effects. Following cancellation, the I/O+ /// object is in a well-known state, and may be used for further operations.+ partial = 2,++ /// Requests cancellation where a successful cancellation results in no+ /// apparent side effects. Following cancellation, the I/O object is in the+ /// same observable state as it was prior to the operation.+ total = 4,++ /// Bitmask representing all types of cancellation.+ all = 0xFFFFFFFF+};++/// Portability typedef.+typedef cancellation_type cancellation_type_t;++#elif defined(ASIO_HAS_ENUM_CLASS)++enum class cancellation_type : unsigned int+{+ none = 0,+ terminal = 1,+ partial = 2,+ total = 4,+ all = 0xFFFFFFFF+};++typedef cancellation_type cancellation_type_t;++#else // defined(ASIO_HAS_ENUM_CLASS)++namespace cancellation_type {++enum cancellation_type_t+{+ none = 0,+ terminal = 1,+ partial = 2,+ total = 4,+ all = 0xFFFFFFFF+};++} // namespace cancellation_type++typedef cancellation_type::cancellation_type_t cancellation_type_t;++#endif // defined(ASIO_HAS_ENUM_CLASS)++/// Negation operator.+/**+ * @relates cancellation_type+ */+inline ASIO_CONSTEXPR bool operator!(cancellation_type_t x)+{+ return static_cast<unsigned int>(x) == 0;+}++/// Bitwise and operator.+/**+ * @relates cancellation_type+ */+inline ASIO_CONSTEXPR cancellation_type_t operator&(+ cancellation_type_t x, cancellation_type_t y)+{+ return static_cast<cancellation_type_t>(+ static_cast<unsigned int>(x) & static_cast<unsigned int>(y));+}++/// Bitwise or operator.+/**+ * @relates cancellation_type+ */+inline ASIO_CONSTEXPR cancellation_type_t operator|(+ cancellation_type_t x, cancellation_type_t y)+{+ return static_cast<cancellation_type_t>(+ static_cast<unsigned int>(x) | static_cast<unsigned int>(y));+}++/// Bitwise xor operator.+/**+ * @relates cancellation_type+ */+inline ASIO_CONSTEXPR cancellation_type_t operator^(+ cancellation_type_t x, cancellation_type_t y)+{+ return static_cast<cancellation_type_t>(+ static_cast<unsigned int>(x) ^ static_cast<unsigned int>(y));+}++/// Bitwise negation operator.+/**+ * @relates cancellation_type+ */+inline ASIO_CONSTEXPR cancellation_type_t operator~(cancellation_type_t x)+{+ return static_cast<cancellation_type_t>(~static_cast<unsigned int>(x));+}++/// Bitwise and-assignment operator.+/**+ * @relates cancellation_type+ */+inline cancellation_type_t& operator&=(+ cancellation_type_t& x, cancellation_type_t y)+{+ x = x & y;+ return x;+}++/// Bitwise or-assignment operator.+/**+ * @relates cancellation_type+ */+inline cancellation_type_t& operator|=(+ cancellation_type_t& x, cancellation_type_t y)+{+ x = x | y;+ return x;+}++/// Bitwise xor-assignment operator.+/**+ * @relates cancellation_type+ */+inline cancellation_type_t& operator^=(+ cancellation_type_t& x, cancellation_type_t y)+{+ x = x ^ y;+ return x;+}++} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // ASIO_CANCELLATION_TYPE_HPP
link/modules/asio-standalone/asio/include/asio/co_spawn.hpp view
@@ -2,7 +2,7 @@ // co_spawn.hpp // ~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -54,11 +54,14 @@ * @param a The asio::awaitable object that is the result of calling the * coroutine's entry point function. *- * @param token The completion token that will handle the notification that+ * @param token The @ref completion_token that will handle the notification that * the thread of execution has completed. The function signature of the * completion handler must be: * @code void handler(std::exception_ptr, T); @endcode *+ * @par Completion Signature+ * @code void(std::exception_ptr, T) @endcode+ * * @par Example * @code * asio::awaitable<std::size_t> echo(tcp::socket socket)@@ -95,6 +98,11 @@ * std::cout << "transferred " << n << "\n"; * }); * @endcode+ *+ * @par Per-Operation Cancellation+ * The new thread of execution is created with a cancellation state that+ * supports @c cancellation_type::terminal values only. To change the+ * cancellation state, call asio::this_coro::reset_cancellation_state. */ template <typename Executor, typename T, typename AwaitableExecutor, ASIO_COMPLETION_TOKEN_FOR(@@ -105,10 +113,10 @@ co_spawn(const Executor& ex, awaitable<T, AwaitableExecutor> a, CompletionToken&& token ASIO_DEFAULT_COMPLETION_TOKEN(Executor),- typename enable_if<+ typename constraint< (is_executor<Executor>::value || execution::is_executor<Executor>::value) && is_convertible<Executor, AwaitableExecutor>::value- >::type* = 0);+ >::type = 0); /// Spawn a new coroutined-based thread of execution. /**@@ -118,11 +126,14 @@ * @param a The asio::awaitable object that is the result of calling the * coroutine's entry point function. *- * @param token The completion token that will handle the notification that+ * @param token The @ref completion_token that will handle the notification that * the thread of execution has completed. The function signature of the * completion handler must be: * @code void handler(std::exception_ptr); @endcode *+ * @par Completion Signature+ * @code void(std::exception_ptr) @endcode+ * * @par Example * @code * asio::awaitable<void> echo(tcp::socket socket)@@ -151,6 +162,11 @@ * echo(std::move(my_tcp_socket)), * asio::detached); * @endcode+ *+ * @par Per-Operation Cancellation+ * The new thread of execution is created with a cancellation state that+ * supports @c cancellation_type::terminal values only. To change the+ * cancellation state, call asio::this_coro::reset_cancellation_state. */ template <typename Executor, typename AwaitableExecutor, ASIO_COMPLETION_TOKEN_FOR(@@ -161,10 +177,10 @@ co_spawn(const Executor& ex, awaitable<void, AwaitableExecutor> a, CompletionToken&& token ASIO_DEFAULT_COMPLETION_TOKEN(Executor),- typename enable_if<+ typename constraint< (is_executor<Executor>::value || execution::is_executor<Executor>::value) && is_convertible<Executor, AwaitableExecutor>::value- >::type* = 0);+ >::type = 0); /// Spawn a new coroutined-based thread of execution. /**@@ -174,11 +190,14 @@ * @param a The asio::awaitable object that is the result of calling the * coroutine's entry point function. *- * @param token The completion token that will handle the notification that+ * @param token The @ref completion_token that will handle the notification that * the thread of execution has completed. The function signature of the * completion handler must be: * @code void handler(std::exception_ptr); @endcode *+ * @par Completion Signature+ * @code void(std::exception_ptr, T) @endcode+ * * @par Example * @code * asio::awaitable<std::size_t> echo(tcp::socket socket)@@ -215,6 +234,11 @@ * std::cout << "transferred " << n << "\n"; * }); * @endcode+ *+ * @par Per-Operation Cancellation+ * The new thread of execution is created with a cancellation state that+ * supports @c cancellation_type::terminal values only. To change the+ * cancellation state, call asio::this_coro::reset_cancellation_state. */ template <typename ExecutionContext, typename T, typename AwaitableExecutor, ASIO_COMPLETION_TOKEN_FOR(@@ -227,11 +251,11 @@ CompletionToken&& token ASIO_DEFAULT_COMPLETION_TOKEN( typename ExecutionContext::executor_type),- typename enable_if<+ typename constraint< is_convertible<ExecutionContext&, execution_context&>::value && is_convertible<typename ExecutionContext::executor_type, AwaitableExecutor>::value- >::type* = 0);+ >::type = 0); /// Spawn a new coroutined-based thread of execution. /**@@ -241,11 +265,14 @@ * @param a The asio::awaitable object that is the result of calling the * coroutine's entry point function. *- * @param token The completion token that will handle the notification that+ * @param token The @ref completion_token that will handle the notification that * the thread of execution has completed. The function signature of the * completion handler must be: * @code void handler(std::exception_ptr); @endcode *+ * @par Completion Signature+ * @code void(std::exception_ptr) @endcode+ * * @par Example * @code * asio::awaitable<void> echo(tcp::socket socket)@@ -274,6 +301,11 @@ * echo(std::move(my_tcp_socket)), * asio::detached); * @endcode+ *+ * @par Per-Operation Cancellation+ * The new thread of execution is created with a cancellation state that+ * supports @c cancellation_type::terminal values only. To change the+ * cancellation state, call asio::this_coro::reset_cancellation_state. */ template <typename ExecutionContext, typename AwaitableExecutor, ASIO_COMPLETION_TOKEN_FOR(@@ -286,11 +318,11 @@ CompletionToken&& token ASIO_DEFAULT_COMPLETION_TOKEN( typename ExecutionContext::executor_type),- typename enable_if<+ typename constraint< is_convertible<ExecutionContext&, execution_context&>::value && is_convertible<typename ExecutionContext::executor_type, AwaitableExecutor>::value- >::type* = 0);+ >::type = 0); /// Spawn a new coroutined-based thread of execution. /**@@ -301,14 +333,19 @@ * @c asio::awaitable<R,E> that will be used as the coroutine's entry * point. *- * @param token The completion token that will handle the notification that the- * thread of execution has completed. If @c R is @c void, the function+ * @param token The @ref completion_token that will handle the notification+ * that the thread of execution has completed. If @c R is @c void, the function * signature of the completion handler must be: * * @code void handler(std::exception_ptr); @endcode * Otherwise, the function signature of the completion handler must be: * @code void handler(std::exception_ptr, R); @endcode *+ * @par Completion Signature+ * @code void(std::exception_ptr, R) @endcode+ * where @c R is the first template argument to the @c awaitable returned by the+ * supplied function object @c F:+ * @code asio::awaitable<R, AwaitableExecutor> F() @endcode * * @par Example * @code@@ -361,6 +398,11 @@ * } * }, asio::detached); * @endcode+ *+ * @par Per-Operation Cancellation+ * The new thread of execution is created with a cancellation state that+ * supports @c cancellation_type::terminal values only. To change the+ * cancellation state, call asio::this_coro::reset_cancellation_state. */ template <typename Executor, typename F, ASIO_COMPLETION_TOKEN_FOR(typename detail::awaitable_signature<@@ -371,9 +413,9 @@ co_spawn(const Executor& ex, F&& f, CompletionToken&& token ASIO_DEFAULT_COMPLETION_TOKEN(Executor),- typename enable_if<+ typename constraint< is_executor<Executor>::value || execution::is_executor<Executor>::value- >::type* = 0);+ >::type = 0); /// Spawn a new coroutined-based thread of execution. /**@@ -384,14 +426,19 @@ * @c asio::awaitable<R,E> that will be used as the coroutine's entry * point. *- * @param token The completion token that will handle the notification that the- * thread of execution has completed. If @c R is @c void, the function+ * @param token The @ref completion_token that will handle the notification+ * that the thread of execution has completed. If @c R is @c void, the function * signature of the completion handler must be: * * @code void handler(std::exception_ptr); @endcode * Otherwise, the function signature of the completion handler must be: * @code void handler(std::exception_ptr, R); @endcode *+ * @par Completion Signature+ * @code void(std::exception_ptr, R) @endcode+ * where @c R is the first template argument to the @c awaitable returned by the+ * supplied function object @c F:+ * @code asio::awaitable<R, AwaitableExecutor> F() @endcode * * @par Example * @code@@ -444,6 +491,11 @@ * } * }, asio::detached); * @endcode+ *+ * @par Per-Operation Cancellation+ * The new thread of execution is created with a cancellation state that+ * supports @c cancellation_type::terminal values only. To change the+ * cancellation state, call asio::this_coro::reset_cancellation_state. */ template <typename ExecutionContext, typename F, ASIO_COMPLETION_TOKEN_FOR(typename detail::awaitable_signature<@@ -456,9 +508,9 @@ CompletionToken&& token ASIO_DEFAULT_COMPLETION_TOKEN( typename ExecutionContext::executor_type),- typename enable_if<+ typename constraint< is_convertible<ExecutionContext&, execution_context&>::value- >::type* = 0);+ >::type = 0); } // namespace asio
link/modules/asio-standalone/asio/include/asio/completion_condition.hpp view
@@ -2,7 +2,7 @@ // completion_condition.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/compose.hpp view
@@ -2,7 +2,7 @@ // compose.hpp // ~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -16,12 +16,308 @@ #endif // defined(_MSC_VER) && (_MSC_VER >= 1200) #include "asio/detail/config.hpp"+#include "asio/associated_executor.hpp" #include "asio/async_result.hpp"+#include "asio/detail/base_from_cancellation_state.hpp"+#include "asio/detail/composed_work.hpp"+#include "asio/detail/handler_alloc_helpers.hpp"+#include "asio/detail/handler_cont_helpers.hpp"+#include "asio/detail/handler_invoke_helpers.hpp"+#include "asio/detail/type_traits.hpp"+#include "asio/detail/variadic_templates.hpp" #include "asio/detail/push_options.hpp" namespace asio {+namespace detail { +#if defined(ASIO_HAS_VARIADIC_TEMPLATES)+template <typename Impl, typename Work, typename Handler, typename Signature>+class composed_op;++template <typename Impl, typename Work, typename Handler,+ typename R, typename... Args>+class composed_op<Impl, Work, Handler, R(Args...)>+#else // defined(ASIO_HAS_VARIADIC_TEMPLATES)+template <typename Impl, typename Work, typename Handler, typename Signature>+class composed_op+#endif // defined(ASIO_HAS_VARIADIC_TEMPLATES)+ : public base_from_cancellation_state<Handler>+{+public:+ template <typename I, typename W, typename H>+ composed_op(ASIO_MOVE_ARG(I) impl,+ ASIO_MOVE_ARG(W) work,+ ASIO_MOVE_ARG(H) handler)+ : base_from_cancellation_state<Handler>(+ handler, enable_terminal_cancellation()),+ impl_(ASIO_MOVE_CAST(I)(impl)),+ work_(ASIO_MOVE_CAST(W)(work)),+ handler_(ASIO_MOVE_CAST(H)(handler)),+ invocations_(0)+ {+ }++#if defined(ASIO_HAS_MOVE)+ composed_op(composed_op&& other)+ : base_from_cancellation_state<Handler>(+ ASIO_MOVE_CAST(base_from_cancellation_state<+ Handler>)(other)),+ impl_(ASIO_MOVE_CAST(Impl)(other.impl_)),+ work_(ASIO_MOVE_CAST(Work)(other.work_)),+ handler_(ASIO_MOVE_CAST(Handler)(other.handler_)),+ invocations_(other.invocations_)+ {+ }+#endif // defined(ASIO_HAS_MOVE)++ typedef typename composed_work_guard<+ typename Work::head_type>::executor_type io_executor_type;++ io_executor_type get_io_executor() const ASIO_NOEXCEPT+ {+ return work_.head_.get_executor();+ }++ typedef typename associated_executor<Handler, io_executor_type>::type+ executor_type;++ executor_type get_executor() const ASIO_NOEXCEPT+ {+ return (get_associated_executor)(handler_, work_.head_.get_executor());+ }++ typedef typename associated_allocator<Handler,+ std::allocator<void> >::type allocator_type;++ allocator_type get_allocator() const ASIO_NOEXCEPT+ {+ return (get_associated_allocator)(handler_, std::allocator<void>());+ }++#if defined(ASIO_HAS_VARIADIC_TEMPLATES)++ template<typename... T>+ void operator()(ASIO_MOVE_ARG(T)... t)+ {+ if (invocations_ < ~0u)+ ++invocations_;+ this->get_cancellation_state().slot().clear();+ impl_(*this, ASIO_MOVE_CAST(T)(t)...);+ }++ void complete(Args... args)+ {+ this->work_.reset();+ ASIO_MOVE_OR_LVALUE(Handler)(this->handler_)(+ ASIO_MOVE_CAST(Args)(args)...);+ }++#else // defined(ASIO_HAS_VARIADIC_TEMPLATES)++ void operator()()+ {+ if (invocations_ < ~0u)+ ++invocations_;+ this->get_cancellation_state().slot().clear();+ impl_(*this);+ }++ void complete()+ {+ this->work_.reset();+ ASIO_MOVE_OR_LVALUE(Handler)(this->handler_)();+ }++#define ASIO_PRIVATE_COMPOSED_OP_DEF(n) \+ template<ASIO_VARIADIC_TPARAMS(n)> \+ void operator()(ASIO_VARIADIC_MOVE_PARAMS(n)) \+ { \+ if (invocations_ < ~0u) \+ ++invocations_; \+ this->get_cancellation_state().slot().clear(); \+ impl_(*this, ASIO_VARIADIC_MOVE_ARGS(n)); \+ } \+ \+ template<ASIO_VARIADIC_TPARAMS(n)> \+ void complete(ASIO_VARIADIC_MOVE_PARAMS(n)) \+ { \+ this->work_.reset(); \+ ASIO_MOVE_OR_LVALUE(Handler)(this->handler_)( \+ ASIO_VARIADIC_MOVE_ARGS(n)); \+ } \+ /**/+ ASIO_VARIADIC_GENERATE(ASIO_PRIVATE_COMPOSED_OP_DEF)+#undef ASIO_PRIVATE_COMPOSED_OP_DEF++#endif // defined(ASIO_HAS_VARIADIC_TEMPLATES)++ void reset_cancellation_state()+ {+ base_from_cancellation_state<Handler>::reset_cancellation_state(handler_);+ }++ template <typename Filter>+ void reset_cancellation_state(ASIO_MOVE_ARG(Filter) filter)+ {+ base_from_cancellation_state<Handler>::reset_cancellation_state(handler_,+ ASIO_MOVE_CAST(Filter)(filter));+ }++ template <typename InFilter, typename OutFilter>+ void reset_cancellation_state(ASIO_MOVE_ARG(InFilter) in_filter,+ ASIO_MOVE_ARG(OutFilter) out_filter)+ {+ base_from_cancellation_state<Handler>::reset_cancellation_state(handler_,+ ASIO_MOVE_CAST(InFilter)(in_filter),+ ASIO_MOVE_CAST(OutFilter)(out_filter));+ }++ cancellation_type_t cancelled() const ASIO_NOEXCEPT+ {+ return base_from_cancellation_state<Handler>::cancelled();+ }++//private:+ Impl impl_;+ Work work_;+ Handler handler_;+ unsigned invocations_;+};++template <typename Impl, typename Work, typename Handler, typename Signature>+inline asio_handler_allocate_is_deprecated+asio_handler_allocate(std::size_t size,+ composed_op<Impl, Work, Handler, Signature>* this_handler)+{+#if defined(ASIO_NO_DEPRECATED)+ asio_handler_alloc_helpers::allocate(size, this_handler->handler_);+ return asio_handler_allocate_is_no_longer_used();+#else // defined(ASIO_NO_DEPRECATED)+ return asio_handler_alloc_helpers::allocate(+ size, this_handler->handler_);+#endif // defined(ASIO_NO_DEPRECATED)+}++template <typename Impl, typename Work, typename Handler, typename Signature>+inline asio_handler_deallocate_is_deprecated+asio_handler_deallocate(void* pointer, std::size_t size,+ composed_op<Impl, Work, Handler, Signature>* this_handler)+{+ asio_handler_alloc_helpers::deallocate(+ pointer, size, this_handler->handler_);+#if defined(ASIO_NO_DEPRECATED)+ return asio_handler_deallocate_is_no_longer_used();+#endif // defined(ASIO_NO_DEPRECATED)+}++template <typename Impl, typename Work, typename Handler, typename Signature>+inline bool asio_handler_is_continuation(+ composed_op<Impl, Work, Handler, Signature>* this_handler)+{+ return this_handler->invocations_ > 1 ? true+ : asio_handler_cont_helpers::is_continuation(+ this_handler->handler_);+}++template <typename Function, typename Impl,+ typename Work, typename Handler, typename Signature>+inline asio_handler_invoke_is_deprecated+asio_handler_invoke(Function& function,+ composed_op<Impl, Work, Handler, Signature>* this_handler)+{+ asio_handler_invoke_helpers::invoke(+ function, this_handler->handler_);+#if defined(ASIO_NO_DEPRECATED)+ return asio_handler_invoke_is_no_longer_used();+#endif // defined(ASIO_NO_DEPRECATED)+}++template <typename Function, typename Impl,+ typename Work, typename Handler, typename Signature>+inline asio_handler_invoke_is_deprecated+asio_handler_invoke(const Function& function,+ composed_op<Impl, Work, Handler, Signature>* this_handler)+{+ asio_handler_invoke_helpers::invoke(+ function, this_handler->handler_);+#if defined(ASIO_NO_DEPRECATED)+ return asio_handler_invoke_is_no_longer_used();+#endif // defined(ASIO_NO_DEPRECATED)+}++template <typename Signature, typename Executors>+class initiate_composed_op+{+public:+ typedef typename composed_io_executors<Executors>::head_type executor_type;++ template <typename T>+ explicit initiate_composed_op(int, ASIO_MOVE_ARG(T) executors)+ : executors_(ASIO_MOVE_CAST(T)(executors))+ {+ }++ executor_type get_executor() const ASIO_NOEXCEPT+ {+ return executors_.head_;+ }++ template <typename Handler, typename Impl>+ void operator()(ASIO_MOVE_ARG(Handler) handler,+ ASIO_MOVE_ARG(Impl) impl) const+ {+ composed_op<typename decay<Impl>::type, composed_work<Executors>,+ typename decay<Handler>::type, Signature>(+ ASIO_MOVE_CAST(Impl)(impl),+ composed_work<Executors>(executors_),+ ASIO_MOVE_CAST(Handler)(handler))();+ }++private:+ composed_io_executors<Executors> executors_;+};++template <typename Signature, typename Executors>+inline initiate_composed_op<Signature, Executors> make_initiate_composed_op(+ ASIO_MOVE_ARG(composed_io_executors<Executors>) executors)+{+ return initiate_composed_op<Signature, Executors>(0,+ ASIO_MOVE_CAST(composed_io_executors<Executors>)(executors));+}++} // namespace detail++#if !defined(GENERATING_DOCUMENTATION)++template <template <typename, typename> class Associator,+ typename Impl, typename Work, typename Handler,+ typename Signature, typename DefaultCandidate>+struct associator<Associator,+ detail::composed_op<Impl, Work, Handler, Signature>,+ DefaultCandidate>+ : Associator<Handler, DefaultCandidate>+{+ static typename Associator<Handler, DefaultCandidate>::type+ get(const detail::composed_op<Impl, Work, Handler, Signature>& h)+ ASIO_NOEXCEPT+ {+ return Associator<Handler, DefaultCandidate>::get(h.handler_);+ }++ static ASIO_AUTO_RETURN_TYPE_PREFIX2(+ typename Associator<Handler, DefaultCandidate>::type)+ get(const detail::composed_op<Impl, Work, Handler, Signature>& h,+ const DefaultCandidate& c) ASIO_NOEXCEPT+ ASIO_AUTO_RETURN_TYPE_SUFFIX((+ Associator<Handler, DefaultCandidate>::get(h.handler_, c)))+ {+ return Associator<Handler, DefaultCandidate>::get(h.handler_, c);+ }+};++#endif // !defined(GENERATING_DOCUMENTATION)+ #if defined(ASIO_HAS_VARIADIC_TEMPLATES) \ || defined(GENERATING_DOCUMENTATION) @@ -37,7 +333,7 @@ * handler. The remaining arguments are any arguments that originate from the * completion handlers of any asynchronous operations performed by the * implementation.-+ * * @param token The completion token. * * @param io_objects_or_executors Zero or more I/O objects or I/O executors for@@ -87,9 +383,11 @@ * auto async_echo(tcp::socket& socket, * asio::mutable_buffer buffer, * CompletionToken&& token) ->- * typename asio::async_result<- * typename std::decay<CompletionToken>::type,- * void(asio::error_code, std::size_t)>::return_type+ * decltype(+ * asio::async_compose<CompletionToken,+ * void(asio::error_code, std::size_t)>(+ * std::declval<async_echo_implementation>(),+ * token, socket)) * { * return asio::async_compose<CompletionToken, * void(asio::error_code, std::size_t)>(@@ -100,37 +398,134 @@ */ template <typename CompletionToken, typename Signature, typename Implementation, typename... IoObjectsOrExecutors>-ASIO_INITFN_AUTO_RESULT_TYPE(CompletionToken, Signature)+ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX(CompletionToken, Signature) async_compose(ASIO_MOVE_ARG(Implementation) implementation, ASIO_NONDEDUCED_MOVE_ARG(CompletionToken) token,- ASIO_MOVE_ARG(IoObjectsOrExecutors)... io_objects_or_executors);+ ASIO_MOVE_ARG(IoObjectsOrExecutors)... io_objects_or_executors)+ ASIO_INITFN_AUTO_RESULT_TYPE_SUFFIX((+ async_initiate<CompletionToken, Signature>(+ detail::make_initiate_composed_op<Signature>(+ detail::make_composed_io_executors(+ detail::get_composed_io_executor(+ ASIO_MOVE_CAST(IoObjectsOrExecutors)(+ io_objects_or_executors))...)),+ token, ASIO_MOVE_CAST(Implementation)(implementation))))+{+ return async_initiate<CompletionToken, Signature>(+ detail::make_initiate_composed_op<Signature>(+ detail::make_composed_io_executors(+ detail::get_composed_io_executor(+ ASIO_MOVE_CAST(IoObjectsOrExecutors)(+ io_objects_or_executors))...)),+ token, ASIO_MOVE_CAST(Implementation)(implementation));+} #else // defined(ASIO_HAS_VARIADIC_TEMPLATES) // || defined(GENERATING_DOCUMENTATION) template <typename CompletionToken, typename Signature, typename Implementation>-ASIO_INITFN_AUTO_RESULT_TYPE(CompletionToken, Signature)+ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX(CompletionToken, Signature) async_compose(ASIO_MOVE_ARG(Implementation) implementation,- ASIO_NONDEDUCED_MOVE_ARG(CompletionToken) token);+ ASIO_NONDEDUCED_MOVE_ARG(CompletionToken) token)+ ASIO_INITFN_AUTO_RESULT_TYPE_SUFFIX((+ async_initiate<CompletionToken, Signature>(+ detail::make_initiate_composed_op<Signature>(+ detail::make_composed_io_executors()),+ token, ASIO_MOVE_CAST(Implementation)(implementation))))+{+ return async_initiate<CompletionToken, Signature>(+ detail::make_initiate_composed_op<Signature>(+ detail::make_composed_io_executors()),+ token, ASIO_MOVE_CAST(Implementation)(implementation));+} +# define ASIO_PRIVATE_GET_COMPOSED_IO_EXECUTOR(n) \+ ASIO_PRIVATE_GET_COMPOSED_IO_EXECUTOR_##n++# define ASIO_PRIVATE_GET_COMPOSED_IO_EXECUTOR_1 \+ detail::get_composed_io_executor(ASIO_MOVE_CAST(T1)(x1))+# define ASIO_PRIVATE_GET_COMPOSED_IO_EXECUTOR_2 \+ detail::get_composed_io_executor(ASIO_MOVE_CAST(T1)(x1)), \+ detail::get_composed_io_executor(ASIO_MOVE_CAST(T2)(x2))+# define ASIO_PRIVATE_GET_COMPOSED_IO_EXECUTOR_3 \+ detail::get_composed_io_executor(ASIO_MOVE_CAST(T1)(x1)), \+ detail::get_composed_io_executor(ASIO_MOVE_CAST(T2)(x2)), \+ detail::get_composed_io_executor(ASIO_MOVE_CAST(T3)(x3))+# define ASIO_PRIVATE_GET_COMPOSED_IO_EXECUTOR_4 \+ detail::get_composed_io_executor(ASIO_MOVE_CAST(T1)(x1)), \+ detail::get_composed_io_executor(ASIO_MOVE_CAST(T2)(x2)), \+ detail::get_composed_io_executor(ASIO_MOVE_CAST(T3)(x3)), \+ detail::get_composed_io_executor(ASIO_MOVE_CAST(T4)(x4))+# define ASIO_PRIVATE_GET_COMPOSED_IO_EXECUTOR_5 \+ detail::get_composed_io_executor(ASIO_MOVE_CAST(T1)(x1)), \+ detail::get_composed_io_executor(ASIO_MOVE_CAST(T2)(x2)), \+ detail::get_composed_io_executor(ASIO_MOVE_CAST(T3)(x3)), \+ detail::get_composed_io_executor(ASIO_MOVE_CAST(T4)(x4)), \+ detail::get_composed_io_executor(ASIO_MOVE_CAST(T5)(x5))+# define ASIO_PRIVATE_GET_COMPOSED_IO_EXECUTOR_6 \+ detail::get_composed_io_executor(ASIO_MOVE_CAST(T1)(x1)), \+ detail::get_composed_io_executor(ASIO_MOVE_CAST(T2)(x2)), \+ detail::get_composed_io_executor(ASIO_MOVE_CAST(T3)(x3)), \+ detail::get_composed_io_executor(ASIO_MOVE_CAST(T4)(x4)), \+ detail::get_composed_io_executor(ASIO_MOVE_CAST(T5)(x5)), \+ detail::get_composed_io_executor(ASIO_MOVE_CAST(T6)(x6))+# define ASIO_PRIVATE_GET_COMPOSED_IO_EXECUTOR_7 \+ detail::get_composed_io_executor(ASIO_MOVE_CAST(T1)(x1)), \+ detail::get_composed_io_executor(ASIO_MOVE_CAST(T2)(x2)), \+ detail::get_composed_io_executor(ASIO_MOVE_CAST(T3)(x3)), \+ detail::get_composed_io_executor(ASIO_MOVE_CAST(T4)(x4)), \+ detail::get_composed_io_executor(ASIO_MOVE_CAST(T5)(x5)), \+ detail::get_composed_io_executor(ASIO_MOVE_CAST(T6)(x6)), \+ detail::get_composed_io_executor(ASIO_MOVE_CAST(T7)(x7))+# define ASIO_PRIVATE_GET_COMPOSED_IO_EXECUTOR_8 \+ detail::get_composed_io_executor(ASIO_MOVE_CAST(T1)(x1)), \+ detail::get_composed_io_executor(ASIO_MOVE_CAST(T2)(x2)), \+ detail::get_composed_io_executor(ASIO_MOVE_CAST(T3)(x3)), \+ detail::get_composed_io_executor(ASIO_MOVE_CAST(T4)(x4)), \+ detail::get_composed_io_executor(ASIO_MOVE_CAST(T5)(x5)), \+ detail::get_composed_io_executor(ASIO_MOVE_CAST(T6)(x6)), \+ detail::get_composed_io_executor(ASIO_MOVE_CAST(T7)(x7)), \+ detail::get_composed_io_executor(ASIO_MOVE_CAST(T8)(x8))+ #define ASIO_PRIVATE_ASYNC_COMPOSE_DEF(n) \ template <typename CompletionToken, typename Signature, \ typename Implementation, ASIO_VARIADIC_TPARAMS(n)> \- ASIO_INITFN_AUTO_RESULT_TYPE(CompletionToken, Signature) \+ ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX(CompletionToken, Signature) \ async_compose(ASIO_MOVE_ARG(Implementation) implementation, \ ASIO_NONDEDUCED_MOVE_ARG(CompletionToken) token, \- ASIO_VARIADIC_MOVE_PARAMS(n));+ ASIO_VARIADIC_MOVE_PARAMS(n)) \+ ASIO_INITFN_AUTO_RESULT_TYPE_SUFFIX(( \+ async_initiate<CompletionToken, Signature>( \+ detail::make_initiate_composed_op<Signature>( \+ detail::make_composed_io_executors( \+ ASIO_PRIVATE_GET_COMPOSED_IO_EXECUTOR(n))), \+ token, ASIO_MOVE_CAST(Implementation)(implementation)))) \+ { \+ return async_initiate<CompletionToken, Signature>( \+ detail::make_initiate_composed_op<Signature>( \+ detail::make_composed_io_executors( \+ ASIO_PRIVATE_GET_COMPOSED_IO_EXECUTOR(n))), \+ token, ASIO_MOVE_CAST(Implementation)(implementation)); \+ } \ /**/ ASIO_VARIADIC_GENERATE(ASIO_PRIVATE_ASYNC_COMPOSE_DEF) #undef ASIO_PRIVATE_ASYNC_COMPOSE_DEF +#undef ASIO_PRIVATE_GET_COMPOSED_IO_EXECUTOR+#undef ASIO_PRIVATE_GET_COMPOSED_IO_EXECUTOR_1+#undef ASIO_PRIVATE_GET_COMPOSED_IO_EXECUTOR_2+#undef ASIO_PRIVATE_GET_COMPOSED_IO_EXECUTOR_3+#undef ASIO_PRIVATE_GET_COMPOSED_IO_EXECUTOR_4+#undef ASIO_PRIVATE_GET_COMPOSED_IO_EXECUTOR_5+#undef ASIO_PRIVATE_GET_COMPOSED_IO_EXECUTOR_6+#undef ASIO_PRIVATE_GET_COMPOSED_IO_EXECUTOR_7+#undef ASIO_PRIVATE_GET_COMPOSED_IO_EXECUTOR_8+ #endif // defined(ASIO_HAS_VARIADIC_TEMPLATES) // || defined(GENERATING_DOCUMENTATION) } // namespace asio #include "asio/detail/pop_options.hpp"--#include "asio/impl/compose.hpp" #endif // ASIO_COMPOSE_HPP
link/modules/asio-standalone/asio/include/asio/connect.hpp view
@@ -2,7 +2,7 @@ // connect.hpp // ~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -27,6 +27,10 @@ namespace detail {+ struct default_connect_condition;+ template <typename, typename> class initiate_async_range_connect;+ template <typename, typename> class initiate_async_iterator_connect;+ char (&has_iterator_helper(...))[2]; template <typename T>@@ -90,8 +94,8 @@ template <typename Protocol, typename Executor, typename EndpointSequence> typename Protocol::endpoint connect(basic_socket<Protocol, Executor>& s, const EndpointSequence& endpoints,- typename enable_if<is_endpoint_sequence<- EndpointSequence>::value>::type* = 0);+ typename constraint<is_endpoint_sequence<+ EndpointSequence>::value>::type = 0); /// Establishes a socket connection by trying each endpoint in a sequence. /**@@ -126,8 +130,8 @@ template <typename Protocol, typename Executor, typename EndpointSequence> typename Protocol::endpoint connect(basic_socket<Protocol, Executor>& s, const EndpointSequence& endpoints, asio::error_code& ec,- typename enable_if<is_endpoint_sequence<- EndpointSequence>::value>::type* = 0);+ typename constraint<is_endpoint_sequence<+ EndpointSequence>::value>::type = 0); #if !defined(ASIO_NO_DEPRECATED) /// (Deprecated: Use range overload.) Establishes a socket connection by trying@@ -156,7 +160,7 @@ */ template <typename Protocol, typename Executor, typename Iterator> Iterator connect(basic_socket<Protocol, Executor>& s, Iterator begin,- typename enable_if<!is_endpoint_sequence<Iterator>::value>::type* = 0);+ typename constraint<!is_endpoint_sequence<Iterator>::value>::type = 0); /// (Deprecated: Use range overload.) Establishes a socket connection by trying /// each endpoint in a sequence.@@ -185,7 +189,7 @@ template <typename Protocol, typename Executor, typename Iterator> Iterator connect(basic_socket<Protocol, Executor>& s, Iterator begin, asio::error_code& ec,- typename enable_if<!is_endpoint_sequence<Iterator>::value>::type* = 0);+ typename constraint<!is_endpoint_sequence<Iterator>::value>::type = 0); #endif // !defined(ASIO_NO_DEPRECATED) /// Establishes a socket connection by trying each endpoint in a sequence.@@ -311,8 +315,8 @@ typename EndpointSequence, typename ConnectCondition> typename Protocol::endpoint connect(basic_socket<Protocol, Executor>& s, const EndpointSequence& endpoints, ConnectCondition connect_condition,- typename enable_if<is_endpoint_sequence<- EndpointSequence>::value>::type* = 0);+ typename constraint<is_endpoint_sequence<+ EndpointSequence>::value>::type = 0); /// Establishes a socket connection by trying each endpoint in a sequence. /**@@ -379,8 +383,8 @@ typename Protocol::endpoint connect(basic_socket<Protocol, Executor>& s, const EndpointSequence& endpoints, ConnectCondition connect_condition, asio::error_code& ec,- typename enable_if<is_endpoint_sequence<- EndpointSequence>::value>::type* = 0);+ typename constraint<is_endpoint_sequence<+ EndpointSequence>::value>::type = 0); #if !defined(ASIO_NO_DEPRECATED) /// (Deprecated: Use range overload.) Establishes a socket connection by trying@@ -422,7 +426,7 @@ typename Iterator, typename ConnectCondition> Iterator connect(basic_socket<Protocol, Executor>& s, Iterator begin, ConnectCondition connect_condition,- typename enable_if<!is_endpoint_sequence<Iterator>::value>::type* = 0);+ typename constraint<!is_endpoint_sequence<Iterator>::value>::type = 0); /// (Deprecated: Use range overload.) Establishes a socket connection by trying /// each endpoint in a sequence.@@ -463,7 +467,7 @@ typename Iterator, typename ConnectCondition> Iterator connect(basic_socket<Protocol, Executor>& s, Iterator begin, ConnectCondition connect_condition, asio::error_code& ec,- typename enable_if<!is_endpoint_sequence<Iterator>::value>::type* = 0);+ typename constraint<!is_endpoint_sequence<Iterator>::value>::type = 0); #endif // !defined(ASIO_NO_DEPRECATED) /// Establishes a socket connection by trying each endpoint in a sequence.@@ -610,16 +614,19 @@ * This function attempts to connect a socket to one of a sequence of * endpoints. It does this by repeated calls to the socket's @c async_connect * member function, once for each endpoint in the sequence, until a connection- * is successfully established.+ * is successfully established. It is an initiating function for an @ref+ * asynchronous_operation, and always returns immediately. * * @param s The socket to be connected. If the socket is already open, it will * be closed. * * @param endpoints A sequence of endpoints. *- * @param handler The handler to be called when the connect operation- * completes. Copies will be made of the handler as required. The function- * signature of the handler must be:+ * @param token The @ref completion_token that will be used to produce a+ * completion handler, which will be called when the connect completes.+ * Potential completion tokens include @ref use_future, @ref use_awaitable,+ * @ref yield_context, or a function object with the correct completion+ * signature. The function signature of the completion handler must be: * @code void handler( * // Result of operation. if the sequence is empty, set to * // asio::error::not_found. Otherwise, contains the@@ -631,10 +638,13 @@ * const typename Protocol::endpoint& endpoint * ); @endcode * Regardless of whether the asynchronous operation completes immediately or- * not, the handler will not be invoked from within this function. On- * immediate completion, invocation of the handler will be performed in a+ * not, the completion handler will not be invoked from within this function.+ * On immediate completion, invocation of the handler will be performed in a * manner equivalent to using asio::post(). *+ * @par Completion Signature+ * @code void(asio::error_code, typename Protocol::endpoint) @endcode+ * * @par Example * @code tcp::resolver r(my_context); * tcp::resolver::query q("host", "service");@@ -664,19 +674,34 @@ * { * // ... * } @endcode+ *+ * @par Per-Operation Cancellation+ * This asynchronous operation supports cancellation for the following+ * asio::cancellation_type values:+ *+ * @li @c cancellation_type::terminal+ *+ * @li @c cancellation_type::partial+ *+ * if they are also supported by the socket's @c async_connect operation. */ template <typename Protocol, typename Executor, typename EndpointSequence, ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code,- typename Protocol::endpoint)) RangeConnectHandler+ typename Protocol::endpoint)) RangeConnectToken ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(Executor)>-ASIO_INITFN_AUTO_RESULT_TYPE(RangeConnectHandler,+ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX(RangeConnectToken, void (asio::error_code, typename Protocol::endpoint)) async_connect(basic_socket<Protocol, Executor>& s, const EndpointSequence& endpoints,- ASIO_MOVE_ARG(RangeConnectHandler) handler+ ASIO_MOVE_ARG(RangeConnectToken) token ASIO_DEFAULT_COMPLETION_TOKEN(Executor),- typename enable_if<is_endpoint_sequence<- EndpointSequence>::value>::type* = 0);+ typename constraint<is_endpoint_sequence<+ EndpointSequence>::value>::type = 0)+ ASIO_INITFN_AUTO_RESULT_TYPE_SUFFIX((+ async_initiate<RangeConnectToken,+ void (asio::error_code, typename Protocol::endpoint)>(+ declval<detail::initiate_async_range_connect<Protocol, Executor> >(),+ token, endpoints, declval<detail::default_connect_condition>()))); #if !defined(ASIO_NO_DEPRECATED) /// (Deprecated: Use range overload.) Asynchronously establishes a socket@@ -685,16 +710,19 @@ * This function attempts to connect a socket to one of a sequence of * endpoints. It does this by repeated calls to the socket's @c async_connect * member function, once for each endpoint in the sequence, until a connection- * is successfully established.+ * is successfully established. It is an initiating function for an @ref+ * asynchronous_operation, and always returns immediately. * * @param s The socket to be connected. If the socket is already open, it will * be closed. * * @param begin An iterator pointing to the start of a sequence of endpoints. *- * @param handler The handler to be called when the connect operation- * completes. Copies will be made of the handler as required. The function- * signature of the handler must be:+ * @param token The @ref completion_token that will be used to produce a+ * completion handler, which will be called when the connect completes.+ * Potential completion tokens include @ref use_future, @ref use_awaitable,+ * @ref yield_context, or a function object with the correct completion+ * signature. The function signature of the completion handler must be: * @code void handler( * // Result of operation. if the sequence is empty, set to * // asio::error::not_found. Otherwise, contains the@@ -706,24 +734,43 @@ * Iterator iterator * ); @endcode * Regardless of whether the asynchronous operation completes immediately or- * not, the handler will not be invoked from within this function. On- * immediate completion, invocation of the handler will be performed in a+ * not, the completion handler will not be invoked from within this function.+ * On immediate completion, invocation of the handler will be performed in a * manner equivalent to using asio::post(). *+ * @par Completion Signature+ * @code void(asio::error_code, Iterator) @endcode+ * * @note This overload assumes that a default constructed object of type @c * Iterator represents the end of the sequence. This is a valid assumption for * iterator types such as @c asio::ip::tcp::resolver::iterator.+ *+ * @par Per-Operation Cancellation+ * This asynchronous operation supports cancellation for the following+ * asio::cancellation_type values:+ *+ * @li @c cancellation_type::terminal+ *+ * @li @c cancellation_type::partial+ *+ * if they are also supported by the socket's @c async_connect operation. */ template <typename Protocol, typename Executor, typename Iterator, ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code,- Iterator)) IteratorConnectHandler+ Iterator)) IteratorConnectToken ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(Executor)>-ASIO_INITFN_AUTO_RESULT_TYPE(IteratorConnectHandler,+ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX(IteratorConnectToken, void (asio::error_code, Iterator)) async_connect(basic_socket<Protocol, Executor>& s, Iterator begin,- ASIO_MOVE_ARG(IteratorConnectHandler) handler+ ASIO_MOVE_ARG(IteratorConnectToken) token ASIO_DEFAULT_COMPLETION_TOKEN(Executor),- typename enable_if<!is_endpoint_sequence<Iterator>::value>::type* = 0);+ typename constraint<!is_endpoint_sequence<Iterator>::value>::type = 0)+ ASIO_INITFN_AUTO_RESULT_TYPE_SUFFIX((+ async_initiate<IteratorConnectToken,+ void (asio::error_code, Iterator)>(+ declval<detail::initiate_async_iterator_connect<Protocol, Executor> >(),+ token, begin, Iterator(),+ declval<detail::default_connect_condition>()))); #endif // !defined(ASIO_NO_DEPRECATED) /// Asynchronously establishes a socket connection by trying each endpoint in a@@ -732,7 +779,8 @@ * This function attempts to connect a socket to one of a sequence of * endpoints. It does this by repeated calls to the socket's @c async_connect * member function, once for each endpoint in the sequence, until a connection- * is successfully established.+ * is successfully established. It is an initiating function for an @ref+ * asynchronous_operation, and always returns immediately. * * @param s The socket to be connected. If the socket is already open, it will * be closed.@@ -741,9 +789,11 @@ * * @param end An iterator pointing to the end of a sequence of endpoints. *- * @param handler The handler to be called when the connect operation- * completes. Copies will be made of the handler as required. The function- * signature of the handler must be:+ * @param token The @ref completion_token that will be used to produce a+ * completion handler, which will be called when the connect completes.+ * Potential completion tokens include @ref use_future, @ref use_awaitable,+ * @ref yield_context, or a function object with the correct completion+ * signature. The function signature of the completion handler must be: * @code void handler( * // Result of operation. if the sequence is empty, set to * // asio::error::not_found. Otherwise, contains the@@ -755,10 +805,13 @@ * Iterator iterator * ); @endcode * Regardless of whether the asynchronous operation completes immediately or- * not, the handler will not be invoked from within this function. On- * immediate completion, invocation of the handler will be performed in a+ * not, the completion handler will not be invoked from within this function.+ * On immediate completion, invocation of the handler will be performed in a * manner equivalent to using asio::post(). *+ * @par Completion Signature+ * @code void(asio::error_code, Iterator) @endcode+ * * @par Example * @code std::vector<tcp::endpoint> endpoints = ...; * tcp::socket s(my_context);@@ -774,16 +827,31 @@ * { * // ... * } @endcode+ *+ * @par Per-Operation Cancellation+ * This asynchronous operation supports cancellation for the following+ * asio::cancellation_type values:+ *+ * @li @c cancellation_type::terminal+ *+ * @li @c cancellation_type::partial+ *+ * if they are also supported by the socket's @c async_connect operation. */ template <typename Protocol, typename Executor, typename Iterator, ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code,- Iterator)) IteratorConnectHandler+ Iterator)) IteratorConnectToken ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(Executor)>-ASIO_INITFN_AUTO_RESULT_TYPE(IteratorConnectHandler,+ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX(IteratorConnectToken, void (asio::error_code, Iterator)) async_connect(basic_socket<Protocol, Executor>& s, Iterator begin, Iterator end,- ASIO_MOVE_ARG(IteratorConnectHandler) handler- ASIO_DEFAULT_COMPLETION_TOKEN(Executor));+ ASIO_MOVE_ARG(IteratorConnectToken) token+ ASIO_DEFAULT_COMPLETION_TOKEN(Executor))+ ASIO_INITFN_AUTO_RESULT_TYPE_SUFFIX((+ async_initiate<IteratorConnectToken,+ void (asio::error_code, Iterator)>(+ declval<detail::initiate_async_iterator_connect<Protocol, Executor> >(),+ token, begin, end, declval<detail::default_connect_condition>()))); /// Asynchronously establishes a socket connection by trying each endpoint in a /// sequence.@@ -791,7 +859,8 @@ * This function attempts to connect a socket to one of a sequence of * endpoints. It does this by repeated calls to the socket's @c async_connect * member function, once for each endpoint in the sequence, until a connection- * is successfully established.+ * is successfully established. It is an initiating function for an @ref+ * asynchronous_operation, and always returns immediately. * * @param s The socket to be connected. If the socket is already open, it will * be closed.@@ -809,9 +878,11 @@ * The function object should return true if the next endpoint should be tried, * and false if it should be skipped. *- * @param handler The handler to be called when the connect operation- * completes. Copies will be made of the handler as required. The function- * signature of the handler must be:+ * @param token The @ref completion_token that will be used to produce a+ * completion handler, which will be called when the connect completes.+ * Potential completion tokens include @ref use_future, @ref use_awaitable,+ * @ref yield_context, or a function object with the correct completion+ * signature. The function signature of the completion handler must be: * @code void handler( * // Result of operation. if the sequence is empty, set to * // asio::error::not_found. Otherwise, contains the@@ -823,10 +894,13 @@ * Iterator iterator * ); @endcode * Regardless of whether the asynchronous operation completes immediately or- * not, the handler will not be invoked from within this function. On- * immediate completion, invocation of the handler will be performed in a+ * not, the completion handler will not be invoked from within this function.+ * On immediate completion, invocation of the handler will be performed in a * manner equivalent to using asio::post(). *+ * @par Completion Signature+ * @code void(asio::error_code, typename Protocol::endpoint) @endcode+ * * @par Example * The following connect condition function object can be used to output * information about the individual connection attempts:@@ -879,20 +953,35 @@ * std::cout << "Connected to: " << endpoint << std::endl; * } * } @endcode+ *+ * @par Per-Operation Cancellation+ * This asynchronous operation supports cancellation for the following+ * asio::cancellation_type values:+ *+ * @li @c cancellation_type::terminal+ *+ * @li @c cancellation_type::partial+ *+ * if they are also supported by the socket's @c async_connect operation. */ template <typename Protocol, typename Executor, typename EndpointSequence, typename ConnectCondition, ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code,- typename Protocol::endpoint)) RangeConnectHandler+ typename Protocol::endpoint)) RangeConnectToken ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(Executor)>-ASIO_INITFN_AUTO_RESULT_TYPE(RangeConnectHandler,+ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX(RangeConnectToken, void (asio::error_code, typename Protocol::endpoint)) async_connect(basic_socket<Protocol, Executor>& s, const EndpointSequence& endpoints, ConnectCondition connect_condition,- ASIO_MOVE_ARG(RangeConnectHandler) handler+ ASIO_MOVE_ARG(RangeConnectToken) token ASIO_DEFAULT_COMPLETION_TOKEN(Executor),- typename enable_if<is_endpoint_sequence<- EndpointSequence>::value>::type* = 0);+ typename constraint<is_endpoint_sequence<+ EndpointSequence>::value>::type = 0)+ ASIO_INITFN_AUTO_RESULT_TYPE_SUFFIX((+ async_initiate<RangeConnectToken,+ void (asio::error_code, typename Protocol::endpoint)>(+ declval<detail::initiate_async_range_connect<Protocol, Executor> >(),+ token, endpoints, connect_condition))); #if !defined(ASIO_NO_DEPRECATED) /// (Deprecated: Use range overload.) Asynchronously establishes a socket@@ -901,7 +990,8 @@ * This function attempts to connect a socket to one of a sequence of * endpoints. It does this by repeated calls to the socket's @c async_connect * member function, once for each endpoint in the sequence, until a connection- * is successfully established.+ * is successfully established. It is an initiating function for an @ref+ * asynchronous_operation, and always returns immediately. * * @param s The socket to be connected. If the socket is already open, it will * be closed.@@ -919,9 +1009,11 @@ * The function object should return true if the next endpoint should be tried, * and false if it should be skipped. *- * @param handler The handler to be called when the connect operation- * completes. Copies will be made of the handler as required. The function- * signature of the handler must be:+ * @param token The @ref completion_token that will be used to produce a+ * completion handler, which will be called when the connect completes.+ * Potential completion tokens include @ref use_future, @ref use_awaitable,+ * @ref yield_context, or a function object with the correct completion+ * signature. The function signature of the completion handler must be: * @code void handler( * // Result of operation. if the sequence is empty, set to * // asio::error::not_found. Otherwise, contains the@@ -933,26 +1025,44 @@ * Iterator iterator * ); @endcode * Regardless of whether the asynchronous operation completes immediately or- * not, the handler will not be invoked from within this function. On- * immediate completion, invocation of the handler will be performed in a+ * not, the completion handler will not be invoked from within this function.+ * On immediate completion, invocation of the handler will be performed in a * manner equivalent to using asio::post(). *+ * @par Completion Signature+ * @code void(asio::error_code, Iterator) @endcode+ * * @note This overload assumes that a default constructed object of type @c * Iterator represents the end of the sequence. This is a valid assumption for * iterator types such as @c asio::ip::tcp::resolver::iterator.+ *+ * @par Per-Operation Cancellation+ * This asynchronous operation supports cancellation for the following+ * asio::cancellation_type values:+ *+ * @li @c cancellation_type::terminal+ *+ * @li @c cancellation_type::partial+ *+ * if they are also supported by the socket's @c async_connect operation. */ template <typename Protocol, typename Executor, typename Iterator, typename ConnectCondition, ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code,- Iterator)) IteratorConnectHandler+ Iterator)) IteratorConnectToken ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(Executor)>-ASIO_INITFN_AUTO_RESULT_TYPE(IteratorConnectHandler,+ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX(IteratorConnectToken, void (asio::error_code, Iterator)) async_connect(basic_socket<Protocol, Executor>& s, Iterator begin, ConnectCondition connect_condition,- ASIO_MOVE_ARG(IteratorConnectHandler) handler+ ASIO_MOVE_ARG(IteratorConnectToken) token ASIO_DEFAULT_COMPLETION_TOKEN(Executor),- typename enable_if<!is_endpoint_sequence<Iterator>::value>::type* = 0);+ typename constraint<!is_endpoint_sequence<Iterator>::value>::type = 0)+ ASIO_INITFN_AUTO_RESULT_TYPE_SUFFIX((+ async_initiate<IteratorConnectToken,+ void (asio::error_code, Iterator)>(+ declval<detail::initiate_async_iterator_connect<Protocol, Executor> >(),+ token, begin, Iterator(), connect_condition))); #endif // !defined(ASIO_NO_DEPRECATED) /// Asynchronously establishes a socket connection by trying each endpoint in a@@ -961,7 +1071,8 @@ * This function attempts to connect a socket to one of a sequence of * endpoints. It does this by repeated calls to the socket's @c async_connect * member function, once for each endpoint in the sequence, until a connection- * is successfully established.+ * is successfully established. It is an initiating function for an @ref+ * asynchronous_operation, and always returns immediately. * * @param s The socket to be connected. If the socket is already open, it will * be closed.@@ -981,9 +1092,11 @@ * The function object should return true if the next endpoint should be tried, * and false if it should be skipped. *- * @param handler The handler to be called when the connect operation- * completes. Copies will be made of the handler as required. The function- * signature of the handler must be:+ * @param token The @ref completion_token that will be used to produce a+ * completion handler, which will be called when the connect completes.+ * Potential completion tokens include @ref use_future, @ref use_awaitable,+ * @ref yield_context, or a function object with the correct completion+ * signature. The function signature of the completion handler must be: * @code void handler( * // Result of operation. if the sequence is empty, set to * // asio::error::not_found. Otherwise, contains the@@ -995,10 +1108,13 @@ * Iterator iterator * ); @endcode * Regardless of whether the asynchronous operation completes immediately or- * not, the handler will not be invoked from within this function. On- * immediate completion, invocation of the handler will be performed in a+ * not, the completion handler will not be invoked from within this function.+ * On immediate completion, invocation of the handler will be performed in a * manner equivalent to using asio::post(). *+ * @par Completion Signature+ * @code void(asio::error_code, Iterator) @endcode+ * * @par Example * The following connect condition function object can be used to output * information about the individual connection attempts:@@ -1052,18 +1168,33 @@ * std::cout << "Connected to: " << i->endpoint() << std::endl; * } * } @endcode+ *+ * @par Per-Operation Cancellation+ * This asynchronous operation supports cancellation for the following+ * asio::cancellation_type values:+ *+ * @li @c cancellation_type::terminal+ *+ * @li @c cancellation_type::partial+ *+ * if they are also supported by the socket's @c async_connect operation. */ template <typename Protocol, typename Executor, typename Iterator, typename ConnectCondition, ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code,- Iterator)) IteratorConnectHandler+ Iterator)) IteratorConnectToken ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(Executor)>-ASIO_INITFN_AUTO_RESULT_TYPE(IteratorConnectHandler,+ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX(IteratorConnectToken, void (asio::error_code, Iterator)) async_connect(basic_socket<Protocol, Executor>& s, Iterator begin, Iterator end, ConnectCondition connect_condition,- ASIO_MOVE_ARG(IteratorConnectHandler) handler- ASIO_DEFAULT_COMPLETION_TOKEN(Executor));+ ASIO_MOVE_ARG(IteratorConnectToken) token+ ASIO_DEFAULT_COMPLETION_TOKEN(Executor))+ ASIO_INITFN_AUTO_RESULT_TYPE_SUFFIX((+ async_initiate<IteratorConnectToken,+ void (asio::error_code, Iterator)>(+ declval<detail::initiate_async_iterator_connect<Protocol, Executor> >(),+ token, begin, end, connect_condition))); /*@}*/
+ link/modules/asio-standalone/asio/include/asio/connect_pipe.hpp view
@@ -0,0 +1,83 @@+//+// connect_pipe.hpp+// ~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com)+//+// Distributed under the Boost Software License, Version 1.0. (See accompanying+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)+//++#ifndef ASIO_CONNECT_PIPE_HPP+#define ASIO_CONNECT_PIPE_HPP++#if defined(_MSC_VER) && (_MSC_VER >= 1200)+# pragma once+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)++#include "asio/detail/config.hpp"++#if defined(ASIO_HAS_PIPE) \+ || defined(GENERATING_DOCUMENTATION)++#include "asio/basic_readable_pipe.hpp"+#include "asio/basic_writable_pipe.hpp"+#include "asio/error.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {+namespace detail {++#if defined(ASIO_HAS_IOCP)+typedef HANDLE native_pipe_handle;+#else // defined(ASIO_HAS_IOCP)+typedef int native_pipe_handle;+#endif // defined(ASIO_HAS_IOCP)++ASIO_DECL void create_pipe(native_pipe_handle p[2],+ asio::error_code& ec);++ASIO_DECL void close_pipe(native_pipe_handle p);++} // namespace detail++/// Connect two pipe ends using an anonymous pipe.+/**+ * @param read_end The read end of the pipe.+ *+ * @param write_end The write end of the pipe.+ *+ * @throws asio::system_error Thrown on failure.+ */+template <typename Executor1, typename Executor2>+void connect_pipe(basic_readable_pipe<Executor1>& read_end,+ basic_writable_pipe<Executor2>& write_end);++/// Connect two pipe ends using an anonymous pipe.+/**+ * @param read_end The read end of the pipe.+ *+ * @param write_end The write end of the pipe.+ *+ * @throws asio::system_error Thrown on failure.+ *+ * @param ec Set to indicate what error occurred, if any.+ */+template <typename Executor1, typename Executor2>+ASIO_SYNC_OP_VOID connect_pipe(basic_readable_pipe<Executor1>& read_end,+ basic_writable_pipe<Executor2>& write_end, asio::error_code& ec);++} // namespace asio++#include "asio/detail/pop_options.hpp"++#include "asio/impl/connect_pipe.hpp"+#if defined(ASIO_HEADER_ONLY)+# include "asio/impl/connect_pipe.ipp"+#endif // defined(ASIO_HEADER_ONLY)++#endif // defined(ASIO_HAS_PIPE)+ // || defined(GENERATING_DOCUMENTATION)++#endif // ASIO_CONNECT_PIPE_HPP
+ link/modules/asio-standalone/asio/include/asio/consign.hpp view
@@ -0,0 +1,88 @@+//+// consign.hpp+// ~~~~~~~~~~+//+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com)+//+// Distributed under the Boost Software License, Version 1.0. (See accompanying+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)+//++#ifndef ASIO_CONSIGN_HPP+#define ASIO_CONSIGN_HPP++#if defined(_MSC_VER) && (_MSC_VER >= 1200)+# pragma once+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)++#include "asio/detail/config.hpp"++#if (defined(ASIO_HAS_STD_TUPLE) \+ && defined(ASIO_HAS_VARIADIC_TEMPLATES)) \+ || defined(GENERATING_DOCUMENTATION)++#include <tuple>+#include "asio/detail/type_traits.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {++/// Completion token type used to specify that the completion handler should+/// carry additional values along with it.+/**+ * This completion token adapter is typically used to keep at least one copy of+ * an object, such as a smart pointer, alive until the completion handler is+ * called.+ */+template <typename CompletionToken, typename... Values>+class consign_t+{+public:+ /// Constructor.+ template <typename T, typename... V>+ ASIO_CONSTEXPR explicit consign_t(+ ASIO_MOVE_ARG(T) completion_token,+ ASIO_MOVE_ARG(V)... values)+ : token_(ASIO_MOVE_CAST(T)(completion_token)),+ values_(ASIO_MOVE_CAST(V)(values)...)+ {+ }++#if defined(GENERATING_DOCUMENTATION)+private:+#endif // defined(GENERATING_DOCUMENTATION)+ CompletionToken token_;+ std::tuple<Values...> values_;+};++/// Completion token adapter used to specify that the completion handler should+/// carry additional values along with it.+/**+ * This completion token adapter is typically used to keep at least one copy of+ * an object, such as a smart pointer, alive until the completion handler is+ * called.+ */+template <typename CompletionToken, typename... Values>+ASIO_NODISCARD inline ASIO_CONSTEXPR consign_t<+ typename decay<CompletionToken>::type, typename decay<Values>::type...>+consign(ASIO_MOVE_ARG(CompletionToken) completion_token,+ ASIO_MOVE_ARG(Values)... values)+{+ return consign_t<+ typename decay<CompletionToken>::type, typename decay<Values>::type...>(+ ASIO_MOVE_CAST(CompletionToken)(completion_token),+ ASIO_MOVE_CAST(Values)(values)...);+}++} // namespace asio++#include "asio/detail/pop_options.hpp"++#include "asio/impl/consign.hpp"++#endif // (defined(ASIO_HAS_STD_TUPLE)+ // && defined(ASIO_HAS_VARIADIC_TEMPLATES))+ // || defined(GENERATING_DOCUMENTATION)++#endif // ASIO_CONSIGN_HPP
link/modules/asio-standalone/asio/include/asio/coroutine.hpp view
@@ -2,7 +2,7 @@ // coroutine.hpp // ~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/deadline_timer.hpp view
@@ -2,7 +2,7 @@ // deadline_timer.hpp // ~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/defer.hpp view
@@ -2,7 +2,7 @@ // defer.hpp // ~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -17,10 +17,13 @@ #include "asio/detail/config.hpp" #include "asio/async_result.hpp"+#include "asio/detail/initiate_defer.hpp" #include "asio/detail/type_traits.hpp" #include "asio/execution_context.hpp"+#include "asio/execution/blocking.hpp" #include "asio/execution/executor.hpp" #include "asio/is_executor.hpp"+#include "asio/require.hpp" #include "asio/detail/push_options.hpp" @@ -37,27 +40,54 @@ * may allow the executor to optimise queueing for cases when the function * object represents a continuation of the current call context. *- * This function has the following effects:+ * @param token The @ref completion_token that will be used to produce a+ * completion handler. The function signature of the completion handler must be:+ * @code void handler(); @endcode *- * @li Constructs a function object handler of type @c Handler, initialized- * with <tt>handler(forward<CompletionToken>(token))</tt>.+ * @returns This function returns <tt>async_initiate<NullaryToken,+ * void()>(Init{}, token)</tt>, where @c Init is a function object type defined+ * as: *- * @li Constructs an object @c result of type <tt>async_result<Handler></tt>,- * initializing the object as <tt>result(handler)</tt>.+ * @code class Init+ * {+ * public:+ * template <typename CompletionHandler>+ * void operator()(CompletionHandler&& completion_handler) const;+ * }; @endcode *- * @li Obtains the handler's associated executor object @c ex by performing- * <tt>get_associated_executor(handler)</tt>.+ * The function call operator of @c Init: *+ * @li Obtains the handler's associated executor object @c ex of type @c Ex by+ * performing @code auto ex = get_associated_executor(handler); @endcode+ * * @li Obtains the handler's associated allocator object @c alloc by performing- * <tt>get_associated_allocator(handler)</tt>.+ * @code auto alloc = get_associated_allocator(handler); @endcode *- * @li Performs <tt>ex.defer(std::move(handler), alloc)</tt>.+ * @li If <tt>execution::is_executor<Ex>::value</tt> is true, performs+ * @code prefer(+ * require(ex, execution::blocking.never),+ * execution::relationship.continuation,+ * execution::allocator(alloc)+ * ).execute(std::forward<CompletionHandler>(completion_handler)); @endcode *- * @li Returns <tt>result.get()</tt>.+ * @li If <tt>execution::is_executor<Ex>::value</tt> is false, performs+ * @code ex.defer(+ * std::forward<CompletionHandler>(completion_handler),+ * alloc); @endcode+ *+ * @par Completion Signature+ * @code void() @endcode */-template <ASIO_COMPLETION_TOKEN_FOR(void()) CompletionToken>-ASIO_INITFN_AUTO_RESULT_TYPE(CompletionToken, void()) defer(- ASIO_MOVE_ARG(CompletionToken) token);+template <ASIO_COMPLETION_TOKEN_FOR(void()) NullaryToken>+ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX(NullaryToken, void()) defer(+ ASIO_MOVE_ARG(NullaryToken) token)+ ASIO_INITFN_AUTO_RESULT_TYPE_SUFFIX((+ async_initiate<NullaryToken, void()>(+ declval<detail::initiate_defer>(), token)))+{+ return async_initiate<NullaryToken, void()>(+ detail::initiate_defer(), token);+} /// Submits a completion token or function object for execution. /**@@ -70,61 +100,123 @@ * may allow the executor to optimise queueing for cases when the function * object represents a continuation of the current call context. *- * This function has the following effects:+ * @param ex The target executor. *- * @li Constructs a function object handler of type @c Handler, initialized- * with <tt>handler(forward<CompletionToken>(token))</tt>.+ * @param token The @ref completion_token that will be used to produce a+ * completion handler. The function signature of the completion handler must be:+ * @code void handler(); @endcode *- * @li Constructs an object @c result of type <tt>async_result<Handler></tt>,- * initializing the object as <tt>result(handler)</tt>.+ * @returns This function returns <tt>async_initiate<NullaryToken,+ * void()>(Init{ex}, token)</tt>, where @c Init is a function object type+ * defined as: *- * @li Obtains the handler's associated executor object @c ex1 by performing- * <tt>get_associated_executor(handler)</tt>.+ * @code class Init+ * {+ * public:+ * using executor_type = Executor;+ * explicit Init(const Executor& ex) : ex_(ex) {}+ * executor_type get_executor() const noexcept { return ex_; }+ * template <typename CompletionHandler>+ * void operator()(CompletionHandler&& completion_handler) const;+ * private:+ * Executor ex_; // exposition only+ * }; @endcode *- * @li Creates a work object @c w by performing <tt>make_work(ex1)</tt>.+ * The function call operator of @c Init: *+ * @li Obtains the handler's associated executor object @c ex1 of type @c Ex1 by+ * performing @code auto ex1 = get_associated_executor(handler, ex); @endcode+ * * @li Obtains the handler's associated allocator object @c alloc by performing- * <tt>get_associated_allocator(handler)</tt>.+ * @code auto alloc = get_associated_allocator(handler); @endcode *- * @li Constructs a function object @c f with a function call operator that- * performs <tt>ex1.dispatch(std::move(handler), alloc)</tt> followed by- * <tt>w.reset()</tt>.+ * @li If <tt>execution::is_executor<Ex1>::value</tt> is true, constructs a+ * function object @c f with a member @c executor_ that is initialised with+ * <tt>prefer(ex1, execution::outstanding_work.tracked)</tt>, a member @c+ * handler_ that is a decay-copy of @c completion_handler, and a function call+ * operator that performs:+ * @code auto a = get_associated_allocator(handler_);+ * prefer(executor_, execution::allocator(a)).execute(std::move(handler_));+ * @endcode *- * @li Performs <tt>Executor(ex).defer(std::move(f), alloc)</tt>.+ * @li If <tt>execution::is_executor<Ex1>::value</tt> is false, constructs a+ * function object @c f with a member @c work_ that is initialised with+ * <tt>make_work_guard(ex1)</tt>, a member @c handler_ that is a decay-copy of+ * @c completion_handler, and a function call operator that performs:+ * @code auto a = get_associated_allocator(handler_);+ * work_.get_executor().dispatch(std::move(handler_), a);+ * work_.reset(); @endcode *- * @li Returns <tt>result.get()</tt>.+ * @li If <tt>execution::is_executor<Ex>::value</tt> is true, performs+ * @code prefer(+ * require(ex, execution::blocking.never),+ * execution::relationship.continuation,+ * execution::allocator(alloc)+ * ).execute(std::move(f)); @endcode+ *+ * @li If <tt>execution::is_executor<Ex>::value</tt> is false, performs+ * @code ex.defer(std::move(f), alloc); @endcode+ *+ * @par Completion Signature+ * @code void() @endcode */ template <typename Executor,- ASIO_COMPLETION_TOKEN_FOR(void()) CompletionToken+ ASIO_COMPLETION_TOKEN_FOR(void()) NullaryToken ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(Executor)>-ASIO_INITFN_AUTO_RESULT_TYPE(CompletionToken, void()) defer(+ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX(NullaryToken, void()) defer( const Executor& ex,- ASIO_MOVE_ARG(CompletionToken) token+ ASIO_MOVE_ARG(NullaryToken) token ASIO_DEFAULT_COMPLETION_TOKEN(Executor),- typename enable_if<- execution::is_executor<Executor>::value || is_executor<Executor>::value- >::type* = 0);+ typename constraint<+ (execution::is_executor<Executor>::value+ && can_require<Executor, execution::blocking_t::never_t>::value)+ || is_executor<Executor>::value+ >::type = 0)+ ASIO_INITFN_AUTO_RESULT_TYPE_SUFFIX((+ async_initiate<NullaryToken, void()>(+ declval<detail::initiate_defer_with_executor<Executor> >(), token)))+{+ return async_initiate<NullaryToken, void()>(+ detail::initiate_defer_with_executor<Executor>(ex), token);+} /// Submits a completion token or function object for execution. /**- * @returns <tt>defer(ctx.get_executor(), forward<CompletionToken>(token))</tt>.+ * @param ctx An execution context, from which the target executor is obtained.+ *+ * @param token The @ref completion_token that will be used to produce a+ * completion handler. The function signature of the completion handler must be:+ * @code void handler(); @endcode+ *+ * @returns <tt>defer(ctx.get_executor(), forward<NullaryToken>(token))</tt>.+ *+ * @par Completion Signature+ * @code void() @endcode */ template <typename ExecutionContext,- ASIO_COMPLETION_TOKEN_FOR(void()) CompletionToken+ ASIO_COMPLETION_TOKEN_FOR(void()) NullaryToken ASIO_DEFAULT_COMPLETION_TOKEN_TYPE( typename ExecutionContext::executor_type)>-ASIO_INITFN_AUTO_RESULT_TYPE(CompletionToken, void()) defer(+ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX(NullaryToken, void()) defer( ExecutionContext& ctx,- ASIO_MOVE_ARG(CompletionToken) token+ ASIO_MOVE_ARG(NullaryToken) token ASIO_DEFAULT_COMPLETION_TOKEN( typename ExecutionContext::executor_type),- typename enable_if<is_convertible<- ExecutionContext&, execution_context&>::value>::type* = 0);+ typename constraint<is_convertible<+ ExecutionContext&, execution_context&>::value>::type = 0)+ ASIO_INITFN_AUTO_RESULT_TYPE_SUFFIX((+ async_initiate<NullaryToken, void()>(+ declval<detail::initiate_defer_with_executor<+ typename ExecutionContext::executor_type> >(), token)))+{+ return async_initiate<NullaryToken, void()>(+ detail::initiate_defer_with_executor<+ typename ExecutionContext::executor_type>(+ ctx.get_executor()), token);+} } // namespace asio #include "asio/detail/pop_options.hpp"--#include "asio/impl/defer.hpp" #endif // ASIO_DEFER_HPP
+ link/modules/asio-standalone/asio/include/asio/deferred.hpp view
@@ -0,0 +1,802 @@+//+// deferred.hpp+// ~~~~~~~~~~~~+//+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com)+//+// Distributed under the Boost Software License, Version 1.0. (See accompanying+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)+//++#ifndef ASIO_DEFERRED_HPP+#define ASIO_DEFERRED_HPP++#if defined(_MSC_VER) && (_MSC_VER >= 1200)+# pragma once+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)++#include "asio/detail/config.hpp"++#if (defined(ASIO_HAS_STD_TUPLE) \+ && defined(ASIO_HAS_DECLTYPE) \+ && defined(ASIO_HAS_VARIADIC_TEMPLATES)) \+ || defined(GENERATING_DOCUMENTATION)++#include <tuple>+#include "asio/associator.hpp"+#include "asio/async_result.hpp"+#include "asio/detail/type_traits.hpp"+#include "asio/detail/utility.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {++/// Trait for detecting objects that are usable as deferred operations.+template <typename T>+struct is_deferred : false_type+{+};++/// Helper type to wrap multiple completion signatures.+template <typename... Signatures>+struct deferred_signatures+{+};++namespace detail {++// Helper trait for getting the completion signatures of the tail in a sequence+// when invoked with the specified arguments.++template <typename Tail, typename... Signatures>+struct deferred_sequence_signatures;++template <typename Tail, typename R, typename... Args, typename... Signatures>+struct deferred_sequence_signatures<Tail, R(Args...), Signatures...>+ : completion_signature_of<decltype(declval<Tail>()(declval<Args>()...))>+{+ static_assert(+ !is_same<decltype(declval<Tail>()(declval<Args>()...)), void>::value,+ "deferred functions must produce a deferred return type");+};++// Completion handler for the head component of a deferred sequence.+template <typename Handler, typename Tail>+class deferred_sequence_handler+{+public:+ template <typename H, typename T>+ explicit deferred_sequence_handler(+ ASIO_MOVE_ARG(H) handler, ASIO_MOVE_ARG(T) tail)+ : handler_(ASIO_MOVE_CAST(H)(handler)),+ tail_(ASIO_MOVE_CAST(T)(tail))+ {+ }++ template <typename... Args>+ void operator()(ASIO_MOVE_ARG(Args)... args)+ {+ ASIO_MOVE_OR_LVALUE(Tail)(tail_)(+ ASIO_MOVE_CAST(Args)(args)...)(+ ASIO_MOVE_OR_LVALUE(Handler)(handler_));+ }++//private:+ Handler handler_;+ Tail tail_;+};++template <typename Head, typename Tail, typename... Signatures>+class deferred_sequence_base+{+private:+ struct initiate+ {+ template <typename Handler>+ void operator()(ASIO_MOVE_ARG(Handler) handler,+ Head head, ASIO_MOVE_ARG(Tail) tail)+ {+ ASIO_MOVE_OR_LVALUE(Head)(head)(+ deferred_sequence_handler<+ typename decay<Handler>::type,+ typename decay<Tail>::type>(+ ASIO_MOVE_CAST(Handler)(handler),+ ASIO_MOVE_CAST(Tail)(tail)));+ }+ };++ Head head_;+ Tail tail_;++public:+ template <typename H, typename T>+ ASIO_CONSTEXPR explicit deferred_sequence_base(+ ASIO_MOVE_ARG(H) head, ASIO_MOVE_ARG(T) tail)+ : head_(ASIO_MOVE_CAST(H)(head)),+ tail_(ASIO_MOVE_CAST(T)(tail))+ {+ }++ template <ASIO_COMPLETION_TOKEN_FOR(Signatures...) CompletionToken>+ auto operator()(+ ASIO_MOVE_ARG(CompletionToken) token) ASIO_RVALUE_REF_QUAL+ -> decltype(+ asio::async_initiate<CompletionToken, Signatures...>(+ declval<initiate>(), token,+ ASIO_MOVE_OR_LVALUE(Head)(this->head_),+ ASIO_MOVE_OR_LVALUE(Tail)(this->tail_)))+ {+ return asio::async_initiate<CompletionToken, Signatures...>(+ initiate(), token,+ ASIO_MOVE_OR_LVALUE(Head)(head_),+ ASIO_MOVE_OR_LVALUE(Tail)(tail_));+ }++#if defined(ASIO_HAS_REF_QUALIFIED_FUNCTIONS)+ template <ASIO_COMPLETION_TOKEN_FOR(Signatures...) CompletionToken>+ auto operator()(+ ASIO_MOVE_ARG(CompletionToken) token) const &+ -> decltype(+ asio::async_initiate<CompletionToken, Signatures...>(+ initiate(), token, this->head_, this->tail_))+ {+ return asio::async_initiate<CompletionToken, Signatures...>(+ initiate(), token, head_, tail_);+ }+#endif // defined(ASIO_HAS_REF_QUALIFIED_FUNCTIONS)+};++// Two-step application of variadic Signatures to determine correct base type.++template <typename Head, typename Tail>+struct deferred_sequence_types+{+ template <typename... Signatures>+ struct op1+ {+ typedef deferred_sequence_base<Head, Tail, Signatures...> type;+ };++ template <typename... Signatures>+ struct op2+ {+ typedef typename deferred_sequence_signatures<Tail, Signatures...>::template+ apply<op1>::type::type type;+ };++ typedef typename completion_signature_of<Head>::template+ apply<op2>::type::type base;+};++} // namespace detail++/// Used to represent an empty deferred action.+struct deferred_noop+{+ /// No effect.+ template <typename... Args>+ void operator()(ASIO_MOVE_ARG(Args)...) ASIO_RVALUE_REF_QUAL+ {+ }++#if defined(ASIO_HAS_REF_QUALIFIED_FUNCTIONS)+ /// No effect.+ template <typename... Args>+ void operator()(ASIO_MOVE_ARG(Args)...) const &+ {+ }+#endif // defined(ASIO_HAS_REF_QUALIFIED_FUNCTIONS)+};++#if !defined(GENERATING_DOCUMENTATION)+template <>+struct is_deferred<deferred_noop> : true_type+{+};+#endif // !defined(GENERATING_DOCUMENTATION)++/// Tag type to disambiguate deferred constructors.+struct deferred_init_tag {};++/// Wraps a function object so that it may be used as an element in a deferred+/// composition.+template <typename Function>+class deferred_function+{+public:+ /// Constructor. + template <typename F>+ ASIO_CONSTEXPR explicit deferred_function(+ deferred_init_tag, ASIO_MOVE_ARG(F) function)+ : function_(ASIO_MOVE_CAST(F)(function))+ {+ }++//private:+ Function function_;++public:+ template <typename... Args>+ auto operator()(+ ASIO_MOVE_ARG(Args)... args) ASIO_RVALUE_REF_QUAL+ -> decltype(+ ASIO_MOVE_CAST(Function)(this->function_)(+ ASIO_MOVE_CAST(Args)(args)...))+ {+ return ASIO_MOVE_CAST(Function)(function_)(+ ASIO_MOVE_CAST(Args)(args)...);+ }++#if defined(ASIO_HAS_REF_QUALIFIED_FUNCTIONS)+ template <typename... Args>+ auto operator()(+ ASIO_MOVE_ARG(Args)... args) const &+ -> decltype(Function(function_)(ASIO_MOVE_CAST(Args)(args)...))+ {+ return Function(function_)(ASIO_MOVE_CAST(Args)(args)...);+ }+#endif // defined(ASIO_HAS_REF_QUALIFIED_FUNCTIONS)+};++#if !defined(GENERATING_DOCUMENTATION)+template <typename Function>+struct is_deferred<deferred_function<Function> > : true_type+{+};+#endif // !defined(GENERATING_DOCUMENTATION)++/// Encapsulates deferred values.+template <typename... Values>+class ASIO_NODISCARD deferred_values+{+private:+ std::tuple<Values...> values_;++ struct initiate+ {+ template <typename Handler, typename... V>+ void operator()(Handler handler, ASIO_MOVE_ARG(V)... values)+ {+ ASIO_MOVE_OR_LVALUE(Handler)(handler)(+ ASIO_MOVE_CAST(V)(values)...);+ }+ };++ template <typename CompletionToken, std::size_t... I>+ auto invoke_helper(+ ASIO_MOVE_ARG(CompletionToken) token,+ detail::index_sequence<I...>)+ -> decltype(+ asio::async_initiate<CompletionToken, void(Values...)>(+ initiate(), token,+ std::get<I>(+ ASIO_MOVE_CAST(std::tuple<Values...>)(this->values_))...))+ {+ return asio::async_initiate<CompletionToken, void(Values...)>(+ initiate(), token,+ std::get<I>(ASIO_MOVE_CAST(std::tuple<Values...>)(values_))...);+ }++#if defined(ASIO_HAS_REF_QUALIFIED_FUNCTIONS)+ template <typename CompletionToken, std::size_t... I>+ auto const_invoke_helper(+ ASIO_MOVE_ARG(CompletionToken) token,+ detail::index_sequence<I...>)+ -> decltype(+ asio::async_initiate<CompletionToken, void(Values...)>(+ initiate(), token, std::get<I>(values_)...))+ {+ return asio::async_initiate<CompletionToken, void(Values...)>(+ initiate(), token, std::get<I>(values_)...);+ }+#endif // defined(ASIO_HAS_REF_QUALIFIED_FUNCTIONS)++public:+ /// Construct a deferred asynchronous operation from the arguments to an+ /// initiation function object.+ template <typename... V>+ ASIO_CONSTEXPR explicit deferred_values(+ deferred_init_tag, ASIO_MOVE_ARG(V)... values)+ : values_(ASIO_MOVE_CAST(V)(values)...)+ {+ }++ /// Initiate the deferred operation using the supplied completion token.+ template <ASIO_COMPLETION_TOKEN_FOR(void(Values...)) CompletionToken>+ auto operator()(+ ASIO_MOVE_ARG(CompletionToken) token) ASIO_RVALUE_REF_QUAL+ -> decltype(+ this->invoke_helper(+ ASIO_MOVE_CAST(CompletionToken)(token),+ detail::index_sequence_for<Values...>()))+ {+ return this->invoke_helper(+ ASIO_MOVE_CAST(CompletionToken)(token),+ detail::index_sequence_for<Values...>());+ }++#if defined(ASIO_HAS_REF_QUALIFIED_FUNCTIONS)+ template <ASIO_COMPLETION_TOKEN_FOR(void(Values...)) CompletionToken>+ auto operator()(+ ASIO_MOVE_ARG(CompletionToken) token) const &+ -> decltype(+ this->const_invoke_helper(+ ASIO_MOVE_CAST(CompletionToken)(token),+ detail::index_sequence_for<Values...>()))+ {+ return this->const_invoke_helper(+ ASIO_MOVE_CAST(CompletionToken)(token),+ detail::index_sequence_for<Values...>());+ }+#endif // defined(ASIO_HAS_REF_QUALIFIED_FUNCTIONS)+};++#if !defined(GENERATING_DOCUMENTATION)+template <typename... Values>+struct is_deferred<deferred_values<Values...> > : true_type+{+};+#endif // !defined(GENERATING_DOCUMENTATION)++/// Encapsulates a deferred asynchronous operation.+template <typename Signature, typename Initiation, typename... InitArgs>+class ASIO_NODISCARD deferred_async_operation+{+private:+ typedef typename decay<Initiation>::type initiation_t;+ initiation_t initiation_;+ typedef std::tuple<typename decay<InitArgs>::type...> init_args_t;+ init_args_t init_args_;++ template <typename CompletionToken, std::size_t... I>+ auto invoke_helper(+ ASIO_MOVE_ARG(CompletionToken) token,+ detail::index_sequence<I...>)+ -> decltype(+ asio::async_initiate<CompletionToken, Signature>(+ ASIO_MOVE_CAST(initiation_t)(initiation_), token,+ std::get<I>(ASIO_MOVE_CAST(init_args_t)(init_args_))...))+ {+ return asio::async_initiate<CompletionToken, Signature>(+ ASIO_MOVE_CAST(initiation_t)(initiation_), token,+ std::get<I>(ASIO_MOVE_CAST(init_args_t)(init_args_))...);+ }++#if defined(ASIO_HAS_REF_QUALIFIED_FUNCTIONS)+ template <typename CompletionToken, std::size_t... I>+ auto const_invoke_helper(+ ASIO_MOVE_ARG(CompletionToken) token,+ detail::index_sequence<I...>) const &+ -> decltype(+ asio::async_initiate<CompletionToken, Signature>(+ initiation_t(initiation_), token, std::get<I>(init_args_)...))+ {+ return asio::async_initiate<CompletionToken, Signature>(+ initiation_t(initiation_), token, std::get<I>(init_args_)...);+ }+#endif // defined(ASIO_HAS_REF_QUALIFIED_FUNCTIONS)++public:+ /// Construct a deferred asynchronous operation from the arguments to an+ /// initiation function object.+ template <typename I, typename... A>+ ASIO_CONSTEXPR explicit deferred_async_operation(+ deferred_init_tag, ASIO_MOVE_ARG(I) initiation,+ ASIO_MOVE_ARG(A)... init_args)+ : initiation_(ASIO_MOVE_CAST(I)(initiation)),+ init_args_(ASIO_MOVE_CAST(A)(init_args)...)+ {+ }++ /// Initiate the asynchronous operation using the supplied completion token.+ template <ASIO_COMPLETION_TOKEN_FOR(Signature) CompletionToken>+ auto operator()(+ ASIO_MOVE_ARG(CompletionToken) token) ASIO_RVALUE_REF_QUAL+ -> decltype(+ this->invoke_helper(+ ASIO_MOVE_CAST(CompletionToken)(token),+ detail::index_sequence_for<InitArgs...>()))+ {+ return this->invoke_helper(+ ASIO_MOVE_CAST(CompletionToken)(token),+ detail::index_sequence_for<InitArgs...>());+ }++#if defined(ASIO_HAS_REF_QUALIFIED_FUNCTIONS)+ template <ASIO_COMPLETION_TOKEN_FOR(Signature) CompletionToken>+ auto operator()(+ ASIO_MOVE_ARG(CompletionToken) token) const &+ -> decltype(+ this->const_invoke_helper(+ ASIO_MOVE_CAST(CompletionToken)(token),+ detail::index_sequence_for<InitArgs...>()))+ {+ return this->const_invoke_helper(+ ASIO_MOVE_CAST(CompletionToken)(token),+ detail::index_sequence_for<InitArgs...>());+ }+#endif // defined(ASIO_HAS_REF_QUALIFIED_FUNCTIONS)+};++/// Encapsulates a deferred asynchronous operation thas has multiple completion+/// signatures.+template <typename... Signatures, typename Initiation, typename... InitArgs>+class ASIO_NODISCARD deferred_async_operation<+ deferred_signatures<Signatures...>, Initiation, InitArgs...>+{+private:+ typedef typename decay<Initiation>::type initiation_t;+ initiation_t initiation_;+ typedef std::tuple<typename decay<InitArgs>::type...> init_args_t;+ init_args_t init_args_;++ template <typename CompletionToken, std::size_t... I>+ auto invoke_helper(+ ASIO_MOVE_ARG(CompletionToken) token,+ detail::index_sequence<I...>)+ -> decltype(+ asio::async_initiate<CompletionToken, Signatures...>(+ ASIO_MOVE_CAST(initiation_t)(initiation_), token,+ std::get<I>(ASIO_MOVE_CAST(init_args_t)(init_args_))...))+ {+ return asio::async_initiate<CompletionToken, Signatures...>(+ ASIO_MOVE_CAST(initiation_t)(initiation_), token,+ std::get<I>(ASIO_MOVE_CAST(init_args_t)(init_args_))...);+ }++#if defined(ASIO_HAS_REF_QUALIFIED_FUNCTIONS)+ template <typename CompletionToken, std::size_t... I>+ auto const_invoke_helper(+ ASIO_MOVE_ARG(CompletionToken) token,+ detail::index_sequence<I...>) const &+ -> decltype(+ asio::async_initiate<CompletionToken, Signatures...>(+ initiation_t(initiation_), token, std::get<I>(init_args_)...))+ {+ return asio::async_initiate<CompletionToken, Signatures...>(+ initiation_t(initiation_), token, std::get<I>(init_args_)...);+ }+#endif // defined(ASIO_HAS_REF_QUALIFIED_FUNCTIONS)++public:+ /// Construct a deferred asynchronous operation from the arguments to an+ /// initiation function object.+ template <typename I, typename... A>+ ASIO_CONSTEXPR explicit deferred_async_operation(+ deferred_init_tag, ASIO_MOVE_ARG(I) initiation,+ ASIO_MOVE_ARG(A)... init_args)+ : initiation_(ASIO_MOVE_CAST(I)(initiation)),+ init_args_(ASIO_MOVE_CAST(A)(init_args)...)+ {+ }++ /// Initiate the asynchronous operation using the supplied completion token.+ template <ASIO_COMPLETION_TOKEN_FOR(Signatures...) CompletionToken>+ auto operator()(+ ASIO_MOVE_ARG(CompletionToken) token) ASIO_RVALUE_REF_QUAL+ -> decltype(+ this->invoke_helper(+ ASIO_MOVE_CAST(CompletionToken)(token),+ detail::index_sequence_for<InitArgs...>()))+ {+ return this->invoke_helper(+ ASIO_MOVE_CAST(CompletionToken)(token),+ detail::index_sequence_for<InitArgs...>());+ }++#if defined(ASIO_HAS_REF_QUALIFIED_FUNCTIONS)+ template <ASIO_COMPLETION_TOKEN_FOR(Signatures...) CompletionToken>+ auto operator()(+ ASIO_MOVE_ARG(CompletionToken) token) const &+ -> decltype(+ this->const_invoke_helper(+ ASIO_MOVE_CAST(CompletionToken)(token),+ detail::index_sequence_for<InitArgs...>()))+ {+ return this->const_invoke_helper(+ ASIO_MOVE_CAST(CompletionToken)(token),+ detail::index_sequence_for<InitArgs...>());+ }+#endif // defined(ASIO_HAS_REF_QUALIFIED_FUNCTIONS)+};++#if !defined(GENERATING_DOCUMENTATION)+template <typename Signature, typename Initiation, typename... InitArgs>+struct is_deferred<+ deferred_async_operation<Signature, Initiation, InitArgs...> > : true_type+{+};+#endif // !defined(GENERATING_DOCUMENTATION)++/// Defines a link between two consecutive operations in a sequence.+template <typename Head, typename Tail>+class ASIO_NODISCARD deferred_sequence :+ public detail::deferred_sequence_types<Head, Tail>::base+{+public:+ template <typename H, typename T>+ ASIO_CONSTEXPR explicit deferred_sequence(deferred_init_tag,+ ASIO_MOVE_ARG(H) head, ASIO_MOVE_ARG(T) tail)+ : detail::deferred_sequence_types<Head, Tail>::base(+ ASIO_MOVE_CAST(H)(head), ASIO_MOVE_CAST(T)(tail))+ {+ }++#if defined(GENERATING_DOCUMENTATION)+ template <typename CompletionToken>+ auto operator()(ASIO_MOVE_ARG(CompletionToken) token)+ ASIO_RVALUE_REF_QUAL;++ template <typename CompletionToken>+ auto operator()(ASIO_MOVE_ARG(CompletionToken) token) const &;+#endif // defined(ASIO_HAS_REF_QUALIFIED_FUNCTIONS)+};++#if !defined(GENERATING_DOCUMENTATION)+template <typename Head, typename Tail>+struct is_deferred<deferred_sequence<Head, Tail> > : true_type+{+};+#endif // !defined(GENERATING_DOCUMENTATION)++/// Used to represent a deferred conditional branch.+template <typename OnTrue = deferred_noop,+ typename OnFalse = deferred_noop>+class ASIO_NODISCARD deferred_conditional+{+private:+ template <typename T, typename F> friend class deferred_conditional;++ // Helper constructor.+ template <typename T, typename F>+ explicit deferred_conditional(bool b, ASIO_MOVE_ARG(T) on_true,+ ASIO_MOVE_ARG(F) on_false)+ : on_true_(ASIO_MOVE_CAST(T)(on_true)),+ on_false_(ASIO_MOVE_CAST(F)(on_false)),+ bool_(b)+ {+ }++ OnTrue on_true_;+ OnFalse on_false_;+ bool bool_;++public:+ /// Construct a deferred conditional with the value to determine which branch+ /// will be executed.+ ASIO_CONSTEXPR explicit deferred_conditional(bool b)+ : on_true_(),+ on_false_(),+ bool_(b)+ {+ }++ /// Invoke the conditional branch bsaed on the stored alue.+ template <typename... Args>+ auto operator()(ASIO_MOVE_ARG(Args)... args) ASIO_RVALUE_REF_QUAL+ -> decltype(+ ASIO_MOVE_OR_LVALUE(OnTrue)(on_true_)(+ ASIO_MOVE_CAST(Args)(args)...))+ {+ if (bool_)+ {+ return ASIO_MOVE_OR_LVALUE(OnTrue)(on_true_)(+ ASIO_MOVE_CAST(Args)(args)...);+ }+ else+ {+ return ASIO_MOVE_OR_LVALUE(OnFalse)(on_false_)(+ ASIO_MOVE_CAST(Args)(args)...);+ }+ }++#if defined(ASIO_HAS_REF_QUALIFIED_FUNCTIONS)+ template <typename... Args>+ auto operator()(ASIO_MOVE_ARG(Args)... args) const &+ -> decltype(on_true_(ASIO_MOVE_CAST(Args)(args)...))+ {+ if (bool_)+ {+ return on_true_(ASIO_MOVE_CAST(Args)(args)...);+ }+ else+ {+ return on_false_(ASIO_MOVE_CAST(Args)(args)...);+ }+ }+#endif // defined(ASIO_HAS_REF_QUALIFIED_FUNCTIONS)++ /// Set the true branch of the conditional.+ template <typename T>+ deferred_conditional<T, OnFalse> then(T on_true,+ typename constraint<+ is_deferred<T>::value+ >::type* = 0,+ typename constraint<+ is_same<+ typename conditional<true, OnTrue, T>::type,+ deferred_noop+ >::value+ >::type* = 0) ASIO_RVALUE_REF_QUAL+ {+ return deferred_conditional<T, OnFalse>(+ bool_, ASIO_MOVE_CAST(T)(on_true),+ ASIO_MOVE_CAST(OnFalse)(on_false_));+ }++ /// Set the false branch of the conditional.+ template <typename T>+ deferred_conditional<OnTrue, T> otherwise(T on_false,+ typename constraint<+ is_deferred<T>::value+ >::type* = 0,+ typename constraint<+ !is_same<+ typename conditional<true, OnTrue, T>::type,+ deferred_noop+ >::value+ >::type* = 0,+ typename constraint<+ is_same<+ typename conditional<true, OnFalse, T>::type,+ deferred_noop+ >::value+ >::type* = 0) ASIO_RVALUE_REF_QUAL+ {+ return deferred_conditional<OnTrue, T>(+ bool_, ASIO_MOVE_CAST(OnTrue)(on_true_),+ ASIO_MOVE_CAST(T)(on_false));+ }+};++#if !defined(GENERATING_DOCUMENTATION)+template <typename OnTrue, typename OnFalse>+struct is_deferred<deferred_conditional<OnTrue, OnFalse> > : true_type+{+};+#endif // !defined(GENERATING_DOCUMENTATION)++/// Class used to specify that an asynchronous operation should return a+/// function object to lazily launch the operation.+/**+ * The deferred_t class is used to indicate that an asynchronous operation+ * should return a function object which is itself an initiation function. A+ * deferred_t object may be passed as a completion token to an asynchronous+ * operation, typically using the special value @c asio::deferred. For+ * example:+ *+ * @code auto my_deferred_op+ * = my_socket.async_read_some(my_buffer,+ * asio::deferred); @endcode+ *+ * The initiating function (async_read_some in the above example) returns a+ * function object that will lazily initiate the operation.+ */+class deferred_t+{+public:+ /// Default constructor.+ ASIO_CONSTEXPR deferred_t()+ {+ }++ /// Adapts an executor to add the @c deferred_t completion token as the+ /// default.+ template <typename InnerExecutor>+ struct executor_with_default : InnerExecutor+ {+ /// Specify @c deferred_t as the default completion token type.+ typedef deferred_t default_completion_token_type;++ /// Construct the adapted executor from the inner executor type.+ template <typename InnerExecutor1>+ executor_with_default(const InnerExecutor1& ex,+ typename constraint<+ conditional<+ !is_same<InnerExecutor1, executor_with_default>::value,+ is_convertible<InnerExecutor1, InnerExecutor>,+ false_type+ >::type::value+ >::type = 0) ASIO_NOEXCEPT+ : InnerExecutor(ex)+ {+ }+ };++ /// Type alias to adapt an I/O object to use @c deferred_t as its+ /// default completion token type.+#if defined(ASIO_HAS_ALIAS_TEMPLATES) \+ || defined(GENERATING_DOCUMENTATION)+ template <typename T>+ using as_default_on_t = typename T::template rebind_executor<+ executor_with_default<typename T::executor_type> >::other;+#endif // defined(ASIO_HAS_ALIAS_TEMPLATES)+ // || defined(GENERATING_DOCUMENTATION)++ /// Function helper to adapt an I/O object to use @c deferred_t as its+ /// default completion token type.+ template <typename T>+ static typename decay<T>::type::template rebind_executor<+ executor_with_default<typename decay<T>::type::executor_type>+ >::other+ as_default_on(ASIO_MOVE_ARG(T) object)+ {+ return typename decay<T>::type::template rebind_executor<+ executor_with_default<typename decay<T>::type::executor_type>+ >::other(ASIO_MOVE_CAST(T)(object));+ }++ /// Creates a new deferred from a function.+ template <typename Function>+ typename constraint<+ !is_deferred<typename decay<Function>::type>::value,+ deferred_function<typename decay<Function>::type>+ >::type operator()(ASIO_MOVE_ARG(Function) function) const+ {+ return deferred_function<typename decay<Function>::type>(+ deferred_init_tag{}, ASIO_MOVE_CAST(Function)(function));+ }++ /// Passes through anything that is already deferred.+ template <typename T>+ typename constraint<+ is_deferred<typename decay<T>::type>::value,+ typename decay<T>::type+ >::type operator()(ASIO_MOVE_ARG(T) t) const+ {+ return ASIO_MOVE_CAST(T)(t);+ }++ /// Returns a deferred operation that returns the provided values.+ template <typename... Args>+ static ASIO_CONSTEXPR deferred_values<typename decay<Args>::type...>+ values(ASIO_MOVE_ARG(Args)... args)+ {+ return deferred_values<typename decay<Args>::type...>(+ deferred_init_tag{}, ASIO_MOVE_CAST(Args)(args)...);+ }++ /// Creates a conditional object for branching deferred operations.+ static ASIO_CONSTEXPR deferred_conditional<> when(bool b)+ {+ return deferred_conditional<>(b);+ }+};++/// Pipe operator used to chain deferred operations.+template <typename Head, typename Tail>+inline auto operator|(Head head, ASIO_MOVE_ARG(Tail) tail)+ -> typename constraint<+ is_deferred<Head>::value,+ decltype(ASIO_MOVE_OR_LVALUE(Head)(head)(+ ASIO_MOVE_CAST(Tail)(tail)))+ >::type+{+ return ASIO_MOVE_OR_LVALUE(Head)(head)(+ ASIO_MOVE_CAST(Tail)(tail));+}++/// A @ref completion_token object used to specify that an asynchronous+/// operation should return a function object to lazily launch the operation.+/**+ * See the documentation for asio::deferred_t for a usage example.+ */+#if defined(ASIO_HAS_CONSTEXPR) || defined(GENERATING_DOCUMENTATION)+constexpr deferred_t deferred;+#elif defined(ASIO_MSVC)+__declspec(selectany) deferred_t deferred;+#endif++} // namespace asio++#include "asio/detail/pop_options.hpp"++#include "asio/impl/deferred.hpp"++#endif // (defined(ASIO_HAS_STD_TUPLE)+ // && defined(ASIO_HAS_DECLTYPE))+ // && defined(ASIO_HAS_VARIADIC_TEMPLATES))+ // || defined(GENERATING_DOCUMENTATION)++#endif // ASIO_DEFERRED_HPP
link/modules/asio-standalone/asio/include/asio/detached.hpp view
@@ -2,7 +2,7 @@ // detached.hpp // ~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -23,15 +23,15 @@ namespace asio { -/// Class used to specify that an asynchronous operation is detached.+/// A @ref completion_token type used to specify that an asynchronous operation+/// is detached. /**- * The detached_t class is used to indicate that an asynchronous operation is * detached. That is, there is no completion handler waiting for the * operation's result. A detached_t object may be passed as a handler to an * asynchronous operation, typically using the special value * @c asio::detached. For example:-+ * * @code my_socket.async_send(my_buffer, asio::detached); * @endcode */@@ -61,9 +61,9 @@ /// that to construct the adapted executor. template <typename OtherExecutor> executor_with_default(const OtherExecutor& ex,- typename enable_if<+ typename constraint< is_convertible<OtherExecutor, InnerExecutor>::value- >::type* = 0) ASIO_NOEXCEPT+ >::type = 0) ASIO_NOEXCEPT : InnerExecutor(ex) { }@@ -93,7 +93,8 @@ } }; -/// A special value, similar to std::nothrow.+/// A @ref completion_token object used to specify that an asynchronous+/// operation is detached. /** * See the documentation for asio::detached_t for a usage example. */
link/modules/asio-standalone/asio/include/asio/detail/array.hpp view
@@ -2,7 +2,7 @@ // detail/array.hpp // ~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/detail/array_fwd.hpp view
@@ -2,7 +2,7 @@ // detail/array_fwd.hpp // ~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/detail/assert.hpp view
@@ -2,7 +2,7 @@ // detail/assert.hpp // ~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/detail/atomic_count.hpp view
@@ -2,7 +2,7 @@ // detail/atomic_count.hpp // ~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -31,11 +31,13 @@ #if !defined(ASIO_HAS_THREADS) typedef long atomic_count; inline void increment(atomic_count& a, long b) { a += b; }+inline void decrement(atomic_count& a, long b) { a -= b; } inline void ref_count_up(atomic_count& a) { ++a; } inline bool ref_count_down(atomic_count& a) { return --a == 0; } #elif defined(ASIO_HAS_STD_ATOMIC) typedef std::atomic<long> atomic_count; inline void increment(atomic_count& a, long b) { a += b; }+inline void decrement(atomic_count& a, long b) { a -= b; } inline void ref_count_up(atomic_count& a) {@@ -54,6 +56,7 @@ #else // defined(ASIO_HAS_STD_ATOMIC) typedef boost::detail::atomic_count atomic_count; inline void increment(atomic_count& a, long b) { while (b > 0) ++a, --b; }+inline void decrement(atomic_count& a, long b) { while (b > 0) --a, --b; } inline void ref_count_up(atomic_count& a) { ++a; } inline bool ref_count_down(atomic_count& a) { return --a == 0; } #endif // defined(ASIO_HAS_STD_ATOMIC)
+ link/modules/asio-standalone/asio/include/asio/detail/base_from_cancellation_state.hpp view
@@ -0,0 +1,163 @@+//+// detail/base_from_cancellation_state.hpp+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com)+//+// Distributed under the Boost Software License, Version 1.0. (See accompanying+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)+//++#ifndef ASIO_DETAIL_BASE_FROM_CANCELLATION_STATE_HPP+#define ASIO_DETAIL_BASE_FROM_CANCELLATION_STATE_HPP++#if defined(_MSC_VER) && (_MSC_VER >= 1200)+# pragma once+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)++#include "asio/detail/config.hpp"+#include "asio/associated_cancellation_slot.hpp"+#include "asio/cancellation_state.hpp"+#include "asio/detail/type_traits.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {+namespace detail {++template <typename Handler, typename = void>+class base_from_cancellation_state+{+public:+ typedef cancellation_slot cancellation_slot_type;++ cancellation_slot_type get_cancellation_slot() const ASIO_NOEXCEPT+ {+ return cancellation_state_.slot();+ }++ cancellation_state get_cancellation_state() const ASIO_NOEXCEPT+ {+ return cancellation_state_;+ }++protected:+ explicit base_from_cancellation_state(const Handler& handler)+ : cancellation_state_(+ asio::get_associated_cancellation_slot(handler))+ {+ }++ template <typename Filter>+ base_from_cancellation_state(const Handler& handler, Filter filter)+ : cancellation_state_(+ asio::get_associated_cancellation_slot(handler), filter, filter)+ {+ }++ template <typename InFilter, typename OutFilter>+ base_from_cancellation_state(const Handler& handler,+ ASIO_MOVE_ARG(InFilter) in_filter,+ ASIO_MOVE_ARG(OutFilter) out_filter)+ : cancellation_state_(+ asio::get_associated_cancellation_slot(handler),+ ASIO_MOVE_CAST(InFilter)(in_filter),+ ASIO_MOVE_CAST(OutFilter)(out_filter))+ {+ }++ void reset_cancellation_state(const Handler& handler)+ {+ cancellation_state_ = cancellation_state(+ asio::get_associated_cancellation_slot(handler));+ }++ template <typename Filter>+ void reset_cancellation_state(const Handler& handler, Filter filter)+ {+ cancellation_state_ = cancellation_state(+ asio::get_associated_cancellation_slot(handler), filter, filter);+ }++ template <typename InFilter, typename OutFilter>+ void reset_cancellation_state(const Handler& handler,+ ASIO_MOVE_ARG(InFilter) in_filter,+ ASIO_MOVE_ARG(OutFilter) out_filter)+ {+ cancellation_state_ = cancellation_state(+ asio::get_associated_cancellation_slot(handler),+ ASIO_MOVE_CAST(InFilter)(in_filter),+ ASIO_MOVE_CAST(OutFilter)(out_filter));+ }++ cancellation_type_t cancelled() const ASIO_NOEXCEPT+ {+ return cancellation_state_.cancelled();+ }++private:+ cancellation_state cancellation_state_;+};++template <typename Handler>+class base_from_cancellation_state<Handler,+ typename enable_if<+ is_same<+ typename associated_cancellation_slot<+ Handler, cancellation_slot+ >::asio_associated_cancellation_slot_is_unspecialised,+ void+ >::value+ >::type>+{+public:+ cancellation_state get_cancellation_state() const ASIO_NOEXCEPT+ {+ return cancellation_state();+ }++protected:+ explicit base_from_cancellation_state(const Handler&)+ {+ }++ template <typename Filter>+ base_from_cancellation_state(const Handler&, Filter)+ {+ }++ template <typename InFilter, typename OutFilter>+ base_from_cancellation_state(const Handler&,+ ASIO_MOVE_ARG(InFilter),+ ASIO_MOVE_ARG(OutFilter))+ {+ }++ void reset_cancellation_state(const Handler&)+ {+ }++ template <typename Filter>+ void reset_cancellation_state(const Handler&, Filter)+ {+ }++ template <typename InFilter, typename OutFilter>+ void reset_cancellation_state(const Handler&,+ ASIO_MOVE_ARG(InFilter),+ ASIO_MOVE_ARG(OutFilter))+ {+ }++ ASIO_CONSTEXPR cancellation_type_t cancelled() const ASIO_NOEXCEPT+ {+ return cancellation_type::none;+ }+};++} // namespace detail+} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // ASIO_DETAIL_BASE_FROM_CANCELLATION_STATE_HPP
link/modules/asio-standalone/asio/include/asio/detail/base_from_completion_cond.hpp view
@@ -2,7 +2,7 @@ // detail/base_from_completion_cond.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/detail/bind_handler.hpp view
@@ -2,7 +2,7 @@ // detail/bind_handler.hpp // ~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -16,8 +16,7 @@ #endif // defined(_MSC_VER) && (_MSC_VER >= 1200) #include "asio/detail/config.hpp"-#include "asio/associated_allocator.hpp"-#include "asio/associated_executor.hpp"+#include "asio/associator.hpp" #include "asio/detail/handler_alloc_helpers.hpp" #include "asio/detail/handler_cont_helpers.hpp" #include "asio/detail/handler_invoke_helpers.hpp"@@ -28,6 +27,113 @@ namespace asio { namespace detail { +template <typename Handler>+class binder0+{+public:+ template <typename T>+ binder0(int, ASIO_MOVE_ARG(T) handler)+ : handler_(ASIO_MOVE_CAST(T)(handler))+ {+ }++ binder0(Handler& handler)+ : handler_(ASIO_MOVE_CAST(Handler)(handler))+ {+ }++#if defined(ASIO_HAS_MOVE)+ binder0(const binder0& other)+ : handler_(other.handler_)+ {+ }++ binder0(binder0&& other)+ : handler_(ASIO_MOVE_CAST(Handler)(other.handler_))+ {+ }+#endif // defined(ASIO_HAS_MOVE)++ void operator()()+ {+ ASIO_MOVE_OR_LVALUE(Handler)(handler_)();+ }++ void operator()() const+ {+ handler_();+ }++//private:+ Handler handler_;+};++template <typename Handler>+inline asio_handler_allocate_is_deprecated+asio_handler_allocate(std::size_t size,+ binder0<Handler>* this_handler)+{+#if defined(ASIO_NO_DEPRECATED)+ asio_handler_alloc_helpers::allocate(size, this_handler->handler_);+ return asio_handler_allocate_is_no_longer_used();+#else // defined(ASIO_NO_DEPRECATED)+ return asio_handler_alloc_helpers::allocate(+ size, this_handler->handler_);+#endif // defined(ASIO_NO_DEPRECATED)+}++template <typename Handler>+inline asio_handler_deallocate_is_deprecated+asio_handler_deallocate(void* pointer, std::size_t size,+ binder0<Handler>* this_handler)+{+ asio_handler_alloc_helpers::deallocate(+ pointer, size, this_handler->handler_);+#if defined(ASIO_NO_DEPRECATED)+ return asio_handler_deallocate_is_no_longer_used();+#endif // defined(ASIO_NO_DEPRECATED)+}++template <typename Handler>+inline bool asio_handler_is_continuation(+ binder0<Handler>* this_handler)+{+ return asio_handler_cont_helpers::is_continuation(+ this_handler->handler_);+}++template <typename Function, typename Handler>+inline asio_handler_invoke_is_deprecated+asio_handler_invoke(Function& function,+ binder0<Handler>* this_handler)+{+ asio_handler_invoke_helpers::invoke(+ function, this_handler->handler_);+#if defined(ASIO_NO_DEPRECATED)+ return asio_handler_invoke_is_no_longer_used();+#endif // defined(ASIO_NO_DEPRECATED)+}++template <typename Function, typename Handler>+inline asio_handler_invoke_is_deprecated+asio_handler_invoke(const Function& function,+ binder0<Handler>* this_handler)+{+ asio_handler_invoke_helpers::invoke(+ function, this_handler->handler_);+#if defined(ASIO_NO_DEPRECATED)+ return asio_handler_invoke_is_no_longer_used();+#endif // defined(ASIO_NO_DEPRECATED)+}++template <typename Handler>+inline binder0<typename decay<Handler>::type> bind_handler(+ ASIO_MOVE_ARG(Handler) handler)+{+ return binder0<typename decay<Handler>::type>(+ 0, ASIO_MOVE_CAST(Handler)(handler));+}+ template <typename Handler, typename Arg1> class binder1 {@@ -61,7 +167,8 @@ void operator()() {- handler_(static_cast<const Arg1&>(arg1_));+ ASIO_MOVE_OR_LVALUE(Handler)(handler_)(+ static_cast<const Arg1&>(arg1_)); } void operator()() const@@ -178,7 +285,8 @@ void operator()() {- handler_(static_cast<const Arg1&>(arg1_),+ ASIO_MOVE_OR_LVALUE(Handler)(handler_)(+ static_cast<const Arg1&>(arg1_), static_cast<const Arg2&>(arg2_)); } @@ -302,8 +410,10 @@ void operator()() {- handler_(static_cast<const Arg1&>(arg1_),- static_cast<const Arg2&>(arg2_), static_cast<const Arg3&>(arg3_));+ ASIO_MOVE_OR_LVALUE(Handler)(handler_)(+ static_cast<const Arg1&>(arg1_),+ static_cast<const Arg2&>(arg2_),+ static_cast<const Arg3&>(arg3_)); } void operator()() const@@ -435,8 +545,10 @@ void operator()() {- handler_(static_cast<const Arg1&>(arg1_),- static_cast<const Arg2&>(arg2_), static_cast<const Arg3&>(arg3_),+ ASIO_MOVE_OR_LVALUE(Handler)(handler_)(+ static_cast<const Arg1&>(arg1_),+ static_cast<const Arg2&>(arg2_),+ static_cast<const Arg3&>(arg3_), static_cast<const Arg4&>(arg4_)); } @@ -578,9 +690,12 @@ void operator()() {- handler_(static_cast<const Arg1&>(arg1_),- static_cast<const Arg2&>(arg2_), static_cast<const Arg3&>(arg3_),- static_cast<const Arg4&>(arg4_), static_cast<const Arg5&>(arg5_));+ ASIO_MOVE_OR_LVALUE(Handler)(handler_)(+ static_cast<const Arg1&>(arg1_),+ static_cast<const Arg2&>(arg2_),+ static_cast<const Arg3&>(arg3_),+ static_cast<const Arg4&>(arg4_),+ static_cast<const Arg5&>(arg5_)); } void operator()() const@@ -691,7 +806,8 @@ void operator()() {- handler_(ASIO_MOVE_CAST(Arg1)(arg1_));+ ASIO_MOVE_OR_LVALUE(Handler)(handler_)(+ ASIO_MOVE_CAST(Arg1)(arg1_)); } //private:@@ -766,7 +882,8 @@ void operator()() {- handler_(static_cast<const Arg1&>(arg1_),+ ASIO_MOVE_OR_LVALUE(Handler)(handler_)(+ static_cast<const Arg1&>(arg1_), ASIO_MOVE_CAST(Arg2)(arg2_)); } @@ -826,102 +943,196 @@ } // namespace detail -template <typename Handler, typename Arg1, typename Allocator>-struct associated_allocator<detail::binder1<Handler, Arg1>, Allocator>+template <template <typename, typename> class Associator,+ typename Handler, typename DefaultCandidate>+struct associator<Associator,+ detail::binder0<Handler>, DefaultCandidate>+ : Associator<Handler, DefaultCandidate> {- typedef typename associated_allocator<Handler, Allocator>::type type;+ static typename Associator<Handler, DefaultCandidate>::type+ get(const detail::binder0<Handler>& h) ASIO_NOEXCEPT+ {+ return Associator<Handler, DefaultCandidate>::get(h.handler_);+ } - static type get(const detail::binder1<Handler, Arg1>& h,- const Allocator& a = Allocator()) ASIO_NOEXCEPT+ static ASIO_AUTO_RETURN_TYPE_PREFIX2(+ typename Associator<Handler, DefaultCandidate>::type)+ get(const detail::binder0<Handler>& h,+ const DefaultCandidate& c) ASIO_NOEXCEPT+ ASIO_AUTO_RETURN_TYPE_SUFFIX((+ Associator<Handler, DefaultCandidate>::get(h.handler_, c))) {- return associated_allocator<Handler, Allocator>::get(h.handler_, a);+ return Associator<Handler, DefaultCandidate>::get(h.handler_, c); } }; -template <typename Handler, typename Arg1, typename Arg2, typename Allocator>-struct associated_allocator<detail::binder2<Handler, Arg1, Arg2>, Allocator>+template <template <typename, typename> class Associator,+ typename Handler, typename Arg1, typename DefaultCandidate>+struct associator<Associator,+ detail::binder1<Handler, Arg1>, DefaultCandidate>+ : Associator<Handler, DefaultCandidate> {- typedef typename associated_allocator<Handler, Allocator>::type type;+ static typename Associator<Handler, DefaultCandidate>::type+ get(const detail::binder1<Handler, Arg1>& h) ASIO_NOEXCEPT+ {+ return Associator<Handler, DefaultCandidate>::get(h.handler_);+ } - static type get(const detail::binder2<Handler, Arg1, Arg2>& h,- const Allocator& a = Allocator()) ASIO_NOEXCEPT+ static ASIO_AUTO_RETURN_TYPE_PREFIX2(+ typename Associator<Handler, DefaultCandidate>::type)+ get(const detail::binder1<Handler, Arg1>& h,+ const DefaultCandidate& c) ASIO_NOEXCEPT+ ASIO_AUTO_RETURN_TYPE_SUFFIX((+ Associator<Handler, DefaultCandidate>::get(h.handler_, c))) {- return associated_allocator<Handler, Allocator>::get(h.handler_, a);+ return Associator<Handler, DefaultCandidate>::get(h.handler_, c); } }; -template <typename Handler, typename Arg1, typename Executor>-struct associated_executor<detail::binder1<Handler, Arg1>, Executor>+template <template <typename, typename> class Associator,+ typename Handler, typename Arg1, typename Arg2,+ typename DefaultCandidate>+struct associator<Associator,+ detail::binder2<Handler, Arg1, Arg2>, DefaultCandidate>+ : Associator<Handler, DefaultCandidate> {- typedef typename associated_executor<Handler, Executor>::type type;+ static typename Associator<Handler, DefaultCandidate>::type+ get(const detail::binder2<Handler, Arg1, Arg2>& h) ASIO_NOEXCEPT+ {+ return Associator<Handler, DefaultCandidate>::get(h.handler_);+ } - static type get(const detail::binder1<Handler, Arg1>& h,- const Executor& ex = Executor()) ASIO_NOEXCEPT+ static ASIO_AUTO_RETURN_TYPE_PREFIX2(+ typename Associator<Handler, DefaultCandidate>::type)+ get(const detail::binder2<Handler, Arg1, Arg2>& h,+ const DefaultCandidate& c) ASIO_NOEXCEPT+ ASIO_AUTO_RETURN_TYPE_SUFFIX((+ Associator<Handler, DefaultCandidate>::get(h.handler_, c))) {- return associated_executor<Handler, Executor>::get(h.handler_, ex);+ return Associator<Handler, DefaultCandidate>::get(h.handler_, c); } }; -template <typename Handler, typename Arg1, typename Arg2, typename Executor>-struct associated_executor<detail::binder2<Handler, Arg1, Arg2>, Executor>+template <template <typename, typename> class Associator,+ typename Handler, typename Arg1, typename Arg2, typename Arg3,+ typename DefaultCandidate>+struct associator<Associator,+ detail::binder3<Handler, Arg1, Arg2, Arg3>, DefaultCandidate>+ : Associator<Handler, DefaultCandidate> {- typedef typename associated_executor<Handler, Executor>::type type;+ static typename Associator<Handler, DefaultCandidate>::type+ get(const detail::binder3<Handler, Arg1, Arg2, Arg3>& h) ASIO_NOEXCEPT+ {+ return Associator<Handler, DefaultCandidate>::get(h.handler_);+ } - static type get(const detail::binder2<Handler, Arg1, Arg2>& h,- const Executor& ex = Executor()) ASIO_NOEXCEPT+ static ASIO_AUTO_RETURN_TYPE_PREFIX2(+ typename Associator<Handler, DefaultCandidate>::type)+ get(const detail::binder3<Handler, Arg1, Arg2, Arg3>& h,+ const DefaultCandidate& c) ASIO_NOEXCEPT+ ASIO_AUTO_RETURN_TYPE_SUFFIX((+ Associator<Handler, DefaultCandidate>::get(h.handler_, c))) {- return associated_executor<Handler, Executor>::get(h.handler_, ex);+ return Associator<Handler, DefaultCandidate>::get(h.handler_, c); } }; -#if defined(ASIO_HAS_MOVE)--template <typename Handler, typename Arg1, typename Allocator>-struct associated_allocator<detail::move_binder1<Handler, Arg1>, Allocator>+template <template <typename, typename> class Associator,+ typename Handler, typename Arg1, typename Arg2, typename Arg3,+ typename Arg4, typename DefaultCandidate>+struct associator<Associator,+ detail::binder4<Handler, Arg1, Arg2, Arg3, Arg4>, DefaultCandidate>+ : Associator<Handler, DefaultCandidate> {- typedef typename associated_allocator<Handler, Allocator>::type type;+ static typename Associator<Handler, DefaultCandidate>::type+ get(const detail::binder4<Handler, Arg1, Arg2, Arg3, Arg4>& h)+ ASIO_NOEXCEPT+ {+ return Associator<Handler, DefaultCandidate>::get(h.handler_);+ } - static type get(const detail::move_binder1<Handler, Arg1>& h,- const Allocator& a = Allocator()) ASIO_NOEXCEPT+ static ASIO_AUTO_RETURN_TYPE_PREFIX2(+ typename Associator<Handler, DefaultCandidate>::type)+ get(const detail::binder4<Handler, Arg1, Arg2, Arg3, Arg4>& h,+ const DefaultCandidate& c) ASIO_NOEXCEPT+ ASIO_AUTO_RETURN_TYPE_SUFFIX((+ Associator<Handler, DefaultCandidate>::get(h.handler_, c))) {- return associated_allocator<Handler, Allocator>::get(h.handler_, a);+ return Associator<Handler, DefaultCandidate>::get(h.handler_, c); } }; -template <typename Handler, typename Arg1, typename Arg2, typename Allocator>-struct associated_allocator<- detail::move_binder2<Handler, Arg1, Arg2>, Allocator>+template <template <typename, typename> class Associator,+ typename Handler, typename Arg1, typename Arg2, typename Arg3,+ typename Arg4, typename Arg5, typename DefaultCandidate>+struct associator<Associator,+ detail::binder5<Handler, Arg1, Arg2, Arg3, Arg4, Arg5>, DefaultCandidate>+ : Associator<Handler, DefaultCandidate> {- typedef typename associated_allocator<Handler, Allocator>::type type;+ static typename Associator<Handler, DefaultCandidate>::type+ get(const detail::binder5<Handler, Arg1, Arg2, Arg3, Arg4, Arg5>& h)+ ASIO_NOEXCEPT+ {+ return Associator<Handler, DefaultCandidate>::get(h.handler_);+ } - static type get(const detail::move_binder2<Handler, Arg1, Arg2>& h,- const Allocator& a = Allocator()) ASIO_NOEXCEPT+ static ASIO_AUTO_RETURN_TYPE_PREFIX2(+ typename Associator<Handler, DefaultCandidate>::type)+ get(const detail::binder5<Handler, Arg1, Arg2, Arg3, Arg4, Arg5>& h,+ const DefaultCandidate& c) ASIO_NOEXCEPT+ ASIO_AUTO_RETURN_TYPE_SUFFIX((+ Associator<Handler, DefaultCandidate>::get(h.handler_, c))) {- return associated_allocator<Handler, Allocator>::get(h.handler_, a);+ return Associator<Handler, DefaultCandidate>::get(h.handler_, c); } }; -template <typename Handler, typename Arg1, typename Executor>-struct associated_executor<detail::move_binder1<Handler, Arg1>, Executor>+#if defined(ASIO_HAS_MOVE)++template <template <typename, typename> class Associator,+ typename Handler, typename Arg1, typename DefaultCandidate>+struct associator<Associator,+ detail::move_binder1<Handler, Arg1>, DefaultCandidate>+ : Associator<Handler, DefaultCandidate> {- typedef typename associated_executor<Handler, Executor>::type type;+ static typename Associator<Handler, DefaultCandidate>::type+ get(const detail::move_binder1<Handler, Arg1>& h) ASIO_NOEXCEPT+ {+ return Associator<Handler, DefaultCandidate>::get(h.handler_);+ } - static type get(const detail::move_binder1<Handler, Arg1>& h,- const Executor& ex = Executor()) ASIO_NOEXCEPT+ static ASIO_AUTO_RETURN_TYPE_PREFIX2(+ typename Associator<Handler, DefaultCandidate>::type)+ get(const detail::move_binder1<Handler, Arg1>& h,+ const DefaultCandidate& c) ASIO_NOEXCEPT+ ASIO_AUTO_RETURN_TYPE_SUFFIX((+ Associator<Handler, DefaultCandidate>::get(h.handler_, c))) {- return associated_executor<Handler, Executor>::get(h.handler_, ex);+ return Associator<Handler, DefaultCandidate>::get(h.handler_, c); } }; -template <typename Handler, typename Arg1, typename Arg2, typename Executor>-struct associated_executor<detail::move_binder2<Handler, Arg1, Arg2>, Executor>+template <template <typename, typename> class Associator,+ typename Handler, typename Arg1, typename Arg2,+ typename DefaultCandidate>+struct associator<Associator,+ detail::move_binder2<Handler, Arg1, Arg2>, DefaultCandidate>+ : Associator<Handler, DefaultCandidate> {- typedef typename associated_executor<Handler, Executor>::type type;+ static typename Associator<Handler, DefaultCandidate>::type+ get(const detail::move_binder2<Handler, Arg1, Arg2>& h) ASIO_NOEXCEPT+ {+ return Associator<Handler, DefaultCandidate>::get(h.handler_);+ } - static type get(const detail::move_binder2<Handler, Arg1, Arg2>& h,- const Executor& ex = Executor()) ASIO_NOEXCEPT+ static ASIO_AUTO_RETURN_TYPE_PREFIX2(+ typename Associator<Handler, DefaultCandidate>::type)+ get(const detail::move_binder2<Handler, Arg1, Arg2>& h,+ const DefaultCandidate& c) ASIO_NOEXCEPT+ ASIO_AUTO_RETURN_TYPE_SUFFIX((+ Associator<Handler, DefaultCandidate>::get(h.handler_, c))) {- return associated_executor<Handler, Executor>::get(h.handler_, ex);+ return Associator<Handler, DefaultCandidate>::get(h.handler_, c); } };
link/modules/asio-standalone/asio/include/asio/detail/blocking_executor_op.hpp view
@@ -2,7 +2,7 @@ // detail/blocking_executor_op.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -77,6 +77,7 @@ const asio::error_code& /*ec*/, std::size_t /*bytes_transferred*/) {+ ASIO_ASSUME(base != 0); blocking_executor_op* o(static_cast<blocking_executor_op*>(base)); typename blocking_executor_op_base<Operation>::do_complete_cleanup
link/modules/asio-standalone/asio/include/asio/detail/buffer_resize_guard.hpp view
@@ -2,7 +2,7 @@ // detail/buffer_resize_guard.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/detail/buffer_sequence_adapter.hpp view
@@ -2,7 +2,7 @@ // detail/buffer_sequence_adapter.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -19,6 +19,7 @@ #include "asio/buffer.hpp" #include "asio/detail/array_fwd.hpp" #include "asio/detail/socket_types.hpp"+#include "asio/registered_buffer.hpp" #include "asio/detail/push_options.hpp" @@ -105,6 +106,7 @@ { public: enum { is_single_buffer = false };+ enum { is_registered_buffer = false }; explicit buffer_sequence_adapter(const Buffers& buffer_sequence) : count_(0), total_buffer_size_(0)@@ -129,6 +131,11 @@ return total_buffer_size_; } + registered_buffer_id registered_id() const+ {+ return registered_buffer_id();+ }+ bool all_empty() const { return total_buffer_size_ == 0;@@ -248,6 +255,7 @@ { public: enum { is_single_buffer = true };+ enum { is_registered_buffer = false }; explicit buffer_sequence_adapter( const asio::mutable_buffer& buffer_sequence)@@ -271,6 +279,11 @@ return total_buffer_size_; } + registered_buffer_id registered_id() const+ {+ return registered_buffer_id();+ }+ bool all_empty() const { return total_buffer_size_ == 0;@@ -310,6 +323,7 @@ { public: enum { is_single_buffer = true };+ enum { is_registered_buffer = false }; explicit buffer_sequence_adapter( const asio::const_buffer& buffer_sequence)@@ -333,6 +347,11 @@ return total_buffer_size_; } + registered_buffer_id registered_id() const+ {+ return registered_buffer_id();+ }+ bool all_empty() const { return total_buffer_size_ == 0;@@ -374,6 +393,7 @@ { public: enum { is_single_buffer = true };+ enum { is_registered_buffer = false }; explicit buffer_sequence_adapter( const asio::mutable_buffers_1& buffer_sequence)@@ -397,6 +417,11 @@ return total_buffer_size_; } + registered_buffer_id registered_id() const+ {+ return registered_buffer_id();+ }+ bool all_empty() const { return total_buffer_size_ == 0;@@ -436,6 +461,7 @@ { public: enum { is_single_buffer = true };+ enum { is_registered_buffer = false }; explicit buffer_sequence_adapter( const asio::const_buffers_1& buffer_sequence)@@ -459,6 +485,11 @@ return total_buffer_size_; } + registered_buffer_id registered_id() const+ {+ return registered_buffer_id();+ }+ bool all_empty() const { return total_buffer_size_ == 0;@@ -494,12 +525,161 @@ #endif // !defined(ASIO_NO_DEPRECATED) +template <typename Buffer>+class buffer_sequence_adapter<Buffer, asio::mutable_registered_buffer>+ : buffer_sequence_adapter_base+{+public:+ enum { is_single_buffer = true };+ enum { is_registered_buffer = true };++ explicit buffer_sequence_adapter(+ const asio::mutable_registered_buffer& buffer_sequence)+ {+ init_native_buffer(buffer_, buffer_sequence.buffer());+ total_buffer_size_ = buffer_sequence.size();+ registered_id_ = buffer_sequence.id();+ }++ native_buffer_type* buffers()+ {+ return &buffer_;+ }++ std::size_t count() const+ {+ return 1;+ }++ std::size_t total_size() const+ {+ return total_buffer_size_;+ }++ registered_buffer_id registered_id() const+ {+ return registered_id_;+ }++ bool all_empty() const+ {+ return total_buffer_size_ == 0;+ }++ static bool all_empty(+ const asio::mutable_registered_buffer& buffer_sequence)+ {+ return buffer_sequence.size() == 0;+ }++ static void validate(+ const asio::mutable_registered_buffer& buffer_sequence)+ {+ buffer_sequence.data();+ }++ static Buffer first(+ const asio::mutable_registered_buffer& buffer_sequence)+ {+ return Buffer(buffer_sequence.buffer());+ }++ enum { linearisation_storage_size = 1 };++ static Buffer linearise(+ const asio::mutable_registered_buffer& buffer_sequence,+ const Buffer&)+ {+ return Buffer(buffer_sequence.buffer());+ }++private:+ native_buffer_type buffer_;+ std::size_t total_buffer_size_;+ registered_buffer_id registered_id_;+};++template <typename Buffer>+class buffer_sequence_adapter<Buffer, asio::const_registered_buffer>+ : buffer_sequence_adapter_base+{+public:+ enum { is_single_buffer = true };+ enum { is_registered_buffer = true };++ explicit buffer_sequence_adapter(+ const asio::const_registered_buffer& buffer_sequence)+ {+ init_native_buffer(buffer_, buffer_sequence.buffer());+ total_buffer_size_ = buffer_sequence.size();+ registered_id_ = buffer_sequence.id();+ }++ native_buffer_type* buffers()+ {+ return &buffer_;+ }++ std::size_t count() const+ {+ return 1;+ }++ std::size_t total_size() const+ {+ return total_buffer_size_;+ }++ registered_buffer_id registered_id() const+ {+ return registered_id_;+ }++ bool all_empty() const+ {+ return total_buffer_size_ == 0;+ }++ static bool all_empty(+ const asio::const_registered_buffer& buffer_sequence)+ {+ return buffer_sequence.size() == 0;+ }++ static void validate(+ const asio::const_registered_buffer& buffer_sequence)+ {+ buffer_sequence.data();+ }++ static Buffer first(+ const asio::const_registered_buffer& buffer_sequence)+ {+ return Buffer(buffer_sequence.buffer());+ }++ enum { linearisation_storage_size = 1 };++ static Buffer linearise(+ const asio::const_registered_buffer& buffer_sequence,+ const Buffer&)+ {+ return Buffer(buffer_sequence.buffer());+ }++private:+ native_buffer_type buffer_;+ std::size_t total_buffer_size_;+ registered_buffer_id registered_id_;+};+ template <typename Buffer, typename Elem> class buffer_sequence_adapter<Buffer, boost::array<Elem, 2> > : buffer_sequence_adapter_base { public: enum { is_single_buffer = false };+ enum { is_registered_buffer = false }; explicit buffer_sequence_adapter( const boost::array<Elem, 2>& buffer_sequence)@@ -524,6 +704,11 @@ return total_buffer_size_; } + registered_buffer_id registered_id() const+ {+ return registered_buffer_id();+ }+ bool all_empty() const { return total_buffer_size_ == 0;@@ -572,6 +757,7 @@ { public: enum { is_single_buffer = false };+ enum { is_registered_buffer = false }; explicit buffer_sequence_adapter( const std::array<Elem, 2>& buffer_sequence)@@ -594,6 +780,11 @@ std::size_t total_size() const { return total_buffer_size_;+ }++ registered_buffer_id registered_id() const+ {+ return registered_buffer_id(); } bool all_empty() const
link/modules/asio-standalone/asio/include/asio/detail/buffered_stream_storage.hpp view
@@ -2,7 +2,7 @@ // detail/buffered_stream_storage.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/detail/bulk_executor_op.hpp view
@@ -2,7 +2,7 @@ // detail/bulk_executor_op.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -49,6 +49,7 @@ std::size_t /*bytes_transferred*/) { // Take ownership of the handler object.+ ASIO_ASSUME(base != 0); bulk_executor_op* o(static_cast<bulk_executor_op*>(base)); Alloc allocator(o->allocator_); ptr p = { detail::addressof(allocator), o, o };
link/modules/asio-standalone/asio/include/asio/detail/call_stack.hpp view
@@ -2,7 +2,7 @@ // detail/call_stack.hpp // ~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/detail/chrono.hpp view
@@ -2,7 +2,7 @@ // detail/chrono.hpp // ~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/detail/chrono_time_traits.hpp view
@@ -2,7 +2,7 @@ // detail/chrono_time_traits.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/detail/completion_handler.hpp view
@@ -2,7 +2,7 @@ // detail/completion_handler.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+ link/modules/asio-standalone/asio/include/asio/detail/composed_work.hpp view
@@ -0,0 +1,328 @@+//+// detail/composed_work.hpp+// ~~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com)+//+// Distributed under the Boost Software License, Version 1.0. (See accompanying+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)+//++#ifndef ASIO_DETAIL_COMPOSED_WORK_HPP+#define ASIO_DETAIL_COMPOSED_WORK_HPP++#if defined(_MSC_VER) && (_MSC_VER >= 1200)+# pragma once+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)++#include "asio/detail/config.hpp"+#include "asio/detail/type_traits.hpp"+#include "asio/detail/variadic_templates.hpp"+#include "asio/execution/executor.hpp"+#include "asio/execution/outstanding_work.hpp"+#include "asio/executor_work_guard.hpp"+#include "asio/is_executor.hpp"+#include "asio/system_executor.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {+namespace detail {++template <typename Executor, typename = void>+class composed_work_guard+{+public:+ typedef typename decay<+ typename prefer_result<Executor,+ execution::outstanding_work_t::tracked_t+ >::type+ >::type executor_type;++ composed_work_guard(const Executor& ex)+ : executor_(asio::prefer(ex, execution::outstanding_work.tracked))+ {+ }++ void reset()+ {+ }++ executor_type get_executor() const ASIO_NOEXCEPT+ {+ return executor_;+ }++private:+ executor_type executor_;+};++template <>+struct composed_work_guard<system_executor>+{+public:+ typedef system_executor executor_type;++ composed_work_guard(const system_executor&)+ {+ }++ void reset()+ {+ }++ executor_type get_executor() const ASIO_NOEXCEPT+ {+ return system_executor();+ }+};++#if !defined(ASIO_NO_TS_EXECUTORS)++template <typename Executor>+struct composed_work_guard<Executor,+ typename enable_if<+ !execution::is_executor<Executor>::value+ >::type> : executor_work_guard<Executor>+{+ composed_work_guard(const Executor& ex)+ : executor_work_guard<Executor>(ex)+ {+ }+};++#endif // !defined(ASIO_NO_TS_EXECUTORS)++template <typename>+struct composed_io_executors;++template <>+struct composed_io_executors<void()>+{+ composed_io_executors() ASIO_NOEXCEPT+ : head_(system_executor())+ {+ }++ typedef system_executor head_type;+ system_executor head_;+};++inline composed_io_executors<void()> make_composed_io_executors()+{+ return composed_io_executors<void()>();+}++template <typename Head>+struct composed_io_executors<void(Head)>+{+ explicit composed_io_executors(const Head& ex) ASIO_NOEXCEPT+ : head_(ex)+ {+ }++ typedef Head head_type;+ Head head_;+};++template <typename Head>+inline composed_io_executors<void(Head)>+make_composed_io_executors(const Head& head)+{+ return composed_io_executors<void(Head)>(head);+}++#if defined(ASIO_HAS_VARIADIC_TEMPLATES)++template <typename Head, typename... Tail>+struct composed_io_executors<void(Head, Tail...)>+{+ explicit composed_io_executors(const Head& head,+ const Tail&... tail) ASIO_NOEXCEPT+ : head_(head),+ tail_(tail...)+ {+ }++ void reset()+ {+ head_.reset();+ tail_.reset();+ }++ typedef Head head_type;+ Head head_;+ composed_io_executors<void(Tail...)> tail_;+};++template <typename Head, typename... Tail>+inline composed_io_executors<void(Head, Tail...)>+make_composed_io_executors(const Head& head, const Tail&... tail)+{+ return composed_io_executors<void(Head, Tail...)>(head, tail...);+}++#else // defined(ASIO_HAS_VARIADIC_TEMPLATES)++#define ASIO_PRIVATE_COMPOSED_IO_EXECUTORS_DEF(n) \+template <typename Head, ASIO_VARIADIC_TPARAMS(n)> \+struct composed_io_executors<void(Head, ASIO_VARIADIC_TARGS(n))> \+{ \+ explicit composed_io_executors(const Head& head, \+ ASIO_VARIADIC_CONSTREF_PARAMS(n)) ASIO_NOEXCEPT \+ : head_(head), \+ tail_(ASIO_VARIADIC_BYVAL_ARGS(n)) \+ { \+ } \+\+ void reset() \+ { \+ head_.reset(); \+ tail_.reset(); \+ } \+\+ typedef Head head_type; \+ Head head_; \+ composed_io_executors<void(ASIO_VARIADIC_TARGS(n))> tail_; \+}; \+\+template <typename Head, ASIO_VARIADIC_TPARAMS(n)> \+inline composed_io_executors<void(Head, ASIO_VARIADIC_TARGS(n))> \+make_composed_io_executors(const Head& head, \+ ASIO_VARIADIC_CONSTREF_PARAMS(n)) \+{ \+ return composed_io_executors< \+ void(Head, ASIO_VARIADIC_TARGS(n))>( \+ head, ASIO_VARIADIC_BYVAL_ARGS(n)); \+} \+/**/+ASIO_VARIADIC_GENERATE(ASIO_PRIVATE_COMPOSED_IO_EXECUTORS_DEF)+#undef ASIO_PRIVATE_COMPOSED_IO_EXECUTORS_DEF++#endif // defined(ASIO_HAS_VARIADIC_TEMPLATES)++template <typename>+struct composed_work;++template <>+struct composed_work<void()>+{+ typedef composed_io_executors<void()> executors_type;++ composed_work(const executors_type&) ASIO_NOEXCEPT+ : head_(system_executor())+ {+ }++ void reset()+ {+ head_.reset();+ }++ typedef system_executor head_type;+ composed_work_guard<system_executor> head_;+};++template <typename Head>+struct composed_work<void(Head)>+{+ typedef composed_io_executors<void(Head)> executors_type;++ explicit composed_work(const executors_type& ex) ASIO_NOEXCEPT+ : head_(ex.head_)+ {+ }++ void reset()+ {+ head_.reset();+ }++ typedef Head head_type;+ composed_work_guard<Head> head_;+};++#if defined(ASIO_HAS_VARIADIC_TEMPLATES)++template <typename Head, typename... Tail>+struct composed_work<void(Head, Tail...)>+{+ typedef composed_io_executors<void(Head, Tail...)> executors_type;++ explicit composed_work(const executors_type& ex) ASIO_NOEXCEPT+ : head_(ex.head_),+ tail_(ex.tail_)+ {+ }++ void reset()+ {+ head_.reset();+ tail_.reset();+ }++ typedef Head head_type;+ composed_work_guard<Head> head_;+ composed_work<void(Tail...)> tail_;+};++#else // defined(ASIO_HAS_VARIADIC_TEMPLATES)++#define ASIO_PRIVATE_COMPOSED_WORK_DEF(n) \+template <typename Head, ASIO_VARIADIC_TPARAMS(n)> \+struct composed_work<void(Head, ASIO_VARIADIC_TARGS(n))> \+{ \+ typedef composed_io_executors<void(Head, \+ ASIO_VARIADIC_TARGS(n))> executors_type; \+\+ explicit composed_work(const executors_type& ex) ASIO_NOEXCEPT \+ : head_(ex.head_), \+ tail_(ex.tail_) \+ { \+ } \+\+ void reset() \+ { \+ head_.reset(); \+ tail_.reset(); \+ } \+\+ typedef Head head_type; \+ composed_work_guard<Head> head_; \+ composed_work<void(ASIO_VARIADIC_TARGS(n))> tail_; \+}; \+/**/+ASIO_VARIADIC_GENERATE(ASIO_PRIVATE_COMPOSED_WORK_DEF)+#undef ASIO_PRIVATE_COMPOSED_WORK_DEF++#endif // defined(ASIO_HAS_VARIADIC_TEMPLATES)++template <typename IoObject>+inline typename IoObject::executor_type+get_composed_io_executor(IoObject& io_object,+ typename enable_if<+ !is_executor<IoObject>::value+ >::type* = 0,+ typename enable_if<+ !execution::is_executor<IoObject>::value+ >::type* = 0)+{+ return io_object.get_executor();+}++template <typename Executor>+inline const Executor& get_composed_io_executor(const Executor& ex,+ typename enable_if<+ is_executor<Executor>::value+ || execution::is_executor<Executor>::value+ >::type* = 0)+{+ return ex;+}++} // namespace detail+} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // ASIO_DETAIL_COMPOSED_WORK_HPP
link/modules/asio-standalone/asio/include/asio/detail/concurrency_hint.hpp view
@@ -2,7 +2,7 @@ // detail/concurrency_hint.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/detail/conditionally_enabled_event.hpp view
@@ -2,7 +2,7 @@ // detail/conditionally_enabled_event.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/detail/conditionally_enabled_mutex.hpp view
@@ -2,7 +2,7 @@ // detail/conditionally_enabled_mutex.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/detail/config.hpp view
@@ -2,7 +2,7 @@ // detail/config.hpp // ~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -24,8 +24,20 @@ # endif // !defined(ASIO_ENABLE_BOOST) #endif // !defined(ASIO_STANDALONE) +// Make standard library feature macros available.+#if defined(__has_include)+# if __has_include(<version>)+# include <version>+# else // __has_include(<version>)+# include <cstddef>+# endif // __has_include(<version>)+#else // defined(__has_include)+# include <cstddef>+#endif // defined(__has_include)+ // boostify: non-boost code ends here #if defined(ASIO_STANDALONE)+# define ASIO_DISABLE_BOOST_ALIGN 1 # define ASIO_DISABLE_BOOST_ARRAY 1 # define ASIO_DISABLE_BOOST_ASSERT 1 # define ASIO_DISABLE_BOOST_BIND 1@@ -37,6 +49,7 @@ # define ASIO_DISABLE_BOOST_THROW_EXCEPTION 1 # define ASIO_DISABLE_BOOST_WORKAROUND 1 #else // defined(ASIO_STANDALONE)+// Boost.Config library is available. # include <boost/config.hpp> # include <boost/version.hpp> # define ASIO_HAS_BOOST_CONFIG 1@@ -112,8 +125,7 @@ # if __has_feature(__cxx_rvalue_references__) # define ASIO_HAS_MOVE 1 # endif // __has_feature(__cxx_rvalue_references__)-# endif // defined(__clang__)-# if defined(__GNUC__)+# elif defined(__GNUC__) # if ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 8)) || (__GNUC__ > 4) # if (__cplusplus >= 201103) || defined(__GXX_EXPERIMENTAL_CXX0X__) # define ASIO_HAS_MOVE 1@@ -148,6 +160,7 @@ # define ASIO_MOVE_CAST(type) static_cast<type&&> # define ASIO_MOVE_CAST2(type1, type2) static_cast<type1, type2&&> # define ASIO_MOVE_OR_LVALUE(type) static_cast<type&&>+# define ASIO_MOVE_OR_LVALUE_ARG(type) type&& # define ASIO_MOVE_OR_LVALUE_TYPE(type) type #endif // defined(ASIO_HAS_MOVE) && !defined(ASIO_MOVE_CAST) @@ -176,6 +189,7 @@ # define ASIO_MOVE_CAST(type) static_cast<const type&> # define ASIO_MOVE_CAST2(type1, type2) static_cast<const type1, type2&> # define ASIO_MOVE_OR_LVALUE(type)+# define ASIO_MOVE_OR_LVALUE_ARG(type) type& # define ASIO_MOVE_OR_LVALUE_TYPE(type) type& #endif // !defined(ASIO_MOVE_CAST) @@ -186,8 +200,7 @@ # if __has_feature(__cxx_variadic_templates__) # define ASIO_HAS_VARIADIC_TEMPLATES 1 # endif // __has_feature(__cxx_variadic_templates__)-# endif // defined(__clang__)-# if defined(__GNUC__)+# elif defined(__GNUC__) # if ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 8)) || (__GNUC__ > 4) # if (__cplusplus >= 201103) || defined(__GXX_EXPERIMENTAL_CXX0X__) # define ASIO_HAS_VARIADIC_TEMPLATES 1@@ -211,18 +224,17 @@ // Support deleted functions on compilers known to allow it. #if !defined(ASIO_DELETED)-# if defined(__GNUC__)+# if defined(__clang__)+# if __has_feature(__cxx_deleted_functions__)+# define ASIO_DELETED = delete+# endif // __has_feature(__cxx_deleted_functions__)+# elif defined(__GNUC__) # if ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 7)) || (__GNUC__ > 4) # if (__cplusplus >= 201103) || defined(__GXX_EXPERIMENTAL_CXX0X__) # define ASIO_DELETED = delete # endif // (__cplusplus >= 201103) || defined(__GXX_EXPERIMENTAL_CXX0X__) # endif // ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 7)) || (__GNUC__ > 4) # endif // defined(__GNUC__)-# if defined(__clang__)-# if __has_feature(__cxx_deleted_functions__)-# define ASIO_DELETED = delete-# endif // __has_feature(__cxx_deleted_functions__)-# endif // defined(__clang__) # if defined(ASIO_MSVC) # if (_MSC_VER >= 1900) # define ASIO_DELETED = delete@@ -240,8 +252,7 @@ # if __has_feature(__cxx_constexpr__) # define ASIO_HAS_CONSTEXPR 1 # endif // __has_feature(__cxx_constexpr__)-# endif // defined(__clang__)-# if defined(__GNUC__)+# elif defined(__GNUC__) # if ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 8)) || (__GNUC__ > 4) # if (__cplusplus >= 201103) || defined(__GXX_EXPERIMENTAL_CXX0X__) # define ASIO_HAS_CONSTEXPR 1@@ -347,6 +358,25 @@ # endif // defined(ASIO_HAS_NOEXCEPT) #endif // !defined(ASIO_NOEXCEPT_IF) +// Support noexcept on function types on compilers known to allow it.+#if !defined(ASIO_HAS_NOEXCEPT_FUNCTION_TYPE)+# if !defined(ASIO_DISABLE_NOEXCEPT_FUNCTION_TYPE)+# if defined(__clang__)+# if (__cplusplus >= 202002)+# define ASIO_HAS_NOEXCEPT_FUNCTION_TYPE 1+# endif // (__cplusplus >= 202002)+# elif defined(__GNUC__)+# if (__cplusplus >= 202002)+# define ASIO_HAS_NOEXCEPT_FUNCTION_TYPE 1+# endif // (__cplusplus >= 202002)+# elif defined(ASIO_MSVC)+# if (_MSC_VER >= 1900 && _MSVC_LANG >= 202002)+# define ASIO_HAS_NOEXCEPT_FUNCTION_TYPE 1+# endif // (_MSC_VER >= 1900 && _MSVC_LANG >= 202002)+# endif // defined(ASIO_MSVC)+# endif // !defined(ASIO_DISABLE_NOEXCEPT_FUNCTION_TYPE)+#endif // !defined(ASIO_HAS_NOEXCEPT_FUNCTION_TYPE)+ // Support automatic type deduction on compilers known to support it. #if !defined(ASIO_HAS_DECLTYPE) # if !defined(ASIO_DISABLE_DECLTYPE)@@ -354,8 +384,7 @@ # if __has_feature(__cxx_decltype__) # define ASIO_HAS_DECLTYPE 1 # endif // __has_feature(__cxx_decltype__)-# endif // defined(__clang__)-# if defined(__GNUC__)+# elif defined(__GNUC__) # if ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 8)) || (__GNUC__ > 4) # if (__cplusplus >= 201103) || defined(__GXX_EXPERIMENTAL_CXX0X__) # define ASIO_HAS_DECLTYPE 1@@ -369,6 +398,17 @@ # endif // defined(ASIO_MSVC) # endif // !defined(ASIO_DISABLE_DECLTYPE) #endif // !defined(ASIO_HAS_DECLTYPE)+#if defined(ASIO_HAS_DECLTYPE)+# define ASIO_AUTO_RETURN_TYPE_PREFIX(t) auto+# define ASIO_AUTO_RETURN_TYPE_PREFIX2(t0, t1) auto+# define ASIO_AUTO_RETURN_TYPE_PREFIX3(t0, t1, t2) auto+# define ASIO_AUTO_RETURN_TYPE_SUFFIX(expr) -> decltype expr+#else // defined(ASIO_HAS_DECLTYPE)+# define ASIO_AUTO_RETURN_TYPE_PREFIX(t) t+# define ASIO_AUTO_RETURN_TYPE_PREFIX2(t0, t1) t0, t1+# define ASIO_AUTO_RETURN_TYPE_PREFIX3(t0, t1, t2) t0, t1, t2+# define ASIO_AUTO_RETURN_TYPE_SUFFIX(expr)+#endif // defined(ASIO_HAS_DECLTYPE) // Support alias templates on compilers known to allow it. #if !defined(ASIO_HAS_ALIAS_TEMPLATES)@@ -377,8 +417,7 @@ # if __has_feature(__cxx_alias_templates__) # define ASIO_HAS_ALIAS_TEMPLATES 1 # endif // __has_feature(__cxx_alias_templates__)-# endif // defined(__clang__)-# if defined(__GNUC__)+# elif defined(__GNUC__) # if ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 7)) || (__GNUC__ > 4) # if (__cplusplus >= 201103) || defined(__GXX_EXPERIMENTAL_CXX0X__) # define ASIO_HAS_ALIAS_TEMPLATES 1@@ -406,7 +445,11 @@ # if (__cpp_return_type_deduction >= 201304) # define ASIO_HAS_RETURN_TYPE_DEDUCTION 1 # endif // (__cpp_return_type_deduction >= 201304)-# endif // defined(__cpp_return_type_deduction)+# elif defined(ASIO_MSVC)+# if (_MSC_VER >= 1900 && _MSVC_LANG >= 201402)+# define ASIO_HAS_RETURN_TYPE_DEDUCTION 1+# endif // (_MSC_VER >= 1900 && _MSVC_LANG >= 201402)+# endif // defined(ASIO_MSVC) # endif // !defined(ASIO_DISABLE_RETURN_TYPE_DEDUCTION) #endif // !defined(ASIO_HAS_RETURN_TYPE_DEDUCTION) @@ -415,10 +458,27 @@ # if !defined(ASIO_DISABLE_DEFAULT_FUNCTION_TEMPLATE_ARGUMENTS) # if (__cplusplus >= 201103) # define ASIO_HAS_DEFAULT_FUNCTION_TEMPLATE_ARGUMENTS 1-# endif // (__cplusplus >= 201103)+# elif defined(ASIO_MSVC)+# if (_MSC_VER >= 1900 && _MSVC_LANG >= 201103)+# define ASIO_HAS_DEFAULT_FUNCTION_TEMPLATE_ARGUMENTS 1+# endif // (_MSC_VER >= 1900 && _MSVC_LANG >= 201103)+# endif // defined(ASIO_MSVC) # endif // !defined(ASIO_DISABLE_DEFAULT_FUNCTION_TEMPLATE_ARGUMENTS) #endif // !defined(ASIO_HAS_DEFAULT_FUNCTION_TEMPLATE_ARGUMENTS) +// Support enum classes on compilers known to allow them.+#if !defined(ASIO_HAS_ENUM_CLASS)+# if !defined(ASIO_DISABLE_ENUM_CLASS)+# if (__cplusplus >= 201103)+# define ASIO_HAS_ENUM_CLASS 1+# elif defined(ASIO_MSVC)+# if (_MSC_VER >= 1900 && _MSVC_LANG >= 201103)+# define ASIO_HAS_ENUM_CLASS 1+# endif // (_MSC_VER >= 1900 && _MSVC_LANG >= 201103)+# endif // defined(ASIO_MSVC)+# endif // !defined(ASIO_DISABLE_ENUM_CLASS)+#endif // !defined(ASIO_HAS_ENUM_CLASS)+ // Support concepts on compilers known to allow them. #if !defined(ASIO_HAS_CONCEPTS) # if !defined(ASIO_DISABLE_CONCEPTS)@@ -433,6 +493,17 @@ # endif // !defined(ASIO_DISABLE_CONCEPTS) #endif // !defined(ASIO_HAS_CONCEPTS) +// Support concepts on compilers known to allow them.+#if !defined(ASIO_HAS_STD_CONCEPTS)+# if !defined(ASIO_DISABLE_STD_CONCEPTS)+# if defined(ASIO_HAS_CONCEPTS)+# if (__cpp_lib_concepts >= 202002L)+# define ASIO_HAS_STD_CONCEPTS 1+# endif // (__cpp_concepts >= 202002L)+# endif // defined(ASIO_HAS_CONCEPTS)+# endif // !defined(ASIO_DISABLE_STD_CONCEPTS)+#endif // !defined(ASIO_HAS_STD_CONCEPTS)+ // Support template variables on compilers known to allow it. #if !defined(ASIO_HAS_VARIABLE_TEMPLATES) # if !defined(ASIO_DISABLE_VARIABLE_TEMPLATES)@@ -442,14 +513,13 @@ # define ASIO_HAS_VARIABLE_TEMPLATES 1 # endif // __has_feature(__cxx_variable_templates__) # endif // (__cplusplus >= 201402)-# endif // defined(__clang__)-# if defined(__GNUC__)+# elif defined(__GNUC__) && !defined(__INTEL_COMPILER) # if (__GNUC__ >= 6) # if (__cplusplus >= 201402) # define ASIO_HAS_VARIABLE_TEMPLATES 1 # endif // (__cplusplus >= 201402) # endif // (__GNUC__ >= 6)-# endif // defined(__GNUC__)+# endif // defined(__GNUC__) && !defined(__INTEL_COMPILER) # if defined(ASIO_MSVC) # if (_MSC_VER >= 1901) # define ASIO_HAS_VARIABLE_TEMPLATES 1@@ -467,8 +537,7 @@ # define ASIO_HAS_SFINAE_VARIABLE_TEMPLATES 1 # endif // __has_feature(__cxx_variable_templates__) # endif // (__cplusplus >= 201703)-# endif // defined(__clang__)-# if defined(__GNUC__)+# elif defined(__GNUC__) # if ((__GNUC__ == 8) && (__GNUC_MINOR__ >= 4)) || (__GNUC__ > 8) # if (__cplusplus >= 201402) # define ASIO_HAS_SFINAE_VARIABLE_TEMPLATES 1@@ -490,14 +559,13 @@ # if (__cplusplus >= 201402) # define ASIO_HAS_CONSTANT_EXPRESSION_SFINAE 1 # endif // (__cplusplus >= 201402)-# endif // defined(__clang__)-# if defined(__GNUC__)+# elif defined(__GNUC__) && !defined(__INTEL_COMPILER) # if (__GNUC__ >= 7) # if (__cplusplus >= 201402) # define ASIO_HAS_CONSTANT_EXPRESSION_SFINAE 1 # endif // (__cplusplus >= 201402) # endif // (__GNUC__ >= 7)-# endif // defined(__GNUC__)+# endif // defined(__GNUC__) && !defined(__INTEL_COMPILER) # if defined(ASIO_MSVC) # if (_MSC_VER >= 1901) # define ASIO_HAS_CONSTANT_EXPRESSION_SFINAE 1@@ -509,11 +577,15 @@ // Enable workarounds for lack of working expression SFINAE. #if !defined(ASIO_HAS_WORKING_EXPRESSION_SFINAE) # if !defined(ASIO_DISABLE_WORKING_EXPRESSION_SFINAE)-# if !defined(ASIO_MSVC)+# if !defined(ASIO_MSVC) && !defined(__INTEL_COMPILER) # if (__cplusplus >= 201103) # define ASIO_HAS_WORKING_EXPRESSION_SFINAE 1 # endif // (__cplusplus >= 201103)-# endif // !defined(ASIO_MSVC)+# elif defined(ASIO_MSVC) && (_MSC_VER >= 1929)+# if (_MSVC_LANG >= 202000)+# define ASIO_HAS_WORKING_EXPRESSION_SFINAE 1+# endif // (_MSVC_LANG >= 202000)+# endif // defined(ASIO_MSVC) && (_MSC_VER >= 1929) # endif // !defined(ASIO_DISABLE_WORKING_EXPRESSION_SFINAE) #endif // !defined(ASIO_HAS_WORKING_EXPRESSION_SFINAE) @@ -524,8 +596,7 @@ # if __has_feature(__cxx_reference_qualified_functions__) # define ASIO_HAS_REF_QUALIFIED_FUNCTIONS 1 # endif // __has_feature(__cxx_reference_qualified_functions__)-# endif // defined(__clang__)-# if defined(__GNUC__)+# elif defined(__GNUC__) # if ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 9)) || (__GNUC__ > 4) # if (__cplusplus >= 201103) || defined(__GXX_EXPERIMENTAL_CXX0X__) # define ASIO_HAS_REF_QUALIFIED_FUNCTIONS 1@@ -555,6 +626,134 @@ # endif // !defined(ASIO_RVALUE_REF_QUAL) #endif // defined(ASIO_HAS_REF_QUALIFIED_FUNCTIONS) +// Support for capturing parameter packs in lambdas.+#if !defined(ASIO_HAS_VARIADIC_LAMBDA_CAPTURES)+# if !defined(ASIO_DISABLE_VARIADIC_LAMBDA_CAPTURES)+# if defined(__GNUC__)+# if (__GNUC__ >= 6)+# define ASIO_HAS_VARIADIC_LAMBDA_CAPTURES 1+# endif // (__GNUC__ >= 6)+# elif defined(ASIO_MSVC)+# if (_MSVC_LANG >= 201103)+# define ASIO_HAS_VARIADIC_LAMBDA_CAPTURES 1+# endif // (_MSC_LANG >= 201103)+# else // defined(ASIO_MSVC)+# if (__cplusplus >= 201103)+# define ASIO_HAS_VARIADIC_LAMBDA_CAPTURES 1+# endif // (__cplusplus >= 201103)+# endif // defined(ASIO_MSVC)+# endif // !defined(ASIO_DISABLE_VARIADIC_LAMBDA_CAPTURES)+#endif // !defined(ASIO_HAS_VARIADIC_LAMBDA_CAPTURES)++// Support for the alignof operator.+#if !defined(ASIO_HAS_ALIGNOF)+# if !defined(ASIO_DISABLE_ALIGNOF)+# if (__cplusplus >= 201103)+# define ASIO_HAS_ALIGNOF 1+# endif // (__cplusplus >= 201103)+# endif // !defined(ASIO_DISABLE_ALIGNOF)+#endif // !defined(ASIO_HAS_ALIGNOF)++#if defined(ASIO_HAS_ALIGNOF)+# define ASIO_ALIGNOF(T) alignof(T)+# if defined(__STDCPP_DEFAULT_NEW_ALIGNMENT__)+# define ASIO_DEFAULT_ALIGN __STDCPP_DEFAULT_NEW_ALIGNMENT__+# elif defined(__GNUC__)+# if ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 9)) || (__GNUC__ > 4)+# define ASIO_DEFAULT_ALIGN alignof(std::max_align_t)+# else // ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 9)) || (__GNUC__ > 4)+# define ASIO_DEFAULT_ALIGN alignof(max_align_t)+# endif // ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 9)) || (__GNUC__ > 4)+# else // defined(__GNUC__)+# define ASIO_DEFAULT_ALIGN alignof(std::max_align_t)+# endif // defined(__GNUC__)+#else // defined(ASIO_HAS_ALIGNOF)+# define ASIO_ALIGNOF(T) 1+# define ASIO_DEFAULT_ALIGN 1+#endif // defined(ASIO_HAS_ALIGNOF)++// Support for user-defined literals.+#if !defined(ASIO_HAS_USER_DEFINED_LITERALS)+# if !defined(ASIO_DISABLE_USER_DEFINED_LITERALS)+# if (__cplusplus >= 201103)+# define ASIO_HAS_USER_DEFINED_LITERALS 1+# elif defined(ASIO_MSVC)+# if (_MSC_VER >= 1900 && _MSVC_LANG >= 201103)+# define ASIO_HAS_USER_DEFINED_LITERALS 1+# endif // (_MSC_VER >= 1900 && _MSVC_LANG >= 201103)+# endif // defined(ASIO_MSVC)+# endif // !defined(ASIO_DISABLE_USER_DEFINED_LITERALS)+#endif // !defined(ASIO_HAS_USER_DEFINED_LITERALS)++// Standard library support for aligned allocation.+#if !defined(ASIO_HAS_STD_ALIGNED_ALLOC)+# if !defined(ASIO_DISABLE_STD_ALIGNED_ALLOC)+# if (__cplusplus >= 201703)+# if defined(__clang__)+# if defined(ASIO_HAS_CLANG_LIBCXX)+# if (_LIBCPP_STD_VER > 14) && defined(_LIBCPP_HAS_ALIGNED_ALLOC) \+ && !defined(_LIBCPP_MSVCRT) && !defined(__MINGW32__)+# if defined(__APPLE__)+# if defined(__MAC_OS_X_VERSION_MIN_REQUIRED)+# if (__MAC_OS_X_VERSION_MIN_REQUIRED >= 101500)+# define ASIO_HAS_STD_ALIGNED_ALLOC 1+# endif // (__MAC_OS_X_VERSION_MIN_REQUIRED >= 101500)+# elif defined(__IPHONE_OS_VERSION_MIN_REQUIRED)+# if (__IPHONE_OS_VERSION_MIN_REQUIRED >= 130000)+# define ASIO_HAS_STD_ALIGNED_ALLOC 1+# endif // (__IPHONE_OS_VERSION_MIN_REQUIRED >= 130000)+# elif defined(__TV_OS_VERSION_MIN_REQUIRED)+# if (__TV_OS_VERSION_MIN_REQUIRED >= 130000)+# define ASIO_HAS_STD_ALIGNED_ALLOC 1+# endif // (__TV_OS_VERSION_MIN_REQUIRED >= 130000)+# elif defined(__WATCH_OS_VERSION_MIN_REQUIRED)+# if (__WATCH_OS_VERSION_MIN_REQUIRED >= 60000)+# define ASIO_HAS_STD_ALIGNED_ALLOC 1+# endif // (__WATCH_OS_VERSION_MIN_REQUIRED >= 60000)+# endif // defined(__WATCH_OS_X_VERSION_MIN_REQUIRED)+# else // defined(__APPLE__)+# define ASIO_HAS_STD_ALIGNED_ALLOC 1+# endif // defined(__APPLE__)+# endif // (_LIBCPP_STD_VER > 14) && defined(_LIBCPP_HAS_ALIGNED_ALLOC)+ // && !defined(_LIBCPP_MSVCRT) && !defined(__MINGW32__)+# elif defined(_GLIBCXX_HAVE_ALIGNED_ALLOC)+# define ASIO_HAS_STD_ALIGNED_ALLOC 1+# endif // defined(_GLIBCXX_HAVE_ALIGNED_ALLOC)+# elif defined(__GNUC__)+# if ((__GNUC__ == 7) && (__GNUC_MINOR__ >= 4)) || (__GNUC__ > 7)+# if defined(_GLIBCXX_HAVE_ALIGNED_ALLOC)+# define ASIO_HAS_STD_ALIGNED_ALLOC 1+# endif // defined(_GLIBCXX_HAVE_ALIGNED_ALLOC)+# endif // ((__GNUC__ == 7) && (__GNUC_MINOR__ >= 4)) || (__GNUC__ > 7)+# endif // defined(__GNUC__)+# endif // (__cplusplus >= 201703)+# endif // !defined(ASIO_DISABLE_STD_ALIGNED_ALLOC)+#endif // !defined(ASIO_HAS_STD_ALIGNED_ALLOC)++// Standard library support for std::align.+#if !defined(ASIO_HAS_STD_ALIGN)+# if !defined(ASIO_DISABLE_STD_ALIGN)+# if defined(__clang__)+# if defined(ASIO_HAS_CLANG_LIBCXX)+# define ASIO_HAS_STD_ALIGN 1+# elif (__cplusplus >= 201103)+# define ASIO_HAS_STD_ALIGN 1+# endif // (__cplusplus >= 201103)+# elif defined(__GNUC__)+# if (__GNUC__ >= 6)+# if (__cplusplus >= 201103) || defined(__GXX_EXPERIMENTAL_CXX0X__)+# define ASIO_HAS_STD_ALIGN 1+# endif // (__cplusplus >= 201103) || defined(__GXX_EXPERIMENTAL_CXX0X__)+# endif // (__GNUC__ >= 6)+# endif // defined(__GNUC__)+# if defined(ASIO_MSVC)+# if (_MSC_VER >= 1700)+# define ASIO_HAS_STD_ALIGN 1+# endif // (_MSC_VER >= 1700)+# endif // defined(ASIO_MSVC)+# endif // !defined(ASIO_DISABLE_STD_ALIGN)+#endif // !defined(ASIO_HAS_STD_ALIGN)+ // Standard library support for system errors. #if !defined(ASIO_HAS_STD_SYSTEM_ERROR) # if !defined(ASIO_DISABLE_STD_SYSTEM_ERROR)@@ -566,8 +765,7 @@ # define ASIO_HAS_STD_SYSTEM_ERROR 1 # endif // __has_include(<system_error>) # endif // (__cplusplus >= 201103)-# endif // defined(__clang__)-# if defined(__GNUC__)+# elif defined(__GNUC__) # if ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 6)) || (__GNUC__ > 4) # if (__cplusplus >= 201103) || defined(__GXX_EXPERIMENTAL_CXX0X__) # define ASIO_HAS_STD_SYSTEM_ERROR 1@@ -617,8 +815,7 @@ # define ASIO_HAS_STD_ARRAY 1 # endif // __has_include(<array>) # endif // (__cplusplus >= 201103)-# endif // defined(__clang__)-# if defined(__GNUC__)+# elif defined(__GNUC__) # if ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 3)) || (__GNUC__ > 4) # if (__cplusplus >= 201103) || defined(__GXX_EXPERIMENTAL_CXX0X__) # define ASIO_HAS_STD_ARRAY 1@@ -642,8 +839,7 @@ # elif (__cplusplus >= 201103) # define ASIO_HAS_STD_SHARED_PTR 1 # endif // (__cplusplus >= 201103)-# endif // defined(__clang__)-# if defined(__GNUC__)+# elif defined(__GNUC__) # if ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 3)) || (__GNUC__ > 4) # if (__cplusplus >= 201103) || defined(__GXX_EXPERIMENTAL_CXX0X__) # define ASIO_HAS_STD_SHARED_PTR 1@@ -667,8 +863,7 @@ # elif (__cplusplus >= 201103) # define ASIO_HAS_STD_ALLOCATOR_ARG 1 # endif // (__cplusplus >= 201103)-# endif // defined(__clang__)-# if defined(__GNUC__)+# elif defined(__GNUC__) # if ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 6)) || (__GNUC__ > 4) # if (__cplusplus >= 201103) || defined(__GXX_EXPERIMENTAL_CXX0X__) # define ASIO_HAS_STD_ALLOCATOR_ARG 1@@ -700,8 +895,7 @@ # endif // __has_include(<atomic>) # endif // (__clang_major__ >= 10) # endif // defined(__apple_build_version__) && defined(_LIBCPP_VERSION)-# endif // defined(__clang__)-# if defined(__GNUC__)+# elif defined(__GNUC__) # if ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 7)) || (__GNUC__ > 4) # if (__cplusplus >= 201103) || defined(__GXX_EXPERIMENTAL_CXX0X__) # define ASIO_HAS_STD_ATOMIC 1@@ -729,8 +923,7 @@ # define ASIO_HAS_STD_CHRONO 1 # endif // __has_include(<chrono>) # endif // (__cplusplus >= 201103)-# endif // defined(__clang__)-# if defined(__GNUC__)+# elif defined(__GNUC__) # if ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 6)) || (__GNUC__ > 4) # if (__cplusplus >= 201103) || defined(__GXX_EXPERIMENTAL_CXX0X__) # define ASIO_HAS_STD_CHRONO 1@@ -773,6 +966,35 @@ # endif // !defined(ASIO_DISABLE_BOOST_DATE_TIME) #endif // !defined(ASIO_HAS_BOOST_DATE_TIME) +// Boost support for the Coroutine library.+#if !defined(ASIO_HAS_BOOST_COROUTINE)+# if !defined(ASIO_DISABLE_BOOST_COROUTINE)+# define ASIO_HAS_BOOST_COROUTINE 1+# endif // !defined(ASIO_DISABLE_BOOST_COROUTINE)+#endif // !defined(ASIO_HAS_BOOST_COROUTINE)++// Boost support for the Context library's fibers.+#if !defined(ASIO_HAS_BOOST_CONTEXT_FIBER)+# if !defined(ASIO_DISABLE_BOOST_CONTEXT_FIBER)+# if defined(__clang__)+# if (__cplusplus >= 201103)+# define ASIO_HAS_BOOST_CONTEXT_FIBER 1+# endif // (__cplusplus >= 201103)+# elif defined(__GNUC__)+# if ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 8)) || (__GNUC__ > 4)+# if (__cplusplus >= 201103) || defined(__GXX_EXPERIMENTAL_CXX0X__)+# define ASIO_HAS_BOOST_CONTEXT_FIBER 1+# endif // (__cplusplus >= 201103) || defined(__GXX_EXPERIMENTAL_CXX0X__)+# endif // ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 8)) || (__GNUC__ > 4)+# endif // defined(__GNUC__)+# if defined(ASIO_MSVC)+# if (_MSVC_LANG >= 201103)+# define ASIO_HAS_BOOST_CONTEXT_FIBER 1+# endif // (_MSC_LANG >= 201103)+# endif // defined(ASIO_MSVC)+# endif // !defined(ASIO_DISABLE_BOOST_CONTEXT_FIBER)+#endif // !defined(ASIO_HAS_BOOST_CONTEXT_FIBER)+ // Standard library support for addressof. #if !defined(ASIO_HAS_STD_ADDRESSOF) # if !defined(ASIO_DISABLE_STD_ADDRESSOF)@@ -782,8 +1004,7 @@ # elif (__cplusplus >= 201103) # define ASIO_HAS_STD_ADDRESSOF 1 # endif // (__cplusplus >= 201103)-# endif // defined(__clang__)-# if defined(__GNUC__)+# elif defined(__GNUC__) # if ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 6)) || (__GNUC__ > 4) # if (__cplusplus >= 201103) || defined(__GXX_EXPERIMENTAL_CXX0X__) # define ASIO_HAS_STD_ADDRESSOF 1@@ -807,8 +1028,7 @@ # elif (__cplusplus >= 201103) # define ASIO_HAS_STD_FUNCTION 1 # endif // (__cplusplus >= 201103)-# endif // defined(__clang__)-# if defined(__GNUC__)+# elif defined(__GNUC__) # if ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 5)) || (__GNUC__ > 4) # if (__cplusplus >= 201103) || defined(__GXX_EXPERIMENTAL_CXX0X__) # define ASIO_HAS_STD_FUNCTION 1@@ -823,6 +1043,30 @@ # endif // !defined(ASIO_DISABLE_STD_FUNCTION) #endif // !defined(ASIO_HAS_STD_FUNCTION) +// Standard library support for the reference_wrapper class.+#if !defined(ASIO_HAS_STD_REFERENCE_WRAPPER)+# if !defined(ASIO_DISABLE_STD_REFERENCE_WRAPPER)+# if defined(__clang__)+# if defined(ASIO_HAS_CLANG_LIBCXX)+# define ASIO_HAS_STD_REFERENCE_WRAPPER 1+# elif (__cplusplus >= 201103)+# define ASIO_HAS_STD_REFERENCE_WRAPPER 1+# endif // (__cplusplus >= 201103)+# elif defined(__GNUC__)+# if ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 5)) || (__GNUC__ > 4)+# if (__cplusplus >= 201103) || defined(__GXX_EXPERIMENTAL_CXX0X__)+# define ASIO_HAS_STD_REFERENCE_WRAPPER 1+# endif // (__cplusplus >= 201103) || defined(__GXX_EXPERIMENTAL_CXX0X__)+# endif // ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 5)) || (__GNUC__ > 4)+# endif // defined(__GNUC__)+# if defined(ASIO_MSVC)+# if (_MSC_VER >= 1700)+# define ASIO_HAS_STD_REFERENCE_WRAPPER 1+# endif // (_MSC_VER >= 1700)+# endif // defined(ASIO_MSVC)+# endif // !defined(ASIO_DISABLE_STD_REFERENCE_WRAPPER)+#endif // !defined(ASIO_HAS_STD_REFERENCE_WRAPPER)+ // Standard library support for type traits. #if !defined(ASIO_HAS_STD_TYPE_TRAITS) # if !defined(ASIO_DISABLE_STD_TYPE_TRAITS)@@ -834,8 +1078,7 @@ # define ASIO_HAS_STD_TYPE_TRAITS 1 # endif // __has_include(<type_traits>) # endif // (__cplusplus >= 201103)-# endif // defined(__clang__)-# if defined(__GNUC__)+# elif defined(__GNUC__) # if ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 8)) || (__GNUC__ > 4) # if (__cplusplus >= 201103) || defined(__GXX_EXPERIMENTAL_CXX0X__) # define ASIO_HAS_STD_TYPE_TRAITS 1@@ -905,8 +1148,7 @@ # elif (__cplusplus >= 201103) # define ASIO_HAS_CSTDINT 1 # endif // (__cplusplus >= 201103)-# endif // defined(__clang__)-# if defined(__GNUC__)+# elif defined(__GNUC__) # if ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 5)) || (__GNUC__ > 4) # if (__cplusplus >= 201103) || defined(__GXX_EXPERIMENTAL_CXX0X__) # define ASIO_HAS_CSTDINT 1@@ -932,8 +1174,7 @@ # define ASIO_HAS_STD_THREAD 1 # endif // __has_include(<thread>) # endif // (__cplusplus >= 201103)-# endif // defined(__clang__)-# if defined(__GNUC__)+# elif defined(__GNUC__) # if ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 7)) || (__GNUC__ > 4) # if (__cplusplus >= 201103) || defined(__GXX_EXPERIMENTAL_CXX0X__) # define ASIO_HAS_STD_THREAD 1@@ -959,8 +1200,7 @@ # define ASIO_HAS_STD_MUTEX_AND_CONDVAR 1 # endif // __has_include(<mutex>) # endif // (__cplusplus >= 201103)-# endif // defined(__clang__)-# if defined(__GNUC__)+# elif defined(__GNUC__) # if ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 7)) || (__GNUC__ > 4) # if (__cplusplus >= 201103) || defined(__GXX_EXPERIMENTAL_CXX0X__) # define ASIO_HAS_STD_MUTEX_AND_CONDVAR 1@@ -986,8 +1226,7 @@ # define ASIO_HAS_STD_CALL_ONCE 1 # endif // __has_include(<mutex>) # endif // (__cplusplus >= 201103)-# endif // defined(__clang__)-# if defined(__GNUC__)+# elif defined(__GNUC__) # if ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 7)) || (__GNUC__ > 4) # if (__cplusplus >= 201103) || defined(__GXX_EXPERIMENTAL_CXX0X__) # define ASIO_HAS_STD_CALL_ONCE 1@@ -1013,8 +1252,7 @@ # define ASIO_HAS_STD_FUTURE 1 # endif // __has_include(<future>) # endif // (__cplusplus >= 201103)-# endif // defined(__clang__)-# if defined(__GNUC__)+# elif defined(__GNUC__) # if ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 7)) || (__GNUC__ > 4) # if (__cplusplus >= 201103) || defined(__GXX_EXPERIMENTAL_CXX0X__) # define ASIO_HAS_STD_FUTURE 1@@ -1029,6 +1267,32 @@ # endif // !defined(ASIO_DISABLE_STD_FUTURE) #endif // !defined(ASIO_HAS_STD_FUTURE) +// Standard library support for std::tuple.+#if !defined(ASIO_HAS_STD_TUPLE)+# if !defined(ASIO_DISABLE_STD_TUPLE)+# if defined(__clang__)+# if defined(ASIO_HAS_CLANG_LIBCXX)+# define ASIO_HAS_STD_TUPLE 1+# elif (__cplusplus >= 201103)+# if __has_include(<tuple>)+# define ASIO_HAS_STD_TUPLE 1+# endif // __has_include(<tuple>)+# endif // (__cplusplus >= 201103)+# elif defined(__GNUC__)+# if ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 8)) || (__GNUC__ > 4)+# if (__cplusplus >= 201103) || defined(__GXX_EXPERIMENTAL_CXX0X__)+# define ASIO_HAS_STD_TUPLE 1+# endif // (__cplusplus >= 201103) || defined(__GXX_EXPERIMENTAL_CXX0X__)+# endif // ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 8)) || (__GNUC__ > 4)+# endif // defined(__GNUC__)+# if defined(ASIO_MSVC)+# if (_MSC_VER >= 1700)+# define ASIO_HAS_STD_TUPLE 1+# endif // (_MSC_VER >= 1700)+# endif // defined(ASIO_MSVC)+# endif // !defined(ASIO_DISABLE_STD_TUPLE)+#endif // !defined(ASIO_HAS_STD_TUPLE)+ // Standard library support for std::string_view. #if !defined(ASIO_HAS_STD_STRING_VIEW) # if !defined(ASIO_DISABLE_STD_STRING_VIEW)@@ -1079,8 +1343,7 @@ # endif // __has_include(<experimental/string_view>) # endif // (__cplusplus >= 201402) # endif // // defined(ASIO_HAS_CLANG_LIBCXX)-# endif // defined(__clang__)-# if defined(__GNUC__)+# elif defined(__GNUC__) # if ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 9)) || (__GNUC__ > 4) # if (__cplusplus >= 201402) # define ASIO_HAS_STD_EXPERIMENTAL_STRING_VIEW 1@@ -1104,14 +1367,17 @@ // Standard library support for iostream move construction and assignment. #if !defined(ASIO_HAS_STD_IOSTREAM_MOVE) # if !defined(ASIO_DISABLE_STD_IOSTREAM_MOVE)-# if defined(__GNUC__)+# if defined(__clang__)+# if (__cplusplus >= 201103)+# define ASIO_HAS_STD_IOSTREAM_MOVE 1+# endif // (__cplusplus >= 201103)+# elif defined(__GNUC__) # if (__GNUC__ > 4) # if (__cplusplus >= 201103) || defined(__GXX_EXPERIMENTAL_CXX0X__) # define ASIO_HAS_STD_IOSTREAM_MOVE 1 # endif // (__cplusplus >= 201103) || defined(__GXX_EXPERIMENTAL_CXX0X__) # endif // (__GNUC__ > 4)-# endif // defined(__GNUC__)-# if defined(ASIO_MSVC)+# elif defined(ASIO_MSVC) # if (_MSC_VER >= 1700) # define ASIO_HAS_STD_IOSTREAM_MOVE 1 # endif // (_MSC_VER >= 1700)@@ -1126,6 +1392,10 @@ # if (_MSC_VER >= 1911 && _MSVC_LANG >= 201703) # define ASIO_HAS_STD_INVOKE_RESULT 1 # endif // (_MSC_VER >= 1911 && _MSVC_LANG >= 201703)+# else // defined(ASIO_MSVC)+# if (__cplusplus >= 201703)+# define ASIO_HAS_STD_INVOKE_RESULT 1+# endif // (__cplusplus >= 201703) # endif // defined(ASIO_MSVC) # endif // !defined(ASIO_DISABLE_STD_INVOKE_RESULT) #endif // !defined(ASIO_HAS_STD_INVOKE_RESULT)@@ -1202,6 +1472,30 @@ # endif // !defined(ASIO_DISABLE_STD_ANY) #endif // !defined(ASIO_HAS_STD_ANY) +// Standard library support for std::variant.+#if !defined(ASIO_HAS_STD_VARIANT)+# if !defined(ASIO_DISABLE_STD_VARIANT)+# if defined(__clang__)+# if (__cplusplus >= 201703)+# if __has_include(<variant>)+# define ASIO_HAS_STD_VARIANT 1+# endif // __has_include(<variant>)+# endif // (__cplusplus >= 201703)+# elif defined(__GNUC__)+# if (__GNUC__ >= 7)+# if (__cplusplus >= 201703)+# define ASIO_HAS_STD_VARIANT 1+# endif // (__cplusplus >= 201703)+# endif // (__GNUC__ >= 7)+# endif // defined(__GNUC__)+# if defined(ASIO_MSVC)+# if (_MSC_VER >= 1910) && (_MSVC_LANG >= 201703)+# define ASIO_HAS_STD_VARIANT 1+# endif // (_MSC_VER >= 1910) && (_MSVC_LANG >= 201703)+# endif // defined(ASIO_MSVC)+# endif // !defined(ASIO_DISABLE_STD_VARIANT)+#endif // !defined(ASIO_HAS_STD_VARIANT)+ // Standard library support for std::source_location. #if !defined(ASIO_HAS_STD_SOURCE_LOCATION) # if !defined(ASIO_DISABLE_STD_SOURCE_LOCATION)@@ -1233,6 +1527,50 @@ # endif // !defined(ASIO_DISABLE_SOURCE_LOCATION) #endif // !defined(ASIO_HAS_SOURCE_LOCATION) +// Boost support for source_location and system errors.+#if !defined(ASIO_HAS_BOOST_SOURCE_LOCATION)+# if !defined(ASIO_DISABLE_BOOST_SOURCE_LOCATION)+# if defined(ASIO_HAS_BOOST_CONFIG) && (BOOST_VERSION >= 107900)+# define ASIO_HAS_BOOST_SOURCE_LOCATION 1+# endif // defined(ASIO_HAS_BOOST_CONFIG) && (BOOST_VERSION >= 107900)+# endif // !defined(ASIO_DISABLE_BOOST_SOURCE_LOCATION)+#endif // !defined(ASIO_HAS_BOOST_SOURCE_LOCATION)++// Helper macros for working with Boost source locations.+#if defined(ASIO_HAS_BOOST_SOURCE_LOCATION)+# define ASIO_SOURCE_LOCATION_PARAM \+ , const boost::source_location& loc+# define ASIO_SOURCE_LOCATION_DEFAULTED_PARAM \+ , const boost::source_location& loc = BOOST_CURRENT_LOCATION+# define ASIO_SOURCE_LOCATION_ARG , loc+#else // if defined(ASIO_HAS_BOOST_SOURCE_LOCATION)+# define ASIO_SOURCE_LOCATION_PARAM+# define ASIO_SOURCE_LOCATION_DEFAULTED_PARAM+# define ASIO_SOURCE_LOCATION_ARG+#endif // if defined(ASIO_HAS_BOOST_SOURCE_LOCATION)++// Standard library support for std::index_sequence.+#if !defined(ASIO_HAS_STD_INDEX_SEQUENCE)+# if !defined(ASIO_DISABLE_STD_INDEX_SEQUENCE)+# if defined(__clang__)+# if (__cplusplus >= 201402)+# define ASIO_HAS_STD_INDEX_SEQUENCE 1+# endif // (__cplusplus >= 201402)+# elif defined(__GNUC__)+# if (__GNUC__ >= 7)+# if (__cplusplus >= 201402)+# define ASIO_HAS_STD_INDEX_SEQUENCE 1+# endif // (__cplusplus >= 201402)+# endif // (__GNUC__ >= 7)+# endif // defined(__GNUC__)+# if defined(ASIO_MSVC)+# if (_MSC_VER >= 1910) && (_MSVC_LANG >= 201402)+# define ASIO_HAS_STD_INDEX_SEQUENCE 1+# endif // (_MSC_VER >= 1910) && (_MSVC_LANG >= 201402)+# endif // defined(ASIO_MSVC)+# endif // !defined(ASIO_DISABLE_STD_INDEX_SEQUENCE)+#endif // !defined(ASIO_HAS_STD_INDEX_SEQUENCE)+ // Windows App target. Windows but with a limited API. #if !defined(ASIO_WINDOWS_APP) # if defined(_WIN32_WINNT) && (_WIN32_WINNT >= 0x0603)@@ -1394,6 +1732,13 @@ # endif // !defined(ASIO_HAS_TIMERFD) #endif // defined(__linux__) +// Linux: io_uring is used instead of epoll.+#if !defined(ASIO_HAS_IO_URING_AS_DEFAULT)+# if !defined(ASIO_HAS_EPOLL) && defined(ASIO_HAS_IO_URING)+# define ASIO_HAS_IO_URING_AS_DEFAULT 1+# endif // !defined(ASIO_HAS_EPOLL) && defined(ASIO_HAS_IO_URING)+#endif // !defined(ASIO_HAS_IO_URING_AS_DEFAULT)+ // Mac OS X, FreeBSD, NetBSD, OpenBSD: kqueue. #if (defined(__MACH__) && defined(__APPLE__)) \ || defined(__FreeBSD__) \@@ -1489,16 +1834,40 @@ // UNIX domain sockets. #if !defined(ASIO_HAS_LOCAL_SOCKETS) # if !defined(ASIO_DISABLE_LOCAL_SOCKETS)-# if !defined(ASIO_WINDOWS) \- && !defined(ASIO_WINDOWS_RUNTIME) \- && !defined(__CYGWIN__)+# if !defined(ASIO_WINDOWS_RUNTIME) # define ASIO_HAS_LOCAL_SOCKETS 1-# endif // !defined(ASIO_WINDOWS)- // && !defined(ASIO_WINDOWS_RUNTIME)- // && !defined(__CYGWIN__)+# endif // !defined(ASIO_WINDOWS_RUNTIME) # endif // !defined(ASIO_DISABLE_LOCAL_SOCKETS) #endif // !defined(ASIO_HAS_LOCAL_SOCKETS) +// Files.+#if !defined(ASIO_HAS_FILE)+# if !defined(ASIO_DISABLE_FILE)+# if defined(ASIO_HAS_WINDOWS_RANDOM_ACCESS_HANDLE)+# define ASIO_HAS_FILE 1+# elif defined(ASIO_HAS_IO_URING)+# define ASIO_HAS_FILE 1+# endif // defined(ASIO_HAS_IO_URING)+# endif // !defined(ASIO_DISABLE_FILE)+#endif // !defined(ASIO_HAS_FILE)++// Pipes.+#if !defined(ASIO_HAS_PIPE)+# if defined(ASIO_HAS_IOCP) \+ || !defined(ASIO_WINDOWS) \+ && !defined(ASIO_WINDOWS_RUNTIME) \+ && !defined(__CYGWIN__)+# if !defined(__SYMBIAN32__)+# if !defined(ASIO_DISABLE_PIPE)+# define ASIO_HAS_PIPE 1+# endif // !defined(ASIO_DISABLE_PIPE)+# endif // !defined(__SYMBIAN32__)+# endif // defined(ASIO_HAS_IOCP)+ // || !defined(ASIO_WINDOWS)+ // && !defined(ASIO_WINDOWS_RUNTIME)+ // && !defined(__CYGWIN__)+#endif // !defined(ASIO_HAS_PIPE)+ // Can use sigaction() instead of signal(). #if !defined(ASIO_HAS_SIGACTION) # if !defined(ASIO_DISABLE_SIGACTION)@@ -1616,6 +1985,15 @@ # endif // !defined(ASIO_DISABLE_BOOST_STATIC_CONSTANT) #endif // !defined(ASIO_STATIC_CONSTANT) +// Boost align library.+#if !defined(ASIO_HAS_BOOST_ALIGN)+# if !defined(ASIO_DISABLE_BOOST_ALIGN)+# if defined(ASIO_HAS_BOOST_CONFIG) && (BOOST_VERSION >= 105600)+# define ASIO_HAS_BOOST_ALIGN 1+# endif // defined(ASIO_HAS_BOOST_CONFIG) && (BOOST_VERSION >= 105600)+# endif // !defined(ASIO_DISABLE_BOOST_ALIGN)+#endif // !defined(ASIO_HAS_BOOST_ALIGN)+ // Boost array library. #if !defined(ASIO_HAS_BOOST_ARRAY) # if !defined(ASIO_DISABLE_BOOST_ARRAY)@@ -1766,22 +2144,51 @@ # define ASIO_UNUSED_VARIABLE #endif // !defined(ASIO_UNUSED_VARIABLE) +// Helper macro to tell the optimiser what may be assumed to be true.+#if defined(ASIO_MSVC)+# define ASIO_ASSUME(expr) __assume(expr)+#elif defined(__clang__)+# if __has_builtin(__builtin_assume)+# define ASIO_ASSUME(expr) __builtin_assume(expr)+# endif // __has_builtin(__builtin_assume)+#elif defined(__GNUC__)+# if ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 5)) || (__GNUC__ > 4)+# define ASIO_ASSUME(expr) if (expr) {} else { __builtin_unreachable(); }+# endif // ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 5)) || (__GNUC__ > 4)+#endif // defined(__GNUC__)+#if !defined(ASIO_ASSUME)+# define ASIO_ASSUME(expr) (void)0+#endif // !defined(ASIO_ASSUME)+ // Support the co_await keyword on compilers known to allow it. #if !defined(ASIO_HAS_CO_AWAIT) # if !defined(ASIO_DISABLE_CO_AWAIT) # if defined(ASIO_MSVC)-# if (_MSC_FULL_VER >= 190023506)+# if (_MSC_VER >= 1928) && (_MSVC_LANG >= 201705) && !defined(__clang__)+# define ASIO_HAS_CO_AWAIT 1+# elif (_MSC_FULL_VER >= 190023506) # if defined(_RESUMABLE_FUNCTIONS_SUPPORTED) # define ASIO_HAS_CO_AWAIT 1 # endif // defined(_RESUMABLE_FUNCTIONS_SUPPORTED) # endif // (_MSC_FULL_VER >= 190023506)-# endif // defined(ASIO_MSVC)-# if defined(__clang__)-# if (__cplusplus >= 201703) && (__cpp_coroutines >= 201703)-# if __has_include(<experimental/coroutine>)-# define ASIO_HAS_CO_AWAIT 1-# endif // __has_include(<experimental/coroutine>)-# endif // (__cplusplus >= 201703) && (__cpp_coroutines >= 201703)+# elif defined(__clang__)+# if (__clang_major__ >= 14)+# if (__cplusplus >= 202002) && (__cpp_impl_coroutine >= 201902)+# if __has_include(<coroutine>)+# define ASIO_HAS_CO_AWAIT 1+# endif // __has_include(<coroutine>)+# elif (__cplusplus >= 201703) && (__cpp_coroutines >= 201703)+# if __has_include(<experimental/coroutine>)+# define ASIO_HAS_CO_AWAIT 1+# endif // __has_include(<experimental/coroutine>)+# endif // (__cplusplus >= 201703) && (__cpp_coroutines >= 201703)+# else // (__clang_major__ >= 14)+# if (__cplusplus >= 201703) && (__cpp_coroutines >= 201703)+# if __has_include(<experimental/coroutine>)+# define ASIO_HAS_CO_AWAIT 1+# endif // __has_include(<experimental/coroutine>)+# endif // (__cplusplus >= 201703) && (__cpp_coroutines >= 201703)+# endif // (__clang_major__ >= 14) # elif defined(__GNUC__) # if (__cplusplus >= 201709) && (__cpp_impl_coroutine >= 201902) # if __has_include(<coroutine>)@@ -1795,7 +2202,19 @@ // Standard library support for coroutines. #if !defined(ASIO_HAS_STD_COROUTINE) # if !defined(ASIO_DISABLE_STD_COROUTINE)-# if defined(__GNUC__)+# if defined(ASIO_MSVC)+# if (_MSC_VER >= 1928) && (_MSVC_LANG >= 201705)+# define ASIO_HAS_STD_COROUTINE 1+# endif // (_MSC_VER >= 1928) && (_MSVC_LANG >= 201705)+# elif defined(__clang__)+# if (__clang_major__ >= 14)+# if (__cplusplus >= 202002) && (__cpp_impl_coroutine >= 201902)+# if __has_include(<coroutine>)+# define ASIO_HAS_STD_COROUTINE 1+# endif // __has_include(<coroutine>)+# endif // (__cplusplus >= 202002) && (__cpp_impl_coroutine >= 201902)+# endif // (__clang_major__ >= 14)+# elif defined(__GNUC__) # if (__cplusplus >= 201709) && (__cpp_impl_coroutine >= 201902) # if __has_include(<coroutine>) # define ASIO_HAS_STD_COROUTINE 1@@ -1818,5 +2237,73 @@ #if !defined(ASIO_NODISCARD) # define ASIO_NODISCARD #endif // !defined(ASIO_NODISCARD)++// Kernel support for MSG_NOSIGNAL.+#if !defined(ASIO_HAS_MSG_NOSIGNAL)+# if defined(__linux__)+# define ASIO_HAS_MSG_NOSIGNAL 1+# elif defined(_POSIX_VERSION)+# if (_POSIX_VERSION >= 200809L)+# define ASIO_HAS_MSG_NOSIGNAL 1+# endif // _POSIX_VERSION >= 200809L+# endif // defined(_POSIX_VERSION)+#endif // !defined(ASIO_HAS_MSG_NOSIGNAL)++// Standard library support for std::hash.+#if !defined(ASIO_HAS_STD_HASH)+# if !defined(ASIO_DISABLE_STD_HASH)+# if defined(__clang__)+# if defined(ASIO_HAS_CLANG_LIBCXX)+# define ASIO_HAS_STD_HASH 1+# elif (__cplusplus >= 201103)+# define ASIO_HAS_STD_HASH 1+# endif // (__cplusplus >= 201103)+# elif defined(__GNUC__)+# if ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 7)) || (__GNUC__ > 4)+# if (__cplusplus >= 201103) || defined(__GXX_EXPERIMENTAL_CXX0X__)+# define ASIO_HAS_STD_HASH 1+# endif // (__cplusplus >= 201103) || defined(__GXX_EXPERIMENTAL_CXX0X__)+# endif // ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 7)) || (__GNUC__ > 4)+# endif // defined(__GNUC__)+# if defined(ASIO_MSVC)+# if (_MSC_VER >= 1700)+# define ASIO_HAS_STD_HASH 1+# endif // (_MSC_VER >= 1700)+# endif // defined(ASIO_MSVC)+# endif // !defined(ASIO_DISABLE_STD_HASH)+#endif // !defined(ASIO_HAS_STD_HASH)++// Standard library support for std::to_address.+#if !defined(ASIO_HAS_STD_TO_ADDRESS)+# if !defined(ASIO_DISABLE_STD_TO_ADDRESS)+# if defined(__clang__)+# if (__cplusplus >= 202002)+# define ASIO_HAS_STD_TO_ADDRESS 1+# endif // (__cplusplus >= 202002)+# elif defined(__GNUC__)+# if (__GNUC__ >= 8)+# if (__cplusplus >= 202002)+# define ASIO_HAS_STD_TO_ADDRESS 1+# endif // (__cplusplus >= 202002)+# endif // (__GNUC__ >= 8)+# endif // defined(__GNUC__)+# if defined(ASIO_MSVC)+# if (_MSC_VER >= 1922) && (_MSVC_LANG >= 202002)+# define ASIO_HAS_STD_TO_ADDRESS 1+# endif // (_MSC_VER >= 1922) && (_MSVC_LANG >= 202002)+# endif // defined(ASIO_MSVC)+# endif // !defined(ASIO_DISABLE_STD_TO_ADDRESS)+#endif // !defined(ASIO_HAS_STD_TO_ADDRESS)++// Standard library support for snprintf.+#if !defined(ASIO_HAS_SNPRINTF)+# if !defined(ASIO_DISABLE_SNPRINTF)+# if defined(__apple_build_version__)+# if (__clang_major__ >= 14)+# define ASIO_HAS_SNPRINTF 1+# endif // (__clang_major__ >= 14)+# endif // defined(__apple_build_version__)+# endif // !defined(ASIO_DISABLE_SNPRINTF)+#endif // !defined(ASIO_HAS_SNPRINTF) #endif // ASIO_DETAIL_CONFIG_HPP
link/modules/asio-standalone/asio/include/asio/detail/consuming_buffers.hpp view
@@ -2,7 +2,7 @@ // detail/consuming_buffers.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -20,6 +20,7 @@ #include "asio/buffer.hpp" #include "asio/detail/buffer_sequence_adapter.hpp" #include "asio/detail/limits.hpp"+#include "asio/registered_buffer.hpp" #include "asio/detail/push_options.hpp" @@ -268,6 +269,42 @@ }; #endif // !defined(ASIO_NO_DEPRECATED)++template <>+class consuming_buffers<mutable_buffer,+ mutable_registered_buffer, const mutable_buffer*>+ : public consuming_single_buffer<mutable_registered_buffer>+{+public:+ explicit consuming_buffers(const mutable_registered_buffer& buffer)+ : consuming_single_buffer<mutable_registered_buffer>(buffer)+ {+ }+};++template <>+class consuming_buffers<const_buffer,+ mutable_registered_buffer, const mutable_buffer*>+ : public consuming_single_buffer<mutable_registered_buffer>+{+public:+ explicit consuming_buffers(const mutable_registered_buffer& buffer)+ : consuming_single_buffer<mutable_registered_buffer>(buffer)+ {+ }+};++template <>+class consuming_buffers<const_buffer,+ const_registered_buffer, const const_buffer*>+ : public consuming_single_buffer<const_registered_buffer>+{+public:+ explicit consuming_buffers(const const_registered_buffer& buffer)+ : consuming_single_buffer<const_registered_buffer>(buffer)+ {+ }+}; template <typename Buffer, typename Elem> class consuming_buffers<Buffer, boost::array<Elem, 2>,
link/modules/asio-standalone/asio/include/asio/detail/cstddef.hpp view
@@ -2,7 +2,7 @@ // detail/cstddef.hpp // ~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/detail/cstdint.hpp view
@@ -2,7 +2,7 @@ // detail/cstdint.hpp // ~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -38,6 +38,7 @@ using std::int_least64_t; using std::uint64_t; using std::uint_least64_t;+using std::uintptr_t; using std::uintmax_t; #else // defined(ASIO_HAS_CSTDINT) using boost::int16_t;@@ -52,6 +53,7 @@ using boost::int_least64_t; using boost::uint64_t; using boost::uint_least64_t;+using boost::uintptr_t; using boost::uintmax_t; #endif // defined(ASIO_HAS_CSTDINT)
link/modules/asio-standalone/asio/include/asio/detail/date_time_fwd.hpp view
@@ -2,7 +2,7 @@ // detail/date_time_fwd.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/detail/deadline_timer_service.hpp view
@@ -2,7 +2,7 @@ // detail/deadline_timer_service.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -17,6 +17,8 @@ #include "asio/detail/config.hpp" #include <cstddef>+#include "asio/associated_cancellation_slot.hpp"+#include "asio/cancellation_type.hpp" #include "asio/error.hpp" #include "asio/execution_context.hpp" #include "asio/detail/bind_handler.hpp"@@ -245,12 +247,22 @@ void async_wait(implementation_type& impl, Handler& handler, const IoExecutor& io_ex) {+ typename associated_cancellation_slot<Handler>::type slot+ = asio::get_associated_cancellation_slot(handler);+ // Allocate and construct an operation to wrap the handler. typedef wait_handler<Handler, IoExecutor> op; typename op::ptr p = { asio::detail::addressof(handler), op::ptr::allocate(handler), 0 }; p.p = new (p.v) op(handler, io_ex); + // Optionally register for per-operation cancellation.+ if (slot.is_connected())+ {+ p.p->cancellation_key_ =+ &slot.template emplace<op_cancellation>(this, &impl.timer_data);+ }+ impl.might_have_pending_waits = true; ASIO_HANDLER_CREATION((scheduler_.context(),@@ -279,6 +291,34 @@ socket_ops::select(0, 0, 0, 0, &tv, ec); #endif // defined(ASIO_WINDOWS_RUNTIME) }++ // Helper class used to implement per-operation cancellation.+ class op_cancellation+ {+ public:+ op_cancellation(deadline_timer_service* s,+ typename timer_queue<Time_Traits>::per_timer_data* p)+ : service_(s),+ timer_data_(p)+ {+ }++ void operator()(cancellation_type_t type)+ {+ if (!!(type &+ (cancellation_type::terminal+ | cancellation_type::partial+ | cancellation_type::total)))+ {+ service_->scheduler_.cancel_timer_by_key(+ service_->timer_queue_, timer_data_, this);+ }+ }++ private:+ deadline_timer_service* service_;+ typename timer_queue<Time_Traits>::per_timer_data* timer_data_;+ }; // The queue of timers. timer_queue<Time_Traits> timer_queue_;
link/modules/asio-standalone/asio/include/asio/detail/dependent_type.hpp view
@@ -2,7 +2,7 @@ // detail/dependent_type.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/detail/descriptor_ops.hpp view
@@ -2,7 +2,7 @@ // detail/descriptor_ops.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -24,6 +24,7 @@ #include <cstddef> #include "asio/error.hpp" #include "asio/error_code.hpp"+#include "asio/detail/cstdint.hpp" #include "asio/detail/socket_types.hpp" #include "asio/detail/push_options.hpp"@@ -55,7 +56,7 @@ { if (!is_error_condition) {- ec.assign(0, ec.category());+ asio::error::clear(ec); } else {@@ -67,6 +68,9 @@ ASIO_DECL int open(const char* path, int flags, asio::error_code& ec); +ASIO_DECL int open(const char* path, int flags, unsigned mode,+ asio::error_code& ec);+ ASIO_DECL int close(int d, state_type& state, asio::error_code& ec); @@ -104,6 +108,42 @@ ASIO_DECL bool non_blocking_write1(int d, const void* data, std::size_t size, asio::error_code& ec, std::size_t& bytes_transferred);++#if defined(ASIO_HAS_FILE)++ASIO_DECL std::size_t sync_read_at(int d, state_type state,+ uint64_t offset, buf* bufs, std::size_t count, bool all_empty,+ asio::error_code& ec);++ASIO_DECL std::size_t sync_read_at1(int d, state_type state,+ uint64_t offset, void* data, std::size_t size,+ asio::error_code& ec);++ASIO_DECL bool non_blocking_read_at(int d, uint64_t offset,+ buf* bufs, std::size_t count, asio::error_code& ec,+ std::size_t& bytes_transferred);++ASIO_DECL bool non_blocking_read_at1(int d, uint64_t offset,+ void* data, std::size_t size, asio::error_code& ec,+ std::size_t& bytes_transferred);++ASIO_DECL std::size_t sync_write_at(int d, state_type state,+ uint64_t offset, const buf* bufs, std::size_t count, bool all_empty,+ asio::error_code& ec);++ASIO_DECL std::size_t sync_write_at1(int d, state_type state,+ uint64_t offset, const void* data, std::size_t size,+ asio::error_code& ec);++ASIO_DECL bool non_blocking_write_at(int d,+ uint64_t offset, const buf* bufs, std::size_t count,+ asio::error_code& ec, std::size_t& bytes_transferred);++ASIO_DECL bool non_blocking_write_at1(int d,+ uint64_t offset, const void* data, std::size_t size,+ asio::error_code& ec, std::size_t& bytes_transferred);++#endif // defined(ASIO_HAS_FILE) ASIO_DECL int ioctl(int d, state_type& state, long cmd, ioctl_arg_type* arg, asio::error_code& ec);
link/modules/asio-standalone/asio/include/asio/detail/descriptor_read_op.hpp view
@@ -2,7 +2,7 @@ // detail/descriptor_read_op.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -26,6 +26,7 @@ #include "asio/detail/handler_work.hpp" #include "asio/detail/memory.hpp" #include "asio/detail/reactor_op.hpp"+#include "asio/dispatch.hpp" #include "asio/detail/push_options.hpp" @@ -48,6 +49,7 @@ static status do_perform(reactor_op* base) {+ ASIO_ASSUME(base != 0); descriptor_read_op_base* o(static_cast<descriptor_read_op_base*>(base)); typedef buffer_sequence_adapter<asio::mutable_buffer,@@ -85,6 +87,9 @@ : public descriptor_read_op_base<MutableBufferSequence> { public:+ typedef Handler handler_type;+ typedef IoExecutor io_executor_type;+ ASIO_DEFINE_HANDLER_PTR(descriptor_read_op); descriptor_read_op(const asio::error_code& success_ec,@@ -102,6 +107,7 @@ std::size_t /*bytes_transferred*/) { // Take ownership of the handler object.+ ASIO_ASSUME(base != 0); descriptor_read_op* o(static_cast<descriptor_read_op*>(base)); ptr p = { asio::detail::addressof(o->handler_), o, o }; @@ -112,6 +118,8 @@ ASIO_MOVE_CAST2(handler_work<Handler, IoExecutor>)( o->work_)); + ASIO_ERROR_LOCATION(o->ec_);+ // Make a copy of the handler so that the memory can be deallocated before // the upcall is made. Even if we're not about to make an upcall, a // sub-object of the handler may be the true owner of the memory associated@@ -131,6 +139,38 @@ w.complete(handler, handler.handler_); ASIO_HANDLER_INVOCATION_END; }+ }++ static void do_immediate(operation* base, bool, const void* io_ex)+ {+ // Take ownership of the handler object.+ ASIO_ASSUME(base != 0);+ descriptor_read_op* o(static_cast<descriptor_read_op*>(base));+ ptr p = { asio::detail::addressof(o->handler_), o, o };++ ASIO_HANDLER_COMPLETION((*o));++ // Take ownership of the operation's outstanding work.+ immediate_handler_work<Handler, IoExecutor> w(+ ASIO_MOVE_CAST2(handler_work<Handler, IoExecutor>)(+ o->work_));++ ASIO_ERROR_LOCATION(o->ec_);++ // Make a copy of the handler so that the memory can be deallocated before+ // the upcall is made. Even if we're not about to make an upcall, a+ // sub-object of the handler may be the true owner of the memory associated+ // with the handler. Consequently, a local copy of the handler is required+ // to ensure that any owning sub-object remains valid until after we have+ // deallocated the memory here.+ detail::binder2<Handler, asio::error_code, std::size_t>+ handler(o->handler_, o->ec_, o->bytes_transferred_);+ p.h = asio::detail::addressof(handler.handler_);+ p.reset();++ ASIO_HANDLER_INVOCATION_BEGIN((handler.arg1_, handler.arg2_));+ w.complete(handler, handler.handler_, io_ex);+ ASIO_HANDLER_INVOCATION_END; } private:
link/modules/asio-standalone/asio/include/asio/detail/descriptor_write_op.hpp view
@@ -2,7 +2,7 @@ // detail/descriptor_write_op.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -48,6 +48,7 @@ static status do_perform(reactor_op* base) {+ ASIO_ASSUME(base != 0); descriptor_write_op_base* o(static_cast<descriptor_write_op_base*>(base)); typedef buffer_sequence_adapter<asio::const_buffer,@@ -85,6 +86,9 @@ : public descriptor_write_op_base<ConstBufferSequence> { public:+ typedef Handler handler_type;+ typedef IoExecutor io_executor_type;+ ASIO_DEFINE_HANDLER_PTR(descriptor_write_op); descriptor_write_op(const asio::error_code& success_ec,@@ -102,6 +106,7 @@ std::size_t /*bytes_transferred*/) { // Take ownership of the handler object.+ ASIO_ASSUME(base != 0); descriptor_write_op* o(static_cast<descriptor_write_op*>(base)); ptr p = { asio::detail::addressof(o->handler_), o, o }; @@ -112,6 +117,8 @@ ASIO_MOVE_CAST2(handler_work<Handler, IoExecutor>)( o->work_)); + ASIO_ERROR_LOCATION(o->ec_);+ // Make a copy of the handler so that the memory can be deallocated before // the upcall is made. Even if we're not about to make an upcall, a // sub-object of the handler may be the true owner of the memory associated@@ -131,6 +138,38 @@ w.complete(handler, handler.handler_); ASIO_HANDLER_INVOCATION_END; }+ }++ static void do_immediate(operation* base, bool, const void* io_ex)+ {+ // Take ownership of the handler object.+ ASIO_ASSUME(base != 0);+ descriptor_write_op* o(static_cast<descriptor_write_op*>(base));+ ptr p = { asio::detail::addressof(o->handler_), o, o };++ ASIO_HANDLER_COMPLETION((*o));++ // Take ownership of the operation's outstanding work.+ immediate_handler_work<Handler, IoExecutor> w(+ ASIO_MOVE_CAST2(handler_work<Handler, IoExecutor>)(+ o->work_));++ ASIO_ERROR_LOCATION(o->ec_);++ // Make a copy of the handler so that the memory can be deallocated before+ // the upcall is made. Even if we're not about to make an upcall, a+ // sub-object of the handler may be the true owner of the memory associated+ // with the handler. Consequently, a local copy of the handler is required+ // to ensure that any owning sub-object remains valid until after we have+ // deallocated the memory here.+ detail::binder2<Handler, asio::error_code, std::size_t>+ handler(o->handler_, o->ec_, o->bytes_transferred_);+ p.h = asio::detail::addressof(handler.handler_);+ p.reset();++ ASIO_HANDLER_INVOCATION_BEGIN((handler.arg1_, handler.arg2_));+ w.complete(handler, handler.handler_, io_ex);+ ASIO_HANDLER_INVOCATION_END; } private:
link/modules/asio-standalone/asio/include/asio/detail/dev_poll_reactor.hpp view
@@ -2,7 +2,7 @@ // detail/dev_poll_reactor.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -28,6 +28,7 @@ #include "asio/detail/op_queue.hpp" #include "asio/detail/reactor_op.hpp" #include "asio/detail/reactor_op_queue.hpp"+#include "asio/detail/scheduler_task.hpp" #include "asio/detail/select_interrupter.hpp" #include "asio/detail/socket_types.hpp" #include "asio/detail/timer_queue_base.hpp"@@ -41,7 +42,8 @@ namespace detail { class dev_poll_reactor- : public execution_context_service_base<dev_poll_reactor>+ : public execution_context_service_base<dev_poll_reactor>,+ public scheduler_task { public: enum op_types { read_op = 0, write_op = 1,@@ -84,22 +86,44 @@ per_descriptor_data& source_descriptor_data); // Post a reactor operation for immediate completion.- void post_immediate_completion(reactor_op* op, bool is_continuation)- {- scheduler_.post_immediate_completion(op, is_continuation);- }+ void post_immediate_completion(operation* op, bool is_continuation) const; + // Post a reactor operation for immediate completion.+ ASIO_DECL static void call_post_immediate_completion(+ operation* op, bool is_continuation, const void* self);+ // Start a new operation. The reactor operation will be performed when the // given descriptor is flagged as ready, or an error has occurred. ASIO_DECL void start_op(int op_type, socket_type descriptor, per_descriptor_data&, reactor_op* op,- bool is_continuation, bool allow_speculative);+ bool is_continuation, bool allow_speculative,+ void (*on_immediate)(operation*, bool, const void*),+ const void* immediate_arg); + // Start a new operation. The reactor operation will be performed when the+ // given descriptor is flagged as ready, or an error has occurred.+ void start_op(int op_type, socket_type descriptor,+ per_descriptor_data& descriptor_data, reactor_op* op,+ bool is_continuation, bool allow_speculative)+ {+ start_op(op_type, descriptor, descriptor_data,+ op, is_continuation, allow_speculative,+ &epoll_reactor::call_post_immediate_completion, this);+ }++ // Cancel all operations associated with the given descriptor. The // handlers associated with the descriptor will be invoked with the // operation_aborted error. ASIO_DECL void cancel_ops(socket_type descriptor, per_descriptor_data&); + // Cancel all operations associated with the given descriptor and key. The+ // handlers associated with the descriptor will be invoked with the+ // operation_aborted error.+ ASIO_DECL void cancel_ops_by_key(socket_type descriptor,+ per_descriptor_data& descriptor_data,+ int op_type, void* cancellation_key);+ // Cancel any operations that are running against the descriptor and remove // its registration from the reactor. The reactor resources associated with // the descriptor must be released by calling cleanup_descriptor_data.@@ -137,6 +161,12 @@ std::size_t cancel_timer(timer_queue<Time_Traits>& queue, typename timer_queue<Time_Traits>::per_timer_data& timer, std::size_t max_cancelled = (std::numeric_limits<std::size_t>::max)());++ // Cancel the timer operations associated with the given key.+ template <typename Time_Traits>+ void cancel_timer_by_key(timer_queue<Time_Traits>& queue,+ typename timer_queue<Time_Traits>::per_timer_data* timer,+ void* cancellation_key); // Move the timer operations associated with the given timer. template <typename Time_Traits>
link/modules/asio-standalone/asio/include/asio/detail/epoll_reactor.hpp view
@@ -2,7 +2,7 @@ // detail/epoll_reactor.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -25,6 +25,7 @@ #include "asio/detail/object_pool.hpp" #include "asio/detail/op_queue.hpp" #include "asio/detail/reactor_op.hpp"+#include "asio/detail/scheduler_task.hpp" #include "asio/detail/select_interrupter.hpp" #include "asio/detail/socket_types.hpp" #include "asio/detail/timer_queue_base.hpp"@@ -42,7 +43,8 @@ namespace detail { class epoll_reactor- : public execution_context_service_base<epoll_reactor>+ : public execution_context_service_base<epoll_reactor>,+ public scheduler_task { private: // The mutex type used by this reactor.@@ -114,23 +116,44 @@ per_descriptor_data& source_descriptor_data); // Post a reactor operation for immediate completion.- void post_immediate_completion(reactor_op* op, bool is_continuation)- {- scheduler_.post_immediate_completion(op, is_continuation);- }+ void post_immediate_completion(operation* op, bool is_continuation) const; + // Post a reactor operation for immediate completion.+ ASIO_DECL static void call_post_immediate_completion(+ operation* op, bool is_continuation, const void* self);+ // Start a new operation. The reactor operation will be performed when the // given descriptor is flagged as ready, or an error has occurred. ASIO_DECL void start_op(int op_type, socket_type descriptor, per_descriptor_data& descriptor_data, reactor_op* op,- bool is_continuation, bool allow_speculative);+ bool is_continuation, bool allow_speculative,+ void (*on_immediate)(operation*, bool, const void*),+ const void* immediate_arg); + // Start a new operation. The reactor operation will be performed when the+ // given descriptor is flagged as ready, or an error has occurred.+ void start_op(int op_type, socket_type descriptor,+ per_descriptor_data& descriptor_data, reactor_op* op,+ bool is_continuation, bool allow_speculative)+ {+ start_op(op_type, descriptor, descriptor_data,+ op, is_continuation, allow_speculative,+ &epoll_reactor::call_post_immediate_completion, this);+ }+ // Cancel all operations associated with the given descriptor. The // handlers associated with the descriptor will be invoked with the // operation_aborted error. ASIO_DECL void cancel_ops(socket_type descriptor, per_descriptor_data& descriptor_data); + // Cancel all operations associated with the given descriptor and key. The+ // handlers associated with the descriptor will be invoked with the+ // operation_aborted error.+ ASIO_DECL void cancel_ops_by_key(socket_type descriptor,+ per_descriptor_data& descriptor_data,+ int op_type, void* cancellation_key);+ // Cancel any operations that are running against the descriptor and remove // its registration from the reactor. The reactor resources associated with // the descriptor must be released by calling cleanup_descriptor_data.@@ -169,6 +192,12 @@ std::size_t cancel_timer(timer_queue<Time_Traits>& queue, typename timer_queue<Time_Traits>::per_timer_data& timer, std::size_t max_cancelled = (std::numeric_limits<std::size_t>::max)());++ // Cancel the timer operations associated with the given key.+ template <typename Time_Traits>+ void cancel_timer_by_key(timer_queue<Time_Traits>& queue,+ typename timer_queue<Time_Traits>::per_timer_data* timer,+ void* cancellation_key); // Move the timer operations associated with the given timer. template <typename Time_Traits>
link/modules/asio-standalone/asio/include/asio/detail/event.hpp view
@@ -2,7 +2,7 @@ // detail/event.hpp // ~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/detail/eventfd_select_interrupter.hpp view
@@ -2,7 +2,7 @@ // detail/eventfd_select_interrupter.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // Copyright (c) 2008 Roelof Naude (roelof.naude at gmail dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying
+ link/modules/asio-standalone/asio/include/asio/detail/exception.hpp view
@@ -0,0 +1,40 @@+//+// detail/exception.hpp+// ~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com)+//+// Distributed under the Boost Software License, Version 1.0. (See accompanying+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)+//++#ifndef ASIO_DETAIL_EXCEPTION_HPP+#define ASIO_DETAIL_EXCEPTION_HPP++#if defined(_MSC_VER) && (_MSC_VER >= 1200)+# pragma once+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)++#include "asio/detail/config.hpp"++#if defined(ASIO_HAS_STD_EXCEPTION_PTR)+# include <exception>+#else // defined(ASIO_HAS_STD_EXCEPTION_PTR)+# include <boost/exception_ptr.hpp>+#endif // defined(ASIO_HAS_STD_EXCEPTION_PTR)++namespace asio {++#if defined(ASIO_HAS_STD_EXCEPTION_PTR)+using std::exception_ptr;+using std::current_exception;+using std::rethrow_exception;+#else // defined(ASIO_HAS_STD_EXCEPTION_PTR)+using boost::exception_ptr;+using boost::current_exception;+using boost::rethrow_exception;+#endif // defined(ASIO_HAS_STD_EXCEPTION_PTR)++} // namespace asio++#endif // ASIO_DETAIL_EXCEPTION_HPP
link/modules/asio-standalone/asio/include/asio/detail/executor_function.hpp view
@@ -2,7 +2,7 @@ // detail/executor_function.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -17,6 +17,7 @@ #include "asio/detail/config.hpp" #include "asio/detail/handler_alloc_helpers.hpp"+#include "asio/detail/handler_invoke_helpers.hpp" #include "asio/detail/memory.hpp" #include "asio/detail/push_options.hpp"@@ -111,7 +112,7 @@ // Make the upcall if required. if (call) {- function();+ asio_handler_invoke_helpers::invoke(function, function); } }
link/modules/asio-standalone/asio/include/asio/detail/executor_op.hpp view
@@ -2,7 +2,7 @@ // detail/executor_op.hpp // ~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -46,6 +46,7 @@ std::size_t /*bytes_transferred*/) { // Take ownership of the handler object.+ ASIO_ASSUME(base != 0); executor_op* o(static_cast<executor_op*>(base)); Alloc allocator(o->allocator_); ptr p = { detail::addressof(allocator), o, o };
link/modules/asio-standalone/asio/include/asio/detail/fd_set_adapter.hpp view
@@ -2,7 +2,7 @@ // detail/fd_set_adapter.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/detail/fenced_block.hpp view
@@ -2,7 +2,7 @@ // detail/fenced_block.hpp // ~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/detail/functional.hpp view
@@ -2,7 +2,7 @@ // detail/functional.hpp // ~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -33,6 +33,12 @@ #endif // defined(ASIO_HAS_STD_FUNCTION) } // namespace detail++#if defined(ASIO_HAS_STD_REFERENCE_WRAPPER)+using std::ref;+using std::reference_wrapper;+#endif // defined(ASIO_HAS_STD_REFERENCE_WRAPPER)+ } // namespace asio #endif // ASIO_DETAIL_FUNCTIONAL_HPP
link/modules/asio-standalone/asio/include/asio/detail/future.hpp view
@@ -2,7 +2,7 @@ // detail/future.hpp // ~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/detail/gcc_arm_fenced_block.hpp view
@@ -2,7 +2,7 @@ // detail/gcc_arm_fenced_block.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/detail/gcc_hppa_fenced_block.hpp view
@@ -2,7 +2,7 @@ // detail/gcc_hppa_fenced_block.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/detail/gcc_sync_fenced_block.hpp view
@@ -2,7 +2,7 @@ // detail/gcc_sync_fenced_block.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/detail/gcc_x86_fenced_block.hpp view
@@ -2,7 +2,7 @@ // detail/gcc_x86_fenced_block.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -55,7 +55,7 @@ { int r = 0, m = 1; __asm__ __volatile__ (- "xchgl %0, %1" :+ "xchg{l} %0, %1" : "=r"(r), "=m"(m) : "0"(1), "m"(m) : "memory", "cc");
link/modules/asio-standalone/asio/include/asio/detail/global.hpp view
@@ -2,7 +2,7 @@ // detail/global.hpp // ~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/detail/handler_alloc_helpers.hpp view
@@ -2,7 +2,7 @@ // detail/handler_alloc_helpers.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -51,21 +51,24 @@ #endif // defined(ASIO_NO_DEPRECATED) template <typename Handler>-inline void* allocate(std::size_t s, Handler& h)+inline void* allocate(std::size_t s, Handler& h,+ std::size_t align = ASIO_DEFAULT_ALIGN) { #if !defined(ASIO_HAS_HANDLER_HOOKS)- return ::operator new(s);+ return asio::aligned_new(align, s); #elif defined(ASIO_NO_DEPRECATED) // The asio_handler_allocate hook is no longer used to obtain memory. (void)&error_if_hooks_are_defined<Handler>; (void)h;-#if !defined(ASIO_DISABLE_SMALL_BLOCK_RECYCLING)+# if !defined(ASIO_DISABLE_SMALL_BLOCK_RECYCLING) return asio::detail::thread_info_base::allocate(- asio::detail::thread_context::thread_call_stack::top(), s);-#else // !defined(ASIO_DISABLE_SMALL_BLOCK_RECYCLING)- return ::operator new(size);-#endif // !defined(ASIO_DISABLE_SMALL_BLOCK_RECYCLING)+ asio::detail::thread_context::top_of_thread_call_stack(),+ s, align);+# else // !defined(ASIO_DISABLE_SMALL_BLOCK_RECYCLING)+ return asio::aligned_new(align, s);+# endif // !defined(ASIO_DISABLE_SMALL_BLOCK_RECYCLING) #else+ (void)align; using asio::asio_handler_allocate; return asio_handler_allocate(s, asio::detail::addressof(h)); #endif@@ -75,17 +78,17 @@ inline void deallocate(void* p, std::size_t s, Handler& h) { #if !defined(ASIO_HAS_HANDLER_HOOKS)- ::operator delete(p);+ asio::aligned_delete(p); #elif defined(ASIO_NO_DEPRECATED) // The asio_handler_allocate hook is no longer used to obtain memory. (void)&error_if_hooks_are_defined<Handler>; (void)h; #if !defined(ASIO_DISABLE_SMALL_BLOCK_RECYCLING) asio::detail::thread_info_base::deallocate(- asio::detail::thread_context::thread_call_stack::top(), p, s);+ asio::detail::thread_context::top_of_thread_call_stack(), p, s); #else // !defined(ASIO_DISABLE_SMALL_BLOCK_RECYCLING) (void)s;- ::operator delete(p);+ asio::aligned_delete(p); #endif // !defined(ASIO_DISABLE_SMALL_BLOCK_RECYCLING) #else using asio::asio_handler_deallocate;@@ -124,7 +127,8 @@ T* allocate(std::size_t n) { return static_cast<T*>(- asio_handler_alloc_helpers::allocate(sizeof(T) * n, handler_));+ asio_handler_alloc_helpers::allocate(+ sizeof(T) * n, handler_, ASIO_ALIGNOF(T))); } void deallocate(T* p, std::size_t n)
link/modules/asio-standalone/asio/include/asio/detail/handler_cont_helpers.hpp view
@@ -2,7 +2,7 @@ // detail/handler_cont_helpers.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/detail/handler_invoke_helpers.hpp view
@@ -2,7 +2,7 @@ // detail/handler_invoke_helpers.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/detail/handler_tracking.hpp view
@@ -2,7 +2,7 @@ // detail/handler_tracking.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/detail/handler_type_requirements.hpp view
@@ -2,7 +2,7 @@ // detail/handler_type_requirements.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -64,7 +64,7 @@ auto zero_arg_copyable_handler_test(Handler h, void*) -> decltype( sizeof(Handler(static_cast<const Handler&>(h))),- ((h)()),+ (ASIO_MOVE_OR_LVALUE(Handler)(h)()), char(0)); template <typename Handler>@@ -74,7 +74,7 @@ auto one_arg_handler_test(Handler h, Arg1* a1) -> decltype( sizeof(Handler(ASIO_MOVE_CAST(Handler)(h))),- ((h)(*a1)),+ (ASIO_MOVE_OR_LVALUE(Handler)(h)(*a1)), char(0)); template <typename Handler>@@ -84,7 +84,7 @@ auto two_arg_handler_test(Handler h, Arg1* a1, Arg2* a2) -> decltype( sizeof(Handler(ASIO_MOVE_CAST(Handler)(h))),- ((h)(*a1, *a2)),+ (ASIO_MOVE_OR_LVALUE(Handler)(h)(*a1, *a2)), char(0)); template <typename Handler>@@ -94,7 +94,8 @@ auto two_arg_move_handler_test(Handler h, Arg1* a1, Arg2* a2) -> decltype( sizeof(Handler(ASIO_MOVE_CAST(Handler)(h))),- ((h)(*a1, ASIO_MOVE_CAST(Arg2)(*a2))),+ (ASIO_MOVE_OR_LVALUE(Handler)(h)(+ *a1, ASIO_MOVE_CAST(Arg2)(*a2))), char(0)); template <typename Handler>@@ -116,9 +117,11 @@ #if defined(ASIO_HAS_MOVE) template <typename T> T rvref(); template <typename T> T rvref(T);+template <typename T> T rorlvref(); #else // defined(ASIO_HAS_MOVE) template <typename T> const T& rvref(); template <typename T> const T& rvref(T);+template <typename T> T& rorlvref(); #endif // defined(ASIO_HAS_MOVE) template <typename T> char argbyv(T); @@ -145,7 +148,7 @@ asio::detail::clvref< \ asio_true_handler_type>())) + \ sizeof( \- asio::detail::lvref< \+ asio::detail::rorlvref< \ asio_true_handler_type>()(), \ char(0))> ASIO_UNUSED_TYPEDEF @@ -170,7 +173,7 @@ asio::detail::rvref< \ asio_true_handler_type>())) + \ sizeof( \- asio::detail::lvref< \+ asio::detail::rorlvref< \ asio_true_handler_type>()( \ asio::detail::lvref<const asio::error_code>(), \ asio::detail::lvref<const std::size_t>()), \@@ -197,7 +200,7 @@ asio::detail::rvref< \ asio_true_handler_type>())) + \ sizeof( \- asio::detail::lvref< \+ asio::detail::rorlvref< \ asio_true_handler_type>()( \ asio::detail::lvref<const asio::error_code>(), \ asio::detail::lvref<const std::size_t>()), \@@ -223,7 +226,7 @@ asio::detail::rvref< \ asio_true_handler_type>())) + \ sizeof( \- asio::detail::lvref< \+ asio::detail::rorlvref< \ asio_true_handler_type>()( \ asio::detail::lvref<const asio::error_code>()), \ char(0))> ASIO_UNUSED_TYPEDEF@@ -249,7 +252,7 @@ asio::detail::rvref< \ asio_true_handler_type>())) + \ sizeof( \- asio::detail::lvref< \+ asio::detail::rorlvref< \ asio_true_handler_type>()( \ asio::detail::lvref<const asio::error_code>(), \ asio::detail::rvref<socket_type>()), \@@ -275,7 +278,7 @@ asio::detail::rvref< \ asio_true_handler_type>())) + \ sizeof( \- asio::detail::lvref< \+ asio::detail::rorlvref< \ asio_true_handler_type>()( \ asio::detail::lvref<const asio::error_code>()), \ char(0))> ASIO_UNUSED_TYPEDEF@@ -301,7 +304,7 @@ asio::detail::rvref< \ asio_true_handler_type>())) + \ sizeof( \- asio::detail::lvref< \+ asio::detail::rorlvref< \ asio_true_handler_type>()( \ asio::detail::lvref<const asio::error_code>(), \ asio::detail::lvref<const endpoint_type>()), \@@ -328,7 +331,7 @@ asio::detail::rvref< \ asio_true_handler_type>())) + \ sizeof( \- asio::detail::lvref< \+ asio::detail::rorlvref< \ asio_true_handler_type>()( \ asio::detail::lvref<const asio::error_code>(), \ asio::detail::lvref<const iter_type>()), \@@ -355,7 +358,7 @@ asio::detail::rvref< \ asio_true_handler_type>())) + \ sizeof( \- asio::detail::lvref< \+ asio::detail::rorlvref< \ asio_true_handler_type>()( \ asio::detail::lvref<const asio::error_code>(), \ asio::detail::lvref<const range_type>()), \@@ -381,7 +384,7 @@ asio::detail::rvref< \ asio_true_handler_type>())) + \ sizeof( \- asio::detail::lvref< \+ asio::detail::rorlvref< \ asio_true_handler_type>()( \ asio::detail::lvref<const asio::error_code>()), \ char(0))> ASIO_UNUSED_TYPEDEF@@ -407,7 +410,7 @@ asio::detail::rvref< \ asio_true_handler_type>())) + \ sizeof( \- asio::detail::lvref< \+ asio::detail::rorlvref< \ asio_true_handler_type>()( \ asio::detail::lvref<const asio::error_code>(), \ asio::detail::lvref<const int>()), \@@ -433,7 +436,7 @@ asio::detail::rvref< \ asio_true_handler_type>())) + \ sizeof( \- asio::detail::lvref< \+ asio::detail::rorlvref< \ asio_true_handler_type>()( \ asio::detail::lvref<const asio::error_code>()), \ char(0))> ASIO_UNUSED_TYPEDEF@@ -459,7 +462,7 @@ asio::detail::rvref< \ asio_true_handler_type>())) + \ sizeof( \- asio::detail::lvref< \+ asio::detail::rorlvref< \ asio_true_handler_type>()( \ asio::detail::lvref<const asio::error_code>(), \ asio::detail::lvref<const std::size_t>()), \@@ -485,7 +488,7 @@ asio::detail::rvref< \ asio_true_handler_type>())) + \ sizeof( \- asio::detail::lvref< \+ asio::detail::rorlvref< \ asio_true_handler_type>()( \ asio::detail::lvref<const asio::error_code>()), \ char(0))> ASIO_UNUSED_TYPEDEF
link/modules/asio-standalone/asio/include/asio/detail/handler_work.hpp view
@@ -2,7 +2,7 @@ // detail/handler_work.hpp // ~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -16,9 +16,13 @@ #endif // defined(_MSC_VER) && (_MSC_VER >= 1200) #include "asio/detail/config.hpp"+#include "asio/associated_allocator.hpp" #include "asio/associated_executor.hpp"+#include "asio/associated_immediate_executor.hpp" #include "asio/detail/handler_invoke_helpers.hpp"+#include "asio/detail/initiate_dispatch.hpp" #include "asio/detail/type_traits.hpp"+#include "asio/detail/work_dispatcher.hpp" #include "asio/execution/allocator.hpp" #include "asio/execution/blocking.hpp" #include "asio/execution/execute.hpp"@@ -34,6 +38,13 @@ class executor; class io_context; +#if !defined(ASIO_USE_TS_EXECUTOR_AS_DEFAULT)++class any_completion_executor;+class any_io_executor;++#endif // !defined(ASIO_USE_TS_EXECUTOR_AS_DEFAULT)+ namespace execution { #if defined(ASIO_HAS_VARIADIC_TEMPLATES)@@ -56,14 +67,14 @@ class handler_work_base { public:- explicit handler_work_base(const Executor& ex) ASIO_NOEXCEPT+ explicit handler_work_base(int, int, const Executor& ex) ASIO_NOEXCEPT : executor_(asio::prefer(ex, execution::outstanding_work.tracked)) { } template <typename OtherExecutor>- handler_work_base(const Executor& ex,- const OtherExecutor&) ASIO_NOEXCEPT+ handler_work_base(bool /*base1_owns_work*/, const Executor& ex,+ const OtherExecutor& /*candidate*/) ASIO_NOEXCEPT : executor_(asio::prefer(ex, execution::outstanding_work.tracked)) { }@@ -88,11 +99,16 @@ template <typename Function, typename Handler> void dispatch(Function& function, Handler& handler) {+#if defined(ASIO_NO_DEPRECATED)+ asio::prefer(executor_,+ execution::allocator((get_associated_allocator)(handler))+ ).execute(ASIO_MOVE_CAST(Function)(function));+#else // defined(ASIO_NO_DEPRECATED) execution::execute( asio::prefer(executor_,- execution::blocking.possibly, execution::allocator((get_associated_allocator)(handler))), ASIO_MOVE_CAST(Function)(function));+#endif // defined(ASIO_NO_DEPRECATED) } private:@@ -116,14 +132,14 @@ >::type> { public:- explicit handler_work_base(const Executor& ex) ASIO_NOEXCEPT+ explicit handler_work_base(int, int, const Executor& ex) ASIO_NOEXCEPT : executor_(ex), owns_work_(true) { executor_.on_work_started(); } - handler_work_base(const Executor& ex,+ handler_work_base(bool /*base1_owns_work*/, const Executor& ex, const Executor& candidate) ASIO_NOEXCEPT : executor_(ex), owns_work_(ex != candidate)@@ -133,8 +149,8 @@ } template <typename OtherExecutor>- handler_work_base(const Executor& ex,- const OtherExecutor&) ASIO_NOEXCEPT+ handler_work_base(bool /*base1_owns_work*/, const Executor& ex,+ const OtherExecutor& /*candidate*/) ASIO_NOEXCEPT : executor_(ex), owns_work_(true) {@@ -191,7 +207,7 @@ >::type> { public:- explicit handler_work_base(const Executor&)+ explicit handler_work_base(int, int, const Executor&) { } @@ -214,7 +230,7 @@ class handler_work_base<Executor, void, IoContext, Executor> { public:- explicit handler_work_base(const Executor& ex) ASIO_NOEXCEPT+ explicit handler_work_base(int, int, const Executor& ex) ASIO_NOEXCEPT #if !defined(ASIO_NO_TYPEID) : executor_( ex.target_type() == typeid(typename IoContext::executor_type)@@ -227,7 +243,7 @@ executor_.on_work_started(); } - handler_work_base(const Executor& ex,+ handler_work_base(bool /*base1_owns_work*/, const Executor& ex, const Executor& candidate) ASIO_NOEXCEPT : executor_(ex != candidate ? ex : Executor()) {@@ -286,14 +302,15 @@ typename T1, typename T2, typename T3, typename T4, typename T5, typename T6, typename T7, typename T8, typename T9, #endif // defined(ASIO_HAS_VARIADIC_TEMPLATES)- typename IoContext, typename PolymorphicExecutor>+ typename CandidateExecutor, typename IoContext,+ typename PolymorphicExecutor> class handler_work_base< #if defined(ASIO_HAS_VARIADIC_TEMPLATES) execution::any_executor<SupportableProperties...>, #else // defined(ASIO_HAS_VARIADIC_TEMPLATES) execution::any_executor<T1, T2, T3, T4, T5, T6, T7, T8, T9>, #endif // defined(ASIO_HAS_VARIADIC_TEMPLATES)- void, IoContext, PolymorphicExecutor>+ CandidateExecutor, IoContext, PolymorphicExecutor> { public: typedef@@ -304,7 +321,8 @@ #endif // defined(ASIO_HAS_VARIADIC_TEMPLATES) executor_type; - explicit handler_work_base(const executor_type& ex) ASIO_NOEXCEPT+ explicit handler_work_base(int, int,+ const executor_type& ex) ASIO_NOEXCEPT #if !defined(ASIO_NO_TYPEID) : executor_( ex.target_type() == typeid(typename IoContext::executor_type)@@ -316,15 +334,18 @@ { } - handler_work_base(const executor_type& ex,+ handler_work_base(bool base1_owns_work, const executor_type& ex, const executor_type& candidate) ASIO_NOEXCEPT- : executor_(ex != candidate ? ex : executor_type())+ : executor_(+ !base1_owns_work && ex == candidate+ ? executor_type()+ : asio::prefer(ex, execution::outstanding_work.tracked)) { } template <typename OtherExecutor>- handler_work_base(const executor_type& ex,- const OtherExecutor&) ASIO_NOEXCEPT+ handler_work_base(bool /*base1_owns_work*/, const executor_type& ex,+ const OtherExecutor& /*candidate*/) ASIO_NOEXCEPT : executor_(asio::prefer(ex, execution::outstanding_work.tracked)) { }@@ -347,19 +368,96 @@ } template <typename Function, typename Handler>- void dispatch(Function& function, Handler& handler)+ void dispatch(Function& function, Handler&) {- execution::execute(- asio::prefer(executor_,- execution::blocking.possibly,- execution::allocator((get_associated_allocator)(handler))),- ASIO_MOVE_CAST(Function)(function));+#if defined(ASIO_NO_DEPRECATED)+ executor_.execute(ASIO_MOVE_CAST(Function)(function));+#else // defined(ASIO_NO_DEPRECATED)+ execution::execute(executor_, ASIO_MOVE_CAST(Function)(function));+#endif // defined(ASIO_NO_DEPRECATED) } private: executor_type executor_; }; +#if !defined(ASIO_USE_TS_EXECUTOR_AS_DEFAULT)++template <typename Executor, typename CandidateExecutor,+ typename IoContext, typename PolymorphicExecutor>+class handler_work_base<+ Executor, CandidateExecutor,+ IoContext, PolymorphicExecutor,+ typename enable_if<+ is_same<Executor, any_completion_executor>::value+ || is_same<Executor, any_io_executor>::value+ >::type>+{+public:+ typedef Executor executor_type;++ explicit handler_work_base(int, int,+ const executor_type& ex) ASIO_NOEXCEPT+#if !defined(ASIO_NO_TYPEID)+ : executor_(+ ex.target_type() == typeid(typename IoContext::executor_type)+ ? executor_type()+ : asio::prefer(ex, execution::outstanding_work.tracked))+#else // !defined(ASIO_NO_TYPEID)+ : executor_(asio::prefer(ex, execution::outstanding_work.tracked))+#endif // !defined(ASIO_NO_TYPEID)+ {+ }++ handler_work_base(bool base1_owns_work, const executor_type& ex,+ const executor_type& candidate) ASIO_NOEXCEPT+ : executor_(+ !base1_owns_work && ex == candidate+ ? executor_type()+ : asio::prefer(ex, execution::outstanding_work.tracked))+ {+ }++ template <typename OtherExecutor>+ handler_work_base(bool /*base1_owns_work*/, const executor_type& ex,+ const OtherExecutor& /*candidate*/) ASIO_NOEXCEPT+ : executor_(asio::prefer(ex, execution::outstanding_work.tracked))+ {+ }++ handler_work_base(const handler_work_base& other) ASIO_NOEXCEPT+ : executor_(other.executor_)+ {+ }++#if defined(ASIO_HAS_MOVE)+ handler_work_base(handler_work_base&& other) ASIO_NOEXCEPT+ : executor_(ASIO_MOVE_CAST(executor_type)(other.executor_))+ {+ }+#endif // defined(ASIO_HAS_MOVE)++ bool owns_work() const ASIO_NOEXCEPT+ {+ return !!executor_;+ }++ template <typename Function, typename Handler>+ void dispatch(Function& function, Handler&)+ {+#if defined(ASIO_NO_DEPRECATED)+ executor_.execute(ASIO_MOVE_CAST(Function)(function));+#else // defined(ASIO_NO_DEPRECATED)+ execution::execute(executor_, ASIO_MOVE_CAST(Function)(function));+#endif // defined(ASIO_NO_DEPRECATED)+ }++private:+ executor_type executor_;+};++#endif // !defined(ASIO_USE_TS_EXECUTOR_AS_DEFAULT)+ template <typename Handler, typename IoExecutor, typename = void> class handler_work : handler_work_base<IoExecutor>,@@ -372,8 +470,9 @@ Handler, IoExecutor>::type, IoExecutor> base2_type; handler_work(Handler& handler, const IoExecutor& io_ex) ASIO_NOEXCEPT- : base1_type(io_ex),- base2_type(asio::get_associated_executor(handler, io_ex), io_ex)+ : base1_type(0, 0, io_ex),+ base2_type(base1_type::owns_work(),+ asio::get_associated_executor(handler, io_ex), io_ex) { } @@ -409,7 +508,7 @@ typedef handler_work_base<IoExecutor> base1_type; handler_work(Handler&, const IoExecutor& io_ex) ASIO_NOEXCEPT- : base1_type(io_ex)+ : base1_type(0, 0, io_ex) { } @@ -428,6 +527,34 @@ base1_type::dispatch(function, handler); } }+};++template <typename Handler, typename IoExecutor>+class immediate_handler_work+{+public:+ typedef handler_work<Handler, IoExecutor> handler_work_type;++ explicit immediate_handler_work(ASIO_MOVE_ARG(handler_work_type) w)+ : handler_work_(ASIO_MOVE_CAST(handler_work_type)(w))+ {+ }++ template <typename Function>+ void complete(Function& function, Handler& handler, const void* io_ex)+ {+ typedef typename associated_immediate_executor<Handler, IoExecutor>::type+ immediate_ex_type;++ immediate_ex_type immediate_ex = (get_associated_immediate_executor)(+ handler, *static_cast<const IoExecutor*>(io_ex));++ (initiate_dispatch_with_executor<immediate_ex_type>(immediate_ex))(+ ASIO_MOVE_CAST(Function)(function));+ }++private:+ handler_work_type handler_work_; }; } // namespace detail
link/modules/asio-standalone/asio/include/asio/detail/hash_map.hpp view
@@ -2,7 +2,7 @@ // detail/hash_map.hpp // ~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/detail/impl/buffer_sequence_adapter.ipp view
@@ -2,7 +2,7 @@ // detail/impl/buffer_sequence_adapter.ipp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/detail/impl/descriptor_ops.ipp view
@@ -2,7 +2,7 @@ // detail/impl/descriptor_ops.ipp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -37,6 +37,14 @@ return result; } +int open(const char* path, int flags,+ unsigned mode, asio::error_code& ec)+{+ int result = ::open(path, flags, mode);+ get_last_error(ec, result < 0);+ return result;+}+ int close(int d, state_type& state, asio::error_code& ec) { int result = 0;@@ -61,7 +69,18 @@ ::fcntl(d, F_SETFL, flags & ~O_NONBLOCK); #else // defined(__SYMBIAN32__) || defined(__EMSCRIPTEN__) ioctl_arg_type arg = 0;+# if defined(ENOTTY)+ result = ::ioctl(d, FIONBIO, &arg);+ get_last_error(ec, result < 0);+ if (ec.value() == ENOTTY)+ {+ int flags = ::fcntl(d, F_GETFL, 0);+ if (flags >= 0)+ ::fcntl(d, F_SETFL, flags & ~O_NONBLOCK);+ }+# else // defined(ENOTTY) ::ioctl(d, FIONBIO, &arg);+# endif // defined(ENOTTY) #endif // defined(__SYMBIAN32__) || defined(__EMSCRIPTEN__) state &= ~non_blocking; @@ -95,6 +114,19 @@ ioctl_arg_type arg = (value ? 1 : 0); int result = ::ioctl(d, FIONBIO, &arg); get_last_error(ec, result < 0);+# if defined(ENOTTY)+ if (ec.value() == ENOTTY)+ {+ result = ::fcntl(d, F_GETFL, 0);+ get_last_error(ec, result < 0);+ if (result >= 0)+ {+ int flag = (value ? (result | O_NONBLOCK) : (result & ~O_NONBLOCK));+ result = ::fcntl(d, F_SETFL, flag);+ get_last_error(ec, result < 0);+ }+ }+# endif // defined(ENOTTY) #endif // defined(__SYMBIAN32__) || defined(__EMSCRIPTEN__) if (result >= 0)@@ -145,6 +177,19 @@ ioctl_arg_type arg = (value ? 1 : 0); int result = ::ioctl(d, FIONBIO, &arg); get_last_error(ec, result < 0);+# if defined(ENOTTY)+ if (ec.value() == ENOTTY)+ {+ result = ::fcntl(d, F_GETFL, 0);+ get_last_error(ec, result < 0);+ if (result >= 0)+ {+ int flag = (value ? (result | O_NONBLOCK) : (result & ~O_NONBLOCK));+ result = ::fcntl(d, F_SETFL, flag);+ get_last_error(ec, result < 0);+ }+ }+# endif // defined(ENOTTY) #endif // defined(__SYMBIAN32__) || defined(__EMSCRIPTEN__) if (result >= 0)@@ -171,7 +216,7 @@ // A request to read 0 bytes on a stream is a no-op. if (all_empty) {- ec.assign(0, ec.category());+ asio::error::clear(ec); return 0; } @@ -217,7 +262,7 @@ // A request to read 0 bytes on a stream is a no-op. if (size == 0) {- ec.assign(0, ec.category());+ asio::error::clear(ec); return 0; } @@ -339,7 +384,7 @@ // A request to write 0 bytes on a stream is a no-op. if (all_empty) {- ec.assign(0, ec.category());+ asio::error::clear(ec); return 0; } @@ -378,7 +423,7 @@ // A request to write 0 bytes on a stream is a no-op. if (size == 0) {- ec.assign(0, ec.category());+ asio::error::clear(ec); return 0; } @@ -466,6 +511,323 @@ return true; } }++#if defined(ASIO_HAS_FILE)++std::size_t sync_read_at(int d, state_type state, uint64_t offset,+ buf* bufs, std::size_t count, bool all_empty, asio::error_code& ec)+{+ if (d == -1)+ {+ ec = asio::error::bad_descriptor;+ return 0;+ }++ // A request to read 0 bytes on a stream is a no-op.+ if (all_empty)+ {+ asio::error::clear(ec);+ return 0;+ }++ // Read some data.+ for (;;)+ {+ // Try to complete the operation without blocking.+ signed_size_type bytes = ::preadv(d, bufs, static_cast<int>(count), offset);+ get_last_error(ec, bytes < 0);++ // Check if operation succeeded.+ if (bytes > 0)+ return bytes;++ // Check for EOF.+ if (bytes == 0)+ {+ ec = asio::error::eof;+ return 0;+ }++ // Operation failed.+ if ((state & user_set_non_blocking)+ || (ec != asio::error::would_block+ && ec != asio::error::try_again))+ return 0;++ // Wait for descriptor to become ready.+ if (descriptor_ops::poll_read(d, 0, ec) < 0)+ return 0;+ }+}++std::size_t sync_read_at1(int d, state_type state, uint64_t offset,+ void* data, std::size_t size, asio::error_code& ec)+{+ if (d == -1)+ {+ ec = asio::error::bad_descriptor;+ return 0;+ }++ // A request to read 0 bytes on a stream is a no-op.+ if (size == 0)+ {+ asio::error::clear(ec);+ return 0;+ }++ // Read some data.+ for (;;)+ {+ // Try to complete the operation without blocking.+ signed_size_type bytes = ::pread(d, data, size, offset);+ get_last_error(ec, bytes < 0);++ // Check if operation succeeded.+ if (bytes > 0)+ return bytes;++ // Check for EOF.+ if (bytes == 0)+ {+ ec = asio::error::eof;+ return 0;+ }++ // Operation failed.+ if ((state & user_set_non_blocking)+ || (ec != asio::error::would_block+ && ec != asio::error::try_again))+ return 0;++ // Wait for descriptor to become ready.+ if (descriptor_ops::poll_read(d, 0, ec) < 0)+ return 0;+ }+}++bool non_blocking_read_at(int d, uint64_t offset, buf* bufs, std::size_t count,+ asio::error_code& ec, std::size_t& bytes_transferred)+{+ for (;;)+ {+ // Read some data.+ signed_size_type bytes = ::preadv(d, bufs, static_cast<int>(count), offset);+ get_last_error(ec, bytes < 0);++ // Check for EOF.+ if (bytes == 0)+ {+ ec = asio::error::eof;+ return true;+ }++ // Check if operation succeeded.+ if (bytes > 0)+ {+ bytes_transferred = bytes;+ return true;+ }++ // Retry operation if interrupted by signal.+ if (ec == asio::error::interrupted)+ continue;++ // Check if we need to run the operation again.+ if (ec == asio::error::would_block+ || ec == asio::error::try_again)+ return false;++ // Operation failed.+ bytes_transferred = 0;+ return true;+ }+}++bool non_blocking_read_at1(int d, uint64_t offset, void* data, std::size_t size,+ asio::error_code& ec, std::size_t& bytes_transferred)+{+ for (;;)+ {+ // Read some data.+ signed_size_type bytes = ::pread(d, data, size, offset);+ get_last_error(ec, bytes < 0);++ // Check for EOF.+ if (bytes == 0)+ {+ ec = asio::error::eof;+ return true;+ }++ // Check if operation succeeded.+ if (bytes > 0)+ {+ bytes_transferred = bytes;+ return true;+ }++ // Retry operation if interrupted by signal.+ if (ec == asio::error::interrupted)+ continue;++ // Check if we need to run the operation again.+ if (ec == asio::error::would_block+ || ec == asio::error::try_again)+ return false;++ // Operation failed.+ bytes_transferred = 0;+ return true;+ }+}++std::size_t sync_write_at(int d, state_type state, uint64_t offset,+ const buf* bufs, std::size_t count, bool all_empty,+ asio::error_code& ec)+{+ if (d == -1)+ {+ ec = asio::error::bad_descriptor;+ return 0;+ }++ // A request to write 0 bytes on a stream is a no-op.+ if (all_empty)+ {+ asio::error::clear(ec);+ return 0;+ }++ // Write some data.+ for (;;)+ {+ // Try to complete the operation without blocking.+ signed_size_type bytes = ::pwritev(d,+ bufs, static_cast<int>(count), offset);+ get_last_error(ec, bytes < 0);++ // Check if operation succeeded.+ if (bytes > 0)+ return bytes;++ // Operation failed.+ if ((state & user_set_non_blocking)+ || (ec != asio::error::would_block+ && ec != asio::error::try_again))+ return 0;++ // Wait for descriptor to become ready.+ if (descriptor_ops::poll_write(d, 0, ec) < 0)+ return 0;+ }+}++std::size_t sync_write_at1(int d, state_type state, uint64_t offset,+ const void* data, std::size_t size, asio::error_code& ec)+{+ if (d == -1)+ {+ ec = asio::error::bad_descriptor;+ return 0;+ }++ // A request to write 0 bytes on a stream is a no-op.+ if (size == 0)+ {+ asio::error::clear(ec);+ return 0;+ }++ // Write some data.+ for (;;)+ {+ // Try to complete the operation without blocking.+ signed_size_type bytes = ::pwrite(d, data, size, offset);+ get_last_error(ec, bytes < 0);++ // Check if operation succeeded.+ if (bytes > 0)+ return bytes;++ // Operation failed.+ if ((state & user_set_non_blocking)+ || (ec != asio::error::would_block+ && ec != asio::error::try_again))+ return 0;++ // Wait for descriptor to become ready.+ if (descriptor_ops::poll_write(d, 0, ec) < 0)+ return 0;+ }+}++bool non_blocking_write_at(int d, uint64_t offset,+ const buf* bufs, std::size_t count,+ asio::error_code& ec, std::size_t& bytes_transferred)+{+ for (;;)+ {+ // Write some data.+ signed_size_type bytes = ::pwritev(d,+ bufs, static_cast<int>(count), offset);+ get_last_error(ec, bytes < 0);++ // Check if operation succeeded.+ if (bytes >= 0)+ {+ bytes_transferred = bytes;+ return true;+ }++ // Retry operation if interrupted by signal.+ if (ec == asio::error::interrupted)+ continue;++ // Check if we need to run the operation again.+ if (ec == asio::error::would_block+ || ec == asio::error::try_again)+ return false;++ // Operation failed.+ bytes_transferred = 0;+ return true;+ }+}++bool non_blocking_write_at1(int d, uint64_t offset,+ const void* data, std::size_t size,+ asio::error_code& ec, std::size_t& bytes_transferred)+{+ for (;;)+ {+ // Write some data.+ signed_size_type bytes = ::pwrite(d, data, size, offset);+ get_last_error(ec, bytes < 0);++ // Check if operation succeeded.+ if (bytes >= 0)+ {+ bytes_transferred = bytes;+ return true;+ }++ // Retry operation if interrupted by signal.+ if (ec == asio::error::interrupted)+ continue;++ // Check if we need to run the operation again.+ if (ec == asio::error::would_block+ || ec == asio::error::try_again)+ return false;++ // Operation failed.+ bytes_transferred = 0;+ return true;+ }+}++#endif // defined(ASIO_HAS_FILE) int ioctl(int d, state_type& state, long cmd, ioctl_arg_type* arg, asio::error_code& ec)
link/modules/asio-standalone/asio/include/asio/detail/impl/dev_poll_reactor.hpp view
@@ -2,7 +2,7 @@ // detail/impl/dev_poll_reactor.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -19,11 +19,19 @@ #if defined(ASIO_HAS_DEV_POLL) +#include "asio/detail/scheduler.hpp"+ #include "asio/detail/push_options.hpp" namespace asio { namespace detail { +inline void dev_poll_reactor::post_immediate_completion(+ operation* op, bool is_continuation) const+{+ scheduler_.post_immediate_completion(op, is_continuation);+}+ template <typename Time_Traits> void dev_poll_reactor::add_timer_queue(timer_queue<Time_Traits>& queue) {@@ -66,6 +74,18 @@ lock.unlock(); scheduler_.post_deferred_completions(ops); return n;+}++template <typename Time_Traits>+void dev_poll_reactor::cancel_timer_by_key(timer_queue<Time_Traits>& queue,+ typename timer_queue<Time_Traits>::per_timer_data* timer,+ void* cancellation_key)+{+ asio::detail::mutex::scoped_lock lock(mutex_);+ op_queue<operation> ops;+ queue.cancel_timer_by_key(timer, ops, cancellation_key);+ lock.unlock();+ scheduler_.post_deferred_completions(ops); } template <typename Time_Traits>
link/modules/asio-standalone/asio/include/asio/detail/impl/dev_poll_reactor.ipp view
@@ -2,7 +2,7 @@ // detail/impl/dev_poll_reactor.ipp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -21,6 +21,7 @@ #include "asio/detail/dev_poll_reactor.hpp" #include "asio/detail/assert.hpp"+#include "asio/detail/scheduler.hpp" #include "asio/detail/throw_error.hpp" #include "asio/error.hpp" @@ -147,15 +148,24 @@ { } +void dev_poll_reactor::call_post_immediate_completion(+ operation* op, bool is_continuation, const void* self)+{+ static_cast<const dev_poll_reactor*>(self)->post_immediate_completion(+ op, is_continuation);+}+ void dev_poll_reactor::start_op(int op_type, socket_type descriptor, dev_poll_reactor::per_descriptor_data&, reactor_op* op,- bool is_continuation, bool allow_speculative)+ bool is_continuation, bool allow_speculative,+ void (*on_immediate)(operation*, bool, const void*),+ const void* immediate_arg) { asio::detail::mutex::scoped_lock lock(mutex_); if (shutdown_) {- post_immediate_completion(op, is_continuation);+ on_immediate(op, is_continuation, immediate_arg); return; } @@ -168,7 +178,7 @@ if (op->perform()) { lock.unlock();- scheduler_.post_immediate_completion(op, is_continuation);+ on_immediate(op, is_continuation, immediate_arg); return; } }@@ -199,6 +209,19 @@ { asio::detail::mutex::scoped_lock lock(mutex_); cancel_ops_unlocked(descriptor, asio::error::operation_aborted);+}++void dev_poll_reactor::cancel_ops_by_key(socket_type descriptor,+ dev_poll_reactor::per_descriptor_data&,+ int op_type, void* cancellation_key)+{+ asio::detail::mutex::scoped_lock lock(mutex_);+ op_queue<operation> ops;+ bool need_interrupt = op_queue_[op_type].cancel_operations_by_key(+ descriptor, ops, cancellation_key, asio::error::operation_aborted);+ scheduler_.post_deferred_completions(ops);+ if (need_interrupt)+ interrupter_.interrupt(); } void dev_poll_reactor::deregister_descriptor(socket_type descriptor,
link/modules/asio-standalone/asio/include/asio/detail/impl/epoll_reactor.hpp view
@@ -2,7 +2,7 @@ // detail/impl/epoll_reactor.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -17,11 +17,19 @@ #if defined(ASIO_HAS_EPOLL) +#include "asio/detail/scheduler.hpp"+ #include "asio/detail/push_options.hpp" namespace asio { namespace detail { +inline void epoll_reactor::post_immediate_completion(+ operation* op, bool is_continuation) const+{+ scheduler_.post_immediate_completion(op, is_continuation);+}+ template <typename Time_Traits> void epoll_reactor::add_timer_queue(timer_queue<Time_Traits>& queue) {@@ -64,6 +72,18 @@ lock.unlock(); scheduler_.post_deferred_completions(ops); return n;+}++template <typename Time_Traits>+void epoll_reactor::cancel_timer_by_key(timer_queue<Time_Traits>& queue,+ typename timer_queue<Time_Traits>::per_timer_data* timer,+ void* cancellation_key)+{+ mutex::scoped_lock lock(mutex_);+ op_queue<operation> ops;+ queue.cancel_timer_by_key(timer, ops, cancellation_key);+ lock.unlock();+ scheduler_.post_deferred_completions(ops); } template <typename Time_Traits>
link/modules/asio-standalone/asio/include/asio/detail/impl/epoll_reactor.ipp view
@@ -2,7 +2,7 @@ // detail/impl/epoll_reactor.ipp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -22,6 +22,7 @@ #include <cstddef> #include <sys/epoll.h> #include "asio/detail/epoll_reactor.hpp"+#include "asio/detail/scheduler.hpp" #include "asio/detail/throw_error.hpp" #include "asio/error.hpp" @@ -228,14 +229,23 @@ source_descriptor_data = 0; } +void epoll_reactor::call_post_immediate_completion(+ operation* op, bool is_continuation, const void* self)+{+ static_cast<const epoll_reactor*>(self)->post_immediate_completion(+ op, is_continuation);+}+ void epoll_reactor::start_op(int op_type, socket_type descriptor, epoll_reactor::per_descriptor_data& descriptor_data, reactor_op* op,- bool is_continuation, bool allow_speculative)+ bool is_continuation, bool allow_speculative,+ void (*on_immediate)(operation*, bool, const void*),+ const void* immediate_arg) { if (!descriptor_data) { op->ec_ = asio::error::bad_descriptor;- post_immediate_completion(op, is_continuation);+ on_immediate(op, is_continuation, immediate_arg); return; } @@ -243,7 +253,7 @@ if (descriptor_data->shutdown_) {- post_immediate_completion(op, is_continuation);+ on_immediate(op, is_continuation, immediate_arg); return; } @@ -261,7 +271,7 @@ if (descriptor_data->registered_events_ != 0) descriptor_data->try_speculative_[op_type] = false; descriptor_lock.unlock();- scheduler_.post_immediate_completion(op, is_continuation);+ on_immediate(op, is_continuation, immediate_arg); return; } }@@ -269,7 +279,7 @@ if (descriptor_data->registered_events_ == 0) { op->ec_ = asio::error::operation_not_supported;- scheduler_.post_immediate_completion(op, is_continuation);+ on_immediate(op, is_continuation, immediate_arg); return; } @@ -288,7 +298,7 @@ { op->ec_ = asio::error_code(errno, asio::error::get_system_category());- scheduler_.post_immediate_completion(op, is_continuation);+ on_immediate(op, is_continuation, immediate_arg); return; } }@@ -297,7 +307,7 @@ else if (descriptor_data->registered_events_ == 0) { op->ec_ = asio::error::operation_not_supported;- scheduler_.post_immediate_completion(op, is_continuation);+ on_immediate(op, is_continuation, immediate_arg); return; } else@@ -336,6 +346,35 @@ ops.push(op); } }++ descriptor_lock.unlock();++ scheduler_.post_deferred_completions(ops);+}++void epoll_reactor::cancel_ops_by_key(socket_type,+ epoll_reactor::per_descriptor_data& descriptor_data,+ int op_type, void* cancellation_key)+{+ if (!descriptor_data)+ return;++ mutex::scoped_lock descriptor_lock(descriptor_data->mutex_);++ op_queue<operation> ops;+ op_queue<reactor_op> other_ops;+ while (reactor_op* op = descriptor_data->op_queue_[op_type].front())+ {+ descriptor_data->op_queue_[op_type].pop();+ if (op->cancellation_key_ == cancellation_key)+ {+ op->ec_ = asio::error::operation_aborted;+ ops.push(op);+ }+ else+ other_ops.push(op);+ }+ descriptor_data->op_queue_[op_type].push(other_ops); descriptor_lock.unlock();
link/modules/asio-standalone/asio/include/asio/detail/impl/eventfd_select_interrupter.ipp view
@@ -2,7 +2,7 @@ // detail/impl/eventfd_select_interrupter.ipp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // Copyright (c) 2008 Roelof Naude (roelof.naude at gmail dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying@@ -23,11 +23,11 @@ #include <sys/stat.h> #include <sys/types.h> #include <fcntl.h>-#if __GLIBC__ == 2 && __GLIBC_MINOR__ < 8+#if __GLIBC__ == 2 && __GLIBC_MINOR__ < 8 && !defined(__UCLIBC__) # include <asm/unistd.h>-#else // __GLIBC__ == 2 && __GLIBC_MINOR__ < 8+#else // __GLIBC__ == 2 && __GLIBC_MINOR__ < 8 && !defined(__UCLIBC__) # include <sys/eventfd.h>-#endif // __GLIBC__ == 2 && __GLIBC_MINOR__ < 8+#endif // __GLIBC__ == 2 && __GLIBC_MINOR__ < 8 && !defined(__UCLIBC__) #include "asio/detail/cstdint.hpp" #include "asio/detail/eventfd_select_interrupter.hpp" #include "asio/detail/throw_error.hpp"@@ -45,14 +45,14 @@ void eventfd_select_interrupter::open_descriptors() {-#if __GLIBC__ == 2 && __GLIBC_MINOR__ < 8+#if __GLIBC__ == 2 && __GLIBC_MINOR__ < 8 && !defined(__UCLIBC__) write_descriptor_ = read_descriptor_ = syscall(__NR_eventfd, 0); if (read_descriptor_ != -1) { ::fcntl(read_descriptor_, F_SETFL, O_NONBLOCK); ::fcntl(read_descriptor_, F_SETFD, FD_CLOEXEC); }-#else // __GLIBC__ == 2 && __GLIBC_MINOR__ < 8+#else // __GLIBC__ == 2 && __GLIBC_MINOR__ < 8 && !defined(__UCLIBC__) # if defined(EFD_CLOEXEC) && defined(EFD_NONBLOCK) write_descriptor_ = read_descriptor_ = ::eventfd(0, EFD_CLOEXEC | EFD_NONBLOCK);@@ -69,7 +69,7 @@ ::fcntl(read_descriptor_, F_SETFD, FD_CLOEXEC); } }-#endif // __GLIBC__ == 2 && __GLIBC_MINOR__ < 8+#endif // __GLIBC__ == 2 && __GLIBC_MINOR__ < 8 && !defined(__UCLIBC__) if (read_descriptor_ == -1) {@@ -152,7 +152,9 @@ return false; if (errno == EINTR) continue;- if (errno == EWOULDBLOCK || errno == EAGAIN)+ if (errno == EWOULDBLOCK)+ return true;+ if (errno == EAGAIN) return true; return false; }
link/modules/asio-standalone/asio/include/asio/detail/impl/handler_tracking.ipp view
@@ -2,7 +2,7 @@ // detail/impl/handler_tracking.ipp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -365,7 +365,9 @@ va_start(args, format); char line[256] = "";-#if defined(ASIO_HAS_SECURE_RTL)+#if defined(ASIO_HAS_SNPRINTF)+ int length = vsnprintf(line, sizeof(line), format, args);+#elif defined(ASIO_HAS_SECURE_RTL) int length = vsprintf_s(line, sizeof(line), format, args); #else // defined(ASIO_HAS_SECURE_RTL) int length = vsprintf(line, format, args);
+ link/modules/asio-standalone/asio/include/asio/detail/impl/io_uring_descriptor_service.ipp view
@@ -0,0 +1,205 @@+//+// detail/impl/io_uring_descriptor_service.ipp+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com)+//+// Distributed under the Boost Software License, Version 1.0. (See accompanying+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)+//++#ifndef ASIO_DETAIL_IMPL_IO_URING_DESCRIPTOR_SERVICE_IPP+#define ASIO_DETAIL_IMPL_IO_URING_DESCRIPTOR_SERVICE_IPP++#if defined(_MSC_VER) && (_MSC_VER >= 1200)+# pragma once+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)++#include "asio/detail/config.hpp"++#if defined(ASIO_HAS_IO_URING)++#include "asio/error.hpp"+#include "asio/detail/io_uring_descriptor_service.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {+namespace detail {++io_uring_descriptor_service::io_uring_descriptor_service(+ execution_context& context)+ : execution_context_service_base<io_uring_descriptor_service>(context),+ io_uring_service_(asio::use_service<io_uring_service>(context))+{+ io_uring_service_.init_task();+}++void io_uring_descriptor_service::shutdown()+{+}++void io_uring_descriptor_service::construct(+ io_uring_descriptor_service::implementation_type& impl)+{+ impl.descriptor_ = -1;+ impl.state_ = 0;+ impl.io_object_data_ = 0;+}++void io_uring_descriptor_service::move_construct(+ io_uring_descriptor_service::implementation_type& impl,+ io_uring_descriptor_service::implementation_type& other_impl)+ ASIO_NOEXCEPT+{+ impl.descriptor_ = other_impl.descriptor_;+ other_impl.descriptor_ = -1;++ impl.state_ = other_impl.state_;+ other_impl.state_ = 0;++ impl.io_object_data_ = other_impl.io_object_data_;+ other_impl.io_object_data_ = 0;+}++void io_uring_descriptor_service::move_assign(+ io_uring_descriptor_service::implementation_type& impl,+ io_uring_descriptor_service& /*other_service*/,+ io_uring_descriptor_service::implementation_type& other_impl)+{+ destroy(impl);++ impl.descriptor_ = other_impl.descriptor_;+ other_impl.descriptor_ = -1;++ impl.state_ = other_impl.state_;+ other_impl.state_ = 0;++ impl.io_object_data_ = other_impl.io_object_data_;+ other_impl.io_object_data_ = 0;+}++void io_uring_descriptor_service::destroy(+ io_uring_descriptor_service::implementation_type& impl)+{+ if (is_open(impl))+ {+ ASIO_HANDLER_OPERATION((io_uring_service_.context(),+ "descriptor", &impl, impl.descriptor_, "close"));++ io_uring_service_.deregister_io_object(impl.io_object_data_);+ asio::error_code ignored_ec;+ descriptor_ops::close(impl.descriptor_, impl.state_, ignored_ec);+ io_uring_service_.cleanup_io_object(impl.io_object_data_);+ }+}++asio::error_code io_uring_descriptor_service::assign(+ io_uring_descriptor_service::implementation_type& impl,+ const native_handle_type& native_descriptor, asio::error_code& ec)+{+ if (is_open(impl))+ {+ ec = asio::error::already_open;+ ASIO_ERROR_LOCATION(ec);+ return ec;+ }++ io_uring_service_.register_io_object(impl.io_object_data_);++ impl.descriptor_ = native_descriptor;+ impl.state_ = descriptor_ops::possible_dup;+ ec = success_ec_;+ return ec;+}++asio::error_code io_uring_descriptor_service::close(+ io_uring_descriptor_service::implementation_type& impl,+ asio::error_code& ec)+{+ if (is_open(impl))+ {+ ASIO_HANDLER_OPERATION((io_uring_service_.context(),+ "descriptor", &impl, impl.descriptor_, "close"));++ io_uring_service_.deregister_io_object(impl.io_object_data_);+ descriptor_ops::close(impl.descriptor_, impl.state_, ec);+ io_uring_service_.cleanup_io_object(impl.io_object_data_);+ }+ else+ {+ ec = success_ec_;+ }++ // The descriptor is closed by the OS even if close() returns an error.+ //+ // (Actually, POSIX says the state of the descriptor is unspecified. On+ // Linux the descriptor is apparently closed anyway; e.g. see+ // http://lkml.org/lkml/2005/9/10/129+ construct(impl);++ ASIO_ERROR_LOCATION(ec);+ return ec;+}++io_uring_descriptor_service::native_handle_type+io_uring_descriptor_service::release(+ io_uring_descriptor_service::implementation_type& impl)+{+ native_handle_type descriptor = impl.descriptor_;++ if (is_open(impl))+ {+ ASIO_HANDLER_OPERATION((io_uring_service_.context(),+ "descriptor", &impl, impl.descriptor_, "release"));++ io_uring_service_.deregister_io_object(impl.io_object_data_);+ io_uring_service_.cleanup_io_object(impl.io_object_data_);+ construct(impl);+ }++ return descriptor;+}++asio::error_code io_uring_descriptor_service::cancel(+ io_uring_descriptor_service::implementation_type& impl,+ asio::error_code& ec)+{+ if (!is_open(impl))+ {+ ec = asio::error::bad_descriptor;+ ASIO_ERROR_LOCATION(ec);+ return ec;+ }++ ASIO_HANDLER_OPERATION((io_uring_service_.context(),+ "descriptor", &impl, impl.descriptor_, "cancel"));++ io_uring_service_.cancel_ops(impl.io_object_data_);+ ec = success_ec_;+ return ec;+}++void io_uring_descriptor_service::start_op(+ io_uring_descriptor_service::implementation_type& impl,+ int op_type, io_uring_operation* op, bool is_continuation, bool noop)+{+ if (!noop)+ {+ io_uring_service_.start_op(op_type,+ impl.io_object_data_, op, is_continuation);+ }+ else+ {+ io_uring_service_.post_immediate_completion(op, is_continuation);+ }+}++} // namespace detail+} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // defined(ASIO_HAS_IO_URING)++#endif // ASIO_DETAIL_IMPL_IO_URING_DESCRIPTOR_SERVICE_IPP
+ link/modules/asio-standalone/asio/include/asio/detail/impl/io_uring_file_service.ipp view
@@ -0,0 +1,140 @@+//+// detail/impl/io_uring_file_service.ipp+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com)+//+// Distributed under the Boost Software License, Version 1.0. (See accompanying+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)+//++#ifndef ASIO_DETAIL_IMPL_IO_URING_FILE_SERVICE_IPP+#define ASIO_DETAIL_IMPL_IO_URING_FILE_SERVICE_IPP++#if defined(_MSC_VER) && (_MSC_VER >= 1200)+# pragma once+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)++#include "asio/detail/config.hpp"++#if defined(ASIO_HAS_FILE) \+ && defined(ASIO_HAS_IO_URING)++#include <cstring>+#include <sys/stat.h>+#include "asio/detail/io_uring_file_service.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {+namespace detail {++io_uring_file_service::io_uring_file_service(+ execution_context& context)+ : execution_context_service_base<io_uring_file_service>(context),+ descriptor_service_(context)+{+}++void io_uring_file_service::shutdown()+{+ descriptor_service_.shutdown();+}++asio::error_code io_uring_file_service::open(+ io_uring_file_service::implementation_type& impl,+ const char* path, file_base::flags open_flags,+ asio::error_code& ec)+{+ if (is_open(impl))+ {+ ec = asio::error::already_open;+ ASIO_ERROR_LOCATION(ec);+ return ec;+ }++ descriptor_ops::state_type state = 0;+ int fd = descriptor_ops::open(path, static_cast<int>(open_flags), 0777, ec);+ if (fd < 0)+ {+ ASIO_ERROR_LOCATION(ec);+ return ec;+ }++ // We're done. Take ownership of the serial port descriptor.+ if (descriptor_service_.assign(impl, fd, ec))+ {+ asio::error_code ignored_ec;+ descriptor_ops::close(fd, state, ignored_ec);+ }++ (void)::posix_fadvise(native_handle(impl), 0, 0,+ impl.is_stream_ ? POSIX_FADV_SEQUENTIAL : POSIX_FADV_RANDOM);++ ASIO_ERROR_LOCATION(ec);+ return ec;+}++uint64_t io_uring_file_service::size(+ const io_uring_file_service::implementation_type& impl,+ asio::error_code& ec) const+{+ struct stat s;+ int result = ::fstat(native_handle(impl), &s);+ descriptor_ops::get_last_error(ec, result != 0);+ ASIO_ERROR_LOCATION(ec);+ return !ec ? s.st_size : 0;+}++asio::error_code io_uring_file_service::resize(+ io_uring_file_service::implementation_type& impl,+ uint64_t n, asio::error_code& ec)+{+ int result = ::ftruncate(native_handle(impl), n);+ descriptor_ops::get_last_error(ec, result != 0);+ ASIO_ERROR_LOCATION(ec);+ return ec;+}++asio::error_code io_uring_file_service::sync_all(+ io_uring_file_service::implementation_type& impl,+ asio::error_code& ec)+{+ int result = ::fsync(native_handle(impl));+ descriptor_ops::get_last_error(ec, result != 0);+ return ec;+}++asio::error_code io_uring_file_service::sync_data(+ io_uring_file_service::implementation_type& impl,+ asio::error_code& ec)+{+#if defined(_POSIX_SYNCHRONIZED_IO)+ int result = ::fdatasync(native_handle(impl));+#else // defined(_POSIX_SYNCHRONIZED_IO)+ int result = ::fsync(native_handle(impl));+#endif // defined(_POSIX_SYNCHRONIZED_IO)+ descriptor_ops::get_last_error(ec, result != 0);+ ASIO_ERROR_LOCATION(ec);+ return ec;+}++uint64_t io_uring_file_service::seek(+ io_uring_file_service::implementation_type& impl, int64_t offset,+ file_base::seek_basis whence, asio::error_code& ec)+{+ int64_t result = ::lseek(native_handle(impl), offset, whence);+ descriptor_ops::get_last_error(ec, result < 0);+ ASIO_ERROR_LOCATION(ec);+ return !ec ? static_cast<uint64_t>(result) : 0;+}++} // namespace detail+} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // defined(ASIO_HAS_FILE)+ // && defined(ASIO_HAS_IO_URING)++#endif // ASIO_DETAIL_IMPL_IO_URING_FILE_SERVICE_IPP
+ link/modules/asio-standalone/asio/include/asio/detail/impl/io_uring_service.hpp view
@@ -0,0 +1,112 @@+//+// detail/impl/io_uring_service.hpp+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com)+//+// Distributed under the Boost Software License, Version 1.0. (See accompanying+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)+//++#ifndef ASIO_DETAIL_IMPL_IO_URING_SERVICE_HPP+#define ASIO_DETAIL_IMPL_IO_URING_SERVICE_HPP++#if defined(_MSC_VER) && (_MSC_VER >= 1200)+# pragma once+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)++#if defined(ASIO_HAS_IO_URING)++#include "asio/detail/scheduler.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {+namespace detail {++inline void io_uring_service::post_immediate_completion(+ operation* op, bool is_continuation)+{+ scheduler_.post_immediate_completion(op, is_continuation);+}++template <typename Time_Traits>+void io_uring_service::add_timer_queue(timer_queue<Time_Traits>& queue)+{+ do_add_timer_queue(queue);+}++template <typename Time_Traits>+void io_uring_service::remove_timer_queue(timer_queue<Time_Traits>& queue)+{+ do_remove_timer_queue(queue);+}++template <typename Time_Traits>+void io_uring_service::schedule_timer(timer_queue<Time_Traits>& queue,+ const typename Time_Traits::time_type& time,+ typename timer_queue<Time_Traits>::per_timer_data& timer, wait_op* op)+{+ mutex::scoped_lock lock(mutex_);++ if (shutdown_)+ {+ scheduler_.post_immediate_completion(op, false);+ return;+ }++ bool earliest = queue.enqueue_timer(time, timer, op);+ scheduler_.work_started();+ if (earliest)+ {+ update_timeout();+ post_submit_sqes_op(lock);+ }+}++template <typename Time_Traits>+std::size_t io_uring_service::cancel_timer(timer_queue<Time_Traits>& queue,+ typename timer_queue<Time_Traits>::per_timer_data& timer,+ std::size_t max_cancelled)+{+ mutex::scoped_lock lock(mutex_);+ op_queue<operation> ops;+ std::size_t n = queue.cancel_timer(timer, ops, max_cancelled);+ lock.unlock();+ scheduler_.post_deferred_completions(ops);+ return n;+}++template <typename Time_Traits>+void io_uring_service::cancel_timer_by_key(timer_queue<Time_Traits>& queue,+ typename timer_queue<Time_Traits>::per_timer_data* timer,+ void* cancellation_key)+{+ mutex::scoped_lock lock(mutex_);+ op_queue<operation> ops;+ queue.cancel_timer_by_key(timer, ops, cancellation_key);+ lock.unlock();+ scheduler_.post_deferred_completions(ops);+}++template <typename Time_Traits>+void io_uring_service::move_timer(timer_queue<Time_Traits>& queue,+ typename timer_queue<Time_Traits>::per_timer_data& target,+ typename timer_queue<Time_Traits>::per_timer_data& source)+{+ mutex::scoped_lock lock(mutex_);+ op_queue<operation> ops;+ queue.cancel_timer(target, ops);+ queue.move_timer(target, source);+ lock.unlock();+ scheduler_.post_deferred_completions(ops);+}++} // namespace detail+} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // defined(ASIO_HAS_IO_URING)++#endif // ASIO_DETAIL_IMPL_IO_URING_SERVICE_HPP
+ link/modules/asio-standalone/asio/include/asio/detail/impl/io_uring_service.ipp view
@@ -0,0 +1,909 @@+//+// detail/impl/io_uring_service.ipp+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com)+//+// Distributed under the Boost Software License, Version 1.0. (See accompanying+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)+//++#ifndef ASIO_DETAIL_IMPL_IO_URING_SERVICE_IPP+#define ASIO_DETAIL_IMPL_IO_URING_SERVICE_IPP++#if defined(_MSC_VER) && (_MSC_VER >= 1200)+# pragma once+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)++#include "asio/detail/config.hpp"++#if defined(ASIO_HAS_IO_URING)++#include <cstddef>+#include <sys/eventfd.h>+#include "asio/detail/io_uring_service.hpp"+#include "asio/detail/reactor_op.hpp"+#include "asio/detail/scheduler.hpp"+#include "asio/detail/throw_error.hpp"+#include "asio/error.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {+namespace detail {++io_uring_service::io_uring_service(asio::execution_context& ctx)+ : execution_context_service_base<io_uring_service>(ctx),+ scheduler_(use_service<scheduler>(ctx)),+ mutex_(ASIO_CONCURRENCY_HINT_IS_LOCKING(+ REACTOR_REGISTRATION, scheduler_.concurrency_hint())),+ outstanding_work_(0),+ submit_sqes_op_(this),+ pending_sqes_(0),+ pending_submit_sqes_op_(false),+ shutdown_(false),+ timeout_(),+ registration_mutex_(mutex_.enabled()),+ reactor_(use_service<reactor>(ctx)),+ reactor_data_(),+ event_fd_(-1)+{+ reactor_.init_task();+ init_ring();+ register_with_reactor();+}++io_uring_service::~io_uring_service()+{+ if (ring_.ring_fd != -1)+ ::io_uring_queue_exit(&ring_);+ if (event_fd_ != -1)+ ::close(event_fd_);+}++void io_uring_service::shutdown()+{+ mutex::scoped_lock lock(mutex_);+ shutdown_ = true;+ lock.unlock();++ op_queue<operation> ops;++ // Cancel all outstanding operations.+ while (io_object* io_obj = registered_io_objects_.first())+ {+ for (int i = 0; i < max_ops; ++i)+ {+ if (!io_obj->queues_[i].op_queue_.empty())+ {+ ops.push(io_obj->queues_[i].op_queue_);+ if (::io_uring_sqe* sqe = get_sqe())+ ::io_uring_prep_cancel(sqe, &io_obj->queues_[i], 0);+ }+ }+ io_obj->shutdown_ = true;+ registered_io_objects_.free(io_obj);+ }++ // Cancel the timeout operation.+ if (::io_uring_sqe* sqe = get_sqe())+ ::io_uring_prep_cancel(sqe, &timeout_, IOSQE_IO_DRAIN);+ submit_sqes();++ // Wait for all completions to come back.+ for (; outstanding_work_ > 0; --outstanding_work_)+ {+ ::io_uring_cqe* cqe = 0;+ if (::io_uring_wait_cqe(&ring_, &cqe) != 0)+ break;+ }++ timer_queues_.get_all_timers(ops);++ scheduler_.abandon_operations(ops);+}++void io_uring_service::notify_fork(+ asio::execution_context::fork_event fork_ev)+{+ switch (fork_ev)+ {+ case asio::execution_context::fork_prepare:+ {+ // Cancel all outstanding operations. They will be restarted+ // after the fork completes.+ mutex::scoped_lock registration_lock(registration_mutex_);+ for (io_object* io_obj = registered_io_objects_.first();+ io_obj != 0; io_obj = io_obj->next_)+ {+ mutex::scoped_lock io_object_lock(io_obj->mutex_);+ for (int i = 0; i < max_ops; ++i)+ {+ if (!io_obj->queues_[i].op_queue_.empty()+ && !io_obj->queues_[i].cancel_requested_)+ {+ mutex::scoped_lock lock(mutex_);+ if (::io_uring_sqe* sqe = get_sqe())+ ::io_uring_prep_cancel(sqe, &io_obj->queues_[i], 0);+ }+ }+ }++ // Cancel the timeout operation.+ {+ mutex::scoped_lock lock(mutex_);+ if (::io_uring_sqe* sqe = get_sqe())+ ::io_uring_prep_cancel(sqe, &timeout_, IOSQE_IO_DRAIN);+ submit_sqes();+ }++ // Wait for all completions to come back, and post all completed I/O+ // queues to the scheduler. Note that some operations may have already+ // completed, or were explicitly cancelled. All others will be+ // automatically restarted.+ op_queue<operation> ops;+ for (; outstanding_work_ > 0; --outstanding_work_)+ {+ ::io_uring_cqe* cqe = 0;+ if (::io_uring_wait_cqe(&ring_, &cqe) != 0)+ break;+ if (void* ptr = ::io_uring_cqe_get_data(cqe))+ {+ if (ptr != this && ptr != &timer_queues_ && ptr != &timeout_)+ {+ io_queue* io_q = static_cast<io_queue*>(ptr);+ io_q->set_result(cqe->res);+ ops.push(io_q);+ }+ }+ }+ scheduler_.post_deferred_completions(ops);++ // Restart and eventfd operation.+ register_with_reactor();+ }+ break;++ case asio::execution_context::fork_parent:+ // Restart the timeout and eventfd operations.+ update_timeout();+ register_with_reactor();+ break;++ case asio::execution_context::fork_child:+ {+ // The child process gets a new io_uring instance.+ ::io_uring_queue_exit(&ring_);+ init_ring();+ register_with_reactor();+ }+ break;+ default:+ break;+ }+}++void io_uring_service::init_task()+{+ scheduler_.init_task();+}++void io_uring_service::register_io_object(+ io_uring_service::per_io_object_data& io_obj)+{+ io_obj = allocate_io_object();++ mutex::scoped_lock io_object_lock(io_obj->mutex_);++ io_obj->service_ = this;+ io_obj->shutdown_ = false;+ for (int i = 0; i < max_ops; ++i)+ {+ io_obj->queues_[i].io_object_ = io_obj;+ io_obj->queues_[i].cancel_requested_ = false;+ }+}++void io_uring_service::register_internal_io_object(+ io_uring_service::per_io_object_data& io_obj,+ int op_type, io_uring_operation* op)+{+ io_obj = allocate_io_object();++ mutex::scoped_lock io_object_lock(io_obj->mutex_);++ io_obj->service_ = this;+ io_obj->shutdown_ = false;+ for (int i = 0; i < max_ops; ++i)+ {+ io_obj->queues_[i].io_object_ = io_obj;+ io_obj->queues_[i].cancel_requested_ = false;+ }++ io_obj->queues_[op_type].op_queue_.push(op);+ io_object_lock.unlock();+ mutex::scoped_lock lock(mutex_);+ if (::io_uring_sqe* sqe = get_sqe())+ {+ op->prepare(sqe);+ ::io_uring_sqe_set_data(sqe, &io_obj->queues_[op_type]);+ post_submit_sqes_op(lock);+ }+ else+ {+ asio::error_code ec(ENOBUFS,+ asio::error::get_system_category());+ asio::detail::throw_error(ec, "io_uring_get_sqe");+ }+}++void io_uring_service::register_buffers(const ::iovec* v, unsigned n)+{+ int result = ::io_uring_register_buffers(&ring_, v, n);+ if (result < 0)+ {+ asio::error_code ec(-result,+ asio::error::get_system_category());+ asio::detail::throw_error(ec, "io_uring_register_buffers");+ }+}++void io_uring_service::unregister_buffers()+{+ (void)::io_uring_unregister_buffers(&ring_);+}++void io_uring_service::start_op(int op_type,+ io_uring_service::per_io_object_data& io_obj,+ io_uring_operation* op, bool is_continuation)+{+ if (!io_obj)+ {+ op->ec_ = asio::error::bad_descriptor;+ post_immediate_completion(op, is_continuation);+ return;+ }++ mutex::scoped_lock io_object_lock(io_obj->mutex_);++ if (io_obj->shutdown_)+ {+ io_object_lock.unlock();+ post_immediate_completion(op, is_continuation);+ return;+ }++ if (io_obj->queues_[op_type].op_queue_.empty())+ {+ if (op->perform(false))+ {+ io_object_lock.unlock();+ scheduler_.post_immediate_completion(op, is_continuation);+ }+ else+ {+ io_obj->queues_[op_type].op_queue_.push(op);+ io_object_lock.unlock();+ mutex::scoped_lock lock(mutex_);+ if (::io_uring_sqe* sqe = get_sqe())+ {+ op->prepare(sqe);+ ::io_uring_sqe_set_data(sqe, &io_obj->queues_[op_type]);+ scheduler_.work_started();+ post_submit_sqes_op(lock);+ }+ else+ {+ lock.unlock();+ io_obj->queues_[op_type].set_result(-ENOBUFS);+ post_immediate_completion(&io_obj->queues_[op_type], is_continuation);+ }+ }+ }+ else+ {+ io_obj->queues_[op_type].op_queue_.push(op);+ scheduler_.work_started();+ }+}++void io_uring_service::cancel_ops(io_uring_service::per_io_object_data& io_obj)+{+ if (!io_obj)+ return;++ mutex::scoped_lock io_object_lock(io_obj->mutex_);+ op_queue<operation> ops;+ do_cancel_ops(io_obj, ops);+ io_object_lock.unlock();+ scheduler_.post_deferred_completions(ops);+}++void io_uring_service::cancel_ops_by_key(+ io_uring_service::per_io_object_data& io_obj,+ int op_type, void* cancellation_key)+{+ if (!io_obj)+ return;++ mutex::scoped_lock io_object_lock(io_obj->mutex_);++ bool first = true;+ op_queue<operation> ops;+ op_queue<io_uring_operation> other_ops;+ while (io_uring_operation* op = io_obj->queues_[op_type].op_queue_.front())+ {+ io_obj->queues_[op_type].op_queue_.pop();+ if (op->cancellation_key_ == cancellation_key)+ {+ if (first)+ {+ other_ops.push(op);+ if (!io_obj->queues_[op_type].cancel_requested_)+ {+ io_obj->queues_[op_type].cancel_requested_ = true;+ mutex::scoped_lock lock(mutex_);+ if (::io_uring_sqe* sqe = get_sqe())+ {+ ::io_uring_prep_cancel(sqe, &io_obj->queues_[op_type], 0);+ submit_sqes();+ }+ }+ }+ else+ {+ op->ec_ = asio::error::operation_aborted;+ ops.push(op);+ }+ }+ else+ other_ops.push(op);+ first = false;+ }+ io_obj->queues_[op_type].op_queue_.push(other_ops);++ io_object_lock.unlock();++ scheduler_.post_deferred_completions(ops);+}++void io_uring_service::deregister_io_object(+ io_uring_service::per_io_object_data& io_obj)+{+ if (!io_obj)+ return;++ mutex::scoped_lock io_object_lock(io_obj->mutex_);+ if (!io_obj->shutdown_)+ {+ op_queue<operation> ops;+ bool pending_cancelled_ops = do_cancel_ops(io_obj, ops);+ io_obj->shutdown_ = true;+ io_object_lock.unlock();+ scheduler_.post_deferred_completions(ops);+ if (pending_cancelled_ops)+ {+ // There are still pending operations. Prevent cleanup_io_object from+ // freeing the I/O object and let the last operation to complete free it.+ io_obj = 0;+ }+ else+ {+ // Leave io_obj set so that it will be freed by the subsequent call to+ // cleanup_io_object.+ }+ }+ else+ {+ // We are shutting down, so prevent cleanup_io_object from freeing+ // the I/O object and let the destructor free it instead.+ io_obj = 0;+ }+}++void io_uring_service::cleanup_io_object(+ io_uring_service::per_io_object_data& io_obj)+{+ if (io_obj)+ {+ free_io_object(io_obj);+ io_obj = 0;+ }+}++void io_uring_service::run(long usec, op_queue<operation>& ops)+{+ __kernel_timespec ts;+ int local_ops = 0;++ if (usec > 0)+ {+ ts.tv_sec = usec / 1000000;+ ts.tv_nsec = (usec % 1000000) * 1000;+ mutex::scoped_lock lock(mutex_);+ if (::io_uring_sqe* sqe = get_sqe())+ {+ ++local_ops;+ ::io_uring_prep_timeout(sqe, &ts, 0, 0);+ ::io_uring_sqe_set_data(sqe, &ts);+ submit_sqes();+ }+ }++ ::io_uring_cqe* cqe = 0;+ int result = (usec == 0)+ ? ::io_uring_peek_cqe(&ring_, &cqe)+ : ::io_uring_wait_cqe(&ring_, &cqe);++ if (result == 0 && usec > 0)+ {+ if (::io_uring_cqe_get_data(cqe) != &ts)+ {+ mutex::scoped_lock lock(mutex_);+ if (::io_uring_sqe* sqe = get_sqe())+ {+ ++local_ops;+ ::io_uring_prep_timeout_remove(sqe, reinterpret_cast<__u64>(&ts), 0);+ submit_sqes();+ }+ }+ }++ bool check_timers = false;+ int count = 0;+ while (result == 0)+ {+ if (void* ptr = ::io_uring_cqe_get_data(cqe))+ {+ if (ptr == this)+ {+ // The io_uring service was interrupted.+ }+ else if (ptr == &timer_queues_)+ {+ check_timers = true;+ }+ else if (ptr == &timeout_)+ {+ check_timers = true;+ timeout_.tv_sec = 0;+ timeout_.tv_nsec = 0;+ }+ else if (ptr == &ts)+ {+ --local_ops;+ }+ else+ {+ io_queue* io_q = static_cast<io_queue*>(ptr);+ io_q->set_result(cqe->res);+ ops.push(io_q);+ }+ }+ ::io_uring_cqe_seen(&ring_, cqe);+ result = (++count < complete_batch_size || local_ops > 0)+ ? ::io_uring_peek_cqe(&ring_, &cqe) : -EAGAIN;+ }++ decrement(outstanding_work_, count);++ if (check_timers)+ {+ mutex::scoped_lock lock(mutex_);+ timer_queues_.get_ready_timers(ops);+ if (timeout_.tv_sec == 0 && timeout_.tv_nsec == 0)+ {+ timeout_ = get_timeout();+ if (::io_uring_sqe* sqe = get_sqe())+ {+ ::io_uring_prep_timeout(sqe, &timeout_, 0, 0);+ ::io_uring_sqe_set_data(sqe, &timeout_);+ push_submit_sqes_op(ops);+ }+ }+ }+}++void io_uring_service::interrupt()+{+ mutex::scoped_lock lock(mutex_);+ if (::io_uring_sqe* sqe = get_sqe())+ {+ ::io_uring_prep_nop(sqe);+ ::io_uring_sqe_set_data(sqe, this);+ }+ submit_sqes();+}++void io_uring_service::init_ring()+{+ int result = ::io_uring_queue_init(ring_size, &ring_, 0);+ if (result < 0)+ {+ ring_.ring_fd = -1;+ asio::error_code ec(-result,+ asio::error::get_system_category());+ asio::detail::throw_error(ec, "io_uring_queue_init");+ }++#if !defined(ASIO_HAS_IO_URING_AS_DEFAULT)+ event_fd_ = ::eventfd(0, EFD_CLOEXEC | EFD_NONBLOCK);+ if (event_fd_ < 0)+ {+ asio::error_code ec(-result,+ asio::error::get_system_category());+ ::io_uring_queue_exit(&ring_);+ asio::detail::throw_error(ec, "eventfd");+ }++ result = ::io_uring_register_eventfd(&ring_, event_fd_);+ if (result < 0)+ {+ ::close(event_fd_);+ ::io_uring_queue_exit(&ring_);+ asio::error_code ec(-result,+ asio::error::get_system_category());+ asio::detail::throw_error(ec, "io_uring_queue_init");+ }+#endif // !defined(ASIO_HAS_IO_URING_AS_DEFAULT)+}++#if !defined(ASIO_HAS_IO_URING_AS_DEFAULT)+class io_uring_service::event_fd_read_op :+ public reactor_op+{+public:+ event_fd_read_op(io_uring_service* s)+ : reactor_op(asio::error_code(),+ &event_fd_read_op::do_perform, event_fd_read_op::do_complete),+ service_(s)+ {+ }++ static status do_perform(reactor_op* base)+ {+ event_fd_read_op* o(static_cast<event_fd_read_op*>(base));++ for (;;)+ {+ // Only perform one read. The kernel maintains an atomic counter.+ uint64_t counter(0);+ errno = 0;+ int bytes_read = ::read(o->service_->event_fd_,+ &counter, sizeof(uint64_t));+ if (bytes_read < 0 && errno == EINTR)+ continue;+ break;+ }++ op_queue<operation> ops;+ o->service_->run(0, ops);+ o->service_->scheduler_.post_deferred_completions(ops);++ return not_done;+ }++ static void do_complete(void* /*owner*/, operation* base,+ const asio::error_code& /*ec*/,+ std::size_t /*bytes_transferred*/)+ {+ event_fd_read_op* o(static_cast<event_fd_read_op*>(base));+ delete o;+ }++private:+ io_uring_service* service_;+};+#endif // !defined(ASIO_HAS_IO_URING_AS_DEFAULT)++void io_uring_service::register_with_reactor()+{+#if !defined(ASIO_HAS_IO_URING_AS_DEFAULT)+ reactor_.register_internal_descriptor(reactor::read_op,+ event_fd_, reactor_data_, new event_fd_read_op(this));+#endif // !defined(ASIO_HAS_IO_URING_AS_DEFAULT)+}++io_uring_service::io_object* io_uring_service::allocate_io_object()+{+ mutex::scoped_lock registration_lock(registration_mutex_);+ return registered_io_objects_.alloc(+ ASIO_CONCURRENCY_HINT_IS_LOCKING(+ REACTOR_IO, scheduler_.concurrency_hint()));+}++void io_uring_service::free_io_object(io_uring_service::io_object* io_obj)+{+ mutex::scoped_lock registration_lock(registration_mutex_);+ registered_io_objects_.free(io_obj);+}++bool io_uring_service::do_cancel_ops(+ per_io_object_data& io_obj, op_queue<operation>& ops)+{+ bool cancel_op = false;++ for (int i = 0; i < max_ops; ++i)+ {+ if (io_uring_operation* first_op = io_obj->queues_[i].op_queue_.front())+ {+ cancel_op = true;+ io_obj->queues_[i].op_queue_.pop();+ while (io_uring_operation* op = io_obj->queues_[i].op_queue_.front())+ {+ op->ec_ = asio::error::operation_aborted;+ io_obj->queues_[i].op_queue_.pop();+ ops.push(op);+ }+ io_obj->queues_[i].op_queue_.push(first_op);+ }+ }++ if (cancel_op)+ {+ mutex::scoped_lock lock(mutex_);+ for (int i = 0; i < max_ops; ++i)+ {+ if (!io_obj->queues_[i].op_queue_.empty()+ && !io_obj->queues_[i].cancel_requested_)+ {+ io_obj->queues_[i].cancel_requested_ = true;+ if (::io_uring_sqe* sqe = get_sqe())+ ::io_uring_prep_cancel(sqe, &io_obj->queues_[i], 0);+ }+ }+ submit_sqes();+ }++ return cancel_op;+}++void io_uring_service::do_add_timer_queue(timer_queue_base& queue)+{+ mutex::scoped_lock lock(mutex_);+ timer_queues_.insert(&queue);+}++void io_uring_service::do_remove_timer_queue(timer_queue_base& queue)+{+ mutex::scoped_lock lock(mutex_);+ timer_queues_.erase(&queue);+}++void io_uring_service::update_timeout()+{+ if (::io_uring_sqe* sqe = get_sqe())+ {+ ::io_uring_prep_timeout_remove(sqe, reinterpret_cast<__u64>(&timeout_), 0);+ ::io_uring_sqe_set_data(sqe, &timer_queues_);+ }+}++__kernel_timespec io_uring_service::get_timeout() const+{+ __kernel_timespec ts;+ long usec = timer_queues_.wait_duration_usec(5 * 60 * 1000 * 1000);+ ts.tv_sec = usec / 1000000;+ ts.tv_nsec = usec ? (usec % 1000000) * 1000 : 1;+ return ts;+}++::io_uring_sqe* io_uring_service::get_sqe()+{+ ::io_uring_sqe* sqe = ::io_uring_get_sqe(&ring_);+ if (!sqe)+ {+ submit_sqes();+ sqe = ::io_uring_get_sqe(&ring_);+ }+ if (sqe)+ {+ ::io_uring_sqe_set_data(sqe, 0);+ ++pending_sqes_;+ }+ return sqe;+}++void io_uring_service::submit_sqes()+{+ if (pending_sqes_ != 0)+ {+ int result = ::io_uring_submit(&ring_);+ if (result > 0)+ {+ pending_sqes_ -= result;+ increment(outstanding_work_, result);+ }+ }+}++void io_uring_service::post_submit_sqes_op(mutex::scoped_lock& lock)+{+ if (pending_sqes_ >= submit_batch_size)+ {+ submit_sqes();+ }+ else if (pending_sqes_ != 0 && !pending_submit_sqes_op_)+ {+ pending_submit_sqes_op_ = true;+ lock.unlock();+ scheduler_.post_immediate_completion(&submit_sqes_op_, false);+ }+}++void io_uring_service::push_submit_sqes_op(op_queue<operation>& ops)+{+ if (pending_sqes_ != 0 && !pending_submit_sqes_op_)+ {+ pending_submit_sqes_op_ = true;+ ops.push(&submit_sqes_op_);+ scheduler_.compensating_work_started();+ }+}++io_uring_service::submit_sqes_op::submit_sqes_op(io_uring_service* s)+ : operation(&io_uring_service::submit_sqes_op::do_complete),+ service_(s)+{+}++void io_uring_service::submit_sqes_op::do_complete(void* owner, operation* base,+ const asio::error_code& /*ec*/, std::size_t /*bytes_transferred*/)+{+ if (owner)+ {+ submit_sqes_op* o = static_cast<submit_sqes_op*>(base);+ mutex::scoped_lock lock(o->service_->mutex_);+ o->service_->submit_sqes();+ if (o->service_->pending_sqes_ != 0)+ o->service_->scheduler_.post_immediate_completion(o, true);+ else+ o->service_->pending_submit_sqes_op_ = false;+ }+}++io_uring_service::io_queue::io_queue()+ : operation(&io_uring_service::io_queue::do_complete)+{+}++struct io_uring_service::perform_io_cleanup_on_block_exit+{+ explicit perform_io_cleanup_on_block_exit(io_uring_service* s)+ : service_(s), io_object_to_free_(0), first_op_(0)+ {+ }++ ~perform_io_cleanup_on_block_exit()+ {+ if (io_object_to_free_)+ {+ mutex::scoped_lock lock(service_->mutex_);+ service_->free_io_object(io_object_to_free_);+ }++ if (first_op_)+ {+ // Post the remaining completed operations for invocation.+ if (!ops_.empty())+ service_->scheduler_.post_deferred_completions(ops_);++ // A user-initiated operation has completed, but there's no need to+ // explicitly call work_finished() here. Instead, we'll take advantage of+ // the fact that the scheduler will call work_finished() once we return.+ }+ else+ {+ // No user-initiated operations have completed, so we need to compensate+ // for the work_finished() call that the scheduler will make once this+ // operation returns.+ service_->scheduler_.compensating_work_started();+ }+ }++ io_uring_service* service_;+ io_object* io_object_to_free_;+ op_queue<operation> ops_;+ operation* first_op_;+};++operation* io_uring_service::io_queue::perform_io(int result)+{+ perform_io_cleanup_on_block_exit io_cleanup(io_object_->service_);+ mutex::scoped_lock io_object_lock(io_object_->mutex_);++ if (result != -ECANCELED || cancel_requested_)+ {+ if (io_uring_operation* op = op_queue_.front())+ {+ if (result < 0)+ {+ op->ec_.assign(-result, asio::error::get_system_category());+ op->bytes_transferred_ = 0;+ }+ else+ {+ op->ec_.assign(0, op->ec_.category());+ op->bytes_transferred_ = static_cast<std::size_t>(result);+ }+ }++ while (io_uring_operation* op = op_queue_.front())+ {+ if (op->perform(io_cleanup.ops_.empty()))+ {+ op_queue_.pop();+ io_cleanup.ops_.push(op);+ }+ else+ break;+ }+ }++ cancel_requested_ = false;++ if (!op_queue_.empty())+ {+ io_uring_service* service = io_object_->service_;+ mutex::scoped_lock lock(service->mutex_);+ if (::io_uring_sqe* sqe = service->get_sqe())+ {+ op_queue_.front()->prepare(sqe);+ ::io_uring_sqe_set_data(sqe, this);+ service->post_submit_sqes_op(lock);+ }+ else+ {+ lock.unlock();+ while (io_uring_operation* op = op_queue_.front())+ {+ op->ec_ = asio::error::no_buffer_space;+ op_queue_.pop();+ io_cleanup.ops_.push(op);+ }+ }+ }++ // The last operation to complete on a shut down object must free it.+ if (io_object_->shutdown_)+ {+ io_cleanup.io_object_to_free_ = io_object_;+ for (int i = 0; i < max_ops; ++i)+ if (!io_object_->queues_[i].op_queue_.empty())+ io_cleanup.io_object_to_free_ = 0;+ }++ // The first operation will be returned for completion now. The others will+ // be posted for later by the io_cleanup object's destructor.+ io_cleanup.first_op_ = io_cleanup.ops_.front();+ io_cleanup.ops_.pop();+ return io_cleanup.first_op_;+}++void io_uring_service::io_queue::do_complete(void* owner, operation* base,+ const asio::error_code& ec, std::size_t bytes_transferred)+{+ if (owner)+ {+ io_queue* io_q = static_cast<io_queue*>(base);+ int result = static_cast<int>(bytes_transferred);+ if (operation* op = io_q->perform_io(result))+ {+ op->complete(owner, ec, 0);+ }+ }+}++io_uring_service::io_object::io_object(bool locking)+ : mutex_(locking)+{+}++} // namespace detail+} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // defined(ASIO_HAS_IO_URING)++#endif // ASIO_DETAIL_IMPL_IO_URING_SERVICE_IPP
+ link/modules/asio-standalone/asio/include/asio/detail/impl/io_uring_socket_service_base.ipp view
@@ -0,0 +1,249 @@+//+// detail/io_uring_socket_service_base.ipp+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com)+//+// Distributed under the Boost Software License, Version 1.0. (See accompanying+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)+//++#ifndef ASIO_DETAIL_IMPL_IO_URING_SOCKET_SERVICE_BASE_IPP+#define ASIO_DETAIL_IMPL_IO_URING_SOCKET_SERVICE_BASE_IPP++#if defined(_MSC_VER) && (_MSC_VER >= 1200)+# pragma once+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)++#include "asio/detail/config.hpp"++#if defined(ASIO_HAS_IO_URING)++#include "asio/detail/io_uring_socket_service_base.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {+namespace detail {++io_uring_socket_service_base::io_uring_socket_service_base(+ execution_context& context)+ : io_uring_service_(asio::use_service<io_uring_service>(context))+{+ io_uring_service_.init_task();+}++void io_uring_socket_service_base::base_shutdown()+{+}++void io_uring_socket_service_base::construct(+ io_uring_socket_service_base::base_implementation_type& impl)+{+ impl.socket_ = invalid_socket;+ impl.state_ = 0;+ impl.io_object_data_ = 0;+}++void io_uring_socket_service_base::base_move_construct(+ io_uring_socket_service_base::base_implementation_type& impl,+ io_uring_socket_service_base::base_implementation_type& other_impl)+ ASIO_NOEXCEPT+{+ impl.socket_ = other_impl.socket_;+ other_impl.socket_ = invalid_socket;++ impl.state_ = other_impl.state_;+ other_impl.state_ = 0;++ impl.io_object_data_ = other_impl.io_object_data_;+ other_impl.io_object_data_ = 0;+}++void io_uring_socket_service_base::base_move_assign(+ io_uring_socket_service_base::base_implementation_type& impl,+ io_uring_socket_service_base& /*other_service*/,+ io_uring_socket_service_base::base_implementation_type& other_impl)+{+ destroy(impl);++ impl.socket_ = other_impl.socket_;+ other_impl.socket_ = invalid_socket;++ impl.state_ = other_impl.state_;+ other_impl.state_ = 0;++ impl.io_object_data_ = other_impl.io_object_data_;+ other_impl.io_object_data_ = 0;+}++void io_uring_socket_service_base::destroy(+ io_uring_socket_service_base::base_implementation_type& impl)+{+ if (impl.socket_ != invalid_socket)+ {+ ASIO_HANDLER_OPERATION((io_uring_service_.context(),+ "socket", &impl, impl.socket_, "close"));++ io_uring_service_.deregister_io_object(impl.io_object_data_);+ asio::error_code ignored_ec;+ socket_ops::close(impl.socket_, impl.state_, true, ignored_ec);+ io_uring_service_.cleanup_io_object(impl.io_object_data_);+ }+}++asio::error_code io_uring_socket_service_base::close(+ io_uring_socket_service_base::base_implementation_type& impl,+ asio::error_code& ec)+{+ if (is_open(impl))+ {+ ASIO_HANDLER_OPERATION((io_uring_service_.context(),+ "socket", &impl, impl.socket_, "close"));++ io_uring_service_.deregister_io_object(impl.io_object_data_);+ socket_ops::close(impl.socket_, impl.state_, false, ec);+ io_uring_service_.cleanup_io_object(impl.io_object_data_);+ }+ else+ {+ ec = success_ec_;+ }++ // The descriptor is closed by the OS even if close() returns an error.+ //+ // (Actually, POSIX says the state of the descriptor is unspecified. On+ // Linux the descriptor is apparently closed anyway; e.g. see+ // http://lkml.org/lkml/2005/9/10/129+ construct(impl);++ return ec;+}++socket_type io_uring_socket_service_base::release(+ io_uring_socket_service_base::base_implementation_type& impl,+ asio::error_code& ec)+{+ if (!is_open(impl))+ {+ ec = asio::error::bad_descriptor;+ return invalid_socket;+ }++ ASIO_HANDLER_OPERATION((io_uring_service_.context(),+ "socket", &impl, impl.socket_, "release"));++ io_uring_service_.deregister_io_object(impl.io_object_data_);+ io_uring_service_.cleanup_io_object(impl.io_object_data_);+ socket_type sock = impl.socket_;+ construct(impl);+ ec = success_ec_;+ return sock;+}++asio::error_code io_uring_socket_service_base::cancel(+ io_uring_socket_service_base::base_implementation_type& impl,+ asio::error_code& ec)+{+ if (!is_open(impl))+ {+ ec = asio::error::bad_descriptor;+ return ec;+ }++ ASIO_HANDLER_OPERATION((io_uring_service_.context(),+ "socket", &impl, impl.socket_, "cancel"));++ io_uring_service_.cancel_ops(impl.io_object_data_);+ ec = success_ec_;+ return ec;+}++asio::error_code io_uring_socket_service_base::do_open(+ io_uring_socket_service_base::base_implementation_type& impl,+ int af, int type, int protocol, asio::error_code& ec)+{+ if (is_open(impl))+ {+ ec = asio::error::already_open;+ return ec;+ }++ socket_holder sock(socket_ops::socket(af, type, protocol, ec));+ if (sock.get() == invalid_socket)+ return ec;++ io_uring_service_.register_io_object(impl.io_object_data_);++ impl.socket_ = sock.release();+ switch (type)+ {+ case SOCK_STREAM: impl.state_ = socket_ops::stream_oriented; break;+ case SOCK_DGRAM: impl.state_ = socket_ops::datagram_oriented; break;+ default: impl.state_ = 0; break;+ }+ ec = success_ec_;+ return ec;+}++asio::error_code io_uring_socket_service_base::do_assign(+ io_uring_socket_service_base::base_implementation_type& impl, int type,+ const io_uring_socket_service_base::native_handle_type& native_socket,+ asio::error_code& ec)+{+ if (is_open(impl))+ {+ ec = asio::error::already_open;+ return ec;+ }++ io_uring_service_.register_io_object(impl.io_object_data_);++ impl.socket_ = native_socket;+ switch (type)+ {+ case SOCK_STREAM: impl.state_ = socket_ops::stream_oriented; break;+ case SOCK_DGRAM: impl.state_ = socket_ops::datagram_oriented; break;+ default: impl.state_ = 0; break;+ }+ impl.state_ |= socket_ops::possible_dup;+ ec = success_ec_;+ return ec;+}++void io_uring_socket_service_base::start_op(+ io_uring_socket_service_base::base_implementation_type& impl,+ int op_type, io_uring_operation* op, bool is_continuation, bool noop)+{+ if (!noop)+ {+ io_uring_service_.start_op(op_type,+ impl.io_object_data_, op, is_continuation);+ }+ else+ {+ io_uring_service_.post_immediate_completion(op, is_continuation);+ }+}++void io_uring_socket_service_base::start_accept_op(+ io_uring_socket_service_base::base_implementation_type& impl,+ io_uring_operation* op, bool is_continuation, bool peer_is_open)+{+ if (!peer_is_open)+ start_op(impl, io_uring_service::read_op, op, is_continuation, false);+ else+ {+ op->ec_ = asio::error::already_open;+ io_uring_service_.post_immediate_completion(op, is_continuation);+ }+}++} // namespace detail+} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // defined(ASIO_HAS_IO_URING)++#endif // ASIO_DETAIL_IMPL_IO_URING_SOCKET_SERVICE_BASE_IPP
link/modules/asio-standalone/asio/include/asio/detail/impl/kqueue_reactor.hpp view
@@ -2,7 +2,7 @@ // detail/impl/kqueue_reactor.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // Copyright (c) 2005 Stefan Arentz (stefan at soze dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying@@ -20,11 +20,19 @@ #if defined(ASIO_HAS_KQUEUE) +#include "asio/detail/scheduler.hpp"+ #include "asio/detail/push_options.hpp" namespace asio { namespace detail { +inline void kqueue_reactor::post_immediate_completion(+ operation* op, bool is_continuation) const+{+ scheduler_.post_immediate_completion(op, is_continuation);+}+ template <typename Time_Traits> void kqueue_reactor::add_timer_queue(timer_queue<Time_Traits>& queue) {@@ -68,6 +76,18 @@ lock.unlock(); scheduler_.post_deferred_completions(ops); return n;+}++template <typename Time_Traits>+void kqueue_reactor::cancel_timer_by_key(timer_queue<Time_Traits>& queue,+ typename timer_queue<Time_Traits>::per_timer_data* timer,+ void* cancellation_key)+{+ mutex::scoped_lock lock(mutex_);+ op_queue<operation> ops;+ queue.cancel_timer_by_key(timer, ops, cancellation_key);+ lock.unlock();+ scheduler_.post_deferred_completions(ops); } template <typename Time_Traits>
link/modules/asio-standalone/asio/include/asio/detail/impl/kqueue_reactor.ipp view
@@ -2,7 +2,7 @@ // detail/impl/kqueue_reactor.ipp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // Copyright (c) 2005 Stefan Arentz (stefan at soze dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying@@ -190,14 +190,23 @@ source_descriptor_data = 0; } +void kqueue_reactor::call_post_immediate_completion(+ operation* op, bool is_continuation, const void* self)+{+ static_cast<const kqueue_reactor*>(self)->post_immediate_completion(+ op, is_continuation);+}+ void kqueue_reactor::start_op(int op_type, socket_type descriptor, kqueue_reactor::per_descriptor_data& descriptor_data, reactor_op* op,- bool is_continuation, bool allow_speculative)+ bool is_continuation, bool allow_speculative,+ void (*on_immediate)(operation*, bool, const void*),+ const void* immediate_arg) { if (!descriptor_data) { op->ec_ = asio::error::bad_descriptor;- post_immediate_completion(op, is_continuation);+ on_immediate(op, is_continuation, immediate_arg); return; } @@ -205,7 +214,7 @@ if (descriptor_data->shutdown_) {- post_immediate_completion(op, is_continuation);+ on_immediate(op, is_continuation, immediate_arg); return; } @@ -220,7 +229,7 @@ if (op->perform()) { descriptor_lock.unlock();- scheduler_.post_immediate_completion(op, is_continuation);+ on_immediate(op, is_continuation, immediate_arg); return; } @@ -239,7 +248,7 @@ { op->ec_ = asio::error_code(errno, asio::error::get_system_category());- scheduler_.post_immediate_completion(op, is_continuation);+ on_immediate(op, is_continuation, immediate_arg); return; } }@@ -280,6 +289,35 @@ ops.push(op); } }++ descriptor_lock.unlock();++ scheduler_.post_deferred_completions(ops);+}++void kqueue_reactor::cancel_ops_by_key(socket_type,+ kqueue_reactor::per_descriptor_data& descriptor_data,+ int op_type, void* cancellation_key)+{+ if (!descriptor_data)+ return;++ mutex::scoped_lock descriptor_lock(descriptor_data->mutex_);++ op_queue<operation> ops;+ op_queue<reactor_op> other_ops;+ while (reactor_op* op = descriptor_data->op_queue_[op_type].front())+ {+ descriptor_data->op_queue_[op_type].pop();+ if (op->cancellation_key_ == cancellation_key)+ {+ op->ec_ = asio::error::operation_aborted;+ ops.push(op);+ }+ else+ other_ops.push(op);+ }+ descriptor_data->op_queue_[op_type].push(other_ops); descriptor_lock.unlock();
link/modules/asio-standalone/asio/include/asio/detail/impl/null_event.ipp view
@@ -2,7 +2,7 @@ // detail/impl/null_event.ipp // ~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/detail/impl/pipe_select_interrupter.ipp view
@@ -2,7 +2,7 @@ // detail/impl/pipe_select_interrupter.ipp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/detail/impl/posix_event.ipp view
@@ -2,7 +2,7 @@ // detail/impl/posix_event.ipp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -37,10 +37,14 @@ #else // (defined(__MACH__) && defined(__APPLE__)) // || (defined(__ANDROID__) && (__ANDROID_API__ < 21)) ::pthread_condattr_t attr;- ::pthread_condattr_init(&attr);- int error = ::pthread_condattr_setclock(&attr, CLOCK_MONOTONIC);+ int error = ::pthread_condattr_init(&attr); if (error == 0)- error = ::pthread_cond_init(&cond_, &attr);+ {+ error = ::pthread_condattr_setclock(&attr, CLOCK_MONOTONIC);+ if (error == 0)+ error = ::pthread_cond_init(&cond_, &attr);+ ::pthread_condattr_destroy(&attr);+ } #endif // (defined(__MACH__) && defined(__APPLE__)) // || (defined(__ANDROID__) && (__ANDROID_API__ < 21))
link/modules/asio-standalone/asio/include/asio/detail/impl/posix_mutex.ipp view
@@ -2,7 +2,7 @@ // detail/impl/posix_mutex.ipp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+ link/modules/asio-standalone/asio/include/asio/detail/impl/posix_serial_port_service.ipp view
@@ -0,0 +1,168 @@+//+// detail/impl/posix_serial_port_service.ipp+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2008 Rep Invariant Systems, Inc. (info@repinvariant.com)+//+// Distributed under the Boost Software License, Version 1.0. (See accompanying+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)+//++#ifndef ASIO_DETAIL_IMPL_POSIX_SERIAL_PORT_SERVICE_IPP+#define ASIO_DETAIL_IMPL_POSIX_SERIAL_PORT_SERVICE_IPP++#if defined(_MSC_VER) && (_MSC_VER >= 1200)+# pragma once+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)++#include "asio/detail/config.hpp"++#if defined(ASIO_HAS_SERIAL_PORT)+#if !defined(ASIO_WINDOWS) && !defined(__CYGWIN__)++#include <cstring>+#include "asio/detail/posix_serial_port_service.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {+namespace detail {++posix_serial_port_service::posix_serial_port_service(+ execution_context& context)+ : execution_context_service_base<posix_serial_port_service>(context),+ descriptor_service_(context)+{+}++void posix_serial_port_service::shutdown()+{+ descriptor_service_.shutdown();+}++asio::error_code posix_serial_port_service::open(+ posix_serial_port_service::implementation_type& impl,+ const std::string& device, asio::error_code& ec)+{+ if (is_open(impl))+ {+ ec = asio::error::already_open;+ ASIO_ERROR_LOCATION(ec);+ return ec;+ }++ descriptor_ops::state_type state = 0;+ int fd = descriptor_ops::open(device.c_str(),+ O_RDWR | O_NONBLOCK | O_NOCTTY, ec);+ if (fd < 0)+ {+ ASIO_ERROR_LOCATION(ec);+ return ec;+ }++ int s = descriptor_ops::fcntl(fd, F_GETFL, ec);+ if (s >= 0)+ s = descriptor_ops::fcntl(fd, F_SETFL, s | O_NONBLOCK, ec);+ if (s < 0)+ {+ asio::error_code ignored_ec;+ descriptor_ops::close(fd, state, ignored_ec);+ ASIO_ERROR_LOCATION(ec);+ return ec;+ }++ // Set up default serial port options.+ termios ios;+ s = ::tcgetattr(fd, &ios);+ descriptor_ops::get_last_error(ec, s < 0);+ if (s >= 0)+ {+#if defined(_BSD_SOURCE) || defined(_DEFAULT_SOURCE)+ ::cfmakeraw(&ios);+#else+ ios.c_iflag &= ~(IGNBRK | BRKINT | PARMRK+ | ISTRIP | INLCR | IGNCR | ICRNL | IXON);+ ios.c_oflag &= ~OPOST;+ ios.c_lflag &= ~(ECHO | ECHONL | ICANON | ISIG | IEXTEN);+ ios.c_cflag &= ~(CSIZE | PARENB);+ ios.c_cflag |= CS8;+#endif+ ios.c_iflag |= IGNPAR;+ ios.c_cflag |= CREAD | CLOCAL;+ s = ::tcsetattr(fd, TCSANOW, &ios);+ descriptor_ops::get_last_error(ec, s < 0);+ }+ if (s < 0)+ {+ asio::error_code ignored_ec;+ descriptor_ops::close(fd, state, ignored_ec);+ ASIO_ERROR_LOCATION(ec);+ return ec;+ }++ // We're done. Take ownership of the serial port descriptor.+ if (descriptor_service_.assign(impl, fd, ec))+ {+ asio::error_code ignored_ec;+ descriptor_ops::close(fd, state, ignored_ec);+ }++ ASIO_ERROR_LOCATION(ec);+ return ec;+}++asio::error_code posix_serial_port_service::do_set_option(+ posix_serial_port_service::implementation_type& impl,+ posix_serial_port_service::store_function_type store,+ const void* option, asio::error_code& ec)+{+ termios ios;+ int s = ::tcgetattr(descriptor_service_.native_handle(impl), &ios);+ descriptor_ops::get_last_error(ec, s < 0);+ if (s < 0)+ {+ ASIO_ERROR_LOCATION(ec);+ return ec;+ }++ if (store(option, ios, ec))+ {+ ASIO_ERROR_LOCATION(ec);+ return ec;+ }++ s = ::tcsetattr(descriptor_service_.native_handle(impl), TCSANOW, &ios);+ descriptor_ops::get_last_error(ec, s < 0);+ ASIO_ERROR_LOCATION(ec);+ return ec;+}++asio::error_code posix_serial_port_service::do_get_option(+ const posix_serial_port_service::implementation_type& impl,+ posix_serial_port_service::load_function_type load,+ void* option, asio::error_code& ec) const+{+ termios ios;+ int s = ::tcgetattr(descriptor_service_.native_handle(impl), &ios);+ descriptor_ops::get_last_error(ec, s < 0);+ if (s < 0)+ {+ ASIO_ERROR_LOCATION(ec);+ return ec;+ }++ load(option, ios, ec);+ ASIO_ERROR_LOCATION(ec);+ return ec;+}++} // namespace detail+} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // !defined(ASIO_WINDOWS) && !defined(__CYGWIN__)+#endif // defined(ASIO_HAS_SERIAL_PORT)++#endif // ASIO_DETAIL_IMPL_POSIX_SERIAL_PORT_SERVICE_IPP
link/modules/asio-standalone/asio/include/asio/detail/impl/posix_thread.ipp view
@@ -2,7 +2,7 @@ // detail/impl/posix_thread.ipp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/detail/impl/posix_tss_ptr.ipp view
@@ -2,7 +2,7 @@ // detail/impl/posix_tss_ptr.ipp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/detail/impl/reactive_descriptor_service.ipp view
@@ -2,7 +2,7 @@ // detail/impl/reactive_descriptor_service.ipp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -19,7 +19,8 @@ #if !defined(ASIO_WINDOWS) \ && !defined(ASIO_WINDOWS_RUNTIME) \- && !defined(__CYGWIN__)+ && !defined(__CYGWIN__) \+ && !defined(ASIO_HAS_IO_URING_AS_DEFAULT) #include "asio/error.hpp" #include "asio/detail/reactive_descriptor_service.hpp"@@ -46,6 +47,7 @@ { impl.descriptor_ = -1; impl.state_ = 0;+ impl.reactor_data_ = reactor::per_descriptor_data(); } void reactive_descriptor_service::move_construct(@@ -105,6 +107,7 @@ if (is_open(impl)) { ec = asio::error::already_open;+ ASIO_ERROR_LOCATION(ec); return ec; } @@ -113,6 +116,7 @@ { ec = asio::error_code(err, asio::error::get_system_category());+ ASIO_ERROR_LOCATION(ec); return ec; } @@ -151,6 +155,7 @@ // We'll just have to assume that other OSes follow the same behaviour.) construct(impl); + ASIO_ERROR_LOCATION(ec); return ec; } @@ -180,6 +185,7 @@ if (!is_open(impl)) { ec = asio::error::bad_descriptor;+ ASIO_ERROR_LOCATION(ec); return ec; } @@ -191,10 +197,10 @@ return ec; } -void reactive_descriptor_service::start_op(- reactive_descriptor_service::implementation_type& impl,- int op_type, reactor_op* op, bool is_continuation,- bool is_non_blocking, bool noop)+void reactive_descriptor_service::do_start_op(implementation_type& impl,+ int op_type, reactor_op* op, bool is_continuation, bool is_non_blocking,+ bool noop, void (*on_immediate)(operation* op, bool, const void*),+ const void* immediate_arg) { if (!noop) {@@ -202,13 +208,13 @@ descriptor_ops::set_internal_non_blocking( impl.descriptor_, impl.state_, true, op->ec_)) {- reactor_.start_op(op_type, impl.descriptor_,- impl.reactor_data_, op, is_continuation, is_non_blocking);+ reactor_.start_op(op_type, impl.descriptor_, impl.reactor_data_, op,+ is_continuation, is_non_blocking, on_immediate, immediate_arg); return; } } - reactor_.post_immediate_completion(op, is_continuation);+ on_immediate(op, is_continuation, immediate_arg); } } // namespace detail@@ -219,5 +225,6 @@ #endif // !defined(ASIO_WINDOWS) // && !defined(ASIO_WINDOWS_RUNTIME) // && !defined(__CYGWIN__)+ // && !defined(ASIO_HAS_IO_URING_AS_DEFAULT) #endif // ASIO_DETAIL_IMPL_REACTIVE_DESCRIPTOR_SERVICE_IPP
− link/modules/asio-standalone/asio/include/asio/detail/impl/reactive_serial_port_service.ipp
@@ -1,149 +0,0 @@-//-// detail/impl/reactive_serial_port_service.ipp-// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~-//-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)-// Copyright (c) 2008 Rep Invariant Systems, Inc. (info@repinvariant.com)-//-// Distributed under the Boost Software License, Version 1.0. (See accompanying-// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)-//--#ifndef ASIO_DETAIL_IMPL_REACTIVE_SERIAL_PORT_SERVICE_IPP-#define ASIO_DETAIL_IMPL_REACTIVE_SERIAL_PORT_SERVICE_IPP--#if defined(_MSC_VER) && (_MSC_VER >= 1200)-# pragma once-#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)--#include "asio/detail/config.hpp"--#if defined(ASIO_HAS_SERIAL_PORT)-#if !defined(ASIO_WINDOWS) && !defined(__CYGWIN__)--#include <cstring>-#include "asio/detail/reactive_serial_port_service.hpp"--#include "asio/detail/push_options.hpp"--namespace asio {-namespace detail {--reactive_serial_port_service::reactive_serial_port_service(- execution_context& context)- : execution_context_service_base<reactive_serial_port_service>(context),- descriptor_service_(context)-{-}--void reactive_serial_port_service::shutdown()-{- descriptor_service_.shutdown();-}--asio::error_code reactive_serial_port_service::open(- reactive_serial_port_service::implementation_type& impl,- const std::string& device, asio::error_code& ec)-{- if (is_open(impl))- {- ec = asio::error::already_open;- return ec;- }-- descriptor_ops::state_type state = 0;- int fd = descriptor_ops::open(device.c_str(),- O_RDWR | O_NONBLOCK | O_NOCTTY, ec);- if (fd < 0)- return ec;-- int s = descriptor_ops::fcntl(fd, F_GETFL, ec);- if (s >= 0)- s = descriptor_ops::fcntl(fd, F_SETFL, s | O_NONBLOCK, ec);- if (s < 0)- {- asio::error_code ignored_ec;- descriptor_ops::close(fd, state, ignored_ec);- return ec;- }-- // Set up default serial port options.- termios ios;- s = ::tcgetattr(fd, &ios);- descriptor_ops::get_last_error(ec, s < 0);- if (s >= 0)- {-#if defined(_BSD_SOURCE) || defined(_DEFAULT_SOURCE)- ::cfmakeraw(&ios);-#else- ios.c_iflag &= ~(IGNBRK | BRKINT | PARMRK- | ISTRIP | INLCR | IGNCR | ICRNL | IXON);- ios.c_oflag &= ~OPOST;- ios.c_lflag &= ~(ECHO | ECHONL | ICANON | ISIG | IEXTEN);- ios.c_cflag &= ~(CSIZE | PARENB);- ios.c_cflag |= CS8;-#endif- ios.c_iflag |= IGNPAR;- ios.c_cflag |= CREAD | CLOCAL;- s = ::tcsetattr(fd, TCSANOW, &ios);- descriptor_ops::get_last_error(ec, s < 0);- }- if (s < 0)- {- asio::error_code ignored_ec;- descriptor_ops::close(fd, state, ignored_ec);- return ec;- }-- // We're done. Take ownership of the serial port descriptor.- if (descriptor_service_.assign(impl, fd, ec))- {- asio::error_code ignored_ec;- descriptor_ops::close(fd, state, ignored_ec);- }-- return ec;-}--asio::error_code reactive_serial_port_service::do_set_option(- reactive_serial_port_service::implementation_type& impl,- reactive_serial_port_service::store_function_type store,- const void* option, asio::error_code& ec)-{- termios ios;- int s = ::tcgetattr(descriptor_service_.native_handle(impl), &ios);- descriptor_ops::get_last_error(ec, s < 0);- if (s < 0)- return ec;-- if (store(option, ios, ec))- return ec;-- s = ::tcsetattr(descriptor_service_.native_handle(impl), TCSANOW, &ios);- descriptor_ops::get_last_error(ec, s < 0);- return ec;-}--asio::error_code reactive_serial_port_service::do_get_option(- const reactive_serial_port_service::implementation_type& impl,- reactive_serial_port_service::load_function_type load,- void* option, asio::error_code& ec) const-{- termios ios;- int s = ::tcgetattr(descriptor_service_.native_handle(impl), &ios);- descriptor_ops::get_last_error(ec, s < 0);- if (s < 0)- return ec;-- return load(option, ios, ec);-}--} // namespace detail-} // namespace asio--#include "asio/detail/pop_options.hpp"--#endif // !defined(ASIO_WINDOWS) && !defined(__CYGWIN__)-#endif // defined(ASIO_HAS_SERIAL_PORT)--#endif // ASIO_DETAIL_IMPL_REACTIVE_SERIAL_PORT_SERVICE_IPP
link/modules/asio-standalone/asio/include/asio/detail/impl/reactive_socket_service_base.ipp view
@@ -2,7 +2,7 @@ // detail/reactive_socket_service_base.ipp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -18,7 +18,8 @@ #include "asio/detail/config.hpp" #if !defined(ASIO_HAS_IOCP) \- && !defined(ASIO_WINDOWS_RUNTIME)+ && !defined(ASIO_WINDOWS_RUNTIME) \+ && !defined(ASIO_HAS_IO_URING_AS_DEFAULT) #include "asio/detail/reactive_socket_service_base.hpp" @@ -43,6 +44,7 @@ { impl.socket_ = invalid_socket; impl.state_ = 0;+ impl.reactor_data_ = reactor::per_descriptor_data(); } void reactive_socket_service_base::base_move_construct(@@ -231,10 +233,11 @@ return ec; } -void reactive_socket_service_base::start_op(- reactive_socket_service_base::base_implementation_type& impl,- int op_type, reactor_op* op, bool is_continuation,- bool is_non_blocking, bool noop)+void reactive_socket_service_base::do_start_op(+ reactive_socket_service_base::base_implementation_type& impl, int op_type,+ reactor_op* op, bool is_continuation, bool is_non_blocking, bool noop,+ void (*on_immediate)(operation* op, bool, const void*),+ const void* immediate_arg) { if (!noop) {@@ -242,32 +245,38 @@ || socket_ops::set_internal_non_blocking( impl.socket_, impl.state_, true, op->ec_)) {- reactor_.start_op(op_type, impl.socket_,- impl.reactor_data_, op, is_continuation, is_non_blocking);+ reactor_.start_op(op_type, impl.socket_, impl.reactor_data_, op,+ is_continuation, is_non_blocking, on_immediate, immediate_arg); return; } } - reactor_.post_immediate_completion(op, is_continuation);+ on_immediate(op, is_continuation, immediate_arg); } -void reactive_socket_service_base::start_accept_op(+void reactive_socket_service_base::do_start_accept_op( reactive_socket_service_base::base_implementation_type& impl,- reactor_op* op, bool is_continuation, bool peer_is_open)+ reactor_op* op, bool is_continuation, bool peer_is_open,+ void (*on_immediate)(operation* op, bool, const void*),+ const void* immediate_arg) { if (!peer_is_open)- start_op(impl, reactor::read_op, op, is_continuation, true, false);+ {+ do_start_op(impl, reactor::read_op, op, is_continuation,+ true, false, on_immediate, immediate_arg);+ } else { op->ec_ = asio::error::already_open;- reactor_.post_immediate_completion(op, is_continuation);+ on_immediate(op, is_continuation, immediate_arg); } } -void reactive_socket_service_base::start_connect_op(+void reactive_socket_service_base::do_start_connect_op( reactive_socket_service_base::base_implementation_type& impl,- reactor_op* op, bool is_continuation,- const socket_addr_type* addr, size_t addrlen)+ reactor_op* op, bool is_continuation, const void* addr, size_t addrlen,+ void (*on_immediate)(operation* op, bool, const void*),+ const void* immediate_arg) { if ((impl.state_ & socket_ops::non_blocking) || socket_ops::set_internal_non_blocking(@@ -279,14 +288,14 @@ || op->ec_ == asio::error::would_block) { op->ec_ = asio::error_code();- reactor_.start_op(reactor::connect_op, impl.socket_,- impl.reactor_data_, op, is_continuation, false);+ reactor_.start_op(reactor::connect_op, impl.socket_, impl.reactor_data_,+ op, is_continuation, false, on_immediate, immediate_arg); return; } } } - reactor_.post_immediate_completion(op, is_continuation);+ on_immediate(op, is_continuation, immediate_arg); } } // namespace detail@@ -296,5 +305,6 @@ #endif // !defined(ASIO_HAS_IOCP) // && !defined(ASIO_WINDOWS_RUNTIME)+ // && !defined(ASIO_HAS_IO_URING_AS_DEFAULT) #endif // ASIO_DETAIL_IMPL_REACTIVE_SOCKET_SERVICE_BASE_IPP
link/modules/asio-standalone/asio/include/asio/detail/impl/resolver_service_base.ipp view
@@ -2,7 +2,7 @@ // detail/impl/resolver_service_base.ipp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/detail/impl/scheduler.ipp view
@@ -2,7 +2,7 @@ // detail/impl/scheduler.ipp // ~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -20,11 +20,16 @@ #include "asio/detail/concurrency_hint.hpp" #include "asio/detail/event.hpp" #include "asio/detail/limits.hpp"-#include "asio/detail/reactor.hpp" #include "asio/detail/scheduler.hpp" #include "asio/detail/scheduler_thread_info.hpp" #include "asio/detail/signal_blocker.hpp" +#if defined(ASIO_HAS_IO_URING_AS_DEFAULT)+# include "asio/detail/io_uring_service.hpp"+#else // defined(ASIO_HAS_IO_URING_AS_DEFAULT)+# include "asio/detail/reactor.hpp"+#endif // defined(ASIO_HAS_IO_URING_AS_DEFAULT)+ #include "asio/detail/push_options.hpp" namespace asio {@@ -104,7 +109,7 @@ }; scheduler::scheduler(asio::execution_context& ctx,- int concurrency_hint, bool own_thread)+ int concurrency_hint, bool own_thread, get_task_func_type get_task) : asio::detail::execution_context_service_base<scheduler>(ctx), one_thread_(concurrency_hint == 1 || !ASIO_CONCURRENCY_HINT_IS_LOCKING(@@ -114,6 +119,7 @@ mutex_(ASIO_CONCURRENCY_HINT_IS_LOCKING( SCHEDULER, concurrency_hint)), task_(0),+ get_task_(get_task), task_interrupted_(true), outstanding_work_(0), stopped_(false),@@ -178,7 +184,7 @@ mutex::scoped_lock lock(mutex_); if (!shutdown_ && !task_) {- task_ = &use_service<reactor>(this->context());+ task_ = get_task_(this->context()); op_queue_.push(&task_operation_); wake_one_thread_and_unlock(lock); }@@ -321,9 +327,15 @@ void scheduler::compensating_work_started() { thread_info_base* this_thread = thread_call_stack::contains(this);+ ASIO_ASSUME(this_thread != 0); // Only called from inside scheduler. ++static_cast<thread_info*>(this_thread)->private_outstanding_work; } +bool scheduler::can_dispatch()+{+ return thread_call_stack::contains(this) != 0;+}+ void scheduler::capture_current_exception() { if (thread_info_base* this_thread = thread_call_stack::contains(this))@@ -644,6 +656,15 @@ } lock.unlock(); }+}++scheduler_task* scheduler::get_default_task(asio::execution_context& ctx)+{+#if defined(ASIO_HAS_IO_URING_AS_DEFAULT)+ return &use_service<io_uring_service>(ctx);+#else // defined(ASIO_HAS_IO_URING_AS_DEFAULT)+ return &use_service<reactor>(ctx);+#endif // defined(ASIO_HAS_IO_URING_AS_DEFAULT) } } // namespace detail
link/modules/asio-standalone/asio/include/asio/detail/impl/select_reactor.hpp view
@@ -2,7 +2,7 @@ // detail/impl/select_reactor.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -23,11 +23,23 @@ && !defined(ASIO_HAS_KQUEUE) \ && !defined(ASIO_WINDOWS_RUNTIME)) +#if defined(ASIO_HAS_IOCP)+# include "asio/detail/win_iocp_io_context.hpp"+#else // defined(ASIO_HAS_IOCP)+# include "asio/detail/scheduler.hpp"+#endif // defined(ASIO_HAS_IOCP)+ #include "asio/detail/push_options.hpp" namespace asio { namespace detail { +inline void select_reactor::post_immediate_completion(+ operation* op, bool is_continuation) const+{+ scheduler_.post_immediate_completion(op, is_continuation);+}+ template <typename Time_Traits> void select_reactor::add_timer_queue(timer_queue<Time_Traits>& queue) {@@ -71,6 +83,18 @@ lock.unlock(); scheduler_.post_deferred_completions(ops); return n;+}++template <typename Time_Traits>+void select_reactor::cancel_timer_by_key(timer_queue<Time_Traits>& queue,+ typename timer_queue<Time_Traits>::per_timer_data* timer,+ void* cancellation_key)+{+ mutex::scoped_lock lock(mutex_);+ op_queue<operation> ops;+ queue.cancel_timer_by_key(timer, ops, cancellation_key);+ lock.unlock();+ scheduler_.post_deferred_completions(ops); } template <typename Time_Traits>
link/modules/asio-standalone/asio/include/asio/detail/impl/select_reactor.ipp view
@@ -2,7 +2,7 @@ // detail/impl/select_reactor.ipp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -28,6 +28,12 @@ #include "asio/detail/signal_blocker.hpp" #include "asio/detail/socket_ops.hpp" +#if defined(ASIO_HAS_IOCP)+# include "asio/detail/win_iocp_io_context.hpp"+#else // defined(ASIO_HAS_IOCP)+# include "asio/detail/scheduler.hpp"+#endif // defined(ASIO_HAS_IOCP)+ #include "asio/detail/push_options.hpp" namespace asio {@@ -60,6 +66,7 @@ #if defined(ASIO_HAS_IOCP) stop_thread_(false), thread_(0),+ restart_reactor_(this), #endif // defined(ASIO_HAS_IOCP) shutdown_(false) {@@ -107,8 +114,12 @@ void select_reactor::notify_fork( asio::execution_context::fork_event fork_ev) {+#if defined(ASIO_HAS_IOCP)+ (void)fork_ev;+#else // defined(ASIO_HAS_IOCP) if (fork_ev == asio::execution_context::fork_child) interrupter_.recreate();+#endif // defined(ASIO_HAS_IOCP) } void select_reactor::init_task()@@ -140,15 +151,23 @@ { } +void select_reactor::call_post_immediate_completion(+ operation* op, bool is_continuation, const void* self)+{+ static_cast<const select_reactor*>(self)->post_immediate_completion(+ op, is_continuation);+}+ void select_reactor::start_op(int op_type, socket_type descriptor,- select_reactor::per_descriptor_data&, reactor_op* op,- bool is_continuation, bool)+ select_reactor::per_descriptor_data&, reactor_op* op, bool is_continuation,+ bool, void (*on_immediate)(operation*, bool, const void*),+ const void* immediate_arg) { asio::detail::mutex::scoped_lock lock(mutex_); if (shutdown_) {- post_immediate_completion(op, is_continuation);+ on_immediate(op, is_continuation, immediate_arg); return; } @@ -165,6 +184,19 @@ cancel_ops_unlocked(descriptor, asio::error::operation_aborted); } +void select_reactor::cancel_ops_by_key(socket_type descriptor,+ select_reactor::per_descriptor_data&,+ int op_type, void* cancellation_key)+{+ asio::detail::mutex::scoped_lock lock(mutex_);+ op_queue<operation> ops;+ bool need_interrupt = op_queue_[op_type].cancel_operations_by_key(+ descriptor, ops, cancellation_key, asio::error::operation_aborted);+ scheduler_.post_deferred_completions(ops);+ if (need_interrupt)+ interrupter_.interrupt();+}+ void select_reactor::deregister_descriptor(socket_type descriptor, select_reactor::per_descriptor_data&, bool) {@@ -243,7 +275,12 @@ if (!interrupter_.reset()) { lock.lock();+#if defined(ASIO_HAS_IOCP)+ stop_thread_ = true;+ scheduler_.post_immediate_completion(&restart_reactor_, false);+#else // defined(ASIO_HAS_IOCP) interrupter_.recreate();+#endif // defined(ASIO_HAS_IOCP) } --retval; }@@ -280,9 +317,34 @@ { lock.unlock(); op_queue<operation> ops;- run(true, ops);+ run(-1, ops); scheduler_.post_deferred_completions(ops); lock.lock();+ }+}++void select_reactor::restart_reactor::do_complete(void* owner, operation* base,+ const asio::error_code& /*ec*/, std::size_t /*bytes_transferred*/)+{+ if (owner)+ {+ select_reactor* reactor = static_cast<restart_reactor*>(base)->reactor_;++ if (reactor->thread_)+ {+ reactor->thread_->join();+ delete reactor->thread_;+ reactor->thread_ = 0;+ }++ asio::detail::mutex::scoped_lock lock(reactor->mutex_);+ reactor->interrupter_.recreate();+ reactor->stop_thread_ = false;+ lock.unlock();++ asio::detail::signal_blocker sb;+ reactor->thread_ =+ new asio::detail::thread(thread_function(reactor)); } } #endif // defined(ASIO_HAS_IOCP)
link/modules/asio-standalone/asio/include/asio/detail/impl/service_registry.hpp view
@@ -2,7 +2,7 @@ // detail/impl/service_registry.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/detail/impl/service_registry.ipp view
@@ -2,7 +2,7 @@ // detail/impl/service_registry.ipp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/detail/impl/signal_set_service.ipp view
@@ -2,7 +2,7 @@ // detail/impl/signal_set_service.ipp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -19,12 +19,17 @@ #include <cstring> #include <stdexcept>-#include "asio/detail/reactor.hpp" #include "asio/detail/signal_blocker.hpp" #include "asio/detail/signal_set_service.hpp" #include "asio/detail/static_mutex.hpp" #include "asio/detail/throw_exception.hpp" +#if defined(ASIO_HAS_IO_URING_AS_DEFAULT)+# include "asio/detail/io_uring_service.hpp"+#else // defined(ASIO_HAS_IO_URING_AS_DEFAULT)+# include "asio/detail/reactor.hpp"+#endif // defined(ASIO_HAS_IO_URING_AS_DEFAULT)+ #include "asio/detail/push_options.hpp" namespace asio {@@ -49,12 +54,16 @@ // A count of the number of objects that are registered for each signal. std::size_t registration_count_[max_signal_number];++ // The flags used for each registered signal.+ signal_set_base::flags_t flags_[max_signal_number]; }; signal_state* get_signal_state() { static signal_state state = {- ASIO_STATIC_MUTEX_INIT, -1, -1, false, 0, { 0 } };+ ASIO_STATIC_MUTEX_INIT, -1, -1, false, 0,+ { 0 }, { signal_set_base::flags_t() } }; return &state; } @@ -85,10 +94,43 @@ #if !defined(ASIO_WINDOWS) \ && !defined(ASIO_WINDOWS_RUNTIME) \ && !defined(__CYGWIN__)-class signal_set_service::pipe_read_op : public reactor_op+class signal_set_service::pipe_read_op :+# if defined(ASIO_HAS_IO_URING_AS_DEFAULT)+ public io_uring_operation+# else // defined(ASIO_HAS_IO_URING_AS_DEFAULT)+ public reactor_op+# endif // defined(ASIO_HAS_IO_URING_AS_DEFAULT) { public:+# if defined(ASIO_HAS_IO_URING_AS_DEFAULT) pipe_read_op()+ : io_uring_operation(asio::error_code(), &pipe_read_op::do_prepare,+ &pipe_read_op::do_perform, pipe_read_op::do_complete)+ {+ }++ static void do_prepare(io_uring_operation*, ::io_uring_sqe* sqe)+ {+ signal_state* state = get_signal_state();++ int fd = state->read_descriptor_;+ ::io_uring_prep_poll_add(sqe, fd, POLLIN);+ }++ static bool do_perform(io_uring_operation*, bool)+ {+ signal_state* state = get_signal_state();++ int fd = state->read_descriptor_;+ int signal_number = 0;+ while (::read(fd, &signal_number, sizeof(int)) == sizeof(int))+ if (signal_number >= 0 && signal_number < max_signal_number)+ signal_set_service::deliver_signal(signal_number);++ return false;+ }+# else // defined(ASIO_HAS_IO_URING_AS_DEFAULT)+ pipe_read_op() : reactor_op(asio::error_code(), &pipe_read_op::do_perform, pipe_read_op::do_complete) {@@ -106,6 +148,7 @@ return not_done; }+# endif // defined(ASIO_HAS_IO_URING_AS_DEFAULT) static void do_complete(void* /*owner*/, operation* base, const asio::error_code& /*ec*/,@@ -125,7 +168,11 @@ #if !defined(ASIO_WINDOWS) \ && !defined(ASIO_WINDOWS_RUNTIME) \ && !defined(__CYGWIN__)+# if defined(ASIO_HAS_IO_URING_AS_DEFAULT)+ io_uring_service_(asio::use_service<io_uring_service>(context)),+# else // defined(ASIO_HAS_IO_URING_AS_DEFAULT) reactor_(asio::use_service<reactor>(context)),+# endif // defined(ASIO_HAS_IO_URING_AS_DEFAULT) #endif // !defined(ASIO_WINDOWS) // && !defined(ASIO_WINDOWS_RUNTIME) // && !defined(__CYGWIN__)@@ -137,7 +184,11 @@ #if !defined(ASIO_WINDOWS) \ && !defined(ASIO_WINDOWS_RUNTIME) \ && !defined(__CYGWIN__)+# if defined(ASIO_HAS_IO_URING_AS_DEFAULT)+ io_uring_service_.init_task();+# else // defined(ASIO_HAS_IO_URING_AS_DEFAULT) reactor_.init_task();+# endif // defined(ASIO_HAS_IO_URING_AS_DEFAULT) #endif // !defined(ASIO_WINDOWS) // && !defined(ASIO_WINDOWS_RUNTIME) // && !defined(__CYGWIN__)@@ -187,8 +238,14 @@ int read_descriptor = state->read_descriptor_; state->fork_prepared_ = true; lock.unlock();+# if defined(ASIO_HAS_IO_URING_AS_DEFAULT)+ (void)read_descriptor;+ io_uring_service_.deregister_io_object(io_object_data_);+ io_uring_service_.cleanup_io_object(io_object_data_);+# else // defined(ASIO_HAS_IO_URING_AS_DEFAULT) reactor_.deregister_internal_descriptor(read_descriptor, reactor_data_); reactor_.cleanup_descriptor_data(reactor_data_);+# endif // defined(ASIO_HAS_IO_URING_AS_DEFAULT) } break; case execution_context::fork_parent:@@ -197,8 +254,14 @@ int read_descriptor = state->read_descriptor_; state->fork_prepared_ = false; lock.unlock();+# if defined(ASIO_HAS_IO_URING_AS_DEFAULT)+ (void)read_descriptor;+ io_uring_service_.register_internal_io_object(io_object_data_,+ io_uring_service::read_op, new pipe_read_op);+# else // defined(ASIO_HAS_IO_URING_AS_DEFAULT) reactor_.register_internal_descriptor(reactor::read_op, read_descriptor, reactor_data_, new pipe_read_op);+# endif // defined(ASIO_HAS_IO_URING_AS_DEFAULT) } break; case execution_context::fork_child:@@ -210,8 +273,14 @@ int read_descriptor = state->read_descriptor_; state->fork_prepared_ = false; lock.unlock();+# if defined(ASIO_HAS_IO_URING_AS_DEFAULT)+ (void)read_descriptor;+ io_uring_service_.register_internal_io_object(io_object_data_,+ io_uring_service::read_op, new pipe_read_op);+# else // defined(ASIO_HAS_IO_URING_AS_DEFAULT) reactor_.register_internal_descriptor(reactor::read_op, read_descriptor, reactor_data_, new pipe_read_op);+# endif // defined(ASIO_HAS_IO_URING_AS_DEFAULT) } break; default:@@ -241,8 +310,8 @@ } asio::error_code signal_set_service::add(- signal_set_service::implementation_type& impl,- int signal_number, asio::error_code& ec)+ signal_set_service::implementation_type& impl, int signal_number,+ signal_set_base::flags_t f, asio::error_code& ec) { // Check that the signal number is valid. if (signal_number < 0 || signal_number >= max_signal_number)@@ -251,6 +320,15 @@ return ec; } + // Check that the specified flags are supported.+#if !defined(ASIO_HAS_SIGACTION)+ if (f != signal_set_base::flags::dont_care)+ {+ ec = asio::error::operation_not_supported;+ return ec;+ }+#endif // !defined(ASIO_HAS_SIGACTION)+ signal_state* state = get_signal_state(); static_mutex::scoped_lock lock(state->mutex_); @@ -278,6 +356,8 @@ memset(&sa, 0, sizeof(sa)); sa.sa_handler = asio_signal_handler; sigfillset(&sa.sa_mask);+ if (f != signal_set_base::flags::dont_care)+ sa.sa_flags = static_cast<int>(f); if (::sigaction(signal_number, &sa, 0) == -1) # else // defined(ASIO_HAS_SIGACTION) if (::signal(signal_number, asio_signal_handler) == SIG_ERR)@@ -292,7 +372,37 @@ delete new_registration; return ec; }+# if defined(ASIO_HAS_SIGACTION)+ state->flags_[signal_number] = f;+# endif // defined(ASIO_HAS_SIGACTION) }+# if defined(ASIO_HAS_SIGACTION)+ // Otherwise check to see if the flags have changed.+ else if (f != signal_set_base::flags::dont_care)+ {+ if (f != state->flags_[signal_number])+ {+ using namespace std; // For memset.+ if (state->flags_[signal_number] != signal_set_base::flags::dont_care)+ {+ ec = asio::error::invalid_argument;+ return ec;+ }+ struct sigaction sa;+ memset(&sa, 0, sizeof(sa));+ sa.sa_handler = asio_signal_handler;+ sigfillset(&sa.sa_mask);+ sa.sa_flags = static_cast<int>(f);+ if (::sigaction(signal_number, &sa, 0) == -1)+ {+ ec = asio::error_code(errno,+ asio::error::get_system_category());+ return ec;+ }+ state->flags_[signal_number] = f;+ }+ }+# endif // defined(ASIO_HAS_SIGACTION) #endif // defined(ASIO_HAS_SIGNAL) || defined(ASIO_HAS_SIGACTION) // Record the new registration in the set.@@ -361,6 +471,9 @@ # endif // defined(ASIO_WINDOWS) || defined(__CYGWIN__) return ec; }+# if defined(ASIO_HAS_SIGACTION)+ state->flags_[signal_number] = signal_set_base::flags_t();+# endif // defined(ASIO_HAS_SIGACTION) } #endif // defined(ASIO_HAS_SIGNAL) || defined(ASIO_HAS_SIGACTION) @@ -415,6 +528,9 @@ # endif // defined(ASIO_WINDOWS) || defined(__CYGWIN__) return ec; }+# if defined(ASIO_HAS_SIGACTION)+ state->flags_[reg->signal_number_] = signal_set_base::flags_t();+# endif // defined(ASIO_HAS_SIGACTION) } #endif // defined(ASIO_HAS_SIGNAL) || defined(ASIO_HAS_SIGACTION) @@ -462,6 +578,33 @@ return ec; } +void signal_set_service::cancel_ops_by_key(+ signal_set_service::implementation_type& impl, void* cancellation_key)+{+ op_queue<operation> ops;+ {+ op_queue<signal_op> other_ops;+ signal_state* state = get_signal_state();+ static_mutex::scoped_lock lock(state->mutex_);++ while (signal_op* op = impl.queue_.front())+ {+ impl.queue_.pop();+ if (op->cancellation_key_ == cancellation_key)+ {+ op->ec_ = asio::error::operation_aborted;+ ops.push(op);+ }+ else+ other_ops.push(op);+ }++ impl.queue_.push(other_ops);+ }++ scheduler_.post_deferred_completions(ops);+}+ void signal_set_service::deliver_signal(int signal_number) { signal_state* state = get_signal_state();@@ -538,8 +681,14 @@ // Register for pipe readiness notifications. int read_descriptor = state->read_descriptor_; lock.unlock();+# if defined(ASIO_HAS_IO_URING_AS_DEFAULT)+ (void)read_descriptor;+ service->io_uring_service_.register_internal_io_object(+ service->io_object_data_, io_uring_service::read_op, new pipe_read_op);+# else // defined(ASIO_HAS_IO_URING_AS_DEFAULT) service->reactor_.register_internal_descriptor(reactor::read_op, read_descriptor, service->reactor_data_, new pipe_read_op);+# endif // defined(ASIO_HAS_IO_URING_AS_DEFAULT) #endif // !defined(ASIO_WINDOWS) // && !defined(ASIO_WINDOWS_RUNTIME) // && !defined(__CYGWIN__)@@ -558,10 +707,17 @@ // Disable the pipe readiness notifications. int read_descriptor = state->read_descriptor_; lock.unlock();+# if defined(ASIO_HAS_IO_URING_AS_DEFAULT)+ (void)read_descriptor;+ service->io_uring_service_.deregister_io_object(service->io_object_data_);+ service->io_uring_service_.cleanup_io_object(service->io_object_data_);+ lock.lock();+# else // defined(ASIO_HAS_IO_URING_AS_DEFAULT) service->reactor_.deregister_internal_descriptor( read_descriptor, service->reactor_data_); service->reactor_.cleanup_descriptor_data(service->reactor_data_); lock.lock();+# endif // defined(ASIO_HAS_IO_URING_AS_DEFAULT) #endif // !defined(ASIO_WINDOWS) // && !defined(ASIO_WINDOWS_RUNTIME) // && !defined(__CYGWIN__)
link/modules/asio-standalone/asio/include/asio/detail/impl/socket_ops.ipp view
@@ -2,7 +2,7 @@ // detail/impl/socket_ops.ipp // ~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -78,7 +78,7 @@ { if (!is_error_condition) {- ec.assign(0, ec.category());+ asio::error::clear(ec); } else {@@ -94,16 +94,18 @@ template <typename SockLenType> inline socket_type call_accept(SockLenType msghdr::*,- socket_type s, socket_addr_type* addr, std::size_t* addrlen)+ socket_type s, void* addr, std::size_t* addrlen) { SockLenType tmp_addrlen = addrlen ? (SockLenType)*addrlen : 0;- socket_type result = ::accept(s, addr, addrlen ? &tmp_addrlen : 0);+ socket_type result = ::accept(s,+ static_cast<socket_addr_type*>(addr),+ addrlen ? &tmp_addrlen : 0); if (addrlen) *addrlen = (std::size_t)tmp_addrlen; return result; } -socket_type accept(socket_type s, socket_addr_type* addr,+socket_type accept(socket_type s, void* addr, std::size_t* addrlen, asio::error_code& ec) { if (s == invalid_socket)@@ -129,12 +131,12 @@ } #endif - ec.assign(0, ec.category());+ asio::error::clear(ec); return new_s; } socket_type sync_accept(socket_type s, state_type state,- socket_addr_type* addr, std::size_t* addrlen, asio::error_code& ec)+ void* addr, std::size_t* addrlen, asio::error_code& ec) { // Accept a socket. for (;;)@@ -179,9 +181,8 @@ #if defined(ASIO_HAS_IOCP) -void complete_iocp_accept(socket_type s,- void* output_buffer, DWORD address_length,- socket_addr_type* addr, std::size_t* addrlen,+void complete_iocp_accept(socket_type s, void* output_buffer,+ DWORD address_length, void* addr, std::size_t* addrlen, socket_type new_socket, asio::error_code& ec) { // Map non-portable errors to their portable counterparts.@@ -225,7 +226,7 @@ #else // defined(ASIO_HAS_IOCP) bool non_blocking_accept(socket_type s,- state_type state, socket_addr_type* addr, std::size_t* addrlen,+ state_type state, void* addr, std::size_t* addrlen, asio::error_code& ec, socket_type& new_socket) { for (;;)@@ -272,12 +273,13 @@ template <typename SockLenType> inline int call_bind(SockLenType msghdr::*,- socket_type s, const socket_addr_type* addr, std::size_t addrlen)+ socket_type s, const void* addr, std::size_t addrlen) {- return ::bind(s, addr, (SockLenType)addrlen);+ return ::bind(s, static_cast<const socket_addr_type*>(addr),+ (SockLenType)addrlen); } -int bind(socket_type s, const socket_addr_type* addr,+int bind(socket_type s, const void* addr, std::size_t addrlen, asio::error_code& ec) { if (s == invalid_socket)@@ -463,12 +465,13 @@ template <typename SockLenType> inline int call_connect(SockLenType msghdr::*,- socket_type s, const socket_addr_type* addr, std::size_t addrlen)+ socket_type s, const void* addr, std::size_t addrlen) {- return ::connect(s, addr, (SockLenType)addrlen);+ return ::connect(s, static_cast<const socket_addr_type*>(addr),+ (SockLenType)addrlen); } -int connect(socket_type s, const socket_addr_type* addr,+int connect(socket_type s, const void* addr, std::size_t addrlen, asio::error_code& ec) { if (s == invalid_socket)@@ -481,12 +484,17 @@ get_last_error(ec, result != 0); #if defined(__linux__) if (result != 0 && ec == asio::error::try_again)- ec = asio::error::no_buffer_space;+ {+ if (static_cast<const socket_addr_type*>(addr)->sa_family == AF_UNIX)+ ec = asio::error::in_progress;+ else+ ec = asio::error::no_buffer_space;+ } #endif // defined(__linux__) return result; } -void sync_connect(socket_type s, const socket_addr_type* addr,+void sync_connect(socket_type s, const void* addr, std::size_t addrlen, asio::error_code& ec) { // Perform the connect operation.@@ -596,7 +604,7 @@ asio::error::get_system_category()); } else- ec.assign(0, ec.category());+ asio::error::clear(ec); } return true;@@ -641,7 +649,7 @@ # endif // defined(ENOTTY) #else // defined(SIOCATMARK) int value = ::sockatmark(s);- get_last_error(ec, result < 0);+ get_last_error(ec, value < 0); #endif // defined(SIOCATMARK) return ec ? false : value != 0;@@ -722,9 +730,9 @@ #endif // defined(ASIO_WINDOWS) || defined(__CYGWIN__) } -inline void init_msghdr_msg_name(void*& name, socket_addr_type* addr)+inline void init_msghdr_msg_name(void*& name, void* addr) {- name = addr;+ name = static_cast<socket_addr_type*>(addr); } inline void init_msghdr_msg_name(void*& name, const socket_addr_type* addr)@@ -733,15 +741,15 @@ } template <typename T>-inline void init_msghdr_msg_name(T& name, socket_addr_type* addr)+inline void init_msghdr_msg_name(T& name, void* addr) {- name = reinterpret_cast<T>(addr);+ name = static_cast<T>(addr); } template <typename T>-inline void init_msghdr_msg_name(T& name, const socket_addr_type* addr)+inline void init_msghdr_msg_name(T& name, const void* addr) {- name = reinterpret_cast<T>(const_cast<socket_addr_type*>(addr));+ name = static_cast<T>(const_cast<void*>(addr)); } signed_size_type recv(socket_type s, buf* bufs, size_t count,@@ -763,7 +771,7 @@ result = 0; if (result != 0) return socket_error_retval;- ec.assign(0, ec.category());+ asio::error::clear(ec); return bytes_transferred; #else // defined(ASIO_WINDOWS) || defined(__CYGWIN__) msghdr msg = msghdr();@@ -796,7 +804,7 @@ result = 0; if (result != 0) return socket_error_retval;- ec.assign(0, ec.category());+ asio::error::clear(ec); return bytes_transferred; #else // defined(ASIO_WINDOWS) || defined(__CYGWIN__) signed_size_type result = ::recv(s, static_cast<char*>(data), size, flags);@@ -817,7 +825,7 @@ // A request to read 0 bytes on a stream is a no-op. if (all_empty && (state & stream_oriented)) {- ec.assign(0, ec.category());+ asio::error::clear(ec); return 0; } @@ -862,7 +870,7 @@ // A request to read 0 bytes on a stream is a no-op. if (size == 0 && (state & stream_oriented)) {- ec.assign(0, ec.category());+ asio::error::clear(ec); return 0; } @@ -915,7 +923,7 @@ } else if (ec.value() == WSAEMSGSIZE || ec.value() == ERROR_MORE_DATA) {- ec.assign(0, ec.category());+ asio::error::clear(ec); } // Check for connection closed.@@ -1008,8 +1016,7 @@ #endif // defined(ASIO_HAS_IOCP) signed_size_type recvfrom(socket_type s, buf* bufs, size_t count,- int flags, socket_addr_type* addr, std::size_t* addrlen,- asio::error_code& ec)+ int flags, void* addr, std::size_t* addrlen, asio::error_code& ec) { #if defined(ASIO_WINDOWS) || defined(__CYGWIN__) // Receive some data.@@ -1017,8 +1024,8 @@ DWORD bytes_transferred = 0; DWORD recv_flags = flags; int tmp_addrlen = (int)*addrlen;- int result = ::WSARecvFrom(s, bufs, recv_buf_count,- &bytes_transferred, &recv_flags, addr, &tmp_addrlen, 0, 0);+ int result = ::WSARecvFrom(s, bufs, recv_buf_count, &bytes_transferred,+ &recv_flags, static_cast<socket_addr_type*>(addr), &tmp_addrlen, 0, 0); get_last_error(ec, true); *addrlen = (std::size_t)tmp_addrlen; if (ec.value() == ERROR_NETNAME_DELETED)@@ -1029,7 +1036,7 @@ result = 0; if (result != 0) return socket_error_retval;- ec.assign(0, ec.category());+ asio::error::clear(ec); return bytes_transferred; #else // defined(ASIO_WINDOWS) || defined(__CYGWIN__) msghdr msg = msghdr();@@ -1045,21 +1052,19 @@ } template <typename SockLenType>-inline signed_size_type call_recvfrom(SockLenType msghdr::*,- socket_type s, void* data, size_t size, int flags,- socket_addr_type* addr, std::size_t* addrlen)+inline signed_size_type call_recvfrom(SockLenType msghdr::*, socket_type s,+ void* data, size_t size, int flags, void* addr, std::size_t* addrlen) { SockLenType tmp_addrlen = addrlen ? (SockLenType)*addrlen : 0;- signed_size_type result = ::recvfrom(s, static_cast<char*>(data),- size, flags, addr, addrlen ? &tmp_addrlen : 0);+ signed_size_type result = ::recvfrom(s, static_cast<char*>(data), size,+ flags, static_cast<socket_addr_type*>(addr), addrlen ? &tmp_addrlen : 0); if (addrlen) *addrlen = (std::size_t)tmp_addrlen; return result; } signed_size_type recvfrom1(socket_type s, void* data, size_t size,- int flags, socket_addr_type* addr, std::size_t* addrlen,- asio::error_code& ec)+ int flags, void* addr, std::size_t* addrlen, asio::error_code& ec) { #if defined(ASIO_WINDOWS) || defined(__CYGWIN__) // Receive some data.@@ -1069,8 +1074,8 @@ DWORD bytes_transferred = 0; DWORD recv_flags = flags; int tmp_addrlen = (int)*addrlen;- int result = ::WSARecvFrom(s, &buf, 1, &bytes_transferred,- &recv_flags, addr, &tmp_addrlen, 0, 0);+ int result = ::WSARecvFrom(s, &buf, 1, &bytes_transferred, &recv_flags,+ static_cast<socket_addr_type*>(addr), &tmp_addrlen, 0, 0); get_last_error(ec, true); *addrlen = (std::size_t)tmp_addrlen; if (ec.value() == ERROR_NETNAME_DELETED)@@ -1081,7 +1086,7 @@ result = 0; if (result != 0) return socket_error_retval;- ec.assign(0, ec.category());+ asio::error::clear(ec); return bytes_transferred; #else // defined(ASIO_WINDOWS) || defined(__CYGWIN__) signed_size_type result = call_recvfrom(&msghdr::msg_namelen,@@ -1091,9 +1096,8 @@ #endif // defined(ASIO_WINDOWS) || defined(__CYGWIN__) } -size_t sync_recvfrom(socket_type s, state_type state, buf* bufs,- size_t count, int flags, socket_addr_type* addr,- std::size_t* addrlen, asio::error_code& ec)+size_t sync_recvfrom(socket_type s, state_type state, buf* bufs, size_t count,+ int flags, void* addr, std::size_t* addrlen, asio::error_code& ec) { if (s == invalid_socket) {@@ -1124,9 +1128,8 @@ } } -size_t sync_recvfrom1(socket_type s, state_type state, void* data,- size_t size, int flags, socket_addr_type* addr,- std::size_t* addrlen, asio::error_code& ec)+size_t sync_recvfrom1(socket_type s, state_type state, void* data, size_t size,+ int flags, void* addr, std::size_t* addrlen, asio::error_code& ec) { if (s == invalid_socket) {@@ -1177,15 +1180,14 @@ } else if (ec.value() == WSAEMSGSIZE || ec.value() == ERROR_MORE_DATA) {- ec.assign(0, ec.category());+ asio::error::clear(ec); } } #else // defined(ASIO_HAS_IOCP) -bool non_blocking_recvfrom(socket_type s,- buf* bufs, size_t count, int flags,- socket_addr_type* addr, std::size_t* addrlen,+bool non_blocking_recvfrom(socket_type s, buf* bufs,+ size_t count, int flags, void* addr, std::size_t* addrlen, asio::error_code& ec, size_t& bytes_transferred) { for (;;)@@ -1216,9 +1218,8 @@ } } -bool non_blocking_recvfrom1(socket_type s,- void* data, size_t size, int flags,- socket_addr_type* addr, std::size_t* addrlen,+bool non_blocking_recvfrom1(socket_type s, void* data,+ size_t size, int flags, void* addr, std::size_t* addrlen, asio::error_code& ec, size_t& bytes_transferred) { for (;;)@@ -1324,7 +1325,7 @@ } else if (ec.value() == WSAEMSGSIZE || ec.value() == ERROR_MORE_DATA) {- ec.assign(0, ec.category());+ asio::error::clear(ec); } } @@ -1381,15 +1382,15 @@ ec = asio::error::connection_refused; if (result != 0) return socket_error_retval;- ec.assign(0, ec.category());+ asio::error::clear(ec); return bytes_transferred; #else // defined(ASIO_WINDOWS) || defined(__CYGWIN__) msghdr msg = msghdr(); msg.msg_iov = const_cast<buf*>(bufs); msg.msg_iovlen = static_cast<int>(count);-#if defined(__linux__)+#if defined(ASIO_HAS_MSG_NOSIGNAL) flags |= MSG_NOSIGNAL;-#endif // defined(__linux__)+#endif // defined(ASIO_HAS_MSG_NOSIGNAL) signed_size_type result = ::sendmsg(s, &msg, flags); get_last_error(ec, result < 0); return result;@@ -1415,12 +1416,12 @@ ec = asio::error::connection_refused; if (result != 0) return socket_error_retval;- ec.assign(0, ec.category());+ asio::error::clear(ec); return bytes_transferred; #else // defined(ASIO_WINDOWS) || defined(__CYGWIN__)-#if defined(__linux__)+#if defined(ASIO_HAS_MSG_NOSIGNAL) flags |= MSG_NOSIGNAL;-#endif // defined(__linux__)+#endif // defined(ASIO_HAS_MSG_NOSIGNAL) signed_size_type result = ::send(s, static_cast<const char*>(data), size, flags); get_last_error(ec, result < 0);@@ -1440,7 +1441,7 @@ // A request to write 0 bytes to a stream is a no-op. if (all_empty && (state & stream_oriented)) {- ec.assign(0, ec.category());+ asio::error::clear(ec); return 0; } @@ -1478,7 +1479,7 @@ // A request to write 0 bytes to a stream is a no-op. if (size == 0 && (state & stream_oriented)) {- ec.assign(0, ec.category());+ asio::error::clear(ec); return 0; } @@ -1590,16 +1591,17 @@ #endif // defined(ASIO_HAS_IOCP) -signed_size_type sendto(socket_type s, const buf* bufs, size_t count,- int flags, const socket_addr_type* addr, std::size_t addrlen,- asio::error_code& ec)+signed_size_type sendto(socket_type s, const buf* bufs,+ size_t count, int flags, const void* addr,+ std::size_t addrlen, asio::error_code& ec) { #if defined(ASIO_WINDOWS) || defined(__CYGWIN__) // Send the data. DWORD send_buf_count = static_cast<DWORD>(count); DWORD bytes_transferred = 0; int result = ::WSASendTo(s, const_cast<buf*>(bufs),- send_buf_count, &bytes_transferred, flags, addr,+ send_buf_count, &bytes_transferred, flags,+ static_cast<const socket_addr_type*>(addr), static_cast<int>(addrlen), 0, 0); get_last_error(ec, true); if (ec.value() == ERROR_NETNAME_DELETED)@@ -1608,7 +1610,7 @@ ec = asio::error::connection_refused; if (result != 0) return socket_error_retval;- ec.assign(0, ec.category());+ asio::error::clear(ec); return bytes_transferred; #else // defined(ASIO_WINDOWS) || defined(__CYGWIN__) msghdr msg = msghdr();@@ -1616,9 +1618,9 @@ msg.msg_namelen = static_cast<int>(addrlen); msg.msg_iov = const_cast<buf*>(bufs); msg.msg_iovlen = static_cast<int>(count);-#if defined(__linux__)+#if defined(ASIO_HAS_MSG_NOSIGNAL) flags |= MSG_NOSIGNAL;-#endif // defined(__linux__)+#endif // defined(ASIO_HAS_MSG_NOSIGNAL) signed_size_type result = ::sendmsg(s, &msg, flags); get_last_error(ec, result < 0); return result;@@ -1628,15 +1630,15 @@ template <typename SockLenType> inline signed_size_type call_sendto(SockLenType msghdr::*, socket_type s, const void* data, size_t size, int flags,- const socket_addr_type* addr, std::size_t addrlen)+ const void* addr, std::size_t addrlen) {- return ::sendto(s, static_cast<char*>(const_cast<void*>(data)),- size, flags, addr, (SockLenType)addrlen);+ return ::sendto(s, static_cast<char*>(const_cast<void*>(data)), size, flags,+ static_cast<const socket_addr_type*>(addr), (SockLenType)addrlen); } -signed_size_type sendto1(socket_type s, const void* data, size_t size,- int flags, const socket_addr_type* addr, std::size_t addrlen,- asio::error_code& ec)+signed_size_type sendto1(socket_type s, const void* data,+ size_t size, int flags, const void* addr,+ std::size_t addrlen, asio::error_code& ec) { #if defined(ASIO_WINDOWS) || defined(__CYGWIN__) // Send the data.@@ -1644,8 +1646,9 @@ buf.buf = const_cast<char*>(static_cast<const char*>(data)); buf.len = static_cast<ULONG>(size); DWORD bytes_transferred = 0;- int result = ::WSASendTo(s, &buf, 1, &bytes_transferred,- flags, addr, static_cast<int>(addrlen), 0, 0);+ int result = ::WSASendTo(s, &buf, 1, &bytes_transferred, flags,+ static_cast<const socket_addr_type*>(addr),+ static_cast<int>(addrlen), 0, 0); get_last_error(ec, true); if (ec.value() == ERROR_NETNAME_DELETED) ec = asio::error::connection_reset;@@ -1653,12 +1656,12 @@ ec = asio::error::connection_refused; if (result != 0) return socket_error_retval;- ec.assign(0, ec.category());+ asio::error::clear(ec); return bytes_transferred; #else // defined(ASIO_WINDOWS) || defined(__CYGWIN__)-#if defined(__linux__)+#if defined(ASIO_HAS_MSG_NOSIGNAL) flags |= MSG_NOSIGNAL;-#endif // defined(__linux__)+#endif // defined(ASIO_HAS_MSG_NOSIGNAL) signed_size_type result = call_sendto(&msghdr::msg_namelen, s, data, size, flags, addr, addrlen); get_last_error(ec, result < 0);@@ -1666,8 +1669,8 @@ #endif // defined(ASIO_WINDOWS) || defined(__CYGWIN__) } -size_t sync_sendto(socket_type s, state_type state, const buf* bufs,- size_t count, int flags, const socket_addr_type* addr,+size_t sync_sendto(socket_type s, state_type state,+ const buf* bufs, size_t count, int flags, const void* addr, std::size_t addrlen, asio::error_code& ec) { if (s == invalid_socket)@@ -1699,8 +1702,8 @@ } } -size_t sync_sendto1(socket_type s, state_type state, const void* data,- size_t size, int flags, const socket_addr_type* addr,+size_t sync_sendto1(socket_type s, state_type state,+ const void* data, size_t size, int flags, const void* addr, std::size_t addrlen, asio::error_code& ec) { if (s == invalid_socket)@@ -1736,7 +1739,7 @@ bool non_blocking_sendto(socket_type s, const buf* bufs, size_t count, int flags,- const socket_addr_type* addr, std::size_t addrlen,+ const void* addr, std::size_t addrlen, asio::error_code& ec, size_t& bytes_transferred) { for (;;)@@ -1769,7 +1772,7 @@ bool non_blocking_sendto1(socket_type s, const void* data, size_t size, int flags,- const socket_addr_type* addr, std::size_t addrlen,+ const void* addr, std::size_t addrlen, asio::error_code& ec, size_t& bytes_transferred) { for (;;)@@ -1824,7 +1827,9 @@ return s; #elif defined(__MACH__) && defined(__APPLE__) || defined(__FreeBSD__) socket_type s = ::socket(af, type, protocol);- get_last_error(ec, s < 0);+ get_last_error(ec, s == invalid_socket);+ if (s == invalid_socket)+ return s; int optval = 1; int result = ::setsockopt(s, SOL_SOCKET,@@ -1881,7 +1886,7 @@ state |= enable_connection_aborted; else state &= ~enable_connection_aborted;- ec.assign(0, ec.category());+ asio::error::clear(ec); return 0; } @@ -1966,7 +1971,7 @@ } *static_cast<int*>(optval) = (state & enable_connection_aborted) ? 1 : 0;- ec.assign(0, ec.category());+ asio::error::clear(ec); return 0; } @@ -1993,7 +1998,7 @@ // value is non-zero (i.e. true). This corresponds to the behavior of // IPv6 sockets on Windows platforms pre-Vista. *static_cast<DWORD*>(optval) = 1;- ec.assign(0, ec.category());+ asio::error::clear(ec); } return result; }@@ -2013,7 +2018,7 @@ // non-zero (i.e. true). This corresponds to the behavior of IPv6 sockets // on Windows platforms pre-Vista. *static_cast<DWORD*>(optval) = 1;- ec.assign(0, ec.category());+ asio::error::clear(ec); } return result; #else // defined(ASIO_WINDOWS) || defined(__CYGWIN__)@@ -2038,16 +2043,17 @@ template <typename SockLenType> inline int call_getpeername(SockLenType msghdr::*,- socket_type s, socket_addr_type* addr, std::size_t* addrlen)+ socket_type s, void* addr, std::size_t* addrlen) { SockLenType tmp_addrlen = (SockLenType)*addrlen;- int result = ::getpeername(s, addr, &tmp_addrlen);+ int result = ::getpeername(s,+ static_cast<socket_addr_type*>(addr), &tmp_addrlen); *addrlen = (std::size_t)tmp_addrlen; return result; } -int getpeername(socket_type s, socket_addr_type* addr,- std::size_t* addrlen, bool cached, asio::error_code& ec)+int getpeername(socket_type s, void* addr, std::size_t* addrlen,+ bool cached, asio::error_code& ec) { if (s == invalid_socket) {@@ -2074,7 +2080,7 @@ } // The cached value is still valid.- ec.assign(0, ec.category());+ asio::error::clear(ec); return 0; } #else // defined(ASIO_WINDOWS) && !defined(ASIO_WINDOWS_APP)@@ -2090,15 +2096,16 @@ template <typename SockLenType> inline int call_getsockname(SockLenType msghdr::*,- socket_type s, socket_addr_type* addr, std::size_t* addrlen)+ socket_type s, void* addr, std::size_t* addrlen) { SockLenType tmp_addrlen = (SockLenType)*addrlen;- int result = ::getsockname(s, addr, &tmp_addrlen);+ int result = ::getsockname(s,+ static_cast<socket_addr_type*>(addr), &tmp_addrlen); *addrlen = (std::size_t)tmp_addrlen; return result; } -int getsockname(socket_type s, socket_addr_type* addr,+int getsockname(socket_type s, void* addr, std::size_t* addrlen, asio::error_code& ec) { if (s == invalid_socket)@@ -2169,7 +2176,7 @@ if (milliseconds == 0) milliseconds = 1; // Force context switch. ::Sleep(milliseconds);- ec.assign(0, ec.category());+ asio::error::clear(ec); return 0; } @@ -2489,7 +2496,7 @@ // Windows may set error code on success. if (result != socket_error_retval)- ec.assign(0, ec.category());+ asio::error::clear(ec); // Windows may not set an error code on failure. else if (result == socket_error_retval && !ec)@@ -2512,7 +2519,11 @@ && ((ipv6_address->s6_addr[1] & 0x0f) == 0x02)); if ((!is_link_local && !is_multicast_link_local) || if_indextoname(static_cast<unsigned>(scope_id), if_name + 1) == 0)+#if defined(ASIO_HAS_SNPRINTF)+ snprintf(if_name + 1, sizeof(if_name) - 1, "%lu", scope_id);+#else // defined(ASIO_HAS_SNPRINTF) sprintf(if_name + 1, "%lu", scope_id);+#endif // defined(ASIO_HAS_SNPRINTF) strcat(dest, if_name); } return result;@@ -2543,7 +2554,7 @@ bytes[1] = static_cast<unsigned char>(b1); bytes[2] = static_cast<unsigned char>(b2); bytes[3] = static_cast<unsigned char>(b3);- ec.assign(), ec.category());+ asio::error::clear(ec); return 1; } else if (af == ASIO_OS_DEF(AF_INET6))@@ -2659,7 +2670,7 @@ for (int i = 0; i < num_back_bytes; ++i) bytes[16 - num_back_bytes + i] = back_bytes[i]; - ec.assign(0, ec.category());+ asio::error::clear(ec); return 1; } else@@ -2702,12 +2713,12 @@ if (result != socket_error_retval) { memcpy(dest, &address.v4.sin_addr, sizeof(in4_addr_type));- ec.assign(0, ec.category());+ asio::error::clear(ec); } else if (strcmp(src, "255.255.255.255") == 0) { static_cast<in4_addr_type*>(dest)->s_addr = INADDR_NONE;- ec.assign(0, ec.category());+ asio::error::clear(ec); } } else // AF_INET6@@ -2717,7 +2728,7 @@ memcpy(dest, &address.v6.sin6_addr, sizeof(in6_addr_type)); if (scope_id) *scope_id = address.v6.sin6_scope_id;- ec.assign(0, ec.category());+ asio::error::clear(ec); } } @@ -2726,7 +2737,7 @@ ec = asio::error::invalid_argument; if (result != socket_error_retval)- ec.assign(0, ec.category());+ asio::error::clear(ec); return result == socket_error_retval ? -1 : 1; #else // defined(ASIO_WINDOWS) || defined(__CYGWIN__)@@ -3620,7 +3631,9 @@ { return ec = asio::error::no_buffer_space; }-#if defined(ASIO_HAS_SECURE_RTL)+#if defined(ASIO_HAS_SNPRINTF)+ snprintf(serv, servlen, "%u", ntohs(port));+#elif defined(ASIO_HAS_SECURE_RTL) sprintf_s(serv, servlen, "%u", ntohs(port)); #else // defined(ASIO_HAS_SECURE_RTL) sprintf(serv, "%u", ntohs(port));@@ -3643,7 +3656,9 @@ { return ec = asio::error::no_buffer_space; }-#if defined(ASIO_HAS_SECURE_RTL)+#if defined(ASIO_HAS_SNPRINTF)+ snprintf(serv, servlen, "%u", ntohs(port));+#elif defined(ASIO_HAS_SECURE_RTL) sprintf_s(serv, servlen, "%u", ntohs(port)); #else // defined(ASIO_HAS_SECURE_RTL) sprintf(serv, "%u", ntohs(port));@@ -3655,7 +3670,7 @@ } } - ec.assign(0, ec.category());+ asio::error::clear(ec); return ec; } @@ -3805,7 +3820,7 @@ #endif } -asio::error_code getnameinfo(const socket_addr_type* addr,+asio::error_code getnameinfo(const void* addr, std::size_t addrlen, char* host, std::size_t hostlen, char* serv, std::size_t servlen, int flags, asio::error_code& ec) {@@ -3813,8 +3828,8 @@ # if defined(ASIO_HAS_GETADDRINFO) // Building for Windows XP, Windows Server 2003, or later. clear_last_error();- int error = ::getnameinfo(addr, static_cast<socklen_t>(addrlen),- host, static_cast<DWORD>(hostlen),+ int error = ::getnameinfo(static_cast<const socket_addr_type*>(addr),+ static_cast<socklen_t>(addrlen), host, static_cast<DWORD>(hostlen), serv, static_cast<DWORD>(servlen), flags); return ec = translate_addrinfo_error(error); # else@@ -3826,34 +3841,34 @@ if (gni_t gni = (gni_t)::GetProcAddress(winsock_module, "getnameinfo")) { clear_last_error();- int error = gni(addr, static_cast<int>(addrlen),- host, static_cast<DWORD>(hostlen),+ int error = gni(static_cast<const socket_addr_type*>(addr),+ static_cast<int>(addrlen), host, static_cast<DWORD>(hostlen), serv, static_cast<DWORD>(servlen), flags); return ec = translate_addrinfo_error(error); } } clear_last_error();- return getnameinfo_emulation(addr, addrlen,- host, hostlen, serv, servlen, flags, ec);+ return getnameinfo_emulation(static_cast<const socket_addr_type*>(addr),+ addrlen, host, hostlen, serv, servlen, flags, ec); # endif #elif !defined(ASIO_HAS_GETADDRINFO) using namespace std; // For memcpy. sockaddr_storage_type tmp_addr; memcpy(&tmp_addr, addr, addrlen);- addr = reinterpret_cast<socket_addr_type*>(&tmp_addr);+ addr = &tmp_addr; clear_last_error();- return getnameinfo_emulation(addr, addrlen,- host, hostlen, serv, servlen, flags, ec);+ return getnameinfo_emulation(static_cast<const socket_addr_type*>(addr),+ addrlen, host, hostlen, serv, servlen, flags, ec); #else clear_last_error();- int error = ::getnameinfo(addr, addrlen, host, hostlen, serv, servlen, flags);+ int error = ::getnameinfo(static_cast<const socket_addr_type*>(addr),+ addrlen, host, hostlen, serv, servlen, flags); return ec = translate_addrinfo_error(error); #endif } -asio::error_code sync_getnameinfo(- const socket_addr_type* addr, std::size_t addrlen,- char* host, std::size_t hostlen, char* serv,+asio::error_code sync_getnameinfo(const void* addr,+ std::size_t addrlen, char* host, std::size_t hostlen, char* serv, std::size_t servlen, int sock_type, asio::error_code& ec) { // First try resolving with the service name. If that fails try resolving@@ -3872,7 +3887,7 @@ asio::error_code background_getnameinfo( const weak_cancel_token_type& cancel_token,- const socket_addr_type* addr, std::size_t addrlen,+ const void* addr, std::size_t addrlen, char* host, std::size_t hostlen, char* serv, std::size_t servlen, int sock_type, asio::error_code& ec) {
link/modules/asio-standalone/asio/include/asio/detail/impl/socket_select_interrupter.ipp view
@@ -2,7 +2,7 @@ // detail/impl/socket_select_interrupter.ipp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -60,11 +60,11 @@ addr.sin_family = AF_INET; addr.sin_addr.s_addr = socket_ops::host_to_network_long(INADDR_LOOPBACK); addr.sin_port = 0;- if (socket_ops::bind(acceptor.get(), (const socket_addr_type*)&addr,+ if (socket_ops::bind(acceptor.get(), &addr, addr_len, ec) == socket_error_retval) asio::detail::throw_error(ec, "socket_select_interrupter"); - if (socket_ops::getsockname(acceptor.get(), (socket_addr_type*)&addr,+ if (socket_ops::getsockname(acceptor.get(), &addr, &addr_len, ec) == socket_error_retval) asio::detail::throw_error(ec, "socket_select_interrupter"); @@ -83,7 +83,7 @@ if (client.get() == invalid_socket) asio::detail::throw_error(ec, "socket_select_interrupter"); - if (socket_ops::connect(client.get(), (const socket_addr_type*)&addr,+ if (socket_ops::connect(client.get(), &addr, addr_len, ec) == socket_error_retval) asio::detail::throw_error(ec, "socket_select_interrupter");
link/modules/asio-standalone/asio/include/asio/detail/impl/strand_executor_service.hpp view
@@ -2,7 +2,7 @@ // detail/impl/strand_executor_service.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -15,7 +15,6 @@ # pragma once #endif // defined(_MSC_VER) && (_MSC_VER >= 1200) -#include "asio/detail/call_stack.hpp" #include "asio/detail/fenced_block.hpp" #include "asio/detail/handler_invoke_helpers.hpp" #include "asio/detail/recycling_allocator.hpp"@@ -103,42 +102,37 @@ ~on_invoker_exit() {- this_->impl_->mutex_->lock();- this_->impl_->ready_queue_.push(this_->impl_->waiting_queue_);- bool more_handlers = this_->impl_->locked_ =- !this_->impl_->ready_queue_.empty();- this_->impl_->mutex_->unlock();-- if (more_handlers)+ if (push_waiting_to_ready(this_->impl_)) { recycling_allocator<void> allocator;+ executor_type ex = this_->executor_;+#if defined(ASIO_NO_DEPRECATED)+ asio::prefer(+ asio::require(+ ASIO_MOVE_CAST(executor_type)(ex),+ execution::blocking.never),+ execution::allocator(allocator)+ ).execute(ASIO_MOVE_CAST(invoker)(*this_));+#else // defined(ASIO_NO_DEPRECATED) execution::execute( asio::prefer(- asio::require(this_->executor_,+ asio::require(+ ASIO_MOVE_CAST(executor_type)(ex), execution::blocking.never),- execution::allocator(allocator)),+ execution::allocator(allocator)), ASIO_MOVE_CAST(invoker)(*this_));+#endif // defined(ASIO_NO_DEPRECATED) } } }; void operator()() {- // Indicate that this strand is executing on the current thread.- call_stack<strand_impl>::context ctx(impl_.get());- // Ensure the next handler, if any, is scheduled on block exit. on_invoker_exit on_exit = { this }; (void)on_exit; - // Run all ready handlers. No lock is required since the ready queue is- // accessed only within the strand.- asio::error_code ec;- while (scheduler_operation* o = impl_->ready_queue_.front())- {- impl_->ready_queue_.pop();- o->complete(impl_.get(), ec, 0);- }+ run_ready_handlers(impl_); } private:@@ -188,13 +182,7 @@ ~on_invoker_exit() {- this_->impl_->mutex_->lock();- this_->impl_->ready_queue_.push(this_->impl_->waiting_queue_);- bool more_handlers = this_->impl_->locked_ =- !this_->impl_->ready_queue_.empty();- this_->impl_->mutex_->unlock();-- if (more_handlers)+ if (push_waiting_to_ready(this_->impl_)) { Executor ex(this_->work_.get_executor()); recycling_allocator<void> allocator;@@ -205,21 +193,11 @@ void operator()() {- // Indicate that this strand is executing on the current thread.- call_stack<strand_impl>::context ctx(impl_.get());- // Ensure the next handler, if any, is scheduled on block exit. on_invoker_exit on_exit = { this }; (void)on_exit; - // Run all ready handlers. No lock is required since the ready queue is- // accessed only within the strand.- asio::error_code ec;- while (scheduler_operation* o = impl_->ready_queue_.front())- {- impl_->ready_queue_.pop();- o->complete(impl_.get(), ec, 0);- }+ run_ready_handlers(impl_); } private:@@ -262,7 +240,7 @@ // If the executor is not never-blocking, and we are already in the strand, // then the function can run immediately. if (asio::query(ex, execution::blocking) != execution::blocking.never- && call_stack<strand_impl>::contains(impl.get()))+ && running_in_this_thread(impl)) { // Make a local, non-const copy of the function. function_type tmp(ASIO_MOVE_CAST(Function)(function));@@ -285,7 +263,11 @@ p.v = p.p = 0; if (first) {+#if defined(ASIO_NO_DEPRECATED)+ ex.execute(invoker<Executor>(impl, ex));+#else // defined(ASIO_NO_DEPRECATED) execution::execute(ex, invoker<Executor>(impl, ex));+#endif // defined(ASIO_NO_DEPRECATED) } } @@ -296,7 +278,7 @@ typedef typename decay<Function>::type function_type; // If we are already in the strand then the function can run immediately.- if (call_stack<strand_impl>::contains(impl.get()))+ if (running_in_this_thread(impl)) { // Make a local, non-const copy of the function. function_type tmp(ASIO_MOVE_CAST(Function)(function));
link/modules/asio-standalone/asio/include/asio/detail/impl/strand_executor_service.ipp view
@@ -2,7 +2,7 @@ // detail/impl/strand_executor_service.ipp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -124,6 +124,30 @@ const implementation_type& impl) { return !!call_stack<strand_impl>::contains(impl.get());+}++bool strand_executor_service::push_waiting_to_ready(implementation_type& impl)+{+ impl->mutex_->lock();+ impl->ready_queue_.push(impl->waiting_queue_);+ bool more_handlers = impl->locked_ = !impl->ready_queue_.empty();+ impl->mutex_->unlock();+ return more_handlers;+}++void strand_executor_service::run_ready_handlers(implementation_type& impl)+{+ // Indicate that this strand is executing on the current thread.+ call_stack<strand_impl>::context ctx(impl.get());++ // Run all ready handlers. No lock is required since the ready queue is+ // accessed only within the strand.+ asio::error_code ec;+ while (scheduler_operation* o = impl->ready_queue_.front())+ {+ impl->ready_queue_.pop();+ o->complete(impl.get(), ec, 0);+ } } } // namespace detail
link/modules/asio-standalone/asio/include/asio/detail/impl/strand_service.hpp view
@@ -2,7 +2,7 @@ // detail/impl/strand_service.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -15,7 +15,6 @@ # pragma once #endif // defined(_MSC_VER) && (_MSC_VER >= 1200) -#include "asio/detail/call_stack.hpp" #include "asio/detail/completion_handler.hpp" #include "asio/detail/fenced_block.hpp" #include "asio/detail/handler_alloc_helpers.hpp"@@ -33,29 +32,12 @@ { } -struct strand_service::on_dispatch_exit-{- io_context_impl* io_context_impl_;- strand_impl* impl_;-- ~on_dispatch_exit()- {- impl_->mutex_.lock();- impl_->ready_queue_.push(impl_->waiting_queue_);- bool more_handlers = impl_->locked_ = !impl_->ready_queue_.empty();- impl_->mutex_.unlock();-- if (more_handlers)- io_context_impl_->post_immediate_completion(impl_, false);- }-};- template <typename Handler> void strand_service::dispatch(strand_service::implementation_type& impl, Handler& handler) { // If we are already in the strand then the handler can run immediately.- if (call_stack<strand_impl>::contains(impl))+ if (running_in_this_thread(impl)) { fenced_block b(fenced_block::full); asio_handler_invoke_helpers::invoke(handler, handler);@@ -71,21 +53,9 @@ ASIO_HANDLER_CREATION((this->context(), *p.p, "strand", impl, 0, "dispatch")); - bool dispatch_immediately = do_dispatch(impl, p.p); operation* o = p.p; p.v = p.p = 0;-- if (dispatch_immediately)- {- // Indicate that this strand is executing on the current thread.- call_stack<strand_impl>::context ctx(impl);-- // Ensure the next handler, if any, is scheduled on block exit.- on_dispatch_exit on_exit = { &io_context_impl_, impl };- (void)on_exit;-- op::do_complete(&io_context_impl_, o, asio::error_code(), 0);- }+ do_dispatch(impl, o); } // Request the io_context to invoke the given handler and return immediately.
link/modules/asio-standalone/asio/include/asio/detail/impl/strand_service.ipp view
@@ -2,7 +2,7 @@ // detail/impl/strand_service.ipp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -91,8 +91,25 @@ return call_stack<strand_impl>::contains(impl) != 0; } -bool strand_service::do_dispatch(implementation_type& impl, operation* op)+struct strand_service::on_dispatch_exit {+ io_context_impl* io_context_impl_;+ strand_impl* impl_;++ ~on_dispatch_exit()+ {+ impl_->mutex_.lock();+ impl_->ready_queue_.push(impl_->waiting_queue_);+ bool more_handlers = impl_->locked_ = !impl_->ready_queue_.empty();+ impl_->mutex_.unlock();++ if (more_handlers)+ io_context_impl_->post_immediate_completion(impl_, false);+ }+};++void strand_service::do_dispatch(implementation_type& impl, operation* op)+{ // If we are running inside the io_context, and no other handler already // holds the strand lock, then the handler can run immediately. bool can_dispatch = io_context_impl_.can_dispatch();@@ -102,7 +119,16 @@ // Immediate invocation is allowed. impl->locked_ = true; impl->mutex_.unlock();- return true;++ // Indicate that this strand is executing on the current thread.+ call_stack<strand_impl>::context ctx(impl);++ // Ensure the next handler, if any, is scheduled on block exit.+ on_dispatch_exit on_exit = { &io_context_impl_, impl };+ (void)on_exit;++ op->complete(&io_context_impl_, asio::error_code(), 0);+ return; } if (impl->locked_)@@ -120,8 +146,6 @@ impl->ready_queue_.push(op); io_context_impl_.post_immediate_completion(impl, false); }-- return false; } void strand_service::do_post(implementation_type& impl,
+ link/modules/asio-standalone/asio/include/asio/detail/impl/thread_context.ipp view
@@ -0,0 +1,35 @@+//+// detail/impl/thread_context.ipp+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com)+//+// Distributed under the Boost Software License, Version 1.0. (See accompanying+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)+//++#ifndef ASIO_DETAIL_IMPL_THREAD_CONTEXT_IPP+#define ASIO_DETAIL_IMPL_THREAD_CONTEXT_IPP++#if defined(_MSC_VER) && (_MSC_VER >= 1200)+# pragma once+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)++#include "asio/detail/config.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {+namespace detail {++thread_info_base* thread_context::top_of_thread_call_stack()+{+ return thread_call_stack::top();+}++} // namespace detail+} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // ASIO_DETAIL_IMPL_THREAD_CONTEXT_IPP
link/modules/asio-standalone/asio/include/asio/detail/impl/throw_error.ipp view
@@ -2,7 +2,7 @@ // detail/impl/throw_error.ipp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -17,7 +17,6 @@ #include "asio/detail/config.hpp" #include "asio/detail/throw_error.hpp"-#include "asio/detail/throw_exception.hpp" #include "asio/system_error.hpp" #include "asio/detail/push_options.hpp"@@ -25,16 +24,23 @@ namespace asio { namespace detail { -void do_throw_error(const asio::error_code& err)+void do_throw_error(+ const asio::error_code& err+ ASIO_SOURCE_LOCATION_PARAM) { asio::system_error e(err);- asio::detail::throw_exception(e);+ asio::detail::throw_exception(e ASIO_SOURCE_LOCATION_ARG); } -void do_throw_error(const asio::error_code& err, const char* location)+void do_throw_error(+ const asio::error_code& err,+ const char* location+ ASIO_SOURCE_LOCATION_PARAM) { // boostify: non-boost code starts here-#if defined(ASIO_MSVC) && defined(ASIO_HAS_STD_SYSTEM_ERROR)+#if defined(ASIO_MSVC) \+ && defined(ASIO_HAS_STD_SYSTEM_ERROR) \+ && (_MSC_VER < 1800) // Microsoft's implementation of std::system_error is non-conformant in that // it ignores the error code's message when a "what" string is supplied. We'll // work around this by explicitly formatting the "what" string.@@ -42,13 +48,17 @@ what_msg += ": "; what_msg += err.message(); asio::system_error e(err, what_msg);- asio::detail::throw_exception(e);-#else // defined(ASIO_MSVC) && defined(ASIO_HAS_STD_SYSTEM_ERROR)+ asio::detail::throw_exception(e ASIO_SOURCE_LOCATION_ARG);+#else // defined(ASIO_MSVC)+ // && defined(ASIO_HAS_STD_SYSTEM_ERROR)+ // && (_MSC_VER < 1928) // boostify: non-boost code ends here asio::system_error e(err, location);- asio::detail::throw_exception(e);+ asio::detail::throw_exception(e ASIO_SOURCE_LOCATION_ARG); // boostify: non-boost code starts here-#endif // defined(ASIO_MSVC) && defined(ASIO_HAS_STD_SYSTEM_ERROR)+#endif // defined(ASIO_MSVC)+ // && defined(ASIO_HAS_STD_SYSTEM_ERROR)+ // && (_MSC_VER < 1800) // boostify: non-boost code ends here }
link/modules/asio-standalone/asio/include/asio/detail/impl/timer_queue_ptime.ipp view
@@ -2,7 +2,7 @@ // detail/impl/timer_queue_ptime.ipp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -73,6 +73,12 @@ per_timer_data& timer, op_queue<operation>& ops, std::size_t max_cancelled) { return impl_.cancel_timer(timer, ops, max_cancelled);+}++void timer_queue<time_traits<boost::posix_time::ptime> >::cancel_timer_by_key(+ per_timer_data* timer, op_queue<operation>& ops, void* cancellation_key)+{+ impl_.cancel_timer_by_key(timer, ops, cancellation_key); } void timer_queue<time_traits<boost::posix_time::ptime> >::move_timer(
link/modules/asio-standalone/asio/include/asio/detail/impl/timer_queue_set.ipp view
@@ -2,7 +2,7 @@ // detail/impl/timer_queue_set.ipp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/detail/impl/win_event.ipp view
@@ -2,7 +2,7 @@ // detail/win_event.ipp // ~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+ link/modules/asio-standalone/asio/include/asio/detail/impl/win_iocp_file_service.ipp view
@@ -0,0 +1,265 @@+//+// detail/impl/win_iocp_file_service.ipp+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com)+//+// Distributed under the Boost Software License, Version 1.0. (See accompanying+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)+//++#ifndef ASIO_DETAIL_IMPL_WIN_IOCP_FILE_SERVICE_IPP+#define ASIO_DETAIL_IMPL_WIN_IOCP_FILE_SERVICE_IPP++#if defined(_MSC_VER) && (_MSC_VER >= 1200)+# pragma once+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)++#include "asio/detail/config.hpp"++#if defined(ASIO_HAS_FILE) \+ && defined(ASIO_HAS_WINDOWS_RANDOM_ACCESS_HANDLE)++#include <cstring>+#include <sys/stat.h>+#include "asio/detail/win_iocp_file_service.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {+namespace detail {++win_iocp_file_service::win_iocp_file_service(+ execution_context& context)+ : execution_context_service_base<win_iocp_file_service>(context),+ handle_service_(context),+ nt_flush_buffers_file_ex_(0)+{+ if (FARPROC nt_flush_buffers_file_ex_ptr = ::GetProcAddress(+ ::GetModuleHandleA("NTDLL"), "NtFlushBuffersFileEx"))+ {+ nt_flush_buffers_file_ex_ = reinterpret_cast<nt_flush_buffers_file_ex_fn>(+ reinterpret_cast<void*>(nt_flush_buffers_file_ex_ptr));+ }+}++void win_iocp_file_service::shutdown()+{+ handle_service_.shutdown();+}++asio::error_code win_iocp_file_service::open(+ win_iocp_file_service::implementation_type& impl,+ const char* path, file_base::flags open_flags,+ asio::error_code& ec)+{+ if (is_open(impl))+ {+ ec = asio::error::already_open;+ ASIO_ERROR_LOCATION(ec);+ return ec;+ }++ DWORD access = 0;+ if ((open_flags & file_base::read_only) != 0)+ access = GENERIC_READ;+ else if ((open_flags & file_base::write_only) != 0)+ access = GENERIC_WRITE;+ else if ((open_flags & file_base::read_write) != 0)+ access = GENERIC_READ | GENERIC_WRITE;++ DWORD share = FILE_SHARE_READ | FILE_SHARE_WRITE;++ DWORD disposition = 0;+ if ((open_flags & file_base::create) != 0)+ {+ if ((open_flags & file_base::exclusive) != 0)+ disposition = CREATE_NEW;+ else+ disposition = OPEN_ALWAYS;+ }+ else+ {+ if ((open_flags & file_base::truncate) != 0)+ disposition = TRUNCATE_EXISTING;+ else+ disposition = OPEN_EXISTING;+ }++ DWORD flags = FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED;+ if (impl.is_stream_)+ flags |= FILE_FLAG_SEQUENTIAL_SCAN;+ else+ flags |= FILE_FLAG_RANDOM_ACCESS;+ if ((open_flags & file_base::sync_all_on_write) != 0)+ flags |= FILE_FLAG_WRITE_THROUGH;++ HANDLE handle = ::CreateFileA(path, access, share, 0, disposition, flags, 0);+ if (handle != INVALID_HANDLE_VALUE)+ {+ if (disposition == OPEN_ALWAYS && (open_flags & file_base::truncate) != 0)+ {+ if (!::SetEndOfFile(handle))+ {+ DWORD last_error = ::GetLastError();+ ::CloseHandle(handle);+ ec.assign(last_error, asio::error::get_system_category());+ ASIO_ERROR_LOCATION(ec);+ return ec;+ }+ }++ handle_service_.assign(impl, handle, ec);+ if (ec)+ ::CloseHandle(handle);+ impl.offset_ = 0;+ ASIO_ERROR_LOCATION(ec);+ return ec;+ }+ else+ {+ DWORD last_error = ::GetLastError();+ ec.assign(last_error, asio::error::get_system_category());+ ASIO_ERROR_LOCATION(ec);+ return ec;+ }+}++uint64_t win_iocp_file_service::size(+ const win_iocp_file_service::implementation_type& impl,+ asio::error_code& ec) const+{+ LARGE_INTEGER result;+ if (::GetFileSizeEx(native_handle(impl), &result))+ {+ asio::error::clear(ec);+ return static_cast<uint64_t>(result.QuadPart);+ }+ else+ {+ DWORD last_error = ::GetLastError();+ ec.assign(last_error, asio::error::get_system_category());+ ASIO_ERROR_LOCATION(ec);+ return 0;+ }+}++asio::error_code win_iocp_file_service::resize(+ win_iocp_file_service::implementation_type& impl,+ uint64_t n, asio::error_code& ec)+{+ LARGE_INTEGER distance;+ distance.QuadPart = n;+ if (::SetFilePointerEx(native_handle(impl), distance, 0, FILE_BEGIN))+ {+ BOOL result = ::SetEndOfFile(native_handle(impl));+ DWORD last_error = ::GetLastError();++ distance.QuadPart = static_cast<LONGLONG>(impl.offset_);+ if (!::SetFilePointerEx(native_handle(impl), distance, 0, FILE_BEGIN))+ {+ result = FALSE;+ last_error = ::GetLastError();+ }++ if (result)+ asio::error::clear(ec);+ else+ ec.assign(last_error, asio::error::get_system_category());+ ASIO_ERROR_LOCATION(ec);+ return ec;+ }+ else+ {+ DWORD last_error = ::GetLastError();+ ec.assign(last_error, asio::error::get_system_category());+ ASIO_ERROR_LOCATION(ec);+ return ec;+ }+}++asio::error_code win_iocp_file_service::sync_all(+ win_iocp_file_service::implementation_type& impl,+ asio::error_code& ec)+{+ BOOL result = ::FlushFileBuffers(native_handle(impl));+ if (result)+ {+ asio::error::clear(ec);+ return ec;+ }+ else+ {+ DWORD last_error = ::GetLastError();+ ec.assign(last_error, asio::error::get_system_category());+ ASIO_ERROR_LOCATION(ec);+ return ec;+ }+}++asio::error_code win_iocp_file_service::sync_data(+ win_iocp_file_service::implementation_type& impl,+ asio::error_code& ec)+{+ if (nt_flush_buffers_file_ex_)+ {+ io_status_block status = {};+ if (!nt_flush_buffers_file_ex_(native_handle(impl),+ flush_flags_file_data_sync_only, 0, 0, &status))+ {+ asio::error::clear(ec);+ return ec;+ }+ }+ return sync_all(impl, ec);+}++uint64_t win_iocp_file_service::seek(+ win_iocp_file_service::implementation_type& impl, int64_t offset,+ file_base::seek_basis whence, asio::error_code& ec)+{+ DWORD method;+ switch (whence)+ {+ case file_base::seek_set:+ method = FILE_BEGIN;+ break;+ case file_base::seek_cur:+ method = FILE_BEGIN;+ offset = static_cast<int64_t>(impl.offset_) + offset;+ break;+ case file_base::seek_end:+ method = FILE_END;+ break;+ default:+ ec = asio::error::invalid_argument;+ ASIO_ERROR_LOCATION(ec);+ return 0;+ }++ LARGE_INTEGER distance, new_offset;+ distance.QuadPart = offset;+ if (::SetFilePointerEx(native_handle(impl), distance, &new_offset, method))+ {+ impl.offset_ = new_offset.QuadPart;+ asio::error::clear(ec);+ return impl.offset_;+ }+ else+ {+ DWORD last_error = ::GetLastError();+ ec.assign(last_error, asio::error::get_system_category());+ ASIO_ERROR_LOCATION(ec);+ return 0;+ }+}++} // namespace detail+} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // defined(ASIO_HAS_FILE)+ // && defined(ASIO_HAS_WINDOWS_RANDOM_ACCESS_HANDLE)++#endif // ASIO_DETAIL_IMPL_WIN_IOCP_FILE_SERVICE_IPP
link/modules/asio-standalone/asio/include/asio/detail/impl/win_iocp_handle_service.ipp view
@@ -2,7 +2,7 @@ // detail/impl/win_iocp_handle_service.ipp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // Copyright (c) 2008 Rep Invariant Systems, Inc. (info@repinvariant.com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying@@ -68,6 +68,7 @@ win_iocp_handle_service::win_iocp_handle_service(execution_context& context) : execution_context_service_base<win_iocp_handle_service>(context), iocp_service_(asio::use_service<win_iocp_io_context>(context)),+ nt_set_info_(0), mutex_(), impl_list_(0) {@@ -182,11 +183,15 @@ if (is_open(impl)) { ec = asio::error::already_open;+ ASIO_ERROR_LOCATION(ec); return ec; } if (iocp_service_.register_handle(handle, ec))+ {+ ASIO_ERROR_LOCATION(ec); return ec;+ } impl.handle_ = handle; ec = asio::error_code();@@ -221,9 +226,47 @@ ec = asio::error_code(); } + ASIO_ERROR_LOCATION(ec); return ec; } +win_iocp_handle_service::native_handle_type win_iocp_handle_service::release(+ win_iocp_handle_service::implementation_type& impl,+ asio::error_code& ec)+{+ if (!is_open(impl))+ return INVALID_HANDLE_VALUE;++ cancel(impl, ec);+ if (ec)+ {+ ASIO_ERROR_LOCATION(ec);+ return INVALID_HANDLE_VALUE;+ }++ nt_set_info_fn fn = get_nt_set_info();+ if (fn == 0)+ {+ ec = asio::error::operation_not_supported;+ ASIO_ERROR_LOCATION(ec);+ return INVALID_HANDLE_VALUE;+ }++ ULONG_PTR iosb[2] = { 0, 0 };+ void* info[2] = { 0, 0 };+ if (fn(impl.handle_, iosb, &info, sizeof(info),+ 61 /* FileReplaceCompletionInformation */))+ {+ ec = asio::error::operation_not_supported;+ ASIO_ERROR_LOCATION(ec);+ return INVALID_HANDLE_VALUE;+ }++ native_handle_type tmp = impl.handle_;+ impl.handle_ = INVALID_HANDLE_VALUE;+ return tmp;+}+ asio::error_code win_iocp_handle_service::cancel( win_iocp_handle_service::implementation_type& impl, asio::error_code& ec)@@ -231,6 +274,7 @@ if (!is_open(impl)) { ec = asio::error::bad_descriptor;+ ASIO_ERROR_LOCATION(ec); return ec; } @@ -292,6 +336,7 @@ ec = asio::error::operation_not_supported; } + ASIO_ERROR_LOCATION(ec); return ec; } @@ -302,6 +347,7 @@ if (!is_open(impl)) { ec = asio::error::bad_descriptor;+ ASIO_ERROR_LOCATION(ec); return 0; } @@ -315,6 +361,7 @@ overlapped_wrapper overlapped(ec); if (ec) {+ ASIO_ERROR_LOCATION(ec); return 0; } @@ -330,6 +377,7 @@ { ec = asio::error_code(last_error, asio::error::get_system_category());+ ASIO_ERROR_LOCATION(ec); return 0; } }@@ -343,6 +391,7 @@ DWORD last_error = ::GetLastError(); ec = asio::error_code(last_error, asio::error::get_system_category());+ ASIO_ERROR_LOCATION(ec); return 0; } @@ -394,6 +443,7 @@ if (!is_open(impl)) { ec = asio::error::bad_descriptor;+ ASIO_ERROR_LOCATION(ec); return 0; } @@ -407,6 +457,7 @@ overlapped_wrapper overlapped(ec); if (ec) {+ ASIO_ERROR_LOCATION(ec); return 0; } @@ -429,6 +480,7 @@ ec = asio::error_code(last_error, asio::error::get_system_category()); }+ ASIO_ERROR_LOCATION(ec); return 0; } }@@ -449,6 +501,7 @@ ec = asio::error_code(last_error, asio::error::get_system_category()); }+ ASIO_ERROR_LOCATION(ec); return (last_error == ERROR_MORE_DATA) ? bytes_transferred : 0; } @@ -513,6 +566,47 @@ impl.handle_ = INVALID_HANDLE_VALUE; impl.safe_cancellation_thread_id_ = 0; }+}++win_iocp_handle_service::nt_set_info_fn+win_iocp_handle_service::get_nt_set_info()+{+ void* ptr = interlocked_compare_exchange_pointer(&nt_set_info_, 0, 0);+ if (!ptr)+ {+ if (HMODULE h = ::GetModuleHandleA("NTDLL.DLL"))+ ptr = reinterpret_cast<void*>(GetProcAddress(h, "NtSetInformationFile"));++ // On failure, set nt_set_info_ to a special value to indicate that the+ // NtSetInformationFile function is unavailable. That way we won't bother+ // trying to look it up again.+ interlocked_exchange_pointer(&nt_set_info_, ptr ? ptr : this);+ }++ return reinterpret_cast<nt_set_info_fn>(ptr == this ? 0 : ptr);+}++void* win_iocp_handle_service::interlocked_compare_exchange_pointer(+ void** dest, void* exch, void* cmp)+{+#if defined(_M_IX86)+ return reinterpret_cast<void*>(InterlockedCompareExchange(+ reinterpret_cast<PLONG>(dest), reinterpret_cast<LONG>(exch),+ reinterpret_cast<LONG>(cmp)));+#else+ return InterlockedCompareExchangePointer(dest, exch, cmp);+#endif+}++void* win_iocp_handle_service::interlocked_exchange_pointer(+ void** dest, void* val)+{+#if defined(_M_IX86)+ return reinterpret_cast<void*>(InterlockedExchange(+ reinterpret_cast<PLONG>(dest), reinterpret_cast<LONG>(val)));+#else+ return InterlockedExchangePointer(dest, val);+#endif } } // namespace detail
link/modules/asio-standalone/asio/include/asio/detail/impl/win_iocp_io_context.hpp view
@@ -2,7 +2,7 @@ // detail/impl/win_iocp_io_context.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -76,8 +76,25 @@ mutex::scoped_lock lock(dispatch_mutex_); op_queue<win_iocp_operation> ops; std::size_t n = queue.cancel_timer(timer, ops, max_cancelled);+ lock.unlock(); post_deferred_completions(ops); return n;+}++template <typename Time_Traits>+void win_iocp_io_context::cancel_timer_by_key(timer_queue<Time_Traits>& queue,+ typename timer_queue<Time_Traits>::per_timer_data* timer,+ void* cancellation_key)+{+ // If the service has been shut down we silently ignore the cancellation.+ if (::InterlockedExchangeAdd(&shutdown_, 0) != 0)+ return;++ mutex::scoped_lock lock(dispatch_mutex_);+ op_queue<win_iocp_operation> ops;+ queue.cancel_timer_by_key(timer, ops, cancellation_key);+ lock.unlock();+ post_deferred_completions(ops); } template <typename Time_Traits>
link/modules/asio-standalone/asio/include/asio/detail/impl/win_iocp_io_context.ipp view
@@ -2,7 +2,7 @@ // detail/impl/win_iocp_io_context.ipp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -51,7 +51,7 @@ struct win_iocp_io_context::work_finished_on_block_exit {- ~work_finished_on_block_exit()+ ~work_finished_on_block_exit() ASIO_NOEXCEPT_IF(false) { io_context_->work_finished(); }@@ -168,7 +168,10 @@ } if (timer_thread_.get())+ { timer_thread_->join();+ timer_thread_.reset();+ } } asio::error_code win_iocp_io_context::register_handle(@@ -287,6 +290,11 @@ } } +bool win_iocp_io_context::can_dispatch()+{+ return thread_call_stack::contains(this) != 0;+}+ void win_iocp_io_context::capture_current_exception() { if (thread_info_base* this_thread = thread_call_stack::contains(this))@@ -522,6 +530,7 @@ DWORD win_iocp_io_context::get_gqcs_timeout() {+#if !defined(_WIN32_WINNT) || (_WIN32_WINNT < 0x0600) OSVERSIONINFOEX osvi; ZeroMemory(&osvi, sizeof(osvi)); osvi.dwOSVersionInfoSize = sizeof(osvi);@@ -534,6 +543,9 @@ return INFINITE; return default_gqcs_timeout;+#else // !defined(_WIN32_WINNT) || (_WIN32_WINNT < 0x0600)+ return INFINITE;+#endif // !defined(_WIN32_WINNT) || (_WIN32_WINNT < 0x0600) } void win_iocp_io_context::do_add_timer_queue(timer_queue_base& queue)
link/modules/asio-standalone/asio/include/asio/detail/impl/win_iocp_serial_port_service.ipp view
@@ -2,7 +2,7 @@ // detail/impl/win_iocp_serial_port_service.ipp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // Copyright (c) 2008 Rep Invariant Systems, Inc. (info@repinvariant.com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying@@ -46,6 +46,7 @@ if (is_open(impl)) { ec = asio::error::already_open;+ ASIO_ERROR_LOCATION(ec); return ec; } @@ -61,6 +62,7 @@ DWORD last_error = ::GetLastError(); ec = asio::error_code(last_error, asio::error::get_system_category());+ ASIO_ERROR_LOCATION(ec); return ec; } @@ -75,6 +77,7 @@ ::CloseHandle(handle); ec = asio::error_code(last_error, asio::error::get_system_category());+ ASIO_ERROR_LOCATION(ec); return ec; } @@ -101,6 +104,7 @@ ::CloseHandle(handle); ec = asio::error_code(last_error, asio::error::get_system_category());+ ASIO_ERROR_LOCATION(ec); return ec; } @@ -119,6 +123,7 @@ ::CloseHandle(handle); ec = asio::error_code(last_error, asio::error::get_system_category());+ ASIO_ERROR_LOCATION(ec); return ec; } @@ -143,6 +148,7 @@ DWORD last_error = ::GetLastError(); ec = asio::error_code(last_error, asio::error::get_system_category());+ ASIO_ERROR_LOCATION(ec); return ec; } @@ -154,6 +160,7 @@ DWORD last_error = ::GetLastError(); ec = asio::error_code(last_error, asio::error::get_system_category());+ ASIO_ERROR_LOCATION(ec); return ec; } @@ -176,6 +183,7 @@ DWORD last_error = ::GetLastError(); ec = asio::error_code(last_error, asio::error::get_system_category());+ ASIO_ERROR_LOCATION(ec); return ec; }
link/modules/asio-standalone/asio/include/asio/detail/impl/win_iocp_socket_service_base.ipp view
@@ -2,7 +2,7 @@ // detail/impl/win_iocp_socket_service_base.ipp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -410,9 +410,8 @@ void win_iocp_socket_service_base::start_send_to_op( win_iocp_socket_service_base::base_implementation_type& impl,- WSABUF* buffers, std::size_t buffer_count,- const socket_addr_type* addr, int addrlen,- socket_base::message_flags flags, operation* op)+ WSABUF* buffers, std::size_t buffer_count, const void* addr,+ int addrlen, socket_base::message_flags flags, operation* op) { update_cancellation_thread_id(impl); iocp_service_.work_started();@@ -423,8 +422,8 @@ { DWORD bytes_transferred = 0; int result = ::WSASendTo(impl.socket_, buffers,- static_cast<DWORD>(buffer_count),- &bytes_transferred, flags, addr, addrlen, op, 0);+ static_cast<DWORD>(buffer_count), &bytes_transferred, flags,+ static_cast<const socket_addr_type*>(addr), addrlen, op, 0); DWORD last_error = ::WSAGetLastError(); if (last_error == ERROR_PORT_UNREACHABLE) last_error = WSAECONNREFUSED;@@ -466,29 +465,30 @@ } } -void win_iocp_socket_service_base::start_null_buffers_receive_op(+int win_iocp_socket_service_base::start_null_buffers_receive_op( win_iocp_socket_service_base::base_implementation_type& impl,- socket_base::message_flags flags, reactor_op* op)+ socket_base::message_flags flags, reactor_op* op, operation* iocp_op) { if ((impl.state_ & socket_ops::stream_oriented) != 0) { // For stream sockets on Windows, we may issue a 0-byte overlapped // WSARecv to wait until there is data available on the socket. ::WSABUF buf = { 0, 0 };- start_receive_op(impl, &buf, 1, flags, false, op);+ start_receive_op(impl, &buf, 1, flags, false, iocp_op);+ return -1; } else {- start_reactor_op(impl,- (flags & socket_base::message_out_of_band)- ? select_reactor::except_op : select_reactor::read_op,- op);+ int op_type = (flags & socket_base::message_out_of_band)+ ? select_reactor::except_op : select_reactor::read_op;+ start_reactor_op(impl, op_type, op);+ return op_type; } } void win_iocp_socket_service_base::start_receive_from_op( win_iocp_socket_service_base::base_implementation_type& impl,- WSABUF* buffers, std::size_t buffer_count, socket_addr_type* addr,+ WSABUF* buffers, std::size_t buffer_count, void* addr, socket_base::message_flags flags, int* addrlen, operation* op) { update_cancellation_thread_id(impl);@@ -501,8 +501,8 @@ DWORD bytes_transferred = 0; DWORD recv_flags = flags; int result = ::WSARecvFrom(impl.socket_, buffers,- static_cast<DWORD>(buffer_count),- &bytes_transferred, &recv_flags, addr, addrlen, op, 0);+ static_cast<DWORD>(buffer_count), &bytes_transferred, &recv_flags,+ static_cast<socket_addr_type*>(addr), addrlen, op, 0); DWORD last_error = ::WSAGetLastError(); if (last_error == ERROR_PORT_UNREACHABLE) last_error = WSAECONNREFUSED;@@ -547,11 +547,17 @@ void win_iocp_socket_service_base::restart_accept_op( socket_type s, socket_holder& new_socket, int family, int type,- int protocol, void* output_buffer, DWORD address_length, operation* op)+ int protocol, void* output_buffer, DWORD address_length,+ long* cancel_requested, operation* op) { new_socket.reset(); iocp_service_.work_started(); + // Check if we were cancelled after the first AcceptEx completed.+ if (cancel_requested)+ if (::InterlockedExchangeAdd(cancel_requested, 0) == 1)+ iocp_service_.on_completion(op, asio::error::operation_aborted);+ asio::error_code ec; new_socket.reset(socket_ops::socket(family, type, protocol, ec)); if (new_socket.get() == invalid_socket)@@ -565,7 +571,19 @@ if (!result && last_error != WSA_IO_PENDING) iocp_service_.on_completion(op, last_error); else+ {+#if defined(_WIN32_WINNT) && (_WIN32_WINNT >= 0x0600)+ if (cancel_requested)+ {+ if (::InterlockedExchangeAdd(cancel_requested, 0) == 1)+ {+ HANDLE sock_as_handle = reinterpret_cast<HANDLE>(s);+ ::CancelIoEx(sock_as_handle, op);+ }+ }+#endif // defined(_WIN32_WINNT) && (_WIN32_WINNT >= 0x0600) iocp_service_.on_pending(op);+ } } } @@ -587,10 +605,10 @@ iocp_service_.post_immediate_completion(op, false); } -void win_iocp_socket_service_base::start_connect_op(+int win_iocp_socket_service_base::start_connect_op( win_iocp_socket_service_base::base_implementation_type& impl,- int family, int type, const socket_addr_type* addr,- std::size_t addrlen, win_iocp_socket_connect_op_base* op)+ int family, int type, const void* addr, std::size_t addrlen,+ win_iocp_socket_connect_op_base* op, operation* iocp_op) { // If ConnectEx is available, use that. if (family == ASIO_OS_DEF(AF_INET)@@ -615,7 +633,7 @@ if (op->ec_ && op->ec_ != asio::error::invalid_argument) { iocp_service_.post_immediate_completion(op, false);- return;+ return -1; } op->connect_ex_ = true;@@ -623,13 +641,14 @@ iocp_service_.work_started(); BOOL result = connect_ex(impl.socket_,- addr, static_cast<int>(addrlen), 0, 0, 0, op);+ static_cast<const socket_addr_type*>(addr),+ static_cast<int>(addrlen), 0, 0, 0, iocp_op); DWORD last_error = ::WSAGetLastError(); if (!result && last_error != WSA_IO_PENDING)- iocp_service_.on_completion(op, last_error);+ iocp_service_.on_completion(iocp_op, last_error); else- iocp_service_.on_pending(op);- return;+ iocp_service_.on_pending(iocp_op);+ return -1; } } @@ -649,12 +668,13 @@ op->ec_ = asio::error_code(); r.start_op(select_reactor::connect_op, impl.socket_, impl.reactor_data_, op, false, false);- return;+ return select_reactor::connect_op; } } } r.post_immediate_completion(op, false);+ return -1; } void win_iocp_socket_service_base::close_for_destruction(
link/modules/asio-standalone/asio/include/asio/detail/impl/win_mutex.ipp view
@@ -2,7 +2,7 @@ // detail/impl/win_mutex.ipp // ~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/detail/impl/win_object_handle_service.ipp view
@@ -2,7 +2,7 @@ // detail/impl/win_object_handle_service.ipp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // Copyright (c) 2011 Boris Schaeling (boris@highscore.de) // // Distributed under the Boost Software License, Version 1.0. (See accompanying@@ -213,6 +213,7 @@ if (is_open(impl)) { ec = asio::error::already_open;+ ASIO_ERROR_LOCATION(ec); return ec; } @@ -270,6 +271,7 @@ ec = asio::error_code(); } + ASIO_ERROR_LOCATION(ec); return ec; } @@ -312,6 +314,7 @@ ec = asio::error::bad_descriptor; } + ASIO_ERROR_LOCATION(ec); return ec; } @@ -326,6 +329,7 @@ DWORD last_error = ::GetLastError(); ec = asio::error_code(last_error, asio::error::get_system_category());+ ASIO_ERROR_LOCATION(ec); break; } case WAIT_OBJECT_0:
link/modules/asio-standalone/asio/include/asio/detail/impl/win_static_mutex.ipp view
@@ -2,7 +2,7 @@ // detail/impl/win_static_mutex.ipp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/detail/impl/win_thread.ipp view
@@ -2,7 +2,7 @@ // detail/impl/win_thread.ipp // ~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/detail/impl/win_tss_ptr.ipp view
@@ -2,7 +2,7 @@ // detail/impl/win_tss_ptr.ipp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/detail/impl/winrt_ssocket_service_base.ipp view
@@ -2,7 +2,7 @@ // detail/impl/winrt_ssocket_service_base.ipp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -182,7 +182,7 @@ : impl.socket_->Information->RemotePort); unsigned long scope = 0; - switch (reinterpret_cast<const socket_addr_type*>(addr)->sa_family)+ switch (static_cast<const socket_addr_type*>(addr)->sa_family) { case ASIO_OS_DEF(AF_INET): if (addr_len < sizeof(sockaddr_in4_type))@@ -351,7 +351,7 @@ char addr_string[max_addr_v6_str_len]; unsigned short port;- switch (reinterpret_cast<const socket_addr_type*>(addr)->sa_family)+ switch (static_cast<const socket_addr_type*>(addr)->sa_family) { case ASIO_OS_DEF(AF_INET): socket_ops::inet_ntop(ASIO_OS_DEF(AF_INET),@@ -401,7 +401,7 @@ char addr_string[max_addr_v6_str_len]; unsigned short port = 0;- switch (reinterpret_cast<const socket_addr_type*>(addr)->sa_family)+ switch (static_cast<const socket_addr_type*>(addr)->sa_family) { case ASIO_OS_DEF(AF_INET): socket_ops::inet_ntop(ASIO_OS_DEF(AF_INET),
link/modules/asio-standalone/asio/include/asio/detail/impl/winrt_timer_scheduler.hpp view
@@ -2,7 +2,7 @@ // detail/impl/winrt_timer_scheduler.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/detail/impl/winrt_timer_scheduler.ipp view
@@ -2,7 +2,7 @@ // detail/impl/winrt_timer_scheduler.ipp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/detail/impl/winsock_init.ipp view
@@ -2,7 +2,7 @@ // detail/impl/winsock_init.ipp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+ link/modules/asio-standalone/asio/include/asio/detail/initiate_defer.hpp view
@@ -0,0 +1,252 @@+//+// detail/initiate_defer.hpp+// ~~~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com)+//+// Distributed under the Boost Software License, Version 1.0. (See accompanying+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)+//++#ifndef ASIO_DETAIL_INITIATE_DEFER_HPP+#define ASIO_DETAIL_INITIATE_DEFER_HPP++#if defined(_MSC_VER) && (_MSC_VER >= 1200)+# pragma once+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)++#include "asio/detail/config.hpp"+#include "asio/associated_allocator.hpp"+#include "asio/associated_executor.hpp"+#include "asio/detail/work_dispatcher.hpp"+#include "asio/execution/allocator.hpp"+#include "asio/execution/blocking.hpp"+#include "asio/execution/relationship.hpp"+#include "asio/prefer.hpp"+#include "asio/require.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {+namespace detail {++class initiate_defer+{+public:+ template <typename CompletionHandler>+ void operator()(ASIO_MOVE_ARG(CompletionHandler) handler,+ typename enable_if<+ execution::is_executor<+ typename associated_executor<+ typename decay<CompletionHandler>::type+ >::type+ >::value+ >::type* = 0) const+ {+ typedef typename decay<CompletionHandler>::type handler_t;++ typename associated_executor<handler_t>::type ex(+ (get_associated_executor)(handler));++ typename associated_allocator<handler_t>::type alloc(+ (get_associated_allocator)(handler));++#if defined(ASIO_NO_DEPRECATED)+ asio::prefer(+ asio::require(ex, execution::blocking.never),+ execution::relationship.continuation,+ execution::allocator(alloc)+ ).execute(+ asio::detail::bind_handler(+ ASIO_MOVE_CAST(CompletionHandler)(handler)));+#else // defined(ASIO_NO_DEPRECATED)+ execution::execute(+ asio::prefer(+ asio::require(ex, execution::blocking.never),+ execution::relationship.continuation,+ execution::allocator(alloc)),+ asio::detail::bind_handler(+ ASIO_MOVE_CAST(CompletionHandler)(handler)));+#endif // defined(ASIO_NO_DEPRECATED)+ }++ template <typename CompletionHandler>+ void operator()(ASIO_MOVE_ARG(CompletionHandler) handler,+ typename enable_if<+ !execution::is_executor<+ typename associated_executor<+ typename decay<CompletionHandler>::type+ >::type+ >::value+ >::type* = 0) const+ {+ typedef typename decay<CompletionHandler>::type handler_t;++ typename associated_executor<handler_t>::type ex(+ (get_associated_executor)(handler));++ typename associated_allocator<handler_t>::type alloc(+ (get_associated_allocator)(handler));++ ex.defer(asio::detail::bind_handler(+ ASIO_MOVE_CAST(CompletionHandler)(handler)), alloc);+ }+};++template <typename Executor>+class initiate_defer_with_executor+{+public:+ typedef Executor executor_type;++ explicit initiate_defer_with_executor(const Executor& ex)+ : ex_(ex)+ {+ }++ executor_type get_executor() const ASIO_NOEXCEPT+ {+ return ex_;+ }++ template <typename CompletionHandler>+ void operator()(ASIO_MOVE_ARG(CompletionHandler) handler,+ typename enable_if<+ execution::is_executor<+ typename conditional<true, executor_type, CompletionHandler>::type+ >::value+ >::type* = 0,+ typename enable_if<+ !detail::is_work_dispatcher_required<+ typename decay<CompletionHandler>::type,+ Executor+ >::value+ >::type* = 0) const+ {+ typedef typename decay<CompletionHandler>::type handler_t;++ typename associated_allocator<handler_t>::type alloc(+ (get_associated_allocator)(handler));++#if defined(ASIO_NO_DEPRECATED)+ asio::prefer(+ asio::require(ex_, execution::blocking.never),+ execution::relationship.continuation,+ execution::allocator(alloc)+ ).execute(+ asio::detail::bind_handler(+ ASIO_MOVE_CAST(CompletionHandler)(handler)));+#else // defined(ASIO_NO_DEPRECATED)+ execution::execute(+ asio::prefer(+ asio::require(ex_, execution::blocking.never),+ execution::relationship.continuation,+ execution::allocator(alloc)),+ asio::detail::bind_handler(+ ASIO_MOVE_CAST(CompletionHandler)(handler)));+#endif // defined(ASIO_NO_DEPRECATED)+ }++ template <typename CompletionHandler>+ void operator()(ASIO_MOVE_ARG(CompletionHandler) handler,+ typename enable_if<+ execution::is_executor<+ typename conditional<true, executor_type, CompletionHandler>::type+ >::value+ >::type* = 0,+ typename enable_if<+ detail::is_work_dispatcher_required<+ typename decay<CompletionHandler>::type,+ Executor+ >::value+ >::type* = 0) const+ {+ typedef typename decay<CompletionHandler>::type handler_t;++ typedef typename associated_executor<+ handler_t, Executor>::type handler_ex_t;+ handler_ex_t handler_ex((get_associated_executor)(handler, ex_));++ typename associated_allocator<handler_t>::type alloc(+ (get_associated_allocator)(handler));++#if defined(ASIO_NO_DEPRECATED)+ asio::prefer(+ asio::require(ex_, execution::blocking.never),+ execution::relationship.continuation,+ execution::allocator(alloc)+ ).execute(+ detail::work_dispatcher<handler_t, handler_ex_t>(+ ASIO_MOVE_CAST(CompletionHandler)(handler), handler_ex));+#else // defined(ASIO_NO_DEPRECATED)+ execution::execute(+ asio::prefer(+ asio::require(ex_, execution::blocking.never),+ execution::relationship.continuation,+ execution::allocator(alloc)),+ detail::work_dispatcher<handler_t, handler_ex_t>(+ ASIO_MOVE_CAST(CompletionHandler)(handler), handler_ex));+#endif // defined(ASIO_NO_DEPRECATED)+ }++ template <typename CompletionHandler>+ void operator()(ASIO_MOVE_ARG(CompletionHandler) handler,+ typename enable_if<+ !execution::is_executor<+ typename conditional<true, executor_type, CompletionHandler>::type+ >::value+ >::type* = 0,+ typename enable_if<+ !detail::is_work_dispatcher_required<+ typename decay<CompletionHandler>::type,+ Executor+ >::value+ >::type* = 0) const+ {+ typedef typename decay<CompletionHandler>::type handler_t;++ typename associated_allocator<handler_t>::type alloc(+ (get_associated_allocator)(handler));++ ex_.defer(asio::detail::bind_handler(+ ASIO_MOVE_CAST(CompletionHandler)(handler)), alloc);+ }++ template <typename CompletionHandler>+ void operator()(ASIO_MOVE_ARG(CompletionHandler) handler,+ typename enable_if<+ !execution::is_executor<+ typename conditional<true, executor_type, CompletionHandler>::type+ >::value+ >::type* = 0,+ typename enable_if<+ detail::is_work_dispatcher_required<+ typename decay<CompletionHandler>::type,+ Executor+ >::value+ >::type* = 0) const+ {+ typedef typename decay<CompletionHandler>::type handler_t;++ typedef typename associated_executor<+ handler_t, Executor>::type handler_ex_t;+ handler_ex_t handler_ex((get_associated_executor)(handler, ex_));++ typename associated_allocator<handler_t>::type alloc(+ (get_associated_allocator)(handler));++ ex_.defer(detail::work_dispatcher<handler_t, handler_ex_t>(+ ASIO_MOVE_CAST(CompletionHandler)(handler),+ handler_ex), alloc);+ }++private:+ Executor ex_;+};++} // namespace detail+} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // ASIO_DETAIL_INITIATE_DEFER_HPP
+ link/modules/asio-standalone/asio/include/asio/detail/initiate_dispatch.hpp view
@@ -0,0 +1,229 @@+//+// detail/initiate_dispatch.hpp+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com)+//+// Distributed under the Boost Software License, Version 1.0. (See accompanying+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)+//++#ifndef ASIO_DETAIL_INITIATE_DISPATCH_HPP+#define ASIO_DETAIL_INITIATE_DISPATCH_HPP++#if defined(_MSC_VER) && (_MSC_VER >= 1200)+# pragma once+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)++#include "asio/detail/config.hpp"+#include "asio/associated_allocator.hpp"+#include "asio/associated_executor.hpp"+#include "asio/detail/work_dispatcher.hpp"+#include "asio/execution/allocator.hpp"+#include "asio/execution/blocking.hpp"+#include "asio/prefer.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {+namespace detail {++class initiate_dispatch+{+public:+ template <typename CompletionHandler>+ void operator()(ASIO_MOVE_ARG(CompletionHandler) handler,+ typename enable_if<+ execution::is_executor<+ typename associated_executor<+ typename decay<CompletionHandler>::type+ >::type+ >::value+ >::type* = 0) const+ {+ typedef typename decay<CompletionHandler>::type handler_t;++ typename associated_executor<handler_t>::type ex(+ (get_associated_executor)(handler));++ typename associated_allocator<handler_t>::type alloc(+ (get_associated_allocator)(handler));++#if defined(ASIO_NO_DEPRECATED)+ asio::prefer(ex, execution::allocator(alloc)).execute(+ asio::detail::bind_handler(+ ASIO_MOVE_CAST(CompletionHandler)(handler)));+#else // defined(ASIO_NO_DEPRECATED)+ execution::execute(+ asio::prefer(ex, execution::allocator(alloc)),+ asio::detail::bind_handler(+ ASIO_MOVE_CAST(CompletionHandler)(handler)));+#endif // defined(ASIO_NO_DEPRECATED)+ }++ template <typename CompletionHandler>+ void operator()(ASIO_MOVE_ARG(CompletionHandler) handler,+ typename enable_if<+ !execution::is_executor<+ typename associated_executor<+ typename decay<CompletionHandler>::type+ >::type+ >::value+ >::type* = 0) const+ {+ typedef typename decay<CompletionHandler>::type handler_t;++ typename associated_executor<handler_t>::type ex(+ (get_associated_executor)(handler));++ typename associated_allocator<handler_t>::type alloc(+ (get_associated_allocator)(handler));++ ex.dispatch(asio::detail::bind_handler(+ ASIO_MOVE_CAST(CompletionHandler)(handler)), alloc);+ }+};++template <typename Executor>+class initiate_dispatch_with_executor+{+public:+ typedef Executor executor_type;++ explicit initiate_dispatch_with_executor(const Executor& ex)+ : ex_(ex)+ {+ }++ executor_type get_executor() const ASIO_NOEXCEPT+ {+ return ex_;+ }++ template <typename CompletionHandler>+ void operator()(ASIO_MOVE_ARG(CompletionHandler) handler,+ typename enable_if<+ execution::is_executor<+ typename conditional<true, executor_type, CompletionHandler>::type+ >::value+ >::type* = 0,+ typename enable_if<+ !detail::is_work_dispatcher_required<+ typename decay<CompletionHandler>::type,+ Executor+ >::value+ >::type* = 0) const+ {+ typedef typename decay<CompletionHandler>::type handler_t;++ typename associated_allocator<handler_t>::type alloc(+ (get_associated_allocator)(handler));++#if defined(ASIO_NO_DEPRECATED)+ asio::prefer(ex_, execution::allocator(alloc)).execute(+ asio::detail::bind_handler(+ ASIO_MOVE_CAST(CompletionHandler)(handler)));+#else // defined(ASIO_NO_DEPRECATED)+ execution::execute(+ asio::prefer(ex_, execution::allocator(alloc)),+ asio::detail::bind_handler(+ ASIO_MOVE_CAST(CompletionHandler)(handler)));+#endif // defined(ASIO_NO_DEPRECATED)+ }++ template <typename CompletionHandler>+ void operator()(ASIO_MOVE_ARG(CompletionHandler) handler,+ typename enable_if<+ execution::is_executor<+ typename conditional<true, executor_type, CompletionHandler>::type+ >::value+ >::type* = 0,+ typename enable_if<+ detail::is_work_dispatcher_required<+ typename decay<CompletionHandler>::type,+ Executor+ >::value+ >::type* = 0) const+ {+ typedef typename decay<CompletionHandler>::type handler_t;++ typedef typename associated_executor<+ handler_t, Executor>::type handler_ex_t;+ handler_ex_t handler_ex((get_associated_executor)(handler, ex_));++ typename associated_allocator<handler_t>::type alloc(+ (get_associated_allocator)(handler));++#if defined(ASIO_NO_DEPRECATED)+ asio::prefer(ex_, execution::allocator(alloc)).execute(+ detail::work_dispatcher<handler_t, handler_ex_t>(+ ASIO_MOVE_CAST(CompletionHandler)(handler), handler_ex));+#else // defined(ASIO_NO_DEPRECATED)+ execution::execute(+ asio::prefer(ex_, execution::allocator(alloc)),+ detail::work_dispatcher<handler_t, handler_ex_t>(+ ASIO_MOVE_CAST(CompletionHandler)(handler), handler_ex));+#endif // defined(ASIO_NO_DEPRECATED)+ }++ template <typename CompletionHandler>+ void operator()(ASIO_MOVE_ARG(CompletionHandler) handler,+ typename enable_if<+ !execution::is_executor<+ typename conditional<true, executor_type, CompletionHandler>::type+ >::value+ >::type* = 0,+ typename enable_if<+ !detail::is_work_dispatcher_required<+ typename decay<CompletionHandler>::type,+ Executor+ >::value+ >::type* = 0) const+ {+ typedef typename decay<CompletionHandler>::type handler_t;++ typename associated_allocator<handler_t>::type alloc(+ (get_associated_allocator)(handler));++ ex_.dispatch(asio::detail::bind_handler(+ ASIO_MOVE_CAST(CompletionHandler)(handler)), alloc);+ }++ template <typename CompletionHandler>+ void operator()(ASIO_MOVE_ARG(CompletionHandler) handler,+ typename enable_if<+ !execution::is_executor<+ typename conditional<true, executor_type, CompletionHandler>::type+ >::value+ >::type* = 0,+ typename enable_if<+ detail::is_work_dispatcher_required<+ typename decay<CompletionHandler>::type,+ Executor+ >::value+ >::type* = 0) const+ {+ typedef typename decay<CompletionHandler>::type handler_t;++ typedef typename associated_executor<+ handler_t, Executor>::type handler_ex_t;+ handler_ex_t handler_ex((get_associated_executor)(handler, ex_));++ typename associated_allocator<handler_t>::type alloc(+ (get_associated_allocator)(handler));++ ex_.dispatch(detail::work_dispatcher<handler_t, handler_ex_t>(+ ASIO_MOVE_CAST(CompletionHandler)(handler),+ handler_ex), alloc);+ }++private:+ Executor ex_;+};++} // namespace detail+} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // ASIO_DETAIL_INITIATE_DISPATCH_HPP
+ link/modules/asio-standalone/asio/include/asio/detail/initiate_post.hpp view
@@ -0,0 +1,252 @@+//+// detail/initiate_post.hpp+// ~~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com)+//+// Distributed under the Boost Software License, Version 1.0. (See accompanying+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)+//++#ifndef ASIO_DETAIL_INITIATE_POST_HPP+#define ASIO_DETAIL_INITIATE_POST_HPP++#if defined(_MSC_VER) && (_MSC_VER >= 1200)+# pragma once+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)++#include "asio/detail/config.hpp"+#include "asio/associated_allocator.hpp"+#include "asio/associated_executor.hpp"+#include "asio/detail/work_dispatcher.hpp"+#include "asio/execution/allocator.hpp"+#include "asio/execution/blocking.hpp"+#include "asio/execution/relationship.hpp"+#include "asio/prefer.hpp"+#include "asio/require.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {+namespace detail {++class initiate_post+{+public:+ template <typename CompletionHandler>+ void operator()(ASIO_MOVE_ARG(CompletionHandler) handler,+ typename enable_if<+ execution::is_executor<+ typename associated_executor<+ typename decay<CompletionHandler>::type+ >::type+ >::value+ >::type* = 0) const+ {+ typedef typename decay<CompletionHandler>::type handler_t;++ typename associated_executor<handler_t>::type ex(+ (get_associated_executor)(handler));++ typename associated_allocator<handler_t>::type alloc(+ (get_associated_allocator)(handler));++#if defined(ASIO_NO_DEPRECATED)+ asio::prefer(+ asio::require(ex, execution::blocking.never),+ execution::relationship.fork,+ execution::allocator(alloc)+ ).execute(+ asio::detail::bind_handler(+ ASIO_MOVE_CAST(CompletionHandler)(handler)));+#else // defined(ASIO_NO_DEPRECATED)+ execution::execute(+ asio::prefer(+ asio::require(ex, execution::blocking.never),+ execution::relationship.fork,+ execution::allocator(alloc)),+ asio::detail::bind_handler(+ ASIO_MOVE_CAST(CompletionHandler)(handler)));+#endif // defined(ASIO_NO_DEPRECATED)+ }++ template <typename CompletionHandler>+ void operator()(ASIO_MOVE_ARG(CompletionHandler) handler,+ typename enable_if<+ !execution::is_executor<+ typename associated_executor<+ typename decay<CompletionHandler>::type+ >::type+ >::value+ >::type* = 0) const+ {+ typedef typename decay<CompletionHandler>::type handler_t;++ typename associated_executor<handler_t>::type ex(+ (get_associated_executor)(handler));++ typename associated_allocator<handler_t>::type alloc(+ (get_associated_allocator)(handler));++ ex.post(asio::detail::bind_handler(+ ASIO_MOVE_CAST(CompletionHandler)(handler)), alloc);+ }+};++template <typename Executor>+class initiate_post_with_executor+{+public:+ typedef Executor executor_type;++ explicit initiate_post_with_executor(const Executor& ex)+ : ex_(ex)+ {+ }++ executor_type get_executor() const ASIO_NOEXCEPT+ {+ return ex_;+ }++ template <typename CompletionHandler>+ void operator()(ASIO_MOVE_ARG(CompletionHandler) handler,+ typename enable_if<+ execution::is_executor<+ typename conditional<true, executor_type, CompletionHandler>::type+ >::value+ >::type* = 0,+ typename enable_if<+ !detail::is_work_dispatcher_required<+ typename decay<CompletionHandler>::type,+ Executor+ >::value+ >::type* = 0) const+ {+ typedef typename decay<CompletionHandler>::type handler_t;++ typename associated_allocator<handler_t>::type alloc(+ (get_associated_allocator)(handler));++#if defined(ASIO_NO_DEPRECATED)+ asio::prefer(+ asio::require(ex_, execution::blocking.never),+ execution::relationship.fork,+ execution::allocator(alloc)+ ).execute(+ asio::detail::bind_handler(+ ASIO_MOVE_CAST(CompletionHandler)(handler)));+#else // defined(ASIO_NO_DEPRECATED)+ execution::execute(+ asio::prefer(+ asio::require(ex_, execution::blocking.never),+ execution::relationship.fork,+ execution::allocator(alloc)),+ asio::detail::bind_handler(+ ASIO_MOVE_CAST(CompletionHandler)(handler)));+#endif // defined(ASIO_NO_DEPRECATED)+ }++ template <typename CompletionHandler>+ void operator()(ASIO_MOVE_ARG(CompletionHandler) handler,+ typename enable_if<+ execution::is_executor<+ typename conditional<true, executor_type, CompletionHandler>::type+ >::value+ >::type* = 0,+ typename enable_if<+ detail::is_work_dispatcher_required<+ typename decay<CompletionHandler>::type,+ Executor+ >::value+ >::type* = 0) const+ {+ typedef typename decay<CompletionHandler>::type handler_t;++ typedef typename associated_executor<+ handler_t, Executor>::type handler_ex_t;+ handler_ex_t handler_ex((get_associated_executor)(handler, ex_));++ typename associated_allocator<handler_t>::type alloc(+ (get_associated_allocator)(handler));++#if defined(ASIO_NO_DEPRECATED)+ asio::prefer(+ asio::require(ex_, execution::blocking.never),+ execution::relationship.fork,+ execution::allocator(alloc)+ ).execute(+ detail::work_dispatcher<handler_t, handler_ex_t>(+ ASIO_MOVE_CAST(CompletionHandler)(handler), handler_ex));+#else // defined(ASIO_NO_DEPRECATED)+ execution::execute(+ asio::prefer(+ asio::require(ex_, execution::blocking.never),+ execution::relationship.fork,+ execution::allocator(alloc)),+ detail::work_dispatcher<handler_t, handler_ex_t>(+ ASIO_MOVE_CAST(CompletionHandler)(handler), handler_ex));+#endif // defined(ASIO_NO_DEPRECATED)+ }++ template <typename CompletionHandler>+ void operator()(ASIO_MOVE_ARG(CompletionHandler) handler,+ typename enable_if<+ !execution::is_executor<+ typename conditional<true, executor_type, CompletionHandler>::type+ >::value+ >::type* = 0,+ typename enable_if<+ !detail::is_work_dispatcher_required<+ typename decay<CompletionHandler>::type,+ Executor+ >::value+ >::type* = 0) const+ {+ typedef typename decay<CompletionHandler>::type handler_t;++ typename associated_allocator<handler_t>::type alloc(+ (get_associated_allocator)(handler));++ ex_.post(asio::detail::bind_handler(+ ASIO_MOVE_CAST(CompletionHandler)(handler)), alloc);+ }++ template <typename CompletionHandler>+ void operator()(ASIO_MOVE_ARG(CompletionHandler) handler,+ typename enable_if<+ !execution::is_executor<+ typename conditional<true, executor_type, CompletionHandler>::type+ >::value+ >::type* = 0,+ typename enable_if<+ detail::is_work_dispatcher_required<+ typename decay<CompletionHandler>::type,+ Executor+ >::value+ >::type* = 0) const+ {+ typedef typename decay<CompletionHandler>::type handler_t;++ typedef typename associated_executor<+ handler_t, Executor>::type handler_ex_t;+ handler_ex_t handler_ex((get_associated_executor)(handler, ex_));++ typename associated_allocator<handler_t>::type alloc(+ (get_associated_allocator)(handler));++ ex_.post(detail::work_dispatcher<handler_t, handler_ex_t>(+ ASIO_MOVE_CAST(CompletionHandler)(handler),+ handler_ex), alloc);+ }++private:+ Executor ex_;+};++} // namespace detail+} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // ASIO_DETAIL_INITIATE_POST_HPP
link/modules/asio-standalone/asio/include/asio/detail/io_control.hpp view
@@ -2,7 +2,7 @@ // detail/io_control.hpp // ~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/detail/io_object_impl.hpp view
@@ -2,7 +2,7 @@ // io_object_impl.hpp // ~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -43,7 +43,7 @@ typedef Executor executor_type; // Construct an I/O object using an executor.- explicit io_object_impl(const executor_type& ex)+ explicit io_object_impl(int, const executor_type& ex) : service_(&asio::use_service<IoObjectService>( io_object_impl::get_context(ex))), executor_(ex)@@ -53,9 +53,7 @@ // Construct an I/O object using an execution context. template <typename ExecutionContext>- explicit io_object_impl(ExecutionContext& context,- typename enable_if<is_convertible<- ExecutionContext&, execution_context&>::value>::type* = 0)+ explicit io_object_impl(int, int, ExecutionContext& context) : service_(&asio::use_service<IoObjectService>(context)), executor_(context.get_executor()) {@@ -71,7 +69,16 @@ service_->move_construct(implementation_, other.implementation_); } - // Perform a converting move-construction of an I/O object.+ // Perform converting move-construction of an I/O object on the same service.+ template <typename Executor1>+ io_object_impl(io_object_impl<IoObjectService, Executor1>&& other)+ : service_(&other.get_service()),+ executor_(other.get_executor())+ {+ service_->move_construct(implementation_, other.get_implementation());+ }++ // Perform converting move-construction of an I/O object on another service. template <typename IoObjectService1, typename Executor1> io_object_impl(io_object_impl<IoObjectService1, Executor1>&& other) : service_(&asio::use_service<IoObjectService>(@@ -98,8 +105,7 @@ service_->move_assign(implementation_, *other.service_, other.implementation_); executor_.~executor_type();- new (&executor_) executor_type(- std::move(other.executor_));+ new (&executor_) executor_type(other.executor_); service_ = other.service_; } return *this;
+ link/modules/asio-standalone/asio/include/asio/detail/io_uring_descriptor_read_at_op.hpp view
@@ -0,0 +1,195 @@+//+// detail/io_uring_descriptor_read_at_op.hpp+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com)+//+// Distributed under the Boost Software License, Version 1.0. (See accompanying+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)+//++#ifndef ASIO_DETAIL_IO_URING_DESCRIPTOR_READ_AT_OP_HPP+#define ASIO_DETAIL_IO_URING_DESCRIPTOR_READ_AT_OP_HPP++#if defined(_MSC_VER) && (_MSC_VER >= 1200)+# pragma once+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)++#include "asio/detail/config.hpp"++#if defined(ASIO_HAS_IO_URING)++#include "asio/detail/bind_handler.hpp"+#include "asio/detail/buffer_sequence_adapter.hpp"+#include "asio/detail/cstdint.hpp"+#include "asio/detail/descriptor_ops.hpp"+#include "asio/detail/fenced_block.hpp"+#include "asio/detail/handler_work.hpp"+#include "asio/detail/io_uring_operation.hpp"+#include "asio/detail/memory.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {+namespace detail {++template <typename MutableBufferSequence>+class io_uring_descriptor_read_at_op_base : public io_uring_operation+{+public:+ io_uring_descriptor_read_at_op_base(+ const asio::error_code& success_ec, int descriptor,+ descriptor_ops::state_type state, uint64_t offset,+ const MutableBufferSequence& buffers, func_type complete_func)+ : io_uring_operation(success_ec,+ &io_uring_descriptor_read_at_op_base::do_prepare,+ &io_uring_descriptor_read_at_op_base::do_perform, complete_func),+ descriptor_(descriptor),+ state_(state),+ offset_(offset),+ buffers_(buffers),+ bufs_(buffers)+ {+ }++ static void do_prepare(io_uring_operation* base, ::io_uring_sqe* sqe)+ {+ ASIO_ASSUME(base != 0);+ io_uring_descriptor_read_at_op_base* o(+ static_cast<io_uring_descriptor_read_at_op_base*>(base));++ if ((o->state_ & descriptor_ops::internal_non_blocking) != 0)+ {+ ::io_uring_prep_poll_add(sqe, o->descriptor_, POLLIN);+ }+ else if (o->bufs_.is_single_buffer && o->bufs_.is_registered_buffer)+ {+ ::io_uring_prep_read_fixed(sqe, o->descriptor_,+ o->bufs_.buffers()->iov_base, o->bufs_.buffers()->iov_len,+ o->offset_, o->bufs_.registered_id().native_handle());+ }+ else+ {+ ::io_uring_prep_readv(sqe, o->descriptor_,+ o->bufs_.buffers(), o->bufs_.count(), o->offset_);+ }+ }++ static bool do_perform(io_uring_operation* base, bool after_completion)+ {+ ASIO_ASSUME(base != 0);+ io_uring_descriptor_read_at_op_base* o(+ static_cast<io_uring_descriptor_read_at_op_base*>(base));++ if ((o->state_ & descriptor_ops::internal_non_blocking) != 0)+ {+ if (o->bufs_.is_single_buffer)+ {+ return descriptor_ops::non_blocking_read_at1(o->descriptor_,+ o->offset_, o->bufs_.first(o->buffers_).data(),+ o->bufs_.first(o->buffers_).size(), o->ec_,+ o->bytes_transferred_);+ }+ else+ {+ return descriptor_ops::non_blocking_read_at(o->descriptor_,+ o->offset_, o->bufs_.buffers(), o->bufs_.count(),+ o->ec_, o->bytes_transferred_);+ }+ }+ else if (after_completion)+ {+ if (!o->ec_ && o->bytes_transferred_ == 0)+ o->ec_ = asio::error::eof;+ }++ if (o->ec_ && o->ec_ == asio::error::would_block)+ {+ o->state_ |= descriptor_ops::internal_non_blocking;+ return false;+ }++ return after_completion;+ }++private:+ int descriptor_;+ descriptor_ops::state_type state_;+ uint64_t offset_;+ MutableBufferSequence buffers_;+ buffer_sequence_adapter<asio::mutable_buffer,+ MutableBufferSequence> bufs_;+};++template <typename MutableBufferSequence, typename Handler, typename IoExecutor>+class io_uring_descriptor_read_at_op+ : public io_uring_descriptor_read_at_op_base<MutableBufferSequence>+{+public:+ ASIO_DEFINE_HANDLER_PTR(io_uring_descriptor_read_at_op);++ io_uring_descriptor_read_at_op(const asio::error_code& success_ec,+ int descriptor, descriptor_ops::state_type state, uint64_t offset,+ const MutableBufferSequence& buffers,+ Handler& handler, const IoExecutor& io_ex)+ : io_uring_descriptor_read_at_op_base<MutableBufferSequence>(+ success_ec, descriptor, state, offset, buffers,+ &io_uring_descriptor_read_at_op::do_complete),+ handler_(ASIO_MOVE_CAST(Handler)(handler)),+ work_(handler_, io_ex)+ {+ }++ static void do_complete(void* owner, operation* base,+ const asio::error_code& /*ec*/,+ std::size_t /*bytes_transferred*/)+ {+ // Take ownership of the handler object.+ ASIO_ASSUME(base != 0);+ io_uring_descriptor_read_at_op* o+ (static_cast<io_uring_descriptor_read_at_op*>(base));+ ptr p = { asio::detail::addressof(o->handler_), o, o };++ ASIO_HANDLER_COMPLETION((*o));++ // Take ownership of the operation's outstanding work.+ handler_work<Handler, IoExecutor> w(+ ASIO_MOVE_CAST2(handler_work<Handler, IoExecutor>)(+ o->work_));++ ASIO_ERROR_LOCATION(o->ec_);++ // Make a copy of the handler so that the memory can be deallocated before+ // the upcall is made. Even if we're not about to make an upcall, a+ // sub-object of the handler may be the true owner of the memory associated+ // with the handler. Consequently, a local copy of the handler is required+ // to ensure that any owning sub-object remains valid until after we have+ // deallocated the memory here.+ detail::binder2<Handler, asio::error_code, std::size_t>+ handler(o->handler_, o->ec_, o->bytes_transferred_);+ p.h = asio::detail::addressof(handler.handler_);+ p.reset();++ // Make the upcall if required.+ if (owner)+ {+ fenced_block b(fenced_block::half);+ ASIO_HANDLER_INVOCATION_BEGIN((handler.arg1_, handler.arg2_));+ w.complete(handler, handler.handler_);+ ASIO_HANDLER_INVOCATION_END;+ }+ }++private:+ Handler handler_;+ handler_work<Handler, IoExecutor> work_;+};++} // namespace detail+} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // defined(ASIO_HAS_IO_URING)++#endif // ASIO_DETAIL_IO_URING_DESCRIPTOR_READ_AT_OP_HPP
+ link/modules/asio-standalone/asio/include/asio/detail/io_uring_descriptor_read_op.hpp view
@@ -0,0 +1,190 @@+//+// detail/io_uring_descriptor_read_op.hpp+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com)+//+// Distributed under the Boost Software License, Version 1.0. (See accompanying+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)+//++#ifndef ASIO_DETAIL_IO_URING_DESCRIPTOR_READ_OP_HPP+#define ASIO_DETAIL_IO_URING_DESCRIPTOR_READ_OP_HPP++#if defined(_MSC_VER) && (_MSC_VER >= 1200)+# pragma once+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)++#include "asio/detail/config.hpp"++#if defined(ASIO_HAS_IO_URING)++#include "asio/detail/bind_handler.hpp"+#include "asio/detail/buffer_sequence_adapter.hpp"+#include "asio/detail/descriptor_ops.hpp"+#include "asio/detail/fenced_block.hpp"+#include "asio/detail/handler_work.hpp"+#include "asio/detail/io_uring_operation.hpp"+#include "asio/detail/memory.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {+namespace detail {++template <typename MutableBufferSequence>+class io_uring_descriptor_read_op_base : public io_uring_operation+{+public:+ io_uring_descriptor_read_op_base(const asio::error_code& success_ec,+ int descriptor, descriptor_ops::state_type state,+ const MutableBufferSequence& buffers, func_type complete_func)+ : io_uring_operation(success_ec,+ &io_uring_descriptor_read_op_base::do_prepare,+ &io_uring_descriptor_read_op_base::do_perform, complete_func),+ descriptor_(descriptor),+ state_(state),+ buffers_(buffers),+ bufs_(buffers)+ {+ }++ static void do_prepare(io_uring_operation* base, ::io_uring_sqe* sqe)+ {+ ASIO_ASSUME(base != 0);+ io_uring_descriptor_read_op_base* o(+ static_cast<io_uring_descriptor_read_op_base*>(base));++ if ((o->state_ & descriptor_ops::internal_non_blocking) != 0)+ {+ ::io_uring_prep_poll_add(sqe, o->descriptor_, POLLIN);+ }+ else if (o->bufs_.is_single_buffer && o->bufs_.is_registered_buffer)+ {+ ::io_uring_prep_read_fixed(sqe, o->descriptor_,+ o->bufs_.buffers()->iov_base, o->bufs_.buffers()->iov_len,+ 0, o->bufs_.registered_id().native_handle());+ }+ else+ {+ ::io_uring_prep_readv(sqe, o->descriptor_,+ o->bufs_.buffers(), o->bufs_.count(), -1);+ }+ }++ static bool do_perform(io_uring_operation* base, bool after_completion)+ {+ ASIO_ASSUME(base != 0);+ io_uring_descriptor_read_op_base* o(+ static_cast<io_uring_descriptor_read_op_base*>(base));++ if ((o->state_ & descriptor_ops::internal_non_blocking) != 0)+ {+ if (o->bufs_.is_single_buffer)+ {+ return descriptor_ops::non_blocking_read1(+ o->descriptor_, o->bufs_.first(o->buffers_).data(),+ o->bufs_.first(o->buffers_).size(), o->ec_,+ o->bytes_transferred_);+ }+ else+ {+ return descriptor_ops::non_blocking_read(+ o->descriptor_, o->bufs_.buffers(), o->bufs_.count(),+ o->ec_, o->bytes_transferred_);+ }+ }+ else if (after_completion)+ {+ if (!o->ec_ && o->bytes_transferred_ == 0)+ o->ec_ = asio::error::eof;+ }++ if (o->ec_ && o->ec_ == asio::error::would_block)+ {+ o->state_ |= descriptor_ops::internal_non_blocking;+ return false;+ }++ return after_completion;+ }++private:+ int descriptor_;+ descriptor_ops::state_type state_;+ MutableBufferSequence buffers_;+ buffer_sequence_adapter<asio::mutable_buffer,+ MutableBufferSequence> bufs_;+};++template <typename MutableBufferSequence, typename Handler, typename IoExecutor>+class io_uring_descriptor_read_op+ : public io_uring_descriptor_read_op_base<MutableBufferSequence>+{+public:+ ASIO_DEFINE_HANDLER_PTR(io_uring_descriptor_read_op);++ io_uring_descriptor_read_op(const asio::error_code& success_ec,+ int descriptor, descriptor_ops::state_type state,+ const MutableBufferSequence& buffers,+ Handler& handler, const IoExecutor& io_ex)+ : io_uring_descriptor_read_op_base<MutableBufferSequence>(success_ec,+ descriptor, state, buffers, &io_uring_descriptor_read_op::do_complete),+ handler_(ASIO_MOVE_CAST(Handler)(handler)),+ work_(handler_, io_ex)+ {+ }++ static void do_complete(void* owner, operation* base,+ const asio::error_code& /*ec*/,+ std::size_t /*bytes_transferred*/)+ {+ // Take ownership of the handler object.+ ASIO_ASSUME(base != 0);+ io_uring_descriptor_read_op* o+ (static_cast<io_uring_descriptor_read_op*>(base));+ ptr p = { asio::detail::addressof(o->handler_), o, o };++ ASIO_HANDLER_COMPLETION((*o));++ // Take ownership of the operation's outstanding work.+ handler_work<Handler, IoExecutor> w(+ ASIO_MOVE_CAST2(handler_work<Handler, IoExecutor>)(+ o->work_));++ ASIO_ERROR_LOCATION(o->ec_);++ // Make a copy of the handler so that the memory can be deallocated before+ // the upcall is made. Even if we're not about to make an upcall, a+ // sub-object of the handler may be the true owner of the memory associated+ // with the handler. Consequently, a local copy of the handler is required+ // to ensure that any owning sub-object remains valid until after we have+ // deallocated the memory here.+ detail::binder2<Handler, asio::error_code, std::size_t>+ handler(o->handler_, o->ec_, o->bytes_transferred_);+ p.h = asio::detail::addressof(handler.handler_);+ p.reset();++ // Make the upcall if required.+ if (owner)+ {+ fenced_block b(fenced_block::half);+ ASIO_HANDLER_INVOCATION_BEGIN((handler.arg1_, handler.arg2_));+ w.complete(handler, handler.handler_);+ ASIO_HANDLER_INVOCATION_END;+ }+ }++private:+ Handler handler_;+ handler_work<Handler, IoExecutor> work_;+};++} // namespace detail+} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // defined(ASIO_HAS_IO_URING)++#endif // ASIO_DETAIL_IO_URING_DESCRIPTOR_READ_OP_HPP
+ link/modules/asio-standalone/asio/include/asio/detail/io_uring_descriptor_service.hpp view
@@ -0,0 +1,687 @@+//+// detail/io_uring_descriptor_service.hpp+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com)+//+// Distributed under the Boost Software License, Version 1.0. (See accompanying+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)+//++#ifndef ASIO_DETAIL_IO_URING_DESCRIPTOR_SERVICE_HPP+#define ASIO_DETAIL_IO_URING_DESCRIPTOR_SERVICE_HPP++#if defined(_MSC_VER) && (_MSC_VER >= 1200)+# pragma once+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)++#include "asio/detail/config.hpp"++#if defined(ASIO_HAS_IO_URING)++#include "asio/associated_cancellation_slot.hpp"+#include "asio/buffer.hpp"+#include "asio/cancellation_type.hpp"+#include "asio/execution_context.hpp"+#include "asio/detail/buffer_sequence_adapter.hpp"+#include "asio/detail/descriptor_ops.hpp"+#include "asio/detail/io_uring_descriptor_read_at_op.hpp"+#include "asio/detail/io_uring_descriptor_read_op.hpp"+#include "asio/detail/io_uring_descriptor_write_at_op.hpp"+#include "asio/detail/io_uring_descriptor_write_op.hpp"+#include "asio/detail/io_uring_null_buffers_op.hpp"+#include "asio/detail/io_uring_service.hpp"+#include "asio/detail/io_uring_wait_op.hpp"+#include "asio/detail/memory.hpp"+#include "asio/detail/noncopyable.hpp"+#include "asio/posix/descriptor_base.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {+namespace detail {++class io_uring_descriptor_service :+ public execution_context_service_base<io_uring_descriptor_service>+{+public:+ // The native type of a descriptor.+ typedef int native_handle_type;++ // The implementation type of the descriptor.+ class implementation_type+ : private asio::detail::noncopyable+ {+ public:+ // Default constructor.+ implementation_type()+ : descriptor_(-1),+ state_(0)+ {+ }++ private:+ // Only this service will have access to the internal values.+ friend class io_uring_descriptor_service;++ // The native descriptor representation.+ int descriptor_;++ // The current state of the descriptor.+ descriptor_ops::state_type state_;++ // Per I/O object data used by the io_uring_service.+ io_uring_service::per_io_object_data io_object_data_;+ };++ // Constructor.+ ASIO_DECL io_uring_descriptor_service(execution_context& context);++ // Destroy all user-defined handler objects owned by the service.+ ASIO_DECL void shutdown();++ // Construct a new descriptor implementation.+ ASIO_DECL void construct(implementation_type& impl);++ // Move-construct a new descriptor implementation.+ ASIO_DECL void move_construct(implementation_type& impl,+ implementation_type& other_impl) ASIO_NOEXCEPT;++ // Move-assign from another descriptor implementation.+ ASIO_DECL void move_assign(implementation_type& impl,+ io_uring_descriptor_service& other_service,+ implementation_type& other_impl);++ // Destroy a descriptor implementation.+ ASIO_DECL void destroy(implementation_type& impl);++ // Assign a native descriptor to a descriptor implementation.+ ASIO_DECL asio::error_code assign(implementation_type& impl,+ const native_handle_type& native_descriptor,+ asio::error_code& ec);++ // Determine whether the descriptor is open.+ bool is_open(const implementation_type& impl) const+ {+ return impl.descriptor_ != -1;+ }++ // Destroy a descriptor implementation.+ ASIO_DECL asio::error_code close(implementation_type& impl,+ asio::error_code& ec);++ // Get the native descriptor representation.+ native_handle_type native_handle(const implementation_type& impl) const+ {+ return impl.descriptor_;+ }++ // Release ownership of the native descriptor representation.+ ASIO_DECL native_handle_type release(implementation_type& impl);++ // Release ownership of the native descriptor representation.+ native_handle_type release(implementation_type& impl,+ asio::error_code& ec)+ {+ ec = success_ec_;+ return release(impl);+ }++ // Cancel all operations associated with the descriptor.+ ASIO_DECL asio::error_code cancel(implementation_type& impl,+ asio::error_code& ec);++ // Perform an IO control command on the descriptor.+ template <typename IO_Control_Command>+ asio::error_code io_control(implementation_type& impl,+ IO_Control_Command& command, asio::error_code& ec)+ {+ descriptor_ops::ioctl(impl.descriptor_, impl.state_,+ command.name(), static_cast<ioctl_arg_type*>(command.data()), ec);+ ASIO_ERROR_LOCATION(ec);+ return ec;+ }++ // Gets the non-blocking mode of the descriptor.+ bool non_blocking(const implementation_type& impl) const+ {+ return (impl.state_ & descriptor_ops::user_set_non_blocking) != 0;+ }++ // Sets the non-blocking mode of the descriptor.+ asio::error_code non_blocking(implementation_type& impl,+ bool mode, asio::error_code& ec)+ {+ descriptor_ops::set_user_non_blocking(+ impl.descriptor_, impl.state_, mode, ec);+ ASIO_ERROR_LOCATION(ec);+ return ec;+ }++ // Gets the non-blocking mode of the native descriptor implementation.+ bool native_non_blocking(const implementation_type& impl) const+ {+ return (impl.state_ & descriptor_ops::internal_non_blocking) != 0;+ }++ // Sets the non-blocking mode of the native descriptor implementation.+ asio::error_code native_non_blocking(implementation_type& impl,+ bool mode, asio::error_code& ec)+ {+ descriptor_ops::set_internal_non_blocking(+ impl.descriptor_, impl.state_, mode, ec);+ ASIO_ERROR_LOCATION(ec);+ return ec;+ }++ // Wait for the descriptor to become ready to read, ready to write, or to have+ // pending error conditions.+ asio::error_code wait(implementation_type& impl,+ posix::descriptor_base::wait_type w, asio::error_code& ec)+ {+ switch (w)+ {+ case posix::descriptor_base::wait_read:+ descriptor_ops::poll_read(impl.descriptor_, impl.state_, ec);+ break;+ case posix::descriptor_base::wait_write:+ descriptor_ops::poll_write(impl.descriptor_, impl.state_, ec);+ break;+ case posix::descriptor_base::wait_error:+ descriptor_ops::poll_error(impl.descriptor_, impl.state_, ec);+ break;+ default:+ ec = asio::error::invalid_argument;+ break;+ }++ ASIO_ERROR_LOCATION(ec);+ return ec;+ }++ // Asynchronously wait for the descriptor to become ready to read, ready to+ // write, or to have pending error conditions.+ template <typename Handler, typename IoExecutor>+ void async_wait(implementation_type& impl,+ posix::descriptor_base::wait_type w,+ Handler& handler, const IoExecutor& io_ex)+ {+ bool is_continuation =+ asio_handler_cont_helpers::is_continuation(handler);++ typename associated_cancellation_slot<Handler>::type slot+ = asio::get_associated_cancellation_slot(handler);++ int op_type;+ int poll_flags;+ switch (w)+ {+ case posix::descriptor_base::wait_read:+ op_type = io_uring_service::read_op;+ poll_flags = POLLIN;+ break;+ case posix::descriptor_base::wait_write:+ op_type = io_uring_service::write_op;+ poll_flags = POLLOUT;+ break;+ case posix::descriptor_base::wait_error:+ op_type = io_uring_service::except_op;+ poll_flags = POLLPRI | POLLERR | POLLHUP;+ break;+ default:+ op_type = -1;+ poll_flags = -1;+ return;+ }++ // Allocate and construct an operation to wrap the handler.+ typedef io_uring_wait_op<Handler, IoExecutor> op;+ typename op::ptr p = { asio::detail::addressof(handler),+ op::ptr::allocate(handler), 0 };+ p.p = new (p.v) op(success_ec_, impl.descriptor_,+ poll_flags, handler, io_ex);++ // Optionally register for per-operation cancellation.+ if (slot.is_connected() && op_type != -1)+ {+ p.p->cancellation_key_ =+ &slot.template emplace<io_uring_op_cancellation>(+ &io_uring_service_, &impl.io_object_data_, op_type);+ }++ ASIO_HANDLER_CREATION((io_uring_service_.context(), *p.p,+ "descriptor", &impl, impl.descriptor_, "async_wait"));++ start_op(impl, op_type, p.p, is_continuation, op_type == -1);+ p.v = p.p = 0;+ }++ // Write some data to the descriptor.+ template <typename ConstBufferSequence>+ size_t write_some(implementation_type& impl,+ const ConstBufferSequence& buffers, asio::error_code& ec)+ {+ typedef buffer_sequence_adapter<asio::const_buffer,+ ConstBufferSequence> bufs_type;++ size_t n;+ if (bufs_type::is_single_buffer)+ {+ n = descriptor_ops::sync_write1(impl.descriptor_,+ impl.state_, bufs_type::first(buffers).data(),+ bufs_type::first(buffers).size(), ec);+ }+ else+ {+ bufs_type bufs(buffers);++ n = descriptor_ops::sync_write(impl.descriptor_, impl.state_,+ bufs.buffers(), bufs.count(), bufs.all_empty(), ec);+ }++ ASIO_ERROR_LOCATION(ec);+ return n;+ }++ // Wait until data can be written without blocking.+ size_t write_some(implementation_type& impl,+ const null_buffers&, asio::error_code& ec)+ {+ // Wait for descriptor to become ready.+ descriptor_ops::poll_write(impl.descriptor_, impl.state_, ec);++ ASIO_ERROR_LOCATION(ec);+ return 0;+ }++ // Start an asynchronous write. The data being sent must be valid for the+ // lifetime of the asynchronous operation.+ template <typename ConstBufferSequence, typename Handler, typename IoExecutor>+ void async_write_some(implementation_type& impl,+ const ConstBufferSequence& buffers, Handler& handler,+ const IoExecutor& io_ex)+ {+ bool is_continuation =+ asio_handler_cont_helpers::is_continuation(handler);++ typename associated_cancellation_slot<Handler>::type slot+ = asio::get_associated_cancellation_slot(handler);++ // Allocate and construct an operation to wrap the handler.+ typedef io_uring_descriptor_write_op<+ ConstBufferSequence, Handler, IoExecutor> op;+ typename op::ptr p = { asio::detail::addressof(handler),+ op::ptr::allocate(handler), 0 };+ p.p = new (p.v) op(success_ec_, impl.descriptor_,+ impl.state_, buffers, handler, io_ex);++ // Optionally register for per-operation cancellation.+ if (slot.is_connected())+ {+ p.p->cancellation_key_ =+ &slot.template emplace<io_uring_op_cancellation>(&io_uring_service_,+ &impl.io_object_data_, io_uring_service::write_op);+ }++ ASIO_HANDLER_CREATION((io_uring_service_.context(), *p.p,+ "descriptor", &impl, impl.descriptor_, "async_write_some"));++ start_op(impl, io_uring_service::write_op, p.p, is_continuation,+ buffer_sequence_adapter<asio::const_buffer,+ ConstBufferSequence>::all_empty(buffers));+ p.v = p.p = 0;+ }++ // Start an asynchronous wait until data can be written without blocking.+ template <typename Handler, typename IoExecutor>+ void async_write_some(implementation_type& impl,+ const null_buffers&, Handler& handler, const IoExecutor& io_ex)+ {+ bool is_continuation =+ asio_handler_cont_helpers::is_continuation(handler);++ typename associated_cancellation_slot<Handler>::type slot+ = asio::get_associated_cancellation_slot(handler);++ // Allocate and construct an operation to wrap the handler.+ typedef io_uring_null_buffers_op<Handler, IoExecutor> op;+ typename op::ptr p = { asio::detail::addressof(handler),+ op::ptr::allocate(handler), 0 };+ p.p = new (p.v) op(success_ec_, impl.descriptor_, POLLOUT, handler, io_ex);++ // Optionally register for per-operation cancellation.+ if (slot.is_connected())+ {+ p.p->cancellation_key_ =+ &slot.template emplace<io_uring_op_cancellation>(&io_uring_service_,+ &impl.io_object_data_, io_uring_service::write_op);+ }++ ASIO_HANDLER_CREATION((io_uring_service_.context(),+ *p.p, "descriptor", &impl, impl.descriptor_,+ "async_write_some(null_buffers)"));++ start_op(impl, io_uring_service::write_op, p.p, is_continuation, false);+ p.v = p.p = 0;+ }++ // Write some data to the descriptor at the specified offset.+ template <typename ConstBufferSequence>+ size_t write_some_at(implementation_type& impl, uint64_t offset,+ const ConstBufferSequence& buffers, asio::error_code& ec)+ {+ typedef buffer_sequence_adapter<asio::const_buffer,+ ConstBufferSequence> bufs_type;++ size_t n;+ if (bufs_type::is_single_buffer)+ {+ n = descriptor_ops::sync_write_at1(impl.descriptor_,+ impl.state_, offset, bufs_type::first(buffers).data(),+ bufs_type::first(buffers).size(), ec);+ }+ else+ {+ bufs_type bufs(buffers);++ n = descriptor_ops::sync_write_at(impl.descriptor_, impl.state_,+ offset, bufs.buffers(), bufs.count(), bufs.all_empty(), ec);+ }++ ASIO_ERROR_LOCATION(ec);+ return n;+ }++ // Wait until data can be written without blocking.+ size_t write_some_at(implementation_type& impl, uint64_t,+ const null_buffers& buffers, asio::error_code& ec)+ {+ return write_some(impl, buffers, ec);+ }++ // Start an asynchronous write at the specified offset. The data being sent+ // must be valid for the lifetime of the asynchronous operation.+ template <typename ConstBufferSequence, typename Handler, typename IoExecutor>+ void async_write_some_at(implementation_type& impl, uint64_t offset,+ const ConstBufferSequence& buffers, Handler& handler,+ const IoExecutor& io_ex)+ {+ bool is_continuation =+ asio_handler_cont_helpers::is_continuation(handler);++ typename associated_cancellation_slot<Handler>::type slot+ = asio::get_associated_cancellation_slot(handler);++ // Allocate and construct an operation to wrap the handler.+ typedef io_uring_descriptor_write_at_op<+ ConstBufferSequence, Handler, IoExecutor> op;+ typename op::ptr p = { asio::detail::addressof(handler),+ op::ptr::allocate(handler), 0 };+ p.p = new (p.v) op(success_ec_, impl.descriptor_,+ impl.state_, offset, buffers, handler, io_ex);++ // Optionally register for per-operation cancellation.+ if (slot.is_connected())+ {+ p.p->cancellation_key_ =+ &slot.template emplace<io_uring_op_cancellation>(&io_uring_service_,+ &impl.io_object_data_, io_uring_service::write_op);+ }++ ASIO_HANDLER_CREATION((io_uring_service_.context(), *p.p,+ "descriptor", &impl, impl.descriptor_, "async_write_some"));++ start_op(impl, io_uring_service::write_op, p.p, is_continuation,+ buffer_sequence_adapter<asio::const_buffer,+ ConstBufferSequence>::all_empty(buffers));+ p.v = p.p = 0;+ }++ // Start an asynchronous wait until data can be written without blocking.+ template <typename Handler, typename IoExecutor>+ void async_write_some_at(implementation_type& impl,+ const null_buffers& buffers, Handler& handler, const IoExecutor& io_ex)+ {+ return async_write_some(impl, buffers, handler, io_ex);+ }++ // Read some data from the stream. Returns the number of bytes read.+ template <typename MutableBufferSequence>+ size_t read_some(implementation_type& impl,+ const MutableBufferSequence& buffers, asio::error_code& ec)+ {+ typedef buffer_sequence_adapter<asio::mutable_buffer,+ MutableBufferSequence> bufs_type;++ size_t n;+ if (bufs_type::is_single_buffer)+ {+ n = descriptor_ops::sync_read1(impl.descriptor_,+ impl.state_, bufs_type::first(buffers).data(),+ bufs_type::first(buffers).size(), ec);+ }+ else+ {+ bufs_type bufs(buffers);++ n = descriptor_ops::sync_read(impl.descriptor_, impl.state_,+ bufs.buffers(), bufs.count(), bufs.all_empty(), ec);+ }++ ASIO_ERROR_LOCATION(ec);+ return n;+ }++ // Wait until data can be read without blocking.+ size_t read_some(implementation_type& impl,+ const null_buffers&, asio::error_code& ec)+ {+ // Wait for descriptor to become ready.+ descriptor_ops::poll_read(impl.descriptor_, impl.state_, ec);++ ASIO_ERROR_LOCATION(ec);+ return 0;+ }++ // Start an asynchronous read. The buffer for the data being read must be+ // valid for the lifetime of the asynchronous operation.+ template <typename MutableBufferSequence,+ typename Handler, typename IoExecutor>+ void async_read_some(implementation_type& impl,+ const MutableBufferSequence& buffers,+ Handler& handler, const IoExecutor& io_ex)+ {+ bool is_continuation =+ asio_handler_cont_helpers::is_continuation(handler);++ typename associated_cancellation_slot<Handler>::type slot+ = asio::get_associated_cancellation_slot(handler);++ // Allocate and construct an operation to wrap the handler.+ typedef io_uring_descriptor_read_op<+ MutableBufferSequence, Handler, IoExecutor> op;+ typename op::ptr p = { asio::detail::addressof(handler),+ op::ptr::allocate(handler), 0 };+ p.p = new (p.v) op(success_ec_, impl.descriptor_,+ impl.state_, buffers, handler, io_ex);++ // Optionally register for per-operation cancellation.+ if (slot.is_connected())+ {+ p.p->cancellation_key_ =+ &slot.template emplace<io_uring_op_cancellation>(&io_uring_service_,+ &impl.io_object_data_, io_uring_service::read_op);+ }++ ASIO_HANDLER_CREATION((io_uring_service_.context(), *p.p,+ "descriptor", &impl, impl.descriptor_, "async_read_some"));++ start_op(impl, io_uring_service::read_op, p.p, is_continuation,+ buffer_sequence_adapter<asio::mutable_buffer,+ MutableBufferSequence>::all_empty(buffers));+ p.v = p.p = 0;+ }++ // Wait until data can be read without blocking.+ template <typename Handler, typename IoExecutor>+ void async_read_some(implementation_type& impl,+ const null_buffers&, Handler& handler, const IoExecutor& io_ex)+ {+ bool is_continuation =+ asio_handler_cont_helpers::is_continuation(handler);++ typename associated_cancellation_slot<Handler>::type slot+ = asio::get_associated_cancellation_slot(handler);++ // Allocate and construct an operation to wrap the handler.+ typedef io_uring_null_buffers_op<Handler, IoExecutor> op;+ typename op::ptr p = { asio::detail::addressof(handler),+ op::ptr::allocate(handler), 0 };+ p.p = new (p.v) op(success_ec_, impl.descriptor_, POLLIN, handler, io_ex);++ // Optionally register for per-operation cancellation.+ if (slot.is_connected())+ {+ p.p->cancellation_key_ =+ &slot.template emplace<io_uring_op_cancellation>(&io_uring_service_,+ &impl.io_object_data_, io_uring_service::read_op);+ }++ ASIO_HANDLER_CREATION((io_uring_service_.context(),+ *p.p, "descriptor", &impl, impl.descriptor_,+ "async_read_some(null_buffers)"));++ start_op(impl, io_uring_service::read_op, p.p, is_continuation, false);+ p.v = p.p = 0;+ }++ // Read some data at the specified offset. Returns the number of bytes read.+ template <typename MutableBufferSequence>+ size_t read_some_at(implementation_type& impl, uint64_t offset,+ const MutableBufferSequence& buffers, asio::error_code& ec)+ {+ typedef buffer_sequence_adapter<asio::mutable_buffer,+ MutableBufferSequence> bufs_type;++ if (bufs_type::is_single_buffer)+ {+ return descriptor_ops::sync_read_at1(impl.descriptor_,+ impl.state_, offset, bufs_type::first(buffers).data(),+ bufs_type::first(buffers).size(), ec);+ }+ else+ {+ bufs_type bufs(buffers);++ return descriptor_ops::sync_read_at(impl.descriptor_, impl.state_,+ offset, bufs.buffers(), bufs.count(), bufs.all_empty(), ec);+ }+ }++ // Wait until data can be read without blocking.+ size_t read_some_at(implementation_type& impl, uint64_t,+ const null_buffers& buffers, asio::error_code& ec)+ {+ return read_some(impl, buffers, ec);+ }++ // Start an asynchronous read. The buffer for the data being read must be+ // valid for the lifetime of the asynchronous operation.+ template <typename MutableBufferSequence,+ typename Handler, typename IoExecutor>+ void async_read_some_at(implementation_type& impl,+ uint64_t offset, const MutableBufferSequence& buffers,+ Handler& handler, const IoExecutor& io_ex)+ {+ bool is_continuation =+ asio_handler_cont_helpers::is_continuation(handler);++ typename associated_cancellation_slot<Handler>::type slot+ = asio::get_associated_cancellation_slot(handler);++ // Allocate and construct an operation to wrap the handler.+ typedef io_uring_descriptor_read_at_op<+ MutableBufferSequence, Handler, IoExecutor> op;+ typename op::ptr p = { asio::detail::addressof(handler),+ op::ptr::allocate(handler), 0 };+ p.p = new (p.v) op(success_ec_, impl.descriptor_,+ impl.state_, offset, buffers, handler, io_ex);++ // Optionally register for per-operation cancellation.+ if (slot.is_connected())+ {+ p.p->cancellation_key_ =+ &slot.template emplace<io_uring_op_cancellation>(&io_uring_service_,+ &impl.io_object_data_, io_uring_service::read_op);+ }++ ASIO_HANDLER_CREATION((io_uring_service_.context(), *p.p,+ "descriptor", &impl, impl.descriptor_, "async_read_some"));++ start_op(impl, io_uring_service::read_op, p.p, is_continuation,+ buffer_sequence_adapter<asio::mutable_buffer,+ MutableBufferSequence>::all_empty(buffers));+ p.v = p.p = 0;+ }++ // Wait until data can be read without blocking.+ template <typename Handler, typename IoExecutor>+ void async_read_some_at(implementation_type& impl, uint64_t,+ const null_buffers& buffers, Handler& handler, const IoExecutor& io_ex)+ {+ return async_read_some(impl, buffers, handler, io_ex);+ }++private:+ // Start the asynchronous operation.+ ASIO_DECL void start_op(implementation_type& impl, int op_type,+ io_uring_operation* op, bool is_continuation, bool noop);++ // Helper class used to implement per-operation cancellation+ class io_uring_op_cancellation+ {+ public:+ io_uring_op_cancellation(io_uring_service* s,+ io_uring_service::per_io_object_data* p, int o)+ : io_uring_service_(s),+ io_object_data_(p),+ op_type_(o)+ {+ }++ void operator()(cancellation_type_t type)+ {+ if (!!(type &+ (cancellation_type::terminal+ | cancellation_type::partial+ | cancellation_type::total)))+ {+ io_uring_service_->cancel_ops_by_key(*io_object_data_, op_type_, this);+ }+ }++ private:+ io_uring_service* io_uring_service_;+ io_uring_service::per_io_object_data* io_object_data_;+ int op_type_;+ };++ // The io_uring_service that performs event demultiplexing for the service.+ io_uring_service& io_uring_service_;++ // Cached success value to avoid accessing category singleton.+ const asio::error_code success_ec_;+};++} // namespace detail+} // namespace asio++#include "asio/detail/pop_options.hpp"++#if defined(ASIO_HEADER_ONLY)+# include "asio/detail/impl/io_uring_descriptor_service.ipp"+#endif // defined(ASIO_HEADER_ONLY)++#endif // defined(ASIO_HAS_IO_URING)++#endif // ASIO_DETAIL_IO_URING_DESCRIPTOR_SERVICE_HPP
+ link/modules/asio-standalone/asio/include/asio/detail/io_uring_descriptor_write_at_op.hpp view
@@ -0,0 +1,189 @@+//+// detail/io_uring_descriptor_write_at_op.hpp+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com)+//+// Distributed under the Boost Software License, Version 1.0. (See accompanying+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)+//++#ifndef ASIO_DETAIL_IO_URING_DESCRIPTOR_WRITE_AT_OP_HPP+#define ASIO_DETAIL_IO_URING_DESCRIPTOR_WRITE_AT_OP_HPP++#if defined(_MSC_VER) && (_MSC_VER >= 1200)+# pragma once+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)++#include "asio/detail/config.hpp"++#if defined(ASIO_HAS_IO_URING)++#include "asio/detail/bind_handler.hpp"+#include "asio/detail/buffer_sequence_adapter.hpp"+#include "asio/detail/descriptor_ops.hpp"+#include "asio/detail/fenced_block.hpp"+#include "asio/detail/handler_work.hpp"+#include "asio/detail/io_uring_operation.hpp"+#include "asio/detail/memory.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {+namespace detail {++template <typename ConstBufferSequence>+class io_uring_descriptor_write_at_op_base : public io_uring_operation+{+public:+ io_uring_descriptor_write_at_op_base(+ const asio::error_code& success_ec, int descriptor,+ descriptor_ops::state_type state, uint64_t offset,+ const ConstBufferSequence& buffers, func_type complete_func)+ : io_uring_operation(success_ec,+ &io_uring_descriptor_write_at_op_base::do_prepare,+ &io_uring_descriptor_write_at_op_base::do_perform, complete_func),+ descriptor_(descriptor),+ state_(state),+ offset_(offset),+ buffers_(buffers),+ bufs_(buffers)+ {+ }++ static void do_prepare(io_uring_operation* base, ::io_uring_sqe* sqe)+ {+ ASIO_ASSUME(base != 0);+ io_uring_descriptor_write_at_op_base* o(+ static_cast<io_uring_descriptor_write_at_op_base*>(base));++ if ((o->state_ & descriptor_ops::internal_non_blocking) != 0)+ {+ ::io_uring_prep_poll_add(sqe, o->descriptor_, POLLOUT);+ }+ else if (o->bufs_.is_single_buffer && o->bufs_.is_registered_buffer)+ {+ ::io_uring_prep_write_fixed(sqe, o->descriptor_,+ o->bufs_.buffers()->iov_base, o->bufs_.buffers()->iov_len,+ o->offset_, o->bufs_.registered_id().native_handle());+ }+ else+ {+ ::io_uring_prep_writev(sqe, o->descriptor_,+ o->bufs_.buffers(), o->bufs_.count(), o->offset_);+ }+ }++ static bool do_perform(io_uring_operation* base, bool after_completion)+ {+ ASIO_ASSUME(base != 0);+ io_uring_descriptor_write_at_op_base* o(+ static_cast<io_uring_descriptor_write_at_op_base*>(base));++ if ((o->state_ & descriptor_ops::internal_non_blocking) != 0)+ {+ if (o->bufs_.is_single_buffer)+ {+ return descriptor_ops::non_blocking_write_at1(o->descriptor_,+ o->offset_, o->bufs_.first(o->buffers_).data(),+ o->bufs_.first(o->buffers_).size(), o->ec_,+ o->bytes_transferred_);+ }+ else+ {+ return descriptor_ops::non_blocking_write_at(o->descriptor_,+ o->offset_, o->bufs_.buffers(), o->bufs_.count(),+ o->ec_, o->bytes_transferred_);+ }+ }++ if (o->ec_ && o->ec_ == asio::error::would_block)+ {+ o->state_ |= descriptor_ops::internal_non_blocking;+ return false;+ }++ return after_completion;+ }++private:+ int descriptor_;+ descriptor_ops::state_type state_;+ uint64_t offset_;+ ConstBufferSequence buffers_;+ buffer_sequence_adapter<asio::const_buffer,+ ConstBufferSequence> bufs_;+};++template <typename ConstBufferSequence, typename Handler, typename IoExecutor>+class io_uring_descriptor_write_at_op+ : public io_uring_descriptor_write_at_op_base<ConstBufferSequence>+{+public:+ ASIO_DEFINE_HANDLER_PTR(io_uring_descriptor_write_at_op);++ io_uring_descriptor_write_at_op(const asio::error_code& success_ec,+ int descriptor, descriptor_ops::state_type state, uint64_t offset,+ const ConstBufferSequence& buffers, Handler& handler,+ const IoExecutor& io_ex)+ : io_uring_descriptor_write_at_op_base<ConstBufferSequence>(+ success_ec, descriptor, state, offset, buffers,+ &io_uring_descriptor_write_at_op::do_complete),+ handler_(ASIO_MOVE_CAST(Handler)(handler)),+ work_(handler_, io_ex)+ {+ }++ static void do_complete(void* owner, operation* base,+ const asio::error_code& /*ec*/,+ std::size_t /*bytes_transferred*/)+ {+ // Take ownership of the handler object.+ ASIO_ASSUME(base != 0);+ io_uring_descriptor_write_at_op* o+ (static_cast<io_uring_descriptor_write_at_op*>(base));+ ptr p = { asio::detail::addressof(o->handler_), o, o };++ ASIO_HANDLER_COMPLETION((*o));++ // Take ownership of the operation's outstanding work.+ handler_work<Handler, IoExecutor> w(+ ASIO_MOVE_CAST2(handler_work<Handler, IoExecutor>)(+ o->work_));++ ASIO_ERROR_LOCATION(o->ec_);++ // Make a copy of the handler so that the memory can be deallocated before+ // the upcall is made. Even if we're not about to make an upcall, a+ // sub-object of the handler may be the true owner of the memory associated+ // with the handler. Consequently, a local copy of the handler is required+ // to ensure that any owning sub-object remains valid until after we have+ // deallocated the memory here.+ detail::binder2<Handler, asio::error_code, std::size_t>+ handler(o->handler_, o->ec_, o->bytes_transferred_);+ p.h = asio::detail::addressof(handler.handler_);+ p.reset();++ // Make the upcall if required.+ if (owner)+ {+ fenced_block b(fenced_block::half);+ ASIO_HANDLER_INVOCATION_BEGIN((handler.arg1_, handler.arg2_));+ w.complete(handler, handler.handler_);+ ASIO_HANDLER_INVOCATION_END;+ }+ }++private:+ Handler handler_;+ handler_work<Handler, IoExecutor> work_;+};++} // namespace detail+} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // defined(ASIO_HAS_IO_URING)++#endif // ASIO_DETAIL_IO_URING_DESCRIPTOR_WRITE_AT_OP_HPP
+ link/modules/asio-standalone/asio/include/asio/detail/io_uring_descriptor_write_op.hpp view
@@ -0,0 +1,185 @@+//+// detail/io_uring_descriptor_write_op.hpp+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com)+//+// Distributed under the Boost Software License, Version 1.0. (See accompanying+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)+//++#ifndef ASIO_DETAIL_IO_URING_DESCRIPTOR_WRITE_OP_HPP+#define ASIO_DETAIL_IO_URING_DESCRIPTOR_WRITE_OP_HPP++#if defined(_MSC_VER) && (_MSC_VER >= 1200)+# pragma once+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)++#include "asio/detail/config.hpp"++#if defined(ASIO_HAS_IO_URING)++#include "asio/detail/bind_handler.hpp"+#include "asio/detail/buffer_sequence_adapter.hpp"+#include "asio/detail/descriptor_ops.hpp"+#include "asio/detail/fenced_block.hpp"+#include "asio/detail/handler_work.hpp"+#include "asio/detail/io_uring_operation.hpp"+#include "asio/detail/memory.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {+namespace detail {++template <typename ConstBufferSequence>+class io_uring_descriptor_write_op_base : public io_uring_operation+{+public:+ io_uring_descriptor_write_op_base(const asio::error_code& success_ec,+ int descriptor, descriptor_ops::state_type state,+ const ConstBufferSequence& buffers, func_type complete_func)+ : io_uring_operation(success_ec,+ &io_uring_descriptor_write_op_base::do_prepare,+ &io_uring_descriptor_write_op_base::do_perform, complete_func),+ descriptor_(descriptor),+ state_(state),+ buffers_(buffers),+ bufs_(buffers)+ {+ }++ static void do_prepare(io_uring_operation* base, ::io_uring_sqe* sqe)+ {+ ASIO_ASSUME(base != 0);+ io_uring_descriptor_write_op_base* o(+ static_cast<io_uring_descriptor_write_op_base*>(base));++ if ((o->state_ & descriptor_ops::internal_non_blocking) != 0)+ {+ ::io_uring_prep_poll_add(sqe, o->descriptor_, POLLOUT);+ }+ else if (o->bufs_.is_single_buffer && o->bufs_.is_registered_buffer)+ {+ ::io_uring_prep_write_fixed(sqe, o->descriptor_,+ o->bufs_.buffers()->iov_base, o->bufs_.buffers()->iov_len,+ 0, o->bufs_.registered_id().native_handle());+ }+ else+ {+ ::io_uring_prep_writev(sqe, o->descriptor_,+ o->bufs_.buffers(), o->bufs_.count(), -1);+ }+ }++ static bool do_perform(io_uring_operation* base, bool after_completion)+ {+ ASIO_ASSUME(base != 0);+ io_uring_descriptor_write_op_base* o(+ static_cast<io_uring_descriptor_write_op_base*>(base));++ if ((o->state_ & descriptor_ops::internal_non_blocking) != 0)+ {+ if (o->bufs_.is_single_buffer)+ {+ return descriptor_ops::non_blocking_write1(+ o->descriptor_, o->bufs_.first(o->buffers_).data(),+ o->bufs_.first(o->buffers_).size(), o->ec_,+ o->bytes_transferred_);+ }+ else+ {+ return descriptor_ops::non_blocking_write(+ o->descriptor_, o->bufs_.buffers(), o->bufs_.count(),+ o->ec_, o->bytes_transferred_);+ }+ }++ if (o->ec_ && o->ec_ == asio::error::would_block)+ {+ o->state_ |= descriptor_ops::internal_non_blocking;+ return false;+ }++ return after_completion;+ }++private:+ int descriptor_;+ descriptor_ops::state_type state_;+ ConstBufferSequence buffers_;+ buffer_sequence_adapter<asio::const_buffer,+ ConstBufferSequence> bufs_;+};++template <typename ConstBufferSequence, typename Handler, typename IoExecutor>+class io_uring_descriptor_write_op+ : public io_uring_descriptor_write_op_base<ConstBufferSequence>+{+public:+ ASIO_DEFINE_HANDLER_PTR(io_uring_descriptor_write_op);++ io_uring_descriptor_write_op(const asio::error_code& success_ec,+ int descriptor, descriptor_ops::state_type state,+ const ConstBufferSequence& buffers, Handler& handler,+ const IoExecutor& io_ex)+ : io_uring_descriptor_write_op_base<ConstBufferSequence>(success_ec,+ descriptor, state, buffers, &io_uring_descriptor_write_op::do_complete),+ handler_(ASIO_MOVE_CAST(Handler)(handler)),+ work_(handler_, io_ex)+ {+ }++ static void do_complete(void* owner, operation* base,+ const asio::error_code& /*ec*/,+ std::size_t /*bytes_transferred*/)+ {+ // Take ownership of the handler object.+ ASIO_ASSUME(base != 0);+ io_uring_descriptor_write_op* o+ (static_cast<io_uring_descriptor_write_op*>(base));+ ptr p = { asio::detail::addressof(o->handler_), o, o };++ ASIO_HANDLER_COMPLETION((*o));++ // Take ownership of the operation's outstanding work.+ handler_work<Handler, IoExecutor> w(+ ASIO_MOVE_CAST2(handler_work<Handler, IoExecutor>)(+ o->work_));++ ASIO_ERROR_LOCATION(o->ec_);++ // Make a copy of the handler so that the memory can be deallocated before+ // the upcall is made. Even if we're not about to make an upcall, a+ // sub-object of the handler may be the true owner of the memory associated+ // with the handler. Consequently, a local copy of the handler is required+ // to ensure that any owning sub-object remains valid until after we have+ // deallocated the memory here.+ detail::binder2<Handler, asio::error_code, std::size_t>+ handler(o->handler_, o->ec_, o->bytes_transferred_);+ p.h = asio::detail::addressof(handler.handler_);+ p.reset();++ // Make the upcall if required.+ if (owner)+ {+ fenced_block b(fenced_block::half);+ ASIO_HANDLER_INVOCATION_BEGIN((handler.arg1_, handler.arg2_));+ w.complete(handler, handler.handler_);+ ASIO_HANDLER_INVOCATION_END;+ }+ }++private:+ Handler handler_;+ handler_work<Handler, IoExecutor> work_;+};++} // namespace detail+} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // defined(ASIO_HAS_IO_URING)++#endif // ASIO_DETAIL_IO_URING_DESCRIPTOR_WRITE_OP_HPP
+ link/modules/asio-standalone/asio/include/asio/detail/io_uring_file_service.hpp view
@@ -0,0 +1,261 @@+//+// detail/io_uring_file_service.hpp+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com)+//+// Distributed under the Boost Software License, Version 1.0. (See accompanying+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)+//++#ifndef ASIO_DETAIL_IO_URING_FILE_SERVICE_HPP+#define ASIO_DETAIL_IO_URING_FILE_SERVICE_HPP++#if defined(_MSC_VER) && (_MSC_VER >= 1200)+# pragma once+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)++#include "asio/detail/config.hpp"++#if defined(ASIO_HAS_FILE) \+ && defined(ASIO_HAS_IO_URING)++#include <string>+#include "asio/detail/cstdint.hpp"+#include "asio/detail/descriptor_ops.hpp"+#include "asio/detail/io_uring_descriptor_service.hpp"+#include "asio/error.hpp"+#include "asio/execution_context.hpp"+#include "asio/file_base.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {+namespace detail {++// Extend the io_uring_descriptor_service to provide file support.+class io_uring_file_service :+ public execution_context_service_base<io_uring_file_service>+{+public:+ typedef io_uring_descriptor_service descriptor_service;++ // The native type of a file.+ typedef descriptor_service::native_handle_type native_handle_type;++ // The implementation type of the file.+ class implementation_type : descriptor_service::implementation_type+ {+ private:+ // Only this service will have access to the internal values.+ friend class io_uring_file_service;++ bool is_stream_;+ };++ ASIO_DECL io_uring_file_service(execution_context& context);++ // Destroy all user-defined handler objects owned by the service.+ ASIO_DECL void shutdown();++ // Construct a new file implementation.+ void construct(implementation_type& impl)+ {+ descriptor_service_.construct(impl);+ impl.is_stream_ = false;+ }++ // Move-construct a new file implementation.+ void move_construct(implementation_type& impl,+ implementation_type& other_impl)+ {+ descriptor_service_.move_construct(impl, other_impl);+ impl.is_stream_ = other_impl.is_stream_;+ }++ // Move-assign from another file implementation.+ void move_assign(implementation_type& impl,+ io_uring_file_service& other_service,+ implementation_type& other_impl)+ {+ descriptor_service_.move_assign(impl,+ other_service.descriptor_service_, other_impl);+ impl.is_stream_ = other_impl.is_stream_;+ }++ // Destroy a file implementation.+ void destroy(implementation_type& impl)+ {+ descriptor_service_.destroy(impl);+ }++ // Open the file using the specified path name.+ ASIO_DECL asio::error_code open(implementation_type& impl,+ const char* path, file_base::flags open_flags,+ asio::error_code& ec);++ // Assign a native descriptor to a file implementation.+ asio::error_code assign(implementation_type& impl,+ const native_handle_type& native_descriptor,+ asio::error_code& ec)+ {+ return descriptor_service_.assign(impl, native_descriptor, ec);+ }++ // Set whether the implementation is stream-oriented.+ void set_is_stream(implementation_type& impl, bool is_stream)+ {+ impl.is_stream_ = is_stream;+ }++ // Determine whether the file is open.+ bool is_open(const implementation_type& impl) const+ {+ return descriptor_service_.is_open(impl);+ }++ // Destroy a file implementation.+ asio::error_code close(implementation_type& impl,+ asio::error_code& ec)+ {+ return descriptor_service_.close(impl, ec);+ }++ // Get the native file representation.+ native_handle_type native_handle(const implementation_type& impl) const+ {+ return descriptor_service_.native_handle(impl);+ }++ // Release ownership of the native descriptor representation.+ native_handle_type release(implementation_type& impl,+ asio::error_code& ec)+ {+ return descriptor_service_.release(impl, ec);+ }++ // Cancel all operations associated with the file.+ asio::error_code cancel(implementation_type& impl,+ asio::error_code& ec)+ {+ return descriptor_service_.cancel(impl, ec);+ }++ // Get the size of the file.+ ASIO_DECL uint64_t size(const implementation_type& impl,+ asio::error_code& ec) const;++ // Alter the size of the file.+ ASIO_DECL asio::error_code resize(implementation_type& impl,+ uint64_t n, asio::error_code& ec);++ // Synchronise the file to disk.+ ASIO_DECL asio::error_code sync_all(implementation_type& impl,+ asio::error_code& ec);++ // Synchronise the file data to disk.+ ASIO_DECL asio::error_code sync_data(implementation_type& impl,+ asio::error_code& ec);++ // Seek to a position in the file.+ ASIO_DECL uint64_t seek(implementation_type& impl, int64_t offset,+ file_base::seek_basis whence, asio::error_code& ec);++ // Write the given data. Returns the number of bytes written.+ template <typename ConstBufferSequence>+ size_t write_some(implementation_type& impl,+ const ConstBufferSequence& buffers, asio::error_code& ec)+ {+ return descriptor_service_.write_some(impl, buffers, ec);+ }++ // Start an asynchronous write. The data being written must be valid for the+ // lifetime of the asynchronous operation.+ template <typename ConstBufferSequence, typename Handler, typename IoExecutor>+ void async_write_some(implementation_type& impl,+ const ConstBufferSequence& buffers,+ Handler& handler, const IoExecutor& io_ex)+ {+ descriptor_service_.async_write_some(impl, buffers, handler, io_ex);+ }++ // Write the given data at the specified location. Returns the number of+ // bytes written.+ template <typename ConstBufferSequence>+ size_t write_some_at(implementation_type& impl, uint64_t offset,+ const ConstBufferSequence& buffers, asio::error_code& ec)+ {+ return descriptor_service_.write_some_at(impl, offset, buffers, ec);+ }++ // Start an asynchronous write at the specified location. The data being+ // written must be valid for the lifetime of the asynchronous operation.+ template <typename ConstBufferSequence, typename Handler, typename IoExecutor>+ void async_write_some_at(implementation_type& impl,+ uint64_t offset, const ConstBufferSequence& buffers,+ Handler& handler, const IoExecutor& io_ex)+ {+ descriptor_service_.async_write_some_at(+ impl, offset, buffers, handler, io_ex);+ }++ // Read some data. Returns the number of bytes read.+ template <typename MutableBufferSequence>+ size_t read_some(implementation_type& impl,+ const MutableBufferSequence& buffers, asio::error_code& ec)+ {+ return descriptor_service_.read_some(impl, buffers, ec);+ }++ // Start an asynchronous read. The buffer for the data being read must be+ // valid for the lifetime of the asynchronous operation.+ template <typename MutableBufferSequence,+ typename Handler, typename IoExecutor>+ void async_read_some(implementation_type& impl,+ const MutableBufferSequence& buffers,+ Handler& handler, const IoExecutor& io_ex)+ {+ descriptor_service_.async_read_some(impl, buffers, handler, io_ex);+ }++ // Read some data. Returns the number of bytes read.+ template <typename MutableBufferSequence>+ size_t read_some_at(implementation_type& impl, uint64_t offset,+ const MutableBufferSequence& buffers, asio::error_code& ec)+ {+ return descriptor_service_.read_some_at(impl, offset, buffers, ec);+ }++ // Start an asynchronous read. The buffer for the data being read must be+ // valid for the lifetime of the asynchronous operation.+ template <typename MutableBufferSequence,+ typename Handler, typename IoExecutor>+ void async_read_some_at(implementation_type& impl,+ uint64_t offset, const MutableBufferSequence& buffers,+ Handler& handler, const IoExecutor& io_ex)+ {+ descriptor_service_.async_read_some_at(+ impl, offset, buffers, handler, io_ex);+ }++private:+ // The implementation used for initiating asynchronous operations.+ descriptor_service descriptor_service_;++ // Cached success value to avoid accessing category singleton.+ const asio::error_code success_ec_;+};++} // namespace detail+} // namespace asio++#include "asio/detail/pop_options.hpp"++#if defined(ASIO_HEADER_ONLY)+# include "asio/detail/impl/io_uring_file_service.ipp"+#endif // defined(ASIO_HEADER_ONLY)++#endif // defined(ASIO_HAS_FILE)+ // && defined(ASIO_HAS_IO_URING)++#endif // ASIO_DETAIL_IO_URING_FILE_SERVICE_HPP
+ link/modules/asio-standalone/asio/include/asio/detail/io_uring_null_buffers_op.hpp view
@@ -0,0 +1,115 @@+//+// detail/io_uring_null_buffers_op.hpp+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com)+//+// Distributed under the Boost Software License, Version 1.0. (See accompanying+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)+//++#ifndef ASIO_DETAIL_IO_URING_NULL_BUFFERS_OP_HPP+#define ASIO_DETAIL_IO_URING_NULL_BUFFERS_OP_HPP++#if defined(_MSC_VER) && (_MSC_VER >= 1200)+# pragma once+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)++#include "asio/detail/config.hpp"+#include "asio/detail/bind_handler.hpp"+#include "asio/detail/fenced_block.hpp"+#include "asio/detail/handler_alloc_helpers.hpp"+#include "asio/detail/handler_invoke_helpers.hpp"+#include "asio/detail/handler_work.hpp"+#include "asio/detail/io_uring_operation.hpp"+#include "asio/detail/memory.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {+namespace detail {++template <typename Handler, typename IoExecutor>+class io_uring_null_buffers_op : public io_uring_operation+{+public:+ ASIO_DEFINE_HANDLER_PTR(io_uring_null_buffers_op);++ io_uring_null_buffers_op(const asio::error_code& success_ec,+ int descriptor, int poll_flags, Handler& handler, const IoExecutor& io_ex)+ : io_uring_operation(success_ec,+ &io_uring_null_buffers_op::do_prepare,+ &io_uring_null_buffers_op::do_perform,+ &io_uring_null_buffers_op::do_complete),+ handler_(ASIO_MOVE_CAST(Handler)(handler)),+ work_(handler_, io_ex),+ descriptor_(descriptor),+ poll_flags_(poll_flags)+ {+ }++ static void do_prepare(io_uring_operation* base, ::io_uring_sqe* sqe)+ {+ ASIO_ASSUME(base != 0);+ io_uring_null_buffers_op* o(static_cast<io_uring_null_buffers_op*>(base));++ ::io_uring_prep_poll_add(sqe, o->descriptor_, o->poll_flags_);+ }++ static bool do_perform(io_uring_operation*, bool after_completion)+ {+ return after_completion;+ }++ static void do_complete(void* owner, operation* base,+ const asio::error_code& /*ec*/,+ std::size_t /*bytes_transferred*/)+ {+ // Take ownership of the handler object.+ ASIO_ASSUME(base != 0);+ io_uring_null_buffers_op* o(static_cast<io_uring_null_buffers_op*>(base));+ ptr p = { asio::detail::addressof(o->handler_), o, o };++ ASIO_HANDLER_COMPLETION((*o));++ // Take ownership of the operation's outstanding work.+ handler_work<Handler, IoExecutor> w(+ ASIO_MOVE_CAST2(handler_work<Handler, IoExecutor>)(+ o->work_));++ ASIO_ERROR_LOCATION(o->ec_);++ // Make a copy of the handler so that the memory can be deallocated before+ // the upcall is made. Even if we're not about to make an upcall, a+ // sub-object of the handler may be the true owner of the memory associated+ // with the handler. Consequently, a local copy of the handler is required+ // to ensure that any owning sub-object remains valid until after we have+ // deallocated the memory here.+ detail::binder2<Handler, asio::error_code, std::size_t>+ handler(o->handler_, o->ec_, o->bytes_transferred_);+ p.h = asio::detail::addressof(handler.handler_);+ p.reset();++ // Make the upcall if required.+ if (owner)+ {+ fenced_block b(fenced_block::half);+ ASIO_HANDLER_INVOCATION_BEGIN((handler.arg1_, handler.arg2_));+ w.complete(handler, handler.handler_);+ ASIO_HANDLER_INVOCATION_END;+ }+ }++private:+ Handler handler_;+ handler_work<Handler, IoExecutor> work_;+ int descriptor_;+ int poll_flags_;+};++} // namespace detail+} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // ASIO_DETAIL_IO_URING_NULL_BUFFERS_OP_HPP
+ link/modules/asio-standalone/asio/include/asio/detail/io_uring_operation.hpp view
@@ -0,0 +1,84 @@+//+// detail/io_uring_operation.hpp+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com)+//+// Distributed under the Boost Software License, Version 1.0. (See accompanying+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)+//++#ifndef ASIO_DETAIL_IO_URING_OPERATION_HPP+#define ASIO_DETAIL_IO_URING_OPERATION_HPP++#if defined(_MSC_VER) && (_MSC_VER >= 1200)+# pragma once+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)++#include "asio/detail/config.hpp"++#if defined(ASIO_HAS_IO_URING)++#include <liburing.h>+#include "asio/detail/cstdint.hpp"+#include "asio/detail/operation.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {+namespace detail {++class io_uring_operation+ : public operation+{+public:+ // The error code to be passed to the completion handler.+ asio::error_code ec_;++ // The number of bytes transferred, to be passed to the completion handler.+ std::size_t bytes_transferred_;++ // The operation key used for targeted cancellation.+ void* cancellation_key_;++ // Prepare the operation.+ void prepare(::io_uring_sqe* sqe)+ {+ return prepare_func_(this, sqe);+ }++ // Perform actions associated with the operation. Returns true when complete.+ bool perform(bool after_completion)+ {+ return perform_func_(this, after_completion);+ }++protected:+ typedef void (*prepare_func_type)(io_uring_operation*, ::io_uring_sqe*);+ typedef bool (*perform_func_type)(io_uring_operation*, bool);++ io_uring_operation(const asio::error_code& success_ec,+ prepare_func_type prepare_func, perform_func_type perform_func,+ func_type complete_func)+ : operation(complete_func),+ ec_(success_ec),+ bytes_transferred_(0),+ cancellation_key_(0),+ prepare_func_(prepare_func),+ perform_func_(perform_func)+ {+ }++private:+ prepare_func_type prepare_func_;+ perform_func_type perform_func_;+};++} // namespace detail+} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // defined(ASIO_HAS_IO_URING)++#endif // ASIO_DETAIL_IO_URING_OPERATION_HPP
+ link/modules/asio-standalone/asio/include/asio/detail/io_uring_service.hpp view
@@ -0,0 +1,319 @@+//+// detail/io_uring_service.hpp+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com)+//+// Distributed under the Boost Software License, Version 1.0. (See accompanying+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)+//++#ifndef ASIO_DETAIL_IO_URING_SERVICE_HPP+#define ASIO_DETAIL_IO_URING_SERVICE_HPP++#if defined(_MSC_VER) && (_MSC_VER >= 1200)+# pragma once+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)++#include "asio/detail/config.hpp"++#if defined(ASIO_HAS_IO_URING)++#include <liburing.h>+#include "asio/detail/atomic_count.hpp"+#include "asio/detail/buffer_sequence_adapter.hpp"+#include "asio/detail/conditionally_enabled_mutex.hpp"+#include "asio/detail/io_uring_operation.hpp"+#include "asio/detail/limits.hpp"+#include "asio/detail/object_pool.hpp"+#include "asio/detail/op_queue.hpp"+#include "asio/detail/reactor.hpp"+#include "asio/detail/scheduler_task.hpp"+#include "asio/detail/timer_queue_base.hpp"+#include "asio/detail/timer_queue_set.hpp"+#include "asio/detail/wait_op.hpp"+#include "asio/execution_context.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {+namespace detail {++class io_uring_service+ : public execution_context_service_base<io_uring_service>,+ public scheduler_task+{+private:+ // The mutex type used by this reactor.+ typedef conditionally_enabled_mutex mutex;++public:+ enum op_types { read_op = 0, write_op = 1, except_op = 2, max_ops = 3 };++ class io_object;++ // An I/O queue stores operations that must run serially.+ class io_queue : operation+ {+ friend class io_uring_service;++ io_object* io_object_;+ op_queue<io_uring_operation> op_queue_;+ bool cancel_requested_;++ ASIO_DECL io_queue();+ void set_result(int r) { task_result_ = static_cast<unsigned>(r); }+ ASIO_DECL operation* perform_io(int result);+ ASIO_DECL static void do_complete(void* owner, operation* base,+ const asio::error_code& ec, std::size_t bytes_transferred);+ };++ // Per I/O object state.+ class io_object+ {+ friend class io_uring_service;+ friend class object_pool_access;++ io_object* next_;+ io_object* prev_;++ mutex mutex_;+ io_uring_service* service_;+ io_queue queues_[max_ops];+ bool shutdown_;++ ASIO_DECL io_object(bool locking);+ };++ // Per I/O object data.+ typedef io_object* per_io_object_data;++ // Constructor.+ ASIO_DECL io_uring_service(asio::execution_context& ctx);++ // Destructor.+ ASIO_DECL ~io_uring_service();++ // Destroy all user-defined handler objects owned by the service.+ ASIO_DECL void shutdown();++ // Recreate internal state following a fork.+ ASIO_DECL void notify_fork(+ asio::execution_context::fork_event fork_ev);++ // Initialise the task.+ ASIO_DECL void init_task();++ // Register an I/O object with io_uring.+ ASIO_DECL void register_io_object(io_object*& io_obj);++ // Register an internal I/O object with io_uring.+ ASIO_DECL void register_internal_io_object(+ io_object*& io_obj, int op_type, io_uring_operation* op);++ // Register buffers with io_uring.+ ASIO_DECL void register_buffers(const ::iovec* v, unsigned n);++ // Unregister buffers from io_uring.+ ASIO_DECL void unregister_buffers();++ // Post an operation for immediate completion.+ void post_immediate_completion(operation* op, bool is_continuation);++ // Start a new operation. The operation will be prepared and submitted to the+ // io_uring when it is at the head of its I/O operation queue.+ ASIO_DECL void start_op(int op_type, per_io_object_data& io_obj,+ io_uring_operation* op, bool is_continuation);++ // Cancel all operations associated with the given I/O object. The handlers+ // associated with the I/O object will be invoked with the operation_aborted+ // error.+ ASIO_DECL void cancel_ops(per_io_object_data& io_obj);++ // Cancel all operations associated with the given I/O object and key. The+ // handlers associated with the object and key will be invoked with the+ // operation_aborted error.+ ASIO_DECL void cancel_ops_by_key(per_io_object_data& io_obj,+ int op_type, void* cancellation_key);++ // Cancel any operations that are running against the I/O object and remove+ // its registration from the service. The service resources associated with+ // the I/O object must be released by calling cleanup_io_object.+ ASIO_DECL void deregister_io_object(per_io_object_data& io_obj);++ // Perform any post-deregistration cleanup tasks associated with the I/O+ // object.+ ASIO_DECL void cleanup_io_object(per_io_object_data& io_obj);++ // Add a new timer queue to the reactor.+ template <typename Time_Traits>+ void add_timer_queue(timer_queue<Time_Traits>& timer_queue);++ // Remove a timer queue from the reactor.+ template <typename Time_Traits>+ void remove_timer_queue(timer_queue<Time_Traits>& timer_queue);++ // Schedule a new operation in the given timer queue to expire at the+ // specified absolute time.+ template <typename Time_Traits>+ void schedule_timer(timer_queue<Time_Traits>& queue,+ const typename Time_Traits::time_type& time,+ typename timer_queue<Time_Traits>::per_timer_data& timer, wait_op* op);++ // Cancel the timer operations associated with the given token. Returns the+ // number of operations that have been posted or dispatched.+ template <typename Time_Traits>+ std::size_t cancel_timer(timer_queue<Time_Traits>& queue,+ typename timer_queue<Time_Traits>::per_timer_data& timer,+ std::size_t max_cancelled = (std::numeric_limits<std::size_t>::max)());++ // Cancel the timer operations associated with the given key.+ template <typename Time_Traits>+ void cancel_timer_by_key(timer_queue<Time_Traits>& queue,+ typename timer_queue<Time_Traits>::per_timer_data* timer,+ void* cancellation_key);++ // Move the timer operations associated with the given timer.+ template <typename Time_Traits>+ void move_timer(timer_queue<Time_Traits>& queue,+ typename timer_queue<Time_Traits>::per_timer_data& target,+ typename timer_queue<Time_Traits>::per_timer_data& source);++ // Wait on io_uring once until interrupted or events are ready to be+ // dispatched.+ ASIO_DECL void run(long usec, op_queue<operation>& ops);++ // Interrupt the io_uring wait.+ ASIO_DECL void interrupt();++private:+ // The hint to pass to io_uring_queue_init to size its data structures.+ enum { ring_size = 16384 };++ // The number of operations to submit in a batch.+ enum { submit_batch_size = 128 };++ // The number of operations to complete in a batch.+ enum { complete_batch_size = 128 };++ // The type used for processing eventfd readiness notifications.+ class event_fd_read_op;++ // Initialise the ring.+ ASIO_DECL void init_ring();++ // Register the eventfd descriptor for readiness notifications.+ ASIO_DECL void register_with_reactor();++ // Allocate a new I/O object.+ ASIO_DECL io_object* allocate_io_object();++ // Free an existing I/O object.+ ASIO_DECL void free_io_object(io_object* s);++ // Helper function to cancel all operations associated with the given I/O+ // object. This function must be called while the I/O object's mutex is held.+ // Returns true if there are operations for which cancellation is pending.+ ASIO_DECL bool do_cancel_ops(+ per_io_object_data& io_obj, op_queue<operation>& ops);++ // Helper function to add a new timer queue.+ ASIO_DECL void do_add_timer_queue(timer_queue_base& queue);++ // Helper function to remove a timer queue.+ ASIO_DECL void do_remove_timer_queue(timer_queue_base& queue);++ // Called to recalculate and update the timeout.+ ASIO_DECL void update_timeout();++ // Get the current timeout value.+ ASIO_DECL __kernel_timespec get_timeout() const;++ // Get a new submission queue entry, flushing the queue if necessary.+ ASIO_DECL ::io_uring_sqe* get_sqe();++ // Submit pending submission queue entries.+ ASIO_DECL void submit_sqes();++ // Post an operation to submit the pending submission queue entries.+ ASIO_DECL void post_submit_sqes_op(mutex::scoped_lock& lock);++ // Push an operation to submit the pending submission queue entries.+ ASIO_DECL void push_submit_sqes_op(op_queue<operation>& ops);++ // Helper operation to submit pending submission queue entries.+ class submit_sqes_op : operation+ {+ friend class io_uring_service;++ io_uring_service* service_;++ ASIO_DECL submit_sqes_op(io_uring_service* s);+ ASIO_DECL static void do_complete(void* owner, operation* base,+ const asio::error_code& ec, std::size_t bytes_transferred);+ };++ // The scheduler implementation used to post completions.+ scheduler& scheduler_;++ // Mutex to protect access to internal data.+ mutex mutex_;++ // The ring.+ ::io_uring ring_;++ // The count of unfinished work.+ atomic_count outstanding_work_;++ // The operation used to submit the pending submission queue entries.+ submit_sqes_op submit_sqes_op_;++ // The number of pending submission queue entries_.+ int pending_sqes_;++ // Whether there is a pending submission operation.+ bool pending_submit_sqes_op_;++ // Whether the service has been shut down.+ bool shutdown_;++ // The timer queues.+ timer_queue_set timer_queues_;++ // The timespec for the pending timeout operation. Must remain valid while the+ // operation is outstanding.+ __kernel_timespec timeout_;++ // Mutex to protect access to the registered I/O objects.+ mutex registration_mutex_;++ // Keep track of all registered I/O objects.+ object_pool<io_object> registered_io_objects_;++ // Helper class to do post-perform_io cleanup.+ struct perform_io_cleanup_on_block_exit;+ friend struct perform_io_cleanup_on_block_exit;++ // The reactor used to register for eventfd readiness.+ reactor& reactor_;++ // The per-descriptor reactor data used for the eventfd.+ reactor::per_descriptor_data reactor_data_;++ // The eventfd descriptor used to wait for readiness.+ int event_fd_;+};++} // namespace detail+} // namespace asio++#include "asio/detail/pop_options.hpp"++#include "asio/detail/impl/io_uring_service.hpp"+#if defined(ASIO_HEADER_ONLY)+# include "asio/detail/impl/io_uring_service.ipp"+#endif // defined(ASIO_HEADER_ONLY)++#endif // defined(ASIO_HAS_IO_URING)++#endif // ASIO_DETAIL_IO_URING_SERVICE_HPP
+ link/modules/asio-standalone/asio/include/asio/detail/io_uring_socket_accept_op.hpp view
@@ -0,0 +1,285 @@+//+// detail/io_uring_socket_accept_op.hpp+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com)+//+// Distributed under the Boost Software License, Version 1.0. (See accompanying+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)+//++#ifndef ASIO_DETAIL_IO_URING_SOCKET_ACCEPT_OP_HPP+#define ASIO_DETAIL_IO_URING_SOCKET_ACCEPT_OP_HPP++#if defined(_MSC_VER) && (_MSC_VER >= 1200)+# pragma once+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)++#include "asio/detail/config.hpp"++#if defined(ASIO_HAS_IO_URING)++#include "asio/detail/bind_handler.hpp"+#include "asio/detail/fenced_block.hpp"+#include "asio/detail/handler_alloc_helpers.hpp"+#include "asio/detail/handler_invoke_helpers.hpp"+#include "asio/detail/handler_work.hpp"+#include "asio/detail/io_uring_operation.hpp"+#include "asio/detail/memory.hpp"+#include "asio/detail/socket_holder.hpp"+#include "asio/detail/socket_ops.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {+namespace detail {++template <typename Socket, typename Protocol>+class io_uring_socket_accept_op_base : public io_uring_operation+{+public:+ io_uring_socket_accept_op_base(const asio::error_code& success_ec,+ socket_type socket, socket_ops::state_type state, Socket& peer,+ const Protocol& protocol, typename Protocol::endpoint* peer_endpoint,+ func_type complete_func)+ : io_uring_operation(success_ec,+ &io_uring_socket_accept_op_base::do_prepare,+ &io_uring_socket_accept_op_base::do_perform, complete_func),+ socket_(socket),+ state_(state),+ peer_(peer),+ protocol_(protocol),+ peer_endpoint_(peer_endpoint),+ addrlen_(peer_endpoint ? peer_endpoint->capacity() : 0)+ {+ }++ static void do_prepare(io_uring_operation* base, ::io_uring_sqe* sqe)+ {+ ASIO_ASSUME(base != 0);+ io_uring_socket_accept_op_base* o(+ static_cast<io_uring_socket_accept_op_base*>(base));++ if ((o->state_ & socket_ops::internal_non_blocking) != 0)+ {+ ::io_uring_prep_poll_add(sqe, o->socket_, POLLIN);+ }+ else+ {+ ::io_uring_prep_accept(sqe, o->socket_,+ o->peer_endpoint_ ? o->peer_endpoint_->data() : 0,+ o->peer_endpoint_ ? &o->addrlen_ : 0, 0);+ }+ }++ static bool do_perform(io_uring_operation* base, bool after_completion)+ {+ ASIO_ASSUME(base != 0);+ io_uring_socket_accept_op_base* o(+ static_cast<io_uring_socket_accept_op_base*>(base));++ if ((o->state_ & socket_ops::internal_non_blocking) != 0)+ {+ socket_type new_socket = invalid_socket;+ std::size_t addrlen = static_cast<std::size_t>(o->addrlen_);+ bool result = socket_ops::non_blocking_accept(o->socket_,+ o->state_, o->peer_endpoint_ ? o->peer_endpoint_->data() : 0,+ o->peer_endpoint_ ? &addrlen : 0, o->ec_, new_socket);+ o->new_socket_.reset(new_socket);+ o->addrlen_ = static_cast<socklen_t>(addrlen);+ return result;+ }++ if (o->ec_ && o->ec_ == asio::error::would_block)+ {+ o->state_ |= socket_ops::internal_non_blocking;+ return false;+ }++ if (after_completion && !o->ec_)+ o->new_socket_.reset(static_cast<int>(o->bytes_transferred_));++ return after_completion;+ }++ void do_assign()+ {+ if (new_socket_.get() != invalid_socket)+ {+ if (peer_endpoint_)+ peer_endpoint_->resize(addrlen_);+ peer_.assign(protocol_, new_socket_.get(), ec_);+ if (!ec_)+ new_socket_.release();+ }+ }++private:+ socket_type socket_;+ socket_ops::state_type state_;+ socket_holder new_socket_;+ Socket& peer_;+ Protocol protocol_;+ typename Protocol::endpoint* peer_endpoint_;+ socklen_t addrlen_;+};++template <typename Socket, typename Protocol,+ typename Handler, typename IoExecutor>+class io_uring_socket_accept_op :+ public io_uring_socket_accept_op_base<Socket, Protocol>+{+public:+ ASIO_DEFINE_HANDLER_PTR(io_uring_socket_accept_op);++ io_uring_socket_accept_op(const asio::error_code& success_ec,+ socket_type socket, socket_ops::state_type state, Socket& peer,+ const Protocol& protocol, typename Protocol::endpoint* peer_endpoint,+ Handler& handler, const IoExecutor& io_ex)+ : io_uring_socket_accept_op_base<Socket, Protocol>(+ success_ec, socket, state, peer, protocol, peer_endpoint,+ &io_uring_socket_accept_op::do_complete),+ handler_(ASIO_MOVE_CAST(Handler)(handler)),+ work_(handler_, io_ex)+ {+ }++ static void do_complete(void* owner, operation* base,+ const asio::error_code& /*ec*/,+ std::size_t /*bytes_transferred*/)+ {+ // Take ownership of the handler object.+ ASIO_ASSUME(base != 0);+ io_uring_socket_accept_op* o(static_cast<io_uring_socket_accept_op*>(base));+ ptr p = { asio::detail::addressof(o->handler_), o, o };++ // On success, assign new connection to peer socket object.+ if (owner)+ o->do_assign();++ ASIO_HANDLER_COMPLETION((*o));++ // Take ownership of the operation's outstanding work.+ handler_work<Handler, IoExecutor> w(+ ASIO_MOVE_CAST2(handler_work<Handler, IoExecutor>)(+ o->work_));++ ASIO_ERROR_LOCATION(o->ec_);++ // Make a copy of the handler so that the memory can be deallocated before+ // the upcall is made. Even if we're not about to make an upcall, a+ // sub-object of the handler may be the true owner of the memory associated+ // with the handler. Consequently, a local copy of the handler is required+ // to ensure that any owning sub-object remains valid until after we have+ // deallocated the memory here.+ detail::binder1<Handler, asio::error_code>+ handler(o->handler_, o->ec_);+ p.h = asio::detail::addressof(handler.handler_);+ p.reset();++ // Make the upcall if required.+ if (owner)+ {+ fenced_block b(fenced_block::half);+ ASIO_HANDLER_INVOCATION_BEGIN((handler.arg1_));+ w.complete(handler, handler.handler_);+ ASIO_HANDLER_INVOCATION_END;+ }+ }++private:+ Handler handler_;+ handler_work<Handler, IoExecutor> work_;+};++#if defined(ASIO_HAS_MOVE)++template <typename Protocol, typename PeerIoExecutor,+ typename Handler, typename IoExecutor>+class io_uring_socket_move_accept_op :+ private Protocol::socket::template rebind_executor<PeerIoExecutor>::other,+ public io_uring_socket_accept_op_base<+ typename Protocol::socket::template rebind_executor<PeerIoExecutor>::other,+ Protocol>+{+public:+ ASIO_DEFINE_HANDLER_PTR(io_uring_socket_move_accept_op);++ io_uring_socket_move_accept_op(const asio::error_code& success_ec,+ const PeerIoExecutor& peer_io_ex, socket_type socket,+ socket_ops::state_type state, const Protocol& protocol,+ typename Protocol::endpoint* peer_endpoint, Handler& handler,+ const IoExecutor& io_ex)+ : peer_socket_type(peer_io_ex),+ io_uring_socket_accept_op_base<peer_socket_type, Protocol>(+ success_ec, socket, state, *this, protocol, peer_endpoint,+ &io_uring_socket_move_accept_op::do_complete),+ handler_(ASIO_MOVE_CAST(Handler)(handler)),+ work_(handler_, io_ex)+ {+ }++ static void do_complete(void* owner, operation* base,+ const asio::error_code& /*ec*/,+ std::size_t /*bytes_transferred*/)+ {+ // Take ownership of the handler object.+ ASIO_ASSUME(base != 0);+ io_uring_socket_move_accept_op* o(+ static_cast<io_uring_socket_move_accept_op*>(base));+ ptr p = { asio::detail::addressof(o->handler_), o, o };++ // On success, assign new connection to peer socket object.+ if (owner)+ o->do_assign();++ ASIO_HANDLER_COMPLETION((*o));++ // Take ownership of the operation's outstanding work.+ handler_work<Handler, IoExecutor> w(+ ASIO_MOVE_CAST2(handler_work<Handler, IoExecutor>)(+ o->work_));++ ASIO_ERROR_LOCATION(o->ec_);++ // Make a copy of the handler so that the memory can be deallocated before+ // the upcall is made. Even if we're not about to make an upcall, a+ // sub-object of the handler may be the true owner of the memory associated+ // with the handler. Consequently, a local copy of the handler is required+ // to ensure that any owning sub-object remains valid until after we have+ // deallocated the memory here.+ detail::move_binder2<Handler,+ asio::error_code, peer_socket_type>+ handler(0, ASIO_MOVE_CAST(Handler)(o->handler_), o->ec_,+ ASIO_MOVE_CAST(peer_socket_type)(*o));+ p.h = asio::detail::addressof(handler.handler_);+ p.reset();++ // Make the upcall if required.+ if (owner)+ {+ fenced_block b(fenced_block::half);+ ASIO_HANDLER_INVOCATION_BEGIN((handler.arg1_, "..."));+ w.complete(handler, handler.handler_);+ ASIO_HANDLER_INVOCATION_END;+ }+ }++private:+ typedef typename Protocol::socket::template+ rebind_executor<PeerIoExecutor>::other peer_socket_type;++ Handler handler_;+ handler_work<Handler, IoExecutor> work_;+};++#endif // defined(ASIO_HAS_MOVE)++} // namespace detail+} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // defined(ASIO_HAS_IO_URING)++#endif // ASIO_DETAIL_IO_URING_SOCKET_ACCEPT_OP_HPP
+ link/modules/asio-standalone/asio/include/asio/detail/io_uring_socket_connect_op.hpp view
@@ -0,0 +1,141 @@+//+// detail/io_uring_socket_connect_op.hpp+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com)+//+// Distributed under the Boost Software License, Version 1.0. (See accompanying+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)+//++#ifndef ASIO_DETAIL_IO_URING_SOCKET_CONNECT_OP_HPP+#define ASIO_DETAIL_IO_URING_SOCKET_CONNECT_OP_HPP++#if defined(_MSC_VER) && (_MSC_VER >= 1200)+# pragma once+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)++#include "asio/detail/config.hpp"++#if defined(ASIO_HAS_IO_URING)++#include "asio/detail/bind_handler.hpp"+#include "asio/detail/fenced_block.hpp"+#include "asio/detail/handler_alloc_helpers.hpp"+#include "asio/detail/handler_invoke_helpers.hpp"+#include "asio/detail/handler_work.hpp"+#include "asio/detail/io_uring_operation.hpp"+#include "asio/detail/memory.hpp"+#include "asio/detail/socket_ops.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {+namespace detail {++template <typename Protocol>+class io_uring_socket_connect_op_base : public io_uring_operation+{+public:+ io_uring_socket_connect_op_base(const asio::error_code& success_ec,+ socket_type socket, const typename Protocol::endpoint& endpoint,+ func_type complete_func)+ : io_uring_operation(success_ec,+ &io_uring_socket_connect_op_base::do_prepare,+ &io_uring_socket_connect_op_base::do_perform, complete_func),+ socket_(socket),+ endpoint_(endpoint)+ {+ }++ static void do_prepare(io_uring_operation* base, ::io_uring_sqe* sqe)+ {+ ASIO_ASSUME(base != 0);+ io_uring_socket_connect_op_base* o(+ static_cast<io_uring_socket_connect_op_base*>(base));++ ::io_uring_prep_connect(sqe, o->socket_,+ static_cast<sockaddr*>(o->endpoint_.data()),+ static_cast<socklen_t>(o->endpoint_.size()));+ }++ static bool do_perform(io_uring_operation*, bool after_completion)+ {+ return after_completion;+ }++private:+ socket_type socket_;+ typename Protocol::endpoint endpoint_;+};++template <typename Protocol, typename Handler, typename IoExecutor>+class io_uring_socket_connect_op :+ public io_uring_socket_connect_op_base<Protocol>+{+public:+ ASIO_DEFINE_HANDLER_PTR(io_uring_socket_connect_op);++ io_uring_socket_connect_op(const asio::error_code& success_ec,+ socket_type socket, const typename Protocol::endpoint& endpoint,+ Handler& handler, const IoExecutor& io_ex)+ : io_uring_socket_connect_op_base<Protocol>(success_ec, socket,+ endpoint, &io_uring_socket_connect_op::do_complete),+ handler_(ASIO_MOVE_CAST(Handler)(handler)),+ work_(handler_, io_ex)+ {+ }++ static void do_complete(void* owner, operation* base,+ const asio::error_code& /*ec*/,+ std::size_t /*bytes_transferred*/)+ {+ // Take ownership of the handler object.+ ASIO_ASSUME(base != 0);+ io_uring_socket_connect_op* o+ (static_cast<io_uring_socket_connect_op*>(base));+ ptr p = { asio::detail::addressof(o->handler_), o, o };++ ASIO_HANDLER_COMPLETION((*o));++ // Take ownership of the operation's outstanding work.+ handler_work<Handler, IoExecutor> w(+ ASIO_MOVE_CAST2(handler_work<Handler, IoExecutor>)(+ o->work_));++ ASIO_ERROR_LOCATION(o->ec_);++ // Make a copy of the handler so that the memory can be deallocated before+ // the upcall is made. Even if we're not about to make an upcall, a+ // sub-object of the handler may be the true owner of the memory associated+ // with the handler. Consequently, a local copy of the handler is required+ // to ensure that any owning sub-object remains valid until after we have+ // deallocated the memory here.+ detail::binder1<Handler, asio::error_code>+ handler(o->handler_, o->ec_);+ p.h = asio::detail::addressof(handler.handler_);+ p.reset();++ // Make the upcall if required.+ if (owner)+ {+ fenced_block b(fenced_block::half);+ ASIO_HANDLER_INVOCATION_BEGIN((handler.arg1_));+ w.complete(handler, handler.handler_);+ ASIO_HANDLER_INVOCATION_END;+ }+ }++private:+ Handler handler_;+ handler_work<Handler, IoExecutor> work_;+};++} // namespace detail+} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // defined(ASIO_HAS_IO_URING)++#endif // ASIO_DETAIL_IO_URING_SOCKET_CONNECT_OP_HPP
+ link/modules/asio-standalone/asio/include/asio/detail/io_uring_socket_recv_op.hpp view
@@ -0,0 +1,205 @@+//+// detail/io_uring_socket_recv_op.hpp+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com)+//+// Distributed under the Boost Software License, Version 1.0. (See accompanying+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)+//++#ifndef ASIO_DETAIL_IO_URING_SOCKET_RECV_OP_HPP+#define ASIO_DETAIL_IO_URING_SOCKET_RECV_OP_HPP++#if defined(_MSC_VER) && (_MSC_VER >= 1200)+# pragma once+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)++#include "asio/detail/config.hpp"++#if defined(ASIO_HAS_IO_URING)++#include "asio/detail/bind_handler.hpp"+#include "asio/detail/buffer_sequence_adapter.hpp"+#include "asio/detail/socket_ops.hpp"+#include "asio/detail/fenced_block.hpp"+#include "asio/detail/handler_work.hpp"+#include "asio/detail/io_uring_operation.hpp"+#include "asio/detail/memory.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {+namespace detail {++template <typename MutableBufferSequence>+class io_uring_socket_recv_op_base : public io_uring_operation+{+public:+ io_uring_socket_recv_op_base(const asio::error_code& success_ec,+ socket_type socket, socket_ops::state_type state,+ const MutableBufferSequence& buffers,+ socket_base::message_flags flags, func_type complete_func)+ : io_uring_operation(success_ec,+ &io_uring_socket_recv_op_base::do_prepare,+ &io_uring_socket_recv_op_base::do_perform, complete_func),+ socket_(socket),+ state_(state),+ buffers_(buffers),+ flags_(flags),+ bufs_(buffers),+ msghdr_()+ {+ msghdr_.msg_iov = bufs_.buffers();+ msghdr_.msg_iovlen = static_cast<int>(bufs_.count());+ }++ static void do_prepare(io_uring_operation* base, ::io_uring_sqe* sqe)+ {+ ASIO_ASSUME(base != 0);+ io_uring_socket_recv_op_base* o(+ static_cast<io_uring_socket_recv_op_base*>(base));++ if ((o->state_ & socket_ops::internal_non_blocking) != 0)+ {+ bool except_op = (o->flags_ & socket_base::message_out_of_band) != 0;+ ::io_uring_prep_poll_add(sqe, o->socket_, except_op ? POLLPRI : POLLIN);+ }+ else if (o->bufs_.is_single_buffer+ && o->bufs_.is_registered_buffer && o->flags_ == 0)+ {+ ::io_uring_prep_read_fixed(sqe, o->socket_,+ o->bufs_.buffers()->iov_base, o->bufs_.buffers()->iov_len,+ 0, o->bufs_.registered_id().native_handle());+ }+ else+ {+ ::io_uring_prep_recvmsg(sqe, o->socket_, &o->msghdr_, o->flags_);+ }+ }++ static bool do_perform(io_uring_operation* base, bool after_completion)+ {+ ASIO_ASSUME(base != 0);+ io_uring_socket_recv_op_base* o(+ static_cast<io_uring_socket_recv_op_base*>(base));++ if ((o->state_ & socket_ops::internal_non_blocking) != 0)+ {+ bool except_op = (o->flags_ & socket_base::message_out_of_band) != 0;+ if (after_completion || !except_op)+ {+ if (o->bufs_.is_single_buffer)+ {+ return socket_ops::non_blocking_recv1(o->socket_,+ o->bufs_.first(o->buffers_).data(),+ o->bufs_.first(o->buffers_).size(), o->flags_,+ (o->state_ & socket_ops::stream_oriented) != 0,+ o->ec_, o->bytes_transferred_);+ }+ else+ {+ return socket_ops::non_blocking_recv(o->socket_,+ o->bufs_.buffers(), o->bufs_.count(), o->flags_,+ (o->state_ & socket_ops::stream_oriented) != 0,+ o->ec_, o->bytes_transferred_);+ }+ }+ }+ else if (after_completion)+ {+ if (!o->ec_ && o->bytes_transferred_ == 0)+ if ((o->state_ & socket_ops::stream_oriented) != 0)+ o->ec_ = asio::error::eof;+ }++ if (o->ec_ && o->ec_ == asio::error::would_block)+ {+ o->state_ |= socket_ops::internal_non_blocking;+ return false;+ }++ return after_completion;+ }++private:+ socket_type socket_;+ socket_ops::state_type state_;+ MutableBufferSequence buffers_;+ socket_base::message_flags flags_;+ buffer_sequence_adapter<asio::mutable_buffer,+ MutableBufferSequence> bufs_;+ msghdr msghdr_;+};++template <typename MutableBufferSequence, typename Handler, typename IoExecutor>+class io_uring_socket_recv_op+ : public io_uring_socket_recv_op_base<MutableBufferSequence>+{+public:+ ASIO_DEFINE_HANDLER_PTR(io_uring_socket_recv_op);++ io_uring_socket_recv_op(const asio::error_code& success_ec,+ int socket, socket_ops::state_type state,+ const MutableBufferSequence& buffers, socket_base::message_flags flags,+ Handler& handler, const IoExecutor& io_ex)+ : io_uring_socket_recv_op_base<MutableBufferSequence>(success_ec,+ socket, state, buffers, flags, &io_uring_socket_recv_op::do_complete),+ handler_(ASIO_MOVE_CAST(Handler)(handler)),+ work_(handler_, io_ex)+ {+ }++ static void do_complete(void* owner, operation* base,+ const asio::error_code& /*ec*/,+ std::size_t /*bytes_transferred*/)+ {+ // Take ownership of the handler object.+ ASIO_ASSUME(base != 0);+ io_uring_socket_recv_op* o+ (static_cast<io_uring_socket_recv_op*>(base));+ ptr p = { asio::detail::addressof(o->handler_), o, o };++ ASIO_HANDLER_COMPLETION((*o));++ // Take ownership of the operation's outstanding work.+ handler_work<Handler, IoExecutor> w(+ ASIO_MOVE_CAST2(handler_work<Handler, IoExecutor>)(+ o->work_));++ ASIO_ERROR_LOCATION(o->ec_);++ // Make a copy of the handler so that the memory can be deallocated before+ // the upcall is made. Even if we're not about to make an upcall, a+ // sub-object of the handler may be the true owner of the memory associated+ // with the handler. Consequently, a local copy of the handler is required+ // to ensure that any owning sub-object remains valid until after we have+ // deallocated the memory here.+ detail::binder2<Handler, asio::error_code, std::size_t>+ handler(o->handler_, o->ec_, o->bytes_transferred_);+ p.h = asio::detail::addressof(handler.handler_);+ p.reset();++ // Make the upcall if required.+ if (owner)+ {+ fenced_block b(fenced_block::half);+ ASIO_HANDLER_INVOCATION_BEGIN((handler.arg1_, handler.arg2_));+ w.complete(handler, handler.handler_);+ ASIO_HANDLER_INVOCATION_END;+ }+ }++private:+ Handler handler_;+ handler_work<Handler, IoExecutor> work_;+};++} // namespace detail+} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // defined(ASIO_HAS_IO_URING)++#endif // ASIO_DETAIL_IO_URING_SOCKET_RECV_OP_HPP
+ link/modules/asio-standalone/asio/include/asio/detail/io_uring_socket_recvfrom_op.hpp view
@@ -0,0 +1,206 @@+//+// detail/io_uring_socket_recvfrom_op.hpp+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com)+//+// Distributed under the Boost Software License, Version 1.0. (See accompanying+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)+//++#ifndef ASIO_DETAIL_IO_URING_SOCKET_RECVFROM_OP_HPP+#define ASIO_DETAIL_IO_URING_SOCKET_RECVFROM_OP_HPP++#if defined(_MSC_VER) && (_MSC_VER >= 1200)+# pragma once+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)++#include "asio/detail/config.hpp"++#if defined(ASIO_HAS_IO_URING)++#include "asio/detail/bind_handler.hpp"+#include "asio/detail/buffer_sequence_adapter.hpp"+#include "asio/detail/socket_ops.hpp"+#include "asio/detail/fenced_block.hpp"+#include "asio/detail/handler_work.hpp"+#include "asio/detail/io_uring_operation.hpp"+#include "asio/detail/memory.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {+namespace detail {++template <typename MutableBufferSequence, typename Endpoint>+class io_uring_socket_recvfrom_op_base : public io_uring_operation+{+public:+ io_uring_socket_recvfrom_op_base(const asio::error_code& success_ec,+ socket_type socket, socket_ops::state_type state,+ const MutableBufferSequence& buffers, Endpoint& endpoint,+ socket_base::message_flags flags, func_type complete_func)+ : io_uring_operation(success_ec,+ &io_uring_socket_recvfrom_op_base::do_prepare,+ &io_uring_socket_recvfrom_op_base::do_perform, complete_func),+ socket_(socket),+ state_(state),+ buffers_(buffers),+ sender_endpoint_(endpoint),+ flags_(flags),+ bufs_(buffers),+ msghdr_()+ {+ msghdr_.msg_iov = bufs_.buffers();+ msghdr_.msg_iovlen = static_cast<int>(bufs_.count());+ msghdr_.msg_name = static_cast<sockaddr*>(+ static_cast<void*>(sender_endpoint_.data()));+ msghdr_.msg_namelen = sender_endpoint_.capacity();+ }++ static void do_prepare(io_uring_operation* base, ::io_uring_sqe* sqe)+ {+ ASIO_ASSUME(base != 0);+ io_uring_socket_recvfrom_op_base* o(+ static_cast<io_uring_socket_recvfrom_op_base*>(base));++ if ((o->state_ & socket_ops::internal_non_blocking) != 0)+ {+ bool except_op = (o->flags_ & socket_base::message_out_of_band) != 0;+ ::io_uring_prep_poll_add(sqe, o->socket_, except_op ? POLLPRI : POLLIN);+ }+ else+ {+ ::io_uring_prep_recvmsg(sqe, o->socket_, &o->msghdr_, o->flags_);+ }+ }++ static bool do_perform(io_uring_operation* base, bool after_completion)+ {+ ASIO_ASSUME(base != 0);+ io_uring_socket_recvfrom_op_base* o(+ static_cast<io_uring_socket_recvfrom_op_base*>(base));++ if ((o->state_ & socket_ops::internal_non_blocking) != 0)+ {+ bool except_op = (o->flags_ & socket_base::message_out_of_band) != 0;+ if (after_completion || !except_op)+ {+ std::size_t addr_len = o->sender_endpoint_.capacity();+ bool result;+ if (o->bufs_.is_single_buffer)+ {+ result = socket_ops::non_blocking_recvfrom1(o->socket_,+ o->bufs_.first(o->buffers_).data(),+ o->bufs_.first(o->buffers_).size(), o->flags_,+ o->sender_endpoint_.data(), &addr_len,+ o->ec_, o->bytes_transferred_);+ }+ else+ {+ result = socket_ops::non_blocking_recvfrom(o->socket_,+ o->bufs_.buffers(), o->bufs_.count(), o->flags_,+ o->sender_endpoint_.data(), &addr_len,+ o->ec_, o->bytes_transferred_);+ }+ if (result && !o->ec_)+ o->sender_endpoint_.resize(addr_len);+ }+ }+ else if (after_completion && !o->ec_)+ o->sender_endpoint_.resize(o->msghdr_.msg_namelen);++ if (o->ec_ && o->ec_ == asio::error::would_block)+ {+ o->state_ |= socket_ops::internal_non_blocking;+ return false;+ }++ return after_completion;+ }++private:+ socket_type socket_;+ socket_ops::state_type state_;+ MutableBufferSequence buffers_;+ Endpoint& sender_endpoint_;+ socket_base::message_flags flags_;+ buffer_sequence_adapter<asio::mutable_buffer,+ MutableBufferSequence> bufs_;+ msghdr msghdr_;+};++template <typename MutableBufferSequence, typename Endpoint,+ typename Handler, typename IoExecutor>+class io_uring_socket_recvfrom_op+ : public io_uring_socket_recvfrom_op_base<MutableBufferSequence, Endpoint>+{+public:+ ASIO_DEFINE_HANDLER_PTR(io_uring_socket_recvfrom_op);++ io_uring_socket_recvfrom_op(const asio::error_code& success_ec,+ int socket, socket_ops::state_type state,+ const MutableBufferSequence& buffers, Endpoint& endpoint,+ socket_base::message_flags flags,+ Handler& handler, const IoExecutor& io_ex)+ : io_uring_socket_recvfrom_op_base<MutableBufferSequence, Endpoint>(+ success_ec, socket, state, buffers, endpoint, flags,+ &io_uring_socket_recvfrom_op::do_complete),+ handler_(ASIO_MOVE_CAST(Handler)(handler)),+ work_(handler_, io_ex)+ {+ }++ static void do_complete(void* owner, operation* base,+ const asio::error_code& /*ec*/,+ std::size_t /*bytes_transferred*/)+ {+ // Take ownership of the handler object.+ ASIO_ASSUME(base != 0);+ io_uring_socket_recvfrom_op* o+ (static_cast<io_uring_socket_recvfrom_op*>(base));+ ptr p = { asio::detail::addressof(o->handler_), o, o };++ ASIO_HANDLER_COMPLETION((*o));++ // Take ownership of the operation's outstanding work.+ handler_work<Handler, IoExecutor> w(+ ASIO_MOVE_CAST2(handler_work<Handler, IoExecutor>)(+ o->work_));++ ASIO_ERROR_LOCATION(o->ec_);++ // Make a copy of the handler so that the memory can be deallocated before+ // the upcall is made. Even if we're not about to make an upcall, a+ // sub-object of the handler may be the true owner of the memory associated+ // with the handler. Consequently, a local copy of the handler is required+ // to ensure that any owning sub-object remains valid until after we have+ // deallocated the memory here.+ detail::binder2<Handler, asio::error_code, std::size_t>+ handler(o->handler_, o->ec_, o->bytes_transferred_);+ p.h = asio::detail::addressof(handler.handler_);+ p.reset();++ // Make the upcall if required.+ if (owner)+ {+ fenced_block b(fenced_block::half);+ ASIO_HANDLER_INVOCATION_BEGIN((handler.arg1_, handler.arg2_));+ w.complete(handler, handler.handler_);+ ASIO_HANDLER_INVOCATION_END;+ }+ }++private:+ Handler handler_;+ handler_work<Handler, IoExecutor> work_;+};++} // namespace detail+} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // defined(ASIO_HAS_IO_URING)++#endif // ASIO_DETAIL_IO_URING_SOCKET_RECVFROM_OP_HPP
+ link/modules/asio-standalone/asio/include/asio/detail/io_uring_socket_recvmsg_op.hpp view
@@ -0,0 +1,192 @@+//+// detail/io_uring_socket_recvmsg_op.hpp+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com)+//+// Distributed under the Boost Software License, Version 1.0. (See accompanying+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)+//++#ifndef ASIO_DETAIL_IO_URING_SOCKET_RECVMSG_OP_HPP+#define ASIO_DETAIL_IO_URING_SOCKET_RECVMSG_OP_HPP++#if defined(_MSC_VER) && (_MSC_VER >= 1200)+# pragma once+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)++#include "asio/detail/config.hpp"++#if defined(ASIO_HAS_IO_URING)++#include "asio/detail/bind_handler.hpp"+#include "asio/detail/buffer_sequence_adapter.hpp"+#include "asio/detail/socket_ops.hpp"+#include "asio/detail/fenced_block.hpp"+#include "asio/detail/handler_work.hpp"+#include "asio/detail/io_uring_operation.hpp"+#include "asio/detail/memory.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {+namespace detail {++template <typename MutableBufferSequence>+class io_uring_socket_recvmsg_op_base : public io_uring_operation+{+public:+ io_uring_socket_recvmsg_op_base(const asio::error_code& success_ec,+ socket_type socket, socket_ops::state_type state,+ const MutableBufferSequence& buffers, socket_base::message_flags in_flags,+ socket_base::message_flags& out_flags, func_type complete_func)+ : io_uring_operation(success_ec,+ &io_uring_socket_recvmsg_op_base::do_prepare,+ &io_uring_socket_recvmsg_op_base::do_perform, complete_func),+ socket_(socket),+ state_(state),+ buffers_(buffers),+ in_flags_(in_flags),+ out_flags_(out_flags),+ bufs_(buffers),+ msghdr_()+ {+ msghdr_.msg_iov = bufs_.buffers();+ msghdr_.msg_iovlen = static_cast<int>(bufs_.count());+ }++ static void do_prepare(io_uring_operation* base, ::io_uring_sqe* sqe)+ {+ ASIO_ASSUME(base != 0);+ io_uring_socket_recvmsg_op_base* o(+ static_cast<io_uring_socket_recvmsg_op_base*>(base));++ if ((o->state_ & socket_ops::internal_non_blocking) != 0)+ {+ bool except_op = (o->in_flags_ & socket_base::message_out_of_band) != 0;+ ::io_uring_prep_poll_add(sqe, o->socket_, except_op ? POLLPRI : POLLIN);+ }+ else+ {+ ::io_uring_prep_recvmsg(sqe, o->socket_, &o->msghdr_, o->in_flags_);+ }+ }++ static bool do_perform(io_uring_operation* base, bool after_completion)+ {+ ASIO_ASSUME(base != 0);+ io_uring_socket_recvmsg_op_base* o(+ static_cast<io_uring_socket_recvmsg_op_base*>(base));++ if ((o->state_ & socket_ops::internal_non_blocking) != 0)+ {+ bool except_op = (o->in_flags_ & socket_base::message_out_of_band) != 0;+ if (after_completion || !except_op)+ {+ return socket_ops::non_blocking_recvmsg(o->socket_,+ o->bufs_.buffers(), o->bufs_.count(), o->in_flags_,+ o->out_flags_, o->ec_, o->bytes_transferred_);+ }+ }+ else if (after_completion)+ {+ if (!o->ec_)+ o->out_flags_ = o->msghdr_.msg_flags;+ else+ o->out_flags_ = 0;+ }++ if (o->ec_ && o->ec_ == asio::error::would_block)+ {+ o->state_ |= socket_ops::internal_non_blocking;+ return false;+ }++ return after_completion;+ }++private:+ socket_type socket_;+ socket_ops::state_type state_;+ MutableBufferSequence buffers_;+ socket_base::message_flags in_flags_;+ socket_base::message_flags& out_flags_;+ buffer_sequence_adapter<asio::mutable_buffer,+ MutableBufferSequence> bufs_;+ msghdr msghdr_;+};++template <typename MutableBufferSequence, typename Handler, typename IoExecutor>+class io_uring_socket_recvmsg_op+ : public io_uring_socket_recvmsg_op_base<MutableBufferSequence>+{+public:+ ASIO_DEFINE_HANDLER_PTR(io_uring_socket_recvmsg_op);++ io_uring_socket_recvmsg_op(const asio::error_code& success_ec,+ int socket, socket_ops::state_type state,+ const MutableBufferSequence& buffers,+ socket_base::message_flags in_flags,+ socket_base::message_flags& out_flags,+ Handler& handler, const IoExecutor& io_ex)+ : io_uring_socket_recvmsg_op_base<MutableBufferSequence>(success_ec,+ socket, state, buffers, in_flags, out_flags,+ &io_uring_socket_recvmsg_op::do_complete),+ handler_(ASIO_MOVE_CAST(Handler)(handler)),+ work_(handler_, io_ex)+ {+ }++ static void do_complete(void* owner, operation* base,+ const asio::error_code& /*ec*/,+ std::size_t /*bytes_transferred*/)+ {+ // Take ownership of the handler object.+ ASIO_ASSUME(base != 0);+ io_uring_socket_recvmsg_op* o+ (static_cast<io_uring_socket_recvmsg_op*>(base));+ ptr p = { asio::detail::addressof(o->handler_), o, o };++ ASIO_HANDLER_COMPLETION((*o));++ // Take ownership of the operation's outstanding work.+ handler_work<Handler, IoExecutor> w(+ ASIO_MOVE_CAST2(handler_work<Handler, IoExecutor>)(+ o->work_));++ ASIO_ERROR_LOCATION(o->ec_);++ // Make a copy of the handler so that the memory can be deallocated before+ // the upcall is made. Even if we're not about to make an upcall, a+ // sub-object of the handler may be the true owner of the memory associated+ // with the handler. Consequently, a local copy of the handler is required+ // to ensure that any owning sub-object remains valid until after we have+ // deallocated the memory here.+ detail::binder2<Handler, asio::error_code, std::size_t>+ handler(o->handler_, o->ec_, o->bytes_transferred_);+ p.h = asio::detail::addressof(handler.handler_);+ p.reset();++ // Make the upcall if required.+ if (owner)+ {+ fenced_block b(fenced_block::half);+ ASIO_HANDLER_INVOCATION_BEGIN((handler.arg1_, handler.arg2_));+ w.complete(handler, handler.handler_);+ ASIO_HANDLER_INVOCATION_END;+ }+ }++private:+ Handler handler_;+ handler_work<Handler, IoExecutor> work_;+};++} // namespace detail+} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // defined(ASIO_HAS_IO_URING)++#endif // ASIO_DETAIL_IO_URING_SOCKET_RECVMSG_OP_HPP
+ link/modules/asio-standalone/asio/include/asio/detail/io_uring_socket_send_op.hpp view
@@ -0,0 +1,191 @@+//+// detail/io_uring_socket_send_op.hpp+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com)+//+// Distributed under the Boost Software License, Version 1.0. (See accompanying+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)+//++#ifndef ASIO_DETAIL_IO_URING_SOCKET_SEND_OP_HPP+#define ASIO_DETAIL_IO_URING_SOCKET_SEND_OP_HPP++#if defined(_MSC_VER) && (_MSC_VER >= 1200)+# pragma once+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)++#include "asio/detail/config.hpp"++#if defined(ASIO_HAS_IO_URING)++#include "asio/detail/bind_handler.hpp"+#include "asio/detail/buffer_sequence_adapter.hpp"+#include "asio/detail/socket_ops.hpp"+#include "asio/detail/fenced_block.hpp"+#include "asio/detail/handler_work.hpp"+#include "asio/detail/io_uring_operation.hpp"+#include "asio/detail/memory.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {+namespace detail {++template <typename ConstBufferSequence>+class io_uring_socket_send_op_base : public io_uring_operation+{+public:+ io_uring_socket_send_op_base(const asio::error_code& success_ec,+ socket_type socket, socket_ops::state_type state,+ const ConstBufferSequence& buffers,+ socket_base::message_flags flags, func_type complete_func)+ : io_uring_operation(success_ec,+ &io_uring_socket_send_op_base::do_prepare,+ &io_uring_socket_send_op_base::do_perform, complete_func),+ socket_(socket),+ state_(state),+ buffers_(buffers),+ flags_(flags),+ bufs_(buffers),+ msghdr_()+ {+ msghdr_.msg_iov = bufs_.buffers();+ msghdr_.msg_iovlen = static_cast<int>(bufs_.count());+ }++ static void do_prepare(io_uring_operation* base, ::io_uring_sqe* sqe)+ {+ ASIO_ASSUME(base != 0);+ io_uring_socket_send_op_base* o(+ static_cast<io_uring_socket_send_op_base*>(base));++ if ((o->state_ & socket_ops::internal_non_blocking) != 0)+ {+ ::io_uring_prep_poll_add(sqe, o->socket_, POLLOUT);+ }+ else if (o->bufs_.is_single_buffer+ && o->bufs_.is_registered_buffer && o->flags_ == 0)+ {+ ::io_uring_prep_write_fixed(sqe, o->socket_,+ o->bufs_.buffers()->iov_base, o->bufs_.buffers()->iov_len,+ 0, o->bufs_.registered_id().native_handle());+ }+ else+ {+ ::io_uring_prep_sendmsg(sqe, o->socket_, &o->msghdr_, o->flags_);+ }+ }++ static bool do_perform(io_uring_operation* base, bool after_completion)+ {+ ASIO_ASSUME(base != 0);+ io_uring_socket_send_op_base* o(+ static_cast<io_uring_socket_send_op_base*>(base));++ if ((o->state_ & socket_ops::internal_non_blocking) != 0)+ {+ if (o->bufs_.is_single_buffer)+ {+ return socket_ops::non_blocking_send1(o->socket_,+ o->bufs_.first(o->buffers_).data(),+ o->bufs_.first(o->buffers_).size(), o->flags_,+ o->ec_, o->bytes_transferred_);+ }+ else+ {+ return socket_ops::non_blocking_send(o->socket_,+ o->bufs_.buffers(), o->bufs_.count(), o->flags_,+ o->ec_, o->bytes_transferred_);+ }+ }++ if (o->ec_ && o->ec_ == asio::error::would_block)+ {+ o->state_ |= socket_ops::internal_non_blocking;+ return false;+ }++ return after_completion;+ }++private:+ socket_type socket_;+ socket_ops::state_type state_;+ ConstBufferSequence buffers_;+ socket_base::message_flags flags_;+ buffer_sequence_adapter<asio::const_buffer, ConstBufferSequence> bufs_;+ msghdr msghdr_;+};++template <typename ConstBufferSequence, typename Handler, typename IoExecutor>+class io_uring_socket_send_op+ : public io_uring_socket_send_op_base<ConstBufferSequence>+{+public:+ ASIO_DEFINE_HANDLER_PTR(io_uring_socket_send_op);++ io_uring_socket_send_op(const asio::error_code& success_ec,+ int socket, socket_ops::state_type state,+ const ConstBufferSequence& buffers, socket_base::message_flags flags,+ Handler& handler, const IoExecutor& io_ex)+ : io_uring_socket_send_op_base<ConstBufferSequence>(success_ec,+ socket, state, buffers, flags, &io_uring_socket_send_op::do_complete),+ handler_(ASIO_MOVE_CAST(Handler)(handler)),+ work_(handler_, io_ex)+ {+ }++ static void do_complete(void* owner, operation* base,+ const asio::error_code& /*ec*/,+ std::size_t /*bytes_transferred*/)+ {+ // Take ownership of the handler object.+ ASIO_ASSUME(base != 0);+ io_uring_socket_send_op* o+ (static_cast<io_uring_socket_send_op*>(base));+ ptr p = { asio::detail::addressof(o->handler_), o, o };++ ASIO_HANDLER_COMPLETION((*o));++ // Take ownership of the operation's outstanding work.+ handler_work<Handler, IoExecutor> w(+ ASIO_MOVE_CAST2(handler_work<Handler, IoExecutor>)(+ o->work_));++ ASIO_ERROR_LOCATION(o->ec_);++ // Make a copy of the handler so that the memory can be deallocated before+ // the upcall is made. Even if we're not about to make an upcall, a+ // sub-object of the handler may be the true owner of the memory associated+ // with the handler. Consequently, a local copy of the handler is required+ // to ensure that any owning sub-object remains valid until after we have+ // deallocated the memory here.+ detail::binder2<Handler, asio::error_code, std::size_t>+ handler(o->handler_, o->ec_, o->bytes_transferred_);+ p.h = asio::detail::addressof(handler.handler_);+ p.reset();++ // Make the upcall if required.+ if (owner)+ {+ fenced_block b(fenced_block::half);+ ASIO_HANDLER_INVOCATION_BEGIN((handler.arg1_, handler.arg2_));+ w.complete(handler, handler.handler_);+ ASIO_HANDLER_INVOCATION_END;+ }+ }++private:+ Handler handler_;+ handler_work<Handler, IoExecutor> work_;+};++} // namespace detail+} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // defined(ASIO_HAS_IO_URING)++#endif // ASIO_DETAIL_IO_URING_SOCKET_SEND_OP_HPP
+ link/modules/asio-standalone/asio/include/asio/detail/io_uring_socket_sendto_op.hpp view
@@ -0,0 +1,194 @@+//+// detail/io_uring_socket_sendto_op.hpp+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com)+//+// Distributed under the Boost Software License, Version 1.0. (See accompanying+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)+//++#ifndef ASIO_DETAIL_IO_URING_SOCKET_SENDTO_OP_HPP+#define ASIO_DETAIL_IO_URING_SOCKET_SENDTO_OP_HPP++#if defined(_MSC_VER) && (_MSC_VER >= 1200)+# pragma once+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)++#include "asio/detail/config.hpp"++#if defined(ASIO_HAS_IO_URING)++#include "asio/detail/bind_handler.hpp"+#include "asio/detail/buffer_sequence_adapter.hpp"+#include "asio/detail/socket_ops.hpp"+#include "asio/detail/fenced_block.hpp"+#include "asio/detail/handler_work.hpp"+#include "asio/detail/io_uring_operation.hpp"+#include "asio/detail/memory.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {+namespace detail {++template <typename ConstBufferSequence, typename Endpoint>+class io_uring_socket_sendto_op_base : public io_uring_operation+{+public:+ io_uring_socket_sendto_op_base(const asio::error_code& success_ec,+ socket_type socket, socket_ops::state_type state,+ const ConstBufferSequence& buffers, const Endpoint& endpoint,+ socket_base::message_flags flags, func_type complete_func)+ : io_uring_operation(success_ec,+ &io_uring_socket_sendto_op_base::do_prepare,+ &io_uring_socket_sendto_op_base::do_perform, complete_func),+ socket_(socket),+ state_(state),+ buffers_(buffers),+ destination_(endpoint),+ flags_(flags),+ bufs_(buffers),+ msghdr_()+ {+ msghdr_.msg_iov = bufs_.buffers();+ msghdr_.msg_iovlen = static_cast<int>(bufs_.count());+ msghdr_.msg_name = static_cast<sockaddr*>(+ static_cast<void*>(destination_.data()));+ msghdr_.msg_namelen = destination_.size();+ }++ static void do_prepare(io_uring_operation* base, ::io_uring_sqe* sqe)+ {+ ASIO_ASSUME(base != 0);+ io_uring_socket_sendto_op_base* o(+ static_cast<io_uring_socket_sendto_op_base*>(base));++ if ((o->state_ & socket_ops::internal_non_blocking) != 0)+ {+ ::io_uring_prep_poll_add(sqe, o->socket_, POLLOUT);+ }+ else+ {+ ::io_uring_prep_sendmsg(sqe, o->socket_, &o->msghdr_, o->flags_);+ }+ }++ static bool do_perform(io_uring_operation* base, bool after_completion)+ {+ ASIO_ASSUME(base != 0);+ io_uring_socket_sendto_op_base* o(+ static_cast<io_uring_socket_sendto_op_base*>(base));++ if ((o->state_ & socket_ops::internal_non_blocking) != 0)+ {+ if (o->bufs_.is_single_buffer)+ {+ return socket_ops::non_blocking_sendto1(o->socket_,+ o->bufs_.first(o->buffers_).data(),+ o->bufs_.first(o->buffers_).size(), o->flags_,+ o->destination_.data(), o->destination_.size(),+ o->ec_, o->bytes_transferred_);+ }+ else+ {+ return socket_ops::non_blocking_sendto(o->socket_,+ o->bufs_.buffers(), o->bufs_.count(), o->flags_,+ o->destination_.data(), o->destination_.size(),+ o->ec_, o->bytes_transferred_);+ }+ }++ if (o->ec_ && o->ec_ == asio::error::would_block)+ {+ o->state_ |= socket_ops::internal_non_blocking;+ return false;+ }++ return after_completion;+ }++private:+ socket_type socket_;+ socket_ops::state_type state_;+ ConstBufferSequence buffers_;+ Endpoint destination_;+ socket_base::message_flags flags_;+ buffer_sequence_adapter<asio::const_buffer, ConstBufferSequence> bufs_;+ msghdr msghdr_;+};++template <typename ConstBufferSequence, typename Endpoint,+ typename Handler, typename IoExecutor>+class io_uring_socket_sendto_op+ : public io_uring_socket_sendto_op_base<ConstBufferSequence, Endpoint>+{+public:+ ASIO_DEFINE_HANDLER_PTR(io_uring_socket_sendto_op);++ io_uring_socket_sendto_op(const asio::error_code& success_ec,+ int socket, socket_ops::state_type state,+ const ConstBufferSequence& buffers, const Endpoint& endpoint,+ socket_base::message_flags flags,+ Handler& handler, const IoExecutor& io_ex)+ : io_uring_socket_sendto_op_base<ConstBufferSequence, Endpoint>(+ success_ec, socket, state, buffers, endpoint, flags,+ &io_uring_socket_sendto_op::do_complete),+ handler_(ASIO_MOVE_CAST(Handler)(handler)),+ work_(handler_, io_ex)+ {+ }++ static void do_complete(void* owner, operation* base,+ const asio::error_code& /*ec*/,+ std::size_t /*bytes_transferred*/)+ {+ // Take ownership of the handler object.+ ASIO_ASSUME(base != 0);+ io_uring_socket_sendto_op* o+ (static_cast<io_uring_socket_sendto_op*>(base));+ ptr p = { asio::detail::addressof(o->handler_), o, o };++ ASIO_HANDLER_COMPLETION((*o));++ // Take ownership of the operation's outstanding work.+ handler_work<Handler, IoExecutor> w(+ ASIO_MOVE_CAST2(handler_work<Handler, IoExecutor>)(+ o->work_));++ ASIO_ERROR_LOCATION(o->ec_);++ // Make a copy of the handler so that the memory can be deallocated before+ // the upcall is made. Even if we're not about to make an upcall, a+ // sub-object of the handler may be the true owner of the memory associated+ // with the handler. Consequently, a local copy of the handler is required+ // to ensure that any owning sub-object remains valid until after we have+ // deallocated the memory here.+ detail::binder2<Handler, asio::error_code, std::size_t>+ handler(o->handler_, o->ec_, o->bytes_transferred_);+ p.h = asio::detail::addressof(handler.handler_);+ p.reset();++ // Make the upcall if required.+ if (owner)+ {+ fenced_block b(fenced_block::half);+ ASIO_HANDLER_INVOCATION_BEGIN((handler.arg1_, handler.arg2_));+ w.complete(handler, handler.handler_);+ ASIO_HANDLER_INVOCATION_END;+ }+ }++private:+ Handler handler_;+ handler_work<Handler, IoExecutor> work_;+};++} // namespace detail+} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // defined(ASIO_HAS_IO_URING)++#endif // ASIO_DETAIL_IO_URING_SOCKET_SENDTO_OP_HPP
+ link/modules/asio-standalone/asio/include/asio/detail/io_uring_socket_service.hpp view
@@ -0,0 +1,631 @@+//+// detail/io_uring_socket_service.hpp+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com)+//+// Distributed under the Boost Software License, Version 1.0. (See accompanying+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)+//++#ifndef ASIO_DETAIL_IO_URING_SOCKET_SERVICE_HPP+#define ASIO_DETAIL_IO_URING_SOCKET_SERVICE_HPP++#if defined(_MSC_VER) && (_MSC_VER >= 1200)+# pragma once+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)++#include "asio/detail/config.hpp"++#if defined(ASIO_HAS_IO_URING)++#include "asio/buffer.hpp"+#include "asio/error.hpp"+#include "asio/execution_context.hpp"+#include "asio/socket_base.hpp"+#include "asio/detail/buffer_sequence_adapter.hpp"+#include "asio/detail/memory.hpp"+#include "asio/detail/noncopyable.hpp"+#include "asio/detail/io_uring_null_buffers_op.hpp"+#include "asio/detail/io_uring_service.hpp"+#include "asio/detail/io_uring_socket_accept_op.hpp"+#include "asio/detail/io_uring_socket_connect_op.hpp"+#include "asio/detail/io_uring_socket_recvfrom_op.hpp"+#include "asio/detail/io_uring_socket_sendto_op.hpp"+#include "asio/detail/io_uring_socket_service_base.hpp"+#include "asio/detail/socket_holder.hpp"+#include "asio/detail/socket_ops.hpp"+#include "asio/detail/socket_types.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {+namespace detail {++template <typename Protocol>+class io_uring_socket_service :+ public execution_context_service_base<io_uring_socket_service<Protocol> >,+ public io_uring_socket_service_base+{+public:+ // The protocol type.+ typedef Protocol protocol_type;++ // The endpoint type.+ typedef typename Protocol::endpoint endpoint_type;++ // The native type of a socket.+ typedef socket_type native_handle_type;++ // The implementation type of the socket.+ struct implementation_type :+ io_uring_socket_service_base::base_implementation_type+ {+ // Default constructor.+ implementation_type()+ : protocol_(endpoint_type().protocol())+ {+ }++ // The protocol associated with the socket.+ protocol_type protocol_;+ };++ // Constructor.+ io_uring_socket_service(execution_context& context)+ : execution_context_service_base<+ io_uring_socket_service<Protocol> >(context),+ io_uring_socket_service_base(context)+ {+ }++ // Destroy all user-defined handler objects owned by the service.+ void shutdown()+ {+ this->base_shutdown();+ }++ // Move-construct a new socket implementation.+ void move_construct(implementation_type& impl,+ implementation_type& other_impl) ASIO_NOEXCEPT+ {+ this->base_move_construct(impl, other_impl);++ impl.protocol_ = other_impl.protocol_;+ other_impl.protocol_ = endpoint_type().protocol();+ }++ // Move-assign from another socket implementation.+ void move_assign(implementation_type& impl,+ io_uring_socket_service_base& other_service,+ implementation_type& other_impl)+ {+ this->base_move_assign(impl, other_service, other_impl);++ impl.protocol_ = other_impl.protocol_;+ other_impl.protocol_ = endpoint_type().protocol();+ }++ // Move-construct a new socket implementation from another protocol type.+ template <typename Protocol1>+ void converting_move_construct(implementation_type& impl,+ io_uring_socket_service<Protocol1>&,+ typename io_uring_socket_service<+ Protocol1>::implementation_type& other_impl)+ {+ this->base_move_construct(impl, other_impl);++ impl.protocol_ = protocol_type(other_impl.protocol_);+ other_impl.protocol_ = typename Protocol1::endpoint().protocol();+ }++ // Open a new socket implementation.+ asio::error_code open(implementation_type& impl,+ const protocol_type& protocol, asio::error_code& ec)+ {+ if (!do_open(impl, protocol.family(),+ protocol.type(), protocol.protocol(), ec))+ impl.protocol_ = protocol;+ ASIO_ERROR_LOCATION(ec);+ return ec;+ }++ // Assign a native socket to a socket implementation.+ asio::error_code assign(implementation_type& impl,+ const protocol_type& protocol, const native_handle_type& native_socket,+ asio::error_code& ec)+ {+ if (!do_assign(impl, protocol.type(), native_socket, ec))+ impl.protocol_ = protocol;+ ASIO_ERROR_LOCATION(ec);+ return ec;+ }++ // Get the native socket representation.+ native_handle_type native_handle(implementation_type& impl)+ {+ return impl.socket_;+ }++ // Bind the socket to the specified local endpoint.+ asio::error_code bind(implementation_type& impl,+ const endpoint_type& endpoint, asio::error_code& ec)+ {+ socket_ops::bind(impl.socket_, endpoint.data(), endpoint.size(), ec);+ ASIO_ERROR_LOCATION(ec);+ return ec;+ }++ // Set a socket option.+ template <typename Option>+ asio::error_code set_option(implementation_type& impl,+ const Option& option, asio::error_code& ec)+ {+ socket_ops::setsockopt(impl.socket_, impl.state_,+ option.level(impl.protocol_), option.name(impl.protocol_),+ option.data(impl.protocol_), option.size(impl.protocol_), ec);+ ASIO_ERROR_LOCATION(ec);+ return ec;+ }++ // Set a socket option.+ template <typename Option>+ asio::error_code get_option(const implementation_type& impl,+ Option& option, asio::error_code& ec) const+ {+ std::size_t size = option.size(impl.protocol_);+ socket_ops::getsockopt(impl.socket_, impl.state_,+ option.level(impl.protocol_), option.name(impl.protocol_),+ option.data(impl.protocol_), &size, ec);+ if (!ec)+ option.resize(impl.protocol_, size);+ ASIO_ERROR_LOCATION(ec);+ return ec;+ }++ // Get the local endpoint.+ endpoint_type local_endpoint(const implementation_type& impl,+ asio::error_code& ec) const+ {+ endpoint_type endpoint;+ std::size_t addr_len = endpoint.capacity();+ if (socket_ops::getsockname(impl.socket_, endpoint.data(), &addr_len, ec))+ {+ ASIO_ERROR_LOCATION(ec);+ return endpoint_type();+ }+ endpoint.resize(addr_len);+ return endpoint;+ }++ // Get the remote endpoint.+ endpoint_type remote_endpoint(const implementation_type& impl,+ asio::error_code& ec) const+ {+ endpoint_type endpoint;+ std::size_t addr_len = endpoint.capacity();+ if (socket_ops::getpeername(impl.socket_,+ endpoint.data(), &addr_len, false, ec))+ {+ ASIO_ERROR_LOCATION(ec);+ return endpoint_type();+ }+ endpoint.resize(addr_len);+ return endpoint;+ }++ // Disable sends or receives on the socket.+ asio::error_code shutdown(base_implementation_type& impl,+ socket_base::shutdown_type what, asio::error_code& ec)+ {+ socket_ops::shutdown(impl.socket_, what, ec);+ ASIO_ERROR_LOCATION(ec);+ return ec;+ }++ // Send a datagram to the specified endpoint. Returns the number of bytes+ // sent.+ template <typename ConstBufferSequence>+ size_t send_to(implementation_type& impl, const ConstBufferSequence& buffers,+ const endpoint_type& destination, socket_base::message_flags flags,+ asio::error_code& ec)+ {+ typedef buffer_sequence_adapter<asio::const_buffer,+ ConstBufferSequence> bufs_type;++ size_t n;+ if (bufs_type::is_single_buffer)+ {+ n = socket_ops::sync_sendto1(impl.socket_, impl.state_,+ bufs_type::first(buffers).data(),+ bufs_type::first(buffers).size(), flags,+ destination.data(), destination.size(), ec);+ }+ else+ {+ bufs_type bufs(buffers);+ n = socket_ops::sync_sendto(impl.socket_, impl.state_,+ bufs.buffers(), bufs.count(), flags,+ destination.data(), destination.size(), ec);+ }++ ASIO_ERROR_LOCATION(ec);+ return n;+ }++ // Wait until data can be sent without blocking.+ size_t send_to(implementation_type& impl, const null_buffers&,+ const endpoint_type&, socket_base::message_flags,+ asio::error_code& ec)+ {+ // Wait for socket to become ready.+ socket_ops::poll_write(impl.socket_, impl.state_, -1, ec);+ ASIO_ERROR_LOCATION(ec);+ return 0;+ }++ // Start an asynchronous send. The data being sent must be valid for the+ // lifetime of the asynchronous operation.+ template <typename ConstBufferSequence, typename Handler, typename IoExecutor>+ void async_send_to(implementation_type& impl,+ const ConstBufferSequence& buffers,+ const endpoint_type& destination, socket_base::message_flags flags,+ Handler& handler, const IoExecutor& io_ex)+ {+ bool is_continuation =+ asio_handler_cont_helpers::is_continuation(handler);++ typename associated_cancellation_slot<Handler>::type slot+ = asio::get_associated_cancellation_slot(handler);++ // Allocate and construct an operation to wrap the handler.+ typedef io_uring_socket_sendto_op<ConstBufferSequence,+ endpoint_type, Handler, IoExecutor> op;+ typename op::ptr p = { asio::detail::addressof(handler),+ op::ptr::allocate(handler), 0 };+ p.p = new (p.v) op(success_ec_, impl.socket_, impl.state_,+ buffers, destination, flags, handler, io_ex);++ // Optionally register for per-operation cancellation.+ if (slot.is_connected())+ {+ p.p->cancellation_key_ =+ &slot.template emplace<io_uring_op_cancellation>(&io_uring_service_,+ &impl.io_object_data_, io_uring_service::write_op);+ }++ ASIO_HANDLER_CREATION((io_uring_service_.context(), *p.p,+ "socket", &impl, impl.socket_, "async_send_to"));++ start_op(impl, io_uring_service::write_op, p.p, is_continuation, false);+ p.v = p.p = 0;+ }++ // Start an asynchronous wait until data can be sent without blocking.+ template <typename Handler, typename IoExecutor>+ void async_send_to(implementation_type& impl, const null_buffers&,+ const endpoint_type&, socket_base::message_flags,+ Handler& handler, const IoExecutor& io_ex)+ {+ bool is_continuation =+ asio_handler_cont_helpers::is_continuation(handler);++ typename associated_cancellation_slot<Handler>::type slot+ = asio::get_associated_cancellation_slot(handler);++ // Allocate and construct an operation to wrap the handler.+ typedef io_uring_null_buffers_op<Handler, IoExecutor> op;+ typename op::ptr p = { asio::detail::addressof(handler),+ op::ptr::allocate(handler), 0 };+ p.p = new (p.v) op(success_ec_, impl.socket_, POLLOUT, handler, io_ex);++ // Optionally register for per-operation cancellation.+ if (slot.is_connected())+ {+ p.p->cancellation_key_ =+ &slot.template emplace<io_uring_op_cancellation>(&io_uring_service_,+ &impl.io_object_data_, io_uring_service::write_op);+ }++ ASIO_HANDLER_CREATION((io_uring_service_.context(), *p.p, "socket",+ &impl, impl.socket_, "async_send_to(null_buffers)"));++ start_op(impl, io_uring_service::write_op, p.p, is_continuation, false);+ p.v = p.p = 0;+ }++ // Receive a datagram with the endpoint of the sender. Returns the number of+ // bytes received.+ template <typename MutableBufferSequence>+ size_t receive_from(implementation_type& impl,+ const MutableBufferSequence& buffers,+ endpoint_type& sender_endpoint, socket_base::message_flags flags,+ asio::error_code& ec)+ {+ typedef buffer_sequence_adapter<asio::mutable_buffer,+ MutableBufferSequence> bufs_type;++ std::size_t addr_len = sender_endpoint.capacity();+ std::size_t n;+ if (bufs_type::is_single_buffer)+ {+ n = socket_ops::sync_recvfrom1(impl.socket_, impl.state_,+ bufs_type::first(buffers).data(), bufs_type::first(buffers).size(),+ flags, sender_endpoint.data(), &addr_len, ec);+ }+ else+ {+ bufs_type bufs(buffers);+ n = socket_ops::sync_recvfrom(impl.socket_, impl.state_, bufs.buffers(),+ bufs.count(), flags, sender_endpoint.data(), &addr_len, ec);+ }++ if (!ec)+ sender_endpoint.resize(addr_len);++ ASIO_ERROR_LOCATION(ec);+ return n;+ }++ // Wait until data can be received without blocking.+ size_t receive_from(implementation_type& impl, const null_buffers&,+ endpoint_type& sender_endpoint, socket_base::message_flags,+ asio::error_code& ec)+ {+ // Wait for socket to become ready.+ socket_ops::poll_read(impl.socket_, impl.state_, -1, ec);++ // Reset endpoint since it can be given no sensible value at this time.+ sender_endpoint = endpoint_type();++ ASIO_ERROR_LOCATION(ec);+ return 0;+ }++ // Start an asynchronous receive. The buffer for the data being received and+ // the sender_endpoint object must both be valid for the lifetime of the+ // asynchronous operation.+ template <typename MutableBufferSequence,+ typename Handler, typename IoExecutor>+ void async_receive_from(implementation_type& impl,+ const MutableBufferSequence& buffers, endpoint_type& sender_endpoint,+ socket_base::message_flags flags, Handler& handler,+ const IoExecutor& io_ex)+ {+ bool is_continuation =+ asio_handler_cont_helpers::is_continuation(handler);++ int op_type = (flags & socket_base::message_out_of_band)+ ? io_uring_service::except_op : io_uring_service::read_op;++ typename associated_cancellation_slot<Handler>::type slot+ = asio::get_associated_cancellation_slot(handler);++ // Allocate and construct an operation to wrap the handler.+ typedef io_uring_socket_recvfrom_op<MutableBufferSequence,+ endpoint_type, Handler, IoExecutor> op;+ typename op::ptr p = { asio::detail::addressof(handler),+ op::ptr::allocate(handler), 0 };+ p.p = new (p.v) op(success_ec_, impl.socket_, impl.state_,+ buffers, sender_endpoint, flags, handler, io_ex);++ // Optionally register for per-operation cancellation.+ if (slot.is_connected())+ {+ p.p->cancellation_key_ =+ &slot.template emplace<io_uring_op_cancellation>(+ &io_uring_service_, &impl.io_object_data_, op_type);+ }++ ASIO_HANDLER_CREATION((io_uring_service_.context(), *p.p,+ "socket", &impl, impl.socket_, "async_receive_from"));++ start_op(impl, op_type, p.p, is_continuation, false);+ p.v = p.p = 0;+ }++ // Wait until data can be received without blocking.+ template <typename Handler, typename IoExecutor>+ void async_receive_from(implementation_type& impl, const null_buffers&,+ endpoint_type& sender_endpoint, socket_base::message_flags flags,+ Handler& handler, const IoExecutor& io_ex)+ {+ bool is_continuation =+ asio_handler_cont_helpers::is_continuation(handler);++ int op_type;+ int poll_flags;+ if ((flags & socket_base::message_out_of_band) != 0)+ {+ op_type = io_uring_service::except_op;+ poll_flags = POLLPRI;+ }+ else+ {+ op_type = io_uring_service::read_op;+ poll_flags = POLLIN;+ }++ typename associated_cancellation_slot<Handler>::type slot+ = asio::get_associated_cancellation_slot(handler);++ // Allocate and construct an operation to wrap the handler.+ typedef io_uring_null_buffers_op<Handler, IoExecutor> op;+ typename op::ptr p = { asio::detail::addressof(handler),+ op::ptr::allocate(handler), 0 };+ p.p = new (p.v) op(success_ec_, impl.socket_, poll_flags, handler, io_ex);++ // Optionally register for per-operation cancellation.+ if (slot.is_connected())+ {+ p.p->cancellation_key_ =+ &slot.template emplace<io_uring_op_cancellation>(+ &io_uring_service_, &impl.io_object_data_, op_type);+ }++ ASIO_HANDLER_CREATION((io_uring_service_.context(), *p.p, "socket",+ &impl, impl.socket_, "async_receive_from(null_buffers)"));++ // Reset endpoint since it can be given no sensible value at this time.+ sender_endpoint = endpoint_type();++ start_op(impl, op_type, p.p, is_continuation, false);+ p.v = p.p = 0;+ }++ // Accept a new connection.+ template <typename Socket>+ asio::error_code accept(implementation_type& impl,+ Socket& peer, endpoint_type* peer_endpoint, asio::error_code& ec)+ {+ // We cannot accept a socket that is already open.+ if (peer.is_open())+ {+ ec = asio::error::already_open;+ ASIO_ERROR_LOCATION(ec);+ return ec;+ }++ std::size_t addr_len = peer_endpoint ? peer_endpoint->capacity() : 0;+ socket_holder new_socket(socket_ops::sync_accept(impl.socket_,+ impl.state_, peer_endpoint ? peer_endpoint->data() : 0,+ peer_endpoint ? &addr_len : 0, ec));++ // On success, assign new connection to peer socket object.+ if (new_socket.get() != invalid_socket)+ {+ if (peer_endpoint)+ peer_endpoint->resize(addr_len);+ peer.assign(impl.protocol_, new_socket.get(), ec);+ if (!ec)+ new_socket.release();+ }++ ASIO_ERROR_LOCATION(ec);+ return ec;+ }++ // Start an asynchronous accept. The peer and peer_endpoint objects must be+ // valid until the accept's handler is invoked.+ template <typename Socket, typename Handler, typename IoExecutor>+ void async_accept(implementation_type& impl, Socket& peer,+ endpoint_type* peer_endpoint, Handler& handler, const IoExecutor& io_ex)+ {+ bool is_continuation =+ asio_handler_cont_helpers::is_continuation(handler);++ typename associated_cancellation_slot<Handler>::type slot+ = asio::get_associated_cancellation_slot(handler);++ // Allocate and construct an operation to wrap the handler.+ typedef io_uring_socket_accept_op<Socket, Protocol, Handler, IoExecutor> op;+ typename op::ptr p = { asio::detail::addressof(handler),+ op::ptr::allocate(handler), 0 };+ p.p = new (p.v) op(success_ec_, impl.socket_, impl.state_,+ peer, impl.protocol_, peer_endpoint, handler, io_ex);++ // Optionally register for per-operation cancellation.+ if (slot.is_connected() && !peer.is_open())+ {+ p.p->cancellation_key_ =+ &slot.template emplace<io_uring_op_cancellation>(&io_uring_service_,+ &impl.io_object_data_, io_uring_service::read_op);+ }++ ASIO_HANDLER_CREATION((io_uring_service_.context(), *p.p,+ "socket", &impl, impl.socket_, "async_accept"));++ start_accept_op(impl, p.p, is_continuation, peer.is_open());+ p.v = p.p = 0;+ }++#if defined(ASIO_HAS_MOVE)+ // Start an asynchronous accept. The peer_endpoint object must be valid until+ // the accept's handler is invoked.+ template <typename PeerIoExecutor, typename Handler, typename IoExecutor>+ void async_move_accept(implementation_type& impl,+ const PeerIoExecutor& peer_io_ex, endpoint_type* peer_endpoint,+ Handler& handler, const IoExecutor& io_ex)+ {+ bool is_continuation =+ asio_handler_cont_helpers::is_continuation(handler);++ typename associated_cancellation_slot<Handler>::type slot+ = asio::get_associated_cancellation_slot(handler);++ // Allocate and construct an operation to wrap the handler.+ typedef io_uring_socket_move_accept_op<Protocol,+ PeerIoExecutor, Handler, IoExecutor> op;+ typename op::ptr p = { asio::detail::addressof(handler),+ op::ptr::allocate(handler), 0 };+ p.p = new (p.v) op(success_ec_, peer_io_ex, impl.socket_,+ impl.state_, impl.protocol_, peer_endpoint, handler, io_ex);++ // Optionally register for per-operation cancellation.+ if (slot.is_connected())+ {+ p.p->cancellation_key_ =+ &slot.template emplace<io_uring_op_cancellation>(&io_uring_service_,+ &impl.io_object_data_, io_uring_service::read_op);+ }++ ASIO_HANDLER_CREATION((io_uring_service_.context(), *p.p,+ "socket", &impl, impl.socket_, "async_accept"));++ start_accept_op(impl, p.p, is_continuation, false);+ p.v = p.p = 0;+ }+#endif // defined(ASIO_HAS_MOVE)++ // Connect the socket to the specified endpoint.+ asio::error_code connect(implementation_type& impl,+ const endpoint_type& peer_endpoint, asio::error_code& ec)+ {+ socket_ops::sync_connect(impl.socket_,+ peer_endpoint.data(), peer_endpoint.size(), ec);+ return ec;+ }++ // Start an asynchronous connect.+ template <typename Handler, typename IoExecutor>+ void async_connect(implementation_type& impl,+ const endpoint_type& peer_endpoint,+ Handler& handler, const IoExecutor& io_ex)+ {+ bool is_continuation =+ asio_handler_cont_helpers::is_continuation(handler);++ typename associated_cancellation_slot<Handler>::type slot+ = asio::get_associated_cancellation_slot(handler);++ // Allocate and construct an operation to wrap the handler.+ typedef io_uring_socket_connect_op<Protocol, Handler, IoExecutor> op;+ typename op::ptr p = { asio::detail::addressof(handler),+ op::ptr::allocate(handler), 0 };+ p.p = new (p.v) op(success_ec_, impl.socket_,+ peer_endpoint, handler, io_ex);++ // Optionally register for per-operation cancellation.+ if (slot.is_connected())+ {+ p.p->cancellation_key_ =+ &slot.template emplace<io_uring_op_cancellation>(&io_uring_service_,+ &impl.io_object_data_, io_uring_service::write_op);+ }++ ASIO_HANDLER_CREATION((io_uring_service_.context(), *p.p,+ "socket", &impl, impl.socket_, "async_connect"));++ start_op(impl, io_uring_service::write_op, p.p, is_continuation, false);+ p.v = p.p = 0;+ }+};++} // namespace detail+} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // defined(ASIO_HAS_IO_URING)++#endif // ASIO_DETAIL_IO_URING_SOCKET_SERVICE_HPP
+ link/modules/asio-standalone/asio/include/asio/detail/io_uring_socket_service_base.hpp view
@@ -0,0 +1,663 @@+//+// detail/io_uring_socket_service_base.hpp+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com)+//+// Distributed under the Boost Software License, Version 1.0. (See accompanying+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)+//++#ifndef ASIO_DETAIL_IO_URING_SOCKET_SERVICE_BASE_HPP+#define ASIO_DETAIL_IO_URING_SOCKET_SERVICE_BASE_HPP++#if defined(_MSC_VER) && (_MSC_VER >= 1200)+# pragma once+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)++#include "asio/detail/config.hpp"++#if defined(ASIO_HAS_IO_URING)++#include "asio/associated_cancellation_slot.hpp"+#include "asio/buffer.hpp"+#include "asio/cancellation_type.hpp"+#include "asio/error.hpp"+#include "asio/execution_context.hpp"+#include "asio/socket_base.hpp"+#include "asio/detail/buffer_sequence_adapter.hpp"+#include "asio/detail/memory.hpp"+#include "asio/detail/io_uring_null_buffers_op.hpp"+#include "asio/detail/io_uring_service.hpp"+#include "asio/detail/io_uring_socket_recv_op.hpp"+#include "asio/detail/io_uring_socket_recvmsg_op.hpp"+#include "asio/detail/io_uring_socket_send_op.hpp"+#include "asio/detail/io_uring_wait_op.hpp"+#include "asio/detail/socket_holder.hpp"+#include "asio/detail/socket_ops.hpp"+#include "asio/detail/socket_types.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {+namespace detail {++class io_uring_socket_service_base+{+public:+ // The native type of a socket.+ typedef socket_type native_handle_type;++ // The implementation type of the socket.+ struct base_implementation_type+ {+ // The native socket representation.+ socket_type socket_;++ // The current state of the socket.+ socket_ops::state_type state_;++ // Per I/O object data used by the io_uring_service.+ io_uring_service::per_io_object_data io_object_data_;+ };++ // Constructor.+ ASIO_DECL io_uring_socket_service_base(execution_context& context);++ // Destroy all user-defined handler objects owned by the service.+ ASIO_DECL void base_shutdown();++ // Construct a new socket implementation.+ ASIO_DECL void construct(base_implementation_type& impl);++ // Move-construct a new socket implementation.+ ASIO_DECL void base_move_construct(base_implementation_type& impl,+ base_implementation_type& other_impl) ASIO_NOEXCEPT;++ // Move-assign from another socket implementation.+ ASIO_DECL void base_move_assign(base_implementation_type& impl,+ io_uring_socket_service_base& other_service,+ base_implementation_type& other_impl);++ // Destroy a socket implementation.+ ASIO_DECL void destroy(base_implementation_type& impl);++ // Determine whether the socket is open.+ bool is_open(const base_implementation_type& impl) const+ {+ return impl.socket_ != invalid_socket;+ }++ // Destroy a socket implementation.+ ASIO_DECL asio::error_code close(+ base_implementation_type& impl, asio::error_code& ec);++ // Release ownership of the socket.+ ASIO_DECL socket_type release(+ base_implementation_type& impl, asio::error_code& ec);++ // Get the native socket representation.+ native_handle_type native_handle(base_implementation_type& impl)+ {+ return impl.socket_;+ }++ // Cancel all operations associated with the socket.+ ASIO_DECL asio::error_code cancel(+ base_implementation_type& impl, asio::error_code& ec);++ // Determine whether the socket is at the out-of-band data mark.+ bool at_mark(const base_implementation_type& impl,+ asio::error_code& ec) const+ {+ return socket_ops::sockatmark(impl.socket_, ec);+ }++ // Determine the number of bytes available for reading.+ std::size_t available(const base_implementation_type& impl,+ asio::error_code& ec) const+ {+ return socket_ops::available(impl.socket_, ec);+ }++ // Place the socket into the state where it will listen for new connections.+ asio::error_code listen(base_implementation_type& impl,+ int backlog, asio::error_code& ec)+ {+ socket_ops::listen(impl.socket_, backlog, ec);+ return ec;+ }++ // Perform an IO control command on the socket.+ template <typename IO_Control_Command>+ asio::error_code io_control(base_implementation_type& impl,+ IO_Control_Command& command, asio::error_code& ec)+ {+ socket_ops::ioctl(impl.socket_, impl.state_, command.name(),+ static_cast<ioctl_arg_type*>(command.data()), ec);+ return ec;+ }++ // Gets the non-blocking mode of the socket.+ bool non_blocking(const base_implementation_type& impl) const+ {+ return (impl.state_ & socket_ops::user_set_non_blocking) != 0;+ }++ // Sets the non-blocking mode of the socket.+ asio::error_code non_blocking(base_implementation_type& impl,+ bool mode, asio::error_code& ec)+ {+ socket_ops::set_user_non_blocking(impl.socket_, impl.state_, mode, ec);+ return ec;+ }++ // Gets the non-blocking mode of the native socket implementation.+ bool native_non_blocking(const base_implementation_type& impl) const+ {+ return (impl.state_ & socket_ops::internal_non_blocking) != 0;+ }++ // Sets the non-blocking mode of the native socket implementation.+ asio::error_code native_non_blocking(base_implementation_type& impl,+ bool mode, asio::error_code& ec)+ {+ socket_ops::set_internal_non_blocking(impl.socket_, impl.state_, mode, ec);+ return ec;+ }++ // Wait for the socket to become ready to read, ready to write, or to have+ // pending error conditions.+ asio::error_code wait(base_implementation_type& impl,+ socket_base::wait_type w, asio::error_code& ec)+ {+ switch (w)+ {+ case socket_base::wait_read:+ socket_ops::poll_read(impl.socket_, impl.state_, -1, ec);+ break;+ case socket_base::wait_write:+ socket_ops::poll_write(impl.socket_, impl.state_, -1, ec);+ break;+ case socket_base::wait_error:+ socket_ops::poll_error(impl.socket_, impl.state_, -1, ec);+ break;+ default:+ ec = asio::error::invalid_argument;+ break;+ }++ return ec;+ }++ // Asynchronously wait for the socket to become ready to read, ready to+ // write, or to have pending error conditions.+ template <typename Handler, typename IoExecutor>+ void async_wait(base_implementation_type& impl,+ socket_base::wait_type w, Handler& handler, const IoExecutor& io_ex)+ {+ bool is_continuation =+ asio_handler_cont_helpers::is_continuation(handler);++ typename associated_cancellation_slot<Handler>::type slot+ = asio::get_associated_cancellation_slot(handler);++ int op_type;+ int poll_flags;+ switch (w)+ {+ case socket_base::wait_read:+ op_type = io_uring_service::read_op;+ poll_flags = POLLIN;+ break;+ case socket_base::wait_write:+ op_type = io_uring_service::write_op;+ poll_flags = POLLOUT;+ break;+ case socket_base::wait_error:+ op_type = io_uring_service::except_op;+ poll_flags = POLLPRI | POLLERR | POLLHUP;+ break;+ default:+ op_type = -1;+ poll_flags = -1;+ return;+ }++ // Allocate and construct an operation to wrap the handler.+ typedef io_uring_wait_op<Handler, IoExecutor> op;+ typename op::ptr p = { asio::detail::addressof(handler),+ op::ptr::allocate(handler), 0 };+ p.p = new (p.v) op(success_ec_, impl.socket_,+ poll_flags, handler, io_ex);++ ASIO_HANDLER_CREATION((io_uring_service_.context(), *p.p,+ "socket", &impl, impl.socket_, "async_wait"));++ // Optionally register for per-operation cancellation.+ if (slot.is_connected())+ {+ p.p->cancellation_key_ =+ &slot.template emplace<io_uring_op_cancellation>(+ &io_uring_service_, &impl.io_object_data_, op_type);+ }++ start_op(impl, op_type, p.p, is_continuation, op_type == -1);+ p.v = p.p = 0;+ }++ // Send the given data to the peer.+ template <typename ConstBufferSequence>+ size_t send(base_implementation_type& impl,+ const ConstBufferSequence& buffers,+ socket_base::message_flags flags, asio::error_code& ec)+ {+ typedef buffer_sequence_adapter<asio::const_buffer,+ ConstBufferSequence> bufs_type;++ if (bufs_type::is_single_buffer)+ {+ return socket_ops::sync_send1(impl.socket_,+ impl.state_, bufs_type::first(buffers).data(),+ bufs_type::first(buffers).size(), flags, ec);+ }+ else+ {+ bufs_type bufs(buffers);+ return socket_ops::sync_send(impl.socket_, impl.state_,+ bufs.buffers(), bufs.count(), flags, bufs.all_empty(), ec);+ }+ }++ // Wait until data can be sent without blocking.+ size_t send(base_implementation_type& impl, const null_buffers&,+ socket_base::message_flags, asio::error_code& ec)+ {+ // Wait for socket to become ready.+ socket_ops::poll_write(impl.socket_, impl.state_, -1, ec);++ return 0;+ }++ // Start an asynchronous send. The data being sent must be valid for the+ // lifetime of the asynchronous operation.+ template <typename ConstBufferSequence, typename Handler, typename IoExecutor>+ void async_send(base_implementation_type& impl,+ const ConstBufferSequence& buffers, socket_base::message_flags flags,+ Handler& handler, const IoExecutor& io_ex)+ {+ bool is_continuation =+ asio_handler_cont_helpers::is_continuation(handler);++ typename associated_cancellation_slot<Handler>::type slot+ = asio::get_associated_cancellation_slot(handler);++ // Allocate and construct an operation to wrap the handler.+ typedef io_uring_socket_send_op<+ ConstBufferSequence, Handler, IoExecutor> op;+ typename op::ptr p = { asio::detail::addressof(handler),+ op::ptr::allocate(handler), 0 };+ p.p = new (p.v) op(success_ec_, impl.socket_,+ impl.state_, buffers, flags, handler, io_ex);++ // Optionally register for per-operation cancellation.+ if (slot.is_connected())+ {+ p.p->cancellation_key_ =+ &slot.template emplace<io_uring_op_cancellation>(&io_uring_service_,+ &impl.io_object_data_, io_uring_service::write_op);+ }++ ASIO_HANDLER_CREATION((io_uring_service_.context(), *p.p,+ "socket", &impl, impl.socket_, "async_send"));++ start_op(impl, io_uring_service::write_op, p.p, is_continuation,+ ((impl.state_ & socket_ops::stream_oriented)+ && buffer_sequence_adapter<asio::const_buffer,+ ConstBufferSequence>::all_empty(buffers)));+ p.v = p.p = 0;+ }++ // Start an asynchronous wait until data can be sent without blocking.+ template <typename Handler, typename IoExecutor>+ void async_send(base_implementation_type& impl, const null_buffers&,+ socket_base::message_flags, Handler& handler, const IoExecutor& io_ex)+ {+ bool is_continuation =+ asio_handler_cont_helpers::is_continuation(handler);++ typename associated_cancellation_slot<Handler>::type slot+ = asio::get_associated_cancellation_slot(handler);++ // Allocate and construct an operation to wrap the handler.+ typedef io_uring_null_buffers_op<Handler, IoExecutor> op;+ typename op::ptr p = { asio::detail::addressof(handler),+ op::ptr::allocate(handler), 0 };+ p.p = new (p.v) op(success_ec_, impl.socket_, POLLOUT, handler, io_ex);++ // Optionally register for per-operation cancellation.+ if (slot.is_connected())+ {+ p.p->cancellation_key_ =+ &slot.template emplace<io_uring_op_cancellation>(&io_uring_service_,+ &impl.io_object_data_, io_uring_service::write_op);+ }++ ASIO_HANDLER_CREATION((io_uring_service_.context(), *p.p,+ "socket", &impl, impl.socket_, "async_send(null_buffers)"));++ start_op(impl, io_uring_service::write_op, p.p, is_continuation, false);+ p.v = p.p = 0;+ }++ // Receive some data from the peer. Returns the number of bytes received.+ template <typename MutableBufferSequence>+ size_t receive(base_implementation_type& impl,+ const MutableBufferSequence& buffers,+ socket_base::message_flags flags, asio::error_code& ec)+ {+ typedef buffer_sequence_adapter<asio::mutable_buffer,+ MutableBufferSequence> bufs_type;++ if (bufs_type::is_single_buffer)+ {+ return socket_ops::sync_recv1(impl.socket_,+ impl.state_, bufs_type::first(buffers).data(),+ bufs_type::first(buffers).size(), flags, ec);+ }+ else+ {+ bufs_type bufs(buffers);+ return socket_ops::sync_recv(impl.socket_, impl.state_,+ bufs.buffers(), bufs.count(), flags, bufs.all_empty(), ec);+ }+ }++ // Wait until data can be received without blocking.+ size_t receive(base_implementation_type& impl, const null_buffers&,+ socket_base::message_flags, asio::error_code& ec)+ {+ // Wait for socket to become ready.+ socket_ops::poll_read(impl.socket_, impl.state_, -1, ec);++ return 0;+ }++ // Start an asynchronous receive. The buffer for the data being received+ // must be valid for the lifetime of the asynchronous operation.+ template <typename MutableBufferSequence,+ typename Handler, typename IoExecutor>+ void async_receive(base_implementation_type& impl,+ const MutableBufferSequence& buffers, socket_base::message_flags flags,+ Handler& handler, const IoExecutor& io_ex)+ {+ bool is_continuation =+ asio_handler_cont_helpers::is_continuation(handler);++ int op_type = (flags & socket_base::message_out_of_band)+ ? io_uring_service::except_op : io_uring_service::read_op;++ typename associated_cancellation_slot<Handler>::type slot+ = asio::get_associated_cancellation_slot(handler);++ // Allocate and construct an operation to wrap the handler.+ typedef io_uring_socket_recv_op<+ MutableBufferSequence, Handler, IoExecutor> op;+ typename op::ptr p = { asio::detail::addressof(handler),+ op::ptr::allocate(handler), 0 };+ p.p = new (p.v) op(success_ec_, impl.socket_,+ impl.state_, buffers, flags, handler, io_ex);++ // Optionally register for per-operation cancellation.+ if (slot.is_connected())+ {+ p.p->cancellation_key_ =+ &slot.template emplace<io_uring_op_cancellation>(+ &io_uring_service_, &impl.io_object_data_, op_type);+ }++ ASIO_HANDLER_CREATION((io_uring_service_.context(), *p.p,+ "socket", &impl, impl.socket_, "async_receive"));++ start_op(impl, op_type, p.p, is_continuation,+ ((impl.state_ & socket_ops::stream_oriented)+ && buffer_sequence_adapter<asio::mutable_buffer,+ MutableBufferSequence>::all_empty(buffers)));+ p.v = p.p = 0;+ }++ // Wait until data can be received without blocking.+ template <typename Handler, typename IoExecutor>+ void async_receive(base_implementation_type& impl,+ const null_buffers&, socket_base::message_flags flags,+ Handler& handler, const IoExecutor& io_ex)+ {+ bool is_continuation =+ asio_handler_cont_helpers::is_continuation(handler);++ int op_type;+ int poll_flags;+ if ((flags & socket_base::message_out_of_band) != 0)+ {+ op_type = io_uring_service::except_op;+ poll_flags = POLLPRI;+ }+ else+ {+ op_type = io_uring_service::read_op;+ poll_flags = POLLIN;+ }++ typename associated_cancellation_slot<Handler>::type slot+ = asio::get_associated_cancellation_slot(handler);++ // Allocate and construct an operation to wrap the handler.+ typedef io_uring_null_buffers_op<Handler, IoExecutor> op;+ typename op::ptr p = { asio::detail::addressof(handler),+ op::ptr::allocate(handler), 0 };+ p.p = new (p.v) op(success_ec_, impl.socket_, poll_flags, handler, io_ex);++ // Optionally register for per-operation cancellation.+ if (slot.is_connected())+ {+ p.p->cancellation_key_ =+ &slot.template emplace<io_uring_op_cancellation>(+ &io_uring_service_, &impl.io_object_data_, op_type);+ }++ ASIO_HANDLER_CREATION((io_uring_service_.context(), *p.p,+ "socket", &impl, impl.socket_, "async_receive(null_buffers)"));++ start_op(impl, op_type, p.p, is_continuation, false);+ p.v = p.p = 0;+ }++ // Receive some data with associated flags. Returns the number of bytes+ // received.+ template <typename MutableBufferSequence>+ size_t receive_with_flags(base_implementation_type& impl,+ const MutableBufferSequence& buffers,+ socket_base::message_flags in_flags,+ socket_base::message_flags& out_flags, asio::error_code& ec)+ {+ buffer_sequence_adapter<asio::mutable_buffer,+ MutableBufferSequence> bufs(buffers);++ return socket_ops::sync_recvmsg(impl.socket_, impl.state_,+ bufs.buffers(), bufs.count(), in_flags, out_flags, ec);+ }++ // Wait until data can be received without blocking.+ size_t receive_with_flags(base_implementation_type& impl,+ const null_buffers&, socket_base::message_flags,+ socket_base::message_flags& out_flags, asio::error_code& ec)+ {+ // Wait for socket to become ready.+ socket_ops::poll_read(impl.socket_, impl.state_, -1, ec);++ // Clear out_flags, since we cannot give it any other sensible value when+ // performing a null_buffers operation.+ out_flags = 0;++ return 0;+ }++ // Start an asynchronous receive. The buffer for the data being received+ // must be valid for the lifetime of the asynchronous operation.+ template <typename MutableBufferSequence,+ typename Handler, typename IoExecutor>+ void async_receive_with_flags(base_implementation_type& impl,+ const MutableBufferSequence& buffers, socket_base::message_flags in_flags,+ socket_base::message_flags& out_flags, Handler& handler,+ const IoExecutor& io_ex)+ {+ bool is_continuation =+ asio_handler_cont_helpers::is_continuation(handler);++ int op_type = (in_flags & socket_base::message_out_of_band)+ ? io_uring_service::except_op : io_uring_service::read_op;++ typename associated_cancellation_slot<Handler>::type slot+ = asio::get_associated_cancellation_slot(handler);++ // Allocate and construct an operation to wrap the handler.+ typedef io_uring_socket_recvmsg_op<+ MutableBufferSequence, Handler, IoExecutor> op;+ typename op::ptr p = { asio::detail::addressof(handler),+ op::ptr::allocate(handler), 0 };+ p.p = new (p.v) op(success_ec_, impl.socket_, impl.state_,+ buffers, in_flags, out_flags, handler, io_ex);++ // Optionally register for per-operation cancellation.+ if (slot.is_connected())+ {+ p.p->cancellation_key_ =+ &slot.template emplace<io_uring_op_cancellation>(+ &io_uring_service_, &impl.io_object_data_, op_type);+ }++ ASIO_HANDLER_CREATION((io_uring_service_.context(), *p.p,+ "socket", &impl, impl.socket_, "async_receive_with_flags"));++ start_op(impl, op_type, p.p, is_continuation, false);+ p.v = p.p = 0;+ }++ // Wait until data can be received without blocking.+ template <typename Handler, typename IoExecutor>+ void async_receive_with_flags(base_implementation_type& impl,+ const null_buffers&, socket_base::message_flags in_flags,+ socket_base::message_flags& out_flags, Handler& handler,+ const IoExecutor& io_ex)+ {+ bool is_continuation =+ asio_handler_cont_helpers::is_continuation(handler);++ int op_type;+ int poll_flags;+ if ((in_flags & socket_base::message_out_of_band) != 0)+ {+ op_type = io_uring_service::except_op;+ poll_flags = POLLPRI;+ }+ else+ {+ op_type = io_uring_service::read_op;+ poll_flags = POLLIN;+ }++ typename associated_cancellation_slot<Handler>::type slot+ = asio::get_associated_cancellation_slot(handler);++ // Allocate and construct an operation to wrap the handler.+ typedef io_uring_null_buffers_op<Handler, IoExecutor> op;+ typename op::ptr p = { asio::detail::addressof(handler),+ op::ptr::allocate(handler), 0 };+ p.p = new (p.v) op(success_ec_, impl.socket_, poll_flags, handler, io_ex);++ // Optionally register for per-operation cancellation.+ if (slot.is_connected())+ {+ p.p->cancellation_key_ =+ &slot.template emplace<io_uring_op_cancellation>(+ &io_uring_service_, &impl.io_object_data_, op_type);+ }++ ASIO_HANDLER_CREATION((io_uring_service_.context(), *p.p, "socket",+ &impl, impl.socket_, "async_receive_with_flags(null_buffers)"));++ // Clear out_flags, since we cannot give it any other sensible value when+ // performing a null_buffers operation.+ out_flags = 0;++ start_op(impl, op_type, p.p, is_continuation, false);+ p.v = p.p = 0;+ }++protected:+ // Open a new socket implementation.+ ASIO_DECL asio::error_code do_open(+ base_implementation_type& impl, int af,+ int type, int protocol, asio::error_code& ec);++ // Assign a native socket to a socket implementation.+ ASIO_DECL asio::error_code do_assign(+ base_implementation_type& impl, int type,+ const native_handle_type& native_socket, asio::error_code& ec);++ // Start the asynchronous read or write operation.+ ASIO_DECL void start_op(base_implementation_type& impl, int op_type,+ io_uring_operation* op, bool is_continuation, bool noop);++ // Start the asynchronous accept operation.+ ASIO_DECL void start_accept_op(base_implementation_type& impl,+ io_uring_operation* op, bool is_continuation, bool peer_is_open);++ // Helper class used to implement per-operation cancellation+ class io_uring_op_cancellation+ {+ public:+ io_uring_op_cancellation(io_uring_service* s,+ io_uring_service::per_io_object_data* p, int o)+ : io_uring_service_(s),+ io_object_data_(p),+ op_type_(o)+ {+ }++ void operator()(cancellation_type_t type)+ {+ if (!!(type &+ (cancellation_type::terminal+ | cancellation_type::partial+ | cancellation_type::total)))+ {+ io_uring_service_->cancel_ops_by_key(*io_object_data_, op_type_, this);+ }+ }++ private:+ io_uring_service* io_uring_service_;+ io_uring_service::per_io_object_data* io_object_data_;+ int op_type_;+ };++ // The io_uring_service that performs event demultiplexing for the service.+ io_uring_service& io_uring_service_;++ // Cached success value to avoid accessing category singleton.+ const asio::error_code success_ec_;+};++} // namespace detail+} // namespace asio++#include "asio/detail/pop_options.hpp"++#if defined(ASIO_HEADER_ONLY)+# include "asio/detail/impl/io_uring_socket_service_base.ipp"+#endif // defined(ASIO_HEADER_ONLY)++#endif // defined(ASIO_HAS_IO_URING)++#endif // ASIO_DETAIL_IO_URING_SOCKET_SERVICE_BASE_HPP
+ link/modules/asio-standalone/asio/include/asio/detail/io_uring_wait_op.hpp view
@@ -0,0 +1,113 @@+//+// detail/io_uring_wait_op.hpp+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com)+//+// Distributed under the Boost Software License, Version 1.0. (See accompanying+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)+//++#ifndef ASIO_DETAIL_IO_URING_WAIT_OP_HPP+#define ASIO_DETAIL_IO_URING_WAIT_OP_HPP++#if defined(_MSC_VER) && (_MSC_VER >= 1200)+# pragma once+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)++#include "asio/detail/config.hpp"+#include "asio/detail/bind_handler.hpp"+#include "asio/detail/fenced_block.hpp"+#include "asio/detail/handler_alloc_helpers.hpp"+#include "asio/detail/handler_invoke_helpers.hpp"+#include "asio/detail/handler_work.hpp"+#include "asio/detail/io_uring_operation.hpp"+#include "asio/detail/memory.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {+namespace detail {++template <typename Handler, typename IoExecutor>+class io_uring_wait_op : public io_uring_operation+{+public:+ ASIO_DEFINE_HANDLER_PTR(io_uring_wait_op);++ io_uring_wait_op(const asio::error_code& success_ec, int descriptor,+ int poll_flags, Handler& handler, const IoExecutor& io_ex)+ : io_uring_operation(success_ec, &io_uring_wait_op::do_prepare,+ &io_uring_wait_op::do_perform, &io_uring_wait_op::do_complete),+ handler_(ASIO_MOVE_CAST(Handler)(handler)),+ work_(handler_, io_ex),+ descriptor_(descriptor),+ poll_flags_(poll_flags)+ {+ }++ static void do_prepare(io_uring_operation* base, ::io_uring_sqe* sqe)+ {+ ASIO_ASSUME(base != 0);+ io_uring_wait_op* o(static_cast<io_uring_wait_op*>(base));++ ::io_uring_prep_poll_add(sqe, o->descriptor_, o->poll_flags_);+ }++ static bool do_perform(io_uring_operation*, bool after_completion)+ {+ return after_completion;+ }++ static void do_complete(void* owner, operation* base,+ const asio::error_code& /*ec*/,+ std::size_t /*bytes_transferred*/)+ {+ // Take ownership of the handler object.+ ASIO_ASSUME(base != 0);+ io_uring_wait_op* o(static_cast<io_uring_wait_op*>(base));+ ptr p = { asio::detail::addressof(o->handler_), o, o };++ ASIO_HANDLER_COMPLETION((*o));++ // Take ownership of the operation's outstanding work.+ handler_work<Handler, IoExecutor> w(+ ASIO_MOVE_CAST2(handler_work<Handler, IoExecutor>)(+ o->work_));++ ASIO_ERROR_LOCATION(o->ec_);++ // Make a copy of the handler so that the memory can be deallocated before+ // the upcall is made. Even if we're not about to make an upcall, a+ // sub-object of the handler may be the true owner of the memory associated+ // with the handler. Consequently, a local copy of the handler is required+ // to ensure that any owning sub-object remains valid until after we have+ // deallocated the memory here.+ detail::binder1<Handler, asio::error_code>+ handler(o->handler_, o->ec_);+ p.h = asio::detail::addressof(handler.handler_);+ p.reset();++ // Make the upcall if required.+ if (owner)+ {+ fenced_block b(fenced_block::half);+ ASIO_HANDLER_INVOCATION_BEGIN((handler.arg1_, handler.arg2_));+ w.complete(handler, handler.handler_);+ ASIO_HANDLER_INVOCATION_END;+ }+ }++private:+ Handler handler_;+ handler_work<Handler, IoExecutor> work_;+ int descriptor_;+ int poll_flags_;+};++} // namespace detail+} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // ASIO_DETAIL_IO_URING_WAIT_OP_HPP
link/modules/asio-standalone/asio/include/asio/detail/is_buffer_sequence.hpp view
@@ -2,7 +2,7 @@ // detail/is_buffer_sequence.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -24,6 +24,8 @@ class mutable_buffer; class const_buffer;+class mutable_registered_buffer;+class const_registered_buffer; namespace detail { @@ -254,6 +256,30 @@ template <> struct is_buffer_sequence<const_buffer, mutable_buffer>+ : false_type+{+};++template <>+struct is_buffer_sequence<mutable_registered_buffer, mutable_buffer>+ : true_type+{+};++template <>+struct is_buffer_sequence<mutable_registered_buffer, const_buffer>+ : true_type+{+};++template <>+struct is_buffer_sequence<const_registered_buffer, const_buffer>+ : true_type+{+};++template <>+struct is_buffer_sequence<const_registered_buffer, mutable_buffer> : false_type { };
link/modules/asio-standalone/asio/include/asio/detail/is_executor.hpp view
@@ -2,7 +2,7 @@ // detail/is_executor.hpp // ~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/detail/keyword_tss_ptr.hpp view
@@ -2,7 +2,7 @@ // detail/keyword_tss_ptr.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/detail/kqueue_reactor.hpp view
@@ -2,7 +2,7 @@ // detail/kqueue_reactor.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // Copyright (c) 2005 Stefan Arentz (stefan at soze dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying@@ -24,11 +24,12 @@ #include <sys/types.h> #include <sys/event.h> #include <sys/time.h>+#include "asio/detail/conditionally_enabled_mutex.hpp" #include "asio/detail/limits.hpp"-#include "asio/detail/mutex.hpp" #include "asio/detail/object_pool.hpp" #include "asio/detail/op_queue.hpp" #include "asio/detail/reactor_op.hpp"+#include "asio/detail/scheduler_task.hpp" #include "asio/detail/select_interrupter.hpp" #include "asio/detail/socket_types.hpp" #include "asio/detail/timer_queue_base.hpp"@@ -50,7 +51,8 @@ class scheduler; class kqueue_reactor- : public execution_context_service_base<kqueue_reactor>+ : public execution_context_service_base<kqueue_reactor>,+ public scheduler_task { private: // The mutex type used by this reactor.@@ -114,23 +116,44 @@ per_descriptor_data& source_descriptor_data); // Post a reactor operation for immediate completion.- void post_immediate_completion(reactor_op* op, bool is_continuation)- {- scheduler_.post_immediate_completion(op, is_continuation);- }+ void post_immediate_completion(operation* op, bool is_continuation) const; + // Post a reactor operation for immediate completion.+ ASIO_DECL static void call_post_immediate_completion(+ operation* op, bool is_continuation, const void* self);+ // Start a new operation. The reactor operation will be performed when the // given descriptor is flagged as ready, or an error has occurred. ASIO_DECL void start_op(int op_type, socket_type descriptor, per_descriptor_data& descriptor_data, reactor_op* op,- bool is_continuation, bool allow_speculative);+ bool is_continuation, bool allow_speculative,+ void (*on_immediate)(operation*, bool, const void*),+ const void* immediate_arg); + // Start a new operation. The reactor operation will be performed when the+ // given descriptor is flagged as ready, or an error has occurred.+ void start_op(int op_type, socket_type descriptor,+ per_descriptor_data& descriptor_data, reactor_op* op,+ bool is_continuation, bool allow_speculative)+ {+ start_op(op_type, descriptor, descriptor_data,+ op, is_continuation, allow_speculative,+ &kqueue_reactor::call_post_immediate_completion, this);+ }+ // Cancel all operations associated with the given descriptor. The // handlers associated with the descriptor will be invoked with the // operation_aborted error. ASIO_DECL void cancel_ops(socket_type descriptor, per_descriptor_data& descriptor_data); + // Cancel all operations associated with the given descriptor and key. The+ // handlers associated with the descriptor will be invoked with the+ // operation_aborted error.+ ASIO_DECL void cancel_ops_by_key(socket_type descriptor,+ per_descriptor_data& descriptor_data,+ int op_type, void* cancellation_key);+ // Cancel any operations that are running against the descriptor and remove // its registration from the reactor. The reactor resources associated with // the descriptor must be released by calling cleanup_descriptor_data.@@ -169,6 +192,12 @@ std::size_t cancel_timer(timer_queue<Time_Traits>& queue, typename timer_queue<Time_Traits>::per_timer_data& timer, std::size_t max_cancelled = (std::numeric_limits<std::size_t>::max)());++ // Cancel the timer operations associated with the given key.+ template <typename Time_Traits>+ void cancel_timer_by_key(timer_queue<Time_Traits>& queue,+ typename timer_queue<Time_Traits>::per_timer_data* timer,+ void* cancellation_key); // Move the timer operations associated with the given timer. template <typename Time_Traits>
link/modules/asio-standalone/asio/include/asio/detail/local_free_on_block_exit.hpp view
@@ -2,7 +2,7 @@ // detail/local_free_on_block_exit.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/detail/macos_fenced_block.hpp view
@@ -2,7 +2,7 @@ // detail/macos_fenced_block.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/detail/memory.hpp view
@@ -2,7 +2,7 @@ // detail/memory.hpp // ~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -16,7 +16,12 @@ #endif // defined(_MSC_VER) && (_MSC_VER >= 1200) #include "asio/detail/config.hpp"+#include <cstddef>+#include <cstdlib> #include <memory>+#include <new>+#include "asio/detail/cstdint.hpp"+#include "asio/detail/throw_exception.hpp" #if !defined(ASIO_HAS_STD_SHARED_PTR) # include <boost/make_shared.hpp>@@ -28,6 +33,14 @@ # include <boost/utility/addressof.hpp> #endif // !defined(ASIO_HAS_STD_ADDRESSOF) +#if !defined(ASIO_HAS_STD_ALIGNED_ALLOC) \+ && defined(ASIO_HAS_BOOST_ALIGN) \+ && defined(ASIO_HAS_ALIGNOF)+# include <boost/align/aligned_alloc.hpp>+#endif // !defined(ASIO_HAS_STD_ALIGNED_ALLOC)+ // && defined(ASIO_HAS_BOOST_ALIGN)+ // && defined(ASIO_HAS_ALIGNOF)+ namespace asio { namespace detail { @@ -47,6 +60,36 @@ using boost::addressof; #endif // defined(ASIO_HAS_STD_ADDRESSOF) +#if defined(ASIO_HAS_STD_TO_ADDRESS)+using std::to_address;+#else // defined(ASIO_HAS_STD_TO_ADDRESS)+template <typename T>+inline T* to_address(T* p) { return p; }+template <typename T>+inline const T* to_address(const T* p) { return p; }+template <typename T>+inline volatile T* to_address(volatile T* p) { return p; }+template <typename T>+inline const volatile T* to_address(const volatile T* p) { return p; }+#endif // defined(ASIO_HAS_STD_TO_ADDRESS)++inline void* align(std::size_t alignment,+ std::size_t size, void*& ptr, std::size_t& space)+{+#if defined(ASIO_HAS_STD_ALIGN)+ return std::align(alignment, size, ptr, space);+#else // defined(ASIO_HAS_STD_ALIGN)+ const uintptr_t intptr = reinterpret_cast<uintptr_t>(ptr);+ const uintptr_t aligned = (intptr - 1u + alignment) & -alignment;+ const std::size_t padding = aligned - intptr;+ if (size + padding > space)+ return 0;+ space -= padding;+ ptr = reinterpret_cast<void*>(aligned);+ return ptr;+#endif // defined(ASIO_HAS_STD_ALIGN)+}+ } // namespace detail #if defined(ASIO_HAS_CXX11_ALLOCATORS)@@ -67,6 +110,57 @@ typename alloc::template rebind<t>::other /**/ #endif // defined(ASIO_HAS_CXX11_ALLOCATORS)++inline void* aligned_new(std::size_t align, std::size_t size)+{+#if defined(ASIO_HAS_STD_ALIGNED_ALLOC) && defined(ASIO_HAS_ALIGNOF)+ align = (align < ASIO_DEFAULT_ALIGN) ? ASIO_DEFAULT_ALIGN : align;+ size = (size % align == 0) ? size : size + (align - size % align);+ void* ptr = std::aligned_alloc(align, size);+ if (!ptr)+ {+ std::bad_alloc ex;+ asio::detail::throw_exception(ex);+ }+ return ptr;+#elif defined(ASIO_HAS_BOOST_ALIGN) && defined(ASIO_HAS_ALIGNOF)+ align = (align < ASIO_DEFAULT_ALIGN) ? ASIO_DEFAULT_ALIGN : align;+ size = (size % align == 0) ? size : size + (align - size % align);+ void* ptr = boost::alignment::aligned_alloc(align, size);+ if (!ptr)+ {+ std::bad_alloc ex;+ asio::detail::throw_exception(ex);+ }+ return ptr;+#elif defined(ASIO_MSVC) && defined(ASIO_HAS_ALIGNOF)+ align = (align < ASIO_DEFAULT_ALIGN) ? ASIO_DEFAULT_ALIGN : align;+ size = (size % align == 0) ? size : size + (align - size % align);+ void* ptr = _aligned_malloc(size, align);+ if (!ptr)+ {+ std::bad_alloc ex;+ asio::detail::throw_exception(ex);+ }+ return ptr;+#else // defined(ASIO_MSVC) && defined(ASIO_HAS_ALIGNOF)+ (void)align;+ return ::operator new(size);+#endif // defined(ASIO_MSVC) && defined(ASIO_HAS_ALIGNOF)+}++inline void aligned_delete(void* ptr)+{+#if defined(ASIO_HAS_STD_ALIGNED_ALLOC) && defined(ASIO_HAS_ALIGNOF)+ std::free(ptr);+#elif defined(ASIO_HAS_BOOST_ALIGN) && defined(ASIO_HAS_ALIGNOF)+ boost::alignment::aligned_free(ptr);+#elif defined(ASIO_MSVC) && defined(ASIO_HAS_ALIGNOF)+ _aligned_free(ptr);+#else // defined(ASIO_MSVC) && defined(ASIO_HAS_ALIGNOF)+ ::operator delete(ptr);+#endif // defined(ASIO_MSVC) && defined(ASIO_HAS_ALIGNOF)+} } // namespace asio
link/modules/asio-standalone/asio/include/asio/detail/mutex.hpp view
@@ -2,7 +2,7 @@ // detail/mutex.hpp // ~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/detail/non_const_lvalue.hpp view
@@ -2,7 +2,7 @@ // detail/non_const_lvalue.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/detail/noncopyable.hpp view
@@ -2,7 +2,7 @@ // detail/noncopyable.hpp // ~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/detail/null_event.hpp view
@@ -2,7 +2,7 @@ // detail/null_event.hpp // ~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/detail/null_fenced_block.hpp view
@@ -2,7 +2,7 @@ // detail/null_fenced_block.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/detail/null_global.hpp view
@@ -2,7 +2,7 @@ // detail/null_global.hpp // ~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/detail/null_mutex.hpp view
@@ -2,7 +2,7 @@ // detail/null_mutex.hpp // ~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -17,8 +17,6 @@ #include "asio/detail/config.hpp" -#if !defined(ASIO_HAS_THREADS)- #include "asio/detail/noncopyable.hpp" #include "asio/detail/scoped_lock.hpp" @@ -58,7 +56,5 @@ } // namespace asio #include "asio/detail/pop_options.hpp"--#endif // !defined(ASIO_HAS_THREADS) #endif // ASIO_DETAIL_NULL_MUTEX_HPP
link/modules/asio-standalone/asio/include/asio/detail/null_reactor.hpp view
@@ -2,7 +2,7 @@ // detail/null_reactor.hpp // ~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -17,9 +17,12 @@ #include "asio/detail/config.hpp" -#if defined(ASIO_HAS_IOCP) || defined(ASIO_WINDOWS_RUNTIME)+#if defined(ASIO_HAS_IOCP) \+ || defined(ASIO_WINDOWS_RUNTIME) \+ || defined(ASIO_HAS_IO_URING_AS_DEFAULT) #include "asio/detail/scheduler_operation.hpp"+#include "asio/detail/scheduler_task.hpp" #include "asio/execution_context.hpp" #include "asio/detail/push_options.hpp"@@ -28,9 +31,14 @@ namespace detail { class null_reactor- : public execution_context_service_base<null_reactor>+ : public execution_context_service_base<null_reactor>,+ public scheduler_task { public:+ struct per_descriptor_data+ {+ };+ // Constructor. null_reactor(asio::execution_context& ctx) : execution_context_service_base<null_reactor>(ctx)@@ -42,6 +50,11 @@ { } + // Initialise the task.+ void init_task()+ {+ }+ // Destroy all user-defined handler objects owned by the service. void shutdown() {@@ -63,6 +76,8 @@ #include "asio/detail/pop_options.hpp" -#endif // defined(ASIO_HAS_IOCP) || defined(ASIO_WINDOWS_RUNTIME)+#endif // defined(ASIO_HAS_IOCP)+ // || defined(ASIO_WINDOWS_RUNTIME)+ // || defined(ASIO_HAS_IO_URING_AS_DEFAULT) #endif // ASIO_DETAIL_NULL_REACTOR_HPP
link/modules/asio-standalone/asio/include/asio/detail/null_signal_blocker.hpp view
@@ -2,7 +2,7 @@ // detail/null_signal_blocker.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/detail/null_socket_service.hpp view
@@ -2,7 +2,7 @@ // detail/null_socket_service.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/detail/null_static_mutex.hpp view
@@ -2,7 +2,7 @@ // detail/null_static_mutex.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/detail/null_thread.hpp view
@@ -2,7 +2,7 @@ // detail/null_thread.hpp // ~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/detail/null_tss_ptr.hpp view
@@ -2,7 +2,7 @@ // detail/null_tss_ptr.hpp // ~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/detail/object_pool.hpp view
@@ -2,7 +2,7 @@ // detail/object_pool.hpp // ~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/detail/old_win_sdk_compat.hpp view
@@ -2,7 +2,7 @@ // detail/old_win_sdk_compat.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/detail/op_queue.hpp view
@@ -2,7 +2,7 @@ // detail/op_queue.hpp // ~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/detail/operation.hpp view
@@ -2,7 +2,7 @@ // detail/operation.hpp // ~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/detail/pipe_select_interrupter.hpp view
@@ -2,7 +2,7 @@ // detail/pipe_select_interrupter.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/detail/pop_options.hpp view
@@ -2,7 +2,7 @@ // detail/pop_options.hpp // ~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -29,6 +29,10 @@ # endif // !defined(ASIO_DISABLE_VISIBILITY) # endif // (__GNUC__ == 4 && __GNUC_MINOR__ >= 1) || (__GNUC__ > 4) +# pragma pop_macro ("emit")+# pragma pop_macro ("signal")+# pragma pop_macro ("slot")+ #elif defined(__clang__) // Clang@@ -51,6 +55,10 @@ # pragma GCC diagnostic pop +# pragma pop_macro ("emit")+# pragma pop_macro ("signal")+# pragma pop_macro ("slot")+ #elif defined(__GNUC__) // GNU C++@@ -77,6 +85,10 @@ # pragma GCC diagnostic pop +# pragma pop_macro ("emit")+# pragma pop_macro ("signal")+# pragma pop_macro ("slot")+ #elif defined(__KCC) // Kai C++@@ -137,5 +149,9 @@ # undef ASIO_CLR_WORKAROUND # endif # endif++# pragma pop_macro ("emit")+# pragma pop_macro ("signal")+# pragma pop_macro ("slot") #endif
link/modules/asio-standalone/asio/include/asio/detail/posix_event.hpp view
@@ -2,7 +2,7 @@ // detail/posix_event.hpp // ~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/detail/posix_fd_set_adapter.hpp view
@@ -2,7 +2,7 @@ // detail/posix_fd_set_adapter.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/detail/posix_global.hpp view
@@ -2,7 +2,7 @@ // detail/posix_global.hpp // ~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/detail/posix_mutex.hpp view
@@ -2,7 +2,7 @@ // detail/posix_mutex.hpp // ~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+ link/modules/asio-standalone/asio/include/asio/detail/posix_serial_port_service.hpp view
@@ -0,0 +1,249 @@+//+// detail/posix_serial_port_service.hpp+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2008 Rep Invariant Systems, Inc. (info@repinvariant.com)+//+// Distributed under the Boost Software License, Version 1.0. (See accompanying+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)+//++#ifndef ASIO_DETAIL_POSIX_SERIAL_PORT_SERVICE_HPP+#define ASIO_DETAIL_POSIX_SERIAL_PORT_SERVICE_HPP++#if defined(_MSC_VER) && (_MSC_VER >= 1200)+# pragma once+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)++#include "asio/detail/config.hpp"++#if defined(ASIO_HAS_SERIAL_PORT)+#if !defined(ASIO_WINDOWS) && !defined(__CYGWIN__)++#include <string>+#include "asio/error.hpp"+#include "asio/execution_context.hpp"+#include "asio/serial_port_base.hpp"+#include "asio/detail/descriptor_ops.hpp"++#if defined(ASIO_HAS_IO_URING_AS_DEFAULT)+# include "asio/detail/io_uring_descriptor_service.hpp"+#else // defined(ASIO_HAS_IO_URING_AS_DEFAULT)+# include "asio/detail/reactive_descriptor_service.hpp"+#endif // defined(ASIO_HAS_IO_URING_AS_DEFAULT)++#include "asio/detail/push_options.hpp"++namespace asio {+namespace detail {++// Extend a descriptor_service to provide serial port support.+class posix_serial_port_service :+ public execution_context_service_base<posix_serial_port_service>+{+public:+#if defined(ASIO_HAS_IO_URING_AS_DEFAULT)+ typedef io_uring_descriptor_service descriptor_service;+#else // defined(ASIO_HAS_IO_URING_AS_DEFAULT)+ typedef reactive_descriptor_service descriptor_service;+#endif // defined(ASIO_HAS_IO_URING_AS_DEFAULT)++ // The native type of a serial port.+ typedef descriptor_service::native_handle_type native_handle_type;++ // The implementation type of the serial port.+ typedef descriptor_service::implementation_type implementation_type;++ ASIO_DECL posix_serial_port_service(execution_context& context);++ // Destroy all user-defined handler objects owned by the service.+ ASIO_DECL void shutdown();++ // Construct a new serial port implementation.+ void construct(implementation_type& impl)+ {+ descriptor_service_.construct(impl);+ }++ // Move-construct a new serial port implementation.+ void move_construct(implementation_type& impl,+ implementation_type& other_impl)+ {+ descriptor_service_.move_construct(impl, other_impl);+ }++ // Move-assign from another serial port implementation.+ void move_assign(implementation_type& impl,+ posix_serial_port_service& other_service,+ implementation_type& other_impl)+ {+ descriptor_service_.move_assign(impl,+ other_service.descriptor_service_, other_impl);+ }++ // Destroy a serial port implementation.+ void destroy(implementation_type& impl)+ {+ descriptor_service_.destroy(impl);+ }++ // Open the serial port using the specified device name.+ ASIO_DECL asio::error_code open(implementation_type& impl,+ const std::string& device, asio::error_code& ec);++ // Assign a native descriptor to a serial port implementation.+ asio::error_code assign(implementation_type& impl,+ const native_handle_type& native_descriptor,+ asio::error_code& ec)+ {+ return descriptor_service_.assign(impl, native_descriptor, ec);+ }++ // Determine whether the serial port is open.+ bool is_open(const implementation_type& impl) const+ {+ return descriptor_service_.is_open(impl);+ }++ // Destroy a serial port implementation.+ asio::error_code close(implementation_type& impl,+ asio::error_code& ec)+ {+ return descriptor_service_.close(impl, ec);+ }++ // Get the native serial port representation.+ native_handle_type native_handle(implementation_type& impl)+ {+ return descriptor_service_.native_handle(impl);+ }++ // Cancel all operations associated with the serial port.+ asio::error_code cancel(implementation_type& impl,+ asio::error_code& ec)+ {+ return descriptor_service_.cancel(impl, ec);+ }++ // Set an option on the serial port.+ template <typename SettableSerialPortOption>+ asio::error_code set_option(implementation_type& impl,+ const SettableSerialPortOption& option, asio::error_code& ec)+ {+ return do_set_option(impl,+ &posix_serial_port_service::store_option<SettableSerialPortOption>,+ &option, ec);+ }++ // Get an option from the serial port.+ template <typename GettableSerialPortOption>+ asio::error_code get_option(const implementation_type& impl,+ GettableSerialPortOption& option, asio::error_code& ec) const+ {+ return do_get_option(impl,+ &posix_serial_port_service::load_option<GettableSerialPortOption>,+ &option, ec);+ }++ // Send a break sequence to the serial port.+ asio::error_code send_break(implementation_type& impl,+ asio::error_code& ec)+ {+ int result = ::tcsendbreak(descriptor_service_.native_handle(impl), 0);+ descriptor_ops::get_last_error(ec, result < 0);+ ASIO_ERROR_LOCATION(ec);+ return ec;+ }++ // Write the given data. Returns the number of bytes sent.+ template <typename ConstBufferSequence>+ size_t write_some(implementation_type& impl,+ const ConstBufferSequence& buffers, asio::error_code& ec)+ {+ return descriptor_service_.write_some(impl, buffers, ec);+ }++ // Start an asynchronous write. The data being written must be valid for the+ // lifetime of the asynchronous operation.+ template <typename ConstBufferSequence, typename Handler, typename IoExecutor>+ void async_write_some(implementation_type& impl,+ const ConstBufferSequence& buffers,+ Handler& handler, const IoExecutor& io_ex)+ {+ descriptor_service_.async_write_some(impl, buffers, handler, io_ex);+ }++ // Read some data. Returns the number of bytes received.+ template <typename MutableBufferSequence>+ size_t read_some(implementation_type& impl,+ const MutableBufferSequence& buffers, asio::error_code& ec)+ {+ return descriptor_service_.read_some(impl, buffers, ec);+ }++ // Start an asynchronous read. The buffer for the data being received must be+ // valid for the lifetime of the asynchronous operation.+ template <typename MutableBufferSequence,+ typename Handler, typename IoExecutor>+ void async_read_some(implementation_type& impl,+ const MutableBufferSequence& buffers,+ Handler& handler, const IoExecutor& io_ex)+ {+ descriptor_service_.async_read_some(impl, buffers, handler, io_ex);+ }++private:+ // Function pointer type for storing a serial port option.+ typedef asio::error_code (*store_function_type)(+ const void*, termios&, asio::error_code&);++ // Helper function template to store a serial port option.+ template <typename SettableSerialPortOption>+ static asio::error_code store_option(const void* option,+ termios& storage, asio::error_code& ec)+ {+ static_cast<const SettableSerialPortOption*>(option)->store(storage, ec);+ return ec;+ }++ // Helper function to set a serial port option.+ ASIO_DECL asio::error_code do_set_option(+ implementation_type& impl, store_function_type store,+ const void* option, asio::error_code& ec);++ // Function pointer type for loading a serial port option.+ typedef asio::error_code (*load_function_type)(+ void*, const termios&, asio::error_code&);++ // Helper function template to load a serial port option.+ template <typename GettableSerialPortOption>+ static asio::error_code load_option(void* option,+ const termios& storage, asio::error_code& ec)+ {+ static_cast<GettableSerialPortOption*>(option)->load(storage, ec);+ return ec;+ }++ // Helper function to get a serial port option.+ ASIO_DECL asio::error_code do_get_option(+ const implementation_type& impl, load_function_type load,+ void* option, asio::error_code& ec) const;++ // The implementation used for initiating asynchronous operations.+ descriptor_service descriptor_service_;+};++} // namespace detail+} // namespace asio++#include "asio/detail/pop_options.hpp"++#if defined(ASIO_HEADER_ONLY)+# include "asio/detail/impl/posix_serial_port_service.ipp"+#endif // defined(ASIO_HEADER_ONLY)++#endif // !defined(ASIO_WINDOWS) && !defined(__CYGWIN__)+#endif // defined(ASIO_HAS_SERIAL_PORT)++#endif // ASIO_DETAIL_POSIX_SERIAL_PORT_SERVICE_HPP
link/modules/asio-standalone/asio/include/asio/detail/posix_signal_blocker.hpp view
@@ -2,7 +2,7 @@ // detail/posix_signal_blocker.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/detail/posix_static_mutex.hpp view
@@ -2,7 +2,7 @@ // detail/posix_static_mutex.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/detail/posix_thread.hpp view
@@ -2,7 +2,7 @@ // detail/posix_thread.hpp // ~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/detail/posix_tss_ptr.hpp view
@@ -2,7 +2,7 @@ // detail/posix_tss_ptr.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/detail/push_options.hpp view
@@ -2,7 +2,7 @@ // detail/push_options.hpp // ~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -29,6 +29,15 @@ # endif // !defined(ASIO_DISABLE_VISIBILITY) # endif // (__GNUC__ == 4 && __GNUC_MINOR__ >= 1) || (__GNUC__ > 4) +# pragma push_macro ("emit")+# undef emit++# pragma push_macro ("signal")+# undef signal++# pragma push_macro ("slot")+# undef slot+ #elif defined(__clang__) // Clang@@ -53,7 +62,19 @@ # pragma GCC diagnostic push # pragma GCC diagnostic ignored "-Wnon-virtual-dtor"+# if (__clang_major__ >= 6)+# pragma GCC diagnostic ignored "-Wzero-as-null-pointer-constant"+# endif // (__clang_major__ >= 6) +# pragma push_macro ("emit")+# undef emit++# pragma push_macro ("signal")+# undef signal++# pragma push_macro ("slot")+# undef slot+ #elif defined(__GNUC__) // GNU C++@@ -82,10 +103,22 @@ # pragma GCC diagnostic push # pragma GCC diagnostic ignored "-Wnon-virtual-dtor"+# if (__GNUC__ == 4 && __GNUC_MINOR__ >= 7) || (__GNUC__ > 4)+# pragma GCC diagnostic ignored "-Wzero-as-null-pointer-constant"+# endif // (__GNUC__ == 4 && __GNUC_MINOR__ >= 7) || (__GNUC__ > 4) # if (__GNUC__ >= 7) # pragma GCC diagnostic ignored "-Wimplicit-fallthrough" # endif // (__GNUC__ >= 7) +# pragma push_macro ("emit")+# undef emit++# pragma push_macro ("signal")+# undef signal++# pragma push_macro ("slot")+# undef slot+ #elif defined(__KCC) // Kai C++@@ -139,12 +172,13 @@ // // Must remain the last #elif since some other vendors (Metrowerks, for example) // also #define _MSC_VER- # pragma warning (disable:4103) # pragma warning (push)+# pragma warning (disable:4619) // suppress 'there is no warning number XXXX' # pragma warning (disable:4127) # pragma warning (disable:4180) # pragma warning (disable:4244)+# pragma warning (disable:4265) # pragma warning (disable:4355) # pragma warning (disable:4510) # pragma warning (disable:4512)@@ -181,5 +215,14 @@ # endif # endif # endif++# pragma push_macro ("emit")+# undef emit++# pragma push_macro ("signal")+# undef signal++# pragma push_macro ("slot")+# undef slot #endif
link/modules/asio-standalone/asio/include/asio/detail/reactive_descriptor_service.hpp view
@@ -2,7 +2,7 @@ // detail/reactive_descriptor_service.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -19,9 +19,13 @@ #if !defined(ASIO_WINDOWS) \ && !defined(ASIO_WINDOWS_RUNTIME) \- && !defined(__CYGWIN__)+ && !defined(__CYGWIN__) \+ && !defined(ASIO_HAS_IO_URING_AS_DEFAULT) +#include "asio/associated_cancellation_slot.hpp"+#include "asio/associated_immediate_executor.hpp" #include "asio/buffer.hpp"+#include "asio/cancellation_type.hpp" #include "asio/execution_context.hpp" #include "asio/detail/bind_handler.hpp" #include "asio/detail/buffer_sequence_adapter.hpp"@@ -119,6 +123,14 @@ // Release ownership of the native descriptor representation. ASIO_DECL native_handle_type release(implementation_type& impl); + // Release ownership of the native descriptor representation.+ native_handle_type release(implementation_type& impl,+ asio::error_code& ec)+ {+ ec = success_ec_;+ return release(impl);+ }+ // Cancel all operations associated with the descriptor. ASIO_DECL asio::error_code cancel(implementation_type& impl, asio::error_code& ec);@@ -130,6 +142,7 @@ { descriptor_ops::ioctl(impl.descriptor_, impl.state_, command.name(), static_cast<ioctl_arg_type*>(command.data()), ec);+ ASIO_ERROR_LOCATION(ec); return ec; } @@ -145,6 +158,7 @@ { descriptor_ops::set_user_non_blocking( impl.descriptor_, impl.state_, mode, ec);+ ASIO_ERROR_LOCATION(ec); return ec; } @@ -184,6 +198,7 @@ break; } + ASIO_ERROR_LOCATION(ec); return ec; } @@ -197,6 +212,9 @@ bool is_continuation = asio_handler_cont_helpers::is_continuation(handler); + typename associated_cancellation_slot<Handler>::type slot+ = asio::get_associated_cancellation_slot(handler);+ // Allocate and construct an operation to wrap the handler. typedef reactive_wait_op<Handler, IoExecutor> op; typename op::ptr p = { asio::detail::addressof(handler),@@ -210,22 +228,31 @@ switch (w) { case posix::descriptor_base::wait_read:- op_type = reactor::read_op;- break;+ op_type = reactor::read_op;+ break; case posix::descriptor_base::wait_write:- op_type = reactor::write_op;- break;+ op_type = reactor::write_op;+ break; case posix::descriptor_base::wait_error:- op_type = reactor::except_op;- break;- default:- p.p->ec_ = asio::error::invalid_argument;- reactor_.post_immediate_completion(p.p, is_continuation);- p.v = p.p = 0;- return;+ op_type = reactor::except_op;+ break;+ default:+ p.p->ec_ = asio::error::invalid_argument;+ start_op(impl, reactor::read_op, p.p,+ is_continuation, false, true, &io_ex, 0);+ p.v = p.p = 0;+ return; } - start_op(impl, op_type, p.p, is_continuation, false, false);+ // Optionally register for per-operation cancellation.+ if (slot.is_connected())+ {+ p.p->cancellation_key_ =+ &slot.template emplace<reactor_op_cancellation>(+ &reactor_, &impl.reactor_data_, impl.descriptor_, op_type);+ }++ start_op(impl, op_type, p.p, is_continuation, false, false, &io_ex, 0); p.v = p.p = 0; } @@ -237,9 +264,10 @@ typedef buffer_sequence_adapter<asio::const_buffer, ConstBufferSequence> bufs_type; + size_t n; if (bufs_type::is_single_buffer) {- return descriptor_ops::sync_write1(impl.descriptor_,+ n = descriptor_ops::sync_write1(impl.descriptor_, impl.state_, bufs_type::first(buffers).data(), bufs_type::first(buffers).size(), ec); }@@ -247,9 +275,12 @@ { bufs_type bufs(buffers); - return descriptor_ops::sync_write(impl.descriptor_, impl.state_,+ n = descriptor_ops::sync_write(impl.descriptor_, impl.state_, bufs.buffers(), bufs.count(), bufs.all_empty(), ec); }++ ASIO_ERROR_LOCATION(ec);+ return n; } // Wait until data can be written without blocking.@@ -258,7 +289,7 @@ { // Wait for descriptor to become ready. descriptor_ops::poll_write(impl.descriptor_, impl.state_, ec);-+ ASIO_ERROR_LOCATION(ec); return 0; } @@ -272,18 +303,30 @@ bool is_continuation = asio_handler_cont_helpers::is_continuation(handler); + typename associated_cancellation_slot<Handler>::type slot+ = asio::get_associated_cancellation_slot(handler);+ // Allocate and construct an operation to wrap the handler. typedef descriptor_write_op<ConstBufferSequence, Handler, IoExecutor> op; typename op::ptr p = { asio::detail::addressof(handler), op::ptr::allocate(handler), 0 }; p.p = new (p.v) op(success_ec_, impl.descriptor_, buffers, handler, io_ex); + // Optionally register for per-operation cancellation.+ if (slot.is_connected())+ {+ p.p->cancellation_key_ =+ &slot.template emplace<reactor_op_cancellation>(+ &reactor_, &impl.reactor_data_,+ impl.descriptor_, reactor::write_op);+ }+ ASIO_HANDLER_CREATION((reactor_.context(), *p.p, "descriptor", &impl, impl.descriptor_, "async_write_some")); start_op(impl, reactor::write_op, p.p, is_continuation, true, buffer_sequence_adapter<asio::const_buffer,- ConstBufferSequence>::all_empty(buffers));+ ConstBufferSequence>::all_empty(buffers), &io_ex, 0); p.v = p.p = 0; } @@ -295,16 +338,29 @@ bool is_continuation = asio_handler_cont_helpers::is_continuation(handler); + typename associated_cancellation_slot<Handler>::type slot+ = asio::get_associated_cancellation_slot(handler);+ // Allocate and construct an operation to wrap the handler. typedef reactive_null_buffers_op<Handler, IoExecutor> op; typename op::ptr p = { asio::detail::addressof(handler), op::ptr::allocate(handler), 0 }; p.p = new (p.v) op(success_ec_, handler, io_ex); + // Optionally register for per-operation cancellation.+ if (slot.is_connected())+ {+ p.p->cancellation_key_ =+ &slot.template emplace<reactor_op_cancellation>(+ &reactor_, &impl.reactor_data_,+ impl.descriptor_, reactor::write_op);+ }+ ASIO_HANDLER_CREATION((reactor_.context(), *p.p, "descriptor", &impl, impl.descriptor_, "async_write_some(null_buffers)")); - start_op(impl, reactor::write_op, p.p, is_continuation, false, false);+ start_op(impl, reactor::write_op, p.p,+ is_continuation, false, false, &io_ex, 0); p.v = p.p = 0; } @@ -316,9 +372,10 @@ typedef buffer_sequence_adapter<asio::mutable_buffer, MutableBufferSequence> bufs_type; + size_t n; if (bufs_type::is_single_buffer) {- return descriptor_ops::sync_read1(impl.descriptor_,+ n = descriptor_ops::sync_read1(impl.descriptor_, impl.state_, bufs_type::first(buffers).data(), bufs_type::first(buffers).size(), ec); }@@ -326,9 +383,12 @@ { bufs_type bufs(buffers); - return descriptor_ops::sync_read(impl.descriptor_, impl.state_,+ n = descriptor_ops::sync_read(impl.descriptor_, impl.state_, bufs.buffers(), bufs.count(), bufs.all_empty(), ec); }++ ASIO_ERROR_LOCATION(ec);+ return n; } // Wait until data can be read without blocking.@@ -337,7 +397,7 @@ { // Wait for descriptor to become ready. descriptor_ops::poll_read(impl.descriptor_, impl.state_, ec);-+ ASIO_ERROR_LOCATION(ec); return 0; } @@ -352,18 +412,30 @@ bool is_continuation = asio_handler_cont_helpers::is_continuation(handler); + typename associated_cancellation_slot<Handler>::type slot+ = asio::get_associated_cancellation_slot(handler);+ // Allocate and construct an operation to wrap the handler. typedef descriptor_read_op<MutableBufferSequence, Handler, IoExecutor> op; typename op::ptr p = { asio::detail::addressof(handler), op::ptr::allocate(handler), 0 }; p.p = new (p.v) op(success_ec_, impl.descriptor_, buffers, handler, io_ex); + // Optionally register for per-operation cancellation.+ if (slot.is_connected())+ {+ p.p->cancellation_key_ =+ &slot.template emplace<reactor_op_cancellation>(+ &reactor_, &impl.reactor_data_,+ impl.descriptor_, reactor::read_op);+ }+ ASIO_HANDLER_CREATION((reactor_.context(), *p.p, "descriptor", &impl, impl.descriptor_, "async_read_some")); start_op(impl, reactor::read_op, p.p, is_continuation, true, buffer_sequence_adapter<asio::mutable_buffer,- MutableBufferSequence>::all_empty(buffers));+ MutableBufferSequence>::all_empty(buffers), &io_ex, 0); p.v = p.p = 0; } @@ -375,24 +447,101 @@ bool is_continuation = asio_handler_cont_helpers::is_continuation(handler); + typename associated_cancellation_slot<Handler>::type slot+ = asio::get_associated_cancellation_slot(handler);+ // Allocate and construct an operation to wrap the handler. typedef reactive_null_buffers_op<Handler, IoExecutor> op; typename op::ptr p = { asio::detail::addressof(handler), op::ptr::allocate(handler), 0 }; p.p = new (p.v) op(success_ec_, handler, io_ex); + // Optionally register for per-operation cancellation.+ if (slot.is_connected())+ {+ p.p->cancellation_key_ =+ &slot.template emplace<reactor_op_cancellation>(+ &reactor_, &impl.reactor_data_,+ impl.descriptor_, reactor::read_op);+ }+ ASIO_HANDLER_CREATION((reactor_.context(), *p.p, "descriptor", &impl, impl.descriptor_, "async_read_some(null_buffers)")); - start_op(impl, reactor::read_op, p.p, is_continuation, false, false);+ start_op(impl, reactor::read_op, p.p,+ is_continuation, false, false, &io_ex, 0); p.v = p.p = 0; } private: // Start the asynchronous operation.- ASIO_DECL void start_op(implementation_type& impl, int op_type,- reactor_op* op, bool is_continuation, bool is_non_blocking, bool noop);+ ASIO_DECL void do_start_op(implementation_type& impl, int op_type,+ reactor_op* op, bool is_continuation, bool is_non_blocking, bool noop,+ void (*on_immediate)(operation* op, bool, const void*),+ const void* immediate_arg); + // Start the asynchronous operation for handlers that are specialised for+ // immediate completion.+ template <typename Op>+ void start_op(implementation_type& impl, int op_type, Op* op,+ bool is_continuation, bool is_non_blocking, bool noop,+ const void* io_ex, ...)+ {+ return do_start_op(impl, op_type, op, is_continuation,+ is_non_blocking, noop, &Op::do_immediate, io_ex);+ }++ // Start the asynchronous operation for handlers that are not specialised for+ // immediate completion.+ template <typename Op>+ void start_op(implementation_type& impl, int op_type, Op* op,+ bool is_continuation, bool is_non_blocking, bool noop, const void*,+ typename enable_if<+ is_same<+ typename associated_immediate_executor<+ typename Op::handler_type,+ typename Op::io_executor_type+ >::asio_associated_immediate_executor_is_unspecialised,+ void+ >::value+ >::type*)+ {+ return do_start_op(impl, op_type, op, is_continuation, is_non_blocking,+ noop, &reactor::call_post_immediate_completion, &reactor_);+ }++ // Helper class used to implement per-operation cancellation+ class reactor_op_cancellation+ {+ public:+ reactor_op_cancellation(reactor* r,+ reactor::per_descriptor_data* p, int d, int o)+ : reactor_(r),+ reactor_data_(p),+ descriptor_(d),+ op_type_(o)+ {+ }++ void operator()(cancellation_type_t type)+ {+ if (!!(type &+ (cancellation_type::terminal+ | cancellation_type::partial+ | cancellation_type::total)))+ {+ reactor_->cancel_ops_by_key(descriptor_,+ *reactor_data_, op_type_, this);+ }+ }++ private:+ reactor* reactor_;+ reactor::per_descriptor_data* reactor_data_;+ int descriptor_;+ int op_type_;+ };+ // The selector that performs event demultiplexing for the service. reactor& reactor_; @@ -412,5 +561,6 @@ #endif // !defined(ASIO_WINDOWS) // && !defined(ASIO_WINDOWS_RUNTIME) // && !defined(__CYGWIN__)+ // && !defined(ASIO_HAS_IO_URING_AS_DEFAULT) #endif // ASIO_DETAIL_REACTIVE_DESCRIPTOR_SERVICE_HPP
link/modules/asio-standalone/asio/include/asio/detail/reactive_null_buffers_op.hpp view
@@ -2,7 +2,7 @@ // detail/reactive_null_buffers_op.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -33,6 +33,9 @@ class reactive_null_buffers_op : public reactor_op { public:+ typedef Handler handler_type;+ typedef IoExecutor io_executor_type;+ ASIO_DEFINE_HANDLER_PTR(reactive_null_buffers_op); reactive_null_buffers_op(const asio::error_code& success_ec,@@ -54,6 +57,7 @@ std::size_t /*bytes_transferred*/) { // Take ownership of the handler object.+ ASIO_ASSUME(base != 0); reactive_null_buffers_op* o(static_cast<reactive_null_buffers_op*>(base)); ptr p = { asio::detail::addressof(o->handler_), o, o }; @@ -83,6 +87,36 @@ w.complete(handler, handler.handler_); ASIO_HANDLER_INVOCATION_END; }+ }++ static void do_immediate(operation* base, bool, const void* io_ex)+ {+ // Take ownership of the handler object.+ ASIO_ASSUME(base != 0);+ reactive_null_buffers_op* o(static_cast<reactive_null_buffers_op*>(base));+ ptr p = { asio::detail::addressof(o->handler_), o, o };++ ASIO_HANDLER_COMPLETION((*o));++ // Take ownership of the operation's outstanding work.+ immediate_handler_work<Handler, IoExecutor> w(+ ASIO_MOVE_CAST2(handler_work<Handler, IoExecutor>)(+ o->work_));++ // Make a copy of the handler so that the memory can be deallocated before+ // the upcall is made. Even if we're not about to make an upcall, a+ // sub-object of the handler may be the true owner of the memory associated+ // with the handler. Consequently, a local copy of the handler is required+ // to ensure that any owning sub-object remains valid until after we have+ // deallocated the memory here.+ detail::binder2<Handler, asio::error_code, std::size_t>+ handler(o->handler_, o->ec_, o->bytes_transferred_);+ p.h = asio::detail::addressof(handler.handler_);+ p.reset();++ ASIO_HANDLER_INVOCATION_BEGIN((handler.arg1_, handler.arg2_));+ w.complete(handler, handler.handler_, io_ex);+ ASIO_HANDLER_INVOCATION_END; } private:
− link/modules/asio-standalone/asio/include/asio/detail/reactive_serial_port_service.hpp
@@ -1,237 +0,0 @@-//-// detail/reactive_serial_port_service.hpp-// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~-//-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)-// Copyright (c) 2008 Rep Invariant Systems, Inc. (info@repinvariant.com)-//-// Distributed under the Boost Software License, Version 1.0. (See accompanying-// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)-//--#ifndef ASIO_DETAIL_REACTIVE_SERIAL_PORT_SERVICE_HPP-#define ASIO_DETAIL_REACTIVE_SERIAL_PORT_SERVICE_HPP--#if defined(_MSC_VER) && (_MSC_VER >= 1200)-# pragma once-#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)--#include "asio/detail/config.hpp"--#if defined(ASIO_HAS_SERIAL_PORT)-#if !defined(ASIO_WINDOWS) && !defined(__CYGWIN__)--#include <string>-#include "asio/error.hpp"-#include "asio/execution_context.hpp"-#include "asio/serial_port_base.hpp"-#include "asio/detail/descriptor_ops.hpp"-#include "asio/detail/reactive_descriptor_service.hpp"--#include "asio/detail/push_options.hpp"--namespace asio {-namespace detail {--// Extend reactive_descriptor_service to provide serial port support.-class reactive_serial_port_service :- public execution_context_service_base<reactive_serial_port_service>-{-public:- // The native type of a serial port.- typedef reactive_descriptor_service::native_handle_type native_handle_type;-- // The implementation type of the serial port.- typedef reactive_descriptor_service::implementation_type implementation_type;-- ASIO_DECL reactive_serial_port_service(execution_context& context);-- // Destroy all user-defined handler objects owned by the service.- ASIO_DECL void shutdown();-- // Construct a new serial port implementation.- void construct(implementation_type& impl)- {- descriptor_service_.construct(impl);- }-- // Move-construct a new serial port implementation.- void move_construct(implementation_type& impl,- implementation_type& other_impl)- {- descriptor_service_.move_construct(impl, other_impl);- }-- // Move-assign from another serial port implementation.- void move_assign(implementation_type& impl,- reactive_serial_port_service& other_service,- implementation_type& other_impl)- {- descriptor_service_.move_assign(impl,- other_service.descriptor_service_, other_impl);- }-- // Destroy a serial port implementation.- void destroy(implementation_type& impl)- {- descriptor_service_.destroy(impl);- }-- // Open the serial port using the specified device name.- ASIO_DECL asio::error_code open(implementation_type& impl,- const std::string& device, asio::error_code& ec);-- // Assign a native descriptor to a serial port implementation.- asio::error_code assign(implementation_type& impl,- const native_handle_type& native_descriptor,- asio::error_code& ec)- {- return descriptor_service_.assign(impl, native_descriptor, ec);- }-- // Determine whether the serial port is open.- bool is_open(const implementation_type& impl) const- {- return descriptor_service_.is_open(impl);- }-- // Destroy a serial port implementation.- asio::error_code close(implementation_type& impl,- asio::error_code& ec)- {- return descriptor_service_.close(impl, ec);- }-- // Get the native serial port representation.- native_handle_type native_handle(implementation_type& impl)- {- return descriptor_service_.native_handle(impl);- }-- // Cancel all operations associated with the serial port.- asio::error_code cancel(implementation_type& impl,- asio::error_code& ec)- {- return descriptor_service_.cancel(impl, ec);- }-- // Set an option on the serial port.- template <typename SettableSerialPortOption>- asio::error_code set_option(implementation_type& impl,- const SettableSerialPortOption& option, asio::error_code& ec)- {- return do_set_option(impl,- &reactive_serial_port_service::store_option<SettableSerialPortOption>,- &option, ec);- }-- // Get an option from the serial port.- template <typename GettableSerialPortOption>- asio::error_code get_option(const implementation_type& impl,- GettableSerialPortOption& option, asio::error_code& ec) const- {- return do_get_option(impl,- &reactive_serial_port_service::load_option<GettableSerialPortOption>,- &option, ec);- }-- // Send a break sequence to the serial port.- asio::error_code send_break(implementation_type& impl,- asio::error_code& ec)- {- int result = ::tcsendbreak(descriptor_service_.native_handle(impl), 0);- descriptor_ops::get_last_error(ec, result < 0);- return ec;- }-- // Write the given data. Returns the number of bytes sent.- template <typename ConstBufferSequence>- size_t write_some(implementation_type& impl,- const ConstBufferSequence& buffers, asio::error_code& ec)- {- return descriptor_service_.write_some(impl, buffers, ec);- }-- // Start an asynchronous write. The data being written must be valid for the- // lifetime of the asynchronous operation.- template <typename ConstBufferSequence, typename Handler, typename IoExecutor>- void async_write_some(implementation_type& impl,- const ConstBufferSequence& buffers,- Handler& handler, const IoExecutor& io_ex)- {- descriptor_service_.async_write_some(impl, buffers, handler, io_ex);- }-- // Read some data. Returns the number of bytes received.- template <typename MutableBufferSequence>- size_t read_some(implementation_type& impl,- const MutableBufferSequence& buffers, asio::error_code& ec)- {- return descriptor_service_.read_some(impl, buffers, ec);- }-- // Start an asynchronous read. The buffer for the data being received must be- // valid for the lifetime of the asynchronous operation.- template <typename MutableBufferSequence,- typename Handler, typename IoExecutor>- void async_read_some(implementation_type& impl,- const MutableBufferSequence& buffers,- Handler& handler, const IoExecutor& io_ex)- {- descriptor_service_.async_read_some(impl, buffers, handler, io_ex);- }--private:- // Function pointer type for storing a serial port option.- typedef asio::error_code (*store_function_type)(- const void*, termios&, asio::error_code&);-- // Helper function template to store a serial port option.- template <typename SettableSerialPortOption>- static asio::error_code store_option(const void* option,- termios& storage, asio::error_code& ec)- {- static_cast<const SettableSerialPortOption*>(option)->store(storage, ec);- return ec;- }-- // Helper function to set a serial port option.- ASIO_DECL asio::error_code do_set_option(- implementation_type& impl, store_function_type store,- const void* option, asio::error_code& ec);-- // Function pointer type for loading a serial port option.- typedef asio::error_code (*load_function_type)(- void*, const termios&, asio::error_code&);-- // Helper function template to load a serial port option.- template <typename GettableSerialPortOption>- static asio::error_code load_option(void* option,- const termios& storage, asio::error_code& ec)- {- static_cast<GettableSerialPortOption*>(option)->load(storage, ec);- return ec;- }-- // Helper function to get a serial port option.- ASIO_DECL asio::error_code do_get_option(- const implementation_type& impl, load_function_type load,- void* option, asio::error_code& ec) const;-- // The implementation used for initiating asynchronous operations.- reactive_descriptor_service descriptor_service_;-};--} // namespace detail-} // namespace asio--#include "asio/detail/pop_options.hpp"--#if defined(ASIO_HEADER_ONLY)-# include "asio/detail/impl/reactive_serial_port_service.ipp"-#endif // defined(ASIO_HEADER_ONLY)--#endif // !defined(ASIO_WINDOWS) && !defined(__CYGWIN__)-#endif // defined(ASIO_HAS_SERIAL_PORT)--#endif // ASIO_DETAIL_REACTIVE_SERIAL_PORT_SERVICE_HPP
link/modules/asio-standalone/asio/include/asio/detail/reactive_socket_accept_op.hpp view
@@ -2,7 +2,7 @@ // detail/reactive_socket_accept_op.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -52,6 +52,7 @@ static status do_perform(reactor_op* base) {+ ASIO_ASSUME(base != 0); reactive_socket_accept_op_base* o( static_cast<reactive_socket_accept_op_base*>(base)); @@ -95,6 +96,9 @@ public reactive_socket_accept_op_base<Socket, Protocol> { public:+ typedef Handler handler_type;+ typedef IoExecutor io_executor_type;+ ASIO_DEFINE_HANDLER_PTR(reactive_socket_accept_op); reactive_socket_accept_op(const asio::error_code& success_ec,@@ -114,6 +118,7 @@ std::size_t /*bytes_transferred*/) { // Take ownership of the handler object.+ ASIO_ASSUME(base != 0); reactive_socket_accept_op* o(static_cast<reactive_socket_accept_op*>(base)); ptr p = { asio::detail::addressof(o->handler_), o, o }; @@ -128,6 +133,8 @@ ASIO_MOVE_CAST2(handler_work<Handler, IoExecutor>)( o->work_)); + ASIO_ERROR_LOCATION(o->ec_);+ // Make a copy of the handler so that the memory can be deallocated before // the upcall is made. Even if we're not about to make an upcall, a // sub-object of the handler may be the true owner of the memory associated@@ -149,6 +156,41 @@ } } + static void do_immediate(operation* base, bool, const void* io_ex)+ {+ // Take ownership of the handler object.+ ASIO_ASSUME(base != 0);+ reactive_socket_accept_op* o(static_cast<reactive_socket_accept_op*>(base));+ ptr p = { asio::detail::addressof(o->handler_), o, o };++ // On success, assign new connection to peer socket object.+ o->do_assign();++ ASIO_HANDLER_COMPLETION((*o));++ // Take ownership of the operation's outstanding work.+ immediate_handler_work<Handler, IoExecutor> w(+ ASIO_MOVE_CAST2(handler_work<Handler, IoExecutor>)(+ o->work_));++ ASIO_ERROR_LOCATION(o->ec_);++ // Make a copy of the handler so that the memory can be deallocated before+ // the upcall is made. Even if we're not about to make an upcall, a+ // sub-object of the handler may be the true owner of the memory associated+ // with the handler. Consequently, a local copy of the handler is required+ // to ensure that any owning sub-object remains valid until after we have+ // deallocated the memory here.+ detail::binder1<Handler, asio::error_code>+ handler(o->handler_, o->ec_);+ p.h = asio::detail::addressof(handler.handler_);+ p.reset();++ ASIO_HANDLER_INVOCATION_BEGIN((handler.arg1_));+ w.complete(handler, handler.handler_, io_ex);+ ASIO_HANDLER_INVOCATION_END;+ }+ private: Handler handler_; handler_work<Handler, IoExecutor> work_;@@ -165,6 +207,9 @@ Protocol> { public:+ typedef Handler handler_type;+ typedef IoExecutor io_executor_type;+ ASIO_DEFINE_HANDLER_PTR(reactive_socket_move_accept_op); reactive_socket_move_accept_op(const asio::error_code& success_ec,@@ -186,6 +231,7 @@ std::size_t /*bytes_transferred*/) { // Take ownership of the handler object.+ ASIO_ASSUME(base != 0); reactive_socket_move_accept_op* o( static_cast<reactive_socket_move_accept_op*>(base)); ptr p = { asio::detail::addressof(o->handler_), o, o };@@ -201,6 +247,8 @@ ASIO_MOVE_CAST2(handler_work<Handler, IoExecutor>)( o->work_)); + ASIO_ERROR_LOCATION(o->ec_);+ // Make a copy of the handler so that the memory can be deallocated before // the upcall is made. Even if we're not about to make an upcall, a // sub-object of the handler may be the true owner of the memory associated@@ -222,6 +270,44 @@ w.complete(handler, handler.handler_); ASIO_HANDLER_INVOCATION_END; }+ }++ static void do_immediate(operation* base, bool, const void* io_ex)+ {+ // Take ownership of the handler object.+ ASIO_ASSUME(base != 0);+ reactive_socket_move_accept_op* o(+ static_cast<reactive_socket_move_accept_op*>(base));+ ptr p = { asio::detail::addressof(o->handler_), o, o };++ // On success, assign new connection to peer socket object.+ o->do_assign();++ ASIO_HANDLER_COMPLETION((*o));++ // Take ownership of the operation's outstanding work.+ immediate_handler_work<Handler, IoExecutor> w(+ ASIO_MOVE_CAST2(handler_work<Handler, IoExecutor>)(+ o->work_));++ ASIO_ERROR_LOCATION(o->ec_);++ // Make a copy of the handler so that the memory can be deallocated before+ // the upcall is made. Even if we're not about to make an upcall, a+ // sub-object of the handler may be the true owner of the memory associated+ // with the handler. Consequently, a local copy of the handler is required+ // to ensure that any owning sub-object remains valid until after we have+ // deallocated the memory here.+ detail::move_binder2<Handler,+ asio::error_code, peer_socket_type>+ handler(0, ASIO_MOVE_CAST(Handler)(o->handler_), o->ec_,+ ASIO_MOVE_CAST(peer_socket_type)(*o));+ p.h = asio::detail::addressof(handler.handler_);+ p.reset();++ ASIO_HANDLER_INVOCATION_BEGIN((handler.arg1_, "..."));+ w.complete(handler, handler.handler_, io_ex);+ ASIO_HANDLER_INVOCATION_END; } private:
link/modules/asio-standalone/asio/include/asio/detail/reactive_socket_connect_op.hpp view
@@ -2,7 +2,7 @@ // detail/reactive_socket_connect_op.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -43,6 +43,7 @@ static status do_perform(reactor_op* base) {+ ASIO_ASSUME(base != 0); reactive_socket_connect_op_base* o( static_cast<reactive_socket_connect_op_base*>(base)); @@ -62,6 +63,9 @@ class reactive_socket_connect_op : public reactive_socket_connect_op_base { public:+ typedef Handler handler_type;+ typedef IoExecutor io_executor_type;+ ASIO_DEFINE_HANDLER_PTR(reactive_socket_connect_op); reactive_socket_connect_op(const asio::error_code& success_ec,@@ -78,6 +82,7 @@ std::size_t /*bytes_transferred*/) { // Take ownership of the handler object.+ ASIO_ASSUME(base != 0); reactive_socket_connect_op* o (static_cast<reactive_socket_connect_op*>(base)); ptr p = { asio::detail::addressof(o->handler_), o, o };@@ -89,6 +94,8 @@ ASIO_MOVE_CAST2(handler_work<Handler, IoExecutor>)( o->work_)); + ASIO_ERROR_LOCATION(o->ec_);+ // Make a copy of the handler so that the memory can be deallocated before // the upcall is made. Even if we're not about to make an upcall, a // sub-object of the handler may be the true owner of the memory associated@@ -108,6 +115,39 @@ w.complete(handler, handler.handler_); ASIO_HANDLER_INVOCATION_END; }+ }++ static void do_immediate(operation* base, bool, const void* io_ex)+ {+ // Take ownership of the handler object.+ ASIO_ASSUME(base != 0);+ reactive_socket_connect_op* o+ (static_cast<reactive_socket_connect_op*>(base));+ ptr p = { asio::detail::addressof(o->handler_), o, o };++ ASIO_HANDLER_COMPLETION((*o));++ // Take ownership of the operation's outstanding work.+ immediate_handler_work<Handler, IoExecutor> w(+ ASIO_MOVE_CAST2(handler_work<Handler, IoExecutor>)(+ o->work_));++ ASIO_ERROR_LOCATION(o->ec_);++ // Make a copy of the handler so that the memory can be deallocated before+ // the upcall is made. Even if we're not about to make an upcall, a+ // sub-object of the handler may be the true owner of the memory associated+ // with the handler. Consequently, a local copy of the handler is required+ // to ensure that any owning sub-object remains valid until after we have+ // deallocated the memory here.+ detail::binder1<Handler, asio::error_code>+ handler(o->handler_, o->ec_);+ p.h = asio::detail::addressof(handler.handler_);+ p.reset();++ ASIO_HANDLER_INVOCATION_BEGIN((handler.arg1_));+ w.complete(handler, handler.handler_, io_ex);+ ASIO_HANDLER_INVOCATION_END; } private:
link/modules/asio-standalone/asio/include/asio/detail/reactive_socket_recv_op.hpp view
@@ -2,7 +2,7 @@ // detail/reactive_socket_recv_op.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -50,6 +50,7 @@ static status do_perform(reactor_op* base) {+ ASIO_ASSUME(base != 0); reactive_socket_recv_op_base* o( static_cast<reactive_socket_recv_op_base*>(base)); @@ -97,6 +98,9 @@ public reactive_socket_recv_op_base<MutableBufferSequence> { public:+ typedef Handler handler_type;+ typedef IoExecutor io_executor_type;+ ASIO_DEFINE_HANDLER_PTR(reactive_socket_recv_op); reactive_socket_recv_op(const asio::error_code& success_ec,@@ -115,6 +119,7 @@ std::size_t /*bytes_transferred*/) { // Take ownership of the handler object.+ ASIO_ASSUME(base != 0); reactive_socket_recv_op* o(static_cast<reactive_socket_recv_op*>(base)); ptr p = { asio::detail::addressof(o->handler_), o, o }; @@ -125,6 +130,8 @@ ASIO_MOVE_CAST2(handler_work<Handler, IoExecutor>)( o->work_)); + ASIO_ERROR_LOCATION(o->ec_);+ // Make a copy of the handler so that the memory can be deallocated before // the upcall is made. Even if we're not about to make an upcall, a // sub-object of the handler may be the true owner of the memory associated@@ -144,6 +151,38 @@ w.complete(handler, handler.handler_); ASIO_HANDLER_INVOCATION_END; }+ }++ static void do_immediate(operation* base, bool, const void* io_ex)+ {+ // Take ownership of the handler object.+ ASIO_ASSUME(base != 0);+ reactive_socket_recv_op* o(static_cast<reactive_socket_recv_op*>(base));+ ptr p = { asio::detail::addressof(o->handler_), o, o };++ ASIO_HANDLER_COMPLETION((*o));++ // Take ownership of the operation's outstanding work.+ immediate_handler_work<Handler, IoExecutor> w(+ ASIO_MOVE_CAST2(handler_work<Handler, IoExecutor>)(+ o->work_));++ ASIO_ERROR_LOCATION(o->ec_);++ // Make a copy of the handler so that the memory can be deallocated before+ // the upcall is made. Even if we're not about to make an upcall, a+ // sub-object of the handler may be the true owner of the memory associated+ // with the handler. Consequently, a local copy of the handler is required+ // to ensure that any owning sub-object remains valid until after we have+ // deallocated the memory here.+ detail::binder2<Handler, asio::error_code, std::size_t>+ handler(o->handler_, o->ec_, o->bytes_transferred_);+ p.h = asio::detail::addressof(handler.handler_);+ p.reset();++ ASIO_HANDLER_INVOCATION_BEGIN((handler.arg1_, handler.arg2_));+ w.complete(handler, handler.handler_, io_ex);+ ASIO_HANDLER_INVOCATION_END; } private:
link/modules/asio-standalone/asio/include/asio/detail/reactive_socket_recvfrom_op.hpp view
@@ -2,7 +2,7 @@ // detail/reactive_socket_recvfrom_op.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -51,6 +51,7 @@ static status do_perform(reactor_op* base) {+ ASIO_ASSUME(base != 0); reactive_socket_recvfrom_op_base* o( static_cast<reactive_socket_recvfrom_op_base*>(base)); @@ -99,6 +100,9 @@ public reactive_socket_recvfrom_op_base<MutableBufferSequence, Endpoint> { public:+ typedef Handler handler_type;+ typedef IoExecutor io_executor_type;+ ASIO_DEFINE_HANDLER_PTR(reactive_socket_recvfrom_op); reactive_socket_recvfrom_op(const asio::error_code& success_ec,@@ -119,6 +123,7 @@ std::size_t /*bytes_transferred*/) { // Take ownership of the handler object.+ ASIO_ASSUME(base != 0); reactive_socket_recvfrom_op* o( static_cast<reactive_socket_recvfrom_op*>(base)); ptr p = { asio::detail::addressof(o->handler_), o, o };@@ -130,6 +135,8 @@ ASIO_MOVE_CAST2(handler_work<Handler, IoExecutor>)( o->work_)); + ASIO_ERROR_LOCATION(o->ec_);+ // Make a copy of the handler so that the memory can be deallocated before // the upcall is made. Even if we're not about to make an upcall, a // sub-object of the handler may be the true owner of the memory associated@@ -149,6 +156,39 @@ w.complete(handler, handler.handler_); ASIO_HANDLER_INVOCATION_END; }+ }++ static void do_immediate(operation* base, bool, const void* io_ex)+ {+ // Take ownership of the handler object.+ ASIO_ASSUME(base != 0);+ reactive_socket_recvfrom_op* o(+ static_cast<reactive_socket_recvfrom_op*>(base));+ ptr p = { asio::detail::addressof(o->handler_), o, o };++ ASIO_HANDLER_COMPLETION((*o));++ // Take ownership of the operation's outstanding work.+ immediate_handler_work<Handler, IoExecutor> w(+ ASIO_MOVE_CAST2(handler_work<Handler, IoExecutor>)(+ o->work_));++ ASIO_ERROR_LOCATION(o->ec_);++ // Make a copy of the handler so that the memory can be deallocated before+ // the upcall is made. Even if we're not about to make an upcall, a+ // sub-object of the handler may be the true owner of the memory associated+ // with the handler. Consequently, a local copy of the handler is required+ // to ensure that any owning sub-object remains valid until after we have+ // deallocated the memory here.+ detail::binder2<Handler, asio::error_code, std::size_t>+ handler(o->handler_, o->ec_, o->bytes_transferred_);+ p.h = asio::detail::addressof(handler.handler_);+ p.reset();++ ASIO_HANDLER_INVOCATION_BEGIN((handler.arg1_, handler.arg2_));+ w.complete(handler, handler.handler_, io_ex);+ ASIO_HANDLER_INVOCATION_END; } private:
link/modules/asio-standalone/asio/include/asio/detail/reactive_socket_recvmsg_op.hpp view
@@ -2,7 +2,7 @@ // detail/reactive_socket_recvmsg_op.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -51,6 +51,7 @@ static status do_perform(reactor_op* base) {+ ASIO_ASSUME(base != 0); reactive_socket_recvmsg_op_base* o( static_cast<reactive_socket_recvmsg_op_base*>(base)); @@ -80,6 +81,9 @@ public reactive_socket_recvmsg_op_base<MutableBufferSequence> { public:+ typedef Handler handler_type;+ typedef IoExecutor io_executor_type;+ ASIO_DEFINE_HANDLER_PTR(reactive_socket_recvmsg_op); reactive_socket_recvmsg_op(const asio::error_code& success_ec,@@ -100,6 +104,7 @@ std::size_t /*bytes_transferred*/) { // Take ownership of the handler object.+ ASIO_ASSUME(base != 0); reactive_socket_recvmsg_op* o( static_cast<reactive_socket_recvmsg_op*>(base)); ptr p = { asio::detail::addressof(o->handler_), o, o };@@ -111,6 +116,8 @@ ASIO_MOVE_CAST2(handler_work<Handler, IoExecutor>)( o->work_)); + ASIO_ERROR_LOCATION(o->ec_);+ // Make a copy of the handler so that the memory can be deallocated before // the upcall is made. Even if we're not about to make an upcall, a // sub-object of the handler may be the true owner of the memory associated@@ -130,6 +137,39 @@ w.complete(handler, handler.handler_); ASIO_HANDLER_INVOCATION_END; }+ }++ static void do_immediate(operation* base, bool, const void* io_ex)+ {+ // Take ownership of the handler object.+ ASIO_ASSUME(base != 0);+ reactive_socket_recvmsg_op* o(+ static_cast<reactive_socket_recvmsg_op*>(base));+ ptr p = { asio::detail::addressof(o->handler_), o, o };++ ASIO_HANDLER_COMPLETION((*o));++ // Take ownership of the operation's outstanding work.+ immediate_handler_work<Handler, IoExecutor> w(+ ASIO_MOVE_CAST2(handler_work<Handler, IoExecutor>)(+ o->work_));++ ASIO_ERROR_LOCATION(o->ec_);++ // Make a copy of the handler so that the memory can be deallocated before+ // the upcall is made. Even if we're not about to make an upcall, a+ // sub-object of the handler may be the true owner of the memory associated+ // with the handler. Consequently, a local copy of the handler is required+ // to ensure that any owning sub-object remains valid until after we have+ // deallocated the memory here.+ detail::binder2<Handler, asio::error_code, std::size_t>+ handler(o->handler_, o->ec_, o->bytes_transferred_);+ p.h = asio::detail::addressof(handler.handler_);+ p.reset();++ ASIO_HANDLER_INVOCATION_BEGIN((handler.arg1_, handler.arg2_));+ w.complete(handler, handler.handler_, io_ex);+ ASIO_HANDLER_INVOCATION_END; } private:
link/modules/asio-standalone/asio/include/asio/detail/reactive_socket_send_op.hpp view
@@ -2,7 +2,7 @@ // detail/reactive_socket_send_op.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -50,6 +50,7 @@ static status do_perform(reactor_op* base) {+ ASIO_ASSUME(base != 0); reactive_socket_send_op_base* o( static_cast<reactive_socket_send_op_base*>(base)); @@ -100,6 +101,9 @@ public reactive_socket_send_op_base<ConstBufferSequence> { public:+ typedef Handler handler_type;+ typedef IoExecutor io_executor_type;+ ASIO_DEFINE_HANDLER_PTR(reactive_socket_send_op); reactive_socket_send_op(const asio::error_code& success_ec,@@ -118,6 +122,7 @@ std::size_t /*bytes_transferred*/) { // Take ownership of the handler object.+ ASIO_ASSUME(base != 0); reactive_socket_send_op* o(static_cast<reactive_socket_send_op*>(base)); ptr p = { asio::detail::addressof(o->handler_), o, o }; @@ -128,6 +133,8 @@ ASIO_MOVE_CAST2(handler_work<Handler, IoExecutor>)( o->work_)); + ASIO_ERROR_LOCATION(o->ec_);+ // Make a copy of the handler so that the memory can be deallocated before // the upcall is made. Even if we're not about to make an upcall, a // sub-object of the handler may be the true owner of the memory associated@@ -148,6 +155,39 @@ ASIO_HANDLER_INVOCATION_END; } }++ static void do_immediate(operation* base, bool, const void* io_ex)+ {+ // Take ownership of the handler object.+ ASIO_ASSUME(base != 0);+ reactive_socket_send_op* o(static_cast<reactive_socket_send_op*>(base));+ ptr p = { asio::detail::addressof(o->handler_), o, o };++ ASIO_HANDLER_COMPLETION((*o));++ // Take ownership of the operation's outstanding work.+ immediate_handler_work<Handler, IoExecutor> w(+ ASIO_MOVE_CAST2(handler_work<Handler, IoExecutor>)(+ o->work_));++ ASIO_ERROR_LOCATION(o->ec_);++ // Make a copy of the handler so that the memory can be deallocated before+ // the upcall is made. Even if we're not about to make an upcall, a+ // sub-object of the handler may be the true owner of the memory associated+ // with the handler. Consequently, a local copy of the handler is required+ // to ensure that any owning sub-object remains valid until after we have+ // deallocated the memory here.+ detail::binder2<Handler, asio::error_code, std::size_t>+ handler(o->handler_, o->ec_, o->bytes_transferred_);+ p.h = asio::detail::addressof(handler.handler_);+ p.reset();++ ASIO_HANDLER_INVOCATION_BEGIN((handler.arg1_, handler.arg2_));+ w.complete(handler, handler.handler_, io_ex);+ ASIO_HANDLER_INVOCATION_END;+ }+ private: Handler handler_;
link/modules/asio-standalone/asio/include/asio/detail/reactive_socket_sendto_op.hpp view
@@ -2,7 +2,7 @@ // detail/reactive_socket_sendto_op.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -50,6 +50,7 @@ static status do_perform(reactor_op* base) {+ ASIO_ASSUME(base != 0); reactive_socket_sendto_op_base* o( static_cast<reactive_socket_sendto_op_base*>(base)); @@ -93,6 +94,9 @@ public reactive_socket_sendto_op_base<ConstBufferSequence, Endpoint> { public:+ typedef Handler handler_type;+ typedef IoExecutor io_executor_type;+ ASIO_DEFINE_HANDLER_PTR(reactive_socket_sendto_op); reactive_socket_sendto_op(const asio::error_code& success_ec,@@ -112,6 +116,7 @@ std::size_t /*bytes_transferred*/) { // Take ownership of the handler object.+ ASIO_ASSUME(base != 0); reactive_socket_sendto_op* o(static_cast<reactive_socket_sendto_op*>(base)); ptr p = { asio::detail::addressof(o->handler_), o, o }; @@ -122,6 +127,8 @@ ASIO_MOVE_CAST2(handler_work<Handler, IoExecutor>)( o->work_)); + ASIO_ERROR_LOCATION(o->ec_);+ // Make a copy of the handler so that the memory can be deallocated before // the upcall is made. Even if we're not about to make an upcall, a // sub-object of the handler may be the true owner of the memory associated@@ -141,6 +148,38 @@ w.complete(handler, handler.handler_); ASIO_HANDLER_INVOCATION_END; }+ }++ static void do_immediate(operation* base, bool, const void* io_ex)+ {+ // Take ownership of the handler object.+ ASIO_ASSUME(base != 0);+ reactive_socket_sendto_op* o(static_cast<reactive_socket_sendto_op*>(base));+ ptr p = { asio::detail::addressof(o->handler_), o, o };++ ASIO_HANDLER_COMPLETION((*o));++ // Take ownership of the operation's outstanding work.+ immediate_handler_work<Handler, IoExecutor> w(+ ASIO_MOVE_CAST2(handler_work<Handler, IoExecutor>)(+ o->work_));++ ASIO_ERROR_LOCATION(o->ec_);++ // Make a copy of the handler so that the memory can be deallocated before+ // the upcall is made. Even if we're not about to make an upcall, a+ // sub-object of the handler may be the true owner of the memory associated+ // with the handler. Consequently, a local copy of the handler is required+ // to ensure that any owning sub-object remains valid until after we have+ // deallocated the memory here.+ detail::binder2<Handler, asio::error_code, std::size_t>+ handler(o->handler_, o->ec_, o->bytes_transferred_);+ p.h = asio::detail::addressof(handler.handler_);+ p.reset();++ ASIO_HANDLER_INVOCATION_BEGIN((handler.arg1_, handler.arg2_));+ w.complete(handler, handler.handler_, io_ex);+ ASIO_HANDLER_INVOCATION_END; } private:
link/modules/asio-standalone/asio/include/asio/detail/reactive_socket_service.hpp view
@@ -2,7 +2,7 @@ // detail/reactive_socket_service.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -17,7 +17,8 @@ #include "asio/detail/config.hpp" -#if !defined(ASIO_HAS_IOCP)+#if !defined(ASIO_HAS_IOCP) \+ && !defined(ASIO_HAS_IO_URING_AS_DEFAULT) #include "asio/buffer.hpp" #include "asio/error.hpp"@@ -127,6 +128,8 @@ if (!do_open(impl, protocol.family(), protocol.type(), protocol.protocol(), ec)) impl.protocol_ = protocol;++ ASIO_ERROR_LOCATION(ec); return ec; } @@ -137,6 +140,8 @@ { if (!do_assign(impl, protocol.type(), native_socket, ec)) impl.protocol_ = protocol;++ ASIO_ERROR_LOCATION(ec); return ec; } @@ -151,6 +156,8 @@ const endpoint_type& endpoint, asio::error_code& ec) { socket_ops::bind(impl.socket_, endpoint.data(), endpoint.size(), ec);++ ASIO_ERROR_LOCATION(ec); return ec; } @@ -162,6 +169,8 @@ socket_ops::setsockopt(impl.socket_, impl.state_, option.level(impl.protocol_), option.name(impl.protocol_), option.data(impl.protocol_), option.size(impl.protocol_), ec);++ ASIO_ERROR_LOCATION(ec); return ec; } @@ -176,6 +185,8 @@ option.data(impl.protocol_), &size, ec); if (!ec) option.resize(impl.protocol_, size);++ ASIO_ERROR_LOCATION(ec); return ec; } @@ -186,7 +197,10 @@ endpoint_type endpoint; std::size_t addr_len = endpoint.capacity(); if (socket_ops::getsockname(impl.socket_, endpoint.data(), &addr_len, ec))+ {+ ASIO_ERROR_LOCATION(ec); return endpoint_type();+ } endpoint.resize(addr_len); return endpoint; }@@ -199,7 +213,10 @@ std::size_t addr_len = endpoint.capacity(); if (socket_ops::getpeername(impl.socket_, endpoint.data(), &addr_len, false, ec))+ {+ ASIO_ERROR_LOCATION(ec); return endpoint_type();+ } endpoint.resize(addr_len); return endpoint; }@@ -209,6 +226,8 @@ socket_base::shutdown_type what, asio::error_code& ec) { socket_ops::shutdown(impl.socket_, what, ec);++ ASIO_ERROR_LOCATION(ec); return ec; } @@ -222,9 +241,10 @@ typedef buffer_sequence_adapter<asio::const_buffer, ConstBufferSequence> bufs_type; + size_t n; if (bufs_type::is_single_buffer) {- return socket_ops::sync_sendto1(impl.socket_, impl.state_,+ n = socket_ops::sync_sendto1(impl.socket_, impl.state_, bufs_type::first(buffers).data(), bufs_type::first(buffers).size(), flags, destination.data(), destination.size(), ec);@@ -232,10 +252,13 @@ else { bufs_type bufs(buffers);- return socket_ops::sync_sendto(impl.socket_, impl.state_,+ n = socket_ops::sync_sendto(impl.socket_, impl.state_, bufs.buffers(), bufs.count(), flags, destination.data(), destination.size(), ec); }++ ASIO_ERROR_LOCATION(ec);+ return n; } // Wait until data can be sent without blocking.@@ -246,6 +269,7 @@ // Wait for socket to become ready. socket_ops::poll_write(impl.socket_, impl.state_, -1, ec); + ASIO_ERROR_LOCATION(ec); return 0; } @@ -260,6 +284,9 @@ bool is_continuation = asio_handler_cont_helpers::is_continuation(handler); + typename associated_cancellation_slot<Handler>::type slot+ = asio::get_associated_cancellation_slot(handler);+ // Allocate and construct an operation to wrap the handler. typedef reactive_socket_sendto_op<ConstBufferSequence, endpoint_type, Handler, IoExecutor> op;@@ -268,10 +295,19 @@ p.p = new (p.v) op(success_ec_, impl.socket_, buffers, destination, flags, handler, io_ex); + // Optionally register for per-operation cancellation.+ if (slot.is_connected())+ {+ p.p->cancellation_key_ =+ &slot.template emplace<reactor_op_cancellation>(+ &reactor_, &impl.reactor_data_, impl.socket_, reactor::write_op);+ }+ ASIO_HANDLER_CREATION((reactor_.context(), *p.p, "socket", &impl, impl.socket_, "async_send_to")); - start_op(impl, reactor::write_op, p.p, is_continuation, true, false);+ start_op(impl, reactor::write_op, p.p,+ is_continuation, true, false, &io_ex, 0); p.v = p.p = 0; } @@ -284,16 +320,28 @@ bool is_continuation = asio_handler_cont_helpers::is_continuation(handler); + typename associated_cancellation_slot<Handler>::type slot+ = asio::get_associated_cancellation_slot(handler);+ // Allocate and construct an operation to wrap the handler. typedef reactive_null_buffers_op<Handler, IoExecutor> op; typename op::ptr p = { asio::detail::addressof(handler), op::ptr::allocate(handler), 0 }; p.p = new (p.v) op(success_ec_, handler, io_ex); + // Optionally register for per-operation cancellation.+ if (slot.is_connected())+ {+ p.p->cancellation_key_ =+ &slot.template emplace<reactor_op_cancellation>(+ &reactor_, &impl.reactor_data_, impl.socket_, reactor::write_op);+ }+ ASIO_HANDLER_CREATION((reactor_.context(), *p.p, "socket", &impl, impl.socket_, "async_send_to(null_buffers)")); - start_op(impl, reactor::write_op, p.p, is_continuation, false, false);+ start_op(impl, reactor::write_op, p.p,+ is_continuation, false, false, &io_ex, 0); p.v = p.p = 0; } @@ -309,26 +357,25 @@ MutableBufferSequence> bufs_type; std::size_t addr_len = sender_endpoint.capacity();- std::size_t bytes_recvd;+ std::size_t n; if (bufs_type::is_single_buffer) {- bytes_recvd = socket_ops::sync_recvfrom1(impl.socket_,- impl.state_, bufs_type::first(buffers).data(),- bufs_type::first(buffers).size(), flags,- sender_endpoint.data(), &addr_len, ec);+ n = socket_ops::sync_recvfrom1(impl.socket_, impl.state_,+ bufs_type::first(buffers).data(), bufs_type::first(buffers).size(),+ flags, sender_endpoint.data(), &addr_len, ec); } else { bufs_type bufs(buffers);- bytes_recvd = socket_ops::sync_recvfrom(- impl.socket_, impl.state_, bufs.buffers(), bufs.count(),- flags, sender_endpoint.data(), &addr_len, ec);+ n = socket_ops::sync_recvfrom(impl.socket_, impl.state_, bufs.buffers(),+ bufs.count(), flags, sender_endpoint.data(), &addr_len, ec); } if (!ec) sender_endpoint.resize(addr_len); - return bytes_recvd;+ ASIO_ERROR_LOCATION(ec);+ return n; } // Wait until data can be received without blocking.@@ -342,6 +389,7 @@ // Reset endpoint since it can be given no sensible value at this time. sender_endpoint = endpoint_type(); + ASIO_ERROR_LOCATION(ec); return 0; } @@ -358,6 +406,9 @@ bool is_continuation = asio_handler_cont_helpers::is_continuation(handler); + typename associated_cancellation_slot<Handler>::type slot+ = asio::get_associated_cancellation_slot(handler);+ // Allocate and construct an operation to wrap the handler. typedef reactive_socket_recvfrom_op<MutableBufferSequence, endpoint_type, Handler, IoExecutor> op;@@ -367,13 +418,21 @@ p.p = new (p.v) op(success_ec_, impl.socket_, protocol, buffers, sender_endpoint, flags, handler, io_ex); + // Optionally register for per-operation cancellation.+ if (slot.is_connected())+ {+ p.p->cancellation_key_ =+ &slot.template emplace<reactor_op_cancellation>(+ &reactor_, &impl.reactor_data_, impl.socket_, reactor::read_op);+ }+ ASIO_HANDLER_CREATION((reactor_.context(), *p.p, "socket", &impl, impl.socket_, "async_receive_from")); start_op(impl, (flags & socket_base::message_out_of_band) ? reactor::except_op : reactor::read_op,- p.p, is_continuation, true, false);+ p.p, is_continuation, true, false, &io_ex, 0); p.v = p.p = 0; } @@ -386,12 +445,23 @@ bool is_continuation = asio_handler_cont_helpers::is_continuation(handler); + typename associated_cancellation_slot<Handler>::type slot+ = asio::get_associated_cancellation_slot(handler);+ // Allocate and construct an operation to wrap the handler. typedef reactive_null_buffers_op<Handler, IoExecutor> op; typename op::ptr p = { asio::detail::addressof(handler), op::ptr::allocate(handler), 0 }; p.p = new (p.v) op(success_ec_, handler, io_ex); + // Optionally register for per-operation cancellation.+ if (slot.is_connected())+ {+ p.p->cancellation_key_ =+ &slot.template emplace<reactor_op_cancellation>(+ &reactor_, &impl.reactor_data_, impl.socket_, reactor::read_op);+ }+ ASIO_HANDLER_CREATION((reactor_.context(), *p.p, "socket", &impl, impl.socket_, "async_receive_from(null_buffers)")); @@ -401,7 +471,7 @@ start_op(impl, (flags & socket_base::message_out_of_band) ? reactor::except_op : reactor::read_op,- p.p, is_continuation, false, false);+ p.p, is_continuation, false, false, &io_ex, 0); p.v = p.p = 0; } @@ -414,6 +484,7 @@ if (peer.is_open()) { ec = asio::error::already_open;+ ASIO_ERROR_LOCATION(ec); return ec; } @@ -432,6 +503,7 @@ new_socket.release(); } + ASIO_ERROR_LOCATION(ec); return ec; } @@ -444,6 +516,9 @@ bool is_continuation = asio_handler_cont_helpers::is_continuation(handler); + typename associated_cancellation_slot<Handler>::type slot+ = asio::get_associated_cancellation_slot(handler);+ // Allocate and construct an operation to wrap the handler. typedef reactive_socket_accept_op<Socket, Protocol, Handler, IoExecutor> op; typename op::ptr p = { asio::detail::addressof(handler),@@ -451,10 +526,18 @@ p.p = new (p.v) op(success_ec_, impl.socket_, impl.state_, peer, impl.protocol_, peer_endpoint, handler, io_ex); + // Optionally register for per-operation cancellation.+ if (slot.is_connected() && !peer.is_open())+ {+ p.p->cancellation_key_ =+ &slot.template emplace<reactor_op_cancellation>(+ &reactor_, &impl.reactor_data_, impl.socket_, reactor::read_op);+ }+ ASIO_HANDLER_CREATION((reactor_.context(), *p.p, "socket", &impl, impl.socket_, "async_accept")); - start_accept_op(impl, p.p, is_continuation, peer.is_open());+ start_accept_op(impl, p.p, is_continuation, peer.is_open(), &io_ex, 0); p.v = p.p = 0; } @@ -469,6 +552,9 @@ bool is_continuation = asio_handler_cont_helpers::is_continuation(handler); + typename associated_cancellation_slot<Handler>::type slot+ = asio::get_associated_cancellation_slot(handler);+ // Allocate and construct an operation to wrap the handler. typedef reactive_socket_move_accept_op<Protocol, PeerIoExecutor, Handler, IoExecutor> op;@@ -477,10 +563,18 @@ p.p = new (p.v) op(success_ec_, peer_io_ex, impl.socket_, impl.state_, impl.protocol_, peer_endpoint, handler, io_ex); + // Optionally register for per-operation cancellation.+ if (slot.is_connected())+ {+ p.p->cancellation_key_ =+ &slot.template emplace<reactor_op_cancellation>(+ &reactor_, &impl.reactor_data_, impl.socket_, reactor::read_op);+ }+ ASIO_HANDLER_CREATION((reactor_.context(), *p.p, "socket", &impl, impl.socket_, "async_accept")); - start_accept_op(impl, p.p, is_continuation, false);+ start_accept_op(impl, p.p, is_continuation, false, &io_ex, 0); p.v = p.p = 0; } #endif // defined(ASIO_HAS_MOVE)@@ -491,6 +585,7 @@ { socket_ops::sync_connect(impl.socket_, peer_endpoint.data(), peer_endpoint.size(), ec);+ ASIO_ERROR_LOCATION(ec); return ec; } @@ -503,17 +598,28 @@ bool is_continuation = asio_handler_cont_helpers::is_continuation(handler); + typename associated_cancellation_slot<Handler>::type slot+ = asio::get_associated_cancellation_slot(handler);+ // Allocate and construct an operation to wrap the handler. typedef reactive_socket_connect_op<Handler, IoExecutor> op; typename op::ptr p = { asio::detail::addressof(handler), op::ptr::allocate(handler), 0 }; p.p = new (p.v) op(success_ec_, impl.socket_, handler, io_ex); + // Optionally register for per-operation cancellation.+ if (slot.is_connected())+ {+ p.p->cancellation_key_ =+ &slot.template emplace<reactor_op_cancellation>(+ &reactor_, &impl.reactor_data_, impl.socket_, reactor::connect_op);+ }+ ASIO_HANDLER_CREATION((reactor_.context(), *p.p, "socket", &impl, impl.socket_, "async_connect")); start_connect_op(impl, p.p, is_continuation,- peer_endpoint.data(), peer_endpoint.size());+ peer_endpoint.data(), peer_endpoint.size(), &io_ex, 0); p.v = p.p = 0; } };@@ -524,5 +630,6 @@ #include "asio/detail/pop_options.hpp" #endif // !defined(ASIO_HAS_IOCP)+ // && !defined(ASIO_HAS_IO_URING_AS_DEFAULT) #endif // ASIO_DETAIL_REACTIVE_SOCKET_SERVICE_HPP
link/modules/asio-standalone/asio/include/asio/detail/reactive_socket_service_base.hpp view
@@ -2,7 +2,7 @@ // detail/reactive_socket_service_base.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -18,9 +18,12 @@ #include "asio/detail/config.hpp" #if !defined(ASIO_HAS_IOCP) \- && !defined(ASIO_WINDOWS_RUNTIME)+ && !defined(ASIO_WINDOWS_RUNTIME) \+ && !defined(ASIO_HAS_IO_URING_AS_DEFAULT) +#include "asio/associated_cancellation_slot.hpp" #include "asio/buffer.hpp"+#include "asio/cancellation_type.hpp" #include "asio/error.hpp" #include "asio/execution_context.hpp" #include "asio/socket_base.hpp"@@ -199,6 +202,9 @@ bool is_continuation = asio_handler_cont_helpers::is_continuation(handler); + typename associated_cancellation_slot<Handler>::type slot+ = asio::get_associated_cancellation_slot(handler);+ // Allocate and construct an operation to wrap the handler. typedef reactive_wait_op<Handler, IoExecutor> op; typename op::ptr p = { asio::detail::addressof(handler),@@ -211,23 +217,32 @@ int op_type; switch (w) {- case socket_base::wait_read:- op_type = reactor::read_op;- break;- case socket_base::wait_write:- op_type = reactor::write_op;- break;- case socket_base::wait_error:- op_type = reactor::except_op;- break;- default:- p.p->ec_ = asio::error::invalid_argument;- reactor_.post_immediate_completion(p.p, is_continuation);- p.v = p.p = 0;- return;+ case socket_base::wait_read:+ op_type = reactor::read_op;+ break;+ case socket_base::wait_write:+ op_type = reactor::write_op;+ break;+ case socket_base::wait_error:+ op_type = reactor::except_op;+ break;+ default:+ p.p->ec_ = asio::error::invalid_argument;+ start_op(impl, reactor::read_op, p.p,+ is_continuation, false, true, &io_ex, 0);+ p.v = p.p = 0;+ return; } - start_op(impl, op_type, p.p, is_continuation, false, false);+ // Optionally register for per-operation cancellation.+ if (slot.is_connected())+ {+ p.p->cancellation_key_ =+ &slot.template emplace<reactor_op_cancellation>(+ &reactor_, &impl.reactor_data_, impl.socket_, op_type);+ }++ start_op(impl, op_type, p.p, is_continuation, false, false, &io_ex, 0); p.v = p.p = 0; } @@ -274,6 +289,9 @@ bool is_continuation = asio_handler_cont_helpers::is_continuation(handler); + typename associated_cancellation_slot<Handler>::type slot+ = asio::get_associated_cancellation_slot(handler);+ // Allocate and construct an operation to wrap the handler. typedef reactive_socket_send_op< ConstBufferSequence, Handler, IoExecutor> op;@@ -282,13 +300,21 @@ p.p = new (p.v) op(success_ec_, impl.socket_, impl.state_, buffers, flags, handler, io_ex); + // Optionally register for per-operation cancellation.+ if (slot.is_connected())+ {+ p.p->cancellation_key_ =+ &slot.template emplace<reactor_op_cancellation>(+ &reactor_, &impl.reactor_data_, impl.socket_, reactor::write_op);+ }+ ASIO_HANDLER_CREATION((reactor_.context(), *p.p, "socket", &impl, impl.socket_, "async_send")); start_op(impl, reactor::write_op, p.p, is_continuation, true, ((impl.state_ & socket_ops::stream_oriented) && buffer_sequence_adapter<asio::const_buffer,- ConstBufferSequence>::all_empty(buffers)));+ ConstBufferSequence>::all_empty(buffers)), &io_ex, 0); p.v = p.p = 0; } @@ -300,16 +326,28 @@ bool is_continuation = asio_handler_cont_helpers::is_continuation(handler); + typename associated_cancellation_slot<Handler>::type slot+ = asio::get_associated_cancellation_slot(handler);+ // Allocate and construct an operation to wrap the handler. typedef reactive_null_buffers_op<Handler, IoExecutor> op; typename op::ptr p = { asio::detail::addressof(handler), op::ptr::allocate(handler), 0 }; p.p = new (p.v) op(success_ec_, handler, io_ex); + // Optionally register for per-operation cancellation.+ if (slot.is_connected())+ {+ p.p->cancellation_key_ =+ &slot.template emplace<reactor_op_cancellation>(+ &reactor_, &impl.reactor_data_, impl.socket_, reactor::write_op);+ }+ ASIO_HANDLER_CREATION((reactor_.context(), *p.p, "socket", &impl, impl.socket_, "async_send(null_buffers)")); - start_op(impl, reactor::write_op, p.p, is_continuation, false, false);+ start_op(impl, reactor::write_op, p.p,+ is_continuation, false, false, &io_ex, 0); p.v = p.p = 0; } @@ -357,6 +395,9 @@ bool is_continuation = asio_handler_cont_helpers::is_continuation(handler); + typename associated_cancellation_slot<Handler>::type slot+ = asio::get_associated_cancellation_slot(handler);+ // Allocate and construct an operation to wrap the handler. typedef reactive_socket_recv_op< MutableBufferSequence, Handler, IoExecutor> op;@@ -365,6 +406,14 @@ p.p = new (p.v) op(success_ec_, impl.socket_, impl.state_, buffers, flags, handler, io_ex); + // Optionally register for per-operation cancellation.+ if (slot.is_connected())+ {+ p.p->cancellation_key_ =+ &slot.template emplace<reactor_op_cancellation>(+ &reactor_, &impl.reactor_data_, impl.socket_, reactor::read_op);+ }+ ASIO_HANDLER_CREATION((reactor_.context(), *p.p, "socket", &impl, impl.socket_, "async_receive")); @@ -375,7 +424,7 @@ (flags & socket_base::message_out_of_band) == 0, ((impl.state_ & socket_ops::stream_oriented) && buffer_sequence_adapter<asio::mutable_buffer,- MutableBufferSequence>::all_empty(buffers)));+ MutableBufferSequence>::all_empty(buffers)), &io_ex, 0); p.v = p.p = 0; } @@ -388,19 +437,30 @@ bool is_continuation = asio_handler_cont_helpers::is_continuation(handler); + typename associated_cancellation_slot<Handler>::type slot+ = asio::get_associated_cancellation_slot(handler);+ // Allocate and construct an operation to wrap the handler. typedef reactive_null_buffers_op<Handler, IoExecutor> op; typename op::ptr p = { asio::detail::addressof(handler), op::ptr::allocate(handler), 0 }; p.p = new (p.v) op(success_ec_, handler, io_ex); + // Optionally register for per-operation cancellation.+ if (slot.is_connected())+ {+ p.p->cancellation_key_ =+ &slot.template emplace<reactor_op_cancellation>(+ &reactor_, &impl.reactor_data_, impl.socket_, reactor::read_op);+ }+ ASIO_HANDLER_CREATION((reactor_.context(), *p.p, "socket", &impl, impl.socket_, "async_receive(null_buffers)")); start_op(impl, (flags & socket_base::message_out_of_band) ? reactor::except_op : reactor::read_op,- p.p, is_continuation, false, false);+ p.p, is_continuation, false, false, &io_ex, 0); p.v = p.p = 0; } @@ -446,6 +506,9 @@ bool is_continuation = asio_handler_cont_helpers::is_continuation(handler); + typename associated_cancellation_slot<Handler>::type slot+ = asio::get_associated_cancellation_slot(handler);+ // Allocate and construct an operation to wrap the handler. typedef reactive_socket_recvmsg_op< MutableBufferSequence, Handler, IoExecutor> op;@@ -454,6 +517,14 @@ p.p = new (p.v) op(success_ec_, impl.socket_, buffers, in_flags, out_flags, handler, io_ex); + // Optionally register for per-operation cancellation.+ if (slot.is_connected())+ {+ p.p->cancellation_key_ =+ &slot.template emplace<reactor_op_cancellation>(+ &reactor_, &impl.reactor_data_, impl.socket_, reactor::read_op);+ }+ ASIO_HANDLER_CREATION((reactor_.context(), *p.p, "socket", &impl, impl.socket_, "async_receive_with_flags")); @@ -461,7 +532,7 @@ (in_flags & socket_base::message_out_of_band) ? reactor::except_op : reactor::read_op, p.p, is_continuation,- (in_flags & socket_base::message_out_of_band) == 0, false);+ (in_flags & socket_base::message_out_of_band) == 0, false, &io_ex, 0); p.v = p.p = 0; } @@ -475,12 +546,23 @@ bool is_continuation = asio_handler_cont_helpers::is_continuation(handler); + typename associated_cancellation_slot<Handler>::type slot+ = asio::get_associated_cancellation_slot(handler);+ // Allocate and construct an operation to wrap the handler. typedef reactive_null_buffers_op<Handler, IoExecutor> op; typename op::ptr p = { asio::detail::addressof(handler), op::ptr::allocate(handler), 0 }; p.p = new (p.v) op(success_ec_, handler, io_ex); + // Optionally register for per-operation cancellation.+ if (slot.is_connected())+ {+ p.p->cancellation_key_ =+ &slot.template emplace<reactor_op_cancellation>(+ &reactor_, &impl.reactor_data_, impl.socket_, reactor::read_op);+ }+ ASIO_HANDLER_CREATION((reactor_.context(), *p.p, "socket", &impl, impl.socket_, "async_receive_with_flags(null_buffers)")); @@ -491,7 +573,7 @@ start_op(impl, (in_flags & socket_base::message_out_of_band) ? reactor::except_op : reactor::read_op,- p.p, is_continuation, false, false);+ p.p, is_continuation, false, false, &io_ex, 0); p.v = p.p = 0; } @@ -507,18 +589,144 @@ const native_handle_type& native_socket, asio::error_code& ec); // Start the asynchronous read or write operation.- ASIO_DECL void start_op(base_implementation_type& impl, int op_type,- reactor_op* op, bool is_continuation, bool is_non_blocking, bool noop);+ ASIO_DECL void do_start_op(base_implementation_type& impl, int op_type,+ reactor_op* op, bool is_continuation, bool is_non_blocking, bool noop,+ void (*on_immediate)(operation* op, bool, const void*),+ const void* immediate_arg); + // Start the asynchronous operation for handlers that are specialised for+ // immediate completion.+ template <typename Op>+ void start_op(base_implementation_type& impl, int op_type, Op* op,+ bool is_continuation, bool is_non_blocking, bool noop,+ const void* io_ex, ...)+ {+ return do_start_op(impl, op_type, op, is_continuation,+ is_non_blocking, noop, &Op::do_immediate, io_ex);+ }++ // Start the asynchronous operation for handlers that are not specialised for+ // immediate completion.+ template <typename Op>+ void start_op(base_implementation_type& impl, int op_type, Op* op,+ bool is_continuation, bool is_non_blocking, bool noop, const void*,+ typename enable_if<+ is_same<+ typename associated_immediate_executor<+ typename Op::handler_type,+ typename Op::io_executor_type+ >::asio_associated_immediate_executor_is_unspecialised,+ void+ >::value+ >::type*)+ {+ return do_start_op(impl, op_type, op, is_continuation, is_non_blocking,+ noop, &reactor::call_post_immediate_completion, &reactor_);+ }+ // Start the asynchronous accept operation.- ASIO_DECL void start_accept_op(base_implementation_type& impl,- reactor_op* op, bool is_continuation, bool peer_is_open);+ ASIO_DECL void do_start_accept_op(base_implementation_type& impl,+ reactor_op* op, bool is_continuation, bool peer_is_open,+ void (*on_immediate)(operation* op, bool, const void*),+ const void* immediate_arg); + // Start the asynchronous accept operation for handlers that are specialised+ // for immediate completion.+ template <typename Op>+ void start_accept_op(base_implementation_type& impl, Op* op,+ bool is_continuation, bool peer_is_open, const void* io_ex, ...)+ {+ return do_start_accept_op(impl, op, is_continuation,+ peer_is_open, &Op::do_immediate, io_ex);+ }++ // Start the asynchronous operation for handlers that are not specialised for+ // immediate completion.+ template <typename Op>+ void start_accept_op(base_implementation_type& impl, Op* op,+ bool is_continuation, bool peer_is_open, const void*,+ typename enable_if<+ is_same<+ typename associated_immediate_executor<+ typename Op::handler_type,+ typename Op::io_executor_type+ >::asio_associated_immediate_executor_is_unspecialised,+ void+ >::value+ >::type*)+ {+ return do_start_accept_op(impl, op, is_continuation, peer_is_open,+ &reactor::call_post_immediate_completion, &reactor_);+ }+ // Start the asynchronous connect operation.- ASIO_DECL void start_connect_op(base_implementation_type& impl,- reactor_op* op, bool is_continuation,- const socket_addr_type* addr, size_t addrlen);+ ASIO_DECL void do_start_connect_op(base_implementation_type& impl,+ reactor_op* op, bool is_continuation, const void* addr, size_t addrlen,+ void (*on_immediate)(operation* op, bool, const void*),+ const void* immediate_arg); + // Start the asynchronous operation for handlers that are specialised for+ // immediate completion.+ template <typename Op>+ void start_connect_op(base_implementation_type& impl,+ Op* op, bool is_continuation, const void* addr,+ size_t addrlen, const void* io_ex, ...)+ {+ return do_start_connect_op(impl, op, is_continuation,+ addr, addrlen, &Op::do_immediate, io_ex);+ }++ // Start the asynchronous operation for handlers that are not specialised for+ // immediate completion.+ template <typename Op>+ void start_connect_op(base_implementation_type& impl, Op* op,+ bool is_continuation, const void* addr, size_t addrlen, const void*,+ typename enable_if<+ is_same<+ typename associated_immediate_executor<+ typename Op::handler_type,+ typename Op::io_executor_type+ >::asio_associated_immediate_executor_is_unspecialised,+ void+ >::value+ >::type*)+ {+ return do_start_connect_op(impl, op, is_continuation, addr,+ addrlen, &reactor::call_post_immediate_completion, &reactor_);+ }++ // Helper class used to implement per-operation cancellation+ class reactor_op_cancellation+ {+ public:+ reactor_op_cancellation(reactor* r,+ reactor::per_descriptor_data* p, int d, int o)+ : reactor_(r),+ reactor_data_(p),+ descriptor_(d),+ op_type_(o)+ {+ }++ void operator()(cancellation_type_t type)+ {+ if (!!(type &+ (cancellation_type::terminal+ | cancellation_type::partial+ | cancellation_type::total)))+ {+ reactor_->cancel_ops_by_key(descriptor_,+ *reactor_data_, op_type_, this);+ }+ }++ private:+ reactor* reactor_;+ reactor::per_descriptor_data* reactor_data_;+ int descriptor_;+ int op_type_;+ };+ // The selector that performs event demultiplexing for the service. reactor& reactor_; @@ -537,5 +745,6 @@ #endif // !defined(ASIO_HAS_IOCP) // && !defined(ASIO_WINDOWS_RUNTIME)+ // && !defined(ASIO_HAS_IO_URING_AS_DEFAULT) #endif // ASIO_DETAIL_REACTIVE_SOCKET_SERVICE_BASE_HPP
link/modules/asio-standalone/asio/include/asio/detail/reactive_wait_op.hpp view
@@ -2,7 +2,7 @@ // detail/reactive_wait_op.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -33,6 +33,9 @@ class reactive_wait_op : public reactor_op { public:+ typedef Handler handler_type;+ typedef IoExecutor io_executor_type;+ ASIO_DEFINE_HANDLER_PTR(reactive_wait_op); reactive_wait_op(const asio::error_code& success_ec,@@ -54,6 +57,7 @@ std::size_t /*bytes_transferred*/) { // Take ownership of the handler object.+ ASIO_ASSUME(base != 0); reactive_wait_op* o(static_cast<reactive_wait_op*>(base)); ptr p = { asio::detail::addressof(o->handler_), o, o }; @@ -83,6 +87,36 @@ w.complete(handler, handler.handler_); ASIO_HANDLER_INVOCATION_END; }+ }++ static void do_immediate(operation* base, bool, const void* io_ex)+ {+ // Take ownership of the handler object.+ ASIO_ASSUME(base != 0);+ reactive_wait_op* o(static_cast<reactive_wait_op*>(base));+ ptr p = { asio::detail::addressof(o->handler_), o, o };++ ASIO_HANDLER_COMPLETION((*o));++ // Take ownership of the operation's outstanding work.+ immediate_handler_work<Handler, IoExecutor> w(+ ASIO_MOVE_CAST2(handler_work<Handler, IoExecutor>)(+ o->work_));++ // Make a copy of the handler so that the memory can be deallocated before+ // the upcall is made. Even if we're not about to make an upcall, a+ // sub-object of the handler may be the true owner of the memory associated+ // with the handler. Consequently, a local copy of the handler is required+ // to ensure that any owning sub-object remains valid until after we have+ // deallocated the memory here.+ detail::binder1<Handler, asio::error_code>+ handler(o->handler_, o->ec_);+ p.h = asio::detail::addressof(handler.handler_);+ p.reset();++ ASIO_HANDLER_INVOCATION_BEGIN((handler.arg1_));+ w.complete(handler, handler.handler_, io_ex);+ ASIO_HANDLER_INVOCATION_END; } private:
link/modules/asio-standalone/asio/include/asio/detail/reactor.hpp view
@@ -2,7 +2,7 @@ // detail/reactor.hpp // ~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -15,18 +15,40 @@ # pragma once #endif // defined(_MSC_VER) && (_MSC_VER >= 1200) -#include "asio/detail/reactor_fwd.hpp"+#include "asio/detail/config.hpp" -#if defined(ASIO_HAS_EPOLL)+#if defined(ASIO_HAS_IOCP) || defined(ASIO_WINDOWS_RUNTIME)+# include "asio/detail/null_reactor.hpp"+#elif defined(ASIO_HAS_IO_URING_AS_DEFAULT)+# include "asio/detail/null_reactor.hpp"+#elif defined(ASIO_HAS_EPOLL) # include "asio/detail/epoll_reactor.hpp" #elif defined(ASIO_HAS_KQUEUE) # include "asio/detail/kqueue_reactor.hpp" #elif defined(ASIO_HAS_DEV_POLL) # include "asio/detail/dev_poll_reactor.hpp"-#elif defined(ASIO_HAS_IOCP) || defined(ASIO_WINDOWS_RUNTIME)-# include "asio/detail/null_reactor.hpp" #else # include "asio/detail/select_reactor.hpp" #endif++namespace asio {+namespace detail {++#if defined(ASIO_HAS_IOCP) || defined(ASIO_WINDOWS_RUNTIME)+typedef null_reactor reactor;+#elif defined(ASIO_HAS_IO_URING_AS_DEFAULT)+typedef null_reactor reactor;+#elif defined(ASIO_HAS_EPOLL)+typedef epoll_reactor reactor;+#elif defined(ASIO_HAS_KQUEUE)+typedef kqueue_reactor reactor;+#elif defined(ASIO_HAS_DEV_POLL)+typedef dev_poll_reactor reactor;+#else+typedef select_reactor reactor;+#endif++} // namespace detail+} // namespace asio #endif // ASIO_DETAIL_REACTOR_HPP
− link/modules/asio-standalone/asio/include/asio/detail/reactor_fwd.hpp
@@ -1,40 +0,0 @@-//-// detail/reactor_fwd.hpp-// ~~~~~~~~~~~~~~~~~~~~~~-//-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)-//-// Distributed under the Boost Software License, Version 1.0. (See accompanying-// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)-//--#ifndef ASIO_DETAIL_REACTOR_FWD_HPP-#define ASIO_DETAIL_REACTOR_FWD_HPP--#if defined(_MSC_VER) && (_MSC_VER >= 1200)-# pragma once-#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)--#include "asio/detail/config.hpp"--namespace asio {-namespace detail {--#if defined(ASIO_HAS_IOCP) || defined(ASIO_WINDOWS_RUNTIME)-typedef class null_reactor reactor;-#elif defined(ASIO_HAS_IOCP)-typedef class select_reactor reactor;-#elif defined(ASIO_HAS_EPOLL)-typedef class epoll_reactor reactor;-#elif defined(ASIO_HAS_KQUEUE)-typedef class kqueue_reactor reactor;-#elif defined(ASIO_HAS_DEV_POLL)-typedef class dev_poll_reactor reactor;-#else-typedef class select_reactor reactor;-#endif--} // namespace detail-} // namespace asio--#endif // ASIO_DETAIL_REACTOR_FWD_HPP
link/modules/asio-standalone/asio/include/asio/detail/reactor_op.hpp view
@@ -2,7 +2,7 @@ // detail/reactor_op.hpp // ~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -30,6 +30,9 @@ // The error code to be passed to the completion handler. asio::error_code ec_; + // The operation key used for targeted cancellation.+ void* cancellation_key_;+ // The number of bytes transferred, to be passed to the completion handler. std::size_t bytes_transferred_; @@ -50,6 +53,7 @@ perform_func_type perform_func, func_type complete_func) : operation(complete_func), ec_(success_ec),+ cancellation_key_(0), bytes_transferred_(0), perform_func_(perform_func) {
link/modules/asio-standalone/asio/include/asio/detail/reactor_op_queue.hpp view
@@ -2,7 +2,7 @@ // detail/reactor_op_queue.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -98,6 +98,50 @@ asio::error::operation_aborted) { return this->cancel_operations(operations_.find(descriptor), ops, ec);+ }++ // Cancel operations associated with the descriptor identified by the+ // supplied iterator, and the specified cancellation key. Any operations+ // pending for the descriptor with the key will be cancelled. Returns true if+ // any operations were cancelled, in which case the reactor's event+ // demultiplexing function may need to be interrupted and restarted.+ bool cancel_operations_by_key(iterator i, op_queue<operation>& ops,+ void* cancellation_key, const asio::error_code& ec =+ asio::error::operation_aborted)+ {+ bool result = false;+ if (i != operations_.end())+ {+ op_queue<reactor_op> other_ops;+ while (reactor_op* op = i->second.front())+ {+ i->second.pop();+ if (op->cancellation_key_ == cancellation_key)+ {+ op->ec_ = ec;+ ops.push(op);+ result = true;+ }+ else+ other_ops.push(op);+ }+ i->second.push(other_ops);+ if (i->second.empty())+ operations_.erase(i);+ }+ return result;+ }++ // Cancel all operations associated with the descriptor. Any operations+ // pending for the descriptor will be cancelled. Returns true if any+ // operations were cancelled, in which case the reactor's event+ // demultiplexing function may need to be interrupted and restarted.+ bool cancel_operations_by_key(Descriptor descriptor, op_queue<operation>& ops,+ void* cancellation_key, const asio::error_code& ec =+ asio::error::operation_aborted)+ {+ return this->cancel_operations_by_key(+ operations_.find(descriptor), ops, cancellation_key, ec); } // Whether there are no operations in the queue.
link/modules/asio-standalone/asio/include/asio/detail/recycling_allocator.hpp view
@@ -2,7 +2,7 @@ // detail/recycling_allocator.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -48,17 +48,16 @@ T* allocate(std::size_t n) {- typedef thread_context::thread_call_stack call_stack; void* p = thread_info_base::allocate(Purpose(),- call_stack::top(), sizeof(T) * n);+ thread_context::top_of_thread_call_stack(),+ sizeof(T) * n, ASIO_ALIGNOF(T)); return static_cast<T*>(p); } void deallocate(T* p, std::size_t n) {- typedef thread_context::thread_call_stack call_stack; thread_info_base::deallocate(Purpose(),- call_stack::top(), p, sizeof(T) * n);+ thread_context::top_of_thread_call_stack(), p, sizeof(T) * n); } };
link/modules/asio-standalone/asio/include/asio/detail/regex_fwd.hpp view
@@ -2,7 +2,7 @@ // detail/regex_fwd.hpp // ~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -18,7 +18,16 @@ #if defined(ASIO_HAS_BOOST_REGEX) #include <boost/regex_fwd.hpp>-#include <boost/regex/v4/match_flags.hpp>+#include <boost/version.hpp>+#if BOOST_VERSION >= 107600+# if defined(BOOST_REGEX_CXX03)+# include <boost/regex/v4/match_flags.hpp>+# else // defined(BOOST_REGEX_CXX03)+# include <boost/regex/v5/match_flags.hpp>+# endif // defined(BOOST_REGEX_CXX03)+#else // BOOST_VERSION >= 107600+# include <boost/regex/v4/match_flags.hpp>+#endif // BOOST_VERSION >= 107600 namespace boost {
link/modules/asio-standalone/asio/include/asio/detail/resolve_endpoint_op.hpp view
@@ -2,7 +2,7 @@ // detail/resolve_endpoint_op.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -70,6 +70,7 @@ std::size_t /*bytes_transferred*/) { // Take ownership of the operation object.+ ASIO_ASSUME(base != 0); resolve_endpoint_op* o(static_cast<resolve_endpoint_op*>(base)); ptr p = { asio::detail::addressof(o->handler_), o, o }; @@ -79,8 +80,8 @@ // the resolver operation. // Perform the blocking endpoint resolution operation.- char host_name[NI_MAXHOST];- char service_name[NI_MAXSERV];+ char host_name[NI_MAXHOST] = "";+ char service_name[NI_MAXSERV] = ""; socket_ops::background_getnameinfo(o->cancel_token_, o->endpoint_.data(), o->endpoint_.size(), host_name, NI_MAXHOST, service_name, NI_MAXSERV, o->endpoint_.protocol().type(), o->ec_);
link/modules/asio-standalone/asio/include/asio/detail/resolve_op.hpp view
@@ -2,7 +2,7 @@ // detail/resolve_op.hpp // ~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/detail/resolve_query_op.hpp view
@@ -2,7 +2,7 @@ // detail/resolve_query_op.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -55,11 +55,11 @@ #endif resolve_query_op(socket_ops::weak_cancel_token_type cancel_token,- const query_type& query, scheduler_impl& sched,+ const query_type& qry, scheduler_impl& sched, Handler& handler, const IoExecutor& io_ex) : resolve_op(&resolve_query_op::do_complete), cancel_token_(cancel_token),- query_(query),+ query_(qry), scheduler_(sched), handler_(ASIO_MOVE_CAST(Handler)(handler)), work_(handler_, io_ex),@@ -78,6 +78,7 @@ std::size_t /*bytes_transferred*/) { // Take ownership of the operation object.+ ASIO_ASSUME(base != 0); resolve_query_op* o(static_cast<resolve_query_op*>(base)); ptr p = { asio::detail::addressof(o->handler_), o, o };
link/modules/asio-standalone/asio/include/asio/detail/resolver_service.hpp view
@@ -2,7 +2,7 @@ // detail/resolver_service.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -71,29 +71,30 @@ } // Resolve a query to a list of entries.- results_type resolve(implementation_type&, const query_type& query,+ results_type resolve(implementation_type&, const query_type& qry, asio::error_code& ec) { asio::detail::addrinfo_type* address_info = 0; - socket_ops::getaddrinfo(query.host_name().c_str(),- query.service_name().c_str(), query.hints(), &address_info, ec);+ socket_ops::getaddrinfo(qry.host_name().c_str(),+ qry.service_name().c_str(), qry.hints(), &address_info, ec); auto_addrinfo auto_address_info(address_info); + ASIO_ERROR_LOCATION(ec); return ec ? results_type() : results_type::create(- address_info, query.host_name(), query.service_name());+ address_info, qry.host_name(), qry.service_name()); } // Asynchronously resolve a query to a list of entries. template <typename Handler, typename IoExecutor>- void async_resolve(implementation_type& impl, const query_type& query,+ void async_resolve(implementation_type& impl, const query_type& qry, Handler& handler, const IoExecutor& io_ex) { // Allocate and construct an operation to wrap the handler. typedef resolve_query_op<Protocol, Handler, IoExecutor> op; typename op::ptr p = { asio::detail::addressof(handler), op::ptr::allocate(handler), 0 };- p.p = new (p.v) op(impl, query, scheduler_, handler, io_ex);+ p.p = new (p.v) op(impl, qry, scheduler_, handler, io_ex); ASIO_HANDLER_CREATION((scheduler_.context(), *p.p, "resolver", &impl, 0, "async_resolve"));@@ -112,6 +113,7 @@ host_name, NI_MAXHOST, service_name, NI_MAXSERV, endpoint.protocol().type(), ec); + ASIO_ERROR_LOCATION(ec); return ec ? results_type() : results_type::create( endpoint, host_name, service_name); }
link/modules/asio-standalone/asio/include/asio/detail/resolver_service_base.hpp view
@@ -2,7 +2,7 @@ // detail/resolver_service_base.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -71,6 +71,21 @@ ASIO_DECL void move_assign(implementation_type& impl, resolver_service_base& other_service, implementation_type& other_impl);++ // Move-construct a new timer implementation.+ void converting_move_construct(implementation_type& impl,+ resolver_service_base&, implementation_type& other_impl)+ {+ move_construct(impl, other_impl);+ }++ // Move-assign from another timer implementation.+ void converting_move_assign(implementation_type& impl,+ resolver_service_base& other_service,+ implementation_type& other_impl)+ {+ move_assign(impl, other_service, other_impl);+ } // Cancel pending asynchronous operations. ASIO_DECL void cancel(implementation_type& impl);
link/modules/asio-standalone/asio/include/asio/detail/scheduler.hpp view
@@ -2,7 +2,7 @@ // detail/scheduler.hpp // ~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -23,8 +23,8 @@ #include "asio/detail/conditionally_enabled_event.hpp" #include "asio/detail/conditionally_enabled_mutex.hpp" #include "asio/detail/op_queue.hpp"-#include "asio/detail/reactor_fwd.hpp" #include "asio/detail/scheduler_operation.hpp"+#include "asio/detail/scheduler_task.hpp" #include "asio/detail/thread.hpp" #include "asio/detail/thread_context.hpp" @@ -42,10 +42,15 @@ public: typedef scheduler_operation operation; + // The type of a function used to obtain a task instance.+ typedef scheduler_task* (*get_task_func_type)(+ asio::execution_context&);+ // Constructor. Specifies the number of concurrent threads that are likely to // run the scheduler. If set to 1 certain optimisation are performed. ASIO_DECL scheduler(asio::execution_context& ctx,- int concurrency_hint = 0, bool own_thread = true);+ int concurrency_hint = 0, bool own_thread = true,+ get_task_func_type get_task = &scheduler::get_default_task); // Destructor. ASIO_DECL ~scheduler();@@ -99,10 +104,7 @@ } // Return whether a handler can be dispatched immediately.- bool can_dispatch()- {- return thread_call_stack::contains(this) != 0;- }+ ASIO_DECL bool can_dispatch(); /// Capture the current exception so it can be rethrown from a run function. ASIO_DECL void capture_current_exception();@@ -168,6 +170,10 @@ ASIO_DECL void wake_one_thread_and_unlock( mutex::scoped_lock& lock); + // Get the default task.+ ASIO_DECL static scheduler_task* get_default_task(+ asio::execution_context& ctx);+ // Helper class to run the scheduler in its own thread. class thread_function; friend class thread_function;@@ -190,7 +196,10 @@ event wakeup_event_; // The task to be run by this service.- reactor* task_;+ scheduler_task* task_;++ // The function used to get the task.+ get_task_func_type get_task_; // Operation object to represent the position of the task in the queue. struct task_operation : operation
link/modules/asio-standalone/asio/include/asio/detail/scheduler_operation.hpp view
@@ -2,7 +2,7 @@ // detail/scheduler_operation.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+ link/modules/asio-standalone/asio/include/asio/detail/scheduler_task.hpp view
@@ -0,0 +1,49 @@+//+// detail/scheduler_task.hpp+// ~~~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com)+//+// Distributed under the Boost Software License, Version 1.0. (See accompanying+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)+//++#ifndef ASIO_DETAIL_SCHEDULER_TASK_HPP+#define ASIO_DETAIL_SCHEDULER_TASK_HPP++#if defined(_MSC_VER) && (_MSC_VER >= 1200)+# pragma once+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)++#include "asio/detail/op_queue.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {+namespace detail {++class scheduler_operation;++// Base class for all tasks that may be run by a scheduler.+class scheduler_task+{+public:+ // Run the task once until interrupted or events are ready to be dispatched.+ virtual void run(long usec, op_queue<scheduler_operation>& ops) = 0;++ // Interrupt the task.+ virtual void interrupt() = 0;++protected:+ // Prevent deletion through this type.+ ~scheduler_task()+ {+ }+};++} // namespace detail+} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // ASIO_DETAIL_SCHEDULER_TASK_HPP
link/modules/asio-standalone/asio/include/asio/detail/scheduler_thread_info.hpp view
@@ -2,7 +2,7 @@ // detail/scheduler_thread_info.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/detail/scoped_lock.hpp view
@@ -2,7 +2,7 @@ // detail/scoped_lock.hpp // ~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/detail/scoped_ptr.hpp view
@@ -2,7 +2,7 @@ // detail/scoped_ptr.hpp // ~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/detail/select_interrupter.hpp view
@@ -2,7 +2,7 @@ // detail/select_interrupter.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/detail/select_reactor.hpp view
@@ -2,7 +2,7 @@ // detail/select_reactor.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -30,6 +30,7 @@ #include "asio/detail/op_queue.hpp" #include "asio/detail/reactor_op.hpp" #include "asio/detail/reactor_op_queue.hpp"+#include "asio/detail/scheduler_task.hpp" #include "asio/detail/select_interrupter.hpp" #include "asio/detail/socket_types.hpp" #include "asio/detail/timer_queue_base.hpp"@@ -48,6 +49,9 @@ class select_reactor : public execution_context_service_base<select_reactor>+#if !defined(ASIO_HAS_IOCP)+ , public scheduler_task+#endif // !defined(ASIO_HAS_IOCP) { public: #if defined(ASIO_WINDOWS) || defined(__CYGWIN__)@@ -90,21 +94,42 @@ per_descriptor_data& descriptor_data, reactor_op* op); // Post a reactor operation for immediate completion.- void post_immediate_completion(reactor_op* op, bool is_continuation)- {- scheduler_.post_immediate_completion(op, is_continuation);- }+ void post_immediate_completion(operation* op, bool is_continuation) const; + // Post a reactor operation for immediate completion.+ ASIO_DECL static void call_post_immediate_completion(+ operation* op, bool is_continuation, const void* self);+ // Start a new operation. The reactor operation will be performed when the // given descriptor is flagged as ready, or an error has occurred. ASIO_DECL void start_op(int op_type, socket_type descriptor,- per_descriptor_data&, reactor_op* op, bool is_continuation, bool);+ per_descriptor_data&, reactor_op* op, bool is_continuation, bool,+ void (*on_immediate)(operation*, bool, const void*),+ const void* immediate_arg); + // Start a new operation. The reactor operation will be performed when the+ // given descriptor is flagged as ready, or an error has occurred.+ void start_op(int op_type, socket_type descriptor,+ per_descriptor_data& descriptor_data, reactor_op* op,+ bool is_continuation, bool allow_speculative)+ {+ start_op(op_type, descriptor, descriptor_data,+ op, is_continuation, allow_speculative,+ &select_reactor::call_post_immediate_completion, this);+ }+ // Cancel all operations associated with the given descriptor. The // handlers associated with the descriptor will be invoked with the // operation_aborted error. ASIO_DECL void cancel_ops(socket_type descriptor, per_descriptor_data&); + // Cancel all operations associated with the given descriptor and key. The+ // handlers associated with the descriptor will be invoked with the+ // operation_aborted error.+ ASIO_DECL void cancel_ops_by_key(socket_type descriptor,+ per_descriptor_data& descriptor_data,+ int op_type, void* cancellation_key);+ // Cancel any operations that are running against the descriptor and remove // its registration from the reactor. The reactor resources associated with // the descriptor must be released by calling cleanup_descriptor_data.@@ -148,6 +173,12 @@ typename timer_queue<Time_Traits>::per_timer_data& timer, std::size_t max_cancelled = (std::numeric_limits<std::size_t>::max)()); + // Cancel the timer operations associated with the given key.+ template <typename Time_Traits>+ void cancel_timer_by_key(timer_queue<Time_Traits>& queue,+ typename timer_queue<Time_Traits>::per_timer_data* timer,+ void* cancellation_key);+ // Move the timer operations associated with the given timer. template <typename Time_Traits> void move_timer(timer_queue<Time_Traits>& queue,@@ -213,6 +244,28 @@ // The thread that is running the reactor loop. asio::detail::thread* thread_;++ // Helper class to join and restart the reactor thread.+ class restart_reactor : public operation+ {+ public:+ restart_reactor(select_reactor* r)+ : operation(&restart_reactor::do_complete),+ reactor_(r)+ {+ }++ ASIO_DECL static void do_complete(void* owner, operation* base,+ const asio::error_code& ec, std::size_t bytes_transferred);++ private:+ select_reactor* reactor_;+ };++ friend class restart_reactor;++ // Operation used to join and restart the reactor thread.+ restart_reactor restart_reactor_; #endif // defined(ASIO_HAS_IOCP) // Whether the service has been shut down.
link/modules/asio-standalone/asio/include/asio/detail/service_registry.hpp view
@@ -2,7 +2,7 @@ // detail/service_registry.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/detail/signal_blocker.hpp view
@@ -2,7 +2,7 @@ // detail/signal_blocker.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/detail/signal_handler.hpp view
@@ -2,7 +2,7 @@ // detail/signal_handler.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/detail/signal_init.hpp view
@@ -2,7 +2,7 @@ // detail/signal_init.hpp // ~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/detail/signal_op.hpp view
@@ -2,7 +2,7 @@ // detail/signal_op.hpp // ~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -30,12 +30,16 @@ // The error code to be passed to the completion handler. asio::error_code ec_; + // The operation key used for targeted cancellation.+ void* cancellation_key_;+ // The signal number to be passed to the completion handler. int signal_number_; protected: signal_op(func_type func) : operation(func),+ cancellation_key_(0), signal_number_(0) { }
link/modules/asio-standalone/asio/include/asio/detail/signal_set_service.hpp view
@@ -2,7 +2,7 @@ // detail/signal_set_service.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -19,8 +19,11 @@ #include <cstddef> #include <signal.h>+#include "asio/associated_cancellation_slot.hpp"+#include "asio/cancellation_type.hpp" #include "asio/error.hpp" #include "asio/execution_context.hpp"+#include "asio/signal_set_base.hpp" #include "asio/detail/handler_alloc_helpers.hpp" #include "asio/detail/memory.hpp" #include "asio/detail/op_queue.hpp"@@ -35,7 +38,11 @@ #endif // defined(ASIO_HAS_IOCP) #if !defined(ASIO_WINDOWS) && !defined(__CYGWIN__)-# include "asio/detail/reactor.hpp"+# if defined(ASIO_HAS_IO_URING_AS_DEFAULT)+# include "asio/detail/io_uring_service.hpp"+# else // defined(ASIO_HAS_IO_URING_AS_DEFAULT)+# include "asio/detail/reactor.hpp"+# endif // defined(ASIO_HAS_IO_URING_AS_DEFAULT) #endif // !defined(ASIO_WINDOWS) && !defined(__CYGWIN__) #include "asio/detail/push_options.hpp"@@ -134,8 +141,16 @@ ASIO_DECL void destroy(implementation_type& impl); // Add a signal to a signal_set.+ asio::error_code add(implementation_type& impl,+ int signal_number, asio::error_code& ec)+ {+ return add(impl, signal_number, signal_set_base::flags::dont_care, ec);+ }++ // Add a signal to a signal_set with the specified flags. ASIO_DECL asio::error_code add(implementation_type& impl,- int signal_number, asio::error_code& ec);+ int signal_number, signal_set_base::flags_t f,+ asio::error_code& ec); // Remove a signal to a signal_set. ASIO_DECL asio::error_code remove(implementation_type& impl,@@ -149,17 +164,31 @@ ASIO_DECL asio::error_code cancel(implementation_type& impl, asio::error_code& ec); + // Cancel a specific operation associated with the signal set.+ ASIO_DECL void cancel_ops_by_key(implementation_type& impl,+ void* cancellation_key);+ // Start an asynchronous operation to wait for a signal to be delivered. template <typename Handler, typename IoExecutor> void async_wait(implementation_type& impl, Handler& handler, const IoExecutor& io_ex) {+ typename associated_cancellation_slot<Handler>::type slot+ = asio::get_associated_cancellation_slot(handler);+ // Allocate and construct an operation to wrap the handler. typedef signal_handler<Handler, IoExecutor> op; typename op::ptr p = { asio::detail::addressof(handler), op::ptr::allocate(handler), 0 }; p.p = new (p.v) op(handler, io_ex); + // Optionally register for per-operation cancellation.+ if (slot.is_connected())+ {+ p.p->cancellation_key_ =+ &slot.template emplace<signal_op_cancellation>(this, &impl);+ }+ ASIO_HANDLER_CREATION((scheduler_.context(), *p.p, "signal_set", &impl, 0, "async_wait")); @@ -186,6 +215,32 @@ // Helper function to start a wait operation. ASIO_DECL void start_wait_op(implementation_type& impl, signal_op* op); + // Helper class used to implement per-operation cancellation+ class signal_op_cancellation+ {+ public:+ signal_op_cancellation(signal_set_service* s, implementation_type* i)+ : service_(s),+ implementation_(i)+ {+ }++ void operator()(cancellation_type_t type)+ {+ if (!!(type &+ (cancellation_type::terminal+ | cancellation_type::partial+ | cancellation_type::total)))+ {+ service_->cancel_ops_by_key(*implementation_, this);+ }+ }++ private:+ signal_set_service* service_;+ implementation_type* implementation_;+ };+ // The scheduler used for dispatching handlers. #if defined(ASIO_HAS_IOCP) typedef class win_iocp_io_context scheduler_impl;@@ -197,14 +252,22 @@ #if !defined(ASIO_WINDOWS) \ && !defined(ASIO_WINDOWS_RUNTIME) \ && !defined(__CYGWIN__)- // The type used for registering for pipe reactor notifications.+ // The type used for processing pipe readiness notifications. class pipe_read_op; +# if defined(ASIO_HAS_IO_URING_AS_DEFAULT)+ // The io_uring service used for waiting for pipe readiness.+ io_uring_service& io_uring_service_;++ // The per I/O object data used for the pipe.+ io_uring_service::per_io_object_data io_object_data_;+# else // defined(ASIO_HAS_IO_URING_AS_DEFAULT) // The reactor used for waiting for pipe readiness. reactor& reactor_; // The per-descriptor reactor data used for the pipe. reactor::per_descriptor_data reactor_data_;+# endif // defined(ASIO_HAS_IO_URING_AS_DEFAULT) #endif // !defined(ASIO_WINDOWS) // && !defined(ASIO_WINDOWS_RUNTIME) // && !defined(__CYGWIN__)
link/modules/asio-standalone/asio/include/asio/detail/socket_holder.hpp view
@@ -2,7 +2,7 @@ // detail/socket_holder.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/detail/socket_ops.hpp view
@@ -2,7 +2,7 @@ // detail/socket_ops.hpp // ~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -63,29 +63,27 @@ #if !defined(ASIO_WINDOWS_RUNTIME) -ASIO_DECL socket_type accept(socket_type s, socket_addr_type* addr,+ASIO_DECL socket_type accept(socket_type s, void* addr, std::size_t* addrlen, asio::error_code& ec); -ASIO_DECL socket_type sync_accept(socket_type s,- state_type state, socket_addr_type* addr,- std::size_t* addrlen, asio::error_code& ec);+ASIO_DECL socket_type sync_accept(socket_type s, state_type state,+ void* addr, std::size_t* addrlen, asio::error_code& ec); #if defined(ASIO_HAS_IOCP) -ASIO_DECL void complete_iocp_accept(socket_type s,- void* output_buffer, DWORD address_length,- socket_addr_type* addr, std::size_t* addrlen,+ASIO_DECL void complete_iocp_accept(socket_type s, void* output_buffer,+ DWORD address_length, void* addr, std::size_t* addrlen, socket_type new_socket, asio::error_code& ec); #else // defined(ASIO_HAS_IOCP) ASIO_DECL bool non_blocking_accept(socket_type s,- state_type state, socket_addr_type* addr, std::size_t* addrlen,+ state_type state, void* addr, std::size_t* addrlen, asio::error_code& ec, socket_type& new_socket); #endif // defined(ASIO_HAS_IOCP) -ASIO_DECL int bind(socket_type s, const socket_addr_type* addr,+ASIO_DECL int bind(socket_type s, const void* addr, std::size_t addrlen, asio::error_code& ec); ASIO_DECL int close(socket_type s, state_type& state,@@ -100,10 +98,10 @@ ASIO_DECL int shutdown(socket_type s, int what, asio::error_code& ec); -ASIO_DECL int connect(socket_type s, const socket_addr_type* addr,+ASIO_DECL int connect(socket_type s, const void* addr, std::size_t addrlen, asio::error_code& ec); -ASIO_DECL void sync_connect(socket_type s, const socket_addr_type* addr,+ASIO_DECL void sync_connect(socket_type s, const void* addr, std::size_t addrlen, asio::error_code& ec); #if defined(ASIO_HAS_IOCP)@@ -166,20 +164,20 @@ #endif // defined(ASIO_HAS_IOCP) -ASIO_DECL signed_size_type recvfrom(socket_type s, buf* bufs,- size_t count, int flags, socket_addr_type* addr,+ASIO_DECL signed_size_type recvfrom(socket_type s,+ buf* bufs, size_t count, int flags, void* addr, std::size_t* addrlen, asio::error_code& ec); -ASIO_DECL signed_size_type recvfrom1(socket_type s, void* data,- size_t size, int flags, socket_addr_type* addr,+ASIO_DECL signed_size_type recvfrom1(socket_type s,+ void* data, size_t size, int flags, void* addr, std::size_t* addrlen, asio::error_code& ec); ASIO_DECL size_t sync_recvfrom(socket_type s, state_type state,- buf* bufs, size_t count, int flags, socket_addr_type* addr,+ buf* bufs, size_t count, int flags, void* addr, std::size_t* addrlen, asio::error_code& ec); ASIO_DECL size_t sync_recvfrom1(socket_type s, state_type state,- void* data, size_t size, int flags, socket_addr_type* addr,+ void* data, size_t size, int flags, void* addr, std::size_t* addrlen, asio::error_code& ec); #if defined(ASIO_HAS_IOCP)@@ -190,14 +188,12 @@ #else // defined(ASIO_HAS_IOCP) -ASIO_DECL bool non_blocking_recvfrom(socket_type s,- buf* bufs, size_t count, int flags,- socket_addr_type* addr, std::size_t* addrlen,+ASIO_DECL bool non_blocking_recvfrom(socket_type s, buf* bufs,+ size_t count, int flags, void* addr, std::size_t* addrlen, asio::error_code& ec, size_t& bytes_transferred); -ASIO_DECL bool non_blocking_recvfrom1(socket_type s,- void* data, size_t size, int flags,- socket_addr_type* addr, std::size_t* addrlen,+ASIO_DECL bool non_blocking_recvfrom1(socket_type s, void* data,+ size_t size, int flags, void* addr, std::size_t* addrlen, asio::error_code& ec, size_t& bytes_transferred); #endif // defined(ASIO_HAS_IOCP)@@ -255,32 +251,30 @@ #endif // defined(ASIO_HAS_IOCP) -ASIO_DECL signed_size_type sendto(socket_type s, const buf* bufs,- size_t count, int flags, const socket_addr_type* addr,+ASIO_DECL signed_size_type sendto(socket_type s,+ const buf* bufs, size_t count, int flags, const void* addr, std::size_t addrlen, asio::error_code& ec); -ASIO_DECL signed_size_type sendto1(socket_type s, const void* data,- size_t size, int flags, const socket_addr_type* addr,+ASIO_DECL signed_size_type sendto1(socket_type s,+ const void* data, size_t size, int flags, const void* addr, std::size_t addrlen, asio::error_code& ec); ASIO_DECL size_t sync_sendto(socket_type s, state_type state,- const buf* bufs, size_t count, int flags, const socket_addr_type* addr,+ const buf* bufs, size_t count, int flags, const void* addr, std::size_t addrlen, asio::error_code& ec); ASIO_DECL size_t sync_sendto1(socket_type s, state_type state,- const void* data, size_t size, int flags, const socket_addr_type* addr,+ const void* data, size_t size, int flags, const void* addr, std::size_t addrlen, asio::error_code& ec); #if !defined(ASIO_HAS_IOCP) -ASIO_DECL bool non_blocking_sendto(socket_type s,- const buf* bufs, size_t count, int flags,- const socket_addr_type* addr, std::size_t addrlen,+ASIO_DECL bool non_blocking_sendto(socket_type s, const buf* bufs,+ size_t count, int flags, const void* addr, std::size_t addrlen, asio::error_code& ec, size_t& bytes_transferred); -ASIO_DECL bool non_blocking_sendto1(socket_type s,- const void* data, size_t size, int flags,- const socket_addr_type* addr, std::size_t addrlen,+ASIO_DECL bool non_blocking_sendto1(socket_type s, const void* data,+ size_t size, int flags, const void* addr, std::size_t addrlen, asio::error_code& ec, size_t& bytes_transferred); #endif // !defined(ASIO_HAS_IOCP)@@ -296,10 +290,10 @@ int level, int optname, void* optval, size_t* optlen, asio::error_code& ec); -ASIO_DECL int getpeername(socket_type s, socket_addr_type* addr,+ASIO_DECL int getpeername(socket_type s, void* addr, std::size_t* addrlen, bool cached, asio::error_code& ec); -ASIO_DECL int getsockname(socket_type s, socket_addr_type* addr,+ASIO_DECL int getsockname(socket_type s, void* addr, std::size_t* addrlen, asio::error_code& ec); ASIO_DECL int ioctl(socket_type s, state_type& state,@@ -344,19 +338,17 @@ ASIO_DECL void freeaddrinfo(addrinfo_type* ai); -ASIO_DECL asio::error_code getnameinfo(- const socket_addr_type* addr, std::size_t addrlen,- char* host, std::size_t hostlen, char* serv,+ASIO_DECL asio::error_code getnameinfo(const void* addr,+ std::size_t addrlen, char* host, std::size_t hostlen, char* serv, std::size_t servlen, int flags, asio::error_code& ec); -ASIO_DECL asio::error_code sync_getnameinfo(- const socket_addr_type* addr, std::size_t addrlen,- char* host, std::size_t hostlen, char* serv,+ASIO_DECL asio::error_code sync_getnameinfo(const void* addr,+ std::size_t addrlen, char* host, std::size_t hostlen, char* serv, std::size_t servlen, int sock_type, asio::error_code& ec); ASIO_DECL asio::error_code background_getnameinfo( const weak_cancel_token_type& cancel_token,- const socket_addr_type* addr, std::size_t addrlen,+ const void* addr, std::size_t addrlen, char* host, std::size_t hostlen, char* serv, std::size_t servlen, int sock_type, asio::error_code& ec);
link/modules/asio-standalone/asio/include/asio/detail/socket_option.hpp view
@@ -2,7 +2,7 @@ // detail/socket_option.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/detail/socket_select_interrupter.hpp view
@@ -2,7 +2,7 @@ // detail/socket_select_interrupter.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/detail/socket_types.hpp view
@@ -2,7 +2,7 @@ // detail/socket_types.hpp // ~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -89,6 +89,7 @@ # include <sys/filio.h> # include <sys/sockio.h> # endif+# include <signal.h> #endif #include "asio/detail/push_options.hpp"@@ -178,6 +179,9 @@ # define ASIO_OS_DEF_AI_V4MAPPED 0x800 # define ASIO_OS_DEF_AI_ALL 0x100 # define ASIO_OS_DEF_AI_ADDRCONFIG 0x400+# define ASIO_OS_DEF_SA_RESTART 0x1+# define ASIO_OS_DEF_SA_NOCLDSTOP 0x2+# define ASIO_OS_DEF_SA_NOCLDWAIT 0x4 #elif defined(ASIO_WINDOWS) || defined(__CYGWIN__) typedef SOCKET socket_type; const SOCKET invalid_socket = INVALID_SOCKET;@@ -206,6 +210,7 @@ typedef u_long u_long_type; typedef u_short u_short_type; typedef int signed_size_type;+struct sockaddr_un_type { u_short sun_family; char sun_path[108]; }; # define ASIO_OS_DEF(c) ASIO_OS_DEF_##c # define ASIO_OS_DEF_AF_UNSPEC AF_UNSPEC # define ASIO_OS_DEF_AF_INET AF_INET@@ -284,6 +289,9 @@ # else const int max_iov_len = 16; # endif+# define ASIO_OS_DEF_SA_RESTART 0x1+# define ASIO_OS_DEF_SA_NOCLDSTOP 0x2+# define ASIO_OS_DEF_SA_NOCLDWAIT 0x4 #else typedef int socket_type; const int invalid_socket = -1;@@ -403,6 +411,9 @@ // POSIX platforms are not required to define IOV_MAX. const int max_iov_len = 16; # endif+# define ASIO_OS_DEF_SA_RESTART SA_RESTART+# define ASIO_OS_DEF_SA_NOCLDSTOP SA_NOCLDSTOP+# define ASIO_OS_DEF_SA_NOCLDWAIT SA_NOCLDWAIT #endif const int custom_socket_option_level = 0xA5100000; const int enable_connection_aborted_option = 1;
link/modules/asio-standalone/asio/include/asio/detail/solaris_fenced_block.hpp view
@@ -2,7 +2,7 @@ // detail/solaris_fenced_block.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/detail/source_location.hpp view
@@ -2,7 +2,7 @@ // detail/source_location.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/detail/static_mutex.hpp view
@@ -2,7 +2,7 @@ // detail/static_mutex.hpp // ~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/detail/std_event.hpp view
@@ -2,7 +2,7 @@ // detail/std_event.hpp // ~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -75,7 +75,7 @@ // Unlock the mutex and signal one waiter who may destroy us. template <typename Lock>- void unlock_and_signal_one(Lock& lock)+ void unlock_and_signal_one_for_destruction(Lock& lock) { ASIO_ASSERT(lock.locked()); state_ |= 1;
link/modules/asio-standalone/asio/include/asio/detail/std_fenced_block.hpp view
@@ -2,7 +2,7 @@ // detail/std_fenced_block.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/detail/std_global.hpp view
@@ -2,7 +2,7 @@ // detail/std_global.hpp // ~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/detail/std_mutex.hpp view
@@ -2,7 +2,7 @@ // detail/std_mutex.hpp // ~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/detail/std_static_mutex.hpp view
@@ -2,7 +2,7 @@ // detail/std_static_mutex.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/detail/std_thread.hpp view
@@ -2,7 +2,7 @@ // detail/std_thread.hpp // ~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/detail/strand_executor_service.hpp view
@@ -2,7 +2,7 @@ // detail/strand_executor_service.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -130,6 +130,13 @@ // Adds a function to the strand. Returns true if it acquires the lock. ASIO_DECL static bool enqueue(const implementation_type& impl, scheduler_operation* op);++ // Transfers waiting handlers to the ready queue. Returns true if one or more+ // handlers were transferred.+ ASIO_DECL static bool push_waiting_to_ready(implementation_type& impl);++ // Invokes all ready-to-run handlers.+ ASIO_DECL static void run_ready_handlers(implementation_type& impl); // Helper function to request invocation of the given function. template <typename Executor, typename Function, typename Allocator>
link/modules/asio-standalone/asio/include/asio/detail/strand_service.hpp view
@@ -2,7 +2,7 @@ // detail/strand_service.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -96,11 +96,10 @@ const implementation_type& impl) const; private:- // Helper function to dispatch a handler. Returns true if the handler should- // be dispatched immediately.- ASIO_DECL bool do_dispatch(implementation_type& impl, operation* op);+ // Helper function to dispatch a handler.+ ASIO_DECL void do_dispatch(implementation_type& impl, operation* op); - // Helper fiunction to post a handler.+ // Helper function to post a handler. ASIO_DECL void do_post(implementation_type& impl, operation* op, bool is_continuation);
link/modules/asio-standalone/asio/include/asio/detail/string_view.hpp view
@@ -2,7 +2,7 @@ // detail/string_view.hpp // ~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/detail/thread.hpp view
@@ -2,7 +2,7 @@ // detail/thread.hpp // ~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -19,6 +19,8 @@ #if !defined(ASIO_HAS_THREADS) # include "asio/detail/null_thread.hpp"+#elif defined(ASIO_HAS_PTHREADS)+# include "asio/detail/posix_thread.hpp" #elif defined(ASIO_WINDOWS) # if defined(UNDER_CE) # include "asio/detail/wince_thread.hpp"@@ -27,8 +29,6 @@ # else # include "asio/detail/win_thread.hpp" # endif-#elif defined(ASIO_HAS_PTHREADS)-# include "asio/detail/posix_thread.hpp" #elif defined(ASIO_HAS_STD_THREAD) # include "asio/detail/std_thread.hpp" #else@@ -40,6 +40,8 @@ #if !defined(ASIO_HAS_THREADS) typedef null_thread thread;+#elif defined(ASIO_HAS_PTHREADS)+typedef posix_thread thread; #elif defined(ASIO_WINDOWS) # if defined(UNDER_CE) typedef wince_thread thread;@@ -48,8 +50,6 @@ # else typedef win_thread thread; # endif-#elif defined(ASIO_HAS_PTHREADS)-typedef posix_thread thread; #elif defined(ASIO_HAS_STD_THREAD) typedef std_thread thread; #endif
link/modules/asio-standalone/asio/include/asio/detail/thread_context.hpp view
@@ -2,7 +2,7 @@ // detail/thread_context.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -30,6 +30,11 @@ class thread_context { public:+ // Obtain a pointer to the top of the thread call stack. Returns null when+ // not running inside a thread context.+ ASIO_DECL static thread_info_base* top_of_thread_call_stack();++protected: // Per-thread call stack to track the state of each thread in the context. typedef call_stack<thread_context, thread_info_base> thread_call_stack; };@@ -38,5 +43,9 @@ } // namespace asio #include "asio/detail/pop_options.hpp"++#if defined(ASIO_HEADER_ONLY)+# include "asio/detail/impl/thread_context.ipp"+#endif // defined(ASIO_HEADER_ONLY) #endif // ASIO_DETAIL_THREAD_CONTEXT_HPP
link/modules/asio-standalone/asio/include/asio/detail/thread_group.hpp view
@@ -2,7 +2,7 @@ // detail/thread_group.hpp // ~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -19,6 +19,8 @@ #include "asio/detail/scoped_ptr.hpp" #include "asio/detail/thread.hpp" +#include "asio/detail/push_options.hpp"+ namespace asio { namespace detail { @@ -91,5 +93,7 @@ } // namespace detail } // namespace asio++#include "asio/detail/pop_options.hpp" #endif // ASIO_DETAIL_THREAD_GROUP_HPP
link/modules/asio-standalone/asio/include/asio/detail/thread_info_base.hpp view
@@ -2,7 +2,7 @@ // detail/thread_info_base.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -18,6 +18,7 @@ #include "asio/detail/config.hpp" #include <climits> #include <cstddef>+#include "asio/detail/memory.hpp" #include "asio/detail/noncopyable.hpp" #if defined(ASIO_HAS_STD_EXCEPTION_PTR) \@@ -32,25 +33,66 @@ namespace asio { namespace detail { +#ifndef ASIO_RECYCLING_ALLOCATOR_CACHE_SIZE+# define ASIO_RECYCLING_ALLOCATOR_CACHE_SIZE 2+#endif // ASIO_RECYCLING_ALLOCATOR_CACHE_SIZE+ class thread_info_base : private noncopyable { public: struct default_tag {- enum { mem_index = 0 };+ enum+ {+ cache_size = ASIO_RECYCLING_ALLOCATOR_CACHE_SIZE,+ begin_mem_index = 0,+ end_mem_index = cache_size+ }; }; struct awaitable_frame_tag {- enum { mem_index = 1 };+ enum+ {+ cache_size = ASIO_RECYCLING_ALLOCATOR_CACHE_SIZE,+ begin_mem_index = default_tag::end_mem_index,+ end_mem_index = begin_mem_index + cache_size+ }; }; struct executor_function_tag {- enum { mem_index = 2 };+ enum+ {+ cache_size = ASIO_RECYCLING_ALLOCATOR_CACHE_SIZE,+ begin_mem_index = awaitable_frame_tag::end_mem_index,+ end_mem_index = begin_mem_index + cache_size+ }; }; + struct cancellation_signal_tag+ {+ enum+ {+ cache_size = ASIO_RECYCLING_ALLOCATOR_CACHE_SIZE,+ begin_mem_index = executor_function_tag::end_mem_index,+ end_mem_index = begin_mem_index + cache_size+ };+ };++ struct parallel_group_tag+ {+ enum+ {+ cache_size = ASIO_RECYCLING_ALLOCATOR_CACHE_SIZE,+ begin_mem_index = cancellation_signal_tag::end_mem_index,+ end_mem_index = begin_mem_index + cache_size+ };+ };++ enum { max_mem_index = parallel_group_tag::end_mem_index };+ thread_info_base() #if defined(ASIO_HAS_STD_EXCEPTION_PTR) \ && !defined(ASIO_NO_EXCEPTIONS)@@ -59,24 +101,25 @@ // && !defined(ASIO_NO_EXCEPTIONS) { for (int i = 0; i < max_mem_index; ++i)+ reusable_memory_[i] = 0;+ }++ ~thread_info_base()+ {+ for (int i = 0; i < max_mem_index; ++i) { // The following test for non-null pointers is technically redundant, but // it is significantly faster when using a tight io_context::poll() loop // in latency sensitive applications. if (reusable_memory_[i])- reusable_memory_[i] = 0;+ aligned_delete(reusable_memory_[i]); } } - ~thread_info_base()- {- for (int i = 0; i < max_mem_index; ++i)- ::operator delete(reusable_memory_[i]);- }-- static void* allocate(thread_info_base* this_thread, std::size_t size)+ static void* allocate(thread_info_base* this_thread,+ std::size_t size, std::size_t align = ASIO_DEFAULT_ALIGN) {- return allocate(default_tag(), this_thread, size);+ return allocate(default_tag(), this_thread, size, align); } static void deallocate(thread_info_base* this_thread,@@ -87,26 +130,43 @@ template <typename Purpose> static void* allocate(Purpose, thread_info_base* this_thread,- std::size_t size)+ std::size_t size, std::size_t align = ASIO_DEFAULT_ALIGN) { std::size_t chunks = (size + chunk_size - 1) / chunk_size; - if (this_thread && this_thread->reusable_memory_[Purpose::mem_index])+ if (this_thread) {- void* const pointer = this_thread->reusable_memory_[Purpose::mem_index];- this_thread->reusable_memory_[Purpose::mem_index] = 0;-- unsigned char* const mem = static_cast<unsigned char*>(pointer);- if (static_cast<std::size_t>(mem[0]) >= chunks)+ for (int mem_index = Purpose::begin_mem_index;+ mem_index < Purpose::end_mem_index; ++mem_index) {- mem[size] = mem[0];- return pointer;+ if (this_thread->reusable_memory_[mem_index])+ {+ void* const pointer = this_thread->reusable_memory_[mem_index];+ unsigned char* const mem = static_cast<unsigned char*>(pointer);+ if (static_cast<std::size_t>(mem[0]) >= chunks+ && reinterpret_cast<std::size_t>(pointer) % align == 0)+ {+ this_thread->reusable_memory_[mem_index] = 0;+ mem[size] = mem[0];+ return pointer;+ }+ } } - ::operator delete(pointer);+ for (int mem_index = Purpose::begin_mem_index;+ mem_index < Purpose::end_mem_index; ++mem_index)+ {+ if (this_thread->reusable_memory_[mem_index])+ {+ void* const pointer = this_thread->reusable_memory_[mem_index];+ this_thread->reusable_memory_[mem_index] = 0;+ aligned_delete(pointer);+ break;+ }+ } } - void* const pointer = ::operator new(chunks * chunk_size + 1);+ void* const pointer = aligned_new(align, chunks * chunk_size + 1); unsigned char* const mem = static_cast<unsigned char*>(pointer); mem[size] = (chunks <= UCHAR_MAX) ? static_cast<unsigned char>(chunks) : 0; return pointer;@@ -118,16 +178,23 @@ { if (size <= chunk_size * UCHAR_MAX) {- if (this_thread && this_thread->reusable_memory_[Purpose::mem_index] == 0)+ if (this_thread) {- unsigned char* const mem = static_cast<unsigned char*>(pointer);- mem[0] = mem[size];- this_thread->reusable_memory_[Purpose::mem_index] = pointer;- return;+ for (int mem_index = Purpose::begin_mem_index;+ mem_index < Purpose::end_mem_index; ++mem_index)+ {+ if (this_thread->reusable_memory_[mem_index] == 0)+ {+ unsigned char* const mem = static_cast<unsigned char*>(pointer);+ mem[0] = mem[size];+ this_thread->reusable_memory_[mem_index] = pointer;+ return;+ }+ } } } - ::operator delete(pointer);+ aligned_delete(pointer); } void capture_current_exception()@@ -145,6 +212,7 @@ pending_exception_ = std::make_exception_ptr<multiple_exceptions>( multiple_exceptions(pending_exception_));+ break; default: break; }@@ -169,8 +237,11 @@ } private:+#if defined(ASIO_HAS_IO_URING)+ enum { chunk_size = 8 };+#else // defined(ASIO_HAS_IO_URING) enum { chunk_size = 4 };- enum { max_mem_index = 3 };+#endif // defined(ASIO_HAS_IO_URING) void* reusable_memory_[max_mem_index]; #if defined(ASIO_HAS_STD_EXCEPTION_PTR) \
link/modules/asio-standalone/asio/include/asio/detail/throw_error.hpp view
@@ -2,7 +2,7 @@ // detail/throw_error.hpp // ~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -16,6 +16,7 @@ #endif // defined(_MSC_VER) && (_MSC_VER >= 1200) #include "asio/detail/config.hpp"+#include "asio/detail/throw_exception.hpp" #include "asio/error_code.hpp" #include "asio/detail/push_options.hpp"@@ -23,22 +24,30 @@ namespace asio { namespace detail { -ASIO_DECL void do_throw_error(const asio::error_code& err);+ASIO_DECL void do_throw_error(+ const asio::error_code& err+ ASIO_SOURCE_LOCATION_PARAM); -ASIO_DECL void do_throw_error(const asio::error_code& err,- const char* location);+ASIO_DECL void do_throw_error(+ const asio::error_code& err,+ const char* location+ ASIO_SOURCE_LOCATION_PARAM); -inline void throw_error(const asio::error_code& err)+inline void throw_error(+ const asio::error_code& err+ ASIO_SOURCE_LOCATION_DEFAULTED_PARAM) { if (err)- do_throw_error(err);+ do_throw_error(err ASIO_SOURCE_LOCATION_ARG); } -inline void throw_error(const asio::error_code& err,- const char* location)+inline void throw_error(+ const asio::error_code& err,+ const char* location+ ASIO_SOURCE_LOCATION_DEFAULTED_PARAM) { if (err)- do_throw_error(err, location);+ do_throw_error(err, location ASIO_SOURCE_LOCATION_ARG); } } // namespace detail
link/modules/asio-standalone/asio/include/asio/detail/throw_exception.hpp view
@@ -2,7 +2,7 @@ // detail/throw_exception.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -30,14 +30,18 @@ // Declare the throw_exception function for all targets. template <typename Exception>-void throw_exception(const Exception& e);+void throw_exception(+ const Exception& e+ ASIO_SOURCE_LOCATION_DEFAULTED_PARAM); // Only define the throw_exception function when exceptions are enabled. // Otherwise, it is up to the application to provide a definition of this // function. # if !defined(ASIO_NO_EXCEPTIONS) template <typename Exception>-void throw_exception(const Exception& e)+void throw_exception(+ const Exception& e+ ASIO_SOURCE_LOCATION_PARAM) { throw e; }
link/modules/asio-standalone/asio/include/asio/detail/timer_queue.hpp view
@@ -2,7 +2,7 @@ // detail/timer_queue.hpp // ~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -150,7 +150,12 @@ while (!heap_.empty() && !Time_Traits::less_than(now, heap_[0].time_)) { per_timer_data* timer = heap_[0].timer_;- ops.push(timer->op_queue_);+ while (wait_op* op = timer->op_queue_.front())+ {+ timer->op_queue_.pop();+ op->ec_ = asio::error_code();+ ops.push(op);+ } remove_timer(*timer); } }@@ -190,6 +195,30 @@ remove_timer(timer); } return num_cancelled;+ }++ // Cancel and dequeue a specific operation for the given timer.+ void cancel_timer_by_key(per_timer_data* timer,+ op_queue<operation>& ops, void* cancellation_key)+ {+ if (timer->prev_ != 0 || timer == timers_)+ {+ op_queue<wait_op> other_ops;+ while (wait_op* op = timer->op_queue_.front())+ {+ timer->op_queue_.pop();+ if (op->cancellation_key_ == cancellation_key)+ {+ op->ec_ = asio::error::operation_aborted;+ ops.push(op);+ }+ else+ other_ops.push(op);+ }+ timer->op_queue_.push(other_ops);+ if (timer->op_queue_.empty())+ remove_timer(*timer);+ } } // Move operations from one timer to another, empty timer.
link/modules/asio-standalone/asio/include/asio/detail/timer_queue_base.hpp view
@@ -2,7 +2,7 @@ // detail/timer_queue_base.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/detail/timer_queue_ptime.hpp view
@@ -2,7 +2,7 @@ // detail/timer_queue_ptime.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -76,6 +76,10 @@ ASIO_DECL std::size_t cancel_timer( per_timer_data& timer, op_queue<operation>& ops, std::size_t max_cancelled = (std::numeric_limits<std::size_t>::max)());++ // Cancel and dequeue operations for the given timer and key.+ ASIO_DECL void cancel_timer_by_key(per_timer_data* timer,+ op_queue<operation>& ops, void* cancellation_key); // Move operations from one timer to another, empty timer. ASIO_DECL void move_timer(per_timer_data& target,
link/modules/asio-standalone/asio/include/asio/detail/timer_queue_set.hpp view
@@ -2,7 +2,7 @@ // detail/timer_queue_set.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/detail/timer_scheduler.hpp view
@@ -2,7 +2,7 @@ // detail/timer_scheduler.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -22,6 +22,8 @@ # include "asio/detail/winrt_timer_scheduler.hpp" #elif defined(ASIO_HAS_IOCP) # include "asio/detail/win_iocp_io_context.hpp"+#elif defined(ASIO_HAS_IO_URING_AS_DEFAULT)+# include "asio/detail/io_uring_service.hpp" #elif defined(ASIO_HAS_EPOLL) # include "asio/detail/epoll_reactor.hpp" #elif defined(ASIO_HAS_KQUEUE)
link/modules/asio-standalone/asio/include/asio/detail/timer_scheduler_fwd.hpp view
@@ -2,7 +2,7 @@ // detail/timer_scheduler_fwd.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -24,6 +24,8 @@ typedef class winrt_timer_scheduler timer_scheduler; #elif defined(ASIO_HAS_IOCP) typedef class win_iocp_io_context timer_scheduler;+#elif defined(ASIO_HAS_IO_URING_AS_DEFAULT)+typedef class io_uring_service timer_scheduler; #elif defined(ASIO_HAS_EPOLL) typedef class epoll_reactor timer_scheduler; #elif defined(ASIO_HAS_KQUEUE)
link/modules/asio-standalone/asio/include/asio/detail/tss_ptr.hpp view
@@ -2,7 +2,7 @@ // detail/tss_ptr.hpp // ~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/detail/type_traits.hpp view
@@ -2,7 +2,7 @@ // detail/type_traits.hpp // ~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -38,6 +38,7 @@ # include <boost/type_traits/is_destructible.hpp> # include <boost/type_traits/is_function.hpp> # include <boost/type_traits/is_object.hpp>+# include <boost/type_traits/is_pointer.hpp> # include <boost/type_traits/is_same.hpp> # include <boost/type_traits/remove_cv.hpp> # include <boost/type_traits/remove_pointer.hpp>@@ -52,7 +53,12 @@ #if defined(ASIO_HAS_STD_TYPE_TRAITS) using std::add_const; using std::add_lvalue_reference;+#if defined(ASIO_MSVC) && (_MSC_VER < 1900) using std::aligned_storage;+#else // defined(ASIO_MSVC) && (_MSC_VER < 1900)+template <std::size_t N, std::size_t A>+struct aligned_storage { struct type { alignas(A) unsigned char data[N]; }; };+#endif // defined(ASIO_MSVC) && (_MSC_VER < 1900) using std::alignment_of; using std::conditional; using std::decay;@@ -72,6 +78,7 @@ using std::is_nothrow_copy_constructible; using std::is_nothrow_destructible; using std::is_object;+using std::is_pointer; using std::is_reference; using std::is_same; using std::is_scalar;@@ -120,6 +127,7 @@ template <typename T> struct is_nothrow_destructible : boost::has_nothrow_destructor<T> {}; using boost::is_object;+using boost::is_pointer; using boost::is_reference; using boost::is_same; using boost::is_scalar;@@ -142,6 +150,14 @@ conditional<Head::value, conjunction<Tail...>, Head>::type {}; #endif // defined(ASIO_HAS_VARIADIC_TEMPLATES)++struct defaulted_constraint+{+ ASIO_CONSTEXPR defaulted_constraint() {}+};++template <bool Condition, typename Type = int>+struct constraint : enable_if<Condition, Type> {}; } // namespace asio
+ link/modules/asio-standalone/asio/include/asio/detail/utility.hpp view
@@ -0,0 +1,83 @@+//+// detail/utility.hpp+// ~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com)+//+// Distributed under the Boost Software License, Version 1.0. (See accompanying+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)+//++#ifndef ASIO_DETAIL_UTILITY_HPP+#define ASIO_DETAIL_UTILITY_HPP++#if defined(_MSC_VER) && (_MSC_VER >= 1200)+# pragma once+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)++#include "asio/detail/config.hpp"+#include <utility>++namespace asio {+namespace detail {++#if defined(ASIO_HAS_STD_INDEX_SEQUENCE)++using std::index_sequence;+using std::index_sequence_for;+using std::make_index_sequence;++#elif defined(ASIO_HAS_VARIADIC_TEMPLATES)++template <std::size_t...>+struct index_sequence+{+};++template <typename T, typename U>+struct join_index_sequences;++template <std::size_t... I, std::size_t... J>+struct join_index_sequences<index_sequence<I...>, index_sequence<J...> >+{+ using type = index_sequence<I..., J...>;+};++template <std::size_t First, std::size_t Last>+struct index_pack :+ join_index_sequences<+ typename index_pack<First, First + (Last - First + 1) / 2 - 1>::type,+ typename index_pack<First + (Last - First + 1) / 2, Last>::type+ >+{+};++template <std::size_t N>+struct index_pack<N, N>+{+ using type = index_sequence<N>;+};++template <std::size_t Begin, std::size_t End>+struct index_range : index_pack<Begin, End - 1>+{+};++template <std::size_t N>+struct index_range<N, N>+{+ using type = index_sequence<>;+};++template <typename... T>+using index_sequence_for = typename index_range<0, sizeof...(T)>::type;++template <std::size_t N>+using make_index_sequence = typename index_range<0, N>::type;++#endif // defined(ASIO_HAS_VARIADIC_TEMPLATES)++} // namespace detail+} // namespace asio++#endif // ASIO_DETAIL_UTILITY_HPP
link/modules/asio-standalone/asio/include/asio/detail/variadic_templates.hpp view
@@ -2,7 +2,7 @@ // detail/variadic_templates.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/detail/wait_handler.hpp view
@@ -2,7 +2,7 @@ // detail/wait_handler.hpp // ~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/detail/wait_op.hpp view
@@ -2,7 +2,7 @@ // detail/wait_op.hpp // ~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -30,9 +30,13 @@ // The error code to be passed to the completion handler. asio::error_code ec_; + // The operation key used for targeted cancellation.+ void* cancellation_key_;+ protected: wait_op(func_type func)- : operation(func)+ : operation(func),+ cancellation_key_(0) { } };
link/modules/asio-standalone/asio/include/asio/detail/win_event.hpp view
@@ -2,7 +2,7 @@ // detail/win_event.hpp // ~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/detail/win_fd_set_adapter.hpp view
@@ -2,7 +2,7 @@ // detail/win_fd_set_adapter.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/detail/win_fenced_block.hpp view
@@ -2,7 +2,7 @@ // detail/win_fenced_block.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/detail/win_global.hpp view
@@ -2,7 +2,7 @@ // detail/win_global.hpp // ~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+ link/modules/asio-standalone/asio/include/asio/detail/win_iocp_file_service.hpp view
@@ -0,0 +1,287 @@+//+// detail/win_iocp_file_service.hpp+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com)+//+// Distributed under the Boost Software License, Version 1.0. (See accompanying+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)+//++#ifndef ASIO_DETAIL_WIN_IOCP_FILE_SERVICE_HPP+#define ASIO_DETAIL_WIN_IOCP_FILE_SERVICE_HPP++#if defined(_MSC_VER) && (_MSC_VER >= 1200)+# pragma once+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)++#include "asio/detail/config.hpp"++#if defined(ASIO_HAS_IOCP) && defined(ASIO_HAS_FILE)++#include <string>+#include "asio/detail/cstdint.hpp"+#include "asio/detail/win_iocp_handle_service.hpp"+#include "asio/error.hpp"+#include "asio/execution_context.hpp"+#include "asio/file_base.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {+namespace detail {++// Extend win_iocp_handle_service to provide file support.+class win_iocp_file_service :+ public execution_context_service_base<win_iocp_file_service>+{+public:+ // The native type of a file.+ typedef win_iocp_handle_service::native_handle_type native_handle_type;++ // The implementation type of the file.+ class implementation_type : win_iocp_handle_service::implementation_type+ {+ private:+ // Only this service will have access to the internal values.+ friend class win_iocp_file_service;++ uint64_t offset_;+ bool is_stream_;+ };++ // Constructor.+ ASIO_DECL win_iocp_file_service(execution_context& context);++ // Destroy all user-defined handler objects owned by the service.+ ASIO_DECL void shutdown();++ // Construct a new file implementation.+ void construct(implementation_type& impl)+ {+ handle_service_.construct(impl);+ impl.offset_ = 0;+ impl.is_stream_ = false;+ }++ // Move-construct a new file implementation.+ void move_construct(implementation_type& impl,+ implementation_type& other_impl)+ {+ handle_service_.move_construct(impl, other_impl);+ impl.offset_ = other_impl.offset_;+ impl.is_stream_ = other_impl.is_stream_;+ other_impl.offset_ = 0;+ }++ // Move-assign from another file implementation.+ void move_assign(implementation_type& impl,+ win_iocp_file_service& other_service,+ implementation_type& other_impl)+ {+ handle_service_.move_assign(impl,+ other_service.handle_service_, other_impl);+ impl.offset_ = other_impl.offset_;+ impl.is_stream_ = other_impl.is_stream_;+ other_impl.offset_ = 0;+ }++ // Destroy a file implementation.+ void destroy(implementation_type& impl)+ {+ handle_service_.destroy(impl);+ }++ // Set whether the implementation is stream-oriented.+ void set_is_stream(implementation_type& impl, bool is_stream)+ {+ impl.is_stream_ = is_stream;+ }++ // Open the file using the specified path name.+ ASIO_DECL asio::error_code open(implementation_type& impl,+ const char* path, file_base::flags open_flags,+ asio::error_code& ec);++ // Assign a native handle to a file implementation.+ asio::error_code assign(implementation_type& impl,+ const native_handle_type& native_handle,+ asio::error_code& ec)+ {+ return handle_service_.assign(impl, native_handle, ec);+ }++ // Determine whether the file is open.+ bool is_open(const implementation_type& impl) const+ {+ return handle_service_.is_open(impl);+ }++ // Destroy a file implementation.+ asio::error_code close(implementation_type& impl,+ asio::error_code& ec)+ {+ return handle_service_.close(impl, ec);+ }++ // Get the native file representation.+ native_handle_type native_handle(const implementation_type& impl) const+ {+ return handle_service_.native_handle(impl);+ }++ // Release ownership of a file.+ native_handle_type release(implementation_type& impl,+ asio::error_code& ec)+ {+ return handle_service_.release(impl, ec);+ }++ // Cancel all operations associated with the file.+ asio::error_code cancel(implementation_type& impl,+ asio::error_code& ec)+ {+ return handle_service_.cancel(impl, ec);+ }++ // Get the size of the file.+ ASIO_DECL uint64_t size(const implementation_type& impl,+ asio::error_code& ec) const;++ // Alter the size of the file.+ ASIO_DECL asio::error_code resize(implementation_type& impl,+ uint64_t n, asio::error_code& ec);++ // Synchronise the file to disk.+ ASIO_DECL asio::error_code sync_all(implementation_type& impl,+ asio::error_code& ec);++ // Synchronise the file data to disk.+ ASIO_DECL asio::error_code sync_data(implementation_type& impl,+ asio::error_code& ec);++ // Seek to a position in the file.+ ASIO_DECL uint64_t seek(implementation_type& impl, int64_t offset,+ file_base::seek_basis whence, asio::error_code& ec);++ // Write the given data. Returns the number of bytes written.+ template <typename ConstBufferSequence>+ size_t write_some(implementation_type& impl,+ const ConstBufferSequence& buffers, asio::error_code& ec)+ {+ uint64_t offset = impl.offset_;+ impl.offset_ += asio::buffer_size(buffers);+ return handle_service_.write_some_at(impl, offset, buffers, ec);+ }++ // Start an asynchronous write. The data being written must be valid for the+ // lifetime of the asynchronous operation.+ template <typename ConstBufferSequence, typename Handler, typename IoExecutor>+ void async_write_some(implementation_type& impl,+ const ConstBufferSequence& buffers,+ Handler& handler, const IoExecutor& io_ex)+ {+ uint64_t offset = impl.offset_;+ impl.offset_ += asio::buffer_size(buffers);+ handle_service_.async_write_some_at(impl, offset, buffers, handler, io_ex);+ }++ // Write the given data at the specified location. Returns the number of+ // bytes written.+ template <typename ConstBufferSequence>+ size_t write_some_at(implementation_type& impl, uint64_t offset,+ const ConstBufferSequence& buffers, asio::error_code& ec)+ {+ return handle_service_.write_some_at(impl, offset, buffers, ec);+ }++ // Start an asynchronous write at the specified location. The data being+ // written must be valid for the lifetime of the asynchronous operation.+ template <typename ConstBufferSequence, typename Handler, typename IoExecutor>+ void async_write_some_at(implementation_type& impl,+ uint64_t offset, const ConstBufferSequence& buffers,+ Handler& handler, const IoExecutor& io_ex)+ {+ handle_service_.async_write_some_at(impl, offset, buffers, handler, io_ex);+ }++ // Read some data. Returns the number of bytes read.+ template <typename MutableBufferSequence>+ size_t read_some(implementation_type& impl,+ const MutableBufferSequence& buffers, asio::error_code& ec)+ {+ uint64_t offset = impl.offset_;+ impl.offset_ += asio::buffer_size(buffers);+ return handle_service_.read_some_at(impl, offset, buffers, ec);+ }++ // Start an asynchronous read. The buffer for the data being read must be+ // valid for the lifetime of the asynchronous operation.+ template <typename MutableBufferSequence,+ typename Handler, typename IoExecutor>+ void async_read_some(implementation_type& impl,+ const MutableBufferSequence& buffers,+ Handler& handler, const IoExecutor& io_ex)+ {+ uint64_t offset = impl.offset_;+ impl.offset_ += asio::buffer_size(buffers);+ handle_service_.async_read_some_at(impl, offset, buffers, handler, io_ex);+ }++ // Read some data. Returns the number of bytes read.+ template <typename MutableBufferSequence>+ size_t read_some_at(implementation_type& impl, uint64_t offset,+ const MutableBufferSequence& buffers, asio::error_code& ec)+ {+ return handle_service_.read_some_at(impl, offset, buffers, ec);+ }++ // Start an asynchronous read. The buffer for the data being read must be+ // valid for the lifetime of the asynchronous operation.+ template <typename MutableBufferSequence,+ typename Handler, typename IoExecutor>+ void async_read_some_at(implementation_type& impl,+ uint64_t offset, const MutableBufferSequence& buffers,+ Handler& handler, const IoExecutor& io_ex)+ {+ handle_service_.async_read_some_at(impl, offset, buffers, handler, io_ex);+ }++private:+ // The implementation used for initiating asynchronous operations.+ win_iocp_handle_service handle_service_;++ // Emulation of Windows IO_STATUS_BLOCK structure.+ struct io_status_block+ {+ union u+ {+ LONG Status;+ void* Pointer;+ };+ ULONG_PTR Information;+ };++ // Emulation of flag passed to NtFlushBuffersFileEx.+ enum { flush_flags_file_data_sync_only = 4 };++ // The type of a NtFlushBuffersFileEx function pointer.+ typedef LONG (NTAPI *nt_flush_buffers_file_ex_fn)(+ HANDLE, ULONG, void*, ULONG, io_status_block*);++ // The NTFlushBuffersFileEx function pointer.+ nt_flush_buffers_file_ex_fn nt_flush_buffers_file_ex_;+};++} // namespace detail+} // namespace asio++#include "asio/detail/pop_options.hpp"++#if defined(ASIO_HEADER_ONLY)+# include "asio/detail/impl/win_iocp_file_service.ipp"+#endif // defined(ASIO_HEADER_ONLY)++#endif // defined(ASIO_HAS_IOCP) && defined(ASIO_HAS_FILE)++#endif // ASIO_DETAIL_WIN_IOCP_FILE_SERVICE_HPP
link/modules/asio-standalone/asio/include/asio/detail/win_iocp_handle_read_op.hpp view
@@ -2,7 +2,7 @@ // detail/win_iocp_handle_read_op.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // Copyright (c) 2008 Rep Invariant Systems, Inc. (info@repinvariant.com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying@@ -57,6 +57,7 @@ asio::error_code ec(result_ec); // Take ownership of the operation object.+ ASIO_ASSUME(base != 0); win_iocp_handle_read_op* o(static_cast<win_iocp_handle_read_op*>(base)); ptr p = { asio::detail::addressof(o->handler_), o, o }; @@ -79,6 +80,8 @@ // Map non-portable errors to their portable counterparts. if (ec.value() == ERROR_HANDLE_EOF) ec = asio::error::eof;++ ASIO_ERROR_LOCATION(ec); // Make a copy of the handler so that the memory can be deallocated before // the upcall is made. Even if we're not about to make an upcall, a
link/modules/asio-standalone/asio/include/asio/detail/win_iocp_handle_service.hpp view
@@ -2,7 +2,7 @@ // detail/win_iocp_handle_service.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // Copyright (c) 2008 Rep Invariant Systems, Inc. (info@repinvariant.com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying@@ -20,6 +20,7 @@ #if defined(ASIO_HAS_IOCP) +#include "asio/associated_cancellation_slot.hpp" #include "asio/error.hpp" #include "asio/execution_context.hpp" #include "asio/detail/buffer_sequence_adapter.hpp"@@ -109,6 +110,10 @@ ASIO_DECL asio::error_code close(implementation_type& impl, asio::error_code& ec); + // Release ownership of a handle.+ ASIO_DECL native_handle_type release(implementation_type& impl,+ asio::error_code& ec);+ // Get the native handle representation. native_handle_type native_handle(const implementation_type& impl) const {@@ -147,19 +152,26 @@ const ConstBufferSequence& buffers, Handler& handler, const IoExecutor& io_ex) {+ typename associated_cancellation_slot<Handler>::type slot+ = asio::get_associated_cancellation_slot(handler);+ // Allocate and construct an operation to wrap the handler. typedef win_iocp_handle_write_op< ConstBufferSequence, Handler, IoExecutor> op; typename op::ptr p = { asio::detail::addressof(handler), op::ptr::allocate(handler), 0 };- p.p = new (p.v) op(buffers, handler, io_ex);+ operation* o = p.p = new (p.v) op(buffers, handler, io_ex); ASIO_HANDLER_CREATION((iocp_service_.context(), *p.p, "handle", &impl, reinterpret_cast<uintmax_t>(impl.handle_), "async_write_some")); + // Optionally register for per-operation cancellation.+ if (slot.is_connected())+ o = &slot.template emplace<iocp_op_cancellation>(impl.handle_, o);+ start_write_op(impl, 0, buffer_sequence_adapter<asio::const_buffer,- ConstBufferSequence>::first(buffers), p.p);+ ConstBufferSequence>::first(buffers), o); p.v = p.p = 0; } @@ -170,19 +182,26 @@ uint64_t offset, const ConstBufferSequence& buffers, Handler& handler, const IoExecutor& io_ex) {+ typename associated_cancellation_slot<Handler>::type slot+ = asio::get_associated_cancellation_slot(handler);+ // Allocate and construct an operation to wrap the handler. typedef win_iocp_handle_write_op< ConstBufferSequence, Handler, IoExecutor> op; typename op::ptr p = { asio::detail::addressof(handler), op::ptr::allocate(handler), 0 };- p.p = new (p.v) op(buffers, handler, io_ex);+ operation* o = p.p = new (p.v) op(buffers, handler, io_ex); ASIO_HANDLER_CREATION((iocp_service_.context(), *p.p, "handle", &impl, reinterpret_cast<uintmax_t>(impl.handle_), "async_write_some_at")); + // Optionally register for per-operation cancellation.+ if (slot.is_connected())+ o = &slot.template emplace<iocp_op_cancellation>(impl.handle_, o);+ start_write_op(impl, offset, buffer_sequence_adapter<asio::const_buffer,- ConstBufferSequence>::first(buffers), p.p);+ ConstBufferSequence>::first(buffers), o); p.v = p.p = 0; } @@ -214,19 +233,26 @@ const MutableBufferSequence& buffers, Handler& handler, const IoExecutor& io_ex) {+ typename associated_cancellation_slot<Handler>::type slot+ = asio::get_associated_cancellation_slot(handler);+ // Allocate and construct an operation to wrap the handler. typedef win_iocp_handle_read_op< MutableBufferSequence, Handler, IoExecutor> op; typename op::ptr p = { asio::detail::addressof(handler), op::ptr::allocate(handler), 0 };- p.p = new (p.v) op(buffers, handler, io_ex);+ operation* o = p.p = new (p.v) op(buffers, handler, io_ex); ASIO_HANDLER_CREATION((iocp_service_.context(), *p.p, "handle", &impl, reinterpret_cast<uintmax_t>(impl.handle_), "async_read_some")); + // Optionally register for per-operation cancellation.+ if (slot.is_connected())+ o = &slot.template emplace<iocp_op_cancellation>(impl.handle_, o);+ start_read_op(impl, 0, buffer_sequence_adapter<asio::mutable_buffer,- MutableBufferSequence>::first(buffers), p.p);+ MutableBufferSequence>::first(buffers), o); p.v = p.p = 0; } @@ -239,19 +265,26 @@ uint64_t offset, const MutableBufferSequence& buffers, Handler& handler, const IoExecutor& io_ex) {+ typename associated_cancellation_slot<Handler>::type slot+ = asio::get_associated_cancellation_slot(handler);+ // Allocate and construct an operation to wrap the handler. typedef win_iocp_handle_read_op< MutableBufferSequence, Handler, IoExecutor> op; typename op::ptr p = { asio::detail::addressof(handler), op::ptr::allocate(handler), 0 };- p.p = new (p.v) op(buffers, handler, io_ex);+ operation* o = p.p = new (p.v) op(buffers, handler, io_ex); ASIO_HANDLER_CREATION((iocp_service_.context(), *p.p, "handle", &impl, reinterpret_cast<uintmax_t>(impl.handle_), "async_read_some_at")); + // Optionally register for per-operation cancellation.+ if (slot.is_connected())+ o = &slot.template emplace<iocp_op_cancellation>(impl.handle_, o);+ start_read_op(impl, offset, buffer_sequence_adapter<asio::mutable_buffer,- MutableBufferSequence>::first(buffers), p.p);+ MutableBufferSequence>::first(buffers), o); p.v = p.p = 0; } @@ -310,9 +343,72 @@ // destroyed. ASIO_DECL void close_for_destruction(implementation_type& impl); + // The type of a NtSetInformationFile function pointer.+ typedef LONG (NTAPI *nt_set_info_fn)(HANDLE, ULONG_PTR*, void*, ULONG, ULONG);++ // Helper function to get the NtSetInformationFile function pointer. If no+ // NtSetInformationFile pointer has been obtained yet, one is obtained using+ // GetProcAddress and the pointer is cached. Returns a null pointer if+ // NtSetInformationFile is not available.+ ASIO_DECL nt_set_info_fn get_nt_set_info();++ // Helper function to emulate InterlockedCompareExchangePointer functionality+ // for:+ // - very old Platform SDKs; and+ // - platform SDKs where MSVC's /Wp64 option causes spurious warnings.+ ASIO_DECL void* interlocked_compare_exchange_pointer(+ void** dest, void* exch, void* cmp);++ // Helper function to emulate InterlockedExchangePointer functionality for:+ // - very old Platform SDKs; and+ // - platform SDKs where MSVC's /Wp64 option causes spurious warnings.+ ASIO_DECL void* interlocked_exchange_pointer(void** dest, void* val);++ // Helper class used to implement per operation cancellation.+ class iocp_op_cancellation : public operation+ {+ public:+ iocp_op_cancellation(HANDLE h, operation* target)+ : operation(&iocp_op_cancellation::do_complete),+ handle_(h),+ target_(target)+ {+ }++ static void do_complete(void* owner, operation* base,+ const asio::error_code& result_ec,+ std::size_t bytes_transferred)+ {+ iocp_op_cancellation* o = static_cast<iocp_op_cancellation*>(base);+ o->target_->complete(owner, result_ec, bytes_transferred);+ }++ void operator()(cancellation_type_t type)+ {+#if defined(_WIN32_WINNT) && (_WIN32_WINNT >= 0x0600)+ if (!!(type &+ (cancellation_type::terminal+ | cancellation_type::partial+ | cancellation_type::total)))+ {+ ::CancelIoEx(handle_, this);+ }+#else // defined(_WIN32_WINNT) && (_WIN32_WINNT >= 0x0600)+ (void)type;+#endif // defined(_WIN32_WINNT) && (_WIN32_WINNT >= 0x0600)+ }++ private:+ HANDLE handle_;+ operation* target_;+ };+ // The IOCP service used for running asynchronous operations and dispatching // handlers. win_iocp_io_context& iocp_service_;++ // Pointer to NtSetInformationFile implementation.+ void* nt_set_info_; // Mutex to protect access to the linked list of implementations. mutex mutex_;
link/modules/asio-standalone/asio/include/asio/detail/win_iocp_handle_write_op.hpp view
@@ -2,7 +2,7 @@ // detail/win_iocp_handle_write_op.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // Copyright (c) 2008 Rep Invariant Systems, Inc. (info@repinvariant.com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying@@ -51,9 +51,12 @@ } static void do_complete(void* owner, operation* base,- const asio::error_code& ec, std::size_t bytes_transferred)+ const asio::error_code& result_ec, std::size_t bytes_transferred) {+ asio::error_code ec(result_ec);+ // Take ownership of the operation object.+ ASIO_ASSUME(base != 0); win_iocp_handle_write_op* o(static_cast<win_iocp_handle_write_op*>(base)); ptr p = { asio::detail::addressof(o->handler_), o, o }; @@ -72,6 +75,8 @@ ConstBufferSequence>::validate(o->buffers_); } #endif // defined(ASIO_ENABLE_BUFFER_DEBUGGING)++ ASIO_ERROR_LOCATION(ec); // Make a copy of the handler so that the memory can be deallocated before // the upcall is made. Even if we're not about to make an upcall, a
link/modules/asio-standalone/asio/include/asio/detail/win_iocp_io_context.hpp view
@@ -2,7 +2,7 @@ // detail/win_iocp_io_context.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -109,10 +109,7 @@ } // Return whether a handler can be dispatched immediately.- bool can_dispatch()- {- return thread_call_stack::contains(this) != 0;- }+ ASIO_DECL bool can_dispatch(); /// Capture the current exception so it can be rethrown from a run function. ASIO_DECL void capture_current_exception();@@ -200,6 +197,12 @@ typename timer_queue<Time_Traits>::per_timer_data& timer, std::size_t max_cancelled = (std::numeric_limits<std::size_t>::max)()); + // Cancel the timer operations associated with the given key.+ template <typename Time_Traits>+ void cancel_timer_by_key(timer_queue<Time_Traits>& queue,+ typename timer_queue<Time_Traits>::per_timer_data* timer,+ void* cancellation_key);+ // Move the timer operations associated with the given timer. template <typename Time_Traits> void move_timer(timer_queue<Time_Traits>& queue,@@ -269,11 +272,13 @@ enum {+#if !defined(_WIN32_WINNT) || (_WIN32_WINNT < 0x0600) // Timeout to use with GetQueuedCompletionStatus on older versions of // Windows. Some versions of windows have a "bug" where a call to // GetQueuedCompletionStatus can appear stuck even though there are events // waiting on the queue. Using a timeout helps to work around the issue. default_gqcs_timeout = 500,+#endif // !defined(_WIN32_WINNT) || (_WIN32_WINNT < 0x0600) // Maximum waitable timer timeout, in milliseconds. max_timeout_msec = 5 * 60 * 1000,
link/modules/asio-standalone/asio/include/asio/detail/win_iocp_null_buffers_op.hpp view
@@ -2,7 +2,7 @@ // detail/win_iocp_null_buffers_op.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -63,6 +63,7 @@ asio::error_code ec(result_ec); // Take ownership of the operation object.+ ASIO_ASSUME(base != 0); win_iocp_null_buffers_op* o(static_cast<win_iocp_null_buffers_op*>(base)); ptr p = { asio::detail::addressof(o->handler_), o, o }; @@ -89,6 +90,8 @@ { ec = asio::error::connection_refused; }++ ASIO_ERROR_LOCATION(ec); // Make a copy of the handler so that the memory can be deallocated before // the upcall is made. Even if we're not about to make an upcall, a
link/modules/asio-standalone/asio/include/asio/detail/win_iocp_operation.hpp view
@@ -2,7 +2,7 @@ // detail/win_iocp_operation.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -51,6 +51,16 @@ func_(0, this, asio::error_code(), 0); } + void reset()+ {+ Internal = 0;+ InternalHigh = 0;+ Offset = 0;+ OffsetHigh = 0;+ hEvent = 0;+ ready_ = 0;+ }+ protected: typedef void (*func_type)( void*, win_iocp_operation*,@@ -66,16 +76,6 @@ // Prevents deletion through this type. ~win_iocp_operation() {- }-- void reset()- {- Internal = 0;- InternalHigh = 0;- Offset = 0;- OffsetHigh = 0;- hEvent = 0;- ready_ = 0; } private:
link/modules/asio-standalone/asio/include/asio/detail/win_iocp_overlapped_op.hpp view
@@ -2,7 +2,7 @@ // detail/win_iocp_overlapped_op.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -47,9 +47,12 @@ } static void do_complete(void* owner, operation* base,- const asio::error_code& ec, std::size_t bytes_transferred)+ const asio::error_code& result_ec, std::size_t bytes_transferred) {+ asio::error_code ec(result_ec);+ // Take ownership of the operation object.+ ASIO_ASSUME(base != 0); win_iocp_overlapped_op* o(static_cast<win_iocp_overlapped_op*>(base)); ptr p = { asio::detail::addressof(o->handler_), o, o }; @@ -59,6 +62,8 @@ handler_work<Handler, IoExecutor> w( ASIO_MOVE_CAST2(handler_work<Handler, IoExecutor>)( o->work_));++ ASIO_ERROR_LOCATION(ec); // Make a copy of the handler so that the memory can be deallocated before // the upcall is made. Even if we're not about to make an upcall, a
link/modules/asio-standalone/asio/include/asio/detail/win_iocp_overlapped_ptr.hpp view
@@ -2,7 +2,7 @@ // detail/win_iocp_overlapped_ptr.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/detail/win_iocp_serial_port_service.hpp view
@@ -2,7 +2,7 @@ // detail/win_iocp_serial_port_service.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // Copyright (c) 2008 Rep Invariant Systems, Inc. (info@repinvariant.com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying@@ -137,6 +137,7 @@ asio::error_code& ec) { ec = asio::error::operation_not_supported;+ ASIO_ERROR_LOCATION(ec); return ec; }
link/modules/asio-standalone/asio/include/asio/detail/win_iocp_socket_accept_op.hpp view
@@ -2,7 +2,7 @@ // detail/win_iocp_socket_accept_op.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -53,6 +53,8 @@ protocol_(protocol), peer_endpoint_(peer_endpoint), enable_connection_aborted_(enable_connection_aborted),+ proxy_op_(0),+ cancel_requested_(0), handler_(ASIO_MOVE_CAST(Handler)(handler)), work_(handler_, io_ex) {@@ -73,6 +75,12 @@ return sizeof(sockaddr_storage_type) + 16; } + void enable_cancellation(long* cancel_requested, operation* proxy_op)+ {+ cancel_requested_ = cancel_requested;+ proxy_op_ = proxy_op;+ }+ static void do_complete(void* owner, operation* base, const asio::error_code& result_ec, std::size_t /*bytes_transferred*/)@@ -80,6 +88,7 @@ asio::error_code ec(result_ec); // Take ownership of the operation object.+ ASIO_ASSUME(base != 0); win_iocp_socket_accept_op* o(static_cast<win_iocp_socket_accept_op*>(base)); ptr p = { asio::detail::addressof(o->handler_), o, o }; @@ -98,10 +107,13 @@ && !o->enable_connection_aborted_) { o->reset();+ if (o->proxy_op_)+ o->proxy_op_->reset(); o->socket_service_.restart_accept_op(o->socket_, o->new_socket_, o->protocol_.family(), o->protocol_.type(), o->protocol_.protocol(),- o->output_buffer(), o->address_length(), o);+ o->output_buffer(), o->address_length(),+ o->cancel_requested_, o->proxy_op_ ? o->proxy_op_ : o); p.v = p.p = 0; return; }@@ -129,6 +141,8 @@ ASIO_MOVE_CAST2(handler_work<Handler, IoExecutor>)( o->work_)); + ASIO_ERROR_LOCATION(ec);+ // Make a copy of the handler so that the memory can be deallocated before // the upcall is made. Even if we're not about to make an upcall, a // sub-object of the handler may be the true owner of the memory associated@@ -159,6 +173,8 @@ typename Protocol::endpoint* peer_endpoint_; unsigned char output_buffer_[(sizeof(sockaddr_storage_type) + 16) * 2]; bool enable_connection_aborted_;+ operation* proxy_op_;+ long* cancel_requested_; Handler handler_; handler_work<Handler, IoExecutor> work_; };@@ -184,6 +200,8 @@ protocol_(protocol), peer_endpoint_(peer_endpoint), enable_connection_aborted_(enable_connection_aborted),+ cancel_requested_(0),+ proxy_op_(0), handler_(ASIO_MOVE_CAST(Handler)(handler)), work_(handler_, io_ex) {@@ -204,6 +222,12 @@ return sizeof(sockaddr_storage_type) + 16; } + void enable_cancellation(long* cancel_requested, operation* proxy_op)+ {+ cancel_requested_ = cancel_requested;+ proxy_op_ = proxy_op;+ }+ static void do_complete(void* owner, operation* base, const asio::error_code& result_ec, std::size_t /*bytes_transferred*/)@@ -211,6 +235,7 @@ asio::error_code ec(result_ec); // Take ownership of the operation object.+ ASIO_ASSUME(base != 0); win_iocp_socket_move_accept_op* o( static_cast<win_iocp_socket_move_accept_op*>(base)); ptr p = { asio::detail::addressof(o->handler_), o, o };@@ -230,10 +255,13 @@ && !o->enable_connection_aborted_) { o->reset();+ if (o->proxy_op_)+ o->proxy_op_->reset(); o->socket_service_.restart_accept_op(o->socket_, o->new_socket_, o->protocol_.family(), o->protocol_.type(), o->protocol_.protocol(),- o->output_buffer(), o->address_length(), o);+ o->output_buffer(), o->address_length(),+ o->cancel_requested_, o->proxy_op_ ? o->proxy_op_ : o); p.v = p.p = 0; return; }@@ -261,6 +289,8 @@ ASIO_MOVE_CAST2(handler_work<Handler, IoExecutor>)( o->work_)); + ASIO_ERROR_LOCATION(ec);+ // Make a copy of the handler so that the memory can be deallocated before // the upcall is made. Even if we're not about to make an upcall, a // sub-object of the handler may be the true owner of the memory associated@@ -296,6 +326,8 @@ typename Protocol::endpoint* peer_endpoint_; unsigned char output_buffer_[(sizeof(sockaddr_storage_type) + 16) * 2]; bool enable_connection_aborted_;+ long* cancel_requested_;+ operation* proxy_op_; Handler handler_; handler_work<Handler, IoExecutor> work_; };
link/modules/asio-standalone/asio/include/asio/detail/win_iocp_socket_connect_op.hpp view
@@ -2,7 +2,7 @@ // detail/win_iocp_socket_connect_op.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -47,6 +47,7 @@ static status do_perform(reactor_op* base) {+ ASIO_ASSUME(base != 0); win_iocp_socket_connect_op_base* o( static_cast<win_iocp_socket_connect_op_base*>(base)); @@ -80,6 +81,7 @@ asio::error_code ec(result_ec); // Take ownership of the operation object.+ ASIO_ASSUME(base != 0); win_iocp_socket_connect_op* o( static_cast<win_iocp_socket_connect_op*>(base)); ptr p = { asio::detail::addressof(o->handler_), o, o };@@ -98,6 +100,8 @@ handler_work<Handler, IoExecutor> w( ASIO_MOVE_CAST2(handler_work<Handler, IoExecutor>)( o->work_));++ ASIO_ERROR_LOCATION(ec); // Make a copy of the handler so that the memory can be deallocated before // the upcall is made. Even if we're not about to make an upcall, a
link/modules/asio-standalone/asio/include/asio/detail/win_iocp_socket_recv_op.hpp view
@@ -2,7 +2,7 @@ // detail/win_iocp_socket_recv_op.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -61,6 +61,7 @@ asio::error_code ec(result_ec); // Take ownership of the operation object.+ ASIO_ASSUME(base != 0); win_iocp_socket_recv_op* o(static_cast<win_iocp_socket_recv_op*>(base)); ptr p = { asio::detail::addressof(o->handler_), o, o }; @@ -84,6 +85,8 @@ buffer_sequence_adapter<asio::mutable_buffer, MutableBufferSequence>::all_empty(o->buffers_), ec, bytes_transferred);++ ASIO_ERROR_LOCATION(ec); // Make a copy of the handler so that the memory can be deallocated before // the upcall is made. Even if we're not about to make an upcall, a
link/modules/asio-standalone/asio/include/asio/detail/win_iocp_socket_recvfrom_op.hpp view
@@ -2,7 +2,7 @@ // detail/win_iocp_socket_recvfrom_op.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -68,6 +68,7 @@ asio::error_code ec(result_ec); // Take ownership of the operation object.+ ASIO_ASSUME(base != 0); win_iocp_socket_recvfrom_op* o( static_cast<win_iocp_socket_recvfrom_op*>(base)); ptr p = { asio::detail::addressof(o->handler_), o, o };@@ -92,6 +93,8 @@ // Record the size of the endpoint returned by the operation. o->endpoint_.resize(o->endpoint_size_);++ ASIO_ERROR_LOCATION(ec); // Make a copy of the handler so that the memory can be deallocated before // the upcall is made. Even if we're not about to make an upcall, a
link/modules/asio-standalone/asio/include/asio/detail/win_iocp_socket_recvmsg_op.hpp view
@@ -2,7 +2,7 @@ // detail/win_iocp_socket_recvmsg_op.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -63,6 +63,7 @@ asio::error_code ec(result_ec); // Take ownership of the operation object.+ ASIO_ASSUME(base != 0); win_iocp_socket_recvmsg_op* o( static_cast<win_iocp_socket_recvmsg_op*>(base)); ptr p = { asio::detail::addressof(o->handler_), o, o };@@ -85,6 +86,8 @@ socket_ops::complete_iocp_recvmsg(o->cancel_token_, ec); o->out_flags_ = 0;++ ASIO_ERROR_LOCATION(ec); // Make a copy of the handler so that the memory can be deallocated before // the upcall is made. Even if we're not about to make an upcall, a
link/modules/asio-standalone/asio/include/asio/detail/win_iocp_socket_send_op.hpp view
@@ -2,7 +2,7 @@ // detail/win_iocp_socket_send_op.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -59,6 +59,7 @@ asio::error_code ec(result_ec); // Take ownership of the operation object.+ ASIO_ASSUME(base != 0); win_iocp_socket_send_op* o(static_cast<win_iocp_socket_send_op*>(base)); ptr p = { asio::detail::addressof(o->handler_), o, o }; @@ -79,6 +80,8 @@ #endif // defined(ASIO_ENABLE_BUFFER_DEBUGGING) socket_ops::complete_iocp_send(o->cancel_token_, ec);++ ASIO_ERROR_LOCATION(ec); // Make a copy of the handler so that the memory can be deallocated before // the upcall is made. Even if we're not about to make an upcall, a
link/modules/asio-standalone/asio/include/asio/detail/win_iocp_socket_service.hpp view
@@ -2,7 +2,7 @@ // detail/win_iocp_socket_service.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -205,6 +205,8 @@ impl.have_remote_endpoint_ = false; impl.remote_endpoint_ = endpoint_type(); }++ ASIO_ERROR_LOCATION(ec); return ec; } @@ -219,6 +221,8 @@ impl.have_remote_endpoint_ = native_socket.have_remote_endpoint(); impl.remote_endpoint_ = native_socket.remote_endpoint(); }++ ASIO_ERROR_LOCATION(ec); return ec; } @@ -235,6 +239,8 @@ const endpoint_type& endpoint, asio::error_code& ec) { socket_ops::bind(impl.socket_, endpoint.data(), endpoint.size(), ec);++ ASIO_ERROR_LOCATION(ec); return ec; } @@ -246,6 +252,8 @@ socket_ops::setsockopt(impl.socket_, impl.state_, option.level(impl.protocol_), option.name(impl.protocol_), option.data(impl.protocol_), option.size(impl.protocol_), ec);++ ASIO_ERROR_LOCATION(ec); return ec; } @@ -260,6 +268,8 @@ option.data(impl.protocol_), &size, ec); if (!ec) option.resize(impl.protocol_, size);++ ASIO_ERROR_LOCATION(ec); return ec; } @@ -270,7 +280,10 @@ endpoint_type endpoint; std::size_t addr_len = endpoint.capacity(); if (socket_ops::getsockname(impl.socket_, endpoint.data(), &addr_len, ec))+ {+ ASIO_ERROR_LOCATION(ec); return endpoint_type();+ } endpoint.resize(addr_len); return endpoint; }@@ -283,7 +296,10 @@ std::size_t addr_len = endpoint.capacity(); if (socket_ops::getpeername(impl.socket_, endpoint.data(), &addr_len, impl.have_remote_endpoint_, ec))+ {+ ASIO_ERROR_LOCATION(ec); return endpoint_type();+ } endpoint.resize(addr_len); return endpoint; }@@ -306,9 +322,12 @@ buffer_sequence_adapter<asio::const_buffer, ConstBufferSequence> bufs(buffers); - return socket_ops::sync_sendto(impl.socket_, impl.state_,- bufs.buffers(), bufs.count(), flags,+ size_t n = socket_ops::sync_sendto(impl.socket_,+ impl.state_, bufs.buffers(), bufs.count(), flags, destination.data(), destination.size(), ec);++ ASIO_ERROR_LOCATION(ec);+ return n; } // Wait until data can be sent without blocking.@@ -318,7 +337,7 @@ { // Wait for socket to become ready. socket_ops::poll_write(impl.socket_, impl.state_, -1, ec);-+ ASIO_ERROR_LOCATION(ec); return 0; } @@ -330,12 +349,16 @@ socket_base::message_flags flags, Handler& handler, const IoExecutor& io_ex) {+ typename associated_cancellation_slot<Handler>::type slot+ = asio::get_associated_cancellation_slot(handler);+ // Allocate and construct an operation to wrap the handler. typedef win_iocp_socket_send_op< ConstBufferSequence, Handler, IoExecutor> op; typename op::ptr p = { asio::detail::addressof(handler), op::ptr::allocate(handler), 0 };- p.p = new (p.v) op(impl.cancel_token_, buffers, handler, io_ex);+ operation* o = p.p = new (p.v) op(+ impl.cancel_token_, buffers, handler, io_ex); ASIO_HANDLER_CREATION((context_, *p.p, "socket", &impl, impl.socket_, "async_send_to"));@@ -343,9 +366,13 @@ buffer_sequence_adapter<asio::const_buffer, ConstBufferSequence> bufs(buffers); + // Optionally register for per-operation cancellation.+ if (slot.is_connected())+ o = &slot.template emplace<iocp_op_cancellation>(impl.socket_, o);+ start_send_to_op(impl, bufs.buffers(), bufs.count(), destination.data(), static_cast<int>(destination.size()),- flags, p.p);+ flags, o); p.v = p.p = 0; } @@ -359,12 +386,12 @@ typedef win_iocp_null_buffers_op<Handler, IoExecutor> op; typename op::ptr p = { asio::detail::addressof(handler), op::ptr::allocate(handler), 0 };- p.p = new (p.v) op(impl.cancel_token_, handler, io_ex);+ reactor_op* o = p.p = new (p.v) op(impl.cancel_token_, handler, io_ex); ASIO_HANDLER_CREATION((context_, *p.p, "socket", &impl, impl.socket_, "async_send_to(null_buffers)")); - start_reactor_op(impl, select_reactor::write_op, p.p);+ start_reactor_op(impl, select_reactor::write_op, o); p.v = p.p = 0; } @@ -380,14 +407,15 @@ MutableBufferSequence> bufs(buffers); std::size_t addr_len = sender_endpoint.capacity();- std::size_t bytes_recvd = socket_ops::sync_recvfrom(- impl.socket_, impl.state_, bufs.buffers(), bufs.count(),- flags, sender_endpoint.data(), &addr_len, ec);+ std::size_t n = socket_ops::sync_recvfrom(impl.socket_,+ impl.state_, bufs.buffers(), bufs.count(), flags,+ sender_endpoint.data(), &addr_len, ec); if (!ec) sender_endpoint.resize(addr_len); - return bytes_recvd;+ ASIO_ERROR_LOCATION(ec);+ return n; } // Wait until data can be received without blocking.@@ -401,6 +429,7 @@ // Reset endpoint since it can be given no sensible value at this time. sender_endpoint = endpoint_type(); + ASIO_ERROR_LOCATION(ec); return 0; } @@ -414,13 +443,16 @@ socket_base::message_flags flags, Handler& handler, const IoExecutor& io_ex) {+ typename associated_cancellation_slot<Handler>::type slot+ = asio::get_associated_cancellation_slot(handler);+ // Allocate and construct an operation to wrap the handler. typedef win_iocp_socket_recvfrom_op<MutableBufferSequence, endpoint_type, Handler, IoExecutor> op; typename op::ptr p = { asio::detail::addressof(handler), op::ptr::allocate(handler), 0 };- p.p = new (p.v) op(sender_endp, impl.cancel_token_,- buffers, handler, io_ex);+ operation* o = p.p = new (p.v) op(sender_endp,+ impl.cancel_token_, buffers, handler, io_ex); ASIO_HANDLER_CREATION((context_, *p.p, "socket", &impl, impl.socket_, "async_receive_from"));@@ -428,8 +460,12 @@ buffer_sequence_adapter<asio::mutable_buffer, MutableBufferSequence> bufs(buffers); + // Optionally register for per-operation cancellation.+ if (slot.is_connected())+ o = &slot.template emplace<iocp_op_cancellation>(impl.socket_, o);+ start_receive_from_op(impl, bufs.buffers(), bufs.count(),- sender_endp.data(), flags, &p.p->endpoint_size(), p.p);+ sender_endp.data(), flags, &p.p->endpoint_size(), o); p.v = p.p = 0; } @@ -439,6 +475,9 @@ endpoint_type& sender_endpoint, socket_base::message_flags flags, Handler& handler, const IoExecutor& io_ex) {+ typename associated_cancellation_slot<Handler>::type slot+ = asio::get_associated_cancellation_slot(handler);+ // Allocate and construct an operation to wrap the handler. typedef win_iocp_null_buffers_op<Handler, IoExecutor> op; typename op::ptr p = { asio::detail::addressof(handler),@@ -451,8 +490,24 @@ // Reset endpoint since it can be given no sensible value at this time. sender_endpoint = endpoint_type(); - start_null_buffers_receive_op(impl, flags, p.p);+ // Optionally register for per-operation cancellation.+ operation* iocp_op = p.p;+ if (slot.is_connected())+ {+ p.p->cancellation_key_ = iocp_op =+ &slot.template emplace<reactor_op_cancellation>(+ impl.socket_, iocp_op);+ }++ int op_type = start_null_buffers_receive_op(impl, flags, p.p, iocp_op); p.v = p.p = 0;++ // Update cancellation method if the reactor was used.+ if (slot.is_connected() && op_type != -1)+ {+ static_cast<reactor_op_cancellation*>(iocp_op)->use_reactor(+ &get_reactor(), &impl.reactor_data_, op_type);+ } } // Accept a new connection.@@ -464,6 +519,7 @@ if (peer.is_open()) { ec = asio::error::already_open;+ ASIO_ERROR_LOCATION(ec); return ec; } @@ -482,6 +538,7 @@ new_socket.release(); } + ASIO_ERROR_LOCATION(ec); return ec; } @@ -491,6 +548,9 @@ void async_accept(implementation_type& impl, Socket& peer, endpoint_type* peer_endpoint, Handler& handler, const IoExecutor& io_ex) {+ typename associated_cancellation_slot<Handler>::type slot+ = asio::get_associated_cancellation_slot(handler);+ // Allocate and construct an operation to wrap the handler. typedef win_iocp_socket_accept_op<Socket, protocol_type, Handler, IoExecutor> op;@@ -498,16 +558,25 @@ op::ptr::allocate(handler), 0 }; bool enable_connection_aborted = (impl.state_ & socket_ops::enable_connection_aborted) != 0;- p.p = new (p.v) op(*this, impl.socket_, peer, impl.protocol_,+ operation* o = p.p = new (p.v) op(*this, impl.socket_, peer, impl.protocol_, peer_endpoint, enable_connection_aborted, handler, io_ex); ASIO_HANDLER_CREATION((context_, *p.p, "socket", &impl, impl.socket_, "async_accept")); + // Optionally register for per-operation cancellation.+ if (slot.is_connected())+ {+ accept_op_cancellation* c =+ &slot.template emplace<accept_op_cancellation>(impl.socket_, o);+ p.p->enable_cancellation(c->get_cancel_requested(), c);+ o = c;+ }+ start_accept_op(impl, peer.is_open(), p.p->new_socket(), impl.protocol_.family(), impl.protocol_.type(), impl.protocol_.protocol(), p.p->output_buffer(),- p.p->address_length(), p.p);+ p.p->address_length(), o); p.v = p.p = 0; } @@ -519,6 +588,9 @@ const PeerIoExecutor& peer_io_ex, endpoint_type* peer_endpoint, Handler& handler, const IoExecutor& io_ex) {+ typename associated_cancellation_slot<Handler>::type slot+ = asio::get_associated_cancellation_slot(handler);+ // Allocate and construct an operation to wrap the handler. typedef win_iocp_socket_move_accept_op< protocol_type, PeerIoExecutor, Handler, IoExecutor> op;@@ -526,17 +598,26 @@ op::ptr::allocate(handler), 0 }; bool enable_connection_aborted = (impl.state_ & socket_ops::enable_connection_aborted) != 0;- p.p = new (p.v) op(*this, impl.socket_, impl.protocol_,+ operation* o = p.p = new (p.v) op(*this, impl.socket_, impl.protocol_, peer_io_ex, peer_endpoint, enable_connection_aborted, handler, io_ex); ASIO_HANDLER_CREATION((context_, *p.p, "socket", &impl, impl.socket_, "async_accept")); + // Optionally register for per-operation cancellation.+ if (slot.is_connected())+ {+ accept_op_cancellation* c =+ &slot.template emplace<accept_op_cancellation>(impl.socket_, o);+ p.p->enable_cancellation(c->get_cancel_requested(), c);+ o = c;+ }+ start_accept_op(impl, false, p.p->new_socket(), impl.protocol_.family(), impl.protocol_.type(), impl.protocol_.protocol(), p.p->output_buffer(),- p.p->address_length(), p.p);+ p.p->address_length(), o); p.v = p.p = 0; } #endif // defined(ASIO_HAS_MOVE)@@ -547,6 +628,7 @@ { socket_ops::sync_connect(impl.socket_, peer_endpoint.data(), peer_endpoint.size(), ec);+ ASIO_ERROR_LOCATION(ec); return ec; } @@ -556,6 +638,9 @@ const endpoint_type& peer_endpoint, Handler& handler, const IoExecutor& io_ex) {+ typename associated_cancellation_slot<Handler>::type slot+ = asio::get_associated_cancellation_slot(handler);+ // Allocate and construct an operation to wrap the handler. typedef win_iocp_socket_connect_op<Handler, IoExecutor> op; typename op::ptr p = { asio::detail::addressof(handler),@@ -565,9 +650,26 @@ ASIO_HANDLER_CREATION((context_, *p.p, "socket", &impl, impl.socket_, "async_connect")); - start_connect_op(impl, impl.protocol_.family(), impl.protocol_.type(),- peer_endpoint.data(), static_cast<int>(peer_endpoint.size()), p.p);+ // Optionally register for per-operation cancellation.+ operation* iocp_op = p.p;+ if (slot.is_connected())+ {+ p.p->cancellation_key_ = iocp_op =+ &slot.template emplace<reactor_op_cancellation>(+ impl.socket_, iocp_op);+ }++ int op_type = start_connect_op(impl, impl.protocol_.family(),+ impl.protocol_.type(), peer_endpoint.data(),+ static_cast<int>(peer_endpoint.size()), p.p, iocp_op); p.v = p.p = 0;++ // Update cancellation method if the reactor was used.+ if (slot.is_connected() && op_type != -1)+ {+ static_cast<reactor_op_cancellation*>(iocp_op)->use_reactor(+ &get_reactor(), &impl.reactor_data_, op_type);+ } } };
link/modules/asio-standalone/asio/include/asio/detail/win_iocp_socket_service_base.hpp view
@@ -2,7 +2,7 @@ // detail/win_iocp_socket_service_base.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -19,6 +19,7 @@ #if defined(ASIO_HAS_IOCP) +#include "asio/associated_cancellation_slot.hpp" #include "asio/error.hpp" #include "asio/execution_context.hpp" #include "asio/socket_base.hpp"@@ -213,6 +214,9 @@ void async_wait(base_implementation_type& impl, socket_base::wait_type w, Handler& handler, const IoExecutor& io_ex) {+ typename associated_cancellation_slot<Handler>::type slot+ = asio::get_associated_cancellation_slot(handler);+ bool is_continuation = asio_handler_cont_helpers::is_continuation(handler); @@ -225,15 +229,27 @@ ASIO_HANDLER_CREATION((context_, *p.p, "socket", &impl, impl.socket_, "async_wait")); + // Optionally register for per-operation cancellation.+ operation* iocp_op = p.p;+ if (slot.is_connected())+ {+ p.p->cancellation_key_ = iocp_op =+ &slot.template emplace<reactor_op_cancellation>(+ impl.socket_, iocp_op);+ }++ int op_type = -1; switch (w) { case socket_base::wait_read:- start_null_buffers_receive_op(impl, 0, p.p);+ op_type = start_null_buffers_receive_op(impl, 0, p.p, iocp_op); break; case socket_base::wait_write:+ op_type = select_reactor::write_op; start_reactor_op(impl, select_reactor::write_op, p.p); break; case socket_base::wait_error:+ op_type = select_reactor::read_op; start_reactor_op(impl, select_reactor::except_op, p.p); break; default:@@ -243,6 +259,13 @@ } p.v = p.p = 0;++ // Update cancellation method if the reactor was used.+ if (slot.is_connected() && op_type != -1)+ {+ static_cast<reactor_op_cancellation*>(iocp_op)->use_reactor(+ &get_reactor(), &impl.reactor_data_, op_type);+ } } // Send the given data to the peer. Returns the number of bytes sent.@@ -275,12 +298,16 @@ const ConstBufferSequence& buffers, socket_base::message_flags flags, Handler& handler, const IoExecutor& io_ex) {+ typename associated_cancellation_slot<Handler>::type slot+ = asio::get_associated_cancellation_slot(handler);+ // Allocate and construct an operation to wrap the handler. typedef win_iocp_socket_send_op< ConstBufferSequence, Handler, IoExecutor> op; typename op::ptr p = { asio::detail::addressof(handler), op::ptr::allocate(handler), 0 };- p.p = new (p.v) op(impl.cancel_token_, buffers, handler, io_ex);+ operation* o = p.p = new (p.v) op(+ impl.cancel_token_, buffers, handler, io_ex); ASIO_HANDLER_CREATION((context_, *p.p, "socket", &impl, impl.socket_, "async_send"));@@ -288,9 +315,13 @@ buffer_sequence_adapter<asio::const_buffer, ConstBufferSequence> bufs(buffers); + // Optionally register for per-operation cancellation.+ if (slot.is_connected())+ o = &slot.template emplace<iocp_op_cancellation>(impl.socket_, o);+ start_send_op(impl, bufs.buffers(), bufs.count(), flags, (impl.state_ & socket_ops::stream_oriented) != 0 && bufs.all_empty(),- p.p);+ o); p.v = p.p = 0; } @@ -343,13 +374,16 @@ const MutableBufferSequence& buffers, socket_base::message_flags flags, Handler& handler, const IoExecutor& io_ex) {+ typename associated_cancellation_slot<Handler>::type slot+ = asio::get_associated_cancellation_slot(handler);+ // Allocate and construct an operation to wrap the handler. typedef win_iocp_socket_recv_op< MutableBufferSequence, Handler, IoExecutor> op; typename op::ptr p = { asio::detail::addressof(handler), op::ptr::allocate(handler), 0 };- p.p = new (p.v) op(impl.state_, impl.cancel_token_,- buffers, handler, io_ex);+ operation* o = p.p = new (p.v) op(impl.state_,+ impl.cancel_token_, buffers, handler, io_ex); ASIO_HANDLER_CREATION((context_, *p.p, "socket", &impl, impl.socket_, "async_receive"));@@ -357,9 +391,13 @@ buffer_sequence_adapter<asio::mutable_buffer, MutableBufferSequence> bufs(buffers); + // Optionally register for per-operation cancellation.+ if (slot.is_connected())+ o = &slot.template emplace<iocp_op_cancellation>(impl.socket_, o);+ start_receive_op(impl, bufs.buffers(), bufs.count(), flags, (impl.state_ & socket_ops::stream_oriented) != 0 && bufs.all_empty(),- p.p);+ o); p.v = p.p = 0; } @@ -369,6 +407,9 @@ const null_buffers&, socket_base::message_flags flags, Handler& handler, const IoExecutor& io_ex) {+ typename associated_cancellation_slot<Handler>::type slot+ = asio::get_associated_cancellation_slot(handler);+ // Allocate and construct an operation to wrap the handler. typedef win_iocp_null_buffers_op<Handler, IoExecutor> op; typename op::ptr p = { asio::detail::addressof(handler),@@ -378,8 +419,24 @@ ASIO_HANDLER_CREATION((context_, *p.p, "socket", &impl, impl.socket_, "async_receive(null_buffers)")); - start_null_buffers_receive_op(impl, flags, p.p);+ // Optionally register for per-operation cancellation.+ operation* iocp_op = p.p;+ if (slot.is_connected())+ {+ p.p->cancellation_key_ = iocp_op =+ &slot.template emplace<reactor_op_cancellation>(+ impl.socket_, iocp_op);+ }++ int op_type = start_null_buffers_receive_op(impl, flags, p.p, iocp_op); p.v = p.p = 0;++ // Update cancellation method if the reactor was used.+ if (slot.is_connected() && op_type != -1)+ {+ static_cast<reactor_op_cancellation*>(iocp_op)->use_reactor(+ &get_reactor(), &impl.reactor_data_, op_type);+ } } // Receive some data with associated flags. Returns the number of bytes@@ -421,12 +478,15 @@ socket_base::message_flags& out_flags, Handler& handler, const IoExecutor& io_ex) {+ typename associated_cancellation_slot<Handler>::type slot+ = asio::get_associated_cancellation_slot(handler);+ // Allocate and construct an operation to wrap the handler. typedef win_iocp_socket_recvmsg_op< MutableBufferSequence, Handler, IoExecutor> op; typename op::ptr p = { asio::detail::addressof(handler), op::ptr::allocate(handler), 0 };- p.p = new (p.v) op(impl.cancel_token_,+ operation* o = p.p = new (p.v) op(impl.cancel_token_, buffers, out_flags, handler, io_ex); ASIO_HANDLER_CREATION((context_, *p.p, "socket",@@ -435,7 +495,11 @@ buffer_sequence_adapter<asio::mutable_buffer, MutableBufferSequence> bufs(buffers); - start_receive_op(impl, bufs.buffers(), bufs.count(), in_flags, false, p.p);+ // Optionally register for per-operation cancellation.+ if (slot.is_connected())+ o = &slot.template emplace<iocp_op_cancellation>(impl.socket_, o);++ start_receive_op(impl, bufs.buffers(), bufs.count(), in_flags, false, o); p.v = p.p = 0; } @@ -446,6 +510,9 @@ socket_base::message_flags& out_flags, Handler& handler, const IoExecutor& io_ex) {+ typename associated_cancellation_slot<Handler>::type slot+ = asio::get_associated_cancellation_slot(handler);+ // Allocate and construct an operation to wrap the handler. typedef win_iocp_null_buffers_op<Handler, IoExecutor> op; typename op::ptr p = { asio::detail::addressof(handler),@@ -458,14 +525,31 @@ // Reset out_flags since it can be given no sensible value at this time. out_flags = 0; - start_null_buffers_receive_op(impl, in_flags, p.p);+ // Optionally register for per-operation cancellation.+ operation* iocp_op = p.p;+ if (slot.is_connected())+ {+ p.p->cancellation_key_ = iocp_op =+ &slot.template emplace<reactor_op_cancellation>(+ impl.socket_, iocp_op);+ }++ int op_type = start_null_buffers_receive_op(impl, in_flags, p.p, iocp_op); p.v = p.p = 0;++ // Update cancellation method if the reactor was used.+ if (slot.is_connected() && op_type != -1)+ {+ static_cast<reactor_op_cancellation*>(iocp_op)->use_reactor(+ &get_reactor(), &impl.reactor_data_, op_type);+ } } // Helper function to restart an asynchronous accept operation. ASIO_DECL void restart_accept_op(socket_type s,- socket_holder& new_socket, int family, int type, int protocol,- void* output_buffer, DWORD address_length, operation* op);+ socket_holder& new_socket, int family, int type,+ int protocol, void* output_buffer, DWORD address_length,+ long* cancel_requested, operation* op); protected: // Open a new socket implementation.@@ -485,9 +569,8 @@ // Helper function to start an asynchronous send_to operation. ASIO_DECL void start_send_to_op(base_implementation_type& impl,- WSABUF* buffers, std::size_t buffer_count,- const socket_addr_type* addr, int addrlen,- socket_base::message_flags flags, operation* op);+ WSABUF* buffers, std::size_t buffer_count, const void* addr,+ int addrlen, socket_base::message_flags flags, operation* op); // Helper function to start an asynchronous receive operation. ASIO_DECL void start_receive_op(base_implementation_type& impl,@@ -495,13 +578,13 @@ socket_base::message_flags flags, bool noop, operation* op); // Helper function to start an asynchronous null_buffers receive operation.- ASIO_DECL void start_null_buffers_receive_op(- base_implementation_type& impl,- socket_base::message_flags flags, reactor_op* op);+ ASIO_DECL int start_null_buffers_receive_op(+ base_implementation_type& impl, socket_base::message_flags flags,+ reactor_op* op, operation* iocp_op); // Helper function to start an asynchronous receive_from operation. ASIO_DECL void start_receive_from_op(base_implementation_type& impl,- WSABUF* buffers, std::size_t buffer_count, socket_addr_type* addr,+ WSABUF* buffers, std::size_t buffer_count, void* addr, socket_base::message_flags flags, int* addrlen, operation* op); // Helper function to start an asynchronous accept operation.@@ -514,9 +597,9 @@ int op_type, reactor_op* op); // Start the asynchronous connect operation using the reactor.- ASIO_DECL void start_connect_op(base_implementation_type& impl,- int family, int type, const socket_addr_type* remote_addr,- std::size_t remote_addrlen, win_iocp_socket_connect_op_base* op);+ ASIO_DECL int start_connect_op(base_implementation_type& impl,+ int family, int type, const void* remote_addr, std::size_t remote_addrlen,+ win_iocp_socket_connect_op_base* op, operation* iocp_op); // Helper function to close a socket when the associated object is being // destroyed.@@ -561,6 +644,153 @@ // - very old Platform SDKs; and // - platform SDKs where MSVC's /Wp64 option causes spurious warnings. ASIO_DECL void* interlocked_exchange_pointer(void** dest, void* val);++ // Helper class used to implement per operation cancellation.+ class iocp_op_cancellation : public operation+ {+ public:+ iocp_op_cancellation(SOCKET s, operation* target)+ : operation(&iocp_op_cancellation::do_complete),+ socket_(s),+ target_(target)+ {+ }++ static void do_complete(void* owner, operation* base,+ const asio::error_code& result_ec,+ std::size_t bytes_transferred)+ {+ iocp_op_cancellation* o = static_cast<iocp_op_cancellation*>(base);+ o->target_->complete(owner, result_ec, bytes_transferred);+ }++ void operator()(cancellation_type_t type)+ {+#if defined(_WIN32_WINNT) && (_WIN32_WINNT >= 0x0600)+ if (!!(type &+ (cancellation_type::terminal+ | cancellation_type::partial+ | cancellation_type::total)))+ {+ HANDLE sock_as_handle = reinterpret_cast<HANDLE>(socket_);+ ::CancelIoEx(sock_as_handle, this);+ }+#else // defined(_WIN32_WINNT) && (_WIN32_WINNT >= 0x0600)+ (void)type;+#endif // defined(_WIN32_WINNT) && (_WIN32_WINNT >= 0x0600)+ }++ private:+ SOCKET socket_;+ operation* target_;+ };++ // Helper class used to implement per operation cancellation.+ class accept_op_cancellation : public operation+ {+ public:+ accept_op_cancellation(SOCKET s, operation* target)+ : operation(&iocp_op_cancellation::do_complete),+ socket_(s),+ target_(target),+ cancel_requested_(0)+ {+ }++ static void do_complete(void* owner, operation* base,+ const asio::error_code& result_ec,+ std::size_t bytes_transferred)+ {+ accept_op_cancellation* o = static_cast<accept_op_cancellation*>(base);+ o->target_->complete(owner, result_ec, bytes_transferred);+ }++ long* get_cancel_requested()+ {+ return &cancel_requested_;+ }++ void operator()(cancellation_type_t type)+ {+#if defined(_WIN32_WINNT) && (_WIN32_WINNT >= 0x0600)+ if (!!(type &+ (cancellation_type::terminal+ | cancellation_type::partial+ | cancellation_type::total)))+ {+ HANDLE sock_as_handle = reinterpret_cast<HANDLE>(socket_);+ ::CancelIoEx(sock_as_handle, this);+ }+#else // defined(_WIN32_WINNT) && (_WIN32_WINNT >= 0x0600)+ (void)type;+#endif // defined(_WIN32_WINNT) && (_WIN32_WINNT >= 0x0600)+ }++ private:+ SOCKET socket_;+ operation* target_;+ long cancel_requested_;+ };++ // Helper class used to implement per operation cancellation.+ class reactor_op_cancellation : public operation+ {+ public:+ reactor_op_cancellation(SOCKET s, operation* base)+ : operation(&reactor_op_cancellation::do_complete),+ socket_(s),+ target_(base),+ reactor_(0),+ reactor_data_(0),+ op_type_(-1)+ {+ }++ void use_reactor(select_reactor* r,+ select_reactor::per_descriptor_data* p, int o)+ {+ reactor_ = r;+ reactor_data_ = p;+ op_type_ = o;+ }++ static void do_complete(void* owner, operation* base,+ const asio::error_code& result_ec,+ std::size_t bytes_transferred)+ {+ reactor_op_cancellation* o = static_cast<reactor_op_cancellation*>(base);+ o->target_->complete(owner, result_ec, bytes_transferred);+ }++ void operator()(cancellation_type_t type)+ {+ if (!!(type &+ (cancellation_type::terminal+ | cancellation_type::partial+ | cancellation_type::total)))+ {+ if (reactor_)+ {+ reactor_->cancel_ops_by_key(socket_,+ *reactor_data_, op_type_, this);+ }+ else+ {+#if defined(_WIN32_WINNT) && (_WIN32_WINNT >= 0x0600)+ HANDLE sock_as_handle = reinterpret_cast<HANDLE>(socket_);+ ::CancelIoEx(sock_as_handle, this);+#endif // defined(_WIN32_WINNT) && (_WIN32_WINNT >= 0x0600)+ }+ }+ }++ private:+ SOCKET socket_;+ operation* target_;+ select_reactor* reactor_;+ select_reactor::per_descriptor_data* reactor_data_;+ int op_type_;+ }; // The execution context used to obtain the reactor, if required. execution_context& context_;
link/modules/asio-standalone/asio/include/asio/detail/win_iocp_thread_info.hpp view
@@ -2,7 +2,7 @@ // detail/win_iocp_thread_info.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/detail/win_iocp_wait_op.hpp view
@@ -2,7 +2,7 @@ // detail/win_iocp_wait_op.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -64,6 +64,7 @@ asio::error_code ec(result_ec); // Take ownership of the operation object.+ ASIO_ASSUME(base != 0); win_iocp_wait_op* o(static_cast<win_iocp_wait_op*>(base)); ptr p = { asio::detail::addressof(o->handler_), o, o }; @@ -90,6 +91,8 @@ { ec = asio::error::connection_refused; }++ ASIO_ERROR_LOCATION(ec); // Make a copy of the handler so that the memory can be deallocated before // the upcall is made. Even if we're not about to make an upcall, a
link/modules/asio-standalone/asio/include/asio/detail/win_mutex.hpp view
@@ -2,7 +2,7 @@ // detail/win_mutex.hpp // ~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/detail/win_object_handle_service.hpp view
@@ -2,7 +2,7 @@ // detail/win_object_handle_service.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // Copyright (c) 2011 Boris Schaeling (boris@highscore.de) // // Distributed under the Boost Software License, Version 1.0. (See accompanying
link/modules/asio-standalone/asio/include/asio/detail/win_static_mutex.hpp view
@@ -2,7 +2,7 @@ // detail/win_static_mutex.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/detail/win_thread.hpp view
@@ -2,7 +2,7 @@ // detail/win_thread.hpp // ~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/detail/win_tss_ptr.hpp view
@@ -2,7 +2,7 @@ // detail/win_tss_ptr.hpp // ~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/detail/winapp_thread.hpp view
@@ -2,7 +2,7 @@ // detail/winapp_thread.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/detail/wince_thread.hpp view
@@ -2,7 +2,7 @@ // detail/wince_thread.hpp // ~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/detail/winrt_async_manager.hpp view
@@ -2,7 +2,7 @@ // detail/winrt_async_manager.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/detail/winrt_async_op.hpp view
@@ -2,7 +2,7 @@ // detail/winrt_async_op.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/detail/winrt_resolve_op.hpp view
@@ -2,7 +2,7 @@ // detail/winrt_resolve_op.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -63,6 +63,7 @@ const asio::error_code&, std::size_t) { // Take ownership of the operation object.+ ASIO_ASSUME(base != 0); winrt_resolve_op* o(static_cast<winrt_resolve_op*>(base)); ptr p = { asio::detail::addressof(o->handler_), o, o };
link/modules/asio-standalone/asio/include/asio/detail/winrt_resolver_service.hpp view
@@ -2,7 +2,7 @@ // detail/winrt_resolver_service.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/detail/winrt_socket_connect_op.hpp view
@@ -2,7 +2,7 @@ // detail/winrt_socket_connect_op.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -52,6 +52,7 @@ const asio::error_code&, std::size_t) { // Take ownership of the operation object.+ ASIO_ASSUME(base != 0); winrt_socket_connect_op* o(static_cast<winrt_socket_connect_op*>(base)); ptr p = { asio::detail::addressof(o->handler_), o, o };
link/modules/asio-standalone/asio/include/asio/detail/winrt_socket_recv_op.hpp view
@@ -2,7 +2,7 @@ // detail/winrt_socket_recv_op.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -55,6 +55,7 @@ const asio::error_code&, std::size_t) { // Take ownership of the operation object.+ ASIO_ASSUME(base != 0); winrt_socket_recv_op* o(static_cast<winrt_socket_recv_op*>(base)); ptr p = { asio::detail::addressof(o->handler_), o, o };
link/modules/asio-standalone/asio/include/asio/detail/winrt_socket_send_op.hpp view
@@ -2,7 +2,7 @@ // detail/winrt_socket_send_op.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -54,6 +54,7 @@ const asio::error_code&, std::size_t) { // Take ownership of the operation object.+ ASIO_ASSUME(base != 0); winrt_socket_send_op* o(static_cast<winrt_socket_send_op*>(base)); ptr p = { asio::detail::addressof(o->handler_), o, o };
link/modules/asio-standalone/asio/include/asio/detail/winrt_ssocket_service.hpp view
@@ -2,7 +2,7 @@ // detail/winrt_ssocket_service.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/detail/winrt_ssocket_service_base.hpp view
@@ -2,7 +2,7 @@ // detail/winrt_ssocket_service_base.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/detail/winrt_timer_scheduler.hpp view
@@ -2,7 +2,7 @@ // detail/winrt_timer_scheduler.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/detail/winrt_utils.hpp view
@@ -2,7 +2,7 @@ // detail/winrt_utils.hpp // ~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/detail/winsock_init.hpp view
@@ -2,7 +2,7 @@ // detail/winsock_init.hpp // ~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/detail/work_dispatcher.hpp view
@@ -2,7 +2,7 @@ // detail/work_dispatcher.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -16,6 +16,7 @@ #endif // defined(_MSC_VER) && (_MSC_VER >= 1200) #include "asio/detail/config.hpp"+#include "asio/detail/bind_handler.hpp" #include "asio/detail/type_traits.hpp" #include "asio/associated_executor.hpp" #include "asio/associated_allocator.hpp"@@ -77,11 +78,18 @@ void operator()() {+ typename associated_allocator<Handler>::type alloc(+ (get_associated_allocator)(handler_));+#if defined(ASIO_NO_DEPRECATED)+ asio::prefer(executor_, execution::allocator(alloc)).execute(+ asio::detail::bind_handler(+ ASIO_MOVE_CAST(Handler)(handler_)));+#else // defined(ASIO_NO_DEPRECATED) execution::execute(- asio::prefer(executor_,- execution::blocking.possibly,- execution::allocator((get_associated_allocator)(handler_))),- ASIO_MOVE_CAST(Handler)(handler_));+ asio::prefer(executor_, execution::allocator(alloc)),+ asio::detail::bind_handler(+ ASIO_MOVE_CAST(Handler)(handler_)));+#endif // defined(ASIO_NO_DEPRECATED) } private:@@ -129,7 +137,8 @@ typename associated_allocator<Handler>::type alloc( (get_associated_allocator)(handler_)); work_.get_executor().dispatch(- ASIO_MOVE_CAST(Handler)(handler_), alloc);+ asio::detail::bind_handler(+ ASIO_MOVE_CAST(Handler)(handler_)), alloc); work_.reset(); }
link/modules/asio-standalone/asio/include/asio/detail/wrapped_handler.hpp view
@@ -2,7 +2,7 @@ // detail/wrapped_handler.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/dispatch.hpp view
@@ -2,7 +2,7 @@ // dispatch.hpp // ~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -17,6 +17,7 @@ #include "asio/detail/config.hpp" #include "asio/async_result.hpp"+#include "asio/detail/initiate_dispatch.hpp" #include "asio/detail/type_traits.hpp" #include "asio/execution_context.hpp" #include "asio/execution/executor.hpp"@@ -32,27 +33,51 @@ * executor. The function object may be called from the current thread prior to * returning from <tt>dispatch()</tt>. Otherwise, it is queued for execution. *- * This function has the following effects:+ * @param token The @ref completion_token that will be used to produce a+ * completion handler. The function signature of the completion handler must be:+ * @code void handler(); @endcode *- * @li Constructs a function object handler of type @c Handler, initialized- * with <tt>handler(forward<CompletionToken>(token))</tt>.+ * @returns This function returns <tt>async_initiate<NullaryToken,+ * void()>(Init{}, token)</tt>, where @c Init is a function object type defined+ * as: *- * @li Constructs an object @c result of type <tt>async_result<Handler></tt>,- * initializing the object as <tt>result(handler)</tt>.+ * @code class Init+ * {+ * public:+ * template <typename CompletionHandler>+ * void operator()(CompletionHandler&& completion_handler) const;+ * }; @endcode *- * @li Obtains the handler's associated executor object @c ex by performing- * <tt>get_associated_executor(handler)</tt>.+ * The function call operator of @c Init: *+ * @li Obtains the handler's associated executor object @c ex of type @c Ex by+ * performing @code auto ex = get_associated_executor(handler); @endcode+ * * @li Obtains the handler's associated allocator object @c alloc by performing- * <tt>get_associated_allocator(handler)</tt>.+ * @code auto alloc = get_associated_allocator(handler); @endcode *- * @li Performs <tt>ex.dispatch(std::move(handler), alloc)</tt>.+ * @li If <tt>execution::is_executor<Ex>::value</tt> is true, performs+ * @code prefer(ex, execution::allocator(alloc)).execute(+ * std::forward<CompletionHandler>(completion_handler)); @endcode *- * @li Returns <tt>result.get()</tt>.+ * @li If <tt>execution::is_executor<Ex>::value</tt> is false, performs+ * @code ex.dispatch(+ * std::forward<CompletionHandler>(completion_handler),+ * alloc); @endcode+ *+ * @par Completion Signature+ * @code void() @endcode */-template <ASIO_COMPLETION_TOKEN_FOR(void()) CompletionToken>-ASIO_INITFN_AUTO_RESULT_TYPE(CompletionToken, void()) dispatch(- ASIO_MOVE_ARG(CompletionToken) token);+template <ASIO_COMPLETION_TOKEN_FOR(void()) NullaryToken>+ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX(NullaryToken, void()) dispatch(+ ASIO_MOVE_ARG(NullaryToken) token)+ ASIO_INITFN_AUTO_RESULT_TYPE_SUFFIX((+ async_initiate<NullaryToken, void()>(+ declval<detail::initiate_dispatch>(), token)))+{+ return async_initiate<NullaryToken, void()>(+ detail::initiate_dispatch(), token);+} /// Submits a completion token or function object for execution. /**@@ -60,62 +85,118 @@ * The function object may be called from the current thread prior to returning * from <tt>dispatch()</tt>. Otherwise, it is queued for execution. *- * This function has the following effects:+ * @param ex The target executor. *- * @li Constructs a function object handler of type @c Handler, initialized- * with <tt>handler(forward<CompletionToken>(token))</tt>.+ * @param token The @ref completion_token that will be used to produce a+ * completion handler. The function signature of the completion handler must be:+ * @code void handler(); @endcode *- * @li Constructs an object @c result of type <tt>async_result<Handler></tt>,- * initializing the object as <tt>result(handler)</tt>.+ * @returns This function returns <tt>async_initiate<NullaryToken,+ * void()>(Init{ex}, token)</tt>, where @c Init is a function object type+ * defined as: *- * @li Obtains the handler's associated executor object @c ex1 by performing- * <tt>get_associated_executor(handler)</tt>.+ * @code class Init+ * {+ * public:+ * using executor_type = Executor;+ * explicit Init(const Executor& ex) : ex_(ex) {}+ * executor_type get_executor() const noexcept { return ex_; }+ * template <typename CompletionHandler>+ * void operator()(CompletionHandler&& completion_handler) const;+ * private:+ * Executor ex_; // exposition only+ * }; @endcode *- * @li Creates a work object @c w by performing <tt>make_work(ex1)</tt>.+ * The function call operator of @c Init: *+ * @li Obtains the handler's associated executor object @c ex1 of type @c Ex1 by+ * performing @code auto ex1 = get_associated_executor(handler, ex); @endcode+ * * @li Obtains the handler's associated allocator object @c alloc by performing- * <tt>get_associated_allocator(handler)</tt>.+ * @code auto alloc = get_associated_allocator(handler); @endcode *- * @li Constructs a function object @c f with a function call operator that- * performs <tt>ex1.dispatch(std::move(handler), alloc)</tt> followed by- * <tt>w.reset()</tt>.+ * @li If <tt>execution::is_executor<Ex1>::value</tt> is true, constructs a+ * function object @c f with a member @c executor_ that is initialised with+ * <tt>prefer(ex1, execution::outstanding_work.tracked)</tt>, a member @c+ * handler_ that is a decay-copy of @c completion_handler, and a function call+ * operator that performs:+ * @code auto a = get_associated_allocator(handler_);+ * prefer(executor_, execution::allocator(a)).execute(std::move(handler_));+ * @endcode *- * @li Performs <tt>Executor(ex).dispatch(std::move(f), alloc)</tt>.+ * @li If <tt>execution::is_executor<Ex1>::value</tt> is false, constructs a+ * function object @c f with a member @c work_ that is initialised with+ * <tt>make_work_guard(ex1)</tt>, a member @c handler_ that is a decay-copy of+ * @c completion_handler, and a function call operator that performs:+ * @code auto a = get_associated_allocator(handler_);+ * work_.get_executor().dispatch(std::move(handler_), a);+ * work_.reset(); @endcode *- * @li Returns <tt>result.get()</tt>.+ * @li If <tt>execution::is_executor<Ex>::value</tt> is true, performs+ * @code prefer(ex, execution::allocator(alloc)).execute(std::move(f)); @endcode+ *+ * @li If <tt>execution::is_executor<Ex>::value</tt> is false, performs+ * @code ex.dispatch(std::move(f), alloc); @endcode+ *+ * @par Completion Signature+ * @code void() @endcode */ template <typename Executor,- ASIO_COMPLETION_TOKEN_FOR(void()) CompletionToken+ ASIO_COMPLETION_TOKEN_FOR(void()) NullaryToken ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(Executor)>-ASIO_INITFN_AUTO_RESULT_TYPE(CompletionToken, void()) dispatch(+ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX(NullaryToken, void()) dispatch( const Executor& ex,- ASIO_MOVE_ARG(CompletionToken) token+ ASIO_MOVE_ARG(NullaryToken) token ASIO_DEFAULT_COMPLETION_TOKEN(Executor),- typename enable_if<+ typename constraint< execution::is_executor<Executor>::value || is_executor<Executor>::value- >::type* = 0);+ >::type = 0)+ ASIO_INITFN_AUTO_RESULT_TYPE_SUFFIX((+ async_initiate<NullaryToken, void()>(+ declval<detail::initiate_dispatch_with_executor<Executor> >(), token)))+{+ return async_initiate<NullaryToken, void()>(+ detail::initiate_dispatch_with_executor<Executor>(ex), token);+} /// Submits a completion token or function object for execution. /**+ * @param ctx An execution context, from which the target executor is obtained.+ *+ * @param token The @ref completion_token that will be used to produce a+ * completion handler. The function signature of the completion handler must be:+ * @code void handler(); @endcode+ * * @returns <tt>dispatch(ctx.get_executor(),- * forward<CompletionToken>(token))</tt>.+ * forward<NullaryToken>(token))</tt>.+ *+ * @par Completion Signature+ * @code void() @endcode */ template <typename ExecutionContext,- ASIO_COMPLETION_TOKEN_FOR(void()) CompletionToken+ ASIO_COMPLETION_TOKEN_FOR(void()) NullaryToken ASIO_DEFAULT_COMPLETION_TOKEN_TYPE( typename ExecutionContext::executor_type)>-ASIO_INITFN_AUTO_RESULT_TYPE(CompletionToken, void()) dispatch(+ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX(NullaryToken, void()) dispatch( ExecutionContext& ctx,- ASIO_MOVE_ARG(CompletionToken) token+ ASIO_MOVE_ARG(NullaryToken) token ASIO_DEFAULT_COMPLETION_TOKEN( typename ExecutionContext::executor_type),- typename enable_if<is_convertible<- ExecutionContext&, execution_context&>::value>::type* = 0);+ typename constraint<is_convertible<+ ExecutionContext&, execution_context&>::value>::type = 0)+ ASIO_INITFN_AUTO_RESULT_TYPE_SUFFIX((+ async_initiate<NullaryToken, void()>(+ declval<detail::initiate_dispatch_with_executor<+ typename ExecutionContext::executor_type> >(), token)))+{+ return async_initiate<NullaryToken, void()>(+ detail::initiate_dispatch_with_executor<+ typename ExecutionContext::executor_type>(+ ctx.get_executor()), token);+} } // namespace asio #include "asio/detail/pop_options.hpp"--#include "asio/impl/dispatch.hpp" #endif // ASIO_DISPATCH_HPP
link/modules/asio-standalone/asio/include/asio/error.hpp view
@@ -2,7 +2,7 @@ // error.hpp // ~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -222,6 +222,41 @@ /// The descriptor cannot fit into the select system call's fd_set. fd_set_failure };++// boostify: non-boost code starts here+#if !defined(ASIO_ERROR_LOCATION)+# define ASIO_ERROR_LOCATION(e) (void)0+#endif // !defined(ASIO_ERROR_LOCATION)++// boostify: non-boost code ends here+#if !defined(ASIO_ERROR_LOCATION) \+ && !defined(ASIO_DISABLE_ERROR_LOCATION) \+ && defined(ASIO_HAS_BOOST_CONFIG) \+ && (BOOST_VERSION >= 107900)++# define ASIO_ERROR_LOCATION(e) \+ do { \+ BOOST_STATIC_CONSTEXPR boost::source_location loc \+ = BOOST_CURRENT_LOCATION; \+ (e).assign((e), &loc); \+ } while (false)++#else // !defined(ASIO_ERROR_LOCATION)+ // && !defined(ASIO_DISABLE_ERROR_LOCATION)+ // && defined(ASIO_HAS_BOOST_CONFIG)+ // && (BOOST_VERSION >= 107900)++# define ASIO_ERROR_LOCATION(e) (void)0++#endif // !defined(ASIO_ERROR_LOCATION)+ // && !defined(ASIO_DISABLE_ERROR_LOCATION)+ // && defined(ASIO_HAS_BOOST_CONFIG)+ // && (BOOST_VERSION >= 107900)++inline void clear(asio::error_code& ec)+{+ ec.assign(0, ec.category());+} inline const asio::error_category& get_system_category() {
link/modules/asio-standalone/asio/include/asio/error_code.hpp view
@@ -2,7 +2,7 @@ // error_code.hpp // ~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/execution.hpp view
@@ -2,7 +2,7 @@ // execution.hpp // ~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/execution/allocator.hpp view
@@ -2,7 +2,7 @@ // execution/allocator.hpp // ~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -78,25 +78,73 @@ struct allocator_t { #if defined(ASIO_HAS_VARIABLE_TEMPLATES)+# if defined(ASIO_NO_DEPRECATED) template <typename T> ASIO_STATIC_CONSTEXPR(bool,- is_applicable_property_v = is_executor<T>::value- || is_sender<T>::value || is_scheduler<T>::value);+ is_applicable_property_v = (+ is_executor<T>::value));+# else // defined(ASIO_NO_DEPRECATED)+ template <typename T>+ ASIO_STATIC_CONSTEXPR(bool,+ is_applicable_property_v = (+ is_executor<T>::value+ || conditional<+ is_executor<T>::value,+ false_type,+ is_sender<T>+ >::type::value+ || conditional<+ is_executor<T>::value,+ false_type,+ is_scheduler<T>+ >::type::value+ ));+# endif // defined(ASIO_NO_DEPRECATED) #endif // defined(ASIO_HAS_VARIABLE_TEMPLATES) ASIO_STATIC_CONSTEXPR(bool, is_requirable = true); ASIO_STATIC_CONSTEXPR(bool, is_preferable = true); + template <typename T>+ struct static_proxy+ {+#if defined(ASIO_HAS_DEDUCED_QUERY_STATIC_CONSTEXPR_MEMBER_TRAIT)+ struct type+ {+ template <typename P>+ static constexpr auto query(ASIO_MOVE_ARG(P) p)+ noexcept(+ noexcept(+ conditional<true, T, P>::type::query(ASIO_MOVE_CAST(P)(p))+ )+ )+ -> decltype(+ conditional<true, T, P>::type::query(ASIO_MOVE_CAST(P)(p))+ )+ {+ return T::query(ASIO_MOVE_CAST(P)(p));+ }+ };+#else // defined(ASIO_HAS_DEDUCED_QUERY_STATIC_CONSTEXPR_MEMBER_TRAIT)+ typedef T type;+#endif // defined(ASIO_HAS_DEDUCED_QUERY_STATIC_CONSTEXPR_MEMBER_TRAIT)+ };++ template <typename T>+ struct query_static_constexpr_member :+ traits::query_static_constexpr_member<+ typename static_proxy<T>::type, allocator_t> {};+ #if defined(ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT) \ && defined(ASIO_HAS_SFINAE_VARIABLE_TEMPLATES) template <typename T> static ASIO_CONSTEXPR- typename traits::query_static_constexpr_member<T, allocator_t>::result_type+ typename query_static_constexpr_member<T>::result_type static_query() ASIO_NOEXCEPT_IF((- traits::query_static_constexpr_member<T, allocator_t>::is_noexcept))+ query_static_constexpr_member<T>::is_noexcept)) {- return traits::query_static_constexpr_member<T, allocator_t>::value();+ return query_static_constexpr_member<T>::value(); } template <typename E, typename T = decltype(allocator_t::static_query<E>())>@@ -132,10 +180,28 @@ struct allocator_t<void> { #if defined(ASIO_HAS_VARIABLE_TEMPLATES)+# if defined(ASIO_NO_DEPRECATED) template <typename T> ASIO_STATIC_CONSTEXPR(bool,- is_applicable_property_v = is_executor<T>::value- || is_sender<T>::value || is_scheduler<T>::value);+ is_applicable_property_v = (+ is_executor<T>::value));+# else // defined(ASIO_NO_DEPRECATED)+ template <typename T>+ ASIO_STATIC_CONSTEXPR(bool,+ is_applicable_property_v = (+ is_executor<T>::value+ || conditional<+ is_executor<T>::value,+ false_type,+ is_sender<T>+ >::type::value+ || conditional<+ is_executor<T>::value,+ false_type,+ is_scheduler<T>+ >::type::value+ ));+# endif // defined(ASIO_NO_DEPRECATED) #endif // defined(ASIO_HAS_VARIABLE_TEMPLATES) ASIO_STATIC_CONSTEXPR(bool, is_requirable = true);@@ -145,16 +211,46 @@ { } + template <typename T>+ struct static_proxy+ {+#if defined(ASIO_HAS_DEDUCED_QUERY_STATIC_CONSTEXPR_MEMBER_TRAIT)+ struct type+ {+ template <typename P>+ static constexpr auto query(ASIO_MOVE_ARG(P) p)+ noexcept(+ noexcept(+ conditional<true, T, P>::type::query(ASIO_MOVE_CAST(P)(p))+ )+ )+ -> decltype(+ conditional<true, T, P>::type::query(ASIO_MOVE_CAST(P)(p))+ )+ {+ return T::query(ASIO_MOVE_CAST(P)(p));+ }+ };+#else // defined(ASIO_HAS_DEDUCED_QUERY_STATIC_CONSTEXPR_MEMBER_TRAIT)+ typedef T type;+#endif // defined(ASIO_HAS_DEDUCED_QUERY_STATIC_CONSTEXPR_MEMBER_TRAIT)+ };++ template <typename T>+ struct query_static_constexpr_member :+ traits::query_static_constexpr_member<+ typename static_proxy<T>::type, allocator_t> {};+ #if defined(ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT) \ && defined(ASIO_HAS_SFINAE_VARIABLE_TEMPLATES) template <typename T> static ASIO_CONSTEXPR- typename traits::query_static_constexpr_member<T, allocator_t>::result_type+ typename query_static_constexpr_member<T>::result_type static_query() ASIO_NOEXCEPT_IF((- traits::query_static_constexpr_member<T, allocator_t>::is_noexcept))+ query_static_constexpr_member<T>::is_noexcept)) {- return traits::query_static_constexpr_member<T, allocator_t>::value();+ return query_static_constexpr_member<T>::value(); } template <typename E, typename T = decltype(allocator_t::static_query<E>())>@@ -203,8 +299,19 @@ struct is_applicable_property<T, execution::allocator_t<ProtoAllocator> > : integral_constant<bool, execution::is_executor<T>::value- || execution::is_sender<T>::value- || execution::is_scheduler<T>::value>+#if !defined(ASIO_NO_DEPRECATED)+ || conditional<+ execution::is_executor<T>::value,+ false_type,+ execution::is_sender<T>+ >::type::value+ || conditional<+ execution::is_executor<T>::value,+ false_type,+ execution::is_scheduler<T>+ >::type::value+#endif // !defined(ASIO_NO_DEPRECATED)+ > { }; @@ -218,20 +325,20 @@ template <typename T, typename ProtoAllocator> struct static_query<T, execution::allocator_t<ProtoAllocator>, typename enable_if<- traits::query_static_constexpr_member<T,- execution::allocator_t<ProtoAllocator> >::is_valid+ execution::allocator_t<ProtoAllocator>::template+ query_static_constexpr_member<T>::is_valid >::type> { ASIO_STATIC_CONSTEXPR(bool, is_valid = true); ASIO_STATIC_CONSTEXPR(bool, is_noexcept = true); - typedef typename traits::query_static_constexpr_member<T,- execution::allocator_t<ProtoAllocator> >::result_type result_type;+ typedef typename execution::allocator_t<ProtoAllocator>::template+ query_static_constexpr_member<T>::result_type result_type; static ASIO_CONSTEXPR result_type value() {- return traits::query_static_constexpr_member<T,- execution::allocator_t<ProtoAllocator> >::value();+ return execution::allocator_t<ProtoAllocator>::template+ query_static_constexpr_member<T>::value(); } };
link/modules/asio-standalone/asio/include/asio/execution/any_executor.hpp view
@@ -2,7 +2,7 @@ // execution/any_executor.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -19,6 +19,7 @@ #include <new> #include <typeinfo> #include "asio/detail/assert.hpp"+#include "asio/detail/atomic_count.hpp" #include "asio/detail/cstddef.hpp" #include "asio/detail/executor_function.hpp" #include "asio/detail/memory.hpp"@@ -64,10 +65,25 @@ template <class... OtherSupportableProperties> any_executor(any_executor<OtherSupportableProperties...> e); + /// Construct to point to the same target as another any_executor.+ template <class... OtherSupportableProperties>+ any_executor(std::nothrow_t,+ any_executor<OtherSupportableProperties...> e) noexcept;++ /// Construct to point to the same target as another any_executor.+ any_executor(std::nothrow_t, const any_executor& e) noexcept;++ /// Construct to point to the same target as another any_executor.+ any_executor(std::nothrow_t, any_executor&& e) noexcept;+ /// Construct a polymorphic wrapper for the specified executor. template <typename Executor> any_executor(Executor e); + /// Construct a polymorphic wrapper for the specified executor.+ template <typename Executor>+ any_executor(std::nothrow_t, Executor e) noexcept;+ /// Assignment operator. any_executor& operator=(const any_executor& e) noexcept; @@ -126,13 +142,6 @@ /// Execute the function on the target executor. /**- * Do not call this function directly. It is intended for use with the- * execution::execute customisation point.- *- * For example:- * @code execution::any_executor<> ex = ...;- * execution::execute(ex, my_function_object); @endcode- * * Throws asio::bad_executor if the polymorphic wrapper has no target. */ template <typename Function>@@ -481,13 +490,108 @@ { }; +template <typename Props>+struct is_valid_target_executor<int, Props> : false_type+{+};++class shared_target_executor+{+public:+ template <typename E>+ shared_target_executor(ASIO_MOVE_ARG(E) e,+ typename decay<E>::type*& target)+ {+ impl<typename decay<E>::type>* i =+ new impl<typename decay<E>::type>(ASIO_MOVE_CAST(E)(e));+ target = &i->ex_;+ impl_ = i;+ }++ template <typename E>+ shared_target_executor(std::nothrow_t, ASIO_MOVE_ARG(E) e,+ typename decay<E>::type*& target) ASIO_NOEXCEPT+ {+ impl<typename decay<E>::type>* i =+ new (std::nothrow) impl<typename decay<E>::type>(+ ASIO_MOVE_CAST(E)(e));+ target = i ? &i->ex_ : 0;+ impl_ = i;+ }++ shared_target_executor(+ const shared_target_executor& other) ASIO_NOEXCEPT+ : impl_(other.impl_)+ {+ if (impl_)+ asio::detail::ref_count_up(impl_->ref_count_);+ }++ shared_target_executor& operator=(+ const shared_target_executor& other) ASIO_NOEXCEPT+ {+ impl_ = other.impl_;+ if (impl_)+ asio::detail::ref_count_up(impl_->ref_count_);+ return *this;+ }++#if defined(ASIO_HAS_MOVE)+ shared_target_executor(+ shared_target_executor&& other) ASIO_NOEXCEPT+ : impl_(other.impl_)+ {+ other.impl_ = 0;+ }++ shared_target_executor& operator=(+ shared_target_executor&& other) ASIO_NOEXCEPT+ {+ impl_ = other.impl_;+ other.impl_ = 0;+ return *this;+ }+#endif // defined(ASIO_HAS_MOVE)++ ~shared_target_executor()+ {+ if (impl_)+ if (asio::detail::ref_count_down(impl_->ref_count_))+ delete impl_;+ }++ void* get() const ASIO_NOEXCEPT+ {+ return impl_ ? impl_->get() : 0;+ }++private:+ struct impl_base+ {+ impl_base() : ref_count_(1) {}+ virtual ~impl_base() {}+ virtual void* get() = 0;+ asio::detail::atomic_count ref_count_;+ };++ template <typename Executor>+ struct impl : impl_base+ {+ impl(Executor ex) : ex_(ASIO_MOVE_CAST(Executor)(ex)) {}+ virtual void* get() { return &ex_; }+ Executor ex_;+ };++ impl_base* impl_;+};+ class any_executor_base { public: any_executor_base() ASIO_NOEXCEPT- : object_fns_(object_fns_table<void>()),+ : object_fns_(0), target_(0),- target_fns_(target_fns_table<void>())+ target_fns_(0) { } @@ -506,28 +610,74 @@ } template <ASIO_EXECUTION_EXECUTOR Executor>+ any_executor_base(std::nothrow_t, Executor ex, false_type) ASIO_NOEXCEPT+ : target_fns_(target_fns_table<Executor>(+ any_executor_base::query_blocking(ex,+ can_query<const Executor&, const execution::blocking_t&>())+ == execution::blocking.always))+ {+ any_executor_base::construct_object(std::nothrow, ex,+ integral_constant<bool,+ sizeof(Executor) <= sizeof(object_type)+ && alignment_of<Executor>::value <= alignment_of<object_type>::value+ >());+ if (target_ == 0)+ {+ object_fns_ = 0;+ target_fns_ = 0;+ }+ }++ template <ASIO_EXECUTION_EXECUTOR Executor> any_executor_base(Executor other, true_type)- : object_fns_(object_fns_table<asio::detail::shared_ptr<void> >()),+ : object_fns_(object_fns_table<shared_target_executor>()), target_fns_(other.target_fns_) {- asio::detail::shared_ptr<Executor> p =- asio::detail::make_shared<Executor>(- ASIO_MOVE_CAST(Executor)(other));+ Executor* p = 0;+ new (&object_) shared_target_executor(+ ASIO_MOVE_CAST(Executor)(other), p); target_ = p->template target<void>();- new (&object_) asio::detail::shared_ptr<void>(- ASIO_MOVE_CAST(asio::detail::shared_ptr<Executor>)(p)); } - any_executor_base(const any_executor_base& other) ASIO_NOEXCEPT- : object_fns_(other.object_fns_),+ template <ASIO_EXECUTION_EXECUTOR Executor>+ any_executor_base(std::nothrow_t,+ Executor other, true_type) ASIO_NOEXCEPT+ : object_fns_(object_fns_table<shared_target_executor>()), target_fns_(other.target_fns_) {- object_fns_->copy(*this, other);+ Executor* p = 0;+ new (&object_) shared_target_executor(+ std::nothrow, ASIO_MOVE_CAST(Executor)(other), p);+ if (p)+ target_ = p->template target<void>();+ else+ {+ target_ = 0;+ object_fns_ = 0;+ target_fns_ = 0;+ } } + any_executor_base(const any_executor_base& other) ASIO_NOEXCEPT+ {+ if (!!other)+ {+ object_fns_ = other.object_fns_;+ target_fns_ = other.target_fns_;+ object_fns_->copy(*this, other);+ }+ else+ {+ object_fns_ = 0;+ target_ = 0;+ target_fns_ = 0;+ }+ }+ ~any_executor_base() ASIO_NOEXCEPT {- object_fns_->destroy(*this);+ if (!!*this)+ object_fns_->destroy(*this); } any_executor_base& operator=(@@ -535,33 +685,53 @@ { if (this != &other) {- object_fns_->destroy(*this);- object_fns_ = other.object_fns_;- target_fns_ = other.target_fns_;- object_fns_->copy(*this, other);+ if (!!*this)+ object_fns_->destroy(*this);+ if (!!other)+ {+ object_fns_ = other.object_fns_;+ target_fns_ = other.target_fns_;+ object_fns_->copy(*this, other);+ }+ else+ {+ object_fns_ = 0;+ target_ = 0;+ target_fns_ = 0;+ } } return *this; } any_executor_base& operator=(nullptr_t) ASIO_NOEXCEPT {- object_fns_->destroy(*this);+ if (target_)+ object_fns_->destroy(*this); target_ = 0;- object_fns_ = object_fns_table<void>();- target_fns_ = target_fns_table<void>();+ object_fns_ = 0;+ target_fns_ = 0; return *this; } #if defined(ASIO_HAS_MOVE) any_executor_base(any_executor_base&& other) ASIO_NOEXCEPT- : object_fns_(other.object_fns_),- target_fns_(other.target_fns_) {- other.object_fns_ = object_fns_table<void>();- other.target_fns_ = target_fns_table<void>();- object_fns_->move(*this, other);- other.target_ = 0;+ if (other.target_)+ {+ object_fns_ = other.object_fns_;+ target_fns_ = other.target_fns_;+ other.object_fns_ = 0;+ other.target_fns_ = 0;+ object_fns_->move(*this, other);+ other.target_ = 0;+ }+ else+ {+ object_fns_ = 0;+ target_ = 0;+ target_fns_ = 0;+ } } any_executor_base& operator=(@@ -569,13 +739,23 @@ { if (this != &other) {- object_fns_->destroy(*this);- object_fns_ = other.object_fns_;- other.object_fns_ = object_fns_table<void>();- target_fns_ = other.target_fns_;- other.target_fns_ = target_fns_table<void>();- object_fns_->move(*this, other);- other.target_ = 0;+ if (!!*this)+ object_fns_->destroy(*this);+ if (!!other)+ {+ object_fns_ = other.object_fns_;+ target_fns_ = other.target_fns_;+ other.object_fns_ = 0;+ other.target_fns_ = 0;+ object_fns_->move(*this, other);+ other.target_ = 0;+ }+ else+ {+ object_fns_ = 0;+ target_ = 0;+ target_fns_ = 0;+ } } return *this; }@@ -595,34 +775,53 @@ template <typename F> void execute(ASIO_MOVE_ARG(F) f) const {- if (target_fns_->blocking_execute != 0)+ if (target_) {- asio::detail::non_const_lvalue<F> f2(f);- target_fns_->blocking_execute(*this, function_view(f2.value));+ if (target_fns_->blocking_execute != 0)+ {+ asio::detail::non_const_lvalue<F> f2(f);+ target_fns_->blocking_execute(*this, function_view(f2.value));+ }+ else+ {+ target_fns_->execute(*this,+ function(ASIO_MOVE_CAST(F)(f), std::allocator<void>()));+ } } else {- target_fns_->execute(*this,- function(ASIO_MOVE_CAST(F)(f), std::allocator<void>()));+ bad_executor ex;+ asio::detail::throw_exception(ex); } } template <typename Executor> Executor* target() {- return static_cast<Executor*>(target_);+ return target_ && (is_same<Executor, void>::value+ || target_fns_->target_type() == target_type_ex<Executor>())+ ? static_cast<Executor*>(target_) : 0; } template <typename Executor> const Executor* target() const {- return static_cast<Executor*>(target_);+ return target_ && (is_same<Executor, void>::value+ || target_fns_->target_type() == target_type_ex<Executor>())+ ? static_cast<const Executor*>(target_) : 0; } +#if !defined(ASIO_NO_TYPEID) const std::type_info& target_type() const {- return target_fns_->target_type();+ return target_ ? target_fns_->target_type() : typeid(void); }+#else // !defined(ASIO_NO_TYPEID)+ const void* target_type() const+ {+ return target_ ? target_fns_->target_type() : 0;+ }+#endif // !defined(ASIO_NO_TYPEID) struct unspecified_bool_type_t {}; typedef void (*unspecified_bool_type)(unspecified_bool_type_t);@@ -672,57 +871,22 @@ const void* (*target)(const any_executor_base&); }; - static void destroy_void(any_executor_base&)- {- }-- static void copy_void(any_executor_base& ex1, const any_executor_base&)- {- ex1.target_ = 0;- }-- static void move_void(any_executor_base& ex1, any_executor_base&)- {- ex1.target_ = 0;- }-- static const void* target_void(const any_executor_base&)- {- return 0;- }-- template <typename Obj>- static const object_fns* object_fns_table(- typename enable_if<- is_same<Obj, void>::value- >::type* = 0)- {- static const object_fns fns =- {- &any_executor_base::destroy_void,- &any_executor_base::copy_void,- &any_executor_base::move_void,- &any_executor_base::target_void- };- return &fns;- }- static void destroy_shared(any_executor_base& ex) {- typedef asio::detail::shared_ptr<void> type;+ typedef shared_target_executor type; ex.object<type>().~type(); } static void copy_shared(any_executor_base& ex1, const any_executor_base& ex2) {- typedef asio::detail::shared_ptr<void> type;+ typedef shared_target_executor type; new (&ex1.object_) type(ex2.object<type>()); ex1.target_ = ex2.target_; } static void move_shared(any_executor_base& ex1, any_executor_base& ex2) {- typedef asio::detail::shared_ptr<void> type;+ typedef shared_target_executor type; new (&ex1.object_) type(ASIO_MOVE_CAST(type)(ex2.object<type>())); ex1.target_ = ex2.target_; ex2.object<type>().~type();@@ -730,14 +894,14 @@ static const void* target_shared(const any_executor_base& ex) {- typedef asio::detail::shared_ptr<void> type;+ typedef shared_target_executor type; return ex.object<type>().get(); } template <typename Obj> static const object_fns* object_fns_table( typename enable_if<- is_same<Obj, asio::detail::shared_ptr<void> >::value+ is_same<Obj, shared_target_executor>::value >::type* = 0) { static const object_fns fns =@@ -781,7 +945,7 @@ static const object_fns* object_fns_table( typename enable_if< !is_same<Obj, void>::value- && !is_same<Obj, asio::detail::shared_ptr<void> >::value+ && !is_same<Obj, shared_target_executor>::value >::type* = 0) { static const object_fns fns =@@ -799,75 +963,64 @@ struct target_fns {+#if !defined(ASIO_NO_TYPEID) const std::type_info& (*target_type)();+#else // !defined(ASIO_NO_TYPEID)+ const void* (*target_type)();+#endif // !defined(ASIO_NO_TYPEID) bool (*equal)(const any_executor_base&, const any_executor_base&); void (*execute)(const any_executor_base&, ASIO_MOVE_ARG(function)); void (*blocking_execute)(const any_executor_base&, function_view); }; - static const std::type_info& target_type_void()- {- return typeid(void);- }-- static bool equal_void(const any_executor_base&, const any_executor_base&)- {- return true;- }-- static void execute_void(const any_executor_base&,- ASIO_MOVE_ARG(function))- {- bad_executor ex;- asio::detail::throw_exception(ex);- }-- static void blocking_execute_void(const any_executor_base&, function_view)- {- bad_executor ex;- asio::detail::throw_exception(ex);- }-+#if !defined(ASIO_NO_TYPEID) template <typename Ex>- static const target_fns* target_fns_table(- typename enable_if<- is_same<Ex, void>::value- >::type* = 0)+ static const std::type_info& target_type_ex() {- static const target_fns fns =- {- &any_executor_base::target_type_void,- &any_executor_base::equal_void,- &any_executor_base::execute_void,- &any_executor_base::blocking_execute_void- };- return &fns;+ return typeid(Ex); }-+#else // !defined(ASIO_NO_TYPEID) template <typename Ex>- static const std::type_info& target_type_ex()+ static const void* target_type_ex() {- return typeid(Ex);+ static int unique_id;+ return &unique_id; }+#endif // !defined(ASIO_NO_TYPEID) template <typename Ex> static bool equal_ex(const any_executor_base& ex1, const any_executor_base& ex2) {- return *ex1.target<Ex>() == *ex2.target<Ex>();+ const Ex* p1 = ex1.target<Ex>();+ const Ex* p2 = ex2.target<Ex>();+ ASIO_ASSUME(p1 != 0 && p2 != 0);+ return *p1 == *p2; } template <typename Ex> static void execute_ex(const any_executor_base& ex, ASIO_MOVE_ARG(function) f) {- execution::execute(*ex.target<Ex>(), ASIO_MOVE_CAST(function)(f));+ const Ex* p = ex.target<Ex>();+ ASIO_ASSUME(p != 0);+#if defined(ASIO_NO_DEPRECATED)+ p->execute(ASIO_MOVE_CAST(function)(f));+#else // defined(ASIO_NO_DEPRECATED)+ execution::execute(*p, ASIO_MOVE_CAST(function)(f));+#endif // defined(ASIO_NO_DEPRECATED) } template <typename Ex> static void blocking_execute_ex(const any_executor_base& ex, function_view f) {- execution::execute(*ex.target<Ex>(), f);+ const Ex* p = ex.target<Ex>();+ ASIO_ASSUME(p != 0);+#if defined(ASIO_NO_DEPRECATED)+ p->execute(f);+#else // defined(ASIO_NO_DEPRECATED)+ execution::execute(*p, f);+#endif // defined(ASIO_NO_DEPRECATED) } template <typename Ex>@@ -1125,20 +1278,37 @@ template <typename Executor> void construct_object(Executor& ex, false_type) {- object_fns_ = object_fns_table<asio::detail::shared_ptr<void> >();- asio::detail::shared_ptr<Executor> p =- asio::detail::make_shared<Executor>(- ASIO_MOVE_CAST(Executor)(ex));- target_ = p.get();- new (&object_) asio::detail::shared_ptr<void>(- ASIO_MOVE_CAST(asio::detail::shared_ptr<Executor>)(p));+ object_fns_ = object_fns_table<shared_target_executor>();+ Executor* p = 0;+ new (&object_) shared_target_executor(+ ASIO_MOVE_CAST(Executor)(ex), p);+ target_ = p; } + template <typename Executor>+ void construct_object(std::nothrow_t,+ Executor& ex, true_type) ASIO_NOEXCEPT+ {+ object_fns_ = object_fns_table<Executor>();+ target_ = new (&object_) Executor(ASIO_MOVE_CAST(Executor)(ex));+ }++ template <typename Executor>+ void construct_object(std::nothrow_t,+ Executor& ex, false_type) ASIO_NOEXCEPT+ {+ object_fns_ = object_fns_table<shared_target_executor>();+ Executor* p = 0;+ new (&object_) shared_target_executor(+ std::nothrow, ASIO_MOVE_CAST(Executor)(ex), p);+ target_ = p;+ }+ /*private:*/public: // template <typename...> friend class any_executor; typedef aligned_storage<- sizeof(asio::detail::shared_ptr<void>),+ sizeof(asio::detail::shared_ptr<void>) + sizeof(void*), alignment_of<asio::detail::shared_ptr<void> >::value >::type object_type; @@ -1198,6 +1368,21 @@ { } + template <typename Executor>+ any_executor(std::nothrow_t, Executor ex,+ typename enable_if<+ conditional<+ !is_same<Executor, any_executor>::value+ && !is_base_of<detail::any_executor_base, Executor>::value,+ is_executor<Executor>,+ false_type+ >::type::value+ >::type* = 0) ASIO_NOEXCEPT+ : detail::any_executor_base(std::nothrow,+ ASIO_MOVE_CAST(Executor)(ex), false_type())+ {+ }+ #if defined(ASIO_HAS_VARIADIC_TEMPLATES) template <typename... OtherSupportableProperties>@@ -1207,6 +1392,14 @@ { } + template <typename... OtherSupportableProperties>+ any_executor(std::nothrow_t,+ any_executor<OtherSupportableProperties...> other) ASIO_NOEXCEPT+ : detail::any_executor_base(+ static_cast<const detail::any_executor_base&>(other))+ {+ }+ #else // defined(ASIO_HAS_VARIADIC_TEMPLATES) template <typename U0, typename U1, typename U2, typename U3,@@ -1217,6 +1410,15 @@ { } + template <typename U0, typename U1, typename U2, typename U3,+ typename U4, typename U5, typename U6, typename U7>+ any_executor(std::nothrow_t,+ any_executor<U0, U1, U2, U3, U4, U5, U6, U7> other) ASIO_NOEXCEPT+ : detail::any_executor_base(+ static_cast<const detail::any_executor_base&>(other))+ {+ }+ #endif // defined(ASIO_HAS_VARIADIC_TEMPLATES) any_executor(const any_executor& other) ASIO_NOEXCEPT@@ -1225,6 +1427,12 @@ { } + any_executor(std::nothrow_t, const any_executor& other) ASIO_NOEXCEPT+ : detail::any_executor_base(+ static_cast<const detail::any_executor_base&>(other))+ {+ }+ any_executor& operator=(const any_executor& other) ASIO_NOEXCEPT { if (this != &other)@@ -1250,6 +1458,13 @@ { } + any_executor(std::nothrow_t, any_executor&& other) ASIO_NOEXCEPT+ : detail::any_executor_base(+ static_cast<any_executor_base&&>(+ static_cast<any_executor_base&>(other)))+ {+ }+ any_executor& operator=(any_executor&& other) ASIO_NOEXCEPT { if (this != &other)@@ -1279,39 +1494,65 @@ { return any_executor_base::equality_helper(other); }-}; -inline bool operator==(const any_executor<>& a,- const any_executor<>& b) ASIO_NOEXCEPT-{- return a.equality_helper(b);-}+ template <typename AnyExecutor1, typename AnyExecutor2>+ friend typename enable_if<+ is_base_of<any_executor, AnyExecutor1>::value+ || is_base_of<any_executor, AnyExecutor2>::value,+ bool+ >::type operator==(const AnyExecutor1& a,+ const AnyExecutor2& b) ASIO_NOEXCEPT+ {+ return static_cast<const any_executor&>(a).equality_helper(b);+ } -inline bool operator==(const any_executor<>& a, nullptr_t) ASIO_NOEXCEPT-{- return !a;-}+ template <typename AnyExecutor>+ friend typename enable_if<+ is_same<AnyExecutor, any_executor>::value,+ bool+ >::type operator==(const AnyExecutor& a, nullptr_t) ASIO_NOEXCEPT+ {+ return !a;+ } -inline bool operator==(nullptr_t, const any_executor<>& b) ASIO_NOEXCEPT-{- return !b;-}+ template <typename AnyExecutor>+ friend typename enable_if<+ is_same<AnyExecutor, any_executor>::value,+ bool+ >::type operator==(nullptr_t, const AnyExecutor& b) ASIO_NOEXCEPT+ {+ return !b;+ } -inline bool operator!=(const any_executor<>& a,- const any_executor<>& b) ASIO_NOEXCEPT-{- return !a.equality_helper(b);-}+ template <typename AnyExecutor1, typename AnyExecutor2>+ friend typename enable_if<+ is_base_of<any_executor, AnyExecutor1>::value+ || is_base_of<any_executor, AnyExecutor2>::value,+ bool+ >::type operator!=(const AnyExecutor1& a,+ const AnyExecutor2& b) ASIO_NOEXCEPT+ {+ return !static_cast<const any_executor&>(a).equality_helper(b);+ } -inline bool operator!=(const any_executor<>& a, nullptr_t) ASIO_NOEXCEPT-{- return !!a;-}+ template <typename AnyExecutor>+ friend typename enable_if<+ is_same<AnyExecutor, any_executor>::value,+ bool+ >::type operator!=(const AnyExecutor& a, nullptr_t) ASIO_NOEXCEPT+ {+ return !!a;+ } -inline bool operator!=(nullptr_t, const any_executor<>& b) ASIO_NOEXCEPT-{- return !!b;-}+ template <typename AnyExecutor>+ friend typename enable_if<+ is_same<AnyExecutor, any_executor>::value,+ bool+ >::type operator!=(nullptr_t, const AnyExecutor& b) ASIO_NOEXCEPT+ {+ return !!b;+ }+}; inline void swap(any_executor<>& a, any_executor<>& b) ASIO_NOEXCEPT {@@ -1358,6 +1599,25 @@ { } + template <typename Executor>+ any_executor(std::nothrow_t, Executor ex,+ typename enable_if<+ conditional<+ !is_same<Executor, any_executor>::value+ && !is_base_of<detail::any_executor_base, Executor>::value,+ detail::is_valid_target_executor<+ Executor, void(SupportableProperties...)>,+ false_type+ >::type::value+ >::type* = 0) ASIO_NOEXCEPT+ : detail::any_executor_base(std::nothrow,+ ASIO_MOVE_CAST(Executor)(ex), false_type()),+ prop_fns_(prop_fns_table<Executor>())+ {+ if (this->template target<void>() == 0)+ prop_fns_ = prop_fns_table<void>();+ }+ template <typename... OtherSupportableProperties> any_executor(any_executor<OtherSupportableProperties...> other, typename enable_if<@@ -1378,6 +1638,29 @@ { } + template <typename... OtherSupportableProperties>+ any_executor(std::nothrow_t,+ any_executor<OtherSupportableProperties...> other,+ typename enable_if<+ conditional<+ !is_same<+ any_executor<OtherSupportableProperties...>,+ any_executor+ >::value,+ typename detail::supportable_properties<+ 0, void(SupportableProperties...)>::template is_valid_target<+ any_executor<OtherSupportableProperties...> >,+ false_type+ >::type::value+ >::type* = 0) ASIO_NOEXCEPT+ : detail::any_executor_base(std::nothrow, ASIO_MOVE_CAST(+ any_executor<OtherSupportableProperties...>)(other), true_type()),+ prop_fns_(prop_fns_table<any_executor<OtherSupportableProperties...> >())+ {+ if (this->template target<void>() == 0)+ prop_fns_ = prop_fns_table<void>();+ }+ any_executor(const any_executor& other) ASIO_NOEXCEPT : detail::any_executor_base( static_cast<const detail::any_executor_base&>(other)),@@ -1385,6 +1668,13 @@ { } + any_executor(std::nothrow_t, const any_executor& other) ASIO_NOEXCEPT+ : detail::any_executor_base(+ static_cast<const detail::any_executor_base&>(other)),+ prop_fns_(other.prop_fns_)+ {+ }+ any_executor& operator=(const any_executor& other) ASIO_NOEXCEPT { if (this != &other)@@ -1414,6 +1704,15 @@ other.prop_fns_ = prop_fns_table<void>(); } + any_executor(std::nothrow_t, any_executor&& other) ASIO_NOEXCEPT+ : detail::any_executor_base(+ static_cast<any_executor_base&&>(+ static_cast<any_executor_base&>(other))),+ prop_fns_(other.prop_fns_)+ {+ other.prop_fns_ = prop_fns_table<void>();+ }+ any_executor& operator=(any_executor&& other) ASIO_NOEXCEPT { if (this != &other)@@ -1451,6 +1750,64 @@ return any_executor_base::equality_helper(other); } + template <typename AnyExecutor1, typename AnyExecutor2>+ friend typename enable_if<+ is_base_of<any_executor, AnyExecutor1>::value+ || is_base_of<any_executor, AnyExecutor2>::value,+ bool+ >::type operator==(const AnyExecutor1& a,+ const AnyExecutor2& b) ASIO_NOEXCEPT+ {+ return static_cast<const any_executor&>(a).equality_helper(b);+ }++ template <typename AnyExecutor>+ friend typename enable_if<+ is_same<AnyExecutor, any_executor>::value,+ bool+ >::type operator==(const AnyExecutor& a, nullptr_t) ASIO_NOEXCEPT+ {+ return !a;+ }++ template <typename AnyExecutor>+ friend typename enable_if<+ is_same<AnyExecutor, any_executor>::value,+ bool+ >::type operator==(nullptr_t, const AnyExecutor& b) ASIO_NOEXCEPT+ {+ return !b;+ }++ template <typename AnyExecutor1, typename AnyExecutor2>+ friend typename enable_if<+ is_base_of<any_executor, AnyExecutor1>::value+ || is_base_of<any_executor, AnyExecutor2>::value,+ bool+ >::type operator!=(const AnyExecutor1& a,+ const AnyExecutor2& b) ASIO_NOEXCEPT+ {+ return !static_cast<const any_executor&>(a).equality_helper(b);+ }++ template <typename AnyExecutor>+ friend typename enable_if<+ is_same<AnyExecutor, any_executor>::value,+ bool+ >::type operator!=(const AnyExecutor& a, nullptr_t) ASIO_NOEXCEPT+ {+ return !!a;+ }++ template <typename AnyExecutor>+ friend typename enable_if<+ is_same<AnyExecutor, any_executor>::value,+ bool+ >::type operator!=(nullptr_t, const AnyExecutor& b) ASIO_NOEXCEPT+ {+ return !!b;+ }+ template <typename T> struct find_convertible_property : detail::supportable_properties<@@ -1596,48 +1953,6 @@ }; template <typename... SupportableProperties>-inline bool operator==(const any_executor<SupportableProperties...>& a,- const any_executor<SupportableProperties...>& b) ASIO_NOEXCEPT-{- return a.equality_helper(b);-}--template <typename... SupportableProperties>-inline bool operator==(const any_executor<SupportableProperties...>& a,- nullptr_t) ASIO_NOEXCEPT-{- return !a;-}--template <typename... SupportableProperties>-inline bool operator==(nullptr_t,- const any_executor<SupportableProperties...>& b) ASIO_NOEXCEPT-{- return !b;-}--template <typename... SupportableProperties>-inline bool operator!=(const any_executor<SupportableProperties...>& a,- const any_executor<SupportableProperties...>& b) ASIO_NOEXCEPT-{- return !a.equality_helper(b);-}--template <typename... SupportableProperties>-inline bool operator!=(const any_executor<SupportableProperties...>& a,- nullptr_t) ASIO_NOEXCEPT-{- return !!a;-}--template <typename... SupportableProperties>-inline bool operator!=(nullptr_t,- const any_executor<SupportableProperties...>& b) ASIO_NOEXCEPT-{- return !!b;-}--template <typename... SupportableProperties> inline void swap(any_executor<SupportableProperties...>& a, any_executor<SupportableProperties...>& b) ASIO_NOEXCEPT {@@ -1717,6 +2032,15 @@ other.prop_fns_ = prop_fns_table<void>(); \ } \ \+ any_executor(std::nothrow_t, any_executor&& other) ASIO_NOEXCEPT \+ : detail::any_executor_base( \+ static_cast<any_executor_base&&>( \+ static_cast<any_executor_base&>(other))), \+ prop_fns_(other.prop_fns_) \+ { \+ other.prop_fns_ = prop_fns_table<void>(); \+ } \+ \ any_executor& operator=(any_executor&& other) ASIO_NOEXCEPT \ { \ if (this != &other) \@@ -1774,6 +2098,25 @@ { \ } \ \+ template <ASIO_EXECUTION_EXECUTOR Executor> \+ any_executor(std::nothrow_t, Executor ex, \+ typename enable_if< \+ conditional< \+ !is_same<Executor, any_executor>::value \+ && !is_base_of<detail::any_executor_base, Executor>::value, \+ detail::is_valid_target_executor< \+ Executor, void(ASIO_VARIADIC_TARGS(n))>, \+ false_type \+ >::type::value \+ >::type* = 0) ASIO_NOEXCEPT \+ : detail::any_executor_base(std::nothrow, \+ ASIO_MOVE_CAST(Executor)(ex), false_type()), \+ prop_fns_(prop_fns_table<Executor>()) \+ { \+ if (this->template target<void>() == 0) \+ prop_fns_ = prop_fns_table<void>(); \+ } \+ \ any_executor(const any_executor& other) ASIO_NOEXCEPT \ : detail::any_executor_base( \ static_cast<const detail::any_executor_base&>(other)), \@@ -1781,6 +2124,16 @@ { \ } \ \+ any_executor(std::nothrow_t, \+ const any_executor& other) ASIO_NOEXCEPT \+ : detail::any_executor_base( \+ static_cast<const detail::any_executor_base&>(other)), \+ prop_fns_(other.prop_fns_) \+ { \+ if (this->template target<void>() == 0) \+ prop_fns_ = prop_fns_table<void>(); \+ } \+ \ any_executor(any_executor<> other) \ : detail::any_executor_base(ASIO_MOVE_CAST( \ any_executor<>)(other), true_type()), \@@ -1788,6 +2141,15 @@ { \ } \ \+ any_executor(std::nothrow_t, any_executor<> other) ASIO_NOEXCEPT \+ : detail::any_executor_base(std::nothrow, \+ ASIO_MOVE_CAST(any_executor<>)(other), true_type()), \+ prop_fns_(prop_fns_table<any_executor<> >()) \+ { \+ if (this->template target<void>() == 0) \+ prop_fns_ = prop_fns_table<void>(); \+ } \+ \ template <typename OtherAnyExecutor> \ any_executor(OtherAnyExecutor other, \ typename enable_if< \@@ -1807,6 +2169,27 @@ { \ } \ \+ template <typename OtherAnyExecutor> \+ any_executor(std::nothrow_t, OtherAnyExecutor other, \+ typename enable_if< \+ conditional< \+ !is_same<OtherAnyExecutor, any_executor>::value \+ && is_base_of<detail::any_executor_base, \+ OtherAnyExecutor>::value, \+ typename detail::supportable_properties< \+ 0, void(ASIO_VARIADIC_TARGS(n))>::template \+ is_valid_target<OtherAnyExecutor>, \+ false_type \+ >::type::value \+ >::type* = 0) ASIO_NOEXCEPT \+ : detail::any_executor_base(std::nothrow, \+ ASIO_MOVE_CAST(OtherAnyExecutor)(other), true_type()), \+ prop_fns_(prop_fns_table<OtherAnyExecutor>()) \+ { \+ if (this->template target<void>() == 0) \+ prop_fns_ = prop_fns_table<void>(); \+ } \+ \ any_executor& operator=(const any_executor& other) ASIO_NOEXCEPT \ { \ if (this != &other) \@@ -1850,6 +2233,64 @@ return any_executor_base::equality_helper(other); \ } \ \+ template <typename AnyExecutor1, typename AnyExecutor2> \+ friend typename enable_if< \+ is_base_of<any_executor, AnyExecutor1>::value \+ || is_base_of<any_executor, AnyExecutor2>::value, \+ bool \+ >::type operator==(const AnyExecutor1& a, \+ const AnyExecutor2& b) ASIO_NOEXCEPT \+ { \+ return static_cast<const any_executor&>(a).equality_helper(b); \+ } \+ \+ template <typename AnyExecutor> \+ friend typename enable_if< \+ is_same<AnyExecutor, any_executor>::value, \+ bool \+ >::type operator==(const AnyExecutor& a, nullptr_t) ASIO_NOEXCEPT \+ { \+ return !a; \+ } \+ \+ template <typename AnyExecutor> \+ friend typename enable_if< \+ is_same<AnyExecutor, any_executor>::value, \+ bool \+ >::type operator==(nullptr_t, const AnyExecutor& b) ASIO_NOEXCEPT \+ { \+ return !b; \+ } \+ \+ template <typename AnyExecutor1, typename AnyExecutor2> \+ friend typename enable_if< \+ is_base_of<any_executor, AnyExecutor1>::value \+ || is_base_of<any_executor, AnyExecutor2>::value, \+ bool \+ >::type operator!=(const AnyExecutor1& a, \+ const AnyExecutor2& b) ASIO_NOEXCEPT \+ { \+ return !static_cast<const any_executor&>(a).equality_helper(b); \+ } \+ \+ template <typename AnyExecutor> \+ friend typename enable_if< \+ is_same<AnyExecutor, any_executor>::value, \+ bool \+ >::type operator!=(const AnyExecutor& a, nullptr_t) ASIO_NOEXCEPT \+ { \+ return !!a; \+ } \+ \+ template <typename AnyExecutor> \+ friend typename enable_if< \+ is_same<AnyExecutor, any_executor>::value, \+ bool \+ >::type operator!=(nullptr_t, const AnyExecutor& b) ASIO_NOEXCEPT \+ { \+ return !!b; \+ } \+ \ template <typename T> \ struct find_convertible_property : \ detail::supportable_properties< \@@ -1987,48 +2428,6 @@ typedef detail::supportable_properties<0, \ void(ASIO_VARIADIC_TARGS(n))> supportable_properties_type; \ }; \- \- template <ASIO_VARIADIC_TPARAMS(n)> \- inline bool operator==(const any_executor<ASIO_VARIADIC_TARGS(n)>& a, \- const any_executor<ASIO_VARIADIC_TARGS(n)>& b) ASIO_NOEXCEPT \- { \- return a.equality_helper(b); \- } \- \- template <ASIO_VARIADIC_TPARAMS(n)> \- inline bool operator==(const any_executor<ASIO_VARIADIC_TARGS(n)>& a, \- nullptr_t) ASIO_NOEXCEPT \- { \- return !a; \- } \- \- template <ASIO_VARIADIC_TPARAMS(n)> \- inline bool operator==(nullptr_t, \- const any_executor<ASIO_VARIADIC_TARGS(n)>& b) ASIO_NOEXCEPT \- { \- return !b; \- } \- \- template <ASIO_VARIADIC_TPARAMS(n)> \- inline bool operator!=(const any_executor<ASIO_VARIADIC_TARGS(n)>& a, \- const any_executor<ASIO_VARIADIC_TARGS(n)>& b) ASIO_NOEXCEPT \- { \- return !a.equality_helper(b); \- } \- \- template <ASIO_VARIADIC_TPARAMS(n)> \- inline bool operator!=(const any_executor<ASIO_VARIADIC_TARGS(n)>& a, \- nullptr_t) ASIO_NOEXCEPT \- { \- return !!a; \- } \- \- template <ASIO_VARIADIC_TPARAMS(n)> \- inline bool operator!=(nullptr_t, \- const any_executor<ASIO_VARIADIC_TARGS(n)>& b) ASIO_NOEXCEPT \- { \- return !!b; \- } \ \ template <ASIO_VARIADIC_TPARAMS(n)> \ inline void swap(any_executor<ASIO_VARIADIC_TARGS(n)>& a, \
link/modules/asio-standalone/asio/include/asio/execution/bad_executor.hpp view
@@ -2,7 +2,7 @@ // execution/bad_executor.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/execution/blocking.hpp view
@@ -2,7 +2,7 @@ // execution/blocking.hpp // ~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -25,6 +25,7 @@ #include "asio/prefer.hpp" #include "asio/query.hpp" #include "asio/require.hpp"+#include "asio/traits/execute_member.hpp" #include "asio/traits/query_free.hpp" #include "asio/traits/query_member.hpp" #include "asio/traits/query_static_constexpr_member.hpp"@@ -208,10 +209,28 @@ struct blocking_t { #if defined(ASIO_HAS_VARIABLE_TEMPLATES)+# if defined(ASIO_NO_DEPRECATED) template <typename T> ASIO_STATIC_CONSTEXPR(bool,- is_applicable_property_v = is_executor<T>::value- || is_sender<T>::value || is_scheduler<T>::value);+ is_applicable_property_v = (+ is_executor<T>::value));+# else // defined(ASIO_NO_DEPRECATED)+ template <typename T>+ ASIO_STATIC_CONSTEXPR(bool,+ is_applicable_property_v = (+ is_executor<T>::value+ || conditional<+ is_executor<T>::value,+ false_type,+ is_sender<T>+ >::type::value+ || conditional<+ is_executor<T>::value,+ false_type,+ is_scheduler<T>+ >::type::value+ ));+# endif // defined(ASIO_NO_DEPRECATED) #endif // defined(ASIO_HAS_VARIABLE_TEMPLATES) ASIO_STATIC_CONSTEXPR(bool, is_requirable = false);@@ -242,16 +261,74 @@ { } + template <typename T>+ struct proxy+ {+#if defined(ASIO_HAS_DEDUCED_QUERY_MEMBER_TRAIT)+ struct type+ {+ template <typename P>+ auto query(ASIO_MOVE_ARG(P) p) const+ noexcept(+ noexcept(+ declval<typename conditional<true, T, P>::type>().query(+ ASIO_MOVE_CAST(P)(p))+ )+ )+ -> decltype(+ declval<typename conditional<true, T, P>::type>().query(+ ASIO_MOVE_CAST(P)(p))+ );+ };+#else // defined(ASIO_HAS_DEDUCED_QUERY_MEMBER_TRAIT)+ typedef T type;+#endif // defined(ASIO_HAS_DEDUCED_QUERY_MEMBER_TRAIT)+ };++ template <typename T>+ struct static_proxy+ {+#if defined(ASIO_HAS_DEDUCED_QUERY_STATIC_CONSTEXPR_MEMBER_TRAIT)+ struct type+ {+ template <typename P>+ static constexpr auto query(ASIO_MOVE_ARG(P) p)+ noexcept(+ noexcept(+ conditional<true, T, P>::type::query(ASIO_MOVE_CAST(P)(p))+ )+ )+ -> decltype(+ conditional<true, T, P>::type::query(ASIO_MOVE_CAST(P)(p))+ )+ {+ return T::query(ASIO_MOVE_CAST(P)(p));+ }+ };+#else // defined(ASIO_HAS_DEDUCED_QUERY_STATIC_CONSTEXPR_MEMBER_TRAIT)+ typedef T type;+#endif // defined(ASIO_HAS_DEDUCED_QUERY_STATIC_CONSTEXPR_MEMBER_TRAIT)+ };++ template <typename T>+ struct query_member :+ traits::query_member<typename proxy<T>::type, blocking_t> {};++ template <typename T>+ struct query_static_constexpr_member :+ traits::query_static_constexpr_member<+ typename static_proxy<T>::type, blocking_t> {};+ #if defined(ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT) \ && defined(ASIO_HAS_SFINAE_VARIABLE_TEMPLATES) template <typename T> static ASIO_CONSTEXPR- typename traits::query_static_constexpr_member<T, blocking_t>::result_type+ typename query_static_constexpr_member<T>::result_type static_query() ASIO_NOEXCEPT_IF((- traits::query_static_constexpr_member<T, blocking_t>::is_noexcept))+ query_static_constexpr_member<T>::is_noexcept)) {- return traits::query_static_constexpr_member<T, blocking_t>::value();+ return query_static_constexpr_member<T>::value(); } template <typename T>@@ -259,9 +336,13 @@ typename traits::static_query<T, possibly_t>::result_type static_query( typename enable_if<- !traits::query_static_constexpr_member<T, blocking_t>::is_valid- && !traits::query_member<T, blocking_t>::is_valid- && traits::static_query<T, possibly_t>::is_valid+ !query_static_constexpr_member<T>::is_valid+ >::type* = 0,+ typename enable_if<+ !query_member<T>::is_valid+ >::type* = 0,+ typename enable_if<+ traits::static_query<T, possibly_t>::is_valid >::type* = 0) ASIO_NOEXCEPT { return traits::static_query<T, possibly_t>::value();@@ -272,10 +353,16 @@ typename traits::static_query<T, always_t>::result_type static_query( typename enable_if<- !traits::query_static_constexpr_member<T, blocking_t>::is_valid- && !traits::query_member<T, blocking_t>::is_valid- && !traits::static_query<T, possibly_t>::is_valid- && traits::static_query<T, always_t>::is_valid+ !query_static_constexpr_member<T>::is_valid+ >::type* = 0,+ typename enable_if<+ !query_member<T>::is_valid+ >::type* = 0,+ typename enable_if<+ !traits::static_query<T, possibly_t>::is_valid+ >::type* = 0,+ typename enable_if<+ traits::static_query<T, always_t>::is_valid >::type* = 0) ASIO_NOEXCEPT { return traits::static_query<T, always_t>::value();@@ -286,11 +373,19 @@ typename traits::static_query<T, never_t>::result_type static_query( typename enable_if<- !traits::query_static_constexpr_member<T, blocking_t>::is_valid- && !traits::query_member<T, blocking_t>::is_valid- && !traits::static_query<T, possibly_t>::is_valid- && !traits::static_query<T, always_t>::is_valid- && traits::static_query<T, never_t>::is_valid+ !query_static_constexpr_member<T>::is_valid+ >::type* = 0,+ typename enable_if<+ !query_member<T>::is_valid+ >::type* = 0,+ typename enable_if<+ !traits::static_query<T, possibly_t>::is_valid+ >::type* = 0,+ typename enable_if<+ !traits::static_query<T, always_t>::is_valid+ >::type* = 0,+ typename enable_if<+ traits::static_query<T, never_t>::is_valid >::type* = 0) ASIO_NOEXCEPT { return traits::static_query<T, never_t>::value();@@ -343,7 +438,9 @@ const Executor& ex, convertible_from_blocking_t, typename enable_if< !can_query<const Executor&, possibly_t>::value- && can_query<const Executor&, always_t>::value+ >::type* = 0,+ typename enable_if<+ can_query<const Executor&, always_t>::value >::type* = 0) #if !defined(__clang__) // Clang crashes if noexcept is used here. #if defined(ASIO_MSVC) // Visual C++ wants the type to be qualified.@@ -363,8 +460,12 @@ const Executor& ex, convertible_from_blocking_t, typename enable_if< !can_query<const Executor&, possibly_t>::value- && !can_query<const Executor&, always_t>::value- && can_query<const Executor&, never_t>::value+ >::type* = 0,+ typename enable_if<+ !can_query<const Executor&, always_t>::value+ >::type* = 0,+ typename enable_if<+ can_query<const Executor&, never_t>::value >::type* = 0) #if !defined(__clang__) // Clang crashes if noexcept is used here. #if defined(ASIO_MSVC) // Visual C++ wants the type to be qualified.@@ -418,10 +519,28 @@ struct possibly_t { #if defined(ASIO_HAS_VARIABLE_TEMPLATES)+# if defined(ASIO_NO_DEPRECATED) template <typename T> ASIO_STATIC_CONSTEXPR(bool,- is_applicable_property_v = is_executor<T>::value- || is_sender<T>::value || is_scheduler<T>::value);+ is_applicable_property_v = (+ is_executor<T>::value));+# else // defined(ASIO_NO_DEPRECATED)+ template <typename T>+ ASIO_STATIC_CONSTEXPR(bool,+ is_applicable_property_v = (+ is_executor<T>::value+ || conditional<+ is_executor<T>::value,+ false_type,+ is_sender<T>+ >::type::value+ || conditional<+ is_executor<T>::value,+ false_type,+ is_scheduler<T>+ >::type::value+ ));+# endif // defined(ASIO_NO_DEPRECATED) #endif // defined(ASIO_HAS_VARIABLE_TEMPLATES) ASIO_STATIC_CONSTEXPR(bool, is_requirable = true);@@ -432,26 +551,44 @@ { } + template <typename T>+ struct query_member :+ traits::query_member<+ typename blocking_t<I>::template proxy<T>::type, possibly_t> {};++ template <typename T>+ struct query_static_constexpr_member :+ traits::query_static_constexpr_member<+ typename blocking_t<I>::template static_proxy<T>::type, possibly_t> {};+ #if defined(ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT) \ && defined(ASIO_HAS_SFINAE_VARIABLE_TEMPLATES) template <typename T> static ASIO_CONSTEXPR- typename traits::query_static_constexpr_member<T, possibly_t>::result_type+ typename query_static_constexpr_member<T>::result_type static_query() ASIO_NOEXCEPT_IF((- traits::query_static_constexpr_member<T, possibly_t>::is_noexcept))+ query_static_constexpr_member<T>::is_noexcept)) {- return traits::query_static_constexpr_member<T, possibly_t>::value();+ return query_static_constexpr_member<T>::value(); } template <typename T> static ASIO_CONSTEXPR possibly_t static_query( typename enable_if<- !traits::query_static_constexpr_member<T, possibly_t>::is_valid- && !traits::query_member<T, possibly_t>::is_valid- && !traits::query_free<T, possibly_t>::is_valid- && !can_query<T, always_t<I> >::value- && !can_query<T, never_t<I> >::value+ !query_static_constexpr_member<T>::is_valid+ >::type* = 0,+ typename enable_if<+ !query_member<T>::is_valid+ >::type* = 0,+ typename enable_if<+ !traits::query_free<T, possibly_t>::is_valid+ >::type* = 0,+ typename enable_if<+ !can_query<T, always_t<I> >::value+ >::type* = 0,+ typename enable_if<+ !can_query<T, never_t<I> >::value >::type* = 0) ASIO_NOEXCEPT { return possibly_t();@@ -622,7 +759,11 @@ template <typename Function> typename enable_if<+#if defined(ASIO_NO_DEPRECATED)+ traits::execute_member<const Executor&, Function>::is_valid+#else // defined(ASIO_NO_DEPRECATED) execution::can_execute<const Executor&, Function>::value+#endif // defined(ASIO_NO_DEPRECATED) >::type execute(ASIO_MOVE_ARG(Function) f) const { blocking_adaptation::blocking_execute(@@ -647,10 +788,28 @@ struct always_t { #if defined(ASIO_HAS_VARIABLE_TEMPLATES)+# if defined(ASIO_NO_DEPRECATED) template <typename T> ASIO_STATIC_CONSTEXPR(bool,- is_applicable_property_v = is_executor<T>::value- || is_sender<T>::value || is_scheduler<T>::value);+ is_applicable_property_v = (+ is_executor<T>::value));+# else // defined(ASIO_NO_DEPRECATED)+ template <typename T>+ ASIO_STATIC_CONSTEXPR(bool,+ is_applicable_property_v = (+ is_executor<T>::value+ || conditional<+ is_executor<T>::value,+ false_type,+ is_sender<T>+ >::type::value+ || conditional<+ is_executor<T>::value,+ false_type,+ is_scheduler<T>+ >::type::value+ ));+# endif // defined(ASIO_NO_DEPRECATED) #endif // defined(ASIO_HAS_VARIABLE_TEMPLATES) ASIO_STATIC_CONSTEXPR(bool, is_requirable = true);@@ -661,16 +820,26 @@ { } + template <typename T>+ struct query_member :+ traits::query_member<+ typename blocking_t<I>::template proxy<T>::type, always_t> {};++ template <typename T>+ struct query_static_constexpr_member :+ traits::query_static_constexpr_member<+ typename blocking_t<I>::template static_proxy<T>::type, always_t> {};+ #if defined(ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT) \ && defined(ASIO_HAS_SFINAE_VARIABLE_TEMPLATES) template <typename T> static ASIO_CONSTEXPR- typename traits::query_static_constexpr_member<T, always_t>::result_type+ typename query_static_constexpr_member<T>::result_type static_query() ASIO_NOEXCEPT_IF((- traits::query_static_constexpr_member<T, always_t>::is_noexcept))+ query_static_constexpr_member<T>::is_noexcept)) {- return traits::query_static_constexpr_member<T, always_t>::value();+ return query_static_constexpr_member<T>::value(); } template <typename E, typename T = decltype(always_t::static_query<E>())>@@ -725,7 +894,9 @@ const Executor& e, const always_t&, typename enable_if< is_executor<Executor>::value- && traits::static_require<+ >::type* = 0,+ typename enable_if<+ traits::static_require< const Executor&, blocking_adaptation::allowed_t<0> >::is_valid@@ -746,10 +917,28 @@ struct never_t { #if defined(ASIO_HAS_VARIABLE_TEMPLATES)+# if defined(ASIO_NO_DEPRECATED) template <typename T> ASIO_STATIC_CONSTEXPR(bool,- is_applicable_property_v = is_executor<T>::value- || is_sender<T>::value || is_scheduler<T>::value);+ is_applicable_property_v = (+ is_executor<T>::value));+# else // defined(ASIO_NO_DEPRECATED)+ template <typename T>+ ASIO_STATIC_CONSTEXPR(bool,+ is_applicable_property_v = (+ is_executor<T>::value+ || conditional<+ is_executor<T>::value,+ false_type,+ is_sender<T>+ >::type::value+ || conditional<+ is_executor<T>::value,+ false_type,+ is_scheduler<T>+ >::type::value+ ));+# endif // defined(ASIO_NO_DEPRECATED) #endif // defined(ASIO_HAS_VARIABLE_TEMPLATES) ASIO_STATIC_CONSTEXPR(bool, is_requirable = true);@@ -760,16 +949,26 @@ { } + template <typename T>+ struct query_member :+ traits::query_member<+ typename blocking_t<I>::template proxy<T>::type, never_t> {};++ template <typename T>+ struct query_static_constexpr_member :+ traits::query_static_constexpr_member<+ typename blocking_t<I>::template static_proxy<T>::type, never_t> {};+ #if defined(ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT) \ && defined(ASIO_HAS_SFINAE_VARIABLE_TEMPLATES) template <typename T> static ASIO_CONSTEXPR- typename traits::query_static_constexpr_member<T, never_t>::result_type+ typename query_static_constexpr_member<T>::result_type static_query() ASIO_NOEXCEPT_IF((- traits::query_static_constexpr_member<T, never_t>::is_noexcept))+ query_static_constexpr_member<T>::is_noexcept)) {- return traits::query_static_constexpr_member<T, never_t>::value();+ return query_static_constexpr_member<T>::value(); } template <typename E, typename T = decltype(never_t::static_query<E>())>@@ -845,8 +1044,19 @@ struct is_applicable_property<T, execution::blocking_t> : integral_constant<bool, execution::is_executor<T>::value- || execution::is_sender<T>::value- || execution::is_scheduler<T>::value>+#if !defined(ASIO_NO_DEPRECATED)+ || conditional<+ execution::is_executor<T>::value,+ false_type,+ execution::is_sender<T>+ >::type::value+ || conditional<+ execution::is_executor<T>::value,+ false_type,+ execution::is_scheduler<T>+ >::type::value+#endif // !defined(ASIO_NO_DEPRECATED)+ > { }; @@ -854,8 +1064,19 @@ struct is_applicable_property<T, execution::blocking_t::possibly_t> : integral_constant<bool, execution::is_executor<T>::value- || execution::is_sender<T>::value- || execution::is_scheduler<T>::value>+#if !defined(ASIO_NO_DEPRECATED)+ || conditional<+ execution::is_executor<T>::value,+ false_type,+ execution::is_sender<T>+ >::type::value+ || conditional<+ execution::is_executor<T>::value,+ false_type,+ execution::is_scheduler<T>+ >::type::value+#endif // !defined(ASIO_NO_DEPRECATED)+ > { }; @@ -863,8 +1084,19 @@ struct is_applicable_property<T, execution::blocking_t::always_t> : integral_constant<bool, execution::is_executor<T>::value- || execution::is_sender<T>::value- || execution::is_scheduler<T>::value>+#if !defined(ASIO_NO_DEPRECATED)+ || conditional<+ execution::is_executor<T>::value,+ false_type,+ execution::is_sender<T>+ >::type::value+ || conditional<+ execution::is_executor<T>::value,+ false_type,+ execution::is_scheduler<T>+ >::type::value+#endif // !defined(ASIO_NO_DEPRECATED)+ > { }; @@ -872,8 +1104,19 @@ struct is_applicable_property<T, execution::blocking_t::never_t> : integral_constant<bool, execution::is_executor<T>::value- || execution::is_sender<T>::value- || execution::is_scheduler<T>::value>+#if !defined(ASIO_NO_DEPRECATED)+ || conditional<+ execution::is_executor<T>::value,+ false_type,+ execution::is_sender<T>+ >::type::value+ || conditional<+ execution::is_executor<T>::value,+ false_type,+ execution::is_scheduler<T>+ >::type::value+#endif // !defined(ASIO_NO_DEPRECATED)+ > { }; @@ -933,28 +1176,29 @@ template <typename T> struct static_query<T, execution::blocking_t, typename enable_if<- traits::query_static_constexpr_member<T,- execution::blocking_t>::is_valid+ execution::detail::blocking_t<0>::+ query_static_constexpr_member<T>::is_valid >::type> { ASIO_STATIC_CONSTEXPR(bool, is_valid = true); ASIO_STATIC_CONSTEXPR(bool, is_noexcept = true); - typedef typename traits::query_static_constexpr_member<T,- execution::blocking_t>::result_type result_type;+ typedef typename execution::detail::blocking_t<0>::+ query_static_constexpr_member<T>::result_type result_type; static ASIO_CONSTEXPR result_type value() {- return traits::query_static_constexpr_member<T,- execution::blocking_t>::value();+ return execution::blocking_t::query_static_constexpr_member<T>::value(); } }; template <typename T> struct static_query<T, execution::blocking_t, typename enable_if<- !traits::query_static_constexpr_member<T, execution::blocking_t>::is_valid- && !traits::query_member<T, execution::blocking_t>::is_valid+ !execution::detail::blocking_t<0>::+ query_static_constexpr_member<T>::is_valid+ && !execution::detail::blocking_t<0>::+ query_member<T>::is_valid && traits::static_query<T, execution::blocking_t::possibly_t>::is_valid >::type> {@@ -973,8 +1217,10 @@ template <typename T> struct static_query<T, execution::blocking_t, typename enable_if<- !traits::query_static_constexpr_member<T, execution::blocking_t>::is_valid- && !traits::query_member<T, execution::blocking_t>::is_valid+ !execution::detail::blocking_t<0>::+ query_static_constexpr_member<T>::is_valid+ && !execution::detail::blocking_t<0>::+ query_member<T>::is_valid && !traits::static_query<T, execution::blocking_t::possibly_t>::is_valid && traits::static_query<T, execution::blocking_t::always_t>::is_valid >::type>@@ -994,8 +1240,10 @@ template <typename T> struct static_query<T, execution::blocking_t, typename enable_if<- !traits::query_static_constexpr_member<T, execution::blocking_t>::is_valid- && !traits::query_member<T, execution::blocking_t>::is_valid+ !execution::detail::blocking_t<0>::+ query_static_constexpr_member<T>::is_valid+ && !execution::detail::blocking_t<0>::+ query_member<T>::is_valid && !traits::static_query<T, execution::blocking_t::possibly_t>::is_valid && !traits::static_query<T, execution::blocking_t::always_t>::is_valid && traits::static_query<T, execution::blocking_t::never_t>::is_valid@@ -1016,29 +1264,30 @@ template <typename T> struct static_query<T, execution::blocking_t::possibly_t, typename enable_if<- traits::query_static_constexpr_member<T,- execution::blocking_t::possibly_t>::is_valid+ execution::detail::blocking::possibly_t<0>::+ query_static_constexpr_member<T>::is_valid >::type> { ASIO_STATIC_CONSTEXPR(bool, is_valid = true); ASIO_STATIC_CONSTEXPR(bool, is_noexcept = true); - typedef typename traits::query_static_constexpr_member<T,- execution::blocking_t::possibly_t>::result_type result_type;+ typedef typename execution::detail::blocking::possibly_t<0>::+ query_static_constexpr_member<T>::result_type result_type; static ASIO_CONSTEXPR result_type value() {- return traits::query_static_constexpr_member<T,- execution::blocking_t::possibly_t>::value();+ return execution::detail::blocking::possibly_t<0>::+ query_static_constexpr_member<T>::value(); } }; template <typename T> struct static_query<T, execution::blocking_t::possibly_t, typename enable_if<- !traits::query_static_constexpr_member<T,- execution::blocking_t::possibly_t>::is_valid- && !traits::query_member<T, execution::blocking_t::possibly_t>::is_valid+ !execution::detail::blocking::possibly_t<0>::+ query_static_constexpr_member<T>::is_valid+ && !execution::detail::blocking::possibly_t<0>::+ query_member<T>::is_valid && !traits::query_free<T, execution::blocking_t::possibly_t>::is_valid && !can_query<T, execution::blocking_t::always_t>::value && !can_query<T, execution::blocking_t::never_t>::value@@ -1058,40 +1307,40 @@ template <typename T> struct static_query<T, execution::blocking_t::always_t, typename enable_if<- traits::query_static_constexpr_member<T,- execution::blocking_t::always_t>::is_valid+ execution::detail::blocking::always_t<0>::+ query_static_constexpr_member<T>::is_valid >::type> { ASIO_STATIC_CONSTEXPR(bool, is_valid = true); ASIO_STATIC_CONSTEXPR(bool, is_noexcept = true); - typedef typename traits::query_static_constexpr_member<T,- execution::blocking_t::always_t>::result_type result_type;+ typedef typename execution::detail::blocking::always_t<0>::+ query_static_constexpr_member<T>::result_type result_type; static ASIO_CONSTEXPR result_type value() {- return traits::query_static_constexpr_member<T,- execution::blocking_t::always_t>::value();+ return execution::detail::blocking::always_t<0>::+ query_static_constexpr_member<T>::value(); } }; template <typename T> struct static_query<T, execution::blocking_t::never_t, typename enable_if<- traits::query_static_constexpr_member<T,- execution::blocking_t::never_t>::is_valid+ execution::detail::blocking::never_t<0>::+ query_static_constexpr_member<T>::is_valid >::type> { ASIO_STATIC_CONSTEXPR(bool, is_valid = true); ASIO_STATIC_CONSTEXPR(bool, is_noexcept = true); - typedef typename traits::query_static_constexpr_member<T,- execution::blocking_t::never_t>::result_type result_type;+ typedef typename execution::detail::blocking::never_t<0>::+ query_static_constexpr_member<T>::result_type result_type; static ASIO_CONSTEXPR result_type value() {- return traits::query_static_constexpr_member<T,- execution::blocking_t::never_t>::value();+ return execution::detail::blocking::never_t<0>::+ query_static_constexpr_member<T>::value(); } };
link/modules/asio-standalone/asio/include/asio/execution/blocking_adaptation.hpp view
@@ -2,7 +2,7 @@ // execution/blocking_adaptation.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -164,10 +164,28 @@ struct blocking_adaptation_t { #if defined(ASIO_HAS_VARIABLE_TEMPLATES)+# if defined(ASIO_NO_DEPRECATED) template <typename T> ASIO_STATIC_CONSTEXPR(bool,- is_applicable_property_v = is_executor<T>::value- || is_sender<T>::value || is_scheduler<T>::value);+ is_applicable_property_v = (+ is_executor<T>::value));+# else // defined(ASIO_NO_DEPRECATED)+ template <typename T>+ ASIO_STATIC_CONSTEXPR(bool,+ is_applicable_property_v = (+ is_executor<T>::value+ || conditional<+ is_executor<T>::value,+ false_type,+ is_sender<T>+ >::type::value+ || conditional<+ is_executor<T>::value,+ false_type,+ is_scheduler<T>+ >::type::value+ ));+# endif // defined(ASIO_NO_DEPRECATED) #endif // defined(ASIO_HAS_VARIABLE_TEMPLATES) ASIO_STATIC_CONSTEXPR(bool, is_requirable = false);@@ -192,20 +210,74 @@ { } + template <typename T>+ struct proxy+ {+#if defined(ASIO_HAS_DEDUCED_QUERY_MEMBER_TRAIT)+ struct type+ {+ template <typename P>+ auto query(ASIO_MOVE_ARG(P) p) const+ noexcept(+ noexcept(+ declval<typename conditional<true, T, P>::type>().query(+ ASIO_MOVE_CAST(P)(p))+ )+ )+ -> decltype(+ declval<typename conditional<true, T, P>::type>().query(+ ASIO_MOVE_CAST(P)(p))+ );+ };+#else // defined(ASIO_HAS_DEDUCED_QUERY_MEMBER_TRAIT)+ typedef T type;+#endif // defined(ASIO_HAS_DEDUCED_QUERY_MEMBER_TRAIT)+ };++ template <typename T>+ struct static_proxy+ {+#if defined(ASIO_HAS_DEDUCED_QUERY_STATIC_CONSTEXPR_MEMBER_TRAIT)+ struct type+ {+ template <typename P>+ static constexpr auto query(ASIO_MOVE_ARG(P) p)+ noexcept(+ noexcept(+ conditional<true, T, P>::type::query(ASIO_MOVE_CAST(P)(p))+ )+ )+ -> decltype(+ conditional<true, T, P>::type::query(ASIO_MOVE_CAST(P)(p))+ )+ {+ return T::query(ASIO_MOVE_CAST(P)(p));+ }+ };+#else // defined(ASIO_HAS_DEDUCED_QUERY_STATIC_CONSTEXPR_MEMBER_TRAIT)+ typedef T type;+#endif // defined(ASIO_HAS_DEDUCED_QUERY_STATIC_CONSTEXPR_MEMBER_TRAIT)+ };++ template <typename T>+ struct query_member :+ traits::query_member<typename proxy<T>::type, blocking_adaptation_t> {};++ template <typename T>+ struct query_static_constexpr_member :+ traits::query_static_constexpr_member<+ typename static_proxy<T>::type, blocking_adaptation_t> {};+ #if defined(ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT) \ && defined(ASIO_HAS_SFINAE_VARIABLE_TEMPLATES) template <typename T> static ASIO_CONSTEXPR- typename traits::query_static_constexpr_member<- T, blocking_adaptation_t>::result_type+ typename query_static_constexpr_member<T>::result_type static_query() ASIO_NOEXCEPT_IF((- traits::query_static_constexpr_member<- T, blocking_adaptation_t- >::is_noexcept))+ query_static_constexpr_member<T>::is_noexcept)) {- return traits::query_static_constexpr_member<- T, blocking_adaptation_t>::value();+ return query_static_constexpr_member<T>::value(); } template <typename T>@@ -213,10 +285,13 @@ typename traits::static_query<T, disallowed_t>::result_type static_query( typename enable_if<- !traits::query_static_constexpr_member<- T, blocking_adaptation_t>::is_valid- && !traits::query_member<T, blocking_adaptation_t>::is_valid- && traits::static_query<T, disallowed_t>::is_valid+ !query_static_constexpr_member<T>::is_valid+ >::type* = 0,+ typename enable_if<+ !query_member<T>::is_valid+ >::type* = 0,+ typename enable_if<+ traits::static_query<T, disallowed_t>::is_valid >::type* = 0) ASIO_NOEXCEPT { return traits::static_query<T, disallowed_t>::value();@@ -227,11 +302,16 @@ typename traits::static_query<T, allowed_t>::result_type static_query( typename enable_if<- !traits::query_static_constexpr_member<- T, blocking_adaptation_t>::is_valid- && !traits::query_member<T, blocking_adaptation_t>::is_valid- && !traits::static_query<T, disallowed_t>::is_valid- && traits::static_query<T, allowed_t>::is_valid+ !query_static_constexpr_member<T>::is_valid+ >::type* = 0,+ typename enable_if<+ !query_member<T>::is_valid+ >::type* = 0,+ typename enable_if<+ !traits::static_query<T, disallowed_t>::is_valid+ >::type* = 0,+ typename enable_if<+ traits::static_query<T, allowed_t>::is_valid >::type* = 0) ASIO_NOEXCEPT { return traits::static_query<T, allowed_t>::value();@@ -289,7 +369,9 @@ const Executor& ex, convertible_from_blocking_adaptation_t, typename enable_if< !can_query<const Executor&, disallowed_t>::value- && can_query<const Executor&, allowed_t>::value+ >::type* = 0,+ typename enable_if<+ can_query<const Executor&, allowed_t>::value >::type* = 0) #if !defined(__clang__) // Clang crashes if noexcept is used here. #if defined(ASIO_MSVC) // Visual C++ wants the type to be qualified.@@ -342,10 +424,28 @@ struct disallowed_t { #if defined(ASIO_HAS_VARIABLE_TEMPLATES)+# if defined(ASIO_NO_DEPRECATED) template <typename T> ASIO_STATIC_CONSTEXPR(bool,- is_applicable_property_v = is_executor<T>::value- || is_sender<T>::value || is_scheduler<T>::value);+ is_applicable_property_v = (+ is_executor<T>::value));+# else // defined(ASIO_NO_DEPRECATED)+ template <typename T>+ ASIO_STATIC_CONSTEXPR(bool,+ is_applicable_property_v = (+ is_executor<T>::value+ || conditional<+ is_executor<T>::value,+ false_type,+ is_sender<T>+ >::type::value+ || conditional<+ is_executor<T>::value,+ false_type,+ is_scheduler<T>+ >::type::value+ ));+# endif // defined(ASIO_NO_DEPRECATED) #endif // defined(ASIO_HAS_VARIABLE_TEMPLATES) ASIO_STATIC_CONSTEXPR(bool, is_requirable = true);@@ -356,25 +456,43 @@ { } + template <typename T>+ struct query_member :+ traits::query_member<+ typename blocking_adaptation_t<I>::template proxy<T>::type,+ disallowed_t> {};++ template <typename T>+ struct query_static_constexpr_member :+ traits::query_static_constexpr_member<+ typename blocking_adaptation_t<I>::template static_proxy<T>::type,+ disallowed_t> {};+ #if defined(ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT) \ && defined(ASIO_HAS_SFINAE_VARIABLE_TEMPLATES) template <typename T> static ASIO_CONSTEXPR- typename traits::query_static_constexpr_member<T, disallowed_t>::result_type+ typename query_static_constexpr_member<T>::result_type static_query() ASIO_NOEXCEPT_IF((- traits::query_static_constexpr_member<T, disallowed_t>::is_noexcept))+ query_static_constexpr_member<T>::is_noexcept)) {- return traits::query_static_constexpr_member<T, disallowed_t>::value();+ return query_static_constexpr_member<T>::value(); } template <typename T> static ASIO_CONSTEXPR disallowed_t static_query( typename enable_if<- !traits::query_static_constexpr_member<T, disallowed_t>::is_valid- && !traits::query_member<T, disallowed_t>::is_valid- && !traits::query_free<T, disallowed_t>::is_valid- && !can_query<T, allowed_t<I> >::value+ !query_static_constexpr_member<T>::is_valid+ >::type* = 0,+ typename enable_if<+ !query_member<T>::is_valid+ >::type* = 0,+ typename enable_if<+ !traits::query_free<T, disallowed_t>::is_valid+ >::type* = 0,+ typename enable_if<+ !can_query<T, allowed_t<I> >::value >::type* = 0) ASIO_NOEXCEPT { return disallowed_t();@@ -502,10 +620,18 @@ template <typename Function> typename enable_if<+#if defined(ASIO_NO_DEPRECATED)+ traits::execute_member<const Executor&, Function>::is_valid+#else // defined(ASIO_NO_DEPRECATED) execution::can_execute<const Executor&, Function>::value+#endif // defined(ASIO_NO_DEPRECATED) >::type execute(ASIO_MOVE_ARG(Function) f) const {+#if defined(ASIO_NO_DEPRECATED)+ executor_.execute(ASIO_MOVE_CAST(Function)(f));+#else // defined(ASIO_NO_DEPRECATED) execution::execute(executor_, ASIO_MOVE_CAST(Function)(f));+#endif // defined(ASIO_NO_DEPRECATED) } friend bool operator==(const adapter& a, const adapter& b) ASIO_NOEXCEPT@@ -526,10 +652,28 @@ struct allowed_t { #if defined(ASIO_HAS_VARIABLE_TEMPLATES)+# if defined(ASIO_NO_DEPRECATED) template <typename T> ASIO_STATIC_CONSTEXPR(bool,- is_applicable_property_v = is_executor<T>::value- || is_sender<T>::value || is_scheduler<T>::value);+ is_applicable_property_v = (+ is_executor<T>::value));+# else // defined(ASIO_NO_DEPRECATED)+ template <typename T>+ ASIO_STATIC_CONSTEXPR(bool,+ is_applicable_property_v = (+ is_executor<T>::value+ || conditional<+ is_executor<T>::value,+ false_type,+ is_sender<T>+ >::type::value+ || conditional<+ is_executor<T>::value,+ false_type,+ is_scheduler<T>+ >::type::value+ ));+# endif // defined(ASIO_NO_DEPRECATED) #endif // defined(ASIO_HAS_VARIABLE_TEMPLATES) ASIO_STATIC_CONSTEXPR(bool, is_requirable = true);@@ -540,16 +684,28 @@ { } + template <typename T>+ struct query_member :+ traits::query_member<+ typename blocking_adaptation_t<I>::template proxy<T>::type,+ allowed_t> {};++ template <typename T>+ struct query_static_constexpr_member :+ traits::query_static_constexpr_member<+ typename blocking_adaptation_t<I>::template static_proxy<T>::type,+ allowed_t> {};+ #if defined(ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT) \ && defined(ASIO_HAS_SFINAE_VARIABLE_TEMPLATES) template <typename T> static ASIO_CONSTEXPR- typename traits::query_static_constexpr_member<T, allowed_t>::result_type+ typename query_static_constexpr_member<T>::result_type static_query() ASIO_NOEXCEPT_IF((- traits::query_static_constexpr_member<T, allowed_t>::is_noexcept))+ query_static_constexpr_member<T>::is_noexcept)) {- return traits::query_static_constexpr_member<T, allowed_t>::value();+ return query_static_constexpr_member<T>::value(); } template <typename E, typename T = decltype(allowed_t::static_query<E>())>@@ -608,7 +764,11 @@ void execute_and_wait(ASIO_MOVE_ARG(Executor) ex) { handler h = { this };+#if defined(ASIO_NO_DEPRECATED)+ ex.execute(h);+#else // defined(ASIO_NO_DEPRECATED) execution::execute(ASIO_MOVE_CAST(Executor)(ex), h);+#endif // defined(ASIO_NO_DEPRECATED) asio::detail::mutex::scoped_lock lock(mutex_); while (!is_complete_) event_.wait(lock);@@ -673,8 +833,19 @@ struct is_applicable_property<T, execution::blocking_adaptation_t> : integral_constant<bool, execution::is_executor<T>::value- || execution::is_sender<T>::value- || execution::is_scheduler<T>::value>+#if !defined(ASIO_NO_DEPRECATED)+ || conditional<+ execution::is_executor<T>::value,+ false_type,+ execution::is_sender<T>+ >::type::value+ || conditional<+ execution::is_executor<T>::value,+ false_type,+ execution::is_scheduler<T>+ >::type::value+#endif // !defined(ASIO_NO_DEPRECATED)+ > { }; @@ -682,8 +853,19 @@ struct is_applicable_property<T, execution::blocking_adaptation_t::disallowed_t> : integral_constant<bool, execution::is_executor<T>::value- || execution::is_sender<T>::value- || execution::is_scheduler<T>::value>+#if !defined(ASIO_NO_DEPRECATED)+ || conditional<+ execution::is_executor<T>::value,+ false_type,+ execution::is_sender<T>+ >::type::value+ || conditional<+ execution::is_executor<T>::value,+ false_type,+ execution::is_scheduler<T>+ >::type::value+#endif // !defined(ASIO_NO_DEPRECATED)+ > { }; @@ -691,8 +873,19 @@ struct is_applicable_property<T, execution::blocking_adaptation_t::allowed_t> : integral_constant<bool, execution::is_executor<T>::value- || execution::is_sender<T>::value- || execution::is_scheduler<T>::value>+#if !defined(ASIO_NO_DEPRECATED)+ || conditional<+ execution::is_executor<T>::value,+ false_type,+ execution::is_sender<T>+ >::type::value+ || conditional<+ execution::is_executor<T>::value,+ false_type,+ execution::is_scheduler<T>+ >::type::value+#endif // !defined(ASIO_NO_DEPRECATED)+ > { }; @@ -737,30 +930,30 @@ template <typename T> struct static_query<T, execution::blocking_adaptation_t, typename enable_if<- traits::query_static_constexpr_member<T,- execution::blocking_adaptation_t>::is_valid+ execution::detail::blocking_adaptation_t<0>::+ query_static_constexpr_member<T>::is_valid >::type> { ASIO_STATIC_CONSTEXPR(bool, is_valid = true); ASIO_STATIC_CONSTEXPR(bool, is_noexcept = true); - typedef typename traits::query_static_constexpr_member<T,- execution::blocking_adaptation_t>::result_type result_type;+ typedef typename execution::detail::blocking_adaptation_t<0>::+ query_static_constexpr_member<T>::result_type result_type; static ASIO_CONSTEXPR result_type value() {- return traits::query_static_constexpr_member<T,- execution::blocking_adaptation_t>::value();+ return execution::detail::blocking_adaptation_t<0>::+ query_static_constexpr_member<T>::value(); } }; template <typename T> struct static_query<T, execution::blocking_adaptation_t, typename enable_if<- !traits::query_static_constexpr_member<T,- execution::blocking_adaptation_t>::is_valid- && !traits::query_member<T,- execution::blocking_adaptation_t>::is_valid+ !execution::detail::blocking_adaptation_t<0>::+ query_static_constexpr_member<T>::is_valid+ && !execution::detail::blocking_adaptation_t<0>::+ query_member<T>::is_valid && traits::static_query<T, execution::blocking_adaptation_t::disallowed_t>::is_valid >::type>@@ -781,10 +974,10 @@ template <typename T> struct static_query<T, execution::blocking_adaptation_t, typename enable_if<- !traits::query_static_constexpr_member<T,- execution::blocking_adaptation_t>::is_valid- && !traits::query_member<T,- execution::blocking_adaptation_t>::is_valid+ !execution::detail::blocking_adaptation_t<0>::+ query_static_constexpr_member<T>::is_valid+ && !execution::detail::blocking_adaptation_t<0>::+ query_member<T>::is_valid && !traits::static_query<T, execution::blocking_adaptation_t::disallowed_t>::is_valid && traits::static_query<T,@@ -807,30 +1000,30 @@ template <typename T> struct static_query<T, execution::blocking_adaptation_t::disallowed_t, typename enable_if<- traits::query_static_constexpr_member<T,- execution::blocking_adaptation_t::disallowed_t>::is_valid+ execution::detail::blocking_adaptation::disallowed_t<0>::+ query_static_constexpr_member<T>::is_valid >::type> { ASIO_STATIC_CONSTEXPR(bool, is_valid = true); ASIO_STATIC_CONSTEXPR(bool, is_noexcept = true); - typedef typename traits::query_static_constexpr_member<T,- execution::blocking_adaptation_t::disallowed_t>::result_type result_type;+ typedef typename execution::detail::blocking_adaptation::disallowed_t<0>::+ query_static_constexpr_member<T>::result_type result_type; static ASIO_CONSTEXPR result_type value() {- return traits::query_static_constexpr_member<T,- execution::blocking_adaptation_t::disallowed_t>::value();+ return execution::detail::blocking_adaptation::disallowed_t<0>::+ query_static_constexpr_member<T>::value(); } }; template <typename T> struct static_query<T, execution::blocking_adaptation_t::disallowed_t, typename enable_if<- !traits::query_static_constexpr_member<T,- execution::blocking_adaptation_t::disallowed_t>::is_valid- && !traits::query_member<T,- execution::blocking_adaptation_t::disallowed_t>::is_valid+ !execution::detail::blocking_adaptation::disallowed_t<0>::+ query_static_constexpr_member<T>::is_valid+ && !execution::detail::blocking_adaptation::disallowed_t<0>::+ query_member<T>::is_valid && !traits::query_free<T, execution::blocking_adaptation_t::disallowed_t>::is_valid && !can_query<T, execution::blocking_adaptation_t::allowed_t>::value@@ -850,20 +1043,20 @@ template <typename T> struct static_query<T, execution::blocking_adaptation_t::allowed_t, typename enable_if<- traits::query_static_constexpr_member<T,- execution::blocking_adaptation_t::allowed_t>::is_valid+ execution::detail::blocking_adaptation::allowed_t<0>::+ query_static_constexpr_member<T>::is_valid >::type> { ASIO_STATIC_CONSTEXPR(bool, is_valid = true); ASIO_STATIC_CONSTEXPR(bool, is_noexcept = true); - typedef typename traits::query_static_constexpr_member<T,- execution::blocking_adaptation_t::allowed_t>::result_type result_type;+ typedef typename execution::detail::blocking_adaptation::allowed_t<0>::+ query_static_constexpr_member<T>::result_type result_type; static ASIO_CONSTEXPR result_type value() {- return traits::query_static_constexpr_member<T,- execution::blocking_adaptation_t::allowed_t>::value();+ return execution::detail::blocking_adaptation::allowed_t<0>::+ query_static_constexpr_member<T>::value(); } };
link/modules/asio-standalone/asio/include/asio/execution/bulk_execute.hpp view
@@ -2,7 +2,7 @@ // execution/bulk_execute.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -16,6 +16,9 @@ #endif // defined(_MSC_VER) && (_MSC_VER >= 1200) #include "asio/detail/config.hpp"++#if !defined(ASIO_NO_DEPRECATED)+ #include "asio/detail/type_traits.hpp" #include "asio/execution/bulk_guarantee.hpp" #include "asio/execution/detail/bulk_sender.hpp"@@ -124,7 +127,8 @@ ill_formed }; -template <typename S, typename Args, typename = void>+template <typename S, typename Args, typename = void, typename = void,+ typename = void, typename = void, typename = void, typename = void> struct call_traits { ASIO_STATIC_CONSTEXPR(overload_type, overload = ill_formed);@@ -135,15 +139,15 @@ template <typename S, typename F, typename N> struct call_traits<S, void(F, N), typename enable_if<- (- is_convertible<N, std::size_t>::value- &&- bulk_execute_member<S, F, N>::is_valid- &&- is_sender<- typename bulk_execute_member<S, F, N>::result_type- >::value- )+ is_convertible<N, std::size_t>::value+ >::type,+ typename enable_if<+ bulk_execute_member<S, F, N>::is_valid+ >::type,+ typename enable_if<+ is_sender<+ typename bulk_execute_member<S, F, N>::result_type+ >::value >::type> : bulk_execute_member<S, F, N> {@@ -153,17 +157,18 @@ template <typename S, typename F, typename N> struct call_traits<S, void(F, N), typename enable_if<- (- is_convertible<N, std::size_t>::value- &&- !bulk_execute_member<S, F, N>::is_valid- &&- bulk_execute_free<S, F, N>::is_valid- &&- is_sender<- typename bulk_execute_free<S, F, N>::result_type- >::value- )+ is_convertible<N, std::size_t>::value+ >::type,+ typename enable_if<+ !bulk_execute_member<S, F, N>::is_valid+ >::type,+ typename enable_if<+ bulk_execute_free<S, F, N>::is_valid+ >::type,+ typename enable_if<+ is_sender<+ typename bulk_execute_free<S, F, N>::result_type+ >::value >::type> : bulk_execute_free<S, F, N> {@@ -173,26 +178,29 @@ template <typename S, typename F, typename N> struct call_traits<S, void(F, N), typename enable_if<- (- is_convertible<N, std::size_t>::value- &&- !bulk_execute_member<S, F, N>::is_valid- &&- !bulk_execute_free<S, F, N>::is_valid- &&- is_sender<S>::value- &&- is_same<- typename result_of<- F(typename executor_index<typename remove_cvref<S>::type>::type)- >::type,- typename result_of<- F(typename executor_index<typename remove_cvref<S>::type>::type)- >::type- >::value- &&- static_require<S, bulk_guarantee_t::unsequenced_t>::is_valid- )+ is_convertible<N, std::size_t>::value+ >::type,+ typename enable_if<+ !bulk_execute_member<S, F, N>::is_valid+ >::type,+ typename enable_if<+ !bulk_execute_free<S, F, N>::is_valid+ >::type,+ typename enable_if<+ is_sender<S>::value+ >::type,+ typename enable_if<+ is_same<+ typename result_of<+ F(typename executor_index<typename remove_cvref<S>::type>::type)+ >::type,+ typename result_of<+ F(typename executor_index<typename remove_cvref<S>::type>::type)+ >::type+ >::value+ >::type,+ typename enable_if<+ static_require<S, bulk_guarantee_t::unsequenced_t>::is_valid >::type> { ASIO_STATIC_CONSTEXPR(overload_type, overload = adapter);@@ -346,8 +354,9 @@ template <typename S, typename F, typename N> struct can_bulk_execute : integral_constant<bool,- asio_execution_bulk_execute_fn::call_traits<S, void(F, N)>::overload !=- asio_execution_bulk_execute_fn::ill_formed>+ asio_execution_bulk_execute_fn::call_traits<+ S, void(F, N)>::overload !=+ asio_execution_bulk_execute_fn::ill_formed> { }; @@ -361,7 +370,8 @@ template <typename S, typename F, typename N> struct is_nothrow_bulk_execute : integral_constant<bool,- asio_execution_bulk_execute_fn::call_traits<S, void(F, N)>::is_noexcept>+ asio_execution_bulk_execute_fn::call_traits<+ S, void(F, N)>::is_noexcept> { }; @@ -386,5 +396,7 @@ #endif // defined(GENERATING_DOCUMENTATION) #include "asio/detail/pop_options.hpp"++#endif // !defined(ASIO_NO_DEPRECATED) #endif // ASIO_EXECUTION_BULK_EXECUTE_HPP
link/modules/asio-standalone/asio/include/asio/execution/bulk_guarantee.hpp view
@@ -2,7 +2,7 @@ // execution/bulk_guarantee.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -16,6 +16,9 @@ #endif // defined(_MSC_VER) && (_MSC_VER >= 1200) #include "asio/detail/config.hpp"++#if !defined(ASIO_NO_DEPRECATED)+ #include "asio/detail/type_traits.hpp" #include "asio/execution/executor.hpp" #include "asio/execution/scheduler.hpp"@@ -196,10 +199,28 @@ struct bulk_guarantee_t { #if defined(ASIO_HAS_VARIABLE_TEMPLATES)+# if defined(ASIO_NO_DEPRECATED) template <typename T> ASIO_STATIC_CONSTEXPR(bool,- is_applicable_property_v = is_executor<T>::value- || is_sender<T>::value || is_scheduler<T>::value);+ is_applicable_property_v = (+ is_executor<T>::value));+# else // defined(ASIO_NO_DEPRECATED)+ template <typename T>+ ASIO_STATIC_CONSTEXPR(bool,+ is_applicable_property_v = (+ is_executor<T>::value+ || conditional<+ is_executor<T>::value,+ false_type,+ is_sender<T>+ >::type::value+ || conditional<+ is_executor<T>::value,+ false_type,+ is_scheduler<T>+ >::type::value+ ));+# endif // defined(ASIO_NO_DEPRECATED) #endif // defined(ASIO_HAS_VARIABLE_TEMPLATES) ASIO_STATIC_CONSTEXPR(bool, is_requirable = false);@@ -230,17 +251,74 @@ { } + template <typename T>+ struct proxy+ {+#if defined(ASIO_HAS_DEDUCED_QUERY_MEMBER_TRAIT)+ struct type+ {+ template <typename P>+ auto query(ASIO_MOVE_ARG(P) p) const+ noexcept(+ noexcept(+ declval<typename conditional<true, T, P>::type>().query(+ ASIO_MOVE_CAST(P)(p))+ )+ )+ -> decltype(+ declval<typename conditional<true, T, P>::type>().query(+ ASIO_MOVE_CAST(P)(p))+ );+ };+#else // defined(ASIO_HAS_DEDUCED_QUERY_MEMBER_TRAIT)+ typedef T type;+#endif // defined(ASIO_HAS_DEDUCED_QUERY_MEMBER_TRAIT)+ };++ template <typename T>+ struct static_proxy+ {+#if defined(ASIO_HAS_DEDUCED_QUERY_STATIC_CONSTEXPR_MEMBER_TRAIT)+ struct type+ {+ template <typename P>+ static constexpr auto query(ASIO_MOVE_ARG(P) p)+ noexcept(+ noexcept(+ conditional<true, T, P>::type::query(ASIO_MOVE_CAST(P)(p))+ )+ )+ -> decltype(+ conditional<true, T, P>::type::query(ASIO_MOVE_CAST(P)(p))+ )+ {+ return T::query(ASIO_MOVE_CAST(P)(p));+ }+ };+#else // defined(ASIO_HAS_DEDUCED_QUERY_STATIC_CONSTEXPR_MEMBER_TRAIT)+ typedef T type;+#endif // defined(ASIO_HAS_DEDUCED_QUERY_STATIC_CONSTEXPR_MEMBER_TRAIT)+ };++ template <typename T>+ struct query_member :+ traits::query_member<typename proxy<T>::type, bulk_guarantee_t> {};++ template <typename T>+ struct query_static_constexpr_member :+ traits::query_static_constexpr_member<+ typename static_proxy<T>::type, bulk_guarantee_t> {};+ #if defined(ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT) \ && defined(ASIO_HAS_SFINAE_VARIABLE_TEMPLATES) template <typename T> static ASIO_CONSTEXPR- typename traits::query_static_constexpr_member<- T, bulk_guarantee_t>::result_type+ typename query_static_constexpr_member<T>::result_type static_query() ASIO_NOEXCEPT_IF((- traits::query_static_constexpr_member<T, bulk_guarantee_t>::is_noexcept))+ query_static_constexpr_member<T>::is_noexcept)) {- return traits::query_static_constexpr_member<T, bulk_guarantee_t>::value();+ return query_static_constexpr_member<T>::value(); } template <typename T>@@ -248,9 +326,13 @@ typename traits::static_query<T, unsequenced_t>::result_type static_query( typename enable_if<- !traits::query_static_constexpr_member<T, bulk_guarantee_t>::is_valid- && !traits::query_member<T, bulk_guarantee_t>::is_valid- && traits::static_query<T, unsequenced_t>::is_valid+ !query_static_constexpr_member<T>::is_valid+ >::type* = 0,+ typename enable_if<+ !query_member<T>::is_valid+ >::type* = 0,+ typename enable_if<+ traits::static_query<T, unsequenced_t>::is_valid >::type* = 0) ASIO_NOEXCEPT { return traits::static_query<T, unsequenced_t>::value();@@ -261,10 +343,16 @@ typename traits::static_query<T, sequenced_t>::result_type static_query( typename enable_if<- !traits::query_static_constexpr_member<T, bulk_guarantee_t>::is_valid- && !traits::query_member<T, bulk_guarantee_t>::is_valid- && !traits::static_query<T, unsequenced_t>::is_valid- && traits::static_query<T, sequenced_t>::is_valid+ !query_static_constexpr_member<T>::is_valid+ >::type* = 0,+ typename enable_if<+ !query_member<T>::is_valid+ >::type* = 0,+ typename enable_if<+ !traits::static_query<T, unsequenced_t>::is_valid+ >::type* = 0,+ typename enable_if<+ traits::static_query<T, sequenced_t>::is_valid >::type* = 0) ASIO_NOEXCEPT { return traits::static_query<T, sequenced_t>::value();@@ -275,11 +363,19 @@ typename traits::static_query<T, parallel_t>::result_type static_query( typename enable_if<- !traits::query_static_constexpr_member<T, bulk_guarantee_t>::is_valid- && !traits::query_member<T, bulk_guarantee_t>::is_valid- && !traits::static_query<T, unsequenced_t>::is_valid- && !traits::static_query<T, sequenced_t>::is_valid- && traits::static_query<T, parallel_t>::is_valid+ !query_static_constexpr_member<T>::is_valid+ >::type* = 0,+ typename enable_if<+ !query_member<T>::is_valid+ >::type* = 0,+ typename enable_if<+ !traits::static_query<T, unsequenced_t>::is_valid+ >::type* = 0,+ typename enable_if<+ !traits::static_query<T, sequenced_t>::is_valid+ >::type* = 0,+ typename enable_if<+ traits::static_query<T, parallel_t>::is_valid >::type* = 0) ASIO_NOEXCEPT { return traits::static_query<T, parallel_t>::value();@@ -334,7 +430,9 @@ const Executor& ex, convertible_from_bulk_guarantee_t, typename enable_if< !can_query<const Executor&, unsequenced_t>::value- && can_query<const Executor&, sequenced_t>::value+ >::type* = 0,+ typename enable_if<+ can_query<const Executor&, sequenced_t>::value >::type* = 0) #if !defined(__clang__) // Clang crashes if noexcept is used here. #if defined(ASIO_MSVC) // Visual C++ wants the type to be qualified.@@ -355,8 +453,12 @@ const Executor& ex, convertible_from_bulk_guarantee_t, typename enable_if< !can_query<const Executor&, unsequenced_t>::value- && !can_query<const Executor&, sequenced_t>::value- && can_query<const Executor&, parallel_t>::value+ >::type* = 0,+ typename enable_if<+ !can_query<const Executor&, sequenced_t>::value+ >::type* = 0,+ typename enable_if<+ can_query<const Executor&, parallel_t>::value >::type* = 0) #if !defined(__clang__) // Clang crashes if noexcept is used here. #if defined(ASIO_MSVC) // Visual C++ wants the type to be qualified.@@ -413,10 +515,28 @@ struct unsequenced_t { #if defined(ASIO_HAS_VARIABLE_TEMPLATES)+# if defined(ASIO_NO_DEPRECATED) template <typename T> ASIO_STATIC_CONSTEXPR(bool,- is_applicable_property_v = is_executor<T>::value- || is_sender<T>::value || is_scheduler<T>::value);+ is_applicable_property_v = (+ is_executor<T>::value));+# else // defined(ASIO_NO_DEPRECATED)+ template <typename T>+ ASIO_STATIC_CONSTEXPR(bool,+ is_applicable_property_v = (+ is_executor<T>::value+ || conditional<+ is_executor<T>::value,+ false_type,+ is_sender<T>+ >::type::value+ || conditional<+ is_executor<T>::value,+ false_type,+ is_scheduler<T>+ >::type::value+ ));+# endif // defined(ASIO_NO_DEPRECATED) #endif // defined(ASIO_HAS_VARIABLE_TEMPLATES) ASIO_STATIC_CONSTEXPR(bool, is_requirable = true);@@ -427,26 +547,46 @@ { } + template <typename T>+ struct query_member :+ traits::query_member<+ typename bulk_guarantee_t<I>::template proxy<T>::type,+ unsequenced_t> {};++ template <typename T>+ struct query_static_constexpr_member :+ traits::query_static_constexpr_member<+ typename bulk_guarantee_t<I>::template static_proxy<T>::type,+ unsequenced_t> {};+ #if defined(ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT) \ && defined(ASIO_HAS_SFINAE_VARIABLE_TEMPLATES) template <typename T> static ASIO_CONSTEXPR- typename traits::query_static_constexpr_member<T, unsequenced_t>::result_type+ typename query_static_constexpr_member<T>::result_type static_query() ASIO_NOEXCEPT_IF((- traits::query_static_constexpr_member<T, unsequenced_t>::is_noexcept))+ query_static_constexpr_member<T>::is_noexcept)) {- return traits::query_static_constexpr_member<T, unsequenced_t>::value();+ return query_static_constexpr_member<T>::value(); } template <typename T> static ASIO_CONSTEXPR unsequenced_t static_query( typename enable_if<- !traits::query_static_constexpr_member<T, unsequenced_t>::is_valid- && !traits::query_member<T, unsequenced_t>::is_valid- && !traits::query_free<T, unsequenced_t>::is_valid- && !can_query<T, sequenced_t<I> >::value- && !can_query<T, parallel_t<I> >::value+ !query_static_constexpr_member<T>::is_valid+ >::type* = 0,+ typename enable_if<+ !query_member<T>::is_valid+ >::type* = 0,+ typename enable_if<+ !traits::query_free<T, unsequenced_t>::is_valid+ >::type* = 0,+ typename enable_if<+ !can_query<T, sequenced_t<I> >::value+ >::type* = 0,+ typename enable_if<+ !can_query<T, parallel_t<I> >::value >::type* = 0) ASIO_NOEXCEPT { return unsequenced_t();@@ -511,10 +651,28 @@ struct sequenced_t { #if defined(ASIO_HAS_VARIABLE_TEMPLATES)+# if defined(ASIO_NO_DEPRECATED) template <typename T> ASIO_STATIC_CONSTEXPR(bool,- is_applicable_property_v = is_executor<T>::value- || is_sender<T>::value || is_scheduler<T>::value);+ is_applicable_property_v = (+ is_executor<T>::value));+# else // defined(ASIO_NO_DEPRECATED)+ template <typename T>+ ASIO_STATIC_CONSTEXPR(bool,+ is_applicable_property_v = (+ is_executor<T>::value+ || conditional<+ is_executor<T>::value,+ false_type,+ is_sender<T>+ >::type::value+ || conditional<+ is_executor<T>::value,+ false_type,+ is_scheduler<T>+ >::type::value+ ));+# endif // defined(ASIO_NO_DEPRECATED) #endif // defined(ASIO_HAS_VARIABLE_TEMPLATES) ASIO_STATIC_CONSTEXPR(bool, is_requirable = true);@@ -525,16 +683,28 @@ { } + template <typename T>+ struct query_member :+ traits::query_member<+ typename bulk_guarantee_t<I>::template proxy<T>::type,+ sequenced_t> {};++ template <typename T>+ struct query_static_constexpr_member :+ traits::query_static_constexpr_member<+ typename bulk_guarantee_t<I>::template static_proxy<T>::type,+ sequenced_t> {};+ #if defined(ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT) \ && defined(ASIO_HAS_SFINAE_VARIABLE_TEMPLATES) template <typename T> static ASIO_CONSTEXPR- typename traits::query_static_constexpr_member<T, sequenced_t>::result_type+ typename query_static_constexpr_member<T>::result_type static_query() ASIO_NOEXCEPT_IF((- traits::query_static_constexpr_member<T, sequenced_t>::is_noexcept))+ query_static_constexpr_member<T>::is_noexcept)) {- return traits::query_static_constexpr_member<T, sequenced_t>::value();+ return query_static_constexpr_member<T>::value(); } template <typename E, typename T = decltype(sequenced_t::static_query<E>())>@@ -596,10 +766,28 @@ struct parallel_t { #if defined(ASIO_HAS_VARIABLE_TEMPLATES)+# if defined(ASIO_NO_DEPRECATED) template <typename T> ASIO_STATIC_CONSTEXPR(bool,- is_applicable_property_v = is_executor<T>::value- || is_sender<T>::value || is_scheduler<T>::value);+ is_applicable_property_v = (+ is_executor<T>::value));+# else // defined(ASIO_NO_DEPRECATED)+ template <typename T>+ ASIO_STATIC_CONSTEXPR(bool,+ is_applicable_property_v = (+ is_executor<T>::value+ || conditional<+ is_executor<T>::value,+ false_type,+ is_sender<T>+ >::type::value+ || conditional<+ is_executor<T>::value,+ false_type,+ is_scheduler<T>+ >::type::value+ ));+# endif // defined(ASIO_NO_DEPRECATED) #endif // defined(ASIO_HAS_VARIABLE_TEMPLATES) ASIO_STATIC_CONSTEXPR(bool, is_requirable = true);@@ -610,16 +798,28 @@ { } + template <typename T>+ struct query_member :+ traits::query_member<+ typename bulk_guarantee_t<I>::template proxy<T>::type,+ parallel_t> {};++ template <typename T>+ struct query_static_constexpr_member :+ traits::query_static_constexpr_member<+ typename bulk_guarantee_t<I>::template static_proxy<T>::type,+ parallel_t> {};+ #if defined(ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT) \ && defined(ASIO_HAS_SFINAE_VARIABLE_TEMPLATES) template <typename T> static ASIO_CONSTEXPR- typename traits::query_static_constexpr_member<T, parallel_t>::result_type+ typename query_static_constexpr_member<T>::result_type static_query() ASIO_NOEXCEPT_IF((- traits::query_static_constexpr_member<T, parallel_t>::is_noexcept))+ query_static_constexpr_member<T>::is_noexcept)) {- return traits::query_static_constexpr_member<T, parallel_t>::value();+ return query_static_constexpr_member<T>::value(); } template <typename E, typename T = decltype(parallel_t::static_query<E>())>@@ -697,8 +897,16 @@ struct is_applicable_property<T, execution::bulk_guarantee_t> : integral_constant<bool, execution::is_executor<T>::value- || execution::is_sender<T>::value- || execution::is_scheduler<T>::value>+ || conditional<+ execution::is_executor<T>::value,+ false_type,+ execution::is_sender<T>+ >::type::value+ || conditional<+ execution::is_executor<T>::value,+ false_type,+ execution::is_scheduler<T>+ >::type::value> { }; @@ -706,8 +914,16 @@ struct is_applicable_property<T, execution::bulk_guarantee_t::unsequenced_t> : integral_constant<bool, execution::is_executor<T>::value- || execution::is_sender<T>::value- || execution::is_scheduler<T>::value>+ || conditional<+ execution::is_executor<T>::value,+ false_type,+ execution::is_sender<T>+ >::type::value+ || conditional<+ execution::is_executor<T>::value,+ false_type,+ execution::is_scheduler<T>+ >::type::value> { }; @@ -715,8 +931,16 @@ struct is_applicable_property<T, execution::bulk_guarantee_t::sequenced_t> : integral_constant<bool, execution::is_executor<T>::value- || execution::is_sender<T>::value- || execution::is_scheduler<T>::value>+ || conditional<+ execution::is_executor<T>::value,+ false_type,+ execution::is_sender<T>+ >::type::value+ || conditional<+ execution::is_executor<T>::value,+ false_type,+ execution::is_scheduler<T>+ >::type::value> { }; @@ -724,8 +948,16 @@ struct is_applicable_property<T, execution::bulk_guarantee_t::parallel_t> : integral_constant<bool, execution::is_executor<T>::value- || execution::is_sender<T>::value- || execution::is_scheduler<T>::value>+ || conditional<+ execution::is_executor<T>::value,+ false_type,+ execution::is_sender<T>+ >::type::value+ || conditional<+ execution::is_executor<T>::value,+ false_type,+ execution::is_scheduler<T>+ >::type::value> { }; @@ -785,30 +1017,30 @@ template <typename T> struct static_query<T, execution::bulk_guarantee_t, typename enable_if<- traits::query_static_constexpr_member<T,- execution::bulk_guarantee_t>::is_valid+ execution::detail::bulk_guarantee_t<0>::+ query_static_constexpr_member<T>::is_valid >::type> { ASIO_STATIC_CONSTEXPR(bool, is_valid = true); ASIO_STATIC_CONSTEXPR(bool, is_noexcept = true); - typedef typename traits::query_static_constexpr_member<T,- execution::bulk_guarantee_t>::result_type result_type;+ typedef typename execution::detail::bulk_guarantee_t<0>::+ query_static_constexpr_member<T>::result_type result_type; static ASIO_CONSTEXPR result_type value() {- return traits::query_static_constexpr_member<T,- execution::bulk_guarantee_t>::value();+ return execution::detail::bulk_guarantee_t<0>::+ query_static_constexpr_member<T>::value(); } }; template <typename T> struct static_query<T, execution::bulk_guarantee_t, typename enable_if<- !traits::query_static_constexpr_member<T,- execution::bulk_guarantee_t>::is_valid- && !traits::query_member<T,- execution::bulk_guarantee_t>::is_valid+ !execution::detail::bulk_guarantee_t<0>::+ query_static_constexpr_member<T>::is_valid+ && !execution::detail::bulk_guarantee_t<0>::+ query_member<T>::is_valid && traits::static_query<T, execution::bulk_guarantee_t::unsequenced_t>::is_valid >::type>@@ -829,10 +1061,10 @@ template <typename T> struct static_query<T, execution::bulk_guarantee_t, typename enable_if<- !traits::query_static_constexpr_member<T,- execution::bulk_guarantee_t>::is_valid- && !traits::query_member<T,- execution::bulk_guarantee_t>::is_valid+ !execution::detail::bulk_guarantee_t<0>::+ query_static_constexpr_member<T>::is_valid+ && !execution::detail::bulk_guarantee_t<0>::+ query_member<T>::is_valid && !traits::static_query<T, execution::bulk_guarantee_t::unsequenced_t>::is_valid && traits::static_query<T,@@ -855,10 +1087,10 @@ template <typename T> struct static_query<T, execution::bulk_guarantee_t, typename enable_if<- !traits::query_static_constexpr_member<T,- execution::bulk_guarantee_t>::is_valid- && !traits::query_member<T,- execution::bulk_guarantee_t>::is_valid+ !execution::detail::bulk_guarantee_t<0>::+ query_static_constexpr_member<T>::is_valid+ && !execution::detail::bulk_guarantee_t<0>::+ query_member<T>::is_valid && !traits::static_query<T, execution::bulk_guarantee_t::unsequenced_t>::is_valid && !traits::static_query<T,@@ -883,30 +1115,30 @@ template <typename T> struct static_query<T, execution::bulk_guarantee_t::unsequenced_t, typename enable_if<- traits::query_static_constexpr_member<T,- execution::bulk_guarantee_t::unsequenced_t>::is_valid+ execution::detail::bulk_guarantee::unsequenced_t<0>::+ query_static_constexpr_member<T>::is_valid >::type> { ASIO_STATIC_CONSTEXPR(bool, is_valid = true); ASIO_STATIC_CONSTEXPR(bool, is_noexcept = true); - typedef typename traits::query_static_constexpr_member<T,- execution::bulk_guarantee_t::unsequenced_t>::result_type result_type;+ typedef typename execution::detail::bulk_guarantee::unsequenced_t<0>::+ query_static_constexpr_member<T>::result_type result_type; static ASIO_CONSTEXPR result_type value() {- return traits::query_static_constexpr_member<T,- execution::bulk_guarantee_t::unsequenced_t>::value();+ return execution::detail::bulk_guarantee::unsequenced_t<0>::+ query_static_constexpr_member<T>::value(); } }; template <typename T> struct static_query<T, execution::bulk_guarantee_t::unsequenced_t, typename enable_if<- !traits::query_static_constexpr_member<T,- execution::bulk_guarantee_t::unsequenced_t>::is_valid- && !traits::query_member<T,- execution::bulk_guarantee_t::unsequenced_t>::is_valid+ !execution::detail::bulk_guarantee::unsequenced_t<0>::+ query_static_constexpr_member<T>::is_valid+ && !execution::detail::bulk_guarantee::unsequenced_t<0>::+ query_member<T>::is_valid && !traits::query_free<T, execution::bulk_guarantee_t::unsequenced_t>::is_valid && !can_query<T, execution::bulk_guarantee_t::sequenced_t>::value@@ -927,40 +1159,40 @@ template <typename T> struct static_query<T, execution::bulk_guarantee_t::sequenced_t, typename enable_if<- traits::query_static_constexpr_member<T,- execution::bulk_guarantee_t::sequenced_t>::is_valid+ execution::detail::bulk_guarantee::sequenced_t<0>::+ query_static_constexpr_member<T>::is_valid >::type> { ASIO_STATIC_CONSTEXPR(bool, is_valid = true); ASIO_STATIC_CONSTEXPR(bool, is_noexcept = true); - typedef typename traits::query_static_constexpr_member<T,- execution::bulk_guarantee_t::sequenced_t>::result_type result_type;+ typedef typename execution::detail::bulk_guarantee::sequenced_t<0>::+ query_static_constexpr_member<T>::result_type result_type; static ASIO_CONSTEXPR result_type value() {- return traits::query_static_constexpr_member<T,- execution::bulk_guarantee_t::sequenced_t>::value();+ return execution::detail::bulk_guarantee::sequenced_t<0>::+ query_static_constexpr_member<T>::value(); } }; template <typename T> struct static_query<T, execution::bulk_guarantee_t::parallel_t, typename enable_if<- traits::query_static_constexpr_member<T,- execution::bulk_guarantee_t::parallel_t>::is_valid+ execution::detail::bulk_guarantee::parallel_t<0>::+ query_static_constexpr_member<T>::is_valid >::type> { ASIO_STATIC_CONSTEXPR(bool, is_valid = true); ASIO_STATIC_CONSTEXPR(bool, is_noexcept = true); - typedef typename traits::query_static_constexpr_member<T,- execution::bulk_guarantee_t::parallel_t>::result_type result_type;+ typedef typename execution::detail::bulk_guarantee::parallel_t<0>::+ query_static_constexpr_member<T>::result_type result_type; static ASIO_CONSTEXPR result_type value() {- return traits::query_static_constexpr_member<T,- execution::bulk_guarantee_t::parallel_t>::value();+ return execution::detail::bulk_guarantee::parallel_t<0>::+ query_static_constexpr_member<T>::value(); } }; @@ -1014,5 +1246,7 @@ } // namespace asio #include "asio/detail/pop_options.hpp"++#endif // !defined(ASIO_NO_DEPRECATED) #endif // ASIO_EXECUTION_BULK_GUARANTEE_HPP
link/modules/asio-standalone/asio/include/asio/execution/connect.hpp view
@@ -2,7 +2,7 @@ // execution/connect.hpp // ~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -16,6 +16,9 @@ #endif // defined(_MSC_VER) && (_MSC_VER >= 1200) #include "asio/detail/config.hpp"++#if !defined(ASIO_NO_DEPRECATED)+ #include "asio/detail/type_traits.hpp" #include "asio/execution/detail/as_invocable.hpp" #include "asio/execution/detail/as_operation.hpp"@@ -157,7 +160,8 @@ ill_formed }; -template <typename S, typename R, typename = void>+template <typename S, typename R, typename = void,+ typename = void, typename = void, typename = void> struct call_traits { ASIO_STATIC_CONSTEXPR(overload_type, overload = ill_formed);@@ -168,13 +172,13 @@ template <typename S, typename R> struct call_traits<S, void(R), typename enable_if<- (- connect_member<S, R>::is_valid- &&- is_operation_state<typename connect_member<S, R>::result_type>::value- &&- is_sender<typename remove_cvref<S>::type>::value- )+ connect_member<S, R>::is_valid+ >::type,+ typename enable_if<+ is_operation_state<typename connect_member<S, R>::result_type>::value+ >::type,+ typename enable_if<+ is_sender<typename remove_cvref<S>::type>::value >::type> : connect_member<S, R> {@@ -184,15 +188,16 @@ template <typename S, typename R> struct call_traits<S, void(R), typename enable_if<- (- !connect_member<S, R>::is_valid- &&- connect_free<S, R>::is_valid- &&- is_operation_state<typename connect_free<S, R>::result_type>::value- &&- is_sender<typename remove_cvref<S>::type>::value- )+ !connect_member<S, R>::is_valid+ >::type,+ typename enable_if<+ connect_free<S, R>::is_valid+ >::type,+ typename enable_if<+ is_operation_state<typename connect_free<S, R>::result_type>::value+ >::type,+ typename enable_if<+ is_sender<typename remove_cvref<S>::type>::value >::type> : connect_free<S, R> {@@ -202,24 +207,25 @@ template <typename S, typename R> struct call_traits<S, void(R), typename enable_if<- (- !connect_member<S, R>::is_valid- &&- !connect_free<S, R>::is_valid- &&- is_receiver<R>::value- &&- conditional<- !is_as_receiver<- typename remove_cvref<R>::type- >::value,- is_executor_of<- typename remove_cvref<S>::type,- as_invocable<typename remove_cvref<R>::type, S>- >,- false_type- >::type::value- )+ !connect_member<S, R>::is_valid+ >::type,+ typename enable_if<+ !connect_free<S, R>::is_valid+ >::type,+ typename enable_if<+ is_receiver<R>::value+ >::type,+ typename enable_if<+ conditional<+ !is_as_receiver<+ typename remove_cvref<R>::type+ >::value,+ is_executor_of<+ typename remove_cvref<S>::type,+ as_invocable<typename remove_cvref<R>::type, S>+ >,+ false_type+ >::type::value >::type> { ASIO_STATIC_CONSTEXPR(overload_type, overload = adapter);@@ -482,5 +488,7 @@ #endif // defined(GENERATING_DOCUMENTATION) #include "asio/detail/pop_options.hpp"++#endif // !defined(ASIO_NO_DEPRECATED) #endif // ASIO_EXECUTION_CONNECT_HPP
link/modules/asio-standalone/asio/include/asio/execution/context.hpp view
@@ -2,7 +2,7 @@ // execution/context.hpp // ~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -69,10 +69,28 @@ struct context_t { #if defined(ASIO_HAS_VARIABLE_TEMPLATES)+# if defined(ASIO_NO_DEPRECATED) template <typename T> ASIO_STATIC_CONSTEXPR(bool,- is_applicable_property_v = is_executor<T>::value- || is_sender<T>::value || is_scheduler<T>::value);+ is_applicable_property_v = (+ is_executor<T>::value));+# else // defined(ASIO_NO_DEPRECATED)+ template <typename T>+ ASIO_STATIC_CONSTEXPR(bool,+ is_applicable_property_v = (+ is_executor<T>::value+ || conditional<+ is_executor<T>::value,+ false_type,+ is_sender<T>+ >::type::value+ || conditional<+ is_executor<T>::value,+ false_type,+ is_scheduler<T>+ >::type::value+ ));+# endif // defined(ASIO_NO_DEPRECATED) #endif // defined(ASIO_HAS_VARIABLE_TEMPLATES) ASIO_STATIC_CONSTEXPR(bool, is_requirable = false);@@ -86,16 +104,46 @@ { } + template <typename T>+ struct static_proxy+ {+#if defined(ASIO_HAS_DEDUCED_QUERY_STATIC_CONSTEXPR_MEMBER_TRAIT)+ struct type+ {+ template <typename P>+ static constexpr auto query(ASIO_MOVE_ARG(P) p)+ noexcept(+ noexcept(+ conditional<true, T, P>::type::query(ASIO_MOVE_CAST(P)(p))+ )+ )+ -> decltype(+ conditional<true, T, P>::type::query(ASIO_MOVE_CAST(P)(p))+ )+ {+ return T::query(ASIO_MOVE_CAST(P)(p));+ }+ };+#else // defined(ASIO_HAS_DEDUCED_QUERY_STATIC_CONSTEXPR_MEMBER_TRAIT)+ typedef T type;+#endif // defined(ASIO_HAS_DEDUCED_QUERY_STATIC_CONSTEXPR_MEMBER_TRAIT)+ };++ template <typename T>+ struct query_static_constexpr_member :+ traits::query_static_constexpr_member<+ typename static_proxy<T>::type, context_t> {};+ #if defined(ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT) \ && defined(ASIO_HAS_SFINAE_VARIABLE_TEMPLATES) template <typename T> static ASIO_CONSTEXPR- typename traits::query_static_constexpr_member<T, context_t>::result_type+ typename query_static_constexpr_member<T>::result_type static_query() ASIO_NOEXCEPT_IF((- traits::query_static_constexpr_member<T, context_t>::is_noexcept))+ query_static_constexpr_member<T>::is_noexcept)) {- return traits::query_static_constexpr_member<T, context_t>::value();+ return query_static_constexpr_member<T>::value(); } template <typename E, typename T = decltype(context_t::static_query<E>())>@@ -139,8 +187,19 @@ struct is_applicable_property<T, execution::context_t> : integral_constant<bool, execution::is_executor<T>::value- || execution::is_sender<T>::value- || execution::is_scheduler<T>::value>+#if !defined(ASIO_NO_DEPRECATED)+ || conditional<+ execution::is_executor<T>::value,+ false_type,+ execution::is_sender<T>+ >::type::value+ || conditional<+ execution::is_executor<T>::value,+ false_type,+ execution::is_scheduler<T>+ >::type::value+#endif // !defined(ASIO_NO_DEPRECATED)+ > { }; @@ -154,20 +213,20 @@ template <typename T> struct static_query<T, execution::context_t, typename enable_if<- traits::query_static_constexpr_member<T,- execution::context_t>::is_valid+ execution::detail::context_t<0>::+ query_static_constexpr_member<T>::is_valid >::type> { ASIO_STATIC_CONSTEXPR(bool, is_valid = true); ASIO_STATIC_CONSTEXPR(bool, is_noexcept = true); - typedef typename traits::query_static_constexpr_member<T,- execution::context_t>::result_type result_type;+ typedef typename execution::detail::context_t<0>::+ query_static_constexpr_member<T>::result_type result_type; static ASIO_CONSTEXPR result_type value() {- return traits::query_static_constexpr_member<T,- execution::context_t>::value();+ return execution::detail::context_t<0>::+ query_static_constexpr_member<T>::value(); } };
link/modules/asio-standalone/asio/include/asio/execution/context_as.hpp view
@@ -2,7 +2,7 @@ // execution/context_as.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -68,10 +68,28 @@ struct context_as_t { #if defined(ASIO_HAS_VARIABLE_TEMPLATES)+# if defined(ASIO_NO_DEPRECATED) template <typename U> ASIO_STATIC_CONSTEXPR(bool,- is_applicable_property_v = is_executor<U>::value- || is_sender<U>::value || is_scheduler<U>::value);+ is_applicable_property_v = (+ is_executor<U>::value));+# else // defined(ASIO_NO_DEPRECATED)+ template <typename U>+ ASIO_STATIC_CONSTEXPR(bool,+ is_applicable_property_v = (+ is_executor<U>::value+ || conditional<+ is_executor<U>::value,+ false_type,+ is_sender<U>+ >::type::value+ || conditional<+ is_executor<U>::value,+ false_type,+ is_scheduler<U>+ >::type::value+ ));+# endif // defined(ASIO_NO_DEPRECATED) #endif // defined(ASIO_HAS_VARIABLE_TEMPLATES) ASIO_STATIC_CONSTEXPR(bool, is_requirable = false);@@ -91,12 +109,12 @@ && defined(ASIO_HAS_SFINAE_VARIABLE_TEMPLATES) template <typename E> static ASIO_CONSTEXPR- typename traits::query_static_constexpr_member<E, context_t>::result_type+ typename context_t::query_static_constexpr_member<E>::result_type static_query() ASIO_NOEXCEPT_IF((- traits::query_static_constexpr_member<E, context_t>::is_noexcept))+ context_t::query_static_constexpr_member<E>::is_noexcept)) {- return traits::query_static_constexpr_member<E, context_t>::value();+ return context_t::query_static_constexpr_member<E>::value(); } template <typename E, typename U = decltype(context_as_t::static_query<E>())>@@ -110,7 +128,9 @@ const Executor& ex, const context_as_t<U>&, typename enable_if< is_same<T, U>::value- && can_query<const Executor&, const context_t&>::value+ >::type* = 0,+ typename enable_if<+ can_query<const Executor&, const context_t&>::value >::type* = 0) #if !defined(__clang__) // Clang crashes if noexcept is used here. #if defined(ASIO_MSVC) // Visual C++ wants the type to be qualified.@@ -150,8 +170,19 @@ struct is_applicable_property<T, execution::context_as_t<U> > : integral_constant<bool, execution::is_executor<T>::value- || execution::is_sender<T>::value- || execution::is_scheduler<T>::value>+#if !defined(ASIO_NO_DEPRECATED)+ || conditional<+ execution::is_executor<T>::value,+ false_type,+ execution::is_sender<T>+ >::type::value+ || conditional<+ execution::is_executor<T>::value,+ false_type,+ execution::is_scheduler<T>+ >::type::value+#endif // !defined(ASIO_NO_DEPRECATED)+ > { };
link/modules/asio-standalone/asio/include/asio/execution/detail/as_invocable.hpp view
@@ -2,7 +2,7 @@ // execution/detail/as_invocable.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/execution/detail/as_operation.hpp view
@@ -2,7 +2,7 @@ // execution/detail/as_operation.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -54,8 +54,12 @@ try { #endif // !defined(ASIO_NO_EXCEPTIONS)+#if defined(ASIO_NO_DEPRECATED)+ ex_.execute(+#else // defined(ASIO_NO_DEPRECATED) execution::execute( ASIO_MOVE_CAST(typename remove_cvref<Executor>::type)(ex_),+#endif // defined(ASIO_NO_DEPRECATED) as_invocable<typename remove_cvref<Receiver>::type, Executor>(receiver_ #if !defined(ASIO_HAS_MOVE)
link/modules/asio-standalone/asio/include/asio/execution/detail/as_receiver.hpp view
@@ -2,7 +2,7 @@ // execution/detail/as_receiver.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/execution/detail/bulk_sender.hpp view
@@ -2,7 +2,7 @@ // execution/detail/bulk_sender.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/execution/detail/submit_receiver.hpp view
@@ -2,7 +2,7 @@ // execution/detail/submit_receiver.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/execution/detail/void_receiver.hpp view
@@ -2,7 +2,7 @@ // execution/detail/void_receiver.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/execution/execute.hpp view
@@ -2,7 +2,7 @@ // execution/execute.hpp // ~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -16,6 +16,9 @@ #endif // defined(_MSC_VER) && (_MSC_VER >= 1200) #include "asio/detail/config.hpp"++#if !defined(ASIO_NO_DEPRECATED)+ #include "asio/detail/type_traits.hpp" #include "asio/execution/detail/as_invocable.hpp" #include "asio/execution/detail/as_receiver.hpp"@@ -29,7 +32,8 @@ namespace asio { namespace execution { -/// A customisation point that executes a function on an executor.+/// (Deprecated: Use @c execute member function.) A customisation point that+/// executes a function on an executor. /** * The name <tt>execution::execute</tt> denotes a customisation point object. *@@ -53,7 +57,8 @@ */ inline constexpr unspecified execute = unspecified; -/// A type trait that determines whether a @c execute expression is well-formed.+/// (Deprecated.) A type trait that determines whether an @c execute expression+/// is well-formed. /** * Class template @c can_execute is a trait that is derived from * @c true_type if the expression <tt>execution::execute(std::declval<T>(),@@ -98,6 +103,7 @@ using asio::traits::execute_free; using asio::traits::execute_member; using asio::true_type;+using asio::void_type; void execute(); @@ -109,61 +115,52 @@ ill_formed }; -template <typename T, typename F, typename = void>+template <typename Impl, typename T, typename F, typename = void,+ typename = void, typename = void, typename = void, typename = void> struct call_traits { ASIO_STATIC_CONSTEXPR(overload_type, overload = ill_formed); }; -template <typename T, typename F>-struct call_traits<T, void(F),+template <typename Impl, typename T, typename F>+struct call_traits<Impl, T, void(F), typename enable_if<- (- execute_member<T, F>::is_valid- )+ execute_member<typename Impl::template proxy<T>::type, F>::is_valid >::type> :- execute_member<T, F>+ execute_member<typename Impl::template proxy<T>::type, F> { ASIO_STATIC_CONSTEXPR(overload_type, overload = call_member); }; -template <typename T, typename F>-struct call_traits<T, void(F),+template <typename Impl, typename T, typename F>+struct call_traits<Impl, T, void(F), typename enable_if<- (- !execute_member<T, F>::is_valid- &&- execute_free<T, F>::is_valid- )+ !execute_member<typename Impl::template proxy<T>, F>::is_valid+ >::type,+ typename enable_if<+ execute_free<T, F>::is_valid >::type> : execute_free<T, F> { ASIO_STATIC_CONSTEXPR(overload_type, overload = call_free); }; -template <typename T, typename F>-struct call_traits<T, void(F),+template <typename Impl, typename T, typename F>+struct call_traits<Impl, T, void(F), typename enable_if<- (- !execute_member<T, F>::is_valid- &&- !execute_free<T, F>::is_valid- &&- conditional<true, true_type,- typename result_of<typename decay<F>::type&()>::type- >::type::value- &&- conditional<- !is_as_invocable<- typename decay<F>::type- >::value,- is_sender_to<- T,- as_receiver<typename decay<F>::type, T>- >,- false_type- >::type::value- )+ !execute_member<typename Impl::template proxy<T>::type, F>::is_valid+ >::type,+ typename enable_if<+ !execute_free<T, F>::is_valid+ >::type,+ typename void_type<+ typename result_of<typename decay<F>::type&()>::type+ >::type,+ typename enable_if<+ !is_as_invocable<typename decay<F>::type>::value+ >::type,+ typename enable_if<+ is_sender_to<T, as_receiver<typename decay<F>::type, T> >::value >::type> { ASIO_STATIC_CONSTEXPR(overload_type, overload = adapter);@@ -174,44 +171,68 @@ struct impl {+ template <typename T>+ struct proxy+ {+#if defined(ASIO_HAS_DEDUCED_EXECUTE_MEMBER_TRAIT)+ struct type+ {+ template <typename F>+ auto execute(ASIO_MOVE_ARG(F) f)+ noexcept(+ noexcept(+ declval<typename conditional<true, T, F>::type>().execute(+ ASIO_MOVE_CAST(F)(f))+ )+ )+ -> decltype(+ declval<typename conditional<true, T, F>::type>().execute(+ ASIO_MOVE_CAST(F)(f))+ );+ };+#else // defined(ASIO_HAS_DEDUCED_EXECUTE_MEMBER_TRAIT)+ typedef T type;+#endif // defined(ASIO_HAS_DEDUCED_EXECUTE_MEMBER_TRAIT)+ };+ template <typename T, typename F> ASIO_CONSTEXPR typename enable_if<- call_traits<T, void(F)>::overload == call_member,- typename call_traits<T, void(F)>::result_type+ call_traits<impl, T, void(F)>::overload == call_member,+ typename call_traits<impl, T, void(F)>::result_type >::type operator()( ASIO_MOVE_ARG(T) t, ASIO_MOVE_ARG(F) f) const ASIO_NOEXCEPT_IF((- call_traits<T, void(F)>::is_noexcept))+ call_traits<impl, T, void(F)>::is_noexcept)) { return ASIO_MOVE_CAST(T)(t).execute(ASIO_MOVE_CAST(F)(f)); } template <typename T, typename F> ASIO_CONSTEXPR typename enable_if<- call_traits<T, void(F)>::overload == call_free,- typename call_traits<T, void(F)>::result_type+ call_traits<impl, T, void(F)>::overload == call_free,+ typename call_traits<impl, T, void(F)>::result_type >::type operator()( ASIO_MOVE_ARG(T) t, ASIO_MOVE_ARG(F) f) const ASIO_NOEXCEPT_IF((- call_traits<T, void(F)>::is_noexcept))+ call_traits<impl, T, void(F)>::is_noexcept)) { return execute(ASIO_MOVE_CAST(T)(t), ASIO_MOVE_CAST(F)(f)); } template <typename T, typename F> ASIO_CONSTEXPR typename enable_if<- call_traits<T, void(F)>::overload == adapter,- typename call_traits<T, void(F)>::result_type+ call_traits<impl, T, void(F)>::overload == adapter,+ typename call_traits<impl, T, void(F)>::result_type >::type operator()( ASIO_MOVE_ARG(T) t, ASIO_MOVE_ARG(F) f) const ASIO_NOEXCEPT_IF((- call_traits<T, void(F)>::is_noexcept))+ call_traits<impl, T, void(F)>::is_noexcept)) { return asio::execution::detail::submit_helper( ASIO_MOVE_CAST(T)(t),@@ -239,11 +260,14 @@ } // namespace +typedef asio_execution_execute_fn::impl execute_t;+ template <typename T, typename F> struct can_execute : integral_constant<bool,- asio_execution_execute_fn::call_traits<T, void(F)>::overload !=- asio_execution_execute_fn::ill_formed>+ asio_execution_execute_fn::call_traits<+ execute_t, T, void(F)>::overload !=+ asio_execution_execute_fn::ill_formed> { }; @@ -260,5 +284,7 @@ #endif // defined(GENERATING_DOCUMENTATION) #include "asio/detail/pop_options.hpp"++#endif // !defined(ASIO_NO_DEPRECATED) #endif // ASIO_EXECUTION_EXECUTE_HPP
link/modules/asio-standalone/asio/include/asio/execution/executor.hpp view
@@ -2,7 +2,7 @@ // execution/executor.hpp // ~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -17,10 +17,14 @@ #include "asio/detail/config.hpp" #include "asio/detail/type_traits.hpp"-#include "asio/execution/execute.hpp" #include "asio/execution/invocable_archetype.hpp" #include "asio/traits/equality_comparable.hpp"+#include "asio/traits/execute_member.hpp" +#if !defined(ASIO_NO_DEPRECATED)+# include "asio/execution/execute.hpp"+#endif // !defined(ASIO_NO_DEPRECATED)+ #if defined(ASIO_HAS_DEDUCED_EXECUTE_FREE_TRAIT) \ && defined(ASIO_HAS_DEDUCED_EXECUTE_MEMBER_TRAIT) \ && defined(ASIO_HAS_DEDUCED_EQUALITY_COMPARABLE_TRAIT)@@ -35,34 +39,54 @@ namespace execution { namespace detail { -template <typename T, typename F>-struct is_executor_of_impl_base :- integral_constant<bool,- conditional<true, true_type,- typename result_of<typename decay<F>::type&()>::type- >::type::value- && is_constructible<typename decay<F>::type, F>::value- && is_move_constructible<typename decay<F>::type>::value-#if defined(ASIO_HAS_NOEXCEPT)- && is_nothrow_copy_constructible<T>::value- && is_nothrow_destructible<T>::value-#else // defined(ASIO_HAS_NOEXCEPT)- && is_copy_constructible<T>::value- && is_destructible<T>::value-#endif // defined(ASIO_HAS_NOEXCEPT)- && traits::equality_comparable<T>::is_valid- && traits::equality_comparable<T>::is_noexcept- >+template <typename T, typename F,+ typename = void, typename = void, typename = void, typename = void,+ typename = void, typename = void, typename = void, typename = void>+struct is_executor_of_impl : false_type { }; template <typename T, typename F>-struct is_executor_of_impl :- conditional<- can_execute<T, F>::value,- is_executor_of_impl_base<T, F>,- false_type- >::type+struct is_executor_of_impl<T, F,+#if defined(ASIO_NO_DEPRECATED)+ typename enable_if<+ traits::execute_member<typename add_const<T>::type, F>::is_valid+ >::type,+#else // defined(ASIO_NO_DEPRECATED)+ typename enable_if<+ can_execute<typename add_const<T>::type, F>::value+ >::type,+#endif // defined(ASIO_NO_DEPRECATED)+ typename void_type<+ typename result_of<typename decay<F>::type&()>::type+ >::type,+ typename enable_if<+ is_constructible<typename decay<F>::type, F>::value+ >::type,+ typename enable_if<+ is_move_constructible<typename decay<F>::type>::value+ >::type,+#if defined(ASIO_HAS_NOEXCEPT)+ typename enable_if<+ is_nothrow_copy_constructible<T>::value+ >::type,+ typename enable_if<+ is_nothrow_destructible<T>::value+ >::type,+#else // defined(ASIO_HAS_NOEXCEPT)+ typename enable_if<+ is_copy_constructible<T>::value+ >::type,+ typename enable_if<+ is_destructible<T>::value+ >::type,+#endif // defined(ASIO_HAS_NOEXCEPT)+ typename enable_if<+ traits::equality_comparable<T>::is_valid+ >::type,+ typename enable_if<+ traits::equality_comparable<T>::is_noexcept+ >::type> : true_type { };
link/modules/asio-standalone/asio/include/asio/execution/impl/bad_executor.ipp view
@@ -2,7 +2,7 @@ // exection/impl/bad_executor.ipp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/execution/impl/receiver_invocation_error.ipp view
@@ -2,7 +2,7 @@ // exection/impl/receiver_invocation_error.ipp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/execution/invocable_archetype.hpp view
@@ -2,7 +2,7 @@ // execution/invocable_archetype.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/execution/mapping.hpp view
@@ -2,7 +2,7 @@ // execution/mapping.hpp // ~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -192,10 +192,28 @@ struct mapping_t { #if defined(ASIO_HAS_VARIABLE_TEMPLATES)+# if defined(ASIO_NO_DEPRECATED) template <typename T> ASIO_STATIC_CONSTEXPR(bool,- is_applicable_property_v = is_executor<T>::value- || is_sender<T>::value || is_scheduler<T>::value);+ is_applicable_property_v = (+ is_executor<T>::value));+# else // defined(ASIO_NO_DEPRECATED)+ template <typename T>+ ASIO_STATIC_CONSTEXPR(bool,+ is_applicable_property_v = (+ is_executor<T>::value+ || conditional<+ is_executor<T>::value,+ false_type,+ is_sender<T>+ >::type::value+ || conditional<+ is_executor<T>::value,+ false_type,+ is_scheduler<T>+ >::type::value+ ));+# endif // defined(ASIO_NO_DEPRECATED) #endif // defined(ASIO_HAS_VARIABLE_TEMPLATES) ASIO_STATIC_CONSTEXPR(bool, is_requirable = false);@@ -226,16 +244,74 @@ { } + template <typename T>+ struct proxy+ {+#if defined(ASIO_HAS_DEDUCED_QUERY_MEMBER_TRAIT)+ struct type+ {+ template <typename P>+ auto query(ASIO_MOVE_ARG(P) p) const+ noexcept(+ noexcept(+ declval<typename conditional<true, T, P>::type>().query(+ ASIO_MOVE_CAST(P)(p))+ )+ )+ -> decltype(+ declval<typename conditional<true, T, P>::type>().query(+ ASIO_MOVE_CAST(P)(p))+ );+ };+#else // defined(ASIO_HAS_DEDUCED_QUERY_MEMBER_TRAIT)+ typedef T type;+#endif // defined(ASIO_HAS_DEDUCED_QUERY_MEMBER_TRAIT)+ };++ template <typename T>+ struct static_proxy+ {+#if defined(ASIO_HAS_DEDUCED_QUERY_STATIC_CONSTEXPR_MEMBER_TRAIT)+ struct type+ {+ template <typename P>+ static constexpr auto query(ASIO_MOVE_ARG(P) p)+ noexcept(+ noexcept(+ conditional<true, T, P>::type::query(ASIO_MOVE_CAST(P)(p))+ )+ )+ -> decltype(+ conditional<true, T, P>::type::query(ASIO_MOVE_CAST(P)(p))+ )+ {+ return T::query(ASIO_MOVE_CAST(P)(p));+ }+ };+#else // defined(ASIO_HAS_DEDUCED_QUERY_STATIC_CONSTEXPR_MEMBER_TRAIT)+ typedef T type;+#endif // defined(ASIO_HAS_DEDUCED_QUERY_STATIC_CONSTEXPR_MEMBER_TRAIT)+ };++ template <typename T>+ struct query_member :+ traits::query_member<typename proxy<T>::type, mapping_t> {};++ template <typename T>+ struct query_static_constexpr_member :+ traits::query_static_constexpr_member<+ typename static_proxy<T>::type, mapping_t> {};+ #if defined(ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT) \ && defined(ASIO_HAS_SFINAE_VARIABLE_TEMPLATES) template <typename T> static ASIO_CONSTEXPR- typename traits::query_static_constexpr_member<T, mapping_t>::result_type+ typename query_static_constexpr_member<T>::result_type static_query() ASIO_NOEXCEPT_IF((- traits::query_static_constexpr_member<T, mapping_t>::is_noexcept))+ query_static_constexpr_member<T>::is_noexcept)) {- return traits::query_static_constexpr_member<T, mapping_t>::value();+ return query_static_constexpr_member<T>::value(); } template <typename T>@@ -243,9 +319,13 @@ typename traits::static_query<T, thread_t>::result_type static_query( typename enable_if<- !traits::query_static_constexpr_member<T, mapping_t>::is_valid- && !traits::query_member<T, mapping_t>::is_valid- && traits::static_query<T, thread_t>::is_valid+ !query_static_constexpr_member<T>::is_valid+ >::type* = 0,+ typename enable_if<+ !query_member<T>::is_valid+ >::type* = 0,+ typename enable_if<+ traits::static_query<T, thread_t>::is_valid >::type* = 0) ASIO_NOEXCEPT { return traits::static_query<T, thread_t>::value();@@ -256,10 +336,16 @@ typename traits::static_query<T, new_thread_t>::result_type static_query( typename enable_if<- !traits::query_static_constexpr_member<T, mapping_t>::is_valid- && !traits::query_member<T, mapping_t>::is_valid- && !traits::static_query<T, thread_t>::is_valid- && traits::static_query<T, new_thread_t>::is_valid+ !query_static_constexpr_member<T>::is_valid+ >::type* = 0,+ typename enable_if<+ !query_member<T>::is_valid+ >::type* = 0,+ typename enable_if<+ !traits::static_query<T, thread_t>::is_valid+ >::type* = 0,+ typename enable_if<+ traits::static_query<T, new_thread_t>::is_valid >::type* = 0) ASIO_NOEXCEPT { return traits::static_query<T, new_thread_t>::value();@@ -270,11 +356,19 @@ typename traits::static_query<T, other_t>::result_type static_query( typename enable_if<- !traits::query_static_constexpr_member<T, mapping_t>::is_valid- && !traits::query_member<T, mapping_t>::is_valid- && !traits::static_query<T, thread_t>::is_valid- && !traits::static_query<T, new_thread_t>::is_valid- && traits::static_query<T, other_t>::is_valid+ !query_static_constexpr_member<T>::is_valid+ >::type* = 0,+ typename enable_if<+ !query_member<T>::is_valid+ >::type* = 0,+ typename enable_if<+ !traits::static_query<T, thread_t>::is_valid+ >::type* = 0,+ typename enable_if<+ !traits::static_query<T, new_thread_t>::is_valid+ >::type* = 0,+ typename enable_if<+ traits::static_query<T, other_t>::is_valid >::type* = 0) ASIO_NOEXCEPT { return traits::static_query<T, other_t>::value();@@ -327,7 +421,9 @@ const Executor& ex, convertible_from_mapping_t, typename enable_if< !can_query<const Executor&, thread_t>::value- && can_query<const Executor&, new_thread_t>::value+ >::type* = 0,+ typename enable_if<+ can_query<const Executor&, new_thread_t>::value >::type* = 0) #if !defined(__clang__) // Clang crashes if noexcept is used here. #if defined(ASIO_MSVC) // Visual C++ wants the type to be qualified.@@ -347,8 +443,12 @@ const Executor& ex, convertible_from_mapping_t, typename enable_if< !can_query<const Executor&, thread_t>::value- && !can_query<const Executor&, new_thread_t>::value- && can_query<const Executor&, other_t>::value+ >::type* = 0,+ typename enable_if<+ !can_query<const Executor&, new_thread_t>::value+ >::type* = 0,+ typename enable_if<+ can_query<const Executor&, other_t>::value >::type* = 0) #if !defined(__clang__) // Clang crashes if noexcept is used here. #if defined(ASIO_MSVC) // Visual C++ wants the type to be qualified.@@ -402,10 +502,28 @@ struct thread_t { #if defined(ASIO_HAS_VARIABLE_TEMPLATES)+# if defined(ASIO_NO_DEPRECATED) template <typename T> ASIO_STATIC_CONSTEXPR(bool,- is_applicable_property_v = is_executor<T>::value- || is_sender<T>::value || is_scheduler<T>::value);+ is_applicable_property_v = (+ is_executor<T>::value));+# else // defined(ASIO_NO_DEPRECATED)+ template <typename T>+ ASIO_STATIC_CONSTEXPR(bool,+ is_applicable_property_v = (+ is_executor<T>::value+ || conditional<+ is_executor<T>::value,+ false_type,+ is_sender<T>+ >::type::value+ || conditional<+ is_executor<T>::value,+ false_type,+ is_scheduler<T>+ >::type::value+ ));+# endif // defined(ASIO_NO_DEPRECATED) #endif // defined(ASIO_HAS_VARIABLE_TEMPLATES) ASIO_STATIC_CONSTEXPR(bool, is_requirable = true);@@ -416,26 +534,44 @@ { } + template <typename T>+ struct query_member :+ traits::query_member<+ typename mapping_t<I>::template proxy<T>::type, thread_t> {};++ template <typename T>+ struct query_static_constexpr_member :+ traits::query_static_constexpr_member<+ typename mapping_t<I>::template static_proxy<T>::type, thread_t> {};+ #if defined(ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT) \ && defined(ASIO_HAS_SFINAE_VARIABLE_TEMPLATES) template <typename T> static ASIO_CONSTEXPR- typename traits::query_static_constexpr_member<T, thread_t>::result_type+ typename query_static_constexpr_member<T>::result_type static_query() ASIO_NOEXCEPT_IF((- traits::query_static_constexpr_member<T, thread_t>::is_noexcept))+ query_static_constexpr_member<T>::is_noexcept)) {- return traits::query_static_constexpr_member<T, thread_t>::value();+ return query_static_constexpr_member<T>::value(); } template <typename T> static ASIO_CONSTEXPR thread_t static_query( typename enable_if<- !traits::query_static_constexpr_member<T, thread_t>::is_valid- && !traits::query_member<T, thread_t>::is_valid- && !traits::query_free<T, thread_t>::is_valid- && !can_query<T, new_thread_t<I> >::value- && !can_query<T, other_t<I> >::value+ !query_static_constexpr_member<T>::is_valid+ >::type* = 0,+ typename enable_if<+ !query_member<T>::is_valid+ >::type* = 0,+ typename enable_if<+ !traits::query_free<T, thread_t>::is_valid+ >::type* = 0,+ typename enable_if<+ !can_query<T, new_thread_t<I> >::value+ >::type* = 0,+ typename enable_if<+ !can_query<T, other_t<I> >::value >::type* = 0) ASIO_NOEXCEPT { return thread_t();@@ -476,10 +612,28 @@ struct new_thread_t { #if defined(ASIO_HAS_VARIABLE_TEMPLATES)+# if defined(ASIO_NO_DEPRECATED) template <typename T> ASIO_STATIC_CONSTEXPR(bool,- is_applicable_property_v = is_executor<T>::value- || is_sender<T>::value || is_scheduler<T>::value);+ is_applicable_property_v = (+ is_executor<T>::value));+# else // defined(ASIO_NO_DEPRECATED)+ template <typename T>+ ASIO_STATIC_CONSTEXPR(bool,+ is_applicable_property_v = (+ is_executor<T>::value+ || conditional<+ is_executor<T>::value,+ false_type,+ is_sender<T>+ >::type::value+ || conditional<+ is_executor<T>::value,+ false_type,+ is_scheduler<T>+ >::type::value+ ));+# endif // defined(ASIO_NO_DEPRECATED) #endif // defined(ASIO_HAS_VARIABLE_TEMPLATES) ASIO_STATIC_CONSTEXPR(bool, is_requirable = true);@@ -490,16 +644,26 @@ { } + template <typename T>+ struct query_member :+ traits::query_member<+ typename mapping_t<I>::template proxy<T>::type, new_thread_t> {};++ template <typename T>+ struct query_static_constexpr_member :+ traits::query_static_constexpr_member<+ typename mapping_t<I>::template static_proxy<T>::type, new_thread_t> {};+ #if defined(ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT) \ && defined(ASIO_HAS_SFINAE_VARIABLE_TEMPLATES) template <typename T> static ASIO_CONSTEXPR- typename traits::query_static_constexpr_member<T, new_thread_t>::result_type+ typename query_static_constexpr_member<T>::result_type static_query() ASIO_NOEXCEPT_IF((- traits::query_static_constexpr_member<T, new_thread_t>::is_noexcept))+ query_static_constexpr_member<T>::is_noexcept)) {- return traits::query_static_constexpr_member<T, new_thread_t>::value();+ return query_static_constexpr_member<T>::value(); } template <typename E, typename T = decltype(new_thread_t::static_query<E>())>@@ -537,10 +701,28 @@ struct other_t { #if defined(ASIO_HAS_VARIABLE_TEMPLATES)+# if defined(ASIO_NO_DEPRECATED) template <typename T> ASIO_STATIC_CONSTEXPR(bool,- is_applicable_property_v = is_executor<T>::value- || is_sender<T>::value || is_scheduler<T>::value);+ is_applicable_property_v = (+ is_executor<T>::value));+# else // defined(ASIO_NO_DEPRECATED)+ template <typename T>+ ASIO_STATIC_CONSTEXPR(bool,+ is_applicable_property_v = (+ is_executor<T>::value+ || conditional<+ is_executor<T>::value,+ false_type,+ is_sender<T>+ >::type::value+ || conditional<+ is_executor<T>::value,+ false_type,+ is_scheduler<T>+ >::type::value+ ));+# endif // defined(ASIO_NO_DEPRECATED) #endif // defined(ASIO_HAS_VARIABLE_TEMPLATES) ASIO_STATIC_CONSTEXPR(bool, is_requirable = true);@@ -551,16 +733,26 @@ { } + template <typename T>+ struct query_member :+ traits::query_member<+ typename mapping_t<I>::template proxy<T>::type, other_t> {};++ template <typename T>+ struct query_static_constexpr_member :+ traits::query_static_constexpr_member<+ typename mapping_t<I>::template static_proxy<T>::type, other_t> {};+ #if defined(ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT) \ && defined(ASIO_HAS_SFINAE_VARIABLE_TEMPLATES) template <typename T> static ASIO_CONSTEXPR- typename traits::query_static_constexpr_member<T, other_t>::result_type+ typename query_static_constexpr_member<T>::result_type static_query() ASIO_NOEXCEPT_IF((- traits::query_static_constexpr_member<T, other_t>::is_noexcept))+ query_static_constexpr_member<T>::is_noexcept)) {- return traits::query_static_constexpr_member<T, other_t>::value();+ return query_static_constexpr_member<T>::value(); } template <typename E, typename T = decltype(other_t::static_query<E>())>@@ -613,8 +805,19 @@ struct is_applicable_property<T, execution::mapping_t> : integral_constant<bool, execution::is_executor<T>::value- || execution::is_sender<T>::value- || execution::is_scheduler<T>::value>+#if !defined(ASIO_NO_DEPRECATED)+ || conditional<+ execution::is_executor<T>::value,+ false_type,+ execution::is_sender<T>+ >::type::value+ || conditional<+ execution::is_executor<T>::value,+ false_type,+ execution::is_scheduler<T>+ >::type::value+#endif // !defined(ASIO_NO_DEPRECATED)+ > { }; @@ -622,8 +825,19 @@ struct is_applicable_property<T, execution::mapping_t::thread_t> : integral_constant<bool, execution::is_executor<T>::value- || execution::is_sender<T>::value- || execution::is_scheduler<T>::value>+#if !defined(ASIO_NO_DEPRECATED)+ || conditional<+ execution::is_executor<T>::value,+ false_type,+ execution::is_sender<T>+ >::type::value+ || conditional<+ execution::is_executor<T>::value,+ false_type,+ execution::is_scheduler<T>+ >::type::value+#endif // !defined(ASIO_NO_DEPRECATED)+ > { }; @@ -631,8 +845,19 @@ struct is_applicable_property<T, execution::mapping_t::new_thread_t> : integral_constant<bool, execution::is_executor<T>::value- || execution::is_sender<T>::value- || execution::is_scheduler<T>::value>+#if !defined(ASIO_NO_DEPRECATED)+ || conditional<+ execution::is_executor<T>::value,+ false_type,+ execution::is_sender<T>+ >::type::value+ || conditional<+ execution::is_executor<T>::value,+ false_type,+ execution::is_scheduler<T>+ >::type::value+#endif // !defined(ASIO_NO_DEPRECATED)+ > { }; @@ -640,8 +865,19 @@ struct is_applicable_property<T, execution::mapping_t::other_t> : integral_constant<bool, execution::is_executor<T>::value- || execution::is_sender<T>::value- || execution::is_scheduler<T>::value>+#if !defined(ASIO_NO_DEPRECATED)+ || conditional<+ execution::is_executor<T>::value,+ false_type,+ execution::is_sender<T>+ >::type::value+ || conditional<+ execution::is_executor<T>::value,+ false_type,+ execution::is_scheduler<T>+ >::type::value+#endif // !defined(ASIO_NO_DEPRECATED)+ > { }; @@ -701,28 +937,30 @@ template <typename T> struct static_query<T, execution::mapping_t, typename enable_if<- traits::query_static_constexpr_member<T,- execution::mapping_t>::is_valid+ execution::detail::mapping_t<0>::+ query_static_constexpr_member<T>::is_valid >::type> { ASIO_STATIC_CONSTEXPR(bool, is_valid = true); ASIO_STATIC_CONSTEXPR(bool, is_noexcept = true); - typedef typename traits::query_static_constexpr_member<T,- execution::mapping_t>::result_type result_type;+ typedef typename execution::detail::mapping_t<0>::+ query_static_constexpr_member<T>::result_type result_type; static ASIO_CONSTEXPR result_type value() {- return traits::query_static_constexpr_member<T,- execution::mapping_t>::value();+ return execution::detail::mapping_t<0>::+ query_static_constexpr_member<T>::value(); } }; template <typename T> struct static_query<T, execution::mapping_t, typename enable_if<- !traits::query_static_constexpr_member<T, execution::mapping_t>::is_valid- && !traits::query_member<T, execution::mapping_t>::is_valid+ !execution::detail::mapping_t<0>::+ query_static_constexpr_member<T>::is_valid+ && !execution::detail::mapping_t<0>::+ query_member<T>::is_valid && traits::static_query<T, execution::mapping_t::thread_t>::is_valid >::type> {@@ -741,8 +979,10 @@ template <typename T> struct static_query<T, execution::mapping_t, typename enable_if<- !traits::query_static_constexpr_member<T, execution::mapping_t>::is_valid- && !traits::query_member<T, execution::mapping_t>::is_valid+ !execution::detail::mapping_t<0>::+ query_static_constexpr_member<T>::is_valid+ && !execution::detail::mapping_t<0>::+ query_member<T>::is_valid && !traits::static_query<T, execution::mapping_t::thread_t>::is_valid && traits::static_query<T, execution::mapping_t::new_thread_t>::is_valid >::type>@@ -762,8 +1002,10 @@ template <typename T> struct static_query<T, execution::mapping_t, typename enable_if<- !traits::query_static_constexpr_member<T, execution::mapping_t>::is_valid- && !traits::query_member<T, execution::mapping_t>::is_valid+ !execution::detail::mapping_t<0>::+ query_static_constexpr_member<T>::is_valid+ && !execution::detail::mapping_t<0>::+ query_member<T>::is_valid && !traits::static_query<T, execution::mapping_t::thread_t>::is_valid && !traits::static_query<T, execution::mapping_t::new_thread_t>::is_valid && traits::static_query<T, execution::mapping_t::other_t>::is_valid@@ -784,29 +1026,30 @@ template <typename T> struct static_query<T, execution::mapping_t::thread_t, typename enable_if<- traits::query_static_constexpr_member<T,- execution::mapping_t::thread_t>::is_valid+ execution::detail::mapping::thread_t<0>::+ query_static_constexpr_member<T>::is_valid >::type> { ASIO_STATIC_CONSTEXPR(bool, is_valid = true); ASIO_STATIC_CONSTEXPR(bool, is_noexcept = true); - typedef typename traits::query_static_constexpr_member<T,- execution::mapping_t::thread_t>::result_type result_type;+ typedef typename execution::detail::mapping::thread_t<0>::+ query_static_constexpr_member<T>::result_type result_type; static ASIO_CONSTEXPR result_type value() {- return traits::query_static_constexpr_member<T,- execution::mapping_t::thread_t>::value();+ return execution::detail::mapping::thread_t<0>::+ query_static_constexpr_member<T>::value(); } }; template <typename T> struct static_query<T, execution::mapping_t::thread_t, typename enable_if<- !traits::query_static_constexpr_member<T,- execution::mapping_t::thread_t>::is_valid- && !traits::query_member<T, execution::mapping_t::thread_t>::is_valid+ !execution::detail::mapping::thread_t<0>::+ query_static_constexpr_member<T>::is_valid+ && !execution::detail::mapping::thread_t<0>::+ query_member<T>::is_valid && !traits::query_free<T, execution::mapping_t::thread_t>::is_valid && !can_query<T, execution::mapping_t::new_thread_t>::value && !can_query<T, execution::mapping_t::other_t>::value@@ -826,40 +1069,40 @@ template <typename T> struct static_query<T, execution::mapping_t::new_thread_t, typename enable_if<- traits::query_static_constexpr_member<T,- execution::mapping_t::new_thread_t>::is_valid+ execution::detail::mapping::new_thread_t<0>::+ query_static_constexpr_member<T>::is_valid >::type> { ASIO_STATIC_CONSTEXPR(bool, is_valid = true); ASIO_STATIC_CONSTEXPR(bool, is_noexcept = true); - typedef typename traits::query_static_constexpr_member<T,- execution::mapping_t::new_thread_t>::result_type result_type;+ typedef typename execution::detail::mapping::new_thread_t<0>::+ query_static_constexpr_member<T>::result_type result_type; static ASIO_CONSTEXPR result_type value() {- return traits::query_static_constexpr_member<T,- execution::mapping_t::new_thread_t>::value();+ return execution::detail::mapping::new_thread_t<0>::+ query_static_constexpr_member<T>::value(); } }; template <typename T> struct static_query<T, execution::mapping_t::other_t, typename enable_if<- traits::query_static_constexpr_member<T,- execution::mapping_t::other_t>::is_valid+ execution::detail::mapping::other_t<0>::+ query_static_constexpr_member<T>::is_valid >::type> { ASIO_STATIC_CONSTEXPR(bool, is_valid = true); ASIO_STATIC_CONSTEXPR(bool, is_noexcept = true); - typedef typename traits::query_static_constexpr_member<T,- execution::mapping_t::other_t>::result_type result_type;+ typedef typename execution::detail::mapping::other_t<0>::+ query_static_constexpr_member<T>::result_type result_type; static ASIO_CONSTEXPR result_type value() {- return traits::query_static_constexpr_member<T,- execution::mapping_t::other_t>::value();+ return execution::detail::mapping::other_t<0>::+ query_static_constexpr_member<T>::value(); } };
link/modules/asio-standalone/asio/include/asio/execution/occupancy.hpp view
@@ -2,7 +2,7 @@ // execution/occupancy.hpp // ~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -65,10 +65,28 @@ struct occupancy_t { #if defined(ASIO_HAS_VARIABLE_TEMPLATES)+# if defined(ASIO_NO_DEPRECATED) template <typename T> ASIO_STATIC_CONSTEXPR(bool,- is_applicable_property_v = is_executor<T>::value- || is_sender<T>::value || is_scheduler<T>::value);+ is_applicable_property_v = (+ is_executor<T>::value));+# else // defined(ASIO_NO_DEPRECATED)+ template <typename T>+ ASIO_STATIC_CONSTEXPR(bool,+ is_applicable_property_v = (+ is_executor<T>::value+ || conditional<+ is_executor<T>::value,+ false_type,+ is_sender<T>+ >::type::value+ || conditional<+ is_executor<T>::value,+ false_type,+ is_scheduler<T>+ >::type::value+ ));+# endif // defined(ASIO_NO_DEPRECATED) #endif // defined(ASIO_HAS_VARIABLE_TEMPLATES) ASIO_STATIC_CONSTEXPR(bool, is_requirable = false);@@ -79,16 +97,46 @@ { } + template <typename T>+ struct static_proxy+ {+#if defined(ASIO_HAS_DEDUCED_QUERY_STATIC_CONSTEXPR_MEMBER_TRAIT)+ struct type+ {+ template <typename P>+ static constexpr auto query(ASIO_MOVE_ARG(P) p)+ noexcept(+ noexcept(+ conditional<true, T, P>::type::query(ASIO_MOVE_CAST(P)(p))+ )+ )+ -> decltype(+ conditional<true, T, P>::type::query(ASIO_MOVE_CAST(P)(p))+ )+ {+ return T::query(ASIO_MOVE_CAST(P)(p));+ }+ };+#else // defined(ASIO_HAS_DEDUCED_QUERY_STATIC_CONSTEXPR_MEMBER_TRAIT)+ typedef T type;+#endif // defined(ASIO_HAS_DEDUCED_QUERY_STATIC_CONSTEXPR_MEMBER_TRAIT)+ };++ template <typename T>+ struct query_static_constexpr_member :+ traits::query_static_constexpr_member<+ typename static_proxy<T>::type, occupancy_t> {};+ #if defined(ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT) \ && defined(ASIO_HAS_SFINAE_VARIABLE_TEMPLATES) template <typename T> static ASIO_CONSTEXPR- typename traits::query_static_constexpr_member<T, occupancy_t>::result_type+ typename query_static_constexpr_member<T>::result_type static_query() ASIO_NOEXCEPT_IF((- traits::query_static_constexpr_member<T, occupancy_t>::is_noexcept))+ query_static_constexpr_member<T>::is_noexcept)) {- return traits::query_static_constexpr_member<T, occupancy_t>::value();+ return query_static_constexpr_member<T>::value(); } template <typename E, typename T = decltype(occupancy_t::static_query<E>())>@@ -132,8 +180,19 @@ struct is_applicable_property<T, execution::occupancy_t> : integral_constant<bool, execution::is_executor<T>::value- || execution::is_sender<T>::value- || execution::is_scheduler<T>::value>+#if !defined(ASIO_NO_DEPRECATED)+ || conditional<+ execution::is_executor<T>::value,+ false_type,+ execution::is_sender<T>+ >::type::value+ || conditional<+ execution::is_executor<T>::value,+ false_type,+ execution::is_scheduler<T>+ >::type::value+#endif // !defined(ASIO_NO_DEPRECATED)+ > { }; @@ -147,20 +206,20 @@ template <typename T> struct static_query<T, execution::occupancy_t, typename enable_if<- traits::query_static_constexpr_member<T,- execution::occupancy_t>::is_valid+ execution::detail::occupancy_t<0>::+ query_static_constexpr_member<T>::is_valid >::type> { ASIO_STATIC_CONSTEXPR(bool, is_valid = true); ASIO_STATIC_CONSTEXPR(bool, is_noexcept = true); - typedef typename traits::query_static_constexpr_member<T,- execution::occupancy_t>::result_type result_type;+ typedef typename execution::detail::occupancy_t<0>::+ query_static_constexpr_member<T>::result_type result_type; static ASIO_CONSTEXPR result_type value() {- return traits::query_static_constexpr_member<T,- execution::occupancy_t>::value();+ return execution::detail::occupancy_t<0>::+ query_static_constexpr_member<T>::value(); } };
link/modules/asio-standalone/asio/include/asio/execution/operation_state.hpp view
@@ -2,7 +2,7 @@ // execution/operation_state.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -16,6 +16,9 @@ #endif // defined(_MSC_VER) && (_MSC_VER >= 1200) #include "asio/detail/config.hpp"++#if !defined(ASIO_NO_DEPRECATED)+ #include "asio/detail/type_traits.hpp" #include "asio/execution/start.hpp" @@ -90,5 +93,7 @@ } // namespace asio #include "asio/detail/pop_options.hpp"++#endif // !defined(ASIO_NO_DEPRECATED) #endif // ASIO_EXECUTION_OPERATION_STATE_HPP
link/modules/asio-standalone/asio/include/asio/execution/outstanding_work.hpp view
@@ -2,7 +2,7 @@ // execution/outstanding_work.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -158,10 +158,28 @@ struct outstanding_work_t { #if defined(ASIO_HAS_VARIABLE_TEMPLATES)+# if defined(ASIO_NO_DEPRECATED) template <typename T> ASIO_STATIC_CONSTEXPR(bool,- is_applicable_property_v = is_executor<T>::value- || is_sender<T>::value || is_scheduler<T>::value);+ is_applicable_property_v = (+ is_executor<T>::value));+# else // defined(ASIO_NO_DEPRECATED)+ template <typename T>+ ASIO_STATIC_CONSTEXPR(bool,+ is_applicable_property_v = (+ is_executor<T>::value+ || conditional<+ is_executor<T>::value,+ false_type,+ is_sender<T>+ >::type::value+ || conditional<+ is_executor<T>::value,+ false_type,+ is_scheduler<T>+ >::type::value+ ));+# endif // defined(ASIO_NO_DEPRECATED) #endif // defined(ASIO_HAS_VARIABLE_TEMPLATES) ASIO_STATIC_CONSTEXPR(bool, is_requirable = false);@@ -186,20 +204,74 @@ { } + template <typename T>+ struct proxy+ {+#if defined(ASIO_HAS_DEDUCED_QUERY_MEMBER_TRAIT)+ struct type+ {+ template <typename P>+ auto query(ASIO_MOVE_ARG(P) p) const+ noexcept(+ noexcept(+ declval<typename conditional<true, T, P>::type>().query(+ ASIO_MOVE_CAST(P)(p))+ )+ )+ -> decltype(+ declval<typename conditional<true, T, P>::type>().query(+ ASIO_MOVE_CAST(P)(p))+ );+ };+#else // defined(ASIO_HAS_DEDUCED_QUERY_MEMBER_TRAIT)+ typedef T type;+#endif // defined(ASIO_HAS_DEDUCED_QUERY_MEMBER_TRAIT)+ };++ template <typename T>+ struct static_proxy+ {+#if defined(ASIO_HAS_DEDUCED_QUERY_STATIC_CONSTEXPR_MEMBER_TRAIT)+ struct type+ {+ template <typename P>+ static constexpr auto query(ASIO_MOVE_ARG(P) p)+ noexcept(+ noexcept(+ conditional<true, T, P>::type::query(ASIO_MOVE_CAST(P)(p))+ )+ )+ -> decltype(+ conditional<true, T, P>::type::query(ASIO_MOVE_CAST(P)(p))+ )+ {+ return T::query(ASIO_MOVE_CAST(P)(p));+ }+ };+#else // defined(ASIO_HAS_DEDUCED_QUERY_STATIC_CONSTEXPR_MEMBER_TRAIT)+ typedef T type;+#endif // defined(ASIO_HAS_DEDUCED_QUERY_STATIC_CONSTEXPR_MEMBER_TRAIT)+ };++ template <typename T>+ struct query_member :+ traits::query_member<typename proxy<T>::type, outstanding_work_t> {};++ template <typename T>+ struct query_static_constexpr_member :+ traits::query_static_constexpr_member<+ typename static_proxy<T>::type, outstanding_work_t> {};+ #if defined(ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT) \ && defined(ASIO_HAS_SFINAE_VARIABLE_TEMPLATES) template <typename T> static ASIO_CONSTEXPR- typename traits::query_static_constexpr_member<- T, outstanding_work_t>::result_type+ typename query_static_constexpr_member<T>::result_type static_query() ASIO_NOEXCEPT_IF((- traits::query_static_constexpr_member<- T, outstanding_work_t- >::is_noexcept))+ query_static_constexpr_member<T>::is_noexcept)) {- return traits::query_static_constexpr_member<- T, outstanding_work_t>::value();+ return query_static_constexpr_member<T>::value(); } template <typename T>@@ -207,10 +279,13 @@ typename traits::static_query<T, untracked_t>::result_type static_query( typename enable_if<- !traits::query_static_constexpr_member<- T, outstanding_work_t>::is_valid- && !traits::query_member<T, outstanding_work_t>::is_valid- && traits::static_query<T, untracked_t>::is_valid+ !query_static_constexpr_member<T>::is_valid+ >::type* = 0,+ typename enable_if<+ !query_member<T>::is_valid+ >::type* = 0,+ typename enable_if<+ traits::static_query<T, untracked_t>::is_valid >::type* = 0) ASIO_NOEXCEPT { return traits::static_query<T, untracked_t>::value();@@ -221,11 +296,16 @@ typename traits::static_query<T, tracked_t>::result_type static_query( typename enable_if<- !traits::query_static_constexpr_member<- T, outstanding_work_t>::is_valid- && !traits::query_member<T, outstanding_work_t>::is_valid- && !traits::static_query<T, untracked_t>::is_valid- && traits::static_query<T, tracked_t>::is_valid+ !query_static_constexpr_member<T>::is_valid+ >::type* = 0,+ typename enable_if<+ !query_member<T>::is_valid+ >::type* = 0,+ typename enable_if<+ !traits::static_query<T, untracked_t>::is_valid+ >::type* = 0,+ typename enable_if<+ traits::static_query<T, tracked_t>::is_valid >::type* = 0) ASIO_NOEXCEPT { return traits::static_query<T, tracked_t>::value();@@ -282,7 +362,9 @@ const Executor& ex, convertible_from_outstanding_work_t, typename enable_if< !can_query<const Executor&, untracked_t>::value- && can_query<const Executor&, tracked_t>::value+ >::type* = 0,+ typename enable_if<+ can_query<const Executor&, tracked_t>::value >::type* = 0) #if !defined(__clang__) // Clang crashes if noexcept is used here. #if defined(ASIO_MSVC) // Visual C++ wants the type to be qualified.@@ -335,10 +417,28 @@ struct untracked_t { #if defined(ASIO_HAS_VARIABLE_TEMPLATES)+# if defined(ASIO_NO_DEPRECATED) template <typename T> ASIO_STATIC_CONSTEXPR(bool,- is_applicable_property_v = is_executor<T>::value- || is_sender<T>::value || is_scheduler<T>::value);+ is_applicable_property_v = (+ is_executor<T>::value));+# else // defined(ASIO_NO_DEPRECATED)+ template <typename T>+ ASIO_STATIC_CONSTEXPR(bool,+ is_applicable_property_v = (+ is_executor<T>::value+ || conditional<+ is_executor<T>::value,+ false_type,+ is_sender<T>+ >::type::value+ || conditional<+ is_executor<T>::value,+ false_type,+ is_scheduler<T>+ >::type::value+ ));+# endif // defined(ASIO_NO_DEPRECATED) #endif // defined(ASIO_HAS_VARIABLE_TEMPLATES) ASIO_STATIC_CONSTEXPR(bool, is_requirable = true);@@ -349,25 +449,42 @@ { } + template <typename T>+ struct query_member :+ traits::query_member<+ typename outstanding_work_t<I>::template proxy<T>::type, untracked_t> {};++ template <typename T>+ struct query_static_constexpr_member :+ traits::query_static_constexpr_member<+ typename outstanding_work_t<I>::template static_proxy<T>::type,+ untracked_t> {};+ #if defined(ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT) \ && defined(ASIO_HAS_SFINAE_VARIABLE_TEMPLATES) template <typename T> static ASIO_CONSTEXPR- typename traits::query_static_constexpr_member<T, untracked_t>::result_type+ typename query_static_constexpr_member<T>::result_type static_query() ASIO_NOEXCEPT_IF((- traits::query_static_constexpr_member<T, untracked_t>::is_noexcept))+ query_static_constexpr_member<T>::is_noexcept)) {- return traits::query_static_constexpr_member<T, untracked_t>::value();+ return query_static_constexpr_member<T>::value(); } template <typename T> static ASIO_CONSTEXPR untracked_t static_query( typename enable_if<- !traits::query_static_constexpr_member<T, untracked_t>::is_valid- && !traits::query_member<T, untracked_t>::is_valid- && !traits::query_free<T, untracked_t>::is_valid- && !can_query<T, tracked_t<I> >::value+ !query_static_constexpr_member<T>::is_valid+ >::type* = 0,+ typename enable_if<+ !query_member<T>::is_valid+ >::type* = 0,+ typename enable_if<+ !traits::query_free<T, untracked_t>::is_valid+ >::type* = 0,+ typename enable_if<+ !can_query<T, tracked_t<I> >::value >::type* = 0) ASIO_NOEXCEPT { return untracked_t();@@ -408,10 +525,28 @@ struct tracked_t { #if defined(ASIO_HAS_VARIABLE_TEMPLATES)+# if defined(ASIO_NO_DEPRECATED) template <typename T> ASIO_STATIC_CONSTEXPR(bool,- is_applicable_property_v = is_executor<T>::value- || is_sender<T>::value || is_scheduler<T>::value);+ is_applicable_property_v = (+ is_executor<T>::value));+# else // defined(ASIO_NO_DEPRECATED)+ template <typename T>+ ASIO_STATIC_CONSTEXPR(bool,+ is_applicable_property_v = (+ is_executor<T>::value+ || conditional<+ is_executor<T>::value,+ false_type,+ is_sender<T>+ >::type::value+ || conditional<+ is_executor<T>::value,+ false_type,+ is_scheduler<T>+ >::type::value+ ));+# endif // defined(ASIO_NO_DEPRECATED) #endif // defined(ASIO_HAS_VARIABLE_TEMPLATES) ASIO_STATIC_CONSTEXPR(bool, is_requirable = true);@@ -422,16 +557,27 @@ { } + template <typename T>+ struct query_member :+ traits::query_member<+ typename outstanding_work_t<I>::template proxy<T>::type, tracked_t> {};++ template <typename T>+ struct query_static_constexpr_member :+ traits::query_static_constexpr_member<+ typename outstanding_work_t<I>::template static_proxy<T>::type,+ tracked_t> {};+ #if defined(ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT) \ && defined(ASIO_HAS_SFINAE_VARIABLE_TEMPLATES) template <typename T> static ASIO_CONSTEXPR- typename traits::query_static_constexpr_member<T, tracked_t>::result_type+ typename query_static_constexpr_member<T>::result_type static_query() ASIO_NOEXCEPT_IF((- traits::query_static_constexpr_member<T, tracked_t>::is_noexcept))+ query_static_constexpr_member<T>::is_noexcept)) {- return traits::query_static_constexpr_member<T, tracked_t>::value();+ return query_static_constexpr_member<T>::value(); } template <typename E, typename T = decltype(tracked_t::static_query<E>())>@@ -485,8 +631,19 @@ struct is_applicable_property<T, execution::outstanding_work_t> : integral_constant<bool, execution::is_executor<T>::value- || execution::is_sender<T>::value- || execution::is_scheduler<T>::value>+#if !defined(ASIO_NO_DEPRECATED)+ || conditional<+ execution::is_executor<T>::value,+ false_type,+ execution::is_sender<T>+ >::type::value+ || conditional<+ execution::is_executor<T>::value,+ false_type,+ execution::is_scheduler<T>+ >::type::value+#endif // !defined(ASIO_NO_DEPRECATED)+ > { }; @@ -494,8 +651,19 @@ struct is_applicable_property<T, execution::outstanding_work_t::untracked_t> : integral_constant<bool, execution::is_executor<T>::value- || execution::is_sender<T>::value- || execution::is_scheduler<T>::value>+#if !defined(ASIO_NO_DEPRECATED)+ || conditional<+ execution::is_executor<T>::value,+ false_type,+ execution::is_sender<T>+ >::type::value+ || conditional<+ execution::is_executor<T>::value,+ false_type,+ execution::is_scheduler<T>+ >::type::value+#endif // !defined(ASIO_NO_DEPRECATED)+ > { }; @@ -503,8 +671,19 @@ struct is_applicable_property<T, execution::outstanding_work_t::tracked_t> : integral_constant<bool, execution::is_executor<T>::value- || execution::is_sender<T>::value- || execution::is_scheduler<T>::value>+#if !defined(ASIO_NO_DEPRECATED)+ || conditional<+ execution::is_executor<T>::value,+ false_type,+ execution::is_sender<T>+ >::type::value+ || conditional<+ execution::is_executor<T>::value,+ false_type,+ execution::is_scheduler<T>+ >::type::value+#endif // !defined(ASIO_NO_DEPRECATED)+ > { }; @@ -549,30 +728,30 @@ template <typename T> struct static_query<T, execution::outstanding_work_t, typename enable_if<- traits::query_static_constexpr_member<T,- execution::outstanding_work_t>::is_valid+ execution::detail::outstanding_work_t<0>::+ query_static_constexpr_member<T>::is_valid >::type> { ASIO_STATIC_CONSTEXPR(bool, is_valid = true); ASIO_STATIC_CONSTEXPR(bool, is_noexcept = true); - typedef typename traits::query_static_constexpr_member<T,- execution::outstanding_work_t>::result_type result_type;+ typedef typename execution::detail::outstanding_work_t<0>::+ query_static_constexpr_member<T>::result_type result_type; static ASIO_CONSTEXPR result_type value() {- return traits::query_static_constexpr_member<T,- execution::outstanding_work_t>::value();+ return execution::detail::outstanding_work_t<0>::+ query_static_constexpr_member<T>::value(); } }; template <typename T> struct static_query<T, execution::outstanding_work_t, typename enable_if<- !traits::query_static_constexpr_member<T,- execution::outstanding_work_t>::is_valid- && !traits::query_member<T,- execution::outstanding_work_t>::is_valid+ !execution::detail::outstanding_work_t<0>::+ query_static_constexpr_member<T>::is_valid+ && !execution::detail::outstanding_work_t<0>::+ query_member<T>::is_valid && traits::static_query<T, execution::outstanding_work_t::untracked_t>::is_valid >::type>@@ -593,10 +772,10 @@ template <typename T> struct static_query<T, execution::outstanding_work_t, typename enable_if<- !traits::query_static_constexpr_member<T,- execution::outstanding_work_t>::is_valid- && !traits::query_member<T,- execution::outstanding_work_t>::is_valid+ !execution::detail::outstanding_work_t<0>::+ query_static_constexpr_member<T>::is_valid+ && !execution::detail::outstanding_work_t<0>::+ query_member<T>::is_valid && !traits::static_query<T, execution::outstanding_work_t::untracked_t>::is_valid && traits::static_query<T,@@ -619,30 +798,30 @@ template <typename T> struct static_query<T, execution::outstanding_work_t::untracked_t, typename enable_if<- traits::query_static_constexpr_member<T,- execution::outstanding_work_t::untracked_t>::is_valid+ execution::detail::outstanding_work::untracked_t<0>::+ query_static_constexpr_member<T>::is_valid >::type> { ASIO_STATIC_CONSTEXPR(bool, is_valid = true); ASIO_STATIC_CONSTEXPR(bool, is_noexcept = true); - typedef typename traits::query_static_constexpr_member<T,- execution::outstanding_work_t::untracked_t>::result_type result_type;+ typedef typename execution::detail::outstanding_work::untracked_t<0>::+ query_static_constexpr_member<T>::result_type result_type; static ASIO_CONSTEXPR result_type value() {- return traits::query_static_constexpr_member<T,- execution::outstanding_work_t::untracked_t>::value();+ return execution::detail::outstanding_work::untracked_t<0>::+ query_static_constexpr_member<T>::value(); } }; template <typename T> struct static_query<T, execution::outstanding_work_t::untracked_t, typename enable_if<- !traits::query_static_constexpr_member<T,- execution::outstanding_work_t::untracked_t>::is_valid- && !traits::query_member<T,- execution::outstanding_work_t::untracked_t>::is_valid+ !execution::detail::outstanding_work::untracked_t<0>::+ query_static_constexpr_member<T>::is_valid+ && !execution::detail::outstanding_work::untracked_t<0>::+ query_member<T>::is_valid && !traits::query_free<T, execution::outstanding_work_t::untracked_t>::is_valid && !can_query<T, execution::outstanding_work_t::tracked_t>::value@@ -662,20 +841,20 @@ template <typename T> struct static_query<T, execution::outstanding_work_t::tracked_t, typename enable_if<- traits::query_static_constexpr_member<T,- execution::outstanding_work_t::tracked_t>::is_valid+ execution::detail::outstanding_work::tracked_t<0>::+ query_static_constexpr_member<T>::is_valid >::type> { ASIO_STATIC_CONSTEXPR(bool, is_valid = true); ASIO_STATIC_CONSTEXPR(bool, is_noexcept = true); - typedef typename traits::query_static_constexpr_member<T,- execution::outstanding_work_t::tracked_t>::result_type result_type;+ typedef typename execution::detail::outstanding_work::tracked_t<0>::+ query_static_constexpr_member<T>::result_type result_type; static ASIO_CONSTEXPR result_type value() {- return traits::query_static_constexpr_member<T,- execution::outstanding_work_t::tracked_t>::value();+ return execution::detail::outstanding_work::tracked_t<0>::+ query_static_constexpr_member<T>::value(); } };
link/modules/asio-standalone/asio/include/asio/execution/prefer_only.hpp view
@@ -2,7 +2,7 @@ // execution/prefer_only.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -220,7 +220,9 @@ prefer(const Executor& ex, const prefer_only<Property>& p, typename enable_if< is_same<Property, InnerProperty>::value- && can_prefer<const Executor&, const InnerProperty&>::value+ >::type* = 0,+ typename enable_if<+ can_prefer<const Executor&, const InnerProperty&>::value >::type* = 0) #if !defined(ASIO_MSVC) \ && !defined(__clang__) // Clang crashes if noexcept is used here.@@ -238,7 +240,9 @@ query(const Executor& ex, const prefer_only<Property>& p, typename enable_if< is_same<Property, InnerProperty>::value- && can_query<const Executor&, const InnerProperty&>::value+ >::type* = 0,+ typename enable_if<+ can_query<const Executor&, const InnerProperty&>::value >::type* = 0) #if !defined(ASIO_MSVC) \ && !defined(__clang__) // Clang crashes if noexcept is used here.
link/modules/asio-standalone/asio/include/asio/execution/receiver.hpp view
@@ -2,7 +2,7 @@ // execution/receiver.hpp // ~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -16,6 +16,9 @@ #endif // defined(_MSC_VER) && (_MSC_VER >= 1200) #include "asio/detail/config.hpp"++#if !defined(ASIO_NO_DEPRECATED)+ #include "asio/detail/type_traits.hpp" #include "asio/detail/variadic_templates.hpp" #include "asio/execution/set_done.hpp"@@ -276,5 +279,7 @@ } // namespace asio #include "asio/detail/pop_options.hpp"++#endif // !defined(ASIO_NO_DEPRECATED) #endif // ASIO_EXECUTION_RECEIVER_HPP
link/modules/asio-standalone/asio/include/asio/execution/receiver_invocation_error.hpp view
@@ -2,7 +2,7 @@ // execution/receiver_invocation_error.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/execution/relationship.hpp view
@@ -2,7 +2,7 @@ // execution/relationship.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -157,10 +157,28 @@ struct relationship_t { #if defined(ASIO_HAS_VARIABLE_TEMPLATES)+# if defined(ASIO_NO_DEPRECATED) template <typename T> ASIO_STATIC_CONSTEXPR(bool,- is_applicable_property_v = is_executor<T>::value- || is_sender<T>::value || is_scheduler<T>::value);+ is_applicable_property_v = (+ is_executor<T>::value));+# else // defined(ASIO_NO_DEPRECATED)+ template <typename T>+ ASIO_STATIC_CONSTEXPR(bool,+ is_applicable_property_v = (+ is_executor<T>::value+ || conditional<+ is_executor<T>::value,+ false_type,+ is_sender<T>+ >::type::value+ || conditional<+ is_executor<T>::value,+ false_type,+ is_scheduler<T>+ >::type::value+ ));+# endif // defined(ASIO_NO_DEPRECATED) #endif // defined(ASIO_HAS_VARIABLE_TEMPLATES) ASIO_STATIC_CONSTEXPR(bool, is_requirable = false);@@ -185,20 +203,74 @@ { } + template <typename T>+ struct proxy+ {+#if defined(ASIO_HAS_DEDUCED_QUERY_MEMBER_TRAIT)+ struct type+ {+ template <typename P>+ auto query(ASIO_MOVE_ARG(P) p) const+ noexcept(+ noexcept(+ declval<typename conditional<true, T, P>::type>().query(+ ASIO_MOVE_CAST(P)(p))+ )+ )+ -> decltype(+ declval<typename conditional<true, T, P>::type>().query(+ ASIO_MOVE_CAST(P)(p))+ );+ };+#else // defined(ASIO_HAS_DEDUCED_QUERY_MEMBER_TRAIT)+ typedef T type;+#endif // defined(ASIO_HAS_DEDUCED_QUERY_MEMBER_TRAIT)+ };++ template <typename T>+ struct static_proxy+ {+#if defined(ASIO_HAS_DEDUCED_QUERY_STATIC_CONSTEXPR_MEMBER_TRAIT)+ struct type+ {+ template <typename P>+ static constexpr auto query(ASIO_MOVE_ARG(P) p)+ noexcept(+ noexcept(+ conditional<true, T, P>::type::query(ASIO_MOVE_CAST(P)(p))+ )+ )+ -> decltype(+ conditional<true, T, P>::type::query(ASIO_MOVE_CAST(P)(p))+ )+ {+ return T::query(ASIO_MOVE_CAST(P)(p));+ }+ };+#else // defined(ASIO_HAS_DEDUCED_QUERY_STATIC_CONSTEXPR_MEMBER_TRAIT)+ typedef T type;+#endif // defined(ASIO_HAS_DEDUCED_QUERY_STATIC_CONSTEXPR_MEMBER_TRAIT)+ };++ template <typename T>+ struct query_member :+ traits::query_member<typename proxy<T>::type, relationship_t> {};++ template <typename T>+ struct query_static_constexpr_member :+ traits::query_static_constexpr_member<+ typename static_proxy<T>::type, relationship_t> {};+ #if defined(ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT) \ && defined(ASIO_HAS_SFINAE_VARIABLE_TEMPLATES) template <typename T> static ASIO_CONSTEXPR- typename traits::query_static_constexpr_member<- T, relationship_t>::result_type+ typename query_static_constexpr_member<T>::result_type static_query() ASIO_NOEXCEPT_IF((- traits::query_static_constexpr_member<- T, relationship_t- >::is_noexcept))+ query_static_constexpr_member<T>::is_noexcept)) {- return traits::query_static_constexpr_member<- T, relationship_t>::value();+ return query_static_constexpr_member<T>::value(); } template <typename T>@@ -206,10 +278,13 @@ typename traits::static_query<T, fork_t>::result_type static_query( typename enable_if<- !traits::query_static_constexpr_member<- T, relationship_t>::is_valid- && !traits::query_member<T, relationship_t>::is_valid- && traits::static_query<T, fork_t>::is_valid+ !query_static_constexpr_member<T>::is_valid+ >::type* = 0,+ typename enable_if<+ !query_member<T>::is_valid+ >::type* = 0,+ typename enable_if<+ traits::static_query<T, fork_t>::is_valid >::type* = 0) ASIO_NOEXCEPT { return traits::static_query<T, fork_t>::value();@@ -220,11 +295,16 @@ typename traits::static_query<T, continuation_t>::result_type static_query( typename enable_if<- !traits::query_static_constexpr_member<- T, relationship_t>::is_valid- && !traits::query_member<T, relationship_t>::is_valid- && !traits::static_query<T, fork_t>::is_valid- && traits::static_query<T, continuation_t>::is_valid+ !query_static_constexpr_member<T>::is_valid+ >::type* = 0,+ typename enable_if<+ !query_member<T>::is_valid+ >::type* = 0,+ typename enable_if<+ !traits::static_query<T, fork_t>::is_valid+ >::type* = 0,+ typename enable_if<+ traits::static_query<T, continuation_t>::is_valid >::type* = 0) ASIO_NOEXCEPT { return traits::static_query<T, continuation_t>::value();@@ -280,7 +360,9 @@ const Executor& ex, convertible_from_relationship_t, typename enable_if< !can_query<const Executor&, fork_t>::value- && can_query<const Executor&, continuation_t>::value+ >::type* = 0,+ typename enable_if<+ can_query<const Executor&, continuation_t>::value >::type* = 0) #if !defined(__clang__) // Clang crashes if noexcept is used here. #if defined(ASIO_MSVC) // Visual C++ wants the type to be qualified.@@ -333,10 +415,28 @@ struct fork_t { #if defined(ASIO_HAS_VARIABLE_TEMPLATES)+# if defined(ASIO_NO_DEPRECATED) template <typename T> ASIO_STATIC_CONSTEXPR(bool,- is_applicable_property_v = is_executor<T>::value- || is_sender<T>::value || is_scheduler<T>::value);+ is_applicable_property_v = (+ is_executor<T>::value));+# else // defined(ASIO_NO_DEPRECATED)+ template <typename T>+ ASIO_STATIC_CONSTEXPR(bool,+ is_applicable_property_v = (+ is_executor<T>::value+ || conditional<+ is_executor<T>::value,+ false_type,+ is_sender<T>+ >::type::value+ || conditional<+ is_executor<T>::value,+ false_type,+ is_scheduler<T>+ >::type::value+ ));+# endif // defined(ASIO_NO_DEPRECATED) #endif // defined(ASIO_HAS_VARIABLE_TEMPLATES) ASIO_STATIC_CONSTEXPR(bool, is_requirable = true);@@ -347,25 +447,41 @@ { } + template <typename T>+ struct query_member :+ traits::query_member<+ typename relationship_t<I>::template proxy<T>::type, fork_t> {};++ template <typename T>+ struct query_static_constexpr_member :+ traits::query_static_constexpr_member<+ typename relationship_t<I>::template static_proxy<T>::type, fork_t> {};+ #if defined(ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT) \ && defined(ASIO_HAS_SFINAE_VARIABLE_TEMPLATES) template <typename T> static ASIO_CONSTEXPR- typename traits::query_static_constexpr_member<T, fork_t>::result_type+ typename query_static_constexpr_member<T>::result_type static_query() ASIO_NOEXCEPT_IF((- traits::query_static_constexpr_member<T, fork_t>::is_noexcept))+ query_static_constexpr_member<T>::is_noexcept)) {- return traits::query_static_constexpr_member<T, fork_t>::value();+ return query_static_constexpr_member<T>::value(); } template <typename T> static ASIO_CONSTEXPR fork_t static_query( typename enable_if<- !traits::query_static_constexpr_member<T, fork_t>::is_valid- && !traits::query_member<T, fork_t>::is_valid- && !traits::query_free<T, fork_t>::is_valid- && !can_query<T, continuation_t<I> >::value+ !query_static_constexpr_member<T>::is_valid+ >::type* = 0,+ typename enable_if<+ !query_member<T>::is_valid+ >::type* = 0,+ typename enable_if<+ !traits::query_free<T, fork_t>::is_valid+ >::type* = 0,+ typename enable_if<+ !can_query<T, continuation_t<I> >::value >::type* = 0) ASIO_NOEXCEPT { return fork_t();@@ -406,10 +522,28 @@ struct continuation_t { #if defined(ASIO_HAS_VARIABLE_TEMPLATES)+# if defined(ASIO_NO_DEPRECATED) template <typename T> ASIO_STATIC_CONSTEXPR(bool,- is_applicable_property_v = is_executor<T>::value- || is_sender<T>::value || is_scheduler<T>::value);+ is_applicable_property_v = (+ is_executor<T>::value));+# else // defined(ASIO_NO_DEPRECATED)+ template <typename T>+ ASIO_STATIC_CONSTEXPR(bool,+ is_applicable_property_v = (+ is_executor<T>::value+ || conditional<+ is_executor<T>::value,+ false_type,+ is_sender<T>+ >::type::value+ || conditional<+ is_executor<T>::value,+ false_type,+ is_scheduler<T>+ >::type::value+ ));+# endif // defined(ASIO_NO_DEPRECATED) #endif // defined(ASIO_HAS_VARIABLE_TEMPLATES) ASIO_STATIC_CONSTEXPR(bool, is_requirable = true);@@ -420,16 +554,27 @@ { } + template <typename T>+ struct query_member :+ traits::query_member<+ typename relationship_t<I>::template proxy<T>::type, continuation_t> {};++ template <typename T>+ struct query_static_constexpr_member :+ traits::query_static_constexpr_member<+ typename relationship_t<I>::template static_proxy<T>::type,+ continuation_t> {};+ #if defined(ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT) \ && defined(ASIO_HAS_SFINAE_VARIABLE_TEMPLATES) template <typename T> static ASIO_CONSTEXPR- typename traits::query_static_constexpr_member<T, continuation_t>::result_type+ typename query_static_constexpr_member<T>::result_type static_query() ASIO_NOEXCEPT_IF((- traits::query_static_constexpr_member<T, continuation_t>::is_noexcept))+ query_static_constexpr_member<T>::is_noexcept)) {- return traits::query_static_constexpr_member<T, continuation_t>::value();+ return query_static_constexpr_member<T>::value(); } template <typename E,@@ -484,8 +629,19 @@ struct is_applicable_property<T, execution::relationship_t> : integral_constant<bool, execution::is_executor<T>::value- || execution::is_sender<T>::value- || execution::is_scheduler<T>::value>+#if !defined(ASIO_NO_DEPRECATED)+ || conditional<+ execution::is_executor<T>::value,+ false_type,+ execution::is_sender<T>+ >::type::value+ || conditional<+ execution::is_executor<T>::value,+ false_type,+ execution::is_scheduler<T>+ >::type::value+#endif // !defined(ASIO_NO_DEPRECATED)+ > { }; @@ -493,8 +649,19 @@ struct is_applicable_property<T, execution::relationship_t::fork_t> : integral_constant<bool, execution::is_executor<T>::value- || execution::is_sender<T>::value- || execution::is_scheduler<T>::value>+#if !defined(ASIO_NO_DEPRECATED)+ || conditional<+ execution::is_executor<T>::value,+ false_type,+ execution::is_sender<T>+ >::type::value+ || conditional<+ execution::is_executor<T>::value,+ false_type,+ execution::is_scheduler<T>+ >::type::value+#endif // !defined(ASIO_NO_DEPRECATED)+ > { }; @@ -502,8 +669,19 @@ struct is_applicable_property<T, execution::relationship_t::continuation_t> : integral_constant<bool, execution::is_executor<T>::value- || execution::is_sender<T>::value- || execution::is_scheduler<T>::value>+#if !defined(ASIO_NO_DEPRECATED)+ || conditional<+ execution::is_executor<T>::value,+ false_type,+ execution::is_sender<T>+ >::type::value+ || conditional<+ execution::is_executor<T>::value,+ false_type,+ execution::is_scheduler<T>+ >::type::value+#endif // !defined(ASIO_NO_DEPRECATED)+ > { }; @@ -548,30 +726,30 @@ template <typename T> struct static_query<T, execution::relationship_t, typename enable_if<- traits::query_static_constexpr_member<T,- execution::relationship_t>::is_valid+ execution::detail::relationship_t<0>::+ query_static_constexpr_member<T>::is_valid >::type> { ASIO_STATIC_CONSTEXPR(bool, is_valid = true); ASIO_STATIC_CONSTEXPR(bool, is_noexcept = true); - typedef typename traits::query_static_constexpr_member<T,- execution::relationship_t>::result_type result_type;+ typedef typename execution::detail::relationship_t<0>::+ query_static_constexpr_member<T>::result_type result_type; static ASIO_CONSTEXPR result_type value() {- return traits::query_static_constexpr_member<T,- execution::relationship_t>::value();+ return execution::detail::relationship_t<0>::+ query_static_constexpr_member<T>::value(); } }; template <typename T> struct static_query<T, execution::relationship_t, typename enable_if<- !traits::query_static_constexpr_member<T,- execution::relationship_t>::is_valid- && !traits::query_member<T,- execution::relationship_t>::is_valid+ !execution::detail::relationship_t<0>::+ query_static_constexpr_member<T>::is_valid+ && !execution::detail::relationship_t<0>::+ query_member<T>::is_valid && traits::static_query<T, execution::relationship_t::fork_t>::is_valid >::type>@@ -592,10 +770,10 @@ template <typename T> struct static_query<T, execution::relationship_t, typename enable_if<- !traits::query_static_constexpr_member<T,- execution::relationship_t>::is_valid- && !traits::query_member<T,- execution::relationship_t>::is_valid+ !execution::detail::relationship_t<0>::+ query_static_constexpr_member<T>::is_valid+ && !execution::detail::relationship_t<0>::+ query_member<T>::is_valid && !traits::static_query<T, execution::relationship_t::fork_t>::is_valid && traits::static_query<T,@@ -618,30 +796,30 @@ template <typename T> struct static_query<T, execution::relationship_t::fork_t, typename enable_if<- traits::query_static_constexpr_member<T,- execution::relationship_t::fork_t>::is_valid+ execution::detail::relationship::fork_t<0>::+ query_static_constexpr_member<T>::is_valid >::type> { ASIO_STATIC_CONSTEXPR(bool, is_valid = true); ASIO_STATIC_CONSTEXPR(bool, is_noexcept = true); - typedef typename traits::query_static_constexpr_member<T,- execution::relationship_t::fork_t>::result_type result_type;+ typedef typename execution::detail::relationship::fork_t<0>::+ query_static_constexpr_member<T>::result_type result_type; static ASIO_CONSTEXPR result_type value() {- return traits::query_static_constexpr_member<T,- execution::relationship_t::fork_t>::value();+ return execution::detail::relationship::fork_t<0>::+ query_static_constexpr_member<T>::value(); } }; template <typename T> struct static_query<T, execution::relationship_t::fork_t, typename enable_if<- !traits::query_static_constexpr_member<T,- execution::relationship_t::fork_t>::is_valid- && !traits::query_member<T,- execution::relationship_t::fork_t>::is_valid+ !execution::detail::relationship::fork_t<0>::+ query_static_constexpr_member<T>::is_valid+ && !execution::detail::relationship::fork_t<0>::+ query_member<T>::is_valid && !traits::query_free<T, execution::relationship_t::fork_t>::is_valid && !can_query<T, execution::relationship_t::continuation_t>::value@@ -661,20 +839,20 @@ template <typename T> struct static_query<T, execution::relationship_t::continuation_t, typename enable_if<- traits::query_static_constexpr_member<T,- execution::relationship_t::continuation_t>::is_valid+ execution::detail::relationship::continuation_t<0>::+ query_static_constexpr_member<T>::is_valid >::type> { ASIO_STATIC_CONSTEXPR(bool, is_valid = true); ASIO_STATIC_CONSTEXPR(bool, is_noexcept = true); - typedef typename traits::query_static_constexpr_member<T,- execution::relationship_t::continuation_t>::result_type result_type;+ typedef typename execution::detail::relationship::continuation_t<0>::+ query_static_constexpr_member<T>::result_type result_type; static ASIO_CONSTEXPR result_type value() {- return traits::query_static_constexpr_member<T,- execution::relationship_t::continuation_t>::value();+ return execution::detail::relationship::continuation_t<0>::+ query_static_constexpr_member<T>::value(); } };
link/modules/asio-standalone/asio/include/asio/execution/schedule.hpp view
@@ -2,7 +2,7 @@ // execution/schedule.hpp // ~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -16,6 +16,9 @@ #endif // defined(_MSC_VER) && (_MSC_VER >= 1200) #include "asio/detail/config.hpp"++#if !defined(ASIO_NO_DEPRECATED)+ #include "asio/detail/type_traits.hpp" #include "asio/execution/executor.hpp" #include "asio/traits/schedule_member.hpp"@@ -86,7 +89,7 @@ ill_formed }; -template <typename S, typename = void>+template <typename S, typename = void, typename = void, typename = void> struct call_traits { ASIO_STATIC_CONSTEXPR(overload_type, overload = ill_formed);@@ -97,9 +100,7 @@ template <typename S> struct call_traits<S, typename enable_if<- (- schedule_member<S>::is_valid- )+ schedule_member<S>::is_valid >::type> : schedule_member<S> {@@ -109,11 +110,10 @@ template <typename S> struct call_traits<S, typename enable_if<- (- !schedule_member<S>::is_valid- &&- schedule_free<S>::is_valid- )+ !schedule_member<S>::is_valid+ >::type,+ typename enable_if<+ schedule_free<S>::is_valid >::type> : schedule_free<S> {@@ -123,13 +123,13 @@ template <typename S> struct call_traits<S, typename enable_if<- (- !schedule_member<S>::is_valid- &&- !schedule_free<S>::is_valid- &&- is_executor<typename decay<S>::type>::value- )+ !schedule_member<S>::is_valid+ >::type,+ typename enable_if<+ !schedule_free<S>::is_valid+ >::type,+ typename enable_if<+ is_executor<typename decay<S>::type>::value >::type> { ASIO_STATIC_CONSTEXPR(overload_type, overload = identity);@@ -286,5 +286,7 @@ #endif // defined(GENERATING_DOCUMENTATION) #include "asio/detail/pop_options.hpp"++#endif // !defined(ASIO_NO_DEPRECATED) #endif // ASIO_EXECUTION_SCHEDULE_HPP
link/modules/asio-standalone/asio/include/asio/execution/scheduler.hpp view
@@ -2,7 +2,7 @@ // execution/scheduler.hpp // ~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -16,6 +16,9 @@ #endif // defined(_MSC_VER) && (_MSC_VER >= 1200) #include "asio/detail/config.hpp"++#if !defined(ASIO_NO_DEPRECATED)+ #include "asio/detail/type_traits.hpp" #include "asio/execution/schedule.hpp" #include "asio/traits/equality_comparable.hpp"@@ -82,5 +85,7 @@ } // namespace asio #include "asio/detail/pop_options.hpp"++#endif // !defined(ASIO_NO_DEPRECATED) #endif // ASIO_EXECUTION_SCHEDULER_HPP
link/modules/asio-standalone/asio/include/asio/execution/sender.hpp view
@@ -2,7 +2,7 @@ // execution/sender.hpp // ~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -16,6 +16,9 @@ #endif // defined(_MSC_VER) && (_MSC_VER >= 1200) #include "asio/detail/config.hpp"++#if !defined(ASIO_NO_DEPRECATED)+ #include "asio/detail/type_traits.hpp" #include "asio/execution/detail/as_invocable.hpp" #include "asio/execution/detail/void_receiver.hpp"@@ -307,5 +310,7 @@ #include "asio/detail/pop_options.hpp" #include "asio/execution/connect.hpp"++#endif // !defined(ASIO_NO_DEPRECATED) #endif // ASIO_EXECUTION_SENDER_HPP
link/modules/asio-standalone/asio/include/asio/execution/set_done.hpp view
@@ -2,7 +2,7 @@ // execution/set_done.hpp // ~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -16,6 +16,9 @@ #endif // defined(_MSC_VER) && (_MSC_VER >= 1200) #include "asio/detail/config.hpp"++#if !defined(ASIO_NO_DEPRECATED)+ #include "asio/detail/type_traits.hpp" #include "asio/traits/set_done_member.hpp" #include "asio/traits/set_done_free.hpp"@@ -83,7 +86,7 @@ ill_formed }; -template <typename R, typename = void>+template <typename R, typename = void, typename = void> struct call_traits { ASIO_STATIC_CONSTEXPR(overload_type, overload = ill_formed);@@ -94,9 +97,7 @@ template <typename R> struct call_traits<R, typename enable_if<- (- set_done_member<R>::is_valid- )+ set_done_member<R>::is_valid >::type> : set_done_member<R> {@@ -106,11 +107,10 @@ template <typename R> struct call_traits<R, typename enable_if<- (- !set_done_member<R>::is_valid- &&- set_done_free<R>::is_valid- )+ !set_done_member<R>::is_valid+ >::type,+ typename enable_if<+ set_done_free<R>::is_valid >::type> : set_done_free<R> {@@ -249,5 +249,7 @@ #endif // defined(GENERATING_DOCUMENTATION) #include "asio/detail/pop_options.hpp"++#endif // !defined(ASIO_NO_DEPRECATED) #endif // ASIO_EXECUTION_SET_DONE_HPP
link/modules/asio-standalone/asio/include/asio/execution/set_error.hpp view
@@ -2,7 +2,7 @@ // execution/set_error.hpp // ~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -16,6 +16,9 @@ #endif // defined(_MSC_VER) && (_MSC_VER >= 1200) #include "asio/detail/config.hpp"++#if !defined(ASIO_NO_DEPRECATED)+ #include "asio/detail/type_traits.hpp" #include "asio/traits/set_error_member.hpp" #include "asio/traits/set_error_free.hpp"@@ -83,7 +86,7 @@ ill_formed }; -template <typename R, typename E, typename = void>+template <typename R, typename E, typename = void, typename = void> struct call_traits { ASIO_STATIC_CONSTEXPR(overload_type, overload = ill_formed);@@ -94,9 +97,7 @@ template <typename R, typename E> struct call_traits<R, void(E), typename enable_if<- (- set_error_member<R, E>::is_valid- )+ set_error_member<R, E>::is_valid >::type> : set_error_member<R, E> {@@ -106,11 +107,10 @@ template <typename R, typename E> struct call_traits<R, void(E), typename enable_if<- (- !set_error_member<R, E>::is_valid- &&- set_error_free<R, E>::is_valid- )+ !set_error_member<R, E>::is_valid+ >::type,+ typename enable_if<+ set_error_free<R, E>::is_valid >::type> : set_error_free<R, E> {@@ -249,5 +249,7 @@ #endif // defined(GENERATING_DOCUMENTATION) #include "asio/detail/pop_options.hpp"++#endif // !defined(ASIO_NO_DEPRECATED) #endif // ASIO_EXECUTION_SET_ERROR_HPP
link/modules/asio-standalone/asio/include/asio/execution/set_value.hpp view
@@ -2,7 +2,7 @@ // execution/set_value.hpp // ~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -16,6 +16,9 @@ #endif // defined(_MSC_VER) && (_MSC_VER >= 1200) #include "asio/detail/config.hpp"++#if !defined(ASIO_NO_DEPRECATED)+ #include "asio/detail/type_traits.hpp" #include "asio/detail/variadic_templates.hpp" #include "asio/traits/set_value_member.hpp"@@ -86,7 +89,7 @@ ill_formed }; -template <typename R, typename Vs, typename = void>+template <typename R, typename Vs, typename = void, typename = void> struct call_traits { ASIO_STATIC_CONSTEXPR(overload_type, overload = ill_formed);@@ -97,9 +100,7 @@ template <typename R, typename Vs> struct call_traits<R, Vs, typename enable_if<- (- set_value_member<R, Vs>::is_valid- )+ set_value_member<R, Vs>::is_valid >::type> : set_value_member<R, Vs> {@@ -109,11 +110,10 @@ template <typename R, typename Vs> struct call_traits<R, Vs, typename enable_if<- (- !set_value_member<R, Vs>::is_valid- &&- set_value_free<R, Vs>::is_valid- )+ !set_value_member<R, Vs>::is_valid+ >::type,+ typename enable_if<+ set_value_free<R, Vs>::is_valid >::type> : set_value_free<R, Vs> {@@ -482,5 +482,7 @@ #endif // defined(GENERATING_DOCUMENTATION) #include "asio/detail/pop_options.hpp"++#endif // !defined(ASIO_NO_DEPRECATED) #endif // ASIO_EXECUTION_SET_VALUE_HPP
link/modules/asio-standalone/asio/include/asio/execution/start.hpp view
@@ -2,7 +2,7 @@ // execution/start.hpp // ~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -16,6 +16,9 @@ #endif // defined(_MSC_VER) && (_MSC_VER >= 1200) #include "asio/detail/config.hpp"++#if !defined(ASIO_NO_DEPRECATED)+ #include "asio/detail/type_traits.hpp" #include "asio/traits/start_member.hpp" #include "asio/traits/start_free.hpp"@@ -80,7 +83,7 @@ ill_formed }; -template <typename R, typename = void>+template <typename R, typename = void, typename = void> struct call_traits { ASIO_STATIC_CONSTEXPR(overload_type, overload = ill_formed);@@ -91,9 +94,7 @@ template <typename R> struct call_traits<R, typename enable_if<- (- start_member<R>::is_valid- )+ start_member<R>::is_valid >::type> : start_member<R> {@@ -103,11 +104,10 @@ template <typename R> struct call_traits<R, typename enable_if<- (- !start_member<R>::is_valid- &&- start_free<R>::is_valid- )+ !start_member<R>::is_valid+ >::type,+ typename enable_if<+ start_free<R>::is_valid >::type> : start_free<R> {@@ -246,5 +246,7 @@ #endif // defined(GENERATING_DOCUMENTATION) #include "asio/detail/pop_options.hpp"++#endif // !defined(ASIO_NO_DEPRECATED) #endif // ASIO_EXECUTION_START_HPP
link/modules/asio-standalone/asio/include/asio/execution/submit.hpp view
@@ -2,7 +2,7 @@ // execution/submit.hpp // ~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -16,6 +16,9 @@ #endif // defined(_MSC_VER) && (_MSC_VER >= 1200) #include "asio/detail/config.hpp"++#if !defined(ASIO_NO_DEPRECATED)+ #include "asio/detail/type_traits.hpp" #include "asio/execution/detail/submit_receiver.hpp" #include "asio/execution/executor.hpp"@@ -125,7 +128,8 @@ ill_formed }; -template <typename S, typename R, typename = void>+template <typename S, typename R, typename = void,+ typename = void, typename = void> struct call_traits { ASIO_STATIC_CONSTEXPR(overload_type, overload = ill_formed);@@ -136,11 +140,10 @@ template <typename S, typename R> struct call_traits<S, void(R), typename enable_if<- (- submit_member<S, R>::is_valid- &&- is_sender_to<S, R>::value- )+ submit_member<S, R>::is_valid+ >::type,+ typename enable_if<+ is_sender_to<S, R>::value >::type> : submit_member<S, R> {@@ -150,13 +153,13 @@ template <typename S, typename R> struct call_traits<S, void(R), typename enable_if<- (- !submit_member<S, R>::is_valid- &&- submit_free<S, R>::is_valid- &&- is_sender_to<S, R>::value- )+ !submit_member<S, R>::is_valid+ >::type,+ typename enable_if<+ submit_free<S, R>::is_valid+ >::type,+ typename enable_if<+ is_sender_to<S, R>::value >::type> : submit_free<S, R> {@@ -166,13 +169,13 @@ template <typename S, typename R> struct call_traits<S, void(R), typename enable_if<- (- !submit_member<S, R>::is_valid- &&- !submit_free<S, R>::is_valid- &&- is_sender_to<S, R>::value- )+ !submit_member<S, R>::is_valid+ >::type,+ typename enable_if<+ !submit_free<S, R>::is_valid+ >::type,+ typename enable_if<+ is_sender_to<S, R>::value >::type> { ASIO_STATIC_CONSTEXPR(overload_type, overload = adapter);@@ -446,5 +449,7 @@ #endif // defined(GENERATING_DOCUMENTATION) #include "asio/detail/pop_options.hpp"++#endif // !defined(ASIO_NO_DEPRECATED) #endif // ASIO_EXECUTION_SUBMIT_HPP
link/modules/asio-standalone/asio/include/asio/execution_context.hpp view
@@ -2,7 +2,7 @@ // execution_context.hpp // ~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/executor.hpp view
@@ -2,7 +2,7 @@ // executor.hpp // ~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/executor_work_guard.hpp view
@@ -2,7 +2,7 @@ // executor_work_guard.hpp // ~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -17,8 +17,6 @@ #include "asio/detail/config.hpp" -#if !defined(ASIO_NO_TS_EXECUTORS)- #include "asio/associated_executor.hpp" #include "asio/detail/type_traits.hpp" #include "asio/execution.hpp"@@ -31,18 +29,16 @@ #if !defined(ASIO_EXECUTOR_WORK_GUARD_DECL) #define ASIO_EXECUTOR_WORK_GUARD_DECL -template <typename Executor, typename = void>+template <typename Executor, typename = void, typename = void> class executor_work_guard; #endif // !defined(ASIO_EXECUTOR_WORK_GUARD_DECL) -/// An object of type @c executor_work_guard controls ownership of executor work-/// within a scope. #if defined(GENERATING_DOCUMENTATION)++/// An object of type @c executor_work_guard controls ownership of outstanding+/// executor work within a scope. template <typename Executor>-#else // defined(GENERATING_DOCUMENTATION)-template <typename Executor, typename>-#endif // defined(GENERATING_DOCUMENTATION) class executor_work_guard { public:@@ -53,6 +49,50 @@ /** * Stores a copy of @c e and calls <tt>on_work_started()</tt> on it. */+ explicit executor_work_guard(const executor_type& e) ASIO_NOEXCEPT;++ /// Copy constructor.+ executor_work_guard(const executor_work_guard& other) ASIO_NOEXCEPT;++ /// Move constructor.+ executor_work_guard(executor_work_guard&& other) ASIO_NOEXCEPT;++ /// Destructor.+ /**+ * Unless the object has already been reset, or is in a moved-from state,+ * calls <tt>on_work_finished()</tt> on the stored executor.+ */+ ~executor_work_guard();++ /// Obtain the associated executor.+ executor_type get_executor() const ASIO_NOEXCEPT;++ /// Whether the executor_work_guard object owns some outstanding work.+ bool owns_work() const ASIO_NOEXCEPT;++ /// Indicate that the work is no longer outstanding.+ /**+ * Unless the object has already been reset, or is in a moved-from state,+ * calls <tt>on_work_finished()</tt> on the stored executor.+ */+ void reset() ASIO_NOEXCEPT;+};++#endif // defined(GENERATING_DOCUMENTATION)++#if !defined(GENERATING_DOCUMENTATION)++#if !defined(ASIO_NO_TS_EXECUTORS)++template <typename Executor>+class executor_work_guard<Executor,+ typename enable_if<+ is_executor<Executor>::value+ >::type>+{+public:+ typedef Executor executor_type;+ explicit executor_work_guard(const executor_type& e) ASIO_NOEXCEPT : executor_(e), owns_(true)@@ -60,7 +100,6 @@ executor_.on_work_started(); } - /// Copy constructor. executor_work_guard(const executor_work_guard& other) ASIO_NOEXCEPT : executor_(other.executor_), owns_(other.owns_)@@ -69,44 +108,31 @@ executor_.on_work_started(); } -#if defined(ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)- /// Move constructor.+#if defined(ASIO_HAS_MOVE) executor_work_guard(executor_work_guard&& other) ASIO_NOEXCEPT : executor_(ASIO_MOVE_CAST(Executor)(other.executor_)), owns_(other.owns_) { other.owns_ = false; }-#endif // defined(ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)+#endif // defined(ASIO_HAS_MOVE) - /// Destructor.- /**- * Unless the object has already been reset, or is in a moved-from state,- * calls <tt>on_work_finished()</tt> on the stored executor.- */ ~executor_work_guard() { if (owns_) executor_.on_work_finished(); } - /// Obtain the associated executor. executor_type get_executor() const ASIO_NOEXCEPT { return executor_; } - /// Whether the executor_work_guard object owns some outstanding work. bool owns_work() const ASIO_NOEXCEPT { return owns_; } - /// Indicate that the work is no longer outstanding.- /**- * Unless the object has already been reset, or is in a moved-from state,- * calls <tt>on_work_finished()</tt> on the stored executor.- */ void reset() ASIO_NOEXCEPT { if (owns_)@@ -124,12 +150,15 @@ bool owns_; }; -#if !defined(GENERATING_DOCUMENTATION)+#endif // !defined(ASIO_NO_TS_EXECUTORS) template <typename Executor> class executor_work_guard<Executor, typename enable_if<- !is_executor<Executor>::value && execution::is_executor<Executor>::value+ !is_executor<Executor>::value+ >::type,+ typename enable_if<+ execution::is_executor<Executor>::value >::type> { public:@@ -215,62 +244,115 @@ #endif // !defined(GENERATING_DOCUMENTATION) /// Create an @ref executor_work_guard object.+/**+ * @param ex An executor.+ *+ * @returns A work guard constructed with the specified executor.+ */ template <typename Executor>-inline executor_work_guard<Executor> make_work_guard(const Executor& ex,- typename enable_if<+ASIO_NODISCARD inline executor_work_guard<Executor>+make_work_guard(const Executor& ex,+ typename constraint< is_executor<Executor>::value || execution::is_executor<Executor>::value- >::type* = 0)+ >::type = 0) { return executor_work_guard<Executor>(ex); } /// Create an @ref executor_work_guard object.+/**+ * @param ctx An execution context, from which an executor will be obtained.+ *+ * @returns A work guard constructed with the execution context's executor,+ * obtained by performing <tt>ctx.get_executor()</tt>.+ */ template <typename ExecutionContext>-inline executor_work_guard<typename ExecutionContext::executor_type>+ASIO_NODISCARD inline+executor_work_guard<typename ExecutionContext::executor_type> make_work_guard(ExecutionContext& ctx,- typename enable_if<+ typename constraint< is_convertible<ExecutionContext&, execution_context&>::value- >::type* = 0)+ >::type = 0) { return executor_work_guard<typename ExecutionContext::executor_type>( ctx.get_executor()); } /// Create an @ref executor_work_guard object.+/**+ * @param t An arbitrary object, such as a completion handler, for which the+ * associated executor will be obtained.+ *+ * @returns A work guard constructed with the associated executor of the object+ * @c t, which is obtained as if by calling <tt>get_associated_executor(t)</tt>.+ */ template <typename T>-inline executor_work_guard<typename associated_executor<T>::type>-make_work_guard(const T& t,- typename enable_if<- !is_executor<T>::value && !execution::is_executor<T>::value- && !is_convertible<T&, execution_context&- >::value>::type* = 0)+ASIO_NODISCARD inline+executor_work_guard<+ typename constraint<+ !is_executor<T>::value+ && !execution::is_executor<T>::value+ && !is_convertible<T&, execution_context&>::value,+ associated_executor<T>+ >::type::type>+make_work_guard(const T& t) { return executor_work_guard<typename associated_executor<T>::type>( associated_executor<T>::get(t)); } /// Create an @ref executor_work_guard object.+/**+ * @param t An arbitrary object, such as a completion handler, for which the+ * associated executor will be obtained.+ *+ * @param ex An executor to be used as the candidate object when determining the+ * associated executor.+ *+ * @returns A work guard constructed with the associated executor of the object+ * @c t, which is obtained as if by calling <tt>get_associated_executor(t,+ * ex)</tt>.+ */ template <typename T, typename Executor>-inline executor_work_guard<typename associated_executor<T, Executor>::type>+ASIO_NODISCARD inline+executor_work_guard<typename associated_executor<T, Executor>::type> make_work_guard(const T& t, const Executor& ex,- typename enable_if<+ typename constraint< is_executor<Executor>::value || execution::is_executor<Executor>::value- >::type* = 0)+ >::type = 0) { return executor_work_guard<typename associated_executor<T, Executor>::type>( associated_executor<T, Executor>::get(t, ex)); } /// Create an @ref executor_work_guard object.+/**+ * @param t An arbitrary object, such as a completion handler, for which the+ * associated executor will be obtained.+ *+ * @param ctx An execution context, from which an executor is obtained to use as+ * the candidate object for determining the associated executor.+ *+ * @returns A work guard constructed with the associated executor of the object+ * @c t, which is obtained as if by calling <tt>get_associated_executor(t,+ * ctx.get_executor())</tt>.+ */ template <typename T, typename ExecutionContext>-inline executor_work_guard<typename associated_executor<T,+ASIO_NODISCARD inline executor_work_guard<typename associated_executor<T, typename ExecutionContext::executor_type>::type> make_work_guard(const T& t, ExecutionContext& ctx,- typename enable_if<- !is_executor<T>::value && !execution::is_executor<T>::value- && !is_convertible<T&, execution_context&>::value- && is_convertible<ExecutionContext&, execution_context&>::value- >::type* = 0)+ typename constraint<+ !is_executor<T>::value+ >::type = 0,+ typename constraint<+ !execution::is_executor<T>::value+ >::type = 0,+ typename constraint<+ !is_convertible<T&, execution_context&>::value+ >::type = 0,+ typename constraint<+ is_convertible<ExecutionContext&, execution_context&>::value+ >::type = 0) { return executor_work_guard<typename associated_executor<T, typename ExecutionContext::executor_type>::type>(@@ -281,7 +363,5 @@ } // namespace asio #include "asio/detail/pop_options.hpp"--#endif // !defined(ASIO_NO_TS_EXECUTORS) #endif // ASIO_EXECUTOR_WORK_GUARD_HPP
+ link/modules/asio-standalone/asio/include/asio/experimental/append.hpp view
@@ -0,0 +1,36 @@+//+// experimental/append.hpp+// ~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com)+//+// Distributed under the Boost Software License, Version 1.0. (See accompanying+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)+//++#ifndef ASIO_EXPERIMENTAL_APPEND_HPP+#define ASIO_EXPERIMENTAL_APPEND_HPP++#if defined(_MSC_VER) && (_MSC_VER >= 1200)+# pragma once+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)++#include "asio/detail/config.hpp"+#include "asio/append.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {+namespace experimental {++#if !defined(ASIO_NO_DEPRECATED)+using asio::append_t;+using asio::append;+#endif // !defined(ASIO_NO_DEPRECATED)++} // namespace experimental+} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // ASIO_EXPERIMENTAL_APPEND_HPP
+ link/modules/asio-standalone/asio/include/asio/experimental/as_single.hpp view
@@ -0,0 +1,136 @@+//+// experimental/as_single.hpp+// ~~~~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com)+//+// Distributed under the Boost Software License, Version 1.0. (See accompanying+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)+//++#ifndef ASIO_EXPERIMENTAL_AS_SINGLE_HPP+#define ASIO_EXPERIMENTAL_AS_SINGLE_HPP++#if defined(_MSC_VER) && (_MSC_VER >= 1200)+# pragma once+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)++#include "asio/detail/config.hpp"+#include "asio/detail/type_traits.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {+namespace experimental {++/// A @ref completion_token adapter used to specify that the completion handler+/// arguments should be combined into a single argument.+/**+ * The as_single_t class is used to indicate that any arguments to the+ * completion handler should be combined and passed as a single argument.+ * If there is already one argument, that argument is passed as-is. If+ * there is more than argument, the arguments are first moved into a+ * @c std::tuple and that tuple is then passed to the completion handler.+ */+template <typename CompletionToken>+class as_single_t+{+public:+ /// Tag type used to prevent the "default" constructor from being used for+ /// conversions.+ struct default_constructor_tag {};++ /// Default constructor.+ /**+ * This constructor is only valid if the underlying completion token is+ * default constructible and move constructible. The underlying completion+ * token is itself defaulted as an argument to allow it to capture a source+ * location.+ */+ ASIO_CONSTEXPR as_single_t(+ default_constructor_tag = default_constructor_tag(),+ CompletionToken token = CompletionToken())+ : token_(ASIO_MOVE_CAST(CompletionToken)(token))+ {+ }++ /// Constructor.+ template <typename T>+ ASIO_CONSTEXPR explicit as_single_t(+ ASIO_MOVE_ARG(T) completion_token)+ : token_(ASIO_MOVE_CAST(T)(completion_token))+ {+ }++ /// Adapts an executor to add the @c as_single_t completion token as the+ /// default.+ template <typename InnerExecutor>+ struct executor_with_default : InnerExecutor+ {+ /// Specify @c as_single_t as the default completion token type.+ typedef as_single_t default_completion_token_type;++ /// Construct the adapted executor from the inner executor type.+ executor_with_default(const InnerExecutor& ex) ASIO_NOEXCEPT+ : InnerExecutor(ex)+ {+ }++ /// Convert the specified executor to the inner executor type, then use+ /// that to construct the adapted executor.+ template <typename OtherExecutor>+ executor_with_default(const OtherExecutor& ex,+ typename constraint<+ is_convertible<OtherExecutor, InnerExecutor>::value+ >::type = 0) ASIO_NOEXCEPT+ : InnerExecutor(ex)+ {+ }+ };++ /// Type alias to adapt an I/O object to use @c as_single_t as its+ /// default completion token type.+#if defined(ASIO_HAS_ALIAS_TEMPLATES) \+ || defined(GENERATING_DOCUMENTATION)+ template <typename T>+ using as_default_on_t = typename T::template rebind_executor<+ executor_with_default<typename T::executor_type> >::other;+#endif // defined(ASIO_HAS_ALIAS_TEMPLATES)+ // || defined(GENERATING_DOCUMENTATION)++ /// Function helper to adapt an I/O object to use @c as_single_t as its+ /// default completion token type.+ template <typename T>+ static typename decay<T>::type::template rebind_executor<+ executor_with_default<typename decay<T>::type::executor_type>+ >::other+ as_default_on(ASIO_MOVE_ARG(T) object)+ {+ return typename decay<T>::type::template rebind_executor<+ executor_with_default<typename decay<T>::type::executor_type>+ >::other(ASIO_MOVE_CAST(T)(object));+ }++//private:+ CompletionToken token_;+};++/// Adapt a @ref completion_token to specify that the completion handler+/// arguments should be combined into a single argument.+template <typename CompletionToken>+ASIO_NODISCARD inline+ASIO_CONSTEXPR as_single_t<typename decay<CompletionToken>::type>+as_single(ASIO_MOVE_ARG(CompletionToken) completion_token)+{+ return as_single_t<typename decay<CompletionToken>::type>(+ ASIO_MOVE_CAST(CompletionToken)(completion_token));+}++} // namespace experimental+} // namespace asio++#include "asio/detail/pop_options.hpp"++#include "asio/experimental/impl/as_single.hpp"++#endif // ASIO_EXPERIMENTAL_AS_SINGLE_HPP
+ link/modules/asio-standalone/asio/include/asio/experimental/as_tuple.hpp view
@@ -0,0 +1,36 @@+//+// experimental/as_tuple.hpp+// ~~~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com)+//+// Distributed under the Boost Software License, Version 1.0. (See accompanying+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)+//++#ifndef ASIO_EXPERIMENTAL_AS_TUPLE_HPP+#define ASIO_EXPERIMENTAL_AS_TUPLE_HPP++#if defined(_MSC_VER) && (_MSC_VER >= 1200)+# pragma once+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)++#include "asio/detail/config.hpp"+#include "asio/as_tuple.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {+namespace experimental {++#if !defined(ASIO_NO_DEPRECATED)+using asio::as_tuple_t;+using asio::as_tuple;+#endif // !defined(ASIO_NO_DEPRECATED)++} // namespace experimental+} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // ASIO_EXPERIMENTAL_AS_TUPLE_HPP
+ link/modules/asio-standalone/asio/include/asio/experimental/awaitable_operators.hpp view
@@ -0,0 +1,536 @@+//+// experimental/awaitable_operators.hpp+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com)+//+// Distributed under the Boost Software License, Version 1.0. (See accompanying+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)+//++#ifndef ASIO_EXPERIMENTAL_AWAITABLE_OPERATORS_HPP+#define ASIO_EXPERIMENTAL_AWAITABLE_OPERATORS_HPP++#if defined(_MSC_VER) && (_MSC_VER >= 1200)+# pragma once+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)++#include "asio/detail/config.hpp"+#include <optional>+#include <stdexcept>+#include <tuple>+#include <variant>+#include "asio/awaitable.hpp"+#include "asio/co_spawn.hpp"+#include "asio/detail/type_traits.hpp"+#include "asio/experimental/deferred.hpp"+#include "asio/experimental/parallel_group.hpp"+#include "asio/multiple_exceptions.hpp"+#include "asio/this_coro.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {+namespace experimental {+namespace awaitable_operators {+namespace detail {++template <typename T, typename Executor>+awaitable<T, Executor> awaitable_wrap(awaitable<T, Executor> a,+ typename constraint<is_constructible<T>::value>::type* = 0)+{+ return a;+}++template <typename T, typename Executor>+awaitable<std::optional<T>, Executor> awaitable_wrap(awaitable<T, Executor> a,+ typename constraint<!is_constructible<T>::value>::type* = 0)+{+ co_return std::optional<T>(co_await std::move(a));+}++template <typename T>+T& awaitable_unwrap(typename conditional<true, T, void>::type& r,+ typename constraint<is_constructible<T>::value>::type* = 0)+{+ return r;+}++template <typename T>+T& awaitable_unwrap(std::optional<typename conditional<true, T, void>::type>& r,+ typename constraint<!is_constructible<T>::value>::type* = 0)+{+ return *r;+}++} // namespace detail++/// Wait for both operations to succeed.+/**+ * If one operations fails, the other is cancelled as the AND-condition can no+ * longer be satisfied.+ */+template <typename Executor>+awaitable<void, Executor> operator&&(+ awaitable<void, Executor> t, awaitable<void, Executor> u)+{+ auto ex = co_await this_coro::executor;++ auto [order, ex0, ex1] =+ co_await make_parallel_group(+ co_spawn(ex, std::move(t), deferred),+ co_spawn(ex, std::move(u), deferred)+ ).async_wait(+ wait_for_one_error(),+ deferred+ );++ if (ex0 && ex1)+ throw multiple_exceptions(ex0);+ if (ex0)+ std::rethrow_exception(ex0);+ if (ex1)+ std::rethrow_exception(ex1);+ co_return;+}++/// Wait for both operations to succeed.+/**+ * If one operations fails, the other is cancelled as the AND-condition can no+ * longer be satisfied.+ */+template <typename U, typename Executor>+awaitable<U, Executor> operator&&(+ awaitable<void, Executor> t, awaitable<U, Executor> u)+{+ auto ex = co_await this_coro::executor;++ auto [order, ex0, ex1, r1] =+ co_await make_parallel_group(+ co_spawn(ex, std::move(t), deferred),+ co_spawn(ex, detail::awaitable_wrap(std::move(u)), deferred)+ ).async_wait(+ wait_for_one_error(),+ deferred+ );++ if (ex0 && ex1)+ throw multiple_exceptions(ex0);+ if (ex0)+ std::rethrow_exception(ex0);+ if (ex1)+ std::rethrow_exception(ex1);+ co_return std::move(detail::awaitable_unwrap<U>(r1));+}++/// Wait for both operations to succeed.+/**+ * If one operations fails, the other is cancelled as the AND-condition can no+ * longer be satisfied.+ */+template <typename T, typename Executor>+awaitable<T, Executor> operator&&(+ awaitable<T, Executor> t, awaitable<void, Executor> u)+{+ auto ex = co_await this_coro::executor;++ auto [order, ex0, r0, ex1] =+ co_await make_parallel_group(+ co_spawn(ex, detail::awaitable_wrap(std::move(t)), deferred),+ co_spawn(ex, std::move(u), deferred)+ ).async_wait(+ wait_for_one_error(),+ deferred+ );++ if (ex0 && ex1)+ throw multiple_exceptions(ex0);+ if (ex0)+ std::rethrow_exception(ex0);+ if (ex1)+ std::rethrow_exception(ex1);+ co_return std::move(detail::awaitable_unwrap<T>(r0));+}++/// Wait for both operations to succeed.+/**+ * If one operations fails, the other is cancelled as the AND-condition can no+ * longer be satisfied.+ */+template <typename T, typename U, typename Executor>+awaitable<std::tuple<T, U>, Executor> operator&&(+ awaitable<T, Executor> t, awaitable<U, Executor> u)+{+ auto ex = co_await this_coro::executor;++ auto [order, ex0, r0, ex1, r1] =+ co_await make_parallel_group(+ co_spawn(ex, detail::awaitable_wrap(std::move(t)), deferred),+ co_spawn(ex, detail::awaitable_wrap(std::move(u)), deferred)+ ).async_wait(+ wait_for_one_error(),+ deferred+ );++ if (ex0 && ex1)+ throw multiple_exceptions(ex0);+ if (ex0)+ std::rethrow_exception(ex0);+ if (ex1)+ std::rethrow_exception(ex1);+ co_return std::make_tuple(+ std::move(detail::awaitable_unwrap<T>(r0)),+ std::move(detail::awaitable_unwrap<U>(r1)));+}++/// Wait for both operations to succeed.+/**+ * If one operations fails, the other is cancelled as the AND-condition can no+ * longer be satisfied.+ */+template <typename... T, typename Executor>+awaitable<std::tuple<T..., std::monostate>, Executor> operator&&(+ awaitable<std::tuple<T...>, Executor> t, awaitable<void, Executor> u)+{+ auto ex = co_await this_coro::executor;++ auto [order, ex0, r0, ex1, r1] =+ co_await make_parallel_group(+ co_spawn(ex, detail::awaitable_wrap(std::move(t)), deferred),+ co_spawn(ex, std::move(u), deferred)+ ).async_wait(+ wait_for_one_error(),+ deferred+ );++ if (ex0 && ex1)+ throw multiple_exceptions(ex0);+ if (ex0)+ std::rethrow_exception(ex0);+ if (ex1)+ std::rethrow_exception(ex1);+ co_return std::move(detail::awaitable_unwrap<std::tuple<T...>>(r0));+}++/// Wait for both operations to succeed.+/**+ * If one operations fails, the other is cancelled as the AND-condition can no+ * longer be satisfied.+ */+template <typename... T, typename U, typename Executor>+awaitable<std::tuple<T..., U>, Executor> operator&&(+ awaitable<std::tuple<T...>, Executor> t, awaitable<U, Executor> u)+{+ auto ex = co_await this_coro::executor;++ auto [order, ex0, r0, ex1, r1] =+ co_await make_parallel_group(+ co_spawn(ex, detail::awaitable_wrap(std::move(t)), deferred),+ co_spawn(ex, detail::awaitable_wrap(std::move(u)), deferred)+ ).async_wait(+ wait_for_one_error(),+ deferred+ );++ if (ex0 && ex1)+ throw multiple_exceptions(ex0);+ if (ex0)+ std::rethrow_exception(ex0);+ if (ex1)+ std::rethrow_exception(ex1);+ co_return std::tuple_cat(+ std::move(detail::awaitable_unwrap<std::tuple<T...>>(r0)),+ std::make_tuple(std::move(detail::awaitable_unwrap<U>(r1))));+}++/// Wait for one operation to succeed.+/**+ * If one operations succeeds, the other is cancelled as the OR-condition is+ * already satisfied.+ */+template <typename Executor>+awaitable<std::variant<std::monostate, std::monostate>, Executor> operator||(+ awaitable<void, Executor> t, awaitable<void, Executor> u)+{+ auto ex = co_await this_coro::executor;++ auto [order, ex0, ex1] =+ co_await make_parallel_group(+ co_spawn(ex, std::move(t), deferred),+ co_spawn(ex, std::move(u), deferred)+ ).async_wait(+ wait_for_one_success(),+ deferred+ );++ if (order[0] == 0)+ {+ if (!ex0)+ co_return std::variant<std::monostate, std::monostate>{+ std::in_place_index<0>};+ if (!ex1)+ co_return std::variant<std::monostate, std::monostate>{+ std::in_place_index<1>};+ throw multiple_exceptions(ex0);+ }+ else+ {+ if (!ex1)+ co_return std::variant<std::monostate, std::monostate>{+ std::in_place_index<1>};+ if (!ex0)+ co_return std::variant<std::monostate, std::monostate>{+ std::in_place_index<0>};+ throw multiple_exceptions(ex1);+ }+}++/// Wait for one operation to succeed.+/**+ * If one operations succeeds, the other is cancelled as the OR-condition is+ * already satisfied.+ */+template <typename U, typename Executor>+awaitable<std::variant<std::monostate, U>, Executor> operator||(+ awaitable<void, Executor> t, awaitable<U, Executor> u)+{+ auto ex = co_await this_coro::executor;++ auto [order, ex0, ex1, r1] =+ co_await make_parallel_group(+ co_spawn(ex, std::move(t), deferred),+ co_spawn(ex, detail::awaitable_wrap(std::move(u)), deferred)+ ).async_wait(+ wait_for_one_success(),+ deferred+ );++ if (order[0] == 0)+ {+ if (!ex0)+ co_return std::variant<std::monostate, U>{+ std::in_place_index<0>};+ if (!ex1)+ co_return std::variant<std::monostate, U>{+ std::in_place_index<1>,+ std::move(detail::awaitable_unwrap<U>(r1))};+ throw multiple_exceptions(ex0);+ }+ else+ {+ if (!ex1)+ co_return std::variant<std::monostate, U>{+ std::in_place_index<1>,+ std::move(detail::awaitable_unwrap<U>(r1))};+ if (!ex0)+ co_return std::variant<std::monostate, U>{+ std::in_place_index<0>};+ throw multiple_exceptions(ex1);+ }+}++/// Wait for one operation to succeed.+/**+ * If one operations succeeds, the other is cancelled as the OR-condition is+ * already satisfied.+ */+template <typename T, typename Executor>+awaitable<std::variant<T, std::monostate>, Executor> operator||(+ awaitable<T, Executor> t, awaitable<void, Executor> u)+{+ auto ex = co_await this_coro::executor;++ auto [order, ex0, r0, ex1] =+ co_await make_parallel_group(+ co_spawn(ex, detail::awaitable_wrap(std::move(t)), deferred),+ co_spawn(ex, std::move(u), deferred)+ ).async_wait(+ wait_for_one_success(),+ deferred+ );++ if (order[0] == 0)+ {+ if (!ex0)+ co_return std::variant<T, std::monostate>{+ std::in_place_index<0>,+ std::move(detail::awaitable_unwrap<T>(r0))};+ if (!ex1)+ co_return std::variant<T, std::monostate>{+ std::in_place_index<1>};+ throw multiple_exceptions(ex0);+ }+ else+ {+ if (!ex1)+ co_return std::variant<T, std::monostate>{+ std::in_place_index<1>};+ if (!ex0)+ co_return std::variant<T, std::monostate>{+ std::in_place_index<0>,+ std::move(detail::awaitable_unwrap<T>(r0))};+ throw multiple_exceptions(ex1);+ }+}++/// Wait for one operation to succeed.+/**+ * If one operations succeeds, the other is cancelled as the OR-condition is+ * already satisfied.+ */+template <typename T, typename U, typename Executor>+awaitable<std::variant<T, U>, Executor> operator||(+ awaitable<T, Executor> t, awaitable<U, Executor> u)+{+ auto ex = co_await this_coro::executor;++ auto [order, ex0, r0, ex1, r1] =+ co_await make_parallel_group(+ co_spawn(ex, detail::awaitable_wrap(std::move(t)), deferred),+ co_spawn(ex, detail::awaitable_wrap(std::move(u)), deferred)+ ).async_wait(+ wait_for_one_success(),+ deferred+ );++ if (order[0] == 0)+ {+ if (!ex0)+ co_return std::variant<T, U>{+ std::in_place_index<0>,+ std::move(detail::awaitable_unwrap<T>(r0))};+ if (!ex1)+ co_return std::variant<T, U>{+ std::in_place_index<1>,+ std::move(detail::awaitable_unwrap<U>(r1))};+ throw multiple_exceptions(ex0);+ }+ else+ {+ if (!ex1)+ co_return std::variant<T, U>{+ std::in_place_index<1>,+ std::move(detail::awaitable_unwrap<U>(r1))};+ if (!ex0)+ co_return std::variant<T, U>{+ std::in_place_index<0>,+ std::move(detail::awaitable_unwrap<T>(r0))};+ throw multiple_exceptions(ex1);+ }+}++namespace detail {++template <typename... T>+struct widen_variant+{+ template <std::size_t I, typename SourceVariant>+ static std::variant<T...> call(SourceVariant& source)+ {+ if (source.index() == I)+ return std::variant<T...>{+ std::in_place_index<I>, std::move(std::get<I>(source))};+ else if constexpr (I + 1 < std::variant_size_v<SourceVariant>)+ return call<I + 1>(source);+ else+ throw std::logic_error("empty variant");+ }+};++} // namespace detail++/// Wait for one operation to succeed.+/**+ * If one operations succeeds, the other is cancelled as the OR-condition is+ * already satisfied.+ */+template <typename... T, typename Executor>+awaitable<std::variant<T..., std::monostate>, Executor> operator||(+ awaitable<std::variant<T...>, Executor> t, awaitable<void, Executor> u)+{+ auto ex = co_await this_coro::executor;++ auto [order, ex0, r0, ex1] =+ co_await make_parallel_group(+ co_spawn(ex, detail::awaitable_wrap(std::move(t)), deferred),+ co_spawn(ex, std::move(u), deferred)+ ).async_wait(+ wait_for_one_success(),+ deferred+ );++ using widen = detail::widen_variant<T..., std::monostate>;+ if (order[0] == 0)+ {+ if (!ex0)+ co_return widen::template call<0>(+ detail::awaitable_unwrap<std::variant<T...>>(r0));+ if (!ex1)+ co_return std::variant<T..., std::monostate>{+ std::in_place_index<sizeof...(T)>};+ throw multiple_exceptions(ex0);+ }+ else+ {+ if (!ex1)+ co_return std::variant<T..., std::monostate>{+ std::in_place_index<sizeof...(T)>};+ if (!ex0)+ co_return widen::template call<0>(+ detail::awaitable_unwrap<std::variant<T...>>(r0));+ throw multiple_exceptions(ex1);+ }+}++/// Wait for one operation to succeed.+/**+ * If one operations succeeds, the other is cancelled as the OR-condition is+ * already satisfied.+ */+template <typename... T, typename U, typename Executor>+awaitable<std::variant<T..., U>, Executor> operator||(+ awaitable<std::variant<T...>, Executor> t, awaitable<U, Executor> u)+{+ auto ex = co_await this_coro::executor;++ auto [order, ex0, r0, ex1, r1] =+ co_await make_parallel_group(+ co_spawn(ex, detail::awaitable_wrap(std::move(t)), deferred),+ co_spawn(ex, detail::awaitable_wrap(std::move(u)), deferred)+ ).async_wait(+ wait_for_one_success(),+ deferred+ );++ using widen = detail::widen_variant<T..., U>;+ if (order[0] == 0)+ {+ if (!ex0)+ co_return widen::template call<0>(+ detail::awaitable_unwrap<std::variant<T...>>(r0));+ if (!ex1)+ co_return std::variant<T..., U>{+ std::in_place_index<sizeof...(T)>,+ std::move(detail::awaitable_unwrap<U>(r1))};+ throw multiple_exceptions(ex0);+ }+ else+ {+ if (!ex1)+ co_return std::variant<T..., U>{+ std::in_place_index<sizeof...(T)>,+ std::move(detail::awaitable_unwrap<U>(r1))};+ if (!ex0)+ co_return widen::template call<0>(+ detail::awaitable_unwrap<std::variant<T...>>(r0));+ throw multiple_exceptions(ex1);+ }+}++} // namespace awaitable_operators+} // namespace experimental+} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // ASIO_EXPERIMENTAL_AWAITABLE_OPERATORS_HPP
+ link/modules/asio-standalone/asio/include/asio/experimental/basic_channel.hpp view
@@ -0,0 +1,491 @@+//+// experimental/basic_channel.hpp+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com)+//+// Distributed under the Boost Software License, Version 1.0. (See accompanying+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)+//++#ifndef ASIO_EXPERIMENTAL_BASIC_CHANNEL_HPP+#define ASIO_EXPERIMENTAL_BASIC_CHANNEL_HPP++#if defined(_MSC_VER) && (_MSC_VER >= 1200)+# pragma once+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)++#include "asio/detail/config.hpp"+#include "asio/detail/non_const_lvalue.hpp"+#include "asio/detail/null_mutex.hpp"+#include "asio/execution/executor.hpp"+#include "asio/execution_context.hpp"+#include "asio/experimental/detail/channel_send_functions.hpp"+#include "asio/experimental/detail/channel_service.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {+namespace experimental {+namespace detail {++} // namespace detail++/// A channel for messages.+/**+ * The basic_channel class template is used for sending messages between+ * different parts of the same application. A <em>message</em> is defined as a+ * collection of arguments to be passed to a completion handler, and the set of+ * messages supported by a channel is specified by its @c Traits and+ * <tt>Signatures...</tt> template parameters. Messages may be sent and received+ * using asynchronous or non-blocking synchronous operations.+ *+ * Unless customising the traits, applications will typically use the @c+ * experimental::channel alias template. For example:+ * @code void send_loop(int i, steady_timer& timer,+ * channel<void(error_code, int)>& ch)+ * {+ * if (i < 10)+ * {+ * timer.expires_after(chrono::seconds(1));+ * timer.async_wait(+ * [i, &timer, &ch](error_code error)+ * {+ * if (!error)+ * {+ * ch.async_send(error_code(), i,+ * [i, &timer, &ch](error_code error)+ * {+ * if (!error)+ * {+ * send_loop(i + 1, timer, ch);+ * }+ * });+ * }+ * });+ * }+ * else+ * {+ * ch.close();+ * }+ * }+ *+ * void receive_loop(channel<void(error_code, int)>& ch)+ * {+ * ch.async_receive(+ * [&ch](error_code error, int i)+ * {+ * if (!error)+ * {+ * std::cout << "Received " << i << "\n";+ * receive_loop(ch);+ * }+ * });+ * } @endcode+ *+ * @par Thread Safety+ * @e Distinct @e objects: Safe.@n+ * @e Shared @e objects: Unsafe.+ *+ * The basic_channel class template is not thread-safe, and would typically be+ * used for passing messages between application code that runs on the same+ * thread or in the same strand. Consider using @ref basic_concurrent_channel,+ * and its alias template @c experimental::concurrent_channel, to pass messages+ * between code running in different threads.+ */+template <typename Executor, typename Traits, typename... Signatures>+class basic_channel+#if !defined(GENERATING_DOCUMENTATION)+ : public detail::channel_send_functions<+ basic_channel<Executor, Traits, Signatures...>,+ Executor, Signatures...>+#endif // !defined(GENERATING_DOCUMENTATION)+{+private:+ class initiate_async_send;+ class initiate_async_receive;+ typedef detail::channel_service<asio::detail::null_mutex> service_type;+ typedef typename service_type::template implementation_type<+ Traits, Signatures...>::payload_type payload_type;++ template <typename... PayloadSignatures,+ ASIO_COMPLETION_TOKEN_FOR(PayloadSignatures...) CompletionToken>+ auto do_async_receive(detail::channel_payload<PayloadSignatures...>*,+ ASIO_MOVE_ARG(CompletionToken) token)+ -> decltype(+ async_initiate<CompletionToken, PayloadSignatures...>(+ declval<initiate_async_receive>(), token))+ {+ return async_initiate<CompletionToken, PayloadSignatures...>(+ initiate_async_receive(this), token);+ }++public:+ /// The type of the executor associated with the channel.+ typedef Executor executor_type;++ /// Rebinds the channel type to another executor.+ template <typename Executor1>+ struct rebind_executor+ {+ /// The channel type when rebound to the specified executor.+ typedef basic_channel<Executor1, Traits, Signatures...> other;+ };++ /// The traits type associated with the channel.+ typedef typename Traits::template rebind<Signatures...>::other traits_type;++ /// Construct a basic_channel.+ /**+ * This constructor creates and channel.+ *+ * @param ex The I/O executor that the channel will use, by default, to+ * dispatch handlers for any asynchronous operations performed on the channel.+ *+ * @param max_buffer_size The maximum number of messages that may be buffered+ * in the channel.+ */+ basic_channel(const executor_type& ex, std::size_t max_buffer_size = 0)+ : service_(&asio::use_service<service_type>(+ basic_channel::get_context(ex))),+ impl_(),+ executor_(ex)+ {+ service_->construct(impl_, max_buffer_size);+ }++ /// Construct and open a basic_channel.+ /**+ * This constructor creates and opens a channel.+ *+ * @param context An execution context which provides the I/O executor that+ * the channel will use, by default, to dispatch handlers for any asynchronous+ * operations performed on the channel.+ *+ * @param max_buffer_size The maximum number of messages that may be buffered+ * in the channel.+ */+ template <typename ExecutionContext>+ basic_channel(ExecutionContext& context, std::size_t max_buffer_size = 0,+ typename constraint<+ is_convertible<ExecutionContext&, execution_context&>::value,+ defaulted_constraint+ >::type = defaulted_constraint())+ : service_(&asio::use_service<service_type>(context)),+ impl_(),+ executor_(context.get_executor())+ {+ service_->construct(impl_, max_buffer_size);+ }++#if defined(ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)+ /// Move-construct a basic_channel from another.+ /**+ * This constructor moves a channel from one object to another.+ *+ * @param other The other basic_channel object from which the move will occur.+ *+ * @note Following the move, the moved-from object is in the same state as if+ * constructed using the @c basic_channel(const executor_type&) constructor.+ */+ basic_channel(basic_channel&& other)+ : service_(other.service_),+ executor_(other.executor_)+ {+ service_->move_construct(impl_, other.impl_);+ }++ /// Move-assign a basic_channel from another.+ /**+ * This assignment operator moves a channel from one object to another.+ * Cancels any outstanding asynchronous operations associated with the target+ * object.+ *+ * @param other The other basic_channel object from which the move will occur.+ *+ * @note Following the move, the moved-from object is in the same state as if+ * constructed using the @c basic_channel(const executor_type&)+ * constructor.+ */+ basic_channel& operator=(basic_channel&& other)+ {+ if (this != &other)+ {+ service_->move_assign(impl_, *other.service_, other.impl_);+ executor_.~executor_type();+ new (&executor_) executor_type(other.executor_);+ service_ = other.service_;+ }+ return *this;+ }++ // All channels have access to each other's implementations.+ template <typename, typename, typename...>+ friend class basic_channel;++ /// Move-construct a basic_channel from another.+ /**+ * This constructor moves a channel from one object to another.+ *+ * @param other The other basic_channel object from which the move will occur.+ *+ * @note Following the move, the moved-from object is in the same state as if+ * constructed using the @c basic_channel(const executor_type&)+ * constructor.+ */+ template <typename Executor1>+ basic_channel(+ basic_channel<Executor1, Traits, Signatures...>&& other,+ typename constraint<+ is_convertible<Executor1, Executor>::value+ >::type = 0)+ : service_(other.service_),+ executor_(other.executor_)+ {+ service_->move_construct(impl_, *other.service_, other.impl_);+ }++ /// Move-assign a basic_channel from another.+ /**+ * This assignment operator moves a channel from one object to another.+ * Cancels any outstanding asynchronous operations associated with the target+ * object.+ *+ * @param other The other basic_channel object from which the move will+ * occur.+ *+ * @note Following the move, the moved-from object is in the same state as if+ * constructed using the @c basic_channel(const executor_type&)+ * constructor.+ */+ template <typename Executor1>+ typename constraint<+ is_convertible<Executor1, Executor>::value,+ basic_channel&+ >::type operator=(basic_channel<Executor1, Traits, Signatures...>&& other)+ {+ if (this != &other)+ {+ service_->move_assign(impl_, *other.service_, other.impl_);+ executor_.~executor_type();+ new (&executor_) executor_type(other.executor_);+ service_ = other.service_;+ }+ return *this;+ }+#endif // defined(ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)++ /// Destructor.+ ~basic_channel()+ {+ service_->destroy(impl_);+ }++ /// Get the executor associated with the object.+ const executor_type& get_executor() ASIO_NOEXCEPT+ {+ return executor_;+ }++ /// Get the capacity of the channel's buffer.+ std::size_t capacity() ASIO_NOEXCEPT+ {+ return service_->capacity(impl_);+ }++ /// Determine whether the channel is open.+ bool is_open() const ASIO_NOEXCEPT+ {+ return service_->is_open(impl_);+ }++ /// Reset the channel to its initial state.+ void reset()+ {+ service_->reset(impl_);+ }++ /// Close the channel.+ void close()+ {+ service_->close(impl_);+ }++ /// Cancel all asynchronous operations waiting on the channel.+ /**+ * All outstanding send operations will complete with the error+ * @c asio::experimental::error::channel_cancelled. Outstanding receive+ * operations complete with the result as determined by the channel traits.+ */+ void cancel()+ {+ service_->cancel(impl_);+ }++ /// Determine whether a message can be received without blocking.+ bool ready() const ASIO_NOEXCEPT+ {+ return service_->ready(impl_);+ }++#if defined(GENERATING_DOCUMENTATION)++ /// Try to send a message without blocking.+ /**+ * Fails if the buffer is full and there are no waiting receive operations.+ *+ * @returns @c true on success, @c false on failure.+ */+ template <typename... Args>+ bool try_send(ASIO_MOVE_ARG(Args)... args);++ /// Try to send a number of messages without blocking.+ /**+ * @returns The number of messages that were sent.+ */+ template <typename... Args>+ std::size_t try_send_n(std::size_t count, ASIO_MOVE_ARG(Args)... args);++ /// Asynchronously send a message.+ /**+ * @par Completion Signature+ * @code void(asio::error_code) @endcode+ */+ template <typename... Args,+ ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code))+ CompletionToken ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(executor_type)>+ auto async_send(ASIO_MOVE_ARG(Args)... args,+ ASIO_MOVE_ARG(CompletionToken) token);++#endif // defined(GENERATING_DOCUMENTATION)++ /// Try to receive a message without blocking.+ /**+ * Fails if the buffer is full and there are no waiting receive operations.+ *+ * @returns @c true on success, @c false on failure.+ */+ template <typename Handler>+ bool try_receive(ASIO_MOVE_ARG(Handler) handler)+ {+ return service_->try_receive(impl_, ASIO_MOVE_CAST(Handler)(handler));+ }++ /// Asynchronously receive a message.+ /**+ * @par Completion Signature+ * As determined by the <tt>Signatures...</tt> template parameter and the+ * channel traits.+ */+ template <typename CompletionToken+ ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(executor_type)>+ auto async_receive(+ ASIO_MOVE_ARG(CompletionToken) token+ ASIO_DEFAULT_COMPLETION_TOKEN(Executor))+#if !defined(GENERATING_DOCUMENTATION)+ -> decltype(+ this->do_async_receive(static_cast<payload_type*>(0),+ ASIO_MOVE_CAST(CompletionToken)(token)))+#endif // !defined(GENERATING_DOCUMENTATION)+ {+ return this->do_async_receive(static_cast<payload_type*>(0),+ ASIO_MOVE_CAST(CompletionToken)(token));+ }++private:+ // Disallow copying and assignment.+ basic_channel(const basic_channel&) ASIO_DELETED;+ basic_channel& operator=(const basic_channel&) ASIO_DELETED;++ template <typename, typename, typename...>+ friend class detail::channel_send_functions;++ // Helper function to get an executor's context.+ template <typename T>+ static execution_context& get_context(const T& t,+ typename enable_if<execution::is_executor<T>::value>::type* = 0)+ {+ return asio::query(t, execution::context);+ }++ // Helper function to get an executor's context.+ template <typename T>+ static execution_context& get_context(const T& t,+ typename enable_if<!execution::is_executor<T>::value>::type* = 0)+ {+ return t.context();+ }++ class initiate_async_send+ {+ public:+ typedef Executor executor_type;++ explicit initiate_async_send(basic_channel* self)+ : self_(self)+ {+ }++ const executor_type& get_executor() const ASIO_NOEXCEPT+ {+ return self_->get_executor();+ }++ template <typename SendHandler>+ void operator()(ASIO_MOVE_ARG(SendHandler) handler,+ ASIO_MOVE_ARG(payload_type) payload) const+ {+ asio::detail::non_const_lvalue<SendHandler> handler2(handler);+ self_->service_->async_send(self_->impl_,+ ASIO_MOVE_CAST(payload_type)(payload),+ handler2.value, self_->get_executor());+ }++ private:+ basic_channel* self_;+ };++ class initiate_async_receive+ {+ public:+ typedef Executor executor_type;++ explicit initiate_async_receive(basic_channel* self)+ : self_(self)+ {+ }++ const executor_type& get_executor() const ASIO_NOEXCEPT+ {+ return self_->get_executor();+ }++ template <typename ReceiveHandler>+ void operator()(ASIO_MOVE_ARG(ReceiveHandler) handler) const+ {+ asio::detail::non_const_lvalue<ReceiveHandler> handler2(handler);+ self_->service_->async_receive(self_->impl_,+ handler2.value, self_->get_executor());+ }++ private:+ basic_channel* self_;+ };++ // The service associated with the I/O object.+ service_type* service_;++ // The underlying implementation of the I/O object.+ typename service_type::template implementation_type<+ Traits, Signatures...> impl_;++ // The associated executor.+ Executor executor_;+};++} // namespace experimental+} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // ASIO_EXPERIMENTAL_BASIC_CHANNEL_HPP
+ link/modules/asio-standalone/asio/include/asio/experimental/basic_concurrent_channel.hpp view
@@ -0,0 +1,491 @@+//+// experimental/basic_concurrent_channel.hpp+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com)+//+// Distributed under the Boost Software License, Version 1.0. (See accompanying+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)+//++#ifndef ASIO_EXPERIMENTAL_BASIC_CONCURRENT_CHANNEL_HPP+#define ASIO_EXPERIMENTAL_BASIC_CONCURRENT_CHANNEL_HPP++#if defined(_MSC_VER) && (_MSC_VER >= 1200)+# pragma once+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)++#include "asio/detail/config.hpp"+#include "asio/detail/non_const_lvalue.hpp"+#include "asio/detail/mutex.hpp"+#include "asio/execution/executor.hpp"+#include "asio/execution_context.hpp"+#include "asio/experimental/detail/channel_send_functions.hpp"+#include "asio/experimental/detail/channel_service.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {+namespace experimental {+namespace detail {++} // namespace detail++/// A channel for messages.+/**+ * The basic_concurrent_channel class template is used for sending messages+ * between different parts of the same application. A <em>message</em> is+ * defined as a collection of arguments to be passed to a completion handler,+ * and the set of messages supported by a channel is specified by its @c Traits+ * and <tt>Signatures...</tt> template parameters. Messages may be sent and+ * received using asynchronous or non-blocking synchronous operations.+ *+ * Unless customising the traits, applications will typically use the @c+ * experimental::concurrent_channel alias template. For example:+ * @code void send_loop(int i, steady_timer& timer,+ * concurrent_channel<void(error_code, int)>& ch)+ * {+ * if (i < 10)+ * {+ * timer.expires_after(chrono::seconds(1));+ * timer.async_wait(+ * [i, &timer, &ch](error_code error)+ * {+ * if (!error)+ * {+ * ch.async_send(error_code(), i,+ * [i, &timer, &ch](error_code error)+ * {+ * if (!error)+ * {+ * send_loop(i + 1, timer, ch);+ * }+ * });+ * }+ * });+ * }+ * else+ * {+ * ch.close();+ * }+ * }+ *+ * void receive_loop(concurent_channel<void(error_code, int)>& ch)+ * {+ * ch.async_receive(+ * [&ch](error_code error, int i)+ * {+ * if (!error)+ * {+ * std::cout << "Received " << i << "\n";+ * receive_loop(ch);+ * }+ * });+ * } @endcode+ *+ * @par Thread Safety+ * @e Distinct @e objects: Safe.@n+ * @e Shared @e objects: Safe.+ *+ * The basic_concurrent_channel class template is thread-safe, and would+ * typically be used for passing messages between application code that run on+ * different threads. Consider using @ref basic_channel, and its alias template+ * @c experimental::channel, to pass messages between code running in a single+ * thread or on the same strand.+ */+template <typename Executor, typename Traits, typename... Signatures>+class basic_concurrent_channel+#if !defined(GENERATING_DOCUMENTATION)+ : public detail::channel_send_functions<+ basic_concurrent_channel<Executor, Traits, Signatures...>,+ Executor, Signatures...>+#endif // !defined(GENERATING_DOCUMENTATION)+{+private:+ class initiate_async_send;+ class initiate_async_receive;+ typedef detail::channel_service<asio::detail::mutex> service_type;+ typedef typename service_type::template implementation_type<+ Traits, Signatures...>::payload_type payload_type;++ template <typename... PayloadSignatures,+ ASIO_COMPLETION_TOKEN_FOR(PayloadSignatures...) CompletionToken>+ auto do_async_receive(detail::channel_payload<PayloadSignatures...>*,+ ASIO_MOVE_ARG(CompletionToken) token)+ -> decltype(+ async_initiate<CompletionToken, PayloadSignatures...>(+ declval<initiate_async_receive>(), token))+ {+ return async_initiate<CompletionToken, PayloadSignatures...>(+ initiate_async_receive(this), token);+ }++public:+ /// The type of the executor associated with the channel.+ typedef Executor executor_type;++ /// Rebinds the channel type to another executor.+ template <typename Executor1>+ struct rebind_executor+ {+ /// The channel type when rebound to the specified executor.+ typedef basic_concurrent_channel<Executor1, Traits, Signatures...> other;+ };++ /// The traits type associated with the channel.+ typedef typename Traits::template rebind<Signatures...>::other traits_type;++ /// Construct a basic_concurrent_channel.+ /**+ * This constructor creates and channel.+ *+ * @param ex The I/O executor that the channel will use, by default, to+ * dispatch handlers for any asynchronous operations performed on the channel.+ *+ * @param max_buffer_size The maximum number of messages that may be buffered+ * in the channel.+ */+ basic_concurrent_channel(const executor_type& ex,+ std::size_t max_buffer_size = 0)+ : service_(&asio::use_service<service_type>(+ basic_concurrent_channel::get_context(ex))),+ impl_(),+ executor_(ex)+ {+ service_->construct(impl_, max_buffer_size);+ }++ /// Construct and open a basic_concurrent_channel.+ /**+ * This constructor creates and opens a channel.+ *+ * @param context An execution context which provides the I/O executor that+ * the channel will use, by default, to dispatch handlers for any asynchronous+ * operations performed on the channel.+ *+ * @param max_buffer_size The maximum number of messages that may be buffered+ * in the channel.+ */+ template <typename ExecutionContext>+ basic_concurrent_channel(ExecutionContext& context,+ std::size_t max_buffer_size = 0,+ typename constraint<+ is_convertible<ExecutionContext&, execution_context&>::value,+ defaulted_constraint+ >::type = defaulted_constraint())+ : service_(&asio::use_service<service_type>(context)),+ impl_(),+ executor_(context.get_executor())+ {+ service_->construct(impl_, max_buffer_size);+ }++#if defined(ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)+ /// Move-construct a basic_concurrent_channel from another.+ /**+ * This constructor moves a channel from one object to another.+ *+ * @param other The other basic_concurrent_channel object from which the move+ * will occur.+ *+ * @note Following the move, the moved-from object is in the same state as if+ * constructed using the @c basic_concurrent_channel(const executor_type&)+ * constructor.+ */+ basic_concurrent_channel(basic_concurrent_channel&& other)+ : service_(other.service_),+ executor_(other.executor_)+ {+ service_->move_construct(impl_, other.impl_);+ }++ /// Move-assign a basic_concurrent_channel from another.+ /**+ * This assignment operator moves a channel from one object to another.+ * Cancels any outstanding asynchronous operations associated with the target+ * object.+ *+ * @param other The other basic_concurrent_channel object from which the move+ * will occur.+ *+ * @note Following the move, the moved-from object is in the same state as if+ * constructed using the @c basic_concurrent_channel(const executor_type&)+ * constructor.+ */+ basic_concurrent_channel& operator=(basic_concurrent_channel&& other)+ {+ if (this != &other)+ {+ service_->move_assign(impl_, *other.service_, other.impl_);+ executor_.~executor_type();+ new (&executor_) executor_type(other.executor_);+ service_ = other.service_;+ }+ return *this;+ }++ // All channels have access to each other's implementations.+ template <typename, typename, typename...>+ friend class basic_concurrent_channel;++ /// Move-construct a basic_concurrent_channel from another.+ /**+ * This constructor moves a channel from one object to another.+ *+ * @param other The other basic_concurrent_channel object from which the move+ * will occur.+ *+ * @note Following the move, the moved-from object is in the same state as if+ * constructed using the @c basic_concurrent_channel(const executor_type&)+ * constructor.+ */+ template <typename Executor1>+ basic_concurrent_channel(+ basic_concurrent_channel<Executor1, Traits, Signatures...>&& other,+ typename constraint<+ is_convertible<Executor1, Executor>::value+ >::type = 0)+ : service_(other.service_),+ executor_(other.executor_)+ {+ service_->move_construct(impl_, *other.service_, other.impl_);+ }++ /// Move-assign a basic_concurrent_channel from another.+ /**+ * This assignment operator moves a channel from one object to another.+ * Cancels any outstanding asynchronous operations associated with the target+ * object.+ *+ * @param other The other basic_concurrent_channel object from which the move+ * will occur.+ *+ * @note Following the move, the moved-from object is in the same state as if+ * constructed using the @c basic_concurrent_channel(const executor_type&)+ * constructor.+ */+ template <typename Executor1>+ typename constraint<+ is_convertible<Executor1, Executor>::value,+ basic_concurrent_channel&+ >::type operator=(+ basic_concurrent_channel<Executor1, Traits, Signatures...>&& other)+ {+ if (this != &other)+ {+ service_->move_assign(impl_, *other.service_, other.impl_);+ executor_.~executor_type();+ new (&executor_) executor_type(other.executor_);+ service_ = other.service_;+ }+ return *this;+ }+#endif // defined(ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)++ /// Destructor.+ ~basic_concurrent_channel()+ {+ service_->destroy(impl_);+ }++ /// Get the executor associated with the object.+ const executor_type& get_executor() ASIO_NOEXCEPT+ {+ return executor_;+ }++ /// Get the capacity of the channel's buffer.+ std::size_t capacity() ASIO_NOEXCEPT+ {+ return service_->capacity(impl_);+ }++ /// Determine whether the channel is open.+ bool is_open() const ASIO_NOEXCEPT+ {+ return service_->is_open(impl_);+ }++ /// Reset the channel to its initial state.+ void reset()+ {+ service_->reset(impl_);+ }++ /// Close the channel.+ void close()+ {+ service_->close(impl_);+ }++ /// Cancel all asynchronous operations waiting on the channel.+ /**+ * All outstanding send operations will complete with the error+ * @c asio::experimental::error::channel_cancelled. Outstanding receive+ * operations complete with the result as determined by the channel traits.+ */+ void cancel()+ {+ service_->cancel(impl_);+ }++ /// Determine whether a message can be received without blocking.+ bool ready() const ASIO_NOEXCEPT+ {+ return service_->ready(impl_);+ }++#if defined(GENERATING_DOCUMENTATION)++ /// Try to send a message without blocking.+ /**+ * Fails if the buffer is full and there are no waiting receive operations.+ *+ * @returns @c true on success, @c false on failure.+ */+ template <typename... Args>+ bool try_send(ASIO_MOVE_ARG(Args)... args);++ /// Try to send a number of messages without blocking.+ /**+ * @returns The number of messages that were sent.+ */+ template <typename... Args>+ std::size_t try_send_n(std::size_t count, ASIO_MOVE_ARG(Args)... args);++ /// Asynchronously send a message.+ template <typename... Args,+ ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code))+ CompletionToken ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(executor_type)>+ auto async_send(ASIO_MOVE_ARG(Args)... args,+ ASIO_MOVE_ARG(CompletionToken) token);++#endif // defined(GENERATING_DOCUMENTATION)++ /// Try to receive a message without blocking.+ /**+ * Fails if the buffer is full and there are no waiting receive operations.+ *+ * @returns @c true on success, @c false on failure.+ */+ template <typename Handler>+ bool try_receive(ASIO_MOVE_ARG(Handler) handler)+ {+ return service_->try_receive(impl_, ASIO_MOVE_CAST(Handler)(handler));+ }++ /// Asynchronously receive a message.+ template <typename CompletionToken+ ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(executor_type)>+ auto async_receive(+ ASIO_MOVE_ARG(CompletionToken) token+ ASIO_DEFAULT_COMPLETION_TOKEN(Executor))+#if !defined(GENERATING_DOCUMENTATION)+ -> decltype(+ this->do_async_receive(static_cast<payload_type*>(0),+ ASIO_MOVE_CAST(CompletionToken)(token)))+#endif // !defined(GENERATING_DOCUMENTATION)+ {+ return this->do_async_receive(static_cast<payload_type*>(0),+ ASIO_MOVE_CAST(CompletionToken)(token));+ }++private:+ // Disallow copying and assignment.+ basic_concurrent_channel(+ const basic_concurrent_channel&) ASIO_DELETED;+ basic_concurrent_channel& operator=(+ const basic_concurrent_channel&) ASIO_DELETED;++ template <typename, typename, typename...>+ friend class detail::channel_send_functions;++ // Helper function to get an executor's context.+ template <typename T>+ static execution_context& get_context(const T& t,+ typename enable_if<execution::is_executor<T>::value>::type* = 0)+ {+ return asio::query(t, execution::context);+ }++ // Helper function to get an executor's context.+ template <typename T>+ static execution_context& get_context(const T& t,+ typename enable_if<!execution::is_executor<T>::value>::type* = 0)+ {+ return t.context();+ }++ class initiate_async_send+ {+ public:+ typedef Executor executor_type;++ explicit initiate_async_send(basic_concurrent_channel* self)+ : self_(self)+ {+ }++ const executor_type& get_executor() const ASIO_NOEXCEPT+ {+ return self_->get_executor();+ }++ template <typename SendHandler>+ void operator()(ASIO_MOVE_ARG(SendHandler) handler,+ ASIO_MOVE_ARG(payload_type) payload) const+ {+ asio::detail::non_const_lvalue<SendHandler> handler2(handler);+ self_->service_->async_send(self_->impl_,+ ASIO_MOVE_CAST(payload_type)(payload),+ handler2.value, self_->get_executor());+ }++ private:+ basic_concurrent_channel* self_;+ };++ class initiate_async_receive+ {+ public:+ typedef Executor executor_type;++ explicit initiate_async_receive(basic_concurrent_channel* self)+ : self_(self)+ {+ }++ const executor_type& get_executor() const ASIO_NOEXCEPT+ {+ return self_->get_executor();+ }++ template <typename ReceiveHandler>+ void operator()(ASIO_MOVE_ARG(ReceiveHandler) handler) const+ {+ asio::detail::non_const_lvalue<ReceiveHandler> handler2(handler);+ self_->service_->async_receive(self_->impl_,+ handler2.value, self_->get_executor());+ }++ private:+ basic_concurrent_channel* self_;+ };++ // The service associated with the I/O object.+ service_type* service_;++ // The underlying implementation of the I/O object.+ typename service_type::template implementation_type<+ Traits, Signatures...> impl_;++ // The associated executor.+ Executor executor_;+};++} // namespace experimental+} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // ASIO_EXPERIMENTAL_BASIC_CONCURRENT_CHANNEL_HPP
+ link/modules/asio-standalone/asio/include/asio/experimental/cancellation_condition.hpp view
@@ -0,0 +1,155 @@+//+// experimental/cancellation_condition.hpp+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com)+//+// Distributed under the Boost Software License, Version 1.0. (See accompanying+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)+//++#ifndef ASIO_EXPERIMENTAL_CANCELLATION_CONDITION_HPP+#define ASIO_EXPERIMENTAL_CANCELLATION_CONDITION_HPP++#if defined(_MSC_VER) && (_MSC_VER >= 1200)+# pragma once+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)++#include "asio/detail/config.hpp"+#include <exception>+#include "asio/cancellation_type.hpp"+#include "asio/error_code.hpp"+#include "asio/detail/type_traits.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {+namespace experimental {++/// Wait for all operations to complete.+class wait_for_all+{+public:+ template <typename... Args>+ ASIO_CONSTEXPR cancellation_type_t operator()(+ Args&&...) const ASIO_NOEXCEPT+ {+ return cancellation_type::none;+ }+};++/// Wait until an operation completes, then cancel the others.+class wait_for_one+{+public:+ ASIO_CONSTEXPR explicit wait_for_one(+ cancellation_type_t cancel_type = cancellation_type::all)+ : cancel_type_(cancel_type)+ {+ }++ template <typename... Args>+ ASIO_CONSTEXPR cancellation_type_t operator()(+ Args&&...) const ASIO_NOEXCEPT+ {+ return cancel_type_;+ }++private:+ cancellation_type_t cancel_type_;+};++/// Wait until an operation completes without an error, then cancel the others.+/**+ * If no operation completes without an error, waits for completion of all+ * operations.+ */+class wait_for_one_success+{+public:+ ASIO_CONSTEXPR explicit wait_for_one_success(+ cancellation_type_t cancel_type = cancellation_type::all)+ : cancel_type_(cancel_type)+ {+ }++ ASIO_CONSTEXPR cancellation_type_t+ operator()() const ASIO_NOEXCEPT+ {+ return cancel_type_;+ }++ template <typename E, typename... Args>+ ASIO_CONSTEXPR typename constraint<+ !is_same<typename decay<E>::type, asio::error_code>::value+ && !is_same<typename decay<E>::type, std::exception_ptr>::value,+ cancellation_type_t+ >::type operator()(const E&, Args&&...) const ASIO_NOEXCEPT+ {+ return cancel_type_;+ }++ template <typename E, typename... Args>+ ASIO_CONSTEXPR typename constraint<+ is_same<typename decay<E>::type, asio::error_code>::value+ || is_same<typename decay<E>::type, std::exception_ptr>::value,+ cancellation_type_t+ >::type operator()(const E& e, Args&&...) const ASIO_NOEXCEPT+ {+ return !!e ? cancellation_type::none : cancel_type_;+ }++private:+ cancellation_type_t cancel_type_;+};++/// Wait until an operation completes with an error, then cancel the others.+/**+ * If no operation completes with an error, waits for completion of all+ * operations.+ */+class wait_for_one_error+{+public:+ ASIO_CONSTEXPR explicit wait_for_one_error(+ cancellation_type_t cancel_type = cancellation_type::all)+ : cancel_type_(cancel_type)+ {+ }++ ASIO_CONSTEXPR cancellation_type_t+ operator()() const ASIO_NOEXCEPT+ {+ return cancellation_type::none;+ }++ template <typename E, typename... Args>+ ASIO_CONSTEXPR typename constraint<+ !is_same<typename decay<E>::type, asio::error_code>::value+ && !is_same<typename decay<E>::type, std::exception_ptr>::value,+ cancellation_type_t+ >::type operator()(const E&, Args&&...) const ASIO_NOEXCEPT+ {+ return cancellation_type::none;+ }++ template <typename E, typename... Args>+ ASIO_CONSTEXPR typename constraint<+ is_same<typename decay<E>::type, asio::error_code>::value+ || is_same<typename decay<E>::type, std::exception_ptr>::value,+ cancellation_type_t+ >::type operator()(const E& e, Args&&...) const ASIO_NOEXCEPT+ {+ return !!e ? cancel_type_ : cancellation_type::none;+ }++private:+ cancellation_type_t cancel_type_;+};++} // namespace experimental+} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // ASIO_EXPERIMENTAL_CANCELLATION_CONDITION_HPP
+ link/modules/asio-standalone/asio/include/asio/experimental/channel.hpp view
@@ -0,0 +1,70 @@+//+// experimental/channel.hpp+// ~~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com)+//+// Distributed under the Boost Software License, Version 1.0. (See accompanying+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)+//++#ifndef ASIO_EXPERIMENTAL_CHANNEL_HPP+#define ASIO_EXPERIMENTAL_CHANNEL_HPP++#if defined(_MSC_VER) && (_MSC_VER >= 1200)+# pragma once+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)++#include "asio/detail/config.hpp"+#include "asio/any_io_executor.hpp"+#include "asio/detail/type_traits.hpp"+#include "asio/execution/executor.hpp"+#include "asio/is_executor.hpp"+#include "asio/experimental/basic_channel.hpp"+#include "asio/experimental/channel_traits.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {+namespace experimental {+namespace detail {++template <typename ExecutorOrSignature, typename = void>+struct channel_type+{+ template <typename... Signatures>+ struct inner+ {+ typedef basic_channel<any_io_executor, channel_traits<>,+ ExecutorOrSignature, Signatures...> type;+ };+};++template <typename ExecutorOrSignature>+struct channel_type<ExecutorOrSignature,+ typename enable_if<+ is_executor<ExecutorOrSignature>::value+ || execution::is_executor<ExecutorOrSignature>::value+ >::type>+{+ template <typename... Signatures>+ struct inner+ {+ typedef basic_channel<ExecutorOrSignature,+ channel_traits<>, Signatures...> type;+ };+};++} // namespace detail++/// Template type alias for common use of channel.+template <typename ExecutorOrSignature, typename... Signatures>+using channel = typename detail::channel_type<+ ExecutorOrSignature>::template inner<Signatures...>::type;++} // namespace experimental+} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // ASIO_EXPERIMENTAL_CHANNEL_HPP
+ link/modules/asio-standalone/asio/include/asio/experimental/channel_error.hpp view
@@ -0,0 +1,84 @@+//+// experimental/channel_error.hpp+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com)+//+// Distributed under the Boost Software License, Version 1.0. (See accompanying+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)+//++#ifndef ASIO_EXPERIMENTAL_CHANNEL_ERROR_HPP+#define ASIO_EXPERIMENTAL_CHANNEL_ERROR_HPP++#if defined(_MSC_VER) && (_MSC_VER >= 1200)+# pragma once+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)++#include "asio/detail/config.hpp"+#include "asio/error_code.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {+namespace experimental {+namespace error {++enum channel_errors+{+ /// The channel was closed.+ channel_closed = 1,++ /// The channel was cancelled.+ channel_cancelled = 2+};++extern ASIO_DECL+const asio::error_category& get_channel_category();++static const asio::error_category&+ channel_category ASIO_UNUSED_VARIABLE+ = asio::experimental::error::get_channel_category();++} // namespace error+namespace channel_errc {+ // Simulates a scoped enum.+ using error::channel_closed;+ using error::channel_cancelled;+} // namespace channel_errc+} // namespace experimental+} // namespace asio++#if defined(ASIO_HAS_STD_SYSTEM_ERROR)+namespace std {++template<> struct is_error_code_enum<+ asio::experimental::error::channel_errors>+{+ static const bool value = true;+};++} // namespace std+#endif // defined(ASIO_HAS_STD_SYSTEM_ERROR)++namespace asio {+namespace experimental {+namespace error {++inline asio::error_code make_error_code(channel_errors e)+{+ return asio::error_code(+ static_cast<int>(e), get_channel_category());+}++} // namespace error+} // namespace experimental+} // namespace asio++#include "asio/detail/pop_options.hpp"++#if defined(ASIO_HEADER_ONLY)+# include "asio/experimental/impl/channel_error.ipp"+#endif // defined(ASIO_HEADER_ONLY)++#endif // ASIO_EXPERIMENTAL_CHANNEL_ERROR_HPP
+ link/modules/asio-standalone/asio/include/asio/experimental/channel_traits.hpp view
@@ -0,0 +1,301 @@+//+// experimental/channel_traits.hpp+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com)+//+// Distributed under the Boost Software License, Version 1.0. (See accompanying+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)+//++#ifndef ASIO_EXPERIMENTAL_CHANNEL_TRAITS_HPP+#define ASIO_EXPERIMENTAL_CHANNEL_TRAITS_HPP++#if defined(_MSC_VER) && (_MSC_VER >= 1200)+# pragma once+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)++#include "asio/detail/config.hpp"+#include <deque>+#include "asio/detail/type_traits.hpp"+#include "asio/error.hpp"+#include "asio/experimental/channel_error.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {+namespace experimental {++#if defined(GENERATING_DOCUMENTATION)++template <typename... Signatures>+struct channel_traits+{+ /// Rebind the traits to a new set of signatures.+ /**+ * This nested structure must have a single nested type @c other that+ * aliases a traits type with the specified set of signatures.+ */+ template <typename... NewSignatures>+ struct rebind+ {+ typedef user_defined other;+ };++ /// Determine the container for the specified elements.+ /**+ * This nested structure must have a single nested type @c other that+ * aliases a container type for the specified element type.+ */+ template <typename Element>+ struct container+ {+ typedef user_defined type;+ };++ /// The signature of a channel cancellation notification.+ typedef void receive_cancelled_signature(...);++ /// Invoke the specified handler with a cancellation notification.+ template <typename F>+ static void invoke_receive_cancelled(F f);++ /// The signature of a channel closed notification.+ typedef void receive_closed_signature(...);++ /// Invoke the specified handler with a closed notification.+ template <typename F>+ static void invoke_receive_closed(F f);+};++#else // defined(GENERATING_DOCUMENTATION)++/// Traits used for customising channel behaviour.+template <typename... Signatures>+struct channel_traits+{+ template <typename... NewSignatures>+ struct rebind+ {+ typedef channel_traits<NewSignatures...> other;+ };+};++template <typename R>+struct channel_traits<R(asio::error_code)>+{+ template <typename... NewSignatures>+ struct rebind+ {+ typedef channel_traits<NewSignatures...> other;+ };++ template <typename Element>+ struct container+ {+ typedef std::deque<Element> type;+ };++ typedef R receive_cancelled_signature(asio::error_code);++ template <typename F>+ static void invoke_receive_cancelled(F f)+ {+ const asio::error_code e = error::channel_cancelled;+ ASIO_MOVE_OR_LVALUE(F)(f)(e);+ }++ typedef R receive_closed_signature(asio::error_code);++ template <typename F>+ static void invoke_receive_closed(F f)+ {+ const asio::error_code e = error::channel_closed;+ ASIO_MOVE_OR_LVALUE(F)(f)(e);+ }+};++template <typename R, typename... Args, typename... Signatures>+struct channel_traits<R(asio::error_code, Args...), Signatures...>+{+ template <typename... NewSignatures>+ struct rebind+ {+ typedef channel_traits<NewSignatures...> other;+ };++ template <typename Element>+ struct container+ {+ typedef std::deque<Element> type;+ };++ typedef R receive_cancelled_signature(asio::error_code, Args...);++ template <typename F>+ static void invoke_receive_cancelled(F f)+ {+ const asio::error_code e = error::channel_cancelled;+ ASIO_MOVE_OR_LVALUE(F)(f)(e, typename decay<Args>::type()...);+ }++ typedef R receive_closed_signature(asio::error_code, Args...);++ template <typename F>+ static void invoke_receive_closed(F f)+ {+ const asio::error_code e = error::channel_closed;+ ASIO_MOVE_OR_LVALUE(F)(f)(e, typename decay<Args>::type()...);+ }+};++template <typename R>+struct channel_traits<R(std::exception_ptr)>+{+ template <typename... NewSignatures>+ struct rebind+ {+ typedef channel_traits<NewSignatures...> other;+ };++ template <typename Element>+ struct container+ {+ typedef std::deque<Element> type;+ };++ typedef R receive_cancelled_signature(std::exception_ptr);++ template <typename F>+ static void invoke_receive_cancelled(F f)+ {+ const asio::error_code e = error::channel_cancelled;+ ASIO_MOVE_OR_LVALUE(F)(f)(+ std::make_exception_ptr(asio::system_error(e)));+ }++ typedef R receive_closed_signature(std::exception_ptr);++ template <typename F>+ static void invoke_receive_closed(F f)+ {+ const asio::error_code e = error::channel_closed;+ ASIO_MOVE_OR_LVALUE(F)(f)(+ std::make_exception_ptr(asio::system_error(e)));+ }+};++template <typename R, typename... Args, typename... Signatures>+struct channel_traits<R(std::exception_ptr, Args...), Signatures...>+{+ template <typename... NewSignatures>+ struct rebind+ {+ typedef channel_traits<NewSignatures...> other;+ };++ template <typename Element>+ struct container+ {+ typedef std::deque<Element> type;+ };++ typedef R receive_cancelled_signature(std::exception_ptr, Args...);++ template <typename F>+ static void invoke_receive_cancelled(F f)+ {+ const asio::error_code e = error::channel_cancelled;+ ASIO_MOVE_OR_LVALUE(F)(f)(+ std::make_exception_ptr(asio::system_error(e)),+ typename decay<Args>::type()...);+ }++ typedef R receive_closed_signature(std::exception_ptr, Args...);++ template <typename F>+ static void invoke_receive_closed(F f)+ {+ const asio::error_code e = error::channel_closed;+ ASIO_MOVE_OR_LVALUE(F)(f)(+ std::make_exception_ptr(asio::system_error(e)),+ typename decay<Args>::type()...);+ }+};++template <typename R>+struct channel_traits<R()>+{+ template <typename... NewSignatures>+ struct rebind+ {+ typedef channel_traits<NewSignatures...> other;+ };++ template <typename Element>+ struct container+ {+ typedef std::deque<Element> type;+ };++ typedef R receive_cancelled_signature(asio::error_code);++ template <typename F>+ static void invoke_receive_cancelled(F f)+ {+ const asio::error_code e = error::channel_cancelled;+ ASIO_MOVE_OR_LVALUE(F)(f)(e);+ }++ typedef R receive_closed_signature(asio::error_code);++ template <typename F>+ static void invoke_receive_closed(F f)+ {+ const asio::error_code e = error::channel_closed;+ ASIO_MOVE_OR_LVALUE(F)(f)(e);+ }+};++template <typename R, typename T>+struct channel_traits<R(T)>+{+ template <typename... NewSignatures>+ struct rebind+ {+ typedef channel_traits<NewSignatures...> other;+ };++ template <typename Element>+ struct container+ {+ typedef std::deque<Element> type;+ };++ typedef R receive_cancelled_signature(asio::error_code);++ template <typename F>+ static void invoke_receive_cancelled(F f)+ {+ const asio::error_code e = error::channel_cancelled;+ ASIO_MOVE_OR_LVALUE(F)(f)(e);+ }++ typedef R receive_closed_signature(asio::error_code);++ template <typename F>+ static void invoke_receive_closed(F f)+ {+ const asio::error_code e = error::channel_closed;+ ASIO_MOVE_OR_LVALUE(F)(f)(e);+ }+};++#endif // defined(GENERATING_DOCUMENTATION)++} // namespace experimental+} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // ASIO_EXPERIMENTAL_CHANNEL_TRAITS_HPP
+ link/modules/asio-standalone/asio/include/asio/experimental/co_composed.hpp view
@@ -0,0 +1,144 @@+//+// experimental/co_composed.hpp+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com)+//+// Distributed under the Boost Software License, Version 1.0. (See accompanying+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)+//++#ifndef ASIO_EXPERIMENTAL_CO_COMPOSED_HPP+#define ASIO_EXPERIMENTAL_CO_COMPOSED_HPP++#if defined(_MSC_VER) && (_MSC_VER >= 1200)+# pragma once+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)++#include "asio/detail/config.hpp"+#include "asio/async_result.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {+namespace experimental {++/// Creates an initiation function object that may be used to launch a+/// coroutine-based composed asynchronous operation.+/**+ * The experimental::co_composed utility simplifies the implementation of+ * composed asynchronous operations by automatically adapting a coroutine to be+ * an initiation function object for use with @c async_initiate. When awaiting+ * asynchronous operations, the coroutine automatically uses a conforming+ * intermediate completion handler.+ *+ * @param implementation A function object that contains the coroutine-based+ * implementation of the composed asynchronous operation. The first argument to+ * the function object represents the state of the operation, and may be used+ * to test for cancellation. The remaining arguments are those passed to @c+ * async_initiate after the completion token.+ *+ * @param io_objects_or_executors Zero or more I/O objects or I/O executors for+ * which outstanding work must be maintained while the operation is incomplete.+ *+ * @par Per-Operation Cancellation+ * By default, per-operation cancellation is disabled for composed operations+ * that use experimental::co_composed. It must be explicitly enabled by calling+ * the state's @c reset_cancellation_state function.+ *+ * @par Examples+ * The following example illustrates manual error handling and explicit checks+ * for cancellation. The completion handler is invoked via a @c co_yield to the+ * state's @c complete function, which never returns.+ *+ * @code template <typename CompletionToken>+ * auto async_echo(tcp::socket& socket,+ * CompletionToken&& token)+ * {+ * return asio::async_initiate<+ * CompletionToken, void(std::error_code)>(+ * asio::experimental::co_composed(+ * [](auto state, tcp::socket& socket) -> void+ * {+ * state.reset_cancellation_state(+ * asio::enable_terminal_cancellation());+ *+ * while (!state.cancelled())+ * {+ * char data[1024];+ * auto [e1, n1] =+ * co_await socket.async_read_some(+ * asio::buffer(data),+ * asio::as_tuple(asio::deferred));+ *+ * if (e1)+ * co_yield state.complete(e1);+ *+ * if (!!state.cancelled())+ * co_yield state.complete(+ * make_error_code(asio::error::operation_aborted));+ *+ * auto [e2, n2] =+ * co_await asio::async_write(socket,+ * asio::buffer(data, n1),+ * asio::as_tuple(asio::deferred));+ *+ * if (e2)+ * co_yield state.complete(e2);+ * }+ * }, socket),+ * token, std::ref(socket));+ * } @endcode+ *+ * This next example shows exception-based error handling and implicit checks+ * for cancellation. The completion handler is invoked after returning from the+ * coroutine via @c co_return. Valid @c co_return values are specified using+ * completion signatures passed to the @c co_composed function.+ *+ * @code template <typename CompletionToken>+ * auto async_echo(tcp::socket& socket,+ * CompletionToken&& token)+ * {+ * return asio::async_initiate<+ * CompletionToken, void(std::error_code)>(+ * asio::experimental::co_composed<+ * void(std::error_code)>(+ * [](auto state, tcp::socket& socket) -> void+ * {+ * try+ * {+ * state.throw_if_cancelled(true);+ * state.reset_cancellation_state(+ * asio::enable_terminal_cancellation());+ *+ * for (;;)+ * {+ * char data[1024];+ * std::size_t n = co_await socket.async_read_some(+ * asio::buffer(data), asio::deferred);+ *+ * co_await asio::async_write(socket,+ * asio::buffer(data, n), asio::deferred);+ * }+ * }+ * catch (const std::system_error& e)+ * {+ * co_return {e.code()};+ * }+ * }, socket),+ * token, std::ref(socket));+ * } @endcode+ */+template <completion_signature... Signatures,+ typename Implementation, typename... IoObjectsOrExecutors>+auto co_composed(Implementation&& implementation,+ IoObjectsOrExecutors&&... io_objects_or_executors);++} // namespace experimental+} // namespace asio++#include "asio/detail/pop_options.hpp"++#include "asio/experimental/impl/co_composed.hpp"++#endif // ASIO_EXPERIMENTAL_CO_COMPOSED_HPP
+ link/modules/asio-standalone/asio/include/asio/experimental/co_spawn.hpp view
@@ -0,0 +1,187 @@+//+// experimental/co_spawn.hpp+// ~~~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2021-2023 Klemens D. Morgenstern+// (klemens dot morgenstern at gmx dot net)+//+// Distributed under the Boost Software License, Version 1.0. (See accompanying+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)+//+#ifndef ASIO_EXPERIMENTAL_CO_SPAWN_HPP+#define ASIO_EXPERIMENTAL_CO_SPAWN_HPP++#if defined(_MSC_VER) && (_MSC_VER >= 1200)+# pragma once+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)++#include "asio/detail/config.hpp"+#include <utility>+#include "asio/compose.hpp"+#include "asio/detail/type_traits.hpp"+#include "asio/experimental/coro.hpp"+#include "asio/experimental/deferred.hpp"+#include "asio/experimental/prepend.hpp"+#include "asio/redirect_error.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {+namespace experimental {+namespace detail {++template <typename T, typename U, typename Executor>+struct coro_spawn_op+{+ coro<T, U, Executor> c;++ void operator()(auto& self)+ {+ auto op = c.async_resume(deferred);+ std::move(op)((prepend)(std::move(self), 0));+ }++ void operator()(auto& self, int, auto... res)+ {+ self.complete(std::move(res)...);+ }+};++} // namespace detail++/// Spawn a resumable coroutine.+/**+ * This function spawns the coroutine for execution on its executor. It binds+ * the lifetime of the coroutine to the executor.+ *+ * @param c The coroutine+ *+ * @param token The completion token+ *+ * @returns Implementation defined+ */+template <typename T, typename Executor, typename CompletionToken>+ASIO_INITFN_AUTO_RESULT_TYPE(+ CompletionToken, void(std::exception_ptr, T))+co_spawn(coro<void, T, Executor> c, CompletionToken&& token)+{+ auto exec = c.get_executor();+ return async_compose<CompletionToken, void(std::exception_ptr, T)>(+ detail::coro_spawn_op<void, T, Executor>{std::move(c)},+ token, exec);+}++/// Spawn a resumable coroutine.+/**+ * This function spawns the coroutine for execution on its executor. It binds+ * the lifetime of the coroutine to the executor.+ *+ * @param c The coroutine+ *+ * @param token The completion token+ *+ * @returns Implementation defined+ */+template <typename T, typename Executor, typename CompletionToken>+ASIO_INITFN_AUTO_RESULT_TYPE(+ CompletionToken, void(std::exception_ptr, T))+co_spawn(coro<void(), T, Executor> c, CompletionToken&& token)+{+ auto exec = c.get_executor();+ return async_compose<CompletionToken, void(std::exception_ptr, T)>(+ detail::coro_spawn_op<void(), T, Executor>{std::move(c)},+ token, exec);+}++/// Spawn a resumable coroutine.+/**+ * This function spawns the coroutine for execution on its executor. It binds+ * the lifetime of the coroutine to the executor.+ *+ * @param c The coroutine+ *+ * @param token The completion token+ *+ * @returns Implementation defined+ */+template <typename T, typename Executor, typename CompletionToken>+ASIO_INITFN_AUTO_RESULT_TYPE(CompletionToken, void(T))+co_spawn(coro<void() noexcept, T, Executor> c, CompletionToken&& token)+{+ auto exec = c.get_executor();+ return async_compose<CompletionToken, void(T)>(+ detail::coro_spawn_op<void() noexcept, T, Executor>{std::move(c)},+ token, exec);+}++/// Spawn a resumable coroutine.+/**+ * This function spawns the coroutine for execution on its executor. It binds+ * the lifetime of the coroutine to the executor.+ *+ * @param c The coroutine+ *+ * @param token The completion token+ *+ * @returns Implementation defined+ */+template <typename Executor, typename CompletionToken>+ASIO_INITFN_AUTO_RESULT_TYPE(+ CompletionToken, void(std::exception_ptr))+co_spawn(coro<void, void, Executor> c, CompletionToken&& token)+{+ auto exec = c.get_executor();+ return async_compose<CompletionToken, void(std::exception_ptr)>(+ detail::coro_spawn_op<void, void, Executor>{std::move(c)},+ token, exec);+}++/// Spawn a resumable coroutine.+/**+ * This function spawns the coroutine for execution on its executor. It binds+ * the lifetime of the coroutine to the executor.+ *+ * @param c The coroutine+ *+ * @param token The completion token+ *+ * @returns Implementation defined+ */+template <typename Executor, typename CompletionToken>+ASIO_INITFN_AUTO_RESULT_TYPE(+ CompletionToken, void(std::exception_ptr))+co_spawn(coro<void(), void, Executor> c, CompletionToken&& token)+{+ auto exec = c.get_executor();+ return async_compose<CompletionToken, void(std::exception_ptr)>(+ detail::coro_spawn_op<void(), void, Executor>{std::move(c)},+ token, exec);+}++/// Spawn a resumable coroutine.+/**+ * This function spawns the coroutine for execution on its executor. It binds+ * the lifetime of the coroutine to the executor.+ *+ * @param c The coroutine+ *+ * @param token The completion token+ *+ * @returns Implementation defined+ */+template <typename Executor, typename CompletionToken>+ASIO_INITFN_AUTO_RESULT_TYPE(CompletionToken, void())+co_spawn(coro<void() noexcept, void, Executor> c, CompletionToken&& token)+{+ auto exec = c.get_executor();+ return async_compose<CompletionToken, void()>(+ detail::coro_spawn_op<void() noexcept, void, Executor>{std::move(c)},+ token, exec);+}++} // namespace detail+} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif //ASIO_EXPERIMENTAL_CO_SPAWN_HPP
+ link/modules/asio-standalone/asio/include/asio/experimental/concurrent_channel.hpp view
@@ -0,0 +1,70 @@+//+// experimental/concurrent_channel.hpp+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com)+//+// Distributed under the Boost Software License, Version 1.0. (See accompanying+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)+//++#ifndef ASIO_EXPERIMENTAL_CONCURRENT_CHANNEL_HPP+#define ASIO_EXPERIMENTAL_CONCURRENT_CHANNEL_HPP++#if defined(_MSC_VER) && (_MSC_VER >= 1200)+# pragma once+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)++#include "asio/detail/config.hpp"+#include "asio/any_io_executor.hpp"+#include "asio/detail/type_traits.hpp"+#include "asio/execution/executor.hpp"+#include "asio/is_executor.hpp"+#include "asio/experimental/basic_concurrent_channel.hpp"+#include "asio/experimental/channel_traits.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {+namespace experimental {+namespace detail {++template <typename ExecutorOrSignature, typename = void>+struct concurrent_channel_type+{+ template <typename... Signatures>+ struct inner+ {+ typedef basic_concurrent_channel<any_io_executor, channel_traits<>,+ ExecutorOrSignature, Signatures...> type;+ };+};++template <typename ExecutorOrSignature>+struct concurrent_channel_type<ExecutorOrSignature,+ typename enable_if<+ is_executor<ExecutorOrSignature>::value+ || execution::is_executor<ExecutorOrSignature>::value+ >::type>+{+ template <typename... Signatures>+ struct inner+ {+ typedef basic_concurrent_channel<ExecutorOrSignature,+ channel_traits<>, Signatures...> type;+ };+};++} // namespace detail++/// Template type alias for common use of channel.+template <typename ExecutorOrSignature, typename... Signatures>+using concurrent_channel = typename detail::concurrent_channel_type<+ ExecutorOrSignature>::template inner<Signatures...>::type;++} // namespace experimental+} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // ASIO_EXPERIMENTAL_CONCURRENT_CHANNEL_HPP
+ link/modules/asio-standalone/asio/include/asio/experimental/coro.hpp view
@@ -0,0 +1,293 @@+//+// experimental/coro.hpp+// ~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2021-2023 Klemens D. Morgenstern+// (klemens dot morgenstern at gmx dot net)+//+// Distributed under the Boost Software License, Version 1.0. (See accompanying+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)+//++#ifndef ASIO_EXPERIMENTAL_CORO_HPP+#define ASIO_EXPERIMENTAL_CORO_HPP++#if defined(_MSC_VER) && (_MSC_VER >= 1200)+# pragma once+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)++#include "asio/detail/config.hpp"+#include "asio/dispatch.hpp"+#include "asio/error.hpp"+#include "asio/error_code.hpp"+#include "asio/experimental/coro_traits.hpp"+#include "asio/experimental/detail/coro_promise_allocator.hpp"+#include "asio/experimental/detail/partial_promise.hpp"+#include "asio/post.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {+namespace experimental {+namespace detail {++template <typename Signature, typename Return,+ typename Executor, typename Allocator>+struct coro_promise;++template <typename T, typename Coroutine>+struct coro_with_arg;++} // namespace detail++/// The main type of a resumable coroutine.+/**+ * Template parameter @c Yield specifies type or signature used by co_yield,+ * @c Return specifies the type used for co_return, and @c Executor specifies+ * the underlying executor type.+ */+template <typename Yield = void, typename Return = void,+ typename Executor = any_io_executor,+ typename Allocator = std::allocator<void>>+struct coro+{+ /// The traits of the coroutine. See asio::experimental::coro_traits+ /// for details.+ using traits = coro_traits<Yield, Return, Executor>;++ /// The value that can be passed into a symmetrical cororoutine. @c void if+ /// asymmetrical.+ using input_type = typename traits::input_type;++ /// The type that can be passed out through a co_yield.+ using yield_type = typename traits::yield_type;++ /// The type that can be passed out through a co_return.+ using return_type = typename traits::return_type;++ /// The type received by a co_await or async_resume. Its a combination of+ /// yield and return.+ using result_type = typename traits::result_type;++ /// The signature used by the async_resume.+ using signature_type = typename traits::signature_type;++ /// Whether or not the coroutine is noexcept.+ constexpr static bool is_noexcept = traits::is_noexcept;++ /// The error type of the coroutine. Void for noexcept+ using error_type = typename traits::error_type;++ /// Completion handler type used by async_resume.+ using completion_handler = typename traits::completion_handler;++ /// The internal promise-type of the coroutine.+ using promise_type = detail::coro_promise<Yield, Return, Executor, Allocator>;++#if !defined(GENERATING_DOCUMENTATION)+ template <typename T, typename Coroutine>+ friend struct detail::coro_with_arg;+#endif // !defined(GENERATING_DOCUMENTATION)++ /// The executor type.+ using executor_type = Executor;++ /// The allocator type.+ using allocator_type = Allocator;++#if !defined(GENERATING_DOCUMENTATION)+ friend struct detail::coro_promise<Yield, Return, Executor, Allocator>;+#endif // !defined(GENERATING_DOCUMENTATION)++ /// The default constructor, gives an invalid coroutine.+ coro() = default;++ /// Move constructor.+ coro(coro&& lhs) noexcept+ : coro_(std::exchange(lhs.coro_, nullptr))+ {+ }++ coro(const coro&) = delete;++ /// Move assignment.+ coro& operator=(coro&& lhs) noexcept+ {+ std::swap(coro_, lhs.coro_);+ return *this;+ }++ coro& operator=(const coro&) = delete;++ /// Destructor. Destroys the coroutine, if it holds a valid one.+ /**+ * @note This does not cancel an active coroutine. Destructing a resumable+ * coroutine, i.e. one with a call to async_resume that has not completed, is+ * undefined behaviour.+ */+ ~coro()+ {+ if (coro_ != nullptr)+ {+ struct destroyer+ {+ detail::coroutine_handle<promise_type> handle;++ destroyer(const detail::coroutine_handle<promise_type>& handle)+ : handle(handle)+ { }++ destroyer(destroyer&& lhs)+ : handle(std::exchange(lhs.handle, nullptr))+ {+ }++ destroyer(const destroyer&) = delete;++ void operator()() {}++ ~destroyer()+ {+ if (handle)+ handle.destroy();+ }+ };++ auto handle =+ detail::coroutine_handle<promise_type>::from_promise(*coro_);+ if (handle)+ asio::dispatch(coro_->get_executor(), destroyer{handle});+ }+ }++ /// Get the used executor.+ executor_type get_executor() const+ {+ if (coro_)+ return coro_->get_executor();++ if constexpr (std::is_default_constructible_v<Executor>)+ return Executor{};+ else+ throw std::logic_error("Coroutine has no executor");+ }++ /// Get the used allocator.+ allocator_type get_allocator() const+ {+ if (coro_)+ return coro_->get_allocator();++ if constexpr (std::is_default_constructible_v<Allocator>)+ return Allocator{};+ else+ throw std::logic_error(+ "Coroutine has no available allocator without a constructed promise");+ }++ /// Resume the coroutine.+ /**+ * @param token The completion token of the async resume.+ *+ * @attention Calling an invalid coroutine with a noexcept signature is+ * undefined behaviour.+ *+ * @note This overload is only available for coroutines without an input+ * value.+ */+ template <typename CompletionToken>+ requires std::is_void_v<input_type>+ auto async_resume(CompletionToken&& token) &+ {+ return async_initiate<CompletionToken,+ typename traits::completion_handler>(+ initiate_async_resume(this), token);+ }++ /// Resume the coroutine.+ /**+ * @param token The completion token of the async resume.+ *+ * @attention Calling an invalid coroutine with a noexcept signature is+ * undefined behaviour.+ *+ * @note This overload is only available for coroutines with an input value.+ */+ template <typename CompletionToken, detail::convertible_to<input_type> T>+ auto async_resume(T&& ip, CompletionToken&& token) &+ {+ return async_initiate<CompletionToken,+ typename traits::completion_handler>(+ initiate_async_resume(this), token, std::forward<T>(ip));+ }++ /// Operator used for coroutines without input value.+ auto operator co_await() requires (std::is_void_v<input_type>)+ {+ return awaitable_t{*this};+ }++ /// Operator used for coroutines with input value.+ /**+ * @param ip The input value+ *+ * @returns An awaitable handle.+ *+ * @code+ * coro<void> push_values(coro<double(int)> c)+ * {+ * std::optional<double> res = co_await c(42);+ * }+ * @endcode+ */+ template <detail::convertible_to<input_type> T>+ auto operator()(T&& ip)+ {+ return detail::coro_with_arg<std::decay_t<T>, coro>{+ std::forward<T>(ip), *this};+ }++ /// Check whether the coroutine is open, i.e. can be resumed.+ bool is_open() const+ {+ if (coro_)+ {+ auto handle =+ detail::coroutine_handle<promise_type>::from_promise(*coro_);+ return handle && !handle.done();+ }+ else+ return false;+ }++ /// Check whether the coroutine is open, i.e. can be resumed.+ explicit operator bool() const { return is_open(); }++private:+ struct awaitable_t;++ struct initiate_async_resume;++ explicit coro(promise_type* const cr) : coro_(cr) {}++ promise_type* coro_{nullptr};+};++/// A generator is a coro that returns void and yields value.+template<typename T, typename Executor = asio::any_io_executor,+ typename Allocator = std::allocator<void>>+using generator = coro<T, void, Executor, Allocator>;++/// A task is a coro that does not yield values+template<typename T, typename Executor = asio::any_io_executor,+ typename Allocator = std::allocator<void>>+using task = coro<void(), T, Executor, Allocator>;++} // namespace experimental+} // namespace asio++#include "asio/detail/pop_options.hpp"++#include "asio/experimental/impl/coro.hpp"++#endif // ASIO_EXPERIMENTAL_CORO_HPP
+ link/modules/asio-standalone/asio/include/asio/experimental/coro_traits.hpp view
@@ -0,0 +1,228 @@+//+// experimental/detail/coro_traits.hpp+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2021-2023 Klemens D. Morgenstern+// (klemens dot morgenstern at gmx dot net)+//+// Distributed under the Boost Software License, Version 1.0. (See accompanying+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)+//++#ifndef ASIO_EXPERIMENTAL_DETAIL_CORO_TRAITS_HPP+#define ASIO_EXPERIMENTAL_DETAIL_CORO_TRAITS_HPP++#if defined(_MSC_VER) && (_MSC_VER >= 1200)+# pragma once+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)++#include "asio/detail/config.hpp"+#include <optional>+#include <variant>+#include "asio/any_io_executor.hpp"++namespace asio {+namespace experimental {+namespace detail {++template <class From, class To>+concept convertible_to = std::is_convertible_v<From, To>;++template <typename T>+concept decays_to_executor = execution::executor<std::decay_t<T>>;++template <typename T, typename Executor = any_io_executor>+concept execution_context = requires (T& t)+{+ {t.get_executor()} -> convertible_to<Executor>;+};++template <typename Yield, typename Return>+struct coro_result+{+ using type = std::variant<Yield, Return>;+};++template <typename Yield>+struct coro_result<Yield, void>+{+ using type = std::optional<Yield>;+};++template <typename Return>+struct coro_result<void, Return>+{+ using type = Return;+};++template <typename YieldReturn>+struct coro_result<YieldReturn, YieldReturn>+{+ using type = YieldReturn;+};++template <>+struct coro_result<void, void>+{+ using type = void;+};++template <typename Yield, typename Return>+using coro_result_t = typename coro_result<Yield, Return>::type;++template <typename Result, bool IsNoexcept>+struct coro_handler;++template <>+struct coro_handler<void, false>+{+ using type = void(std::exception_ptr);+};++template <>+struct coro_handler<void, true>+{+ using type = void();+};++template <typename T>+struct coro_handler<T, false>+{+ using type = void(std::exception_ptr, T);+};++template <typename T>+struct coro_handler<T, true>+{+ using type = void(T);+};++template <typename Result, bool IsNoexcept>+using coro_handler_t = typename coro_handler<Result, IsNoexcept>::type;++} // namespace detail++#if defined(GENERATING_DOCUMENTATION)++/// The traits describing the resumable coroutine behaviour.+/**+ * Template parameter @c Yield specifies type or signature used by co_yield,+ * @c Return specifies the type used for co_return, and @c Executor specifies+ * the underlying executor type.+ */+template <typename Yield, typename Return, typename Executor>+struct coro_traits+{+ /// The value that can be passed into a symmetrical cororoutine. @c void if+ /// asymmetrical.+ using input_type = argument_dependent;++ /// The type that can be passed out through a co_yield.+ using yield_type = argument_dependent;++ /// The type that can be passed out through a co_return.+ using return_type = argument_dependent;++ /// The type received by a co_await or async_resume. It's a combination of+ /// yield and return.+ using result_type = argument_dependent;++ /// The signature used by the async_resume.+ using signature_type = argument_dependent;++ /// Whether or not the coroutine is noexcept.+ constexpr static bool is_noexcept = argument_dependent;++ /// The error type of the coroutine. @c void for noexcept.+ using error_type = argument_dependent;++ /// Completion handler type used by async_resume.+ using completion_handler = argument_dependent;+};++#else // defined(GENERATING_DOCUMENTATION)++template <typename Yield, typename Return, typename Executor>+struct coro_traits+{+ using input_type = void;+ using yield_type = Yield;+ using return_type = Return;+ using result_type = detail::coro_result_t<yield_type, return_type>;+ using signature_type = result_type();+ constexpr static bool is_noexcept = false;+ using error_type = std::conditional_t<is_noexcept, void, std::exception_ptr>;+ using completion_handler = detail::coro_handler_t<result_type, is_noexcept>;+};++template <typename T, typename Return, typename Executor>+struct coro_traits<T(), Return, Executor>+{+ using input_type = void;+ using yield_type = T;+ using return_type = Return;+ using result_type = detail::coro_result_t<yield_type, return_type>;+ using signature_type = result_type();+ constexpr static bool is_noexcept = false;+ using error_type = std::conditional_t<is_noexcept, void, std::exception_ptr>;+ using completion_handler = detail::coro_handler_t<result_type, is_noexcept>;+};++template <typename T, typename Return, typename Executor>+struct coro_traits<T() noexcept, Return, Executor>+{+ using input_type = void;+ using yield_type = T;+ using return_type = Return;+ using result_type = detail::coro_result_t<yield_type, return_type>;+ using signature_type = result_type();+ constexpr static bool is_noexcept = true;+ using error_type = std::conditional_t<is_noexcept, void, std::exception_ptr>;+ using completion_handler = detail::coro_handler_t<result_type, is_noexcept>;+};++template <typename T, typename U, typename Return, typename Executor>+struct coro_traits<T(U), Return, Executor>+{+ using input_type = U;+ using yield_type = T;+ using return_type = Return;+ using result_type = detail::coro_result_t<yield_type, return_type>;+ using signature_type = result_type(input_type);+ constexpr static bool is_noexcept = false;+ using error_type = std::conditional_t<is_noexcept, void, std::exception_ptr>;+ using completion_handler = detail::coro_handler_t<result_type, is_noexcept>;+};++template <typename T, typename U, typename Return, typename Executor>+struct coro_traits<T(U) noexcept, Return, Executor>+{+ using input_type = U;+ using yield_type = T;+ using return_type = Return;+ using result_type = detail::coro_result_t<yield_type, return_type>;+ using signature_type = result_type(input_type);+ constexpr static bool is_noexcept = true;+ using error_type = std::conditional_t<is_noexcept, void, std::exception_ptr>;+ using completion_handler = detail::coro_handler_t<result_type, is_noexcept>;+};++template <typename Executor>+struct coro_traits<void() noexcept, void, Executor>+{+ using input_type = void;+ using yield_type = void;+ using return_type = void;+ using result_type = detail::coro_result_t<yield_type, return_type>;+ using signature_type = result_type(input_type);+ constexpr static bool is_noexcept = true;+ using error_type = std::conditional_t<is_noexcept, void, std::exception_ptr>;+ using completion_handler = detail::coro_handler_t<result_type, is_noexcept>;+};++#endif // defined(GENERATING_DOCUMENTATION)++} // namespace experimental+} // namespace asio++#endif // ASIO_EXPERIMENTAL_DETAIL_CORO_TRAITS_HPP
+ link/modules/asio-standalone/asio/include/asio/experimental/deferred.hpp view
@@ -0,0 +1,36 @@+//+// experimental/deferred.hpp+// ~~~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com)+//+// Distributed under the Boost Software License, Version 1.0. (See accompanying+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)+//++#ifndef ASIO_EXPERIMENTAL_DEFERRED_HPP+#define ASIO_EXPERIMENTAL_DEFERRED_HPP++#if defined(_MSC_VER) && (_MSC_VER >= 1200)+# pragma once+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)++#include "asio/detail/config.hpp"+#include "asio/deferred.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {+namespace experimental {++#if !defined(ASIO_NO_DEPRECATED)+using asio::deferred_t;+using asio::deferred;+#endif // !defined(ASIO_NO_DEPRECATED)++} // namespace experimental+} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // ASIO_EXPERIMENTAL_DEFERRED_HPP
+ link/modules/asio-standalone/asio/include/asio/experimental/detail/channel_handler.hpp view
@@ -0,0 +1,80 @@+//+// experimental/detail/channel_handler.hpp+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com)+//+// Distributed under the Boost Software License, Version 1.0. (See accompanying+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)+//++#ifndef ASIO_EXPERIMENTAL_DETAIL_CHANNEL_HANDLER_HPP+#define ASIO_EXPERIMENTAL_DETAIL_CHANNEL_HANDLER_HPP++#if defined(_MSC_VER) && (_MSC_VER >= 1200)+# pragma once+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)++#include "asio/detail/config.hpp"+#include "asio/associator.hpp"+#include "asio/experimental/detail/channel_payload.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {+namespace experimental {+namespace detail {++template <typename Payload, typename Handler>+class channel_handler+{+public:+ channel_handler(ASIO_MOVE_ARG(Payload) p, Handler& h)+ : payload_(ASIO_MOVE_CAST(Payload)(p)),+ handler_(ASIO_MOVE_CAST(Handler)(h))+ {+ }++ void operator()()+ {+ payload_.receive(handler_);+ }++//private:+ Payload payload_;+ Handler handler_;+};++} // namespace detail+} // namespace experimental++template <template <typename, typename> class Associator,+ typename Payload, typename Handler, typename DefaultCandidate>+struct associator<Associator,+ experimental::detail::channel_handler<Payload, Handler>,+ DefaultCandidate>+ : Associator<Handler, DefaultCandidate>+{+ static typename Associator<Handler, DefaultCandidate>::type+ get(const experimental::detail::channel_handler<Payload, Handler>& h)+ ASIO_NOEXCEPT+ {+ return Associator<Handler, DefaultCandidate>::get(h.handler_);+ }++ static ASIO_AUTO_RETURN_TYPE_PREFIX2(+ typename Associator<Handler, DefaultCandidate>::type)+ get(const experimental::detail::channel_handler<Payload, Handler>& h,+ const DefaultCandidate& c) ASIO_NOEXCEPT+ ASIO_AUTO_RETURN_TYPE_SUFFIX((+ Associator<Handler, DefaultCandidate>::get(h.handler_, c)))+ {+ return Associator<Handler, DefaultCandidate>::get(h.handler_, c);+ }+};++} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // ASIO_EXPERIMENTAL_DETAIL_CHANNEL_HANDLER_HPP
+ link/modules/asio-standalone/asio/include/asio/experimental/detail/channel_message.hpp view
@@ -0,0 +1,129 @@+//+// experimental/detail/channel_message.hpp+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com)+//+// Distributed under the Boost Software License, Version 1.0. (See accompanying+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)+//++#ifndef ASIO_EXPERIMENTAL_DETAIL_CHANNEL_MESSAGE_HPP+#define ASIO_EXPERIMENTAL_DETAIL_CHANNEL_MESSAGE_HPP++#if defined(_MSC_VER) && (_MSC_VER >= 1200)+# pragma once+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)++#include "asio/detail/config.hpp"+#include <tuple>+#include "asio/detail/type_traits.hpp"+#include "asio/detail/utility.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {+namespace experimental {+namespace detail {++template <typename Signature>+class channel_message;++template <typename R>+class channel_message<R()>+{+public:+ channel_message(int)+ {+ }++ template <typename Handler>+ void receive(Handler& handler)+ {+ ASIO_MOVE_OR_LVALUE(Handler)(handler)();+ }+};++template <typename R, typename Arg0>+class channel_message<R(Arg0)>+{+public:+ template <typename T0>+ channel_message(int, ASIO_MOVE_ARG(T0) t0)+ : arg0_(ASIO_MOVE_CAST(T0)(t0))+ {+ }++ template <typename Handler>+ void receive(Handler& handler)+ {+ ASIO_MOVE_OR_LVALUE(Handler)(handler)(+ ASIO_MOVE_CAST(arg0_type)(arg0_));+ }++private:+ typedef typename decay<Arg0>::type arg0_type;+ arg0_type arg0_;+};++template <typename R, typename Arg0, typename Arg1>+class channel_message<R(Arg0, Arg1)>+{+public:+ template <typename T0, typename T1>+ channel_message(int, ASIO_MOVE_ARG(T0) t0, ASIO_MOVE_ARG(T1) t1)+ : arg0_(ASIO_MOVE_CAST(T0)(t0)),+ arg1_(ASIO_MOVE_CAST(T1)(t1))+ {+ }++ template <typename Handler>+ void receive(Handler& handler)+ {+ ASIO_MOVE_OR_LVALUE(Handler)(handler)(+ ASIO_MOVE_CAST(arg0_type)(arg0_),+ ASIO_MOVE_CAST(arg1_type)(arg1_));+ }++private:+ typedef typename decay<Arg0>::type arg0_type;+ arg0_type arg0_;+ typedef typename decay<Arg1>::type arg1_type;+ arg1_type arg1_;+};++template <typename R, typename... Args>+class channel_message<R(Args...)>+{+public:+ template <typename... T>+ channel_message(int, ASIO_MOVE_ARG(T)... t)+ : args_(ASIO_MOVE_CAST(T)(t)...)+ {+ }++ template <typename Handler>+ void receive(Handler& h)+ {+ this->do_receive(h, asio::detail::index_sequence_for<Args...>());+ }++private:+ template <typename Handler, std::size_t... I>+ void do_receive(Handler& h, asio::detail::index_sequence<I...>)+ {+ ASIO_MOVE_OR_LVALUE(Handler)(h)(+ std::get<I>(ASIO_MOVE_CAST(args_type)(args_))...);+ }++ typedef std::tuple<typename decay<Args>::type...> args_type;+ args_type args_;+};++} // namespace detail+} // namespace experimental+} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // ASIO_EXPERIMENTAL_DETAIL_CHANNEL_MESSAGE_HPP
+ link/modules/asio-standalone/asio/include/asio/experimental/detail/channel_operation.hpp view
@@ -0,0 +1,284 @@+//+// experimental/detail/channel_operation.hpp+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com)+//+// Distributed under the Boost Software License, Version 1.0. (See accompanying+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)+//++#ifndef ASIO_EXPERIMENTAL_DETAIL_CHANNEL_OPERATION_HPP+#define ASIO_EXPERIMENTAL_DETAIL_CHANNEL_OPERATION_HPP++#if defined(_MSC_VER) && (_MSC_VER >= 1200)+# pragma once+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)++#include "asio/detail/config.hpp"+#include "asio/associated_allocator.hpp"+#include "asio/associated_executor.hpp"+#include "asio/associated_immediate_executor.hpp"+#include "asio/detail/initiate_post.hpp"+#include "asio/detail/initiate_dispatch.hpp"+#include "asio/detail/op_queue.hpp"+#include "asio/detail/type_traits.hpp"+#include "asio/execution/executor.hpp"+#include "asio/execution/outstanding_work.hpp"+#include "asio/executor_work_guard.hpp"+#include "asio/prefer.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {+namespace experimental {+namespace detail {++// Base class for all channel operations. A function pointer is used instead of+// virtual functions to avoid the associated overhead.+class channel_operation ASIO_INHERIT_TRACKED_HANDLER+{+public:+ template <typename Executor, typename = void>+ class handler_work_base;++ template <typename Handler, typename IoExecutor, typename = void>+ class handler_work;++ void destroy()+ {+ func_(this, destroy_op, 0);+ }++protected:+ enum action+ {+ destroy_op = 0,+ immediate_op = 1,+ complete_op = 2,+ cancel_op = 3,+ close_op = 4+ };++ typedef void (*func_type)(channel_operation*, action, void*);++ channel_operation(func_type func)+ : next_(0),+ func_(func),+ cancellation_key_(0)+ {+ }++ // Prevents deletion through this type.+ ~channel_operation()+ {+ }++ friend class asio::detail::op_queue_access;+ channel_operation* next_;+ func_type func_;++public:+ // The operation key used for targeted cancellation.+ void* cancellation_key_;+};++template <typename Executor, typename>+class channel_operation::handler_work_base+{+public:+ typedef typename decay<+ typename prefer_result<Executor,+ execution::outstanding_work_t::tracked_t+ >::type+ >::type executor_type;++ handler_work_base(int, const Executor& ex)+ : executor_(asio::prefer(ex, execution::outstanding_work.tracked))+ {+ }++ const executor_type& get_executor() const ASIO_NOEXCEPT+ {+ return executor_;+ }++ template <typename Function, typename Handler>+ void post(Function& function, Handler& handler)+ {+ typename associated_allocator<Handler>::type allocator =+ (get_associated_allocator)(handler);++#if defined(ASIO_NO_DEPRECATED)+ asio::prefer(+ asio::require(executor_, execution::blocking.never),+ execution::allocator(allocator)+ ).execute(ASIO_MOVE_CAST(Function)(function));+#else // defined(ASIO_NO_DEPRECATED)+ execution::execute(+ asio::prefer(+ asio::require(executor_, execution::blocking.never),+ execution::allocator(allocator)),+ ASIO_MOVE_CAST(Function)(function));+#endif // defined(ASIO_NO_DEPRECATED)+ }++private:+ executor_type executor_;+};++#if !defined(ASIO_NO_TS_EXECUTORS)++template <typename Executor>+class channel_operation::handler_work_base<Executor,+ typename enable_if<+ !execution::is_executor<Executor>::value+ >::type>+{+public:+ typedef Executor executor_type;++ handler_work_base(int, const Executor& ex)+ : work_(ex)+ {+ }++ executor_type get_executor() const ASIO_NOEXCEPT+ {+ return work_.get_executor();+ }++ template <typename Function, typename Handler>+ void post(Function& function, Handler& handler)+ {+ typename associated_allocator<Handler>::type allocator =+ (get_associated_allocator)(handler);++ work_.get_executor().post(+ ASIO_MOVE_CAST(Function)(function), allocator);+ }++private:+ executor_work_guard<Executor> work_;+};++#endif // !defined(ASIO_NO_TS_EXECUTORS)++template <typename Handler, typename IoExecutor, typename>+class channel_operation::handler_work :+ channel_operation::handler_work_base<IoExecutor>,+ channel_operation::handler_work_base<+ typename associated_executor<Handler, IoExecutor>::type, IoExecutor>+{+public:+ typedef channel_operation::handler_work_base<IoExecutor> base1_type;++ typedef channel_operation::handler_work_base<+ typename associated_executor<Handler, IoExecutor>::type, IoExecutor>+ base2_type;++ handler_work(Handler& handler, const IoExecutor& io_ex) ASIO_NOEXCEPT+ : base1_type(0, io_ex),+ base2_type(0, (get_associated_executor)(handler, io_ex))+ {+ }++ template <typename Function>+ void complete(Function& function, Handler& handler)+ {+ base2_type::post(function, handler);+ }++ template <typename Function>+ void immediate(Function& function, Handler& handler, ...)+ {+ typedef typename associated_immediate_executor<Handler,+ typename base1_type::executor_type>::type immediate_ex_type;++ immediate_ex_type immediate_ex = (get_associated_immediate_executor)(+ handler, base1_type::get_executor());++ (asio::detail::initiate_dispatch_with_executor<immediate_ex_type>(+ immediate_ex))(ASIO_MOVE_CAST(Function)(function));+ }++ template <typename Function>+ void immediate(Function& function, Handler&,+ typename enable_if<+ is_same<+ typename associated_immediate_executor<+ typename conditional<false, Function, Handler>::type,+ typename base1_type::executor_type>::+ asio_associated_immediate_executor_is_unspecialised,+ void+ >::value+ >::type*)+ {+ (asio::detail::initiate_post_with_executor<+ typename base1_type::executor_type>(+ base1_type::get_executor()))(+ ASIO_MOVE_CAST(Function)(function));+ }+};++template <typename Handler, typename IoExecutor>+class channel_operation::handler_work<+ Handler, IoExecutor,+ typename enable_if<+ is_same<+ typename associated_executor<Handler,+ IoExecutor>::asio_associated_executor_is_unspecialised,+ void+ >::value+ >::type> : handler_work_base<IoExecutor>+{+public:+ typedef channel_operation::handler_work_base<IoExecutor> base1_type;++ handler_work(Handler&, const IoExecutor& io_ex) ASIO_NOEXCEPT+ : base1_type(0, io_ex)+ {+ }++ template <typename Function>+ void complete(Function& function, Handler& handler)+ {+ base1_type::post(function, handler);+ }++ template <typename Function>+ void immediate(Function& function, Handler& handler, ...)+ {+ typedef typename associated_immediate_executor<Handler,+ typename base1_type::executor_type>::type immediate_ex_type;++ immediate_ex_type immediate_ex = (get_associated_immediate_executor)(+ handler, base1_type::get_executor());++ (asio::detail::initiate_dispatch_with_executor<immediate_ex_type>(+ immediate_ex))(ASIO_MOVE_CAST(Function)(function));+ }++ template <typename Function>+ void immediate(Function& function, Handler& handler,+ typename enable_if<+ is_same<+ typename associated_immediate_executor<+ typename conditional<false, Function, Handler>::type,+ typename base1_type::executor_type>::+ asio_associated_immediate_executor_is_unspecialised,+ void+ >::value+ >::type*)+ {+ base1_type::post(function, handler);+ }+};++} // namespace detail+} // namespace experimental+} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // ASIO_EXPERIMENTAL_DETAIL_CHANNEL_OPERATION_HPP
+ link/modules/asio-standalone/asio/include/asio/experimental/detail/channel_payload.hpp view
@@ -0,0 +1,139 @@+//+// experimental/detail/channel_payload.hpp+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com)+//+// Distributed under the Boost Software License, Version 1.0. (See accompanying+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)+//++#ifndef ASIO_EXPERIMENTAL_DETAIL_CHANNEL_PAYLOAD_HPP+#define ASIO_EXPERIMENTAL_DETAIL_CHANNEL_PAYLOAD_HPP++#if defined(_MSC_VER) && (_MSC_VER >= 1200)+# pragma once+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)++#include "asio/detail/config.hpp"+#include "asio/detail/type_traits.hpp"+#include "asio/error_code.hpp"+#include "asio/experimental/detail/channel_message.hpp"++#if defined(ASIO_HAS_STD_VARIANT)+# include <variant>+#endif // defined(ASIO_HAS_STD_VARIANT)++#include "asio/detail/push_options.hpp"++namespace asio {+namespace experimental {+namespace detail {++template <typename... Signatures>+class channel_payload;++template <typename R>+class channel_payload<R()>+{+public:+ explicit channel_payload(channel_message<R()>)+ {+ }++ template <typename Handler>+ void receive(Handler& handler)+ {+ ASIO_MOVE_OR_LVALUE(Handler)(handler)();+ }+};++template <typename Signature>+class channel_payload<Signature>+{+public:+ channel_payload(ASIO_MOVE_ARG(channel_message<Signature>) m)+ : message_(ASIO_MOVE_CAST(channel_message<Signature>)(m))+ {+ }++ template <typename Handler>+ void receive(Handler& handler)+ {+ message_.receive(handler);+ }++private:+ channel_message<Signature> message_;+};++#if defined(ASIO_HAS_STD_VARIANT)++template <typename... Signatures>+class channel_payload+{+public:+ template <typename Signature>+ channel_payload(ASIO_MOVE_ARG(channel_message<Signature>) m)+ : message_(ASIO_MOVE_CAST(channel_message<Signature>)(m))+ {+ }++ template <typename Handler>+ void receive(Handler& handler)+ {+ std::visit(+ [&](auto& message)+ {+ message.receive(handler);+ }, message_);+ }++private:+ std::variant<channel_message<Signatures>...> message_;+};++#else // defined(ASIO_HAS_STD_VARIANT)++template <typename R1, typename R2>+class channel_payload<R1(), R2(asio::error_code)>+{+public:+ typedef channel_message<R1()> void_message_type;+ typedef channel_message<R2(asio::error_code)> error_message_type;++ channel_payload(ASIO_MOVE_ARG(void_message_type))+ : message_(0, asio::error_code()),+ empty_(true)+ {+ }++ channel_payload(ASIO_MOVE_ARG(error_message_type) m)+ : message_(ASIO_MOVE_CAST(error_message_type)(m)),+ empty_(false)+ {+ }++ template <typename Handler>+ void receive(Handler& handler)+ {+ if (empty_)+ channel_message<R1()>(0).receive(handler);+ else+ message_.receive(handler);+ }++private:+ error_message_type message_;+ bool empty_;+};++#endif // defined(ASIO_HAS_STD_VARIANT)++} // namespace detail+} // namespace experimental+} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // ASIO_EXPERIMENTAL_DETAIL_CHANNEL_PAYLOAD_HPP
+ link/modules/asio-standalone/asio/include/asio/experimental/detail/channel_receive_op.hpp view
@@ -0,0 +1,120 @@+//+// experimental/detail/channel_receive_op.hpp+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com)+//+// Distributed under the Boost Software License, Version 1.0. (See accompanying+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)+//++#ifndef ASIO_EXPERIMENTAL_DETAIL_CHANNEL_RECEIVE_OP_HPP+#define ASIO_EXPERIMENTAL_DETAIL_CHANNEL_RECEIVE_OP_HPP++#if defined(_MSC_VER) && (_MSC_VER >= 1200)+# pragma once+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)++#include "asio/detail/config.hpp"+#include "asio/detail/bind_handler.hpp"+#include "asio/detail/handler_alloc_helpers.hpp"+#include "asio/error.hpp"+#include "asio/experimental/detail/channel_handler.hpp"+#include "asio/experimental/detail/channel_operation.hpp"+#include "asio/experimental/detail/channel_payload.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {+namespace experimental {+namespace detail {++template <typename Payload>+class channel_receive : public channel_operation+{+public:+ void immediate(Payload payload)+ {+ func_(this, immediate_op, &payload);+ }++ void complete(Payload payload)+ {+ func_(this, complete_op, &payload);+ }++protected:+ channel_receive(func_type func)+ : channel_operation(func)+ {+ }+};++template <typename Payload, typename Handler, typename IoExecutor>+class channel_receive_op : public channel_receive<Payload>+{+public:+ ASIO_DEFINE_HANDLER_PTR(channel_receive_op);++ template <typename... Args>+ channel_receive_op(Handler& handler, const IoExecutor& io_ex)+ : channel_receive<Payload>(&channel_receive_op::do_action),+ handler_(ASIO_MOVE_CAST(Handler)(handler)),+ work_(handler_, io_ex)+ {+ }++ static void do_action(channel_operation* base,+ channel_operation::action a, void* v)+ {+ // Take ownership of the operation object.+ channel_receive_op* o(static_cast<channel_receive_op*>(base));+ ptr p = { asio::detail::addressof(o->handler_), o, o };++ ASIO_HANDLER_COMPLETION((*o));++ // Take ownership of the operation's outstanding work.+ channel_operation::handler_work<Handler, IoExecutor> w(+ ASIO_MOVE_CAST2(channel_operation::handler_work<+ Handler, IoExecutor>)(o->work_));++ // Make a copy of the handler so that the memory can be deallocated before+ // the handler is posted. Even if we're not about to post the handler, a+ // sub-object of the handler may be the true owner of the memory associated+ // with the handler. Consequently, a local copy of the handler is required+ // to ensure that any owning sub-object remains valid until after we have+ // deallocated the memory here.+ if (a != channel_operation::destroy_op)+ {+ Payload* payload = static_cast<Payload*>(v);+ channel_handler<Payload, Handler> handler(+ ASIO_MOVE_CAST(Payload)(*payload), o->handler_);+ p.h = asio::detail::addressof(handler.handler_);+ p.reset();+ ASIO_HANDLER_INVOCATION_BEGIN(());+ if (a == channel_operation::immediate_op)+ w.immediate(handler, handler.handler_, 0);+ else+ w.complete(handler, handler.handler_);+ ASIO_HANDLER_INVOCATION_END;+ }+ else+ {+ asio::detail::binder0<Handler> handler(o->handler_);+ p.h = asio::detail::addressof(handler.handler_);+ p.reset();+ }+ }++private:+ Handler handler_;+ channel_operation::handler_work<Handler, IoExecutor> work_;+};++} // namespace detail+} // namespace experimental+} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // ASIO_EXPERIMENTAL_DETAIL_CHANNEL_RECEIVE_OP_HPP
+ link/modules/asio-standalone/asio/include/asio/experimental/detail/channel_send_functions.hpp view
@@ -0,0 +1,144 @@+//+// experimental/detail/channel_send_functions.hpp+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com)+//+// Distributed under the Boost Software License, Version 1.0. (See accompanying+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)+//++#ifndef ASIO_EXPERIMENTAL_DETAIL_CHANNEL_SEND_FUNCTIONS_HPP+#define ASIO_EXPERIMENTAL_DETAIL_CHANNEL_SEND_FUNCTIONS_HPP++#if defined(_MSC_VER) && (_MSC_VER >= 1200)+# pragma once+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)++#include "asio/detail/config.hpp"+#include "asio/async_result.hpp"+#include "asio/detail/type_traits.hpp"+#include "asio/error_code.hpp"+#include "asio/experimental/detail/channel_message.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {+namespace experimental {+namespace detail {++template <typename Derived, typename Executor, typename... Signatures>+class channel_send_functions;++template <typename Derived, typename Executor, typename R, typename... Args>+class channel_send_functions<Derived, Executor, R(Args...)>+{+public:+ template <typename... Args2>+ typename enable_if<+ is_constructible<detail::channel_message<R(Args...)>, int, Args2...>::value,+ bool+ >::type try_send(ASIO_MOVE_ARG(Args2)... args)+ {+ typedef typename detail::channel_message<R(Args...)> message_type;+ Derived* self = static_cast<Derived*>(this);+ return self->service_->template try_send<message_type>(+ self->impl_, ASIO_MOVE_CAST(Args2)(args)...);+ }++ template <typename... Args2>+ typename enable_if<+ is_constructible<detail::channel_message<R(Args...)>, int, Args2...>::value,+ std::size_t+ >::type try_send_n(std::size_t count, ASIO_MOVE_ARG(Args2)... args)+ {+ typedef typename detail::channel_message<R(Args...)> message_type;+ Derived* self = static_cast<Derived*>(this);+ return self->service_->template try_send_n<message_type>(+ self->impl_, count, ASIO_MOVE_CAST(Args2)(args)...);+ }++ template <+ ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code))+ CompletionToken ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(Executor)>+ auto async_send(Args... args,+ ASIO_MOVE_ARG(CompletionToken) token+ ASIO_DEFAULT_COMPLETION_TOKEN(Executor))+ -> decltype(+ async_initiate<CompletionToken, void (asio::error_code)>(+ declval<typename conditional<false, CompletionToken,+ Derived>::type::initiate_async_send>(), token,+ declval<typename conditional<false, CompletionToken,+ Derived>::type::payload_type>()))+ {+ typedef typename Derived::payload_type payload_type;+ typedef typename detail::channel_message<R(Args...)> message_type;+ Derived* self = static_cast<Derived*>(this);+ return async_initiate<CompletionToken, void (asio::error_code)>(+ typename Derived::initiate_async_send(self), token,+ payload_type(message_type(0, ASIO_MOVE_CAST(Args)(args)...)));+ }+};++template <typename Derived, typename Executor,+ typename R, typename... Args, typename... Signatures>+class channel_send_functions<Derived, Executor, R(Args...), Signatures...> :+ public channel_send_functions<Derived, Executor, Signatures...>+{+public:+ using channel_send_functions<Derived, Executor, Signatures...>::try_send;+ using channel_send_functions<Derived, Executor, Signatures...>::async_send;++ template <typename... Args2>+ typename enable_if<+ is_constructible<detail::channel_message<R(Args...)>, int, Args2...>::value,+ bool+ >::type try_send(ASIO_MOVE_ARG(Args2)... args)+ {+ typedef typename detail::channel_message<R(Args...)> message_type;+ Derived* self = static_cast<Derived*>(this);+ return self->service_->template try_send<message_type>(+ self->impl_, ASIO_MOVE_CAST(Args2)(args)...);+ }++ template <typename... Args2>+ typename enable_if<+ is_constructible<detail::channel_message<R(Args...)>, int, Args2...>::value,+ std::size_t+ >::type try_send_n(std::size_t count, ASIO_MOVE_ARG(Args2)... args)+ {+ typedef typename detail::channel_message<R(Args...)> message_type;+ Derived* self = static_cast<Derived*>(this);+ return self->service_->template try_send_n<message_type>(+ self->impl_, count, ASIO_MOVE_CAST(Args2)(args)...);+ }++ template <+ ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code))+ CompletionToken ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(Executor)>+ auto async_send(Args... args,+ ASIO_MOVE_ARG(CompletionToken) token+ ASIO_DEFAULT_COMPLETION_TOKEN(Executor))+ -> decltype(+ async_initiate<CompletionToken, void (asio::error_code)>(+ declval<typename conditional<false, CompletionToken,+ Derived>::type::initiate_async_send>(), token,+ declval<typename conditional<false, CompletionToken,+ Derived>::type::payload_type>()))+ {+ typedef typename Derived::payload_type payload_type;+ typedef typename detail::channel_message<R(Args...)> message_type;+ Derived* self = static_cast<Derived*>(this);+ return async_initiate<CompletionToken, void (asio::error_code)>(+ typename Derived::initiate_async_send(self), token,+ payload_type(message_type(0, ASIO_MOVE_CAST(Args)(args)...)));+ }+};++} // namespace detail+} // namespace experimental+} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // ASIO_EXPERIMENTAL_DETAIL_CHANNEL_SEND_FUNCTIONS_HPP
+ link/modules/asio-standalone/asio/include/asio/experimental/detail/channel_send_op.hpp view
@@ -0,0 +1,148 @@+//+// experimental/detail/channel_send_op.hpp+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com)+//+// Distributed under the Boost Software License, Version 1.0. (See accompanying+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)+//++#ifndef ASIO_EXPERIMENTAL_DETAIL_CHANNEL_SEND_OP_HPP+#define ASIO_EXPERIMENTAL_DETAIL_CHANNEL_SEND_OP_HPP++#if defined(_MSC_VER) && (_MSC_VER >= 1200)+# pragma once+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)++#include "asio/detail/config.hpp"+#include "asio/detail/bind_handler.hpp"+#include "asio/detail/handler_alloc_helpers.hpp"+#include "asio/error.hpp"+#include "asio/experimental/channel_error.hpp"+#include "asio/experimental/detail/channel_operation.hpp"+#include "asio/experimental/detail/channel_payload.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {+namespace experimental {+namespace detail {++template <typename Payload>+class channel_send : public channel_operation+{+public:+ Payload get_payload()+ {+ return ASIO_MOVE_CAST(Payload)(payload_);+ }++ void immediate()+ {+ func_(this, immediate_op, 0);+ }++ void complete()+ {+ func_(this, complete_op, 0);+ }++ void cancel()+ {+ func_(this, cancel_op, 0);+ }++ void close()+ {+ func_(this, close_op, 0);+ }++protected:+ channel_send(func_type func, ASIO_MOVE_ARG(Payload) payload)+ : channel_operation(func),+ payload_(ASIO_MOVE_CAST(Payload)(payload))+ {+ }++private:+ Payload payload_;+};++template <typename Payload, typename Handler, typename IoExecutor>+class channel_send_op : public channel_send<Payload>+{+public:+ ASIO_DEFINE_HANDLER_PTR(channel_send_op);++ channel_send_op(ASIO_MOVE_ARG(Payload) payload,+ Handler& handler, const IoExecutor& io_ex)+ : channel_send<Payload>(&channel_send_op::do_action,+ ASIO_MOVE_CAST(Payload)(payload)),+ handler_(ASIO_MOVE_CAST(Handler)(handler)),+ work_(handler_, io_ex)+ {+ }++ static void do_action(channel_operation* base,+ channel_operation::action a, void*)+ {+ // Take ownership of the operation object.+ channel_send_op* o(static_cast<channel_send_op*>(base));+ ptr p = { asio::detail::addressof(o->handler_), o, o };++ ASIO_HANDLER_COMPLETION((*o));++ // Take ownership of the operation's outstanding work.+ channel_operation::handler_work<Handler, IoExecutor> w(+ ASIO_MOVE_CAST2(channel_operation::handler_work<+ Handler, IoExecutor>)(o->work_));++ asio::error_code ec;+ switch (a)+ {+ case channel_operation::cancel_op:+ ec = error::channel_cancelled;+ break;+ case channel_operation::close_op:+ ec = error::channel_closed;+ break;+ default:+ break;+ }++ // Make a copy of the handler so that the memory can be deallocated before+ // the handler is posted. Even if we're not about to post the handler, a+ // sub-object of the handler may be the true owner of the memory associated+ // with the handler. Consequently, a local copy of the handler is required+ // to ensure that any owning sub-object remains valid until after we have+ // deallocated the memory here.+ asio::detail::binder1<Handler, asio::error_code>+ handler(o->handler_, ec);+ p.h = asio::detail::addressof(handler.handler_);+ p.reset();++ // Post the completion if required.+ if (a != channel_operation::destroy_op)+ {+ ASIO_HANDLER_INVOCATION_BEGIN((handler.arg1_));+ if (a == channel_operation::immediate_op)+ w.immediate(handler, handler.handler_, 0);+ else+ w.complete(handler, handler.handler_);+ ASIO_HANDLER_INVOCATION_END;+ }+ }++private:+ Handler handler_;+ channel_operation::handler_work<Handler, IoExecutor> work_;+};++} // namespace detail+} // namespace experimental+} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // ASIO_EXPERIMENTAL_DETAIL_CHANNEL_SEND_OP_HPP
+ link/modules/asio-standalone/asio/include/asio/experimental/detail/channel_service.hpp view
@@ -0,0 +1,677 @@+//+// experimental/detail/channel_service.hpp+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com)+//+// Distributed under the Boost Software License, Version 1.0. (See accompanying+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)+//++#ifndef ASIO_EXPERIMENTAL_DETAIL_CHANNEL_SERVICE_HPP+#define ASIO_EXPERIMENTAL_DETAIL_CHANNEL_SERVICE_HPP++#if defined(_MSC_VER) && (_MSC_VER >= 1200)+# pragma once+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)++#include "asio/detail/config.hpp"+#include "asio/associated_cancellation_slot.hpp"+#include "asio/cancellation_type.hpp"+#include "asio/detail/mutex.hpp"+#include "asio/detail/op_queue.hpp"+#include "asio/execution_context.hpp"+#include "asio/experimental/detail/channel_message.hpp"+#include "asio/experimental/detail/channel_receive_op.hpp"+#include "asio/experimental/detail/channel_send_op.hpp"+#include "asio/experimental/detail/has_signature.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {+namespace experimental {+namespace detail {++template <typename Mutex>+class channel_service+ : public asio::detail::execution_context_service_base<+ channel_service<Mutex> >+{+public:+ // Possible states for a channel end.+ enum state+ {+ buffer = 0,+ waiter = 1,+ block = 2,+ closed = 3+ };++ // The base implementation type of all channels.+ struct base_implementation_type+ {+ // Default constructor.+ base_implementation_type()+ : receive_state_(block),+ send_state_(block),+ max_buffer_size_(0),+ next_(0),+ prev_(0)+ {+ }++ // The current state of the channel.+ state receive_state_ : 16;+ state send_state_ : 16;++ // The maximum number of elements that may be buffered in the channel.+ std::size_t max_buffer_size_;++ // The operations that are waiting on the channel.+ asio::detail::op_queue<channel_operation> waiters_;++ // Pointers to adjacent channel implementations in linked list.+ base_implementation_type* next_;+ base_implementation_type* prev_;++ // The mutex type to protect the internal implementation.+ mutable Mutex mutex_;+ };++ // The implementation for a specific value type.+ template <typename Traits, typename... Signatures>+ struct implementation_type;++ // Constructor.+ channel_service(execution_context& ctx);++ // Destroy all user-defined handler objects owned by the service.+ void shutdown();++ // Construct a new channel implementation.+ void construct(base_implementation_type& impl, std::size_t max_buffer_size);++ // Destroy a channel implementation.+ template <typename Traits, typename... Signatures>+ void destroy(implementation_type<Traits, Signatures...>& impl);++ // Move-construct a new channel implementation.+ template <typename Traits, typename... Signatures>+ void move_construct(implementation_type<Traits, Signatures...>& impl,+ implementation_type<Traits, Signatures...>& other_impl);++ // Move-assign from another channel implementation.+ template <typename Traits, typename... Signatures>+ void move_assign(implementation_type<Traits, Signatures...>& impl,+ channel_service& other_service,+ implementation_type<Traits, Signatures...>& other_impl);++ // Get the capacity of the channel.+ std::size_t capacity(+ const base_implementation_type& impl) const ASIO_NOEXCEPT;++ // Determine whether the channel is open.+ bool is_open(const base_implementation_type& impl) const ASIO_NOEXCEPT;++ // Reset the channel to its initial state.+ template <typename Traits, typename... Signatures>+ void reset(implementation_type<Traits, Signatures...>& impl);++ // Close the channel.+ template <typename Traits, typename... Signatures>+ void close(implementation_type<Traits, Signatures...>& impl);++ // Cancel all operations associated with the channel.+ template <typename Traits, typename... Signatures>+ void cancel(implementation_type<Traits, Signatures...>& impl);++ // Cancel the operation associated with the channel that has the given key.+ template <typename Traits, typename... Signatures>+ void cancel_by_key(implementation_type<Traits, Signatures...>& impl,+ void* cancellation_key);++ // Determine whether a value can be read from the channel without blocking.+ bool ready(const base_implementation_type& impl) const ASIO_NOEXCEPT;++ // Synchronously send a new value into the channel.+ template <typename Message, typename Traits,+ typename... Signatures, typename... Args>+ bool try_send(implementation_type<Traits, Signatures...>& impl,+ ASIO_MOVE_ARG(Args)... args);++ // Synchronously send a number of new values into the channel.+ template <typename Message, typename Traits,+ typename... Signatures, typename... Args>+ std::size_t try_send_n(implementation_type<Traits, Signatures...>& impl,+ std::size_t count, ASIO_MOVE_ARG(Args)... args);++ // Asynchronously send a new value into the channel.+ template <typename Traits, typename... Signatures,+ typename Handler, typename IoExecutor>+ void async_send(implementation_type<Traits, Signatures...>& impl,+ ASIO_MOVE_ARG2(typename implementation_type<+ Traits, Signatures...>::payload_type) payload,+ Handler& handler, const IoExecutor& io_ex)+ {+ typename associated_cancellation_slot<Handler>::type slot+ = asio::get_associated_cancellation_slot(handler);++ // Allocate and construct an operation to wrap the handler.+ typedef channel_send_op<+ typename implementation_type<Traits, Signatures...>::payload_type,+ Handler, IoExecutor> op;+ typename op::ptr p = { asio::detail::addressof(handler),+ op::ptr::allocate(handler), 0 };+ p.p = new (p.v) op(ASIO_MOVE_CAST2(typename implementation_type<+ Traits, Signatures...>::payload_type)(payload), handler, io_ex);++ // Optionally register for per-operation cancellation.+ if (slot.is_connected())+ {+ p.p->cancellation_key_ =+ &slot.template emplace<op_cancellation<Traits, Signatures...> >(+ this, &impl);+ }++ ASIO_HANDLER_CREATION((this->context(), *p.p,+ "channel", &impl, 0, "async_send"));++ start_send_op(impl, p.p);+ p.v = p.p = 0;+ }++ // Synchronously receive a value from the channel.+ template <typename Traits, typename... Signatures, typename Handler>+ bool try_receive(implementation_type<Traits, Signatures...>& impl,+ ASIO_MOVE_ARG(Handler) handler);++ // Asynchronously receive a value from the channel.+ template <typename Traits, typename... Signatures,+ typename Handler, typename IoExecutor>+ void async_receive(implementation_type<Traits, Signatures...>& impl,+ Handler& handler, const IoExecutor& io_ex)+ {+ typename associated_cancellation_slot<Handler>::type slot+ = asio::get_associated_cancellation_slot(handler);++ // Allocate and construct an operation to wrap the handler.+ typedef channel_receive_op<+ typename implementation_type<Traits, Signatures...>::payload_type,+ Handler, IoExecutor> op;+ typename op::ptr p = { asio::detail::addressof(handler),+ op::ptr::allocate(handler), 0 };+ p.p = new (p.v) op(handler, io_ex);++ // Optionally register for per-operation cancellation.+ if (slot.is_connected())+ {+ p.p->cancellation_key_ =+ &slot.template emplace<op_cancellation<Traits, Signatures...> >(+ this, &impl);+ }++ ASIO_HANDLER_CREATION((this->context(), *p.p,+ "channel", &impl, 0, "async_receive"));++ start_receive_op(impl, p.p);+ p.v = p.p = 0;+ }++private:+ // Helper function object to handle a closed notification.+ template <typename Payload, typename Signature>+ struct complete_receive+ {+ explicit complete_receive(channel_receive<Payload>* op)+ : op_(op)+ {+ }++ template <typename... Args>+ void operator()(ASIO_MOVE_ARG(Args)... args)+ {+ op_->complete(+ channel_message<Signature>(0,+ ASIO_MOVE_CAST(Args)(args)...));+ }++ channel_receive<Payload>* op_;+ };++ // Destroy a base channel implementation.+ void base_destroy(base_implementation_type& impl);++ // Helper function to start an asynchronous put operation.+ template <typename Traits, typename... Signatures>+ void start_send_op(implementation_type<Traits, Signatures...>& impl,+ channel_send<typename implementation_type<+ Traits, Signatures...>::payload_type>* send_op);++ // Helper function to start an asynchronous get operation.+ template <typename Traits, typename... Signatures>+ void start_receive_op(implementation_type<Traits, Signatures...>& impl,+ channel_receive<typename implementation_type<+ Traits, Signatures...>::payload_type>* receive_op);++ // Helper class used to implement per-operation cancellation.+ template <typename Traits, typename... Signatures>+ class op_cancellation+ {+ public:+ op_cancellation(channel_service* s,+ implementation_type<Traits, Signatures...>* impl)+ : service_(s),+ impl_(impl)+ {+ }++ void operator()(cancellation_type_t type)+ {+ if (!!(type &+ (cancellation_type::terminal+ | cancellation_type::partial+ | cancellation_type::total)))+ {+ service_->cancel_by_key(*impl_, this);+ }+ }++ private:+ channel_service* service_;+ implementation_type<Traits, Signatures...>* impl_;+ };++ // Mutex to protect access to the linked list of implementations.+ asio::detail::mutex mutex_;++ // The head of a linked list of all implementations.+ base_implementation_type* impl_list_;+};++// The implementation for a specific value type.+template <typename Mutex>+template <typename Traits, typename... Signatures>+struct channel_service<Mutex>::implementation_type : base_implementation_type+{+ // The traits type associated with the channel.+ typedef typename Traits::template rebind<Signatures...>::other traits_type;++ // Type of an element stored in the buffer.+ typedef typename conditional<+ has_signature<+ typename traits_type::receive_cancelled_signature,+ Signatures...+ >::value,+ typename conditional<+ has_signature<+ typename traits_type::receive_closed_signature,+ Signatures...+ >::value,+ channel_payload<Signatures...>,+ channel_payload<+ Signatures...,+ typename traits_type::receive_closed_signature+ >+ >::type,+ typename conditional<+ has_signature<+ typename traits_type::receive_closed_signature,+ Signatures...,+ typename traits_type::receive_cancelled_signature+ >::value,+ channel_payload<+ Signatures...,+ typename traits_type::receive_cancelled_signature+ >,+ channel_payload<+ Signatures...,+ typename traits_type::receive_cancelled_signature,+ typename traits_type::receive_closed_signature+ >+ >::type+ >::type payload_type;++ // Move from another buffer.+ void buffer_move_from(implementation_type& other)+ {+ buffer_ = ASIO_MOVE_CAST(+ typename traits_type::template container<+ payload_type>::type)(other.buffer_);+ other.buffer_clear();+ }++ // Get number of buffered elements.+ std::size_t buffer_size() const+ {+ return buffer_.size();+ }++ // Push a new value to the back of the buffer.+ void buffer_push(payload_type payload)+ {+ buffer_.push_back(ASIO_MOVE_CAST(payload_type)(payload));+ }++ // Push new values to the back of the buffer.+ std::size_t buffer_push_n(std::size_t count, payload_type payload)+ {+ std::size_t i = 0;+ for (; i < count && buffer_.size() < this->max_buffer_size_; ++i)+ buffer_.push_back(payload);+ return i;+ }++ // Get the element at the front of the buffer.+ payload_type buffer_front()+ {+ return ASIO_MOVE_CAST(payload_type)(buffer_.front());+ }++ // Pop a value from the front of the buffer.+ void buffer_pop()+ {+ buffer_.pop_front();+ }++ // Clear all buffered values.+ void buffer_clear()+ {+ buffer_.clear();+ }++private:+ // Buffered values.+ typename traits_type::template container<payload_type>::type buffer_;+};++// The implementation for a void value type.+template <typename Mutex>+template <typename Traits, typename R>+struct channel_service<Mutex>::implementation_type<Traits, R()>+ : channel_service::base_implementation_type+{+ // The traits type associated with the channel.+ typedef typename Traits::template rebind<R()>::other traits_type;++ // Type of an element stored in the buffer.+ typedef typename conditional<+ has_signature<+ typename traits_type::receive_cancelled_signature,+ R()+ >::value,+ typename conditional<+ has_signature<+ typename traits_type::receive_closed_signature,+ R()+ >::value,+ channel_payload<R()>,+ channel_payload<+ R(),+ typename traits_type::receive_closed_signature+ >+ >::type,+ typename conditional<+ has_signature<+ typename traits_type::receive_closed_signature,+ R(),+ typename traits_type::receive_cancelled_signature+ >::value,+ channel_payload<+ R(),+ typename traits_type::receive_cancelled_signature+ >,+ channel_payload<+ R(),+ typename traits_type::receive_cancelled_signature,+ typename traits_type::receive_closed_signature+ >+ >::type+ >::type payload_type;++ // Construct with empty buffer.+ implementation_type()+ : buffer_(0)+ {+ }++ // Move from another buffer.+ void buffer_move_from(implementation_type& other)+ {+ buffer_ = other.buffer_;+ other.buffer_ = 0;+ }++ // Get number of buffered elements.+ std::size_t buffer_size() const+ {+ return buffer_;+ }++ // Push a new value to the back of the buffer.+ void buffer_push(payload_type)+ {+ ++buffer_;+ }++ // Push new values to the back of the buffer.+ std::size_t buffer_push_n(std::size_t count, payload_type)+ {+ std::size_t available = this->max_buffer_size_ - buffer_;+ count = (count < available) ? count : available;+ buffer_ += count;+ return count;+ }++ // Get the element at the front of the buffer.+ payload_type buffer_front()+ {+ return payload_type(channel_message<R()>(0));+ }++ // Pop a value from the front of the buffer.+ void buffer_pop()+ {+ --buffer_;+ }++ // Clear all values from the buffer.+ void buffer_clear()+ {+ buffer_ = 0;+ }++private:+ // Number of buffered "values".+ std::size_t buffer_;+};++// The implementation for an error_code signature.+template <typename Mutex>+template <typename Traits, typename R>+struct channel_service<Mutex>::implementation_type<+ Traits, R(asio::error_code)>+ : channel_service::base_implementation_type+{+ // The traits type associated with the channel.+ typedef typename Traits::template rebind<R(asio::error_code)>::other+ traits_type;++ // Type of an element stored in the buffer.+ typedef typename conditional<+ has_signature<+ typename traits_type::receive_cancelled_signature,+ R(asio::error_code)+ >::value,+ typename conditional<+ has_signature<+ typename traits_type::receive_closed_signature,+ R(asio::error_code)+ >::value,+ channel_payload<R(asio::error_code)>,+ channel_payload<+ R(asio::error_code),+ typename traits_type::receive_closed_signature+ >+ >::type,+ typename conditional<+ has_signature<+ typename traits_type::receive_closed_signature,+ R(asio::error_code),+ typename traits_type::receive_cancelled_signature+ >::value,+ channel_payload<+ R(asio::error_code),+ typename traits_type::receive_cancelled_signature+ >,+ channel_payload<+ R(asio::error_code),+ typename traits_type::receive_cancelled_signature,+ typename traits_type::receive_closed_signature+ >+ >::type+ >::type payload_type;++ // Construct with empty buffer.+ implementation_type()+ : size_(0)+ {+ first_.count_ = 0;+ }++ // Move from another buffer.+ void buffer_move_from(implementation_type& other)+ {+ size_ = other.buffer_;+ other.size_ = 0;+ first_ = other.first_;+ other.first.count_ = 0;+ rest_ = ASIO_MOVE_CAST(+ typename traits_type::template container<+ buffered_value>::type)(other.rest_);+ other.buffer_clear();+ }++ // Get number of buffered elements.+ std::size_t buffer_size() const+ {+ return size_;+ }++ // Push a new value to the back of the buffer.+ void buffer_push(payload_type payload)+ {+ buffered_value& last = rest_.empty() ? first_ : rest_.back();+ if (last.count_ == 0)+ {+ value_handler handler{last.value_};+ payload.receive(handler);+ last.count_ = 1;+ }+ else+ {+ asio::error_code value{last.value_};+ value_handler handler{value};+ payload.receive(handler);+ if (last.value_ == value)+ ++last.count_;+ else+ rest_.push_back({value, 1});+ }+ ++size_;+ }++ // Push new values to the back of the buffer.+ std::size_t buffer_push_n(std::size_t count, payload_type payload)+ {+ std::size_t available = this->max_buffer_size_ - size_;+ count = (count < available) ? count : available;+ if (count > 0)+ {+ buffered_value& last = rest_.empty() ? first_ : rest_.back();+ if (last.count_ == 0)+ {+ payload.receive(value_handler{last.value_});+ last.count_ = count;+ }+ else+ {+ asio::error_code value{last.value_};+ payload.receive(value_handler{value});+ if (last.value_ == value)+ last.count_ += count;+ else+ rest_.push_back({value, count});+ }+ size_ += count;+ }+ return count;+ }++ // Get the element at the front of the buffer.+ payload_type buffer_front()+ {+ return payload_type({0, first_.value_});+ }++ // Pop a value from the front of the buffer.+ void buffer_pop()+ {+ --size_;+ if (--first_.count_ == 0 && !rest_.empty())+ {+ first_ = rest_.front();+ rest_.pop_front();+ }+ }++ // Clear all values from the buffer.+ void buffer_clear()+ {+ size_ = 0;+ first_.count_ == 0;+ rest_.clear();+ }++private:+ struct buffered_value+ {+ asio::error_code value_;+ std::size_t count_;+ };++ struct value_handler+ {+ asio::error_code& target_;++ template <typename... Args>+ void operator()(const asio::error_code& value, Args&&...)+ {+ target_ = value;+ }+ };++ buffered_value& last_value()+ {+ return rest_.empty() ? first_ : rest_.back();+ }++ // Total number of buffered values.+ std::size_t size_;++ // The first buffered value is maintained as a separate data member to avoid+ // allocating space in the container in the common case.+ buffered_value first_;++ // The rest of the buffered values.+ typename traits_type::template container<buffered_value>::type rest_;+};++} // namespace detail+} // namespace experimental+} // namespace asio++#include "asio/detail/pop_options.hpp"++#include "asio/experimental/detail/impl/channel_service.hpp"++#endif // ASIO_EXPERIMENTAL_DETAIL_CHANNEL_SERVICE_HPP
+ link/modules/asio-standalone/asio/include/asio/experimental/detail/coro_completion_handler.hpp view
@@ -0,0 +1,169 @@+//+// experimental/detail/coro_completion_handler.hpp+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2021-2023 Klemens D. Morgenstern+// (klemens dot morgenstern at gmx dot net)+//+// Distributed under the Boost Software License, Version 1.0. (See accompanying+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)+//++#ifndef ASIO_EXPERIMENTAL_DETAIL_CORO_COMPLETION_HANDLER_HPP+#define ASIO_EXPERIMENTAL_DETAIL_CORO_COMPLETION_HANDLER_HPP++#if defined(_MSC_VER) && (_MSC_VER >= 1200)+# pragma once+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)++#include "asio/detail/config.hpp"+#include "asio/deferred.hpp"+#include "asio/experimental/coro.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {+namespace experimental {+namespace detail {++template <typename Promise, typename... Args>+struct coro_completion_handler+{+ coro_completion_handler(coroutine_handle<Promise> h,+ std::optional<std::tuple<Args...>>& result)+ : self(h),+ result(result)+ {+ }++ coro_completion_handler(coro_completion_handler&&) = default;++ coroutine_handle<Promise> self;++ std::optional<std::tuple<Args...>>& result;++ using promise_type = Promise;++ void operator()(Args... args)+ {+ result.emplace(std::move(args)...);+ self.resume();+ }++ using allocator_type = typename promise_type::allocator_type;+ allocator_type get_allocator() const noexcept+ {+ return self.promise().get_allocator();+ }++ using executor_type = typename promise_type::executor_type;+ executor_type get_executor() const noexcept+ {+ return self.promise().get_executor();+ }++ using cancellation_slot_type = typename promise_type::cancellation_slot_type;+ cancellation_slot_type get_cancellation_slot() const noexcept+ {+ return self.promise().get_cancellation_slot();+ }+};++template <typename Signature>+struct coro_completion_handler_type;++template <typename... Args>+struct coro_completion_handler_type<void(Args...)>+{+ using type = std::tuple<Args...>;++ template <typename Promise>+ using completion_handler = coro_completion_handler<Promise, Args...>;+};++template <typename Signature>+using coro_completion_handler_type_t =+ typename coro_completion_handler_type<Signature>::type;++inline void coro_interpret_result(std::tuple<>&&)+{+}++template <typename... Args>+inline auto coro_interpret_result(std::tuple<Args...>&& args)+{+ return std::move(args);+}++template <typename... Args>+auto coro_interpret_result(std::tuple<std::exception_ptr, Args...>&& args)+{+ if (std::get<0>(args))+ std::rethrow_exception(std::get<0>(args));++ return std::apply(+ [](auto, auto&&... rest)+ {+ return std::make_tuple(std::move(rest)...);+ }, std::move(args));+}++template <typename... Args>+auto coro_interpret_result(+ std::tuple<asio::error_code, Args...>&& args)+{+ if (std::get<0>(args))+ asio::detail::throw_exception(+ asio::system_error(std::get<0>(args)));++ return std::apply(+ [](auto, auto&&... rest)+ {+ return std::make_tuple(std::move(rest)...);+ }, std::move(args));+}++template <typename Arg>+inline auto coro_interpret_result(std::tuple<Arg>&& args)+{+ return std::get<0>(std::move(args));+}++template <typename Arg>+auto coro_interpret_result(std::tuple<std::exception_ptr, Arg>&& args)+{+ if (std::get<0>(args))+ std::rethrow_exception(std::get<0>(args));+ return std::get<1>(std::move(args));+}++inline auto coro_interpret_result(+ std::tuple<asio::error_code>&& args)+{+ if (std::get<0>(args))+ asio::detail::throw_exception(+ asio::system_error(std::get<0>(args)));+}++inline auto coro_interpret_result(std::tuple<std::exception_ptr>&& args)+{+ if (std::get<0>(args))+ std::rethrow_exception(std::get<0>(args));+}++template <typename Arg>+auto coro_interpret_result(std::tuple<asio::error_code, Arg>&& args)+{+ if (std::get<0>(args))+ asio::detail::throw_exception(+ asio::system_error(std::get<0>(args)));+ return std::get<1>(std::move(args));+}++} // namespace detail+} // namespace experimental+} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // ASIO_EXPERIMENTAL_DETAIL_CORO_COMPLETION_HANDLER_HPP
+ link/modules/asio-standalone/asio/include/asio/experimental/detail/coro_promise_allocator.hpp view
@@ -0,0 +1,141 @@+//+// experimental/detail/coro_promise_allocator.hpp+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2021-2023 Klemens D. Morgenstern+// (klemens dot morgenstern at gmx dot net)+//+// Distributed under the Boost Software License, Version 1.0. (See accompanying+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)+//++#ifndef ASIO_EXPERIMENTAL_DETAIL_CORO_PROMISE_ALLOCATOR_HPP+#define ASIO_EXPERIMENTAL_DETAIL_CORO_PROMISE_ALLOCATOR_HPP++#include "asio/detail/config.hpp"+#include "asio/experimental/coro_traits.hpp"++namespace asio {+namespace experimental {+namespace detail {++/// Allocate the memory and put the allocator behind the coro memory+template <typename AllocatorType>+void* allocate_coroutine(const std::size_t size, AllocatorType alloc_)+{+ using alloc_type = typename std::allocator_traits<AllocatorType>::template+ rebind_alloc<unsigned char>;+ alloc_type alloc{alloc_};++ const auto align_needed = size % alignof(alloc_type);+ const auto align_offset = align_needed != 0+ ? alignof(alloc_type) - align_needed : 0ull;+ const auto alloc_size = size + sizeof(alloc_type) + align_offset;+ const auto raw =+ std::allocator_traits<alloc_type>::allocate(alloc, alloc_size);+ new(raw + size + align_offset) alloc_type(std::move(alloc));++ return raw;+}++/// Deallocate the memory and destroy the allocator in the coro memory.+template <typename AllocatorType>+void deallocate_coroutine(void* raw_, const std::size_t size)+{+ using alloc_type = typename std::allocator_traits<AllocatorType>::template+ rebind_alloc<unsigned char>;++ const auto raw = static_cast<unsigned char *>(raw_);++ const auto align_needed = size % alignof(alloc_type);+ const auto align_offset = align_needed != 0+ ? alignof(alloc_type) - align_needed : 0ull;+ const auto alloc_size = size + sizeof(alloc_type) + align_offset;++ auto alloc_p = reinterpret_cast<alloc_type *>(raw + size + align_offset);+ auto alloc = std::move(*alloc_p);+ alloc_p->~alloc_type();+ std::allocator_traits<alloc_type>::deallocate(alloc, raw, alloc_size);+}++template <typename T>+constexpr std::size_t variadic_first(std::size_t = 0u)+{+ return std::numeric_limits<std::size_t>::max();+}+++template <typename T, typename First, typename... Args>+constexpr std::size_t variadic_first(std::size_t pos = 0u)+{+ if constexpr (std::is_same_v<std::decay_t<First>, T>)+ return pos;+ else+ return variadic_first<T, Args...>(pos+1);+}++template <std::size_t Idx, typename First, typename... Args>+ requires (Idx <= sizeof...(Args))+constexpr decltype(auto) get_variadic(First&& first, Args&&... args)+{+ if constexpr (Idx == 0u)+ return static_cast<First>(first);+ else+ return get_variadic<Idx-1u>(static_cast<Args>(args)...);+}++template <std::size_t Idx>+constexpr decltype(auto) get_variadic();++template <typename Allocator>+struct coro_promise_allocator+{+ using allocator_type = Allocator;+ allocator_type get_allocator() const {return alloc_;}++ template <typename... Args>+ void* operator new(const std::size_t size, Args & ... args)+ {+ return allocate_coroutine(size,+ get_variadic<variadic_first<std::allocator_arg_t,+ std::decay_t<Args>...>() + 1u>(args...));+ }++ void operator delete(void* raw, const std::size_t size)+ {+ deallocate_coroutine<allocator_type>(raw, size);+ }++ template <typename... Args>+ coro_promise_allocator(Args&& ... args)+ : alloc_(+ get_variadic<variadic_first<std::allocator_arg_t,+ std::decay_t<Args>...>() + 1u>(args...))+ {+ }++private:+ allocator_type alloc_;+};++template <>+struct coro_promise_allocator<std::allocator<void>>+{+ using allocator_type = std::allocator<void>;++ template <typename... Args>+ coro_promise_allocator(Args&&...)+ {+ }++ allocator_type get_allocator() const+ {+ return {};+ }+};++} // namespace detail+} // namespace experimental+} // namespace asio++#endif // ASIO_EXPERIMENTAL_DETAIL_CORO_PROMISE_ALLOCATOR_HPP
+ link/modules/asio-standalone/asio/include/asio/experimental/detail/has_signature.hpp view
@@ -0,0 +1,54 @@+//+// experimental/detail/has_signature.hpp+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com)+//+// Distributed under the Boost Software License, Version 1.0. (See accompanying+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)+//++#ifndef ASIO_EXPERIMENTAL_DETAIL_HAS_SIGNATURE_HPP+#define ASIO_EXPERIMENTAL_DETAIL_HAS_SIGNATURE_HPP++#if defined(_MSC_VER) && (_MSC_VER >= 1200)+# pragma once+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)++#include "asio/detail/config.hpp"+#include "asio/detail/type_traits.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {+namespace experimental {+namespace detail {++template <typename S, typename... Signatures>+struct has_signature;++template <typename S, typename... Signatures>+struct has_signature;++template <typename S>+struct has_signature<S> : false_type+{+};++template <typename S, typename... Signatures>+struct has_signature<S, S, Signatures...> : true_type+{+};++template <typename S, typename Head, typename... Tail>+struct has_signature<S, Head, Tail...> : has_signature<S, Tail...>+{+};++} // namespace detail+} // namespace experimental+} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // ASIO_EXPERIMENTAL_DETAIL_HAS_SIGNATURE_HPP
+ link/modules/asio-standalone/asio/include/asio/experimental/detail/impl/channel_service.hpp view
@@ -0,0 +1,612 @@+//+// experimental/detail/impl/channel_service.hpp+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com)+//+// Distributed under the Boost Software License, Version 1.0. (See accompanying+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)+//++#ifndef ASIO_EXPERIMENTAL_DETAIL_IMPL_CHANNEL_SERVICE_HPP+#define ASIO_EXPERIMENTAL_DETAIL_IMPL_CHANNEL_SERVICE_HPP++#if defined(_MSC_VER) && (_MSC_VER >= 1200)+# pragma once+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)++#include "asio/detail/push_options.hpp"++namespace asio {+namespace experimental {+namespace detail {++template <typename Mutex>+inline channel_service<Mutex>::channel_service(execution_context& ctx)+ : asio::detail::execution_context_service_base<channel_service>(ctx),+ mutex_(),+ impl_list_(0)+{+}++template <typename Mutex>+inline void channel_service<Mutex>::shutdown()+{+ // Abandon all pending operations.+ asio::detail::op_queue<channel_operation> ops;+ asio::detail::mutex::scoped_lock lock(mutex_);+ base_implementation_type* impl = impl_list_;+ while (impl)+ {+ ops.push(impl->waiters_);+ impl = impl->next_;+ }+}++template <typename Mutex>+inline void channel_service<Mutex>::construct(+ channel_service<Mutex>::base_implementation_type& impl,+ std::size_t max_buffer_size)+{+ impl.max_buffer_size_ = max_buffer_size;+ impl.receive_state_ = block;+ impl.send_state_ = max_buffer_size ? buffer : block;++ // Insert implementation into linked list of all implementations.+ asio::detail::mutex::scoped_lock lock(mutex_);+ impl.next_ = impl_list_;+ impl.prev_ = 0;+ if (impl_list_)+ impl_list_->prev_ = &impl;+ impl_list_ = &impl;+}++template <typename Mutex>+template <typename Traits, typename... Signatures>+void channel_service<Mutex>::destroy(+ channel_service<Mutex>::implementation_type<Traits, Signatures...>& impl)+{+ cancel(impl);+ base_destroy(impl);+}++template <typename Mutex>+template <typename Traits, typename... Signatures>+void channel_service<Mutex>::move_construct(+ channel_service<Mutex>::implementation_type<Traits, Signatures...>& impl,+ channel_service<Mutex>::implementation_type<+ Traits, Signatures...>& other_impl)+{+ impl.max_buffer_size_ = other_impl.max_buffer_size_;+ impl.receive_state_ = other_impl.receive_state_;+ other_impl.receive_state_ = block;+ impl.send_state_ = other_impl.send_state_;+ other_impl.send_state_ = other_impl.max_buffer_size_ ? buffer : block;+ impl.buffer_move_from(other_impl);++ // Insert implementation into linked list of all implementations.+ asio::detail::mutex::scoped_lock lock(mutex_);+ impl.next_ = impl_list_;+ impl.prev_ = 0;+ if (impl_list_)+ impl_list_->prev_ = &impl;+ impl_list_ = &impl;+}++template <typename Mutex>+template <typename Traits, typename... Signatures>+void channel_service<Mutex>::move_assign(+ channel_service<Mutex>::implementation_type<Traits, Signatures...>& impl,+ channel_service& other_service,+ channel_service<Mutex>::implementation_type<+ Traits, Signatures...>& other_impl)+{+ cancel(impl);++ if (this != &other_service)+ {+ // Remove implementation from linked list of all implementations.+ asio::detail::mutex::scoped_lock lock(mutex_);+ if (impl_list_ == &impl)+ impl_list_ = impl.next_;+ if (impl.prev_)+ impl.prev_->next_ = impl.next_;+ if (impl.next_)+ impl.next_->prev_= impl.prev_;+ impl.next_ = 0;+ impl.prev_ = 0;+ }++ impl.max_buffer_size_ = other_impl.max_buffer_size_;+ impl.receive_state_ = other_impl.receive_state_;+ other_impl.receive_state_ = block;+ impl.send_state_ = other_impl.send_state_;+ other_impl.send_state_ = other_impl.max_buffer_size_ ? buffer : block;+ impl.buffer_move_from(other_impl);++ if (this != &other_service)+ {+ // Insert implementation into linked list of all implementations.+ asio::detail::mutex::scoped_lock lock(other_service.mutex_);+ impl.next_ = other_service.impl_list_;+ impl.prev_ = 0;+ if (other_service.impl_list_)+ other_service.impl_list_->prev_ = &impl;+ other_service.impl_list_ = &impl;+ }+}++template <typename Mutex>+inline void channel_service<Mutex>::base_destroy(+ channel_service<Mutex>::base_implementation_type& impl)+{+ // Remove implementation from linked list of all implementations.+ asio::detail::mutex::scoped_lock lock(mutex_);+ if (impl_list_ == &impl)+ impl_list_ = impl.next_;+ if (impl.prev_)+ impl.prev_->next_ = impl.next_;+ if (impl.next_)+ impl.next_->prev_= impl.prev_;+ impl.next_ = 0;+ impl.prev_ = 0;+}++template <typename Mutex>+inline std::size_t channel_service<Mutex>::capacity(+ const channel_service<Mutex>::base_implementation_type& impl)+ const ASIO_NOEXCEPT+{+ typename Mutex::scoped_lock lock(impl.mutex_);++ return impl.max_buffer_size_;+}++template <typename Mutex>+inline bool channel_service<Mutex>::is_open(+ const channel_service<Mutex>::base_implementation_type& impl)+ const ASIO_NOEXCEPT+{+ typename Mutex::scoped_lock lock(impl.mutex_);++ return impl.send_state_ != closed;+}++template <typename Mutex>+template <typename Traits, typename... Signatures>+void channel_service<Mutex>::reset(+ channel_service<Mutex>::implementation_type<Traits, Signatures...>& impl)+{+ cancel(impl);++ typename Mutex::scoped_lock lock(impl.mutex_);++ impl.receive_state_ = block;+ impl.send_state_ = impl.max_buffer_size_ ? buffer : block;+ impl.buffer_clear();+}++template <typename Mutex>+template <typename Traits, typename... Signatures>+void channel_service<Mutex>::close(+ channel_service<Mutex>::implementation_type<Traits, Signatures...>& impl)+{+ typedef typename implementation_type<Traits,+ Signatures...>::traits_type traits_type;+ typedef typename implementation_type<Traits,+ Signatures...>::payload_type payload_type;++ typename Mutex::scoped_lock lock(impl.mutex_);++ if (impl.receive_state_ == block)+ {+ while (channel_operation* op = impl.waiters_.front())+ {+ impl.waiters_.pop();+ traits_type::invoke_receive_closed(+ complete_receive<payload_type,+ typename traits_type::receive_closed_signature>(+ static_cast<channel_receive<payload_type>*>(op)));+ }+ }++ impl.send_state_ = closed;+ if (impl.receive_state_ != buffer)+ impl.receive_state_ = closed;+}++template <typename Mutex>+template <typename Traits, typename... Signatures>+void channel_service<Mutex>::cancel(+ channel_service<Mutex>::implementation_type<Traits, Signatures...>& impl)+{+ typedef typename implementation_type<Traits,+ Signatures...>::traits_type traits_type;+ typedef typename implementation_type<Traits,+ Signatures...>::payload_type payload_type;++ typename Mutex::scoped_lock lock(impl.mutex_);++ while (channel_operation* op = impl.waiters_.front())+ {+ if (impl.send_state_ == block)+ {+ impl.waiters_.pop();+ static_cast<channel_send<payload_type>*>(op)->cancel();+ }+ else+ {+ impl.waiters_.pop();+ traits_type::invoke_receive_cancelled(+ complete_receive<payload_type,+ typename traits_type::receive_cancelled_signature>(+ static_cast<channel_receive<payload_type>*>(op)));+ }+ }++ if (impl.receive_state_ == waiter)+ impl.receive_state_ = block;+ if (impl.send_state_ == waiter)+ impl.send_state_ = impl.max_buffer_size_ ? buffer : block;+}++template <typename Mutex>+template <typename Traits, typename... Signatures>+void channel_service<Mutex>::cancel_by_key(+ channel_service<Mutex>::implementation_type<Traits, Signatures...>& impl,+ void* cancellation_key)+{+ typedef typename implementation_type<Traits,+ Signatures...>::traits_type traits_type;+ typedef typename implementation_type<Traits,+ Signatures...>::payload_type payload_type;++ typename Mutex::scoped_lock lock(impl.mutex_);++ asio::detail::op_queue<channel_operation> other_ops;+ while (channel_operation* op = impl.waiters_.front())+ {+ if (op->cancellation_key_ == cancellation_key)+ {+ if (impl.send_state_ == block)+ {+ impl.waiters_.pop();+ static_cast<channel_send<payload_type>*>(op)->cancel();+ }+ else+ {+ impl.waiters_.pop();+ traits_type::invoke_receive_cancelled(+ complete_receive<payload_type,+ typename traits_type::receive_cancelled_signature>(+ static_cast<channel_receive<payload_type>*>(op)));+ }+ }+ else+ {+ impl.waiters_.pop();+ other_ops.push(op);+ }+ }+ impl.waiters_.push(other_ops);++ if (impl.waiters_.empty())+ {+ if (impl.receive_state_ == waiter)+ impl.receive_state_ = block;+ if (impl.send_state_ == waiter)+ impl.send_state_ = impl.max_buffer_size_ ? buffer : block;+ }+}++template <typename Mutex>+inline bool channel_service<Mutex>::ready(+ const channel_service<Mutex>::base_implementation_type& impl)+ const ASIO_NOEXCEPT+{+ typename Mutex::scoped_lock lock(impl.mutex_);++ return impl.receive_state_ != block;+}++template <typename Mutex>+template <typename Message, typename Traits,+ typename... Signatures, typename... Args>+bool channel_service<Mutex>::try_send(+ channel_service<Mutex>::implementation_type<Traits, Signatures...>& impl,+ ASIO_MOVE_ARG(Args)... args)+{+ typedef typename implementation_type<Traits,+ Signatures...>::payload_type payload_type;++ typename Mutex::scoped_lock lock(impl.mutex_);++ switch (impl.send_state_)+ {+ case block:+ {+ return false;+ }+ case buffer:+ {+ impl.buffer_push(Message(0, ASIO_MOVE_CAST(Args)(args)...));+ impl.receive_state_ = buffer;+ if (impl.buffer_size() == impl.max_buffer_size_)+ impl.send_state_ = block;+ return true;+ }+ case waiter:+ {+ payload_type payload(Message(0, ASIO_MOVE_CAST(Args)(args)...));+ channel_receive<payload_type>* receive_op =+ static_cast<channel_receive<payload_type>*>(impl.waiters_.front());+ impl.waiters_.pop();+ receive_op->complete(ASIO_MOVE_CAST(payload_type)(payload));+ if (impl.waiters_.empty())+ impl.send_state_ = impl.max_buffer_size_ ? buffer : block;+ return true;+ }+ case closed:+ default:+ {+ return false;+ }+ }+}++template <typename Mutex>+template <typename Message, typename Traits,+ typename... Signatures, typename... Args>+std::size_t channel_service<Mutex>::try_send_n(+ channel_service<Mutex>::implementation_type<Traits, Signatures...>& impl,+ std::size_t count, ASIO_MOVE_ARG(Args)... args)+{+ typedef typename implementation_type<Traits,+ Signatures...>::payload_type payload_type;++ typename Mutex::scoped_lock lock(impl.mutex_);++ if (count == 0)+ return 0;++ switch (impl.send_state_)+ {+ case block:+ return 0;+ case buffer:+ case waiter:+ break;+ case closed:+ default:+ return 0;+ }++ payload_type payload(Message(0, ASIO_MOVE_CAST(Args)(args)...));++ for (std::size_t i = 0; i < count; ++i)+ {+ switch (impl.send_state_)+ {+ case block:+ {+ return i;+ }+ case buffer:+ {+ i += impl.buffer_push_n(count - i,+ ASIO_MOVE_CAST(payload_type)(payload));+ impl.receive_state_ = buffer;+ if (impl.buffer_size() == impl.max_buffer_size_)+ impl.send_state_ = block;+ return i;+ }+ case waiter:+ {+ channel_receive<payload_type>* receive_op =+ static_cast<channel_receive<payload_type>*>(impl.waiters_.front());+ impl.waiters_.pop();+ receive_op->complete(payload);+ if (impl.waiters_.empty())+ impl.send_state_ = impl.max_buffer_size_ ? buffer : block;+ break;+ }+ case closed:+ default:+ {+ return i;+ }+ }+ }++ return count;+}++template <typename Mutex>+template <typename Traits, typename... Signatures>+void channel_service<Mutex>::start_send_op(+ channel_service<Mutex>::implementation_type<Traits, Signatures...>& impl,+ channel_send<typename implementation_type<+ Traits, Signatures...>::payload_type>* send_op)+{+ typedef typename implementation_type<Traits,+ Signatures...>::payload_type payload_type;++ typename Mutex::scoped_lock lock(impl.mutex_);++ switch (impl.send_state_)+ {+ case block:+ {+ impl.waiters_.push(send_op);+ if (impl.receive_state_ == block)+ impl.receive_state_ = waiter;+ return;+ }+ case buffer:+ {+ impl.buffer_push(send_op->get_payload());+ impl.receive_state_ = buffer;+ if (impl.buffer_size() == impl.max_buffer_size_)+ impl.send_state_ = block;+ send_op->immediate();+ break;+ }+ case waiter:+ {+ channel_receive<payload_type>* receive_op =+ static_cast<channel_receive<payload_type>*>(impl.waiters_.front());+ impl.waiters_.pop();+ receive_op->complete(send_op->get_payload());+ if (impl.waiters_.empty())+ impl.send_state_ = impl.max_buffer_size_ ? buffer : block;+ send_op->immediate();+ break;+ }+ case closed:+ default:+ {+ send_op->close();+ break;+ }+ }+}++template <typename Mutex>+template <typename Traits, typename... Signatures, typename Handler>+bool channel_service<Mutex>::try_receive(+ channel_service<Mutex>::implementation_type<Traits, Signatures...>& impl,+ ASIO_MOVE_ARG(Handler) handler)+{+ typedef typename implementation_type<Traits,+ Signatures...>::payload_type payload_type;++ typename Mutex::scoped_lock lock(impl.mutex_);++ switch (impl.receive_state_)+ {+ case block:+ {+ return false;+ }+ case buffer:+ {+ payload_type payload(impl.buffer_front());+ if (channel_send<payload_type>* send_op =+ static_cast<channel_send<payload_type>*>(impl.waiters_.front()))+ {+ impl.buffer_pop();+ impl.buffer_push(send_op->get_payload());+ impl.waiters_.pop();+ send_op->complete();+ }+ else+ {+ impl.buffer_pop();+ if (impl.buffer_size() == 0)+ impl.receive_state_ = (impl.send_state_ == closed) ? closed : block;+ impl.send_state_ = (impl.send_state_ == closed) ? closed : buffer;+ }+ lock.unlock();+ asio::detail::non_const_lvalue<Handler> handler2(handler);+ channel_handler<payload_type, typename decay<Handler>::type>(+ ASIO_MOVE_CAST(payload_type)(payload), handler2.value)();+ return true;+ }+ case waiter:+ {+ channel_send<payload_type>* send_op =+ static_cast<channel_send<payload_type>*>(impl.waiters_.front());+ payload_type payload = send_op->get_payload();+ impl.waiters_.pop();+ send_op->complete();+ if (impl.waiters_.front() == 0)+ impl.receive_state_ = (impl.send_state_ == closed) ? closed : block;+ lock.unlock();+ asio::detail::non_const_lvalue<Handler> handler2(handler);+ channel_handler<payload_type, typename decay<Handler>::type>(+ ASIO_MOVE_CAST(payload_type)(payload), handler2.value)();+ return true;+ }+ case closed:+ default:+ {+ return false;+ }+ }+}++template <typename Mutex>+template <typename Traits, typename... Signatures>+void channel_service<Mutex>::start_receive_op(+ channel_service<Mutex>::implementation_type<Traits, Signatures...>& impl,+ channel_receive<typename implementation_type<+ Traits, Signatures...>::payload_type>* receive_op)+{+ typedef typename implementation_type<Traits,+ Signatures...>::traits_type traits_type;+ typedef typename implementation_type<Traits,+ Signatures...>::payload_type payload_type;++ typename Mutex::scoped_lock lock(impl.mutex_);++ switch (impl.receive_state_)+ {+ case block:+ {+ impl.waiters_.push(receive_op);+ if (impl.send_state_ != closed)+ impl.send_state_ = waiter;+ return;+ }+ case buffer:+ {+ payload_type payload(+ ASIO_MOVE_CAST(payload_type)(impl.buffer_front()));+ if (channel_send<payload_type>* send_op =+ static_cast<channel_send<payload_type>*>(impl.waiters_.front()))+ {+ impl.buffer_pop();+ impl.buffer_push(send_op->get_payload());+ impl.waiters_.pop();+ send_op->complete();+ }+ else+ {+ impl.buffer_pop();+ if (impl.buffer_size() == 0)+ impl.receive_state_ = (impl.send_state_ == closed) ? closed : block;+ impl.send_state_ = (impl.send_state_ == closed) ? closed : buffer;+ }+ receive_op->immediate(ASIO_MOVE_CAST(payload_type)(payload));+ break;+ }+ case waiter:+ {+ channel_send<payload_type>* send_op =+ static_cast<channel_send<payload_type>*>(impl.waiters_.front());+ payload_type payload = send_op->get_payload();+ impl.waiters_.pop();+ send_op->complete();+ if (impl.waiters_.front() == 0)+ impl.receive_state_ = (impl.send_state_ == closed) ? closed : block;+ receive_op->immediate(ASIO_MOVE_CAST(payload_type)(payload));+ break;+ }+ case closed:+ default:+ {+ traits_type::invoke_receive_closed(+ complete_receive<payload_type,+ typename traits_type::receive_closed_signature>(receive_op));+ break;+ }+ }+}++} // namespace detail+} // namespace experimental+} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // ASIO_EXPERIMENTAL_DETAIL_IMPL_CHANNEL_SERVICE_HPP
+ link/modules/asio-standalone/asio/include/asio/experimental/detail/partial_promise.hpp view
@@ -0,0 +1,197 @@+//+// experimental/detail/partial_promise.hpp+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2021-2023 Klemens D. Morgenstern+// (klemens dot morgenstern at gmx dot net)+//+// Distributed under the Boost Software License, Version 1.0. (See accompanying+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)+//++#ifndef ASIO_EXPERIMENTAL_DETAIL_PARTIAL_PROMISE_HPP+#define ASIO_EXPERIMENTAL_DETAIL_PARTIAL_PROMISE_HPP++#include "asio/detail/config.hpp"+#include "asio/append.hpp"+#include "asio/awaitable.hpp"+#include "asio/experimental/coro_traits.hpp"++#if defined(ASIO_HAS_STD_COROUTINE)+# include <coroutine>+#else // defined(ASIO_HAS_STD_COROUTINE)+# include <experimental/coroutine>+#endif // defined(ASIO_HAS_STD_COROUTINE)++namespace asio {+namespace experimental {+namespace detail {++#if defined(ASIO_HAS_STD_COROUTINE)++using std::coroutine_handle;+using std::coroutine_traits;+using std::suspend_never;+using std::suspend_always;+using std::noop_coroutine;++#else // defined(ASIO_HAS_STD_COROUTINE)++using std::experimental::coroutine_handle;+using std::experimental::coroutine_traits;+using std::experimental::suspend_never;+using std::experimental::suspend_always;+using std::experimental::noop_coroutine;++#endif // defined(ASIO_HAS_STD_COROUTINE)++struct partial_coro+{+ coroutine_handle<void> handle{nullptr};+};++template <typename Allocator>+struct partial_promise_base+{+ template <typename Executor, typename Token, typename... Args>+ void* operator new(const std::size_t size, Executor&, Token& tk, Args&...)+ {+ return allocate_coroutine<Allocator>(size, get_associated_allocator(tk));+ }++ void operator delete(void* raw, const std::size_t size)+ {+ deallocate_coroutine<Allocator>(raw, size);+ }+};++template <>+struct partial_promise_base<std::allocator<void>>+{+};++template <typename Allocator>+struct partial_promise : partial_promise_base<Allocator>+{+ auto initial_suspend() noexcept+ {+ return asio::detail::suspend_always{};+ }++ auto final_suspend() noexcept+ {+ struct awaitable_t+ {+ partial_promise *p;++ constexpr bool await_ready() noexcept { return true; }++ auto await_suspend(asio::detail::coroutine_handle<>) noexcept+ {+ p->get_return_object().handle.destroy();+ }++ constexpr void await_resume() noexcept {}+ };++ return awaitable_t{this};+ }++ void return_void() {}++ partial_coro get_return_object()+ {+ return partial_coro{coroutine_handle<partial_promise>::from_promise(*this)};+ }++ void unhandled_exception()+ {+ assert(false);+ }+};++++}; // namespace detail+} // namespace experimental+} // namespace asio++#if defined(ASIO_HAS_STD_COROUTINE)++namespace std {++template <typename Executor, typename Completion, typename... Args>+struct coroutine_traits<+ asio::experimental::detail::partial_coro,+ Executor, Completion, Args...>+{+ using promise_type =+ asio::experimental::detail::partial_promise<+ asio::associated_allocator_t<Completion>>;+};++} // namespace std++#else // defined(ASIO_HAS_STD_COROUTINE)++namespace std { namespace experimental {++template <typename Executor, typename Completion, typename... Args>+struct coroutine_traits<+ asio::experimental::detail::partial_coro,+ Executor, Completion, Args...>+{+ using promise_type =+ asio::experimental::detail::partial_promise<+ asio::associated_allocator_t<Completion>>;+};++}} // namespace std::experimental++#endif // defined(ASIO_HAS_STD_COROUTINE)++namespace asio {+namespace experimental {+namespace detail {++template <execution::executor Executor,+ typename CompletionToken, typename... Args>+partial_coro post_coroutine(Executor exec,+ CompletionToken token, Args&&... args) noexcept+{+ post(exec, asio::append(std::move(token), std::move(args)...));+ co_return;+}++template <detail::execution_context Context,+ typename CompletionToken, typename... Args>+partial_coro post_coroutine(Context& ctx,+ CompletionToken token, Args&&... args) noexcept+{+ post(ctx, asio::append(std::move(token), std::move(args)...));+ co_return;+}++template <execution::executor Executor,+ typename CompletionToken, typename... Args>+partial_coro dispatch_coroutine(Executor exec,+ CompletionToken token, Args&&... args) noexcept+{+ dispatch(exec, asio::append(std::move(token), std::move(args)...));+ co_return;+}++template <detail::execution_context Context,+ typename CompletionToken, typename... Args>+partial_coro dispatch_coroutine(Context& ctx,+ CompletionToken token, Args &&... args) noexcept+{+ dispatch(ctx, asio::append(std::move(token), std::move(args)...));+ co_return;+}++} // namespace detail+} // namespace experimental+} // namespace asio++#endif // ASIO_EXPERIMENTAL_DETAIL_PARTIAL_PROMISE_HPP
+ link/modules/asio-standalone/asio/include/asio/experimental/impl/as_single.hpp view
@@ -0,0 +1,239 @@+//+// experimental/impl/as_single.hpp+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com)+//+// Distributed under the Boost Software License, Version 1.0. (See accompanying+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)+//++#ifndef ASIO_IMPL_EXPERIMENTAL_AS_SINGLE_HPP+#define ASIO_IMPL_EXPERIMENTAL_AS_SINGLE_HPP++#if defined(_MSC_VER) && (_MSC_VER >= 1200)+# pragma once+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)++#include "asio/detail/config.hpp"++#include <tuple>++#include "asio/associator.hpp"+#include "asio/async_result.hpp"+#include "asio/detail/handler_alloc_helpers.hpp"+#include "asio/detail/handler_cont_helpers.hpp"+#include "asio/detail/handler_invoke_helpers.hpp"+#include "asio/detail/type_traits.hpp"+#include "asio/detail/variadic_templates.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {+namespace experimental {+namespace detail {++// Class to adapt a as_single_t as a completion handler.+template <typename Handler>+class as_single_handler+{+public:+ typedef void result_type;++ template <typename CompletionToken>+ as_single_handler(as_single_t<CompletionToken> e)+ : handler_(ASIO_MOVE_CAST(CompletionToken)(e.token_))+ {+ }++ template <typename RedirectedHandler>+ as_single_handler(ASIO_MOVE_ARG(RedirectedHandler) h)+ : handler_(ASIO_MOVE_CAST(RedirectedHandler)(h))+ {+ }++ void operator()()+ {+ ASIO_MOVE_OR_LVALUE(Handler)(handler_)();+ }++ template <typename Arg>+ void operator()(ASIO_MOVE_ARG(Arg) arg)+ {+ ASIO_MOVE_OR_LVALUE(Handler)(handler_)(+ ASIO_MOVE_CAST(Arg)(arg));+ }++ template <typename... Args>+ void operator()(ASIO_MOVE_ARG(Args)... args)+ {+ ASIO_MOVE_OR_LVALUE(Handler)(handler_)(+ std::make_tuple(ASIO_MOVE_CAST(Args)(args)...));+ }++//private:+ Handler handler_;+};++template <typename Handler>+inline asio_handler_allocate_is_deprecated+asio_handler_allocate(std::size_t size,+ as_single_handler<Handler>* this_handler)+{+#if defined(ASIO_NO_DEPRECATED)+ asio_handler_alloc_helpers::allocate(size, this_handler->handler_);+ return asio_handler_allocate_is_no_longer_used();+#else // defined(ASIO_NO_DEPRECATED)+ return asio_handler_alloc_helpers::allocate(+ size, this_handler->handler_);+#endif // defined(ASIO_NO_DEPRECATED)+}++template <typename Handler>+inline asio_handler_deallocate_is_deprecated+asio_handler_deallocate(void* pointer, std::size_t size,+ as_single_handler<Handler>* this_handler)+{+ asio_handler_alloc_helpers::deallocate(+ pointer, size, this_handler->handler_);+#if defined(ASIO_NO_DEPRECATED)+ return asio_handler_deallocate_is_no_longer_used();+#endif // defined(ASIO_NO_DEPRECATED)+}++template <typename Handler>+inline bool asio_handler_is_continuation(+ as_single_handler<Handler>* this_handler)+{+ return asio_handler_cont_helpers::is_continuation(+ this_handler->handler_);+}++template <typename Function, typename Handler>+inline asio_handler_invoke_is_deprecated+asio_handler_invoke(Function& function,+ as_single_handler<Handler>* this_handler)+{+ asio_handler_invoke_helpers::invoke(+ function, this_handler->handler_);+#if defined(ASIO_NO_DEPRECATED)+ return asio_handler_invoke_is_no_longer_used();+#endif // defined(ASIO_NO_DEPRECATED)+}++template <typename Function, typename Handler>+inline asio_handler_invoke_is_deprecated+asio_handler_invoke(const Function& function,+ as_single_handler<Handler>* this_handler)+{+ asio_handler_invoke_helpers::invoke(+ function, this_handler->handler_);+#if defined(ASIO_NO_DEPRECATED)+ return asio_handler_invoke_is_no_longer_used();+#endif // defined(ASIO_NO_DEPRECATED)+}++template <typename Signature>+struct as_single_signature+{+ typedef Signature type;+};++template <typename R>+struct as_single_signature<R()>+{+ typedef R type();+};++template <typename R, typename Arg>+struct as_single_signature<R(Arg)>+{+ typedef R type(Arg);+};++template <typename R, typename... Args>+struct as_single_signature<R(Args...)>+{+ typedef R type(std::tuple<typename decay<Args>::type...>);+};++} // namespace detail+} // namespace experimental++#if !defined(GENERATING_DOCUMENTATION)++template <typename CompletionToken, typename Signature>+struct async_result<experimental::as_single_t<CompletionToken>, Signature>+{+ typedef typename async_result<CompletionToken,+ typename experimental::detail::as_single_signature<Signature>::type>+ ::return_type return_type;++ template <typename Initiation>+ struct init_wrapper+ {+ init_wrapper(Initiation init)+ : initiation_(ASIO_MOVE_CAST(Initiation)(init))+ {+ }++ template <typename Handler, typename... Args>+ void operator()(+ ASIO_MOVE_ARG(Handler) handler,+ ASIO_MOVE_ARG(Args)... args)+ {+ ASIO_MOVE_CAST(Initiation)(initiation_)(+ experimental::detail::as_single_handler<+ typename decay<Handler>::type>(+ ASIO_MOVE_CAST(Handler)(handler)),+ ASIO_MOVE_CAST(Args)(args)...);+ }++ Initiation initiation_;+ };++ template <typename Initiation, typename RawCompletionToken, typename... Args>+ static return_type initiate(+ ASIO_MOVE_ARG(Initiation) initiation,+ ASIO_MOVE_ARG(RawCompletionToken) token,+ ASIO_MOVE_ARG(Args)... args)+ {+ return async_initiate<CompletionToken,+ typename experimental::detail::as_single_signature<Signature>::type>(+ init_wrapper<typename decay<Initiation>::type>(+ ASIO_MOVE_CAST(Initiation)(initiation)),+ token.token_, ASIO_MOVE_CAST(Args)(args)...);+ }+};++template <template <typename, typename> class Associator,+ typename Handler, typename DefaultCandidate>+struct associator<Associator,+ experimental::detail::as_single_handler<Handler>, DefaultCandidate>+ : Associator<Handler, DefaultCandidate>+{+ static typename Associator<Handler, DefaultCandidate>::type+ get(const experimental::detail::as_single_handler<Handler>& h)+ ASIO_NOEXCEPT+ {+ return Associator<Handler, DefaultCandidate>::get(h.handler_);+ }++ static ASIO_AUTO_RETURN_TYPE_PREFIX2(+ typename Associator<Handler, DefaultCandidate>::type)+ get(const experimental::detail::as_single_handler<Handler>& h,+ const DefaultCandidate& c) ASIO_NOEXCEPT+ ASIO_AUTO_RETURN_TYPE_SUFFIX((+ Associator<Handler, DefaultCandidate>::get(h.handler_, c)))+ {+ return Associator<Handler, DefaultCandidate>::get(h.handler_, c);+ }+};++#endif // !defined(GENERATING_DOCUMENTATION)++} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // ASIO_IMPL_EXPERIMENTAL_AS_SINGLE_HPP
+ link/modules/asio-standalone/asio/include/asio/experimental/impl/channel_error.ipp view
@@ -0,0 +1,61 @@+//+// experimental/impl/channel_error.ipp+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com)+//+// Distributed under the Boost Software License, Version 1.0. (See accompanying+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)+//++#ifndef ASIO_EXPERIMENTAL_IMPL_CHANNEL_ERROR_IPP+#define ASIO_EXPERIMENTAL_IMPL_CHANNEL_ERROR_IPP++#if defined(_MSC_VER) && (_MSC_VER >= 1200)+# pragma once+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)++#include "asio/detail/config.hpp"+#include "asio/experimental/channel_error.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {+namespace experimental {+namespace error {+namespace detail {++class channel_category : public asio::error_category+{+public:+ const char* name() const ASIO_ERROR_CATEGORY_NOEXCEPT+ {+ return "asio.channel";+ }++ std::string message(int value) const+ {+ switch (value)+ {+ case channel_closed: return "Channel closed";+ case channel_cancelled: return "Channel cancelled";+ default: return "asio.channel error";+ }+ }+};++} // namespace detail++const asio::error_category& get_channel_category()+{+ static detail::channel_category instance;+ return instance;+}++} // namespace error+} // namespace experimental+} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // ASIO_EXPERIMENTAL_IMPL_CHANNEL_ERROR_IPP
+ link/modules/asio-standalone/asio/include/asio/experimental/impl/co_composed.hpp view
@@ -0,0 +1,1175 @@+//+// experimental/impl/co_composed.hpp+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com)+//+// Distributed under the Boost Software License, Version 1.0. (See accompanying+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)+//++#ifndef ASIO_IMPL_EXPERIMENTAL_CO_COMPOSED_HPP+#define ASIO_IMPL_EXPERIMENTAL_CO_COMPOSED_HPP++#if defined(_MSC_VER) && (_MSC_VER >= 1200)+# pragma once+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)++#include "asio/detail/config.hpp"+#include <new>+#include <tuple>+#include <variant>+#include "asio/associated_cancellation_slot.hpp"+#include "asio/associator.hpp"+#include "asio/async_result.hpp"+#include "asio/cancellation_state.hpp"+#include "asio/detail/composed_work.hpp"+#include "asio/detail/recycling_allocator.hpp"+#include "asio/detail/throw_error.hpp"+#include "asio/detail/type_traits.hpp"+#include "asio/error.hpp"++#if defined(ASIO_HAS_STD_COROUTINE)+# include <coroutine>+#else // defined(ASIO_HAS_STD_COROUTINE)+# include <experimental/coroutine>+#endif // defined(ASIO_HAS_STD_COROUTINE)++#if defined(ASIO_ENABLE_HANDLER_TRACKING)+# if defined(ASIO_HAS_SOURCE_LOCATION)+# include "asio/detail/source_location.hpp"+# endif // defined(ASIO_HAS_SOURCE_LOCATION)+#endif // defined(ASIO_ENABLE_HANDLER_TRACKING)++#include "asio/detail/push_options.hpp"++namespace asio {+namespace experimental {+namespace detail {++#if defined(ASIO_HAS_STD_COROUTINE)+using std::coroutine_handle;+using std::suspend_always;+using std::suspend_never;+#else // defined(ASIO_HAS_STD_COROUTINE)+using std::experimental::coroutine_handle;+using std::experimental::suspend_always;+using std::experimental::suspend_never;+#endif // defined(ASIO_HAS_STD_COROUTINE)++using asio::detail::composed_io_executors;+using asio::detail::composed_work;+using asio::detail::composed_work_guard;+using asio::detail::get_composed_io_executor;+using asio::detail::make_composed_io_executors;+using asio::detail::recycling_allocator;+using asio::detail::throw_error;++template <typename Executors, typename Handler, typename Return>+class co_composed_state;++template <typename Executors, typename Handler, typename Return>+class co_composed_handler_base;++template <typename Executors, typename Handler, typename Return>+class co_composed_promise;++template <completion_signature... Signatures>+class co_composed_returns+{+};++struct co_composed_on_suspend+{+ void (*fn_)(void*) = nullptr;+ void* arg_ = nullptr;+};++template <typename... T>+struct co_composed_completion : std::tuple<T&&...>+{+ template <typename... U>+ co_composed_completion(U&&... u) noexcept+ : std::tuple<T&&...>(std::forward<U>(u)...)+ {+ }+};++template <typename Executors, typename Handler,+ typename Return, typename Signature>+class co_composed_state_return_overload;++template <typename Executors, typename Handler,+ typename Return, typename R, typename... Args>+class co_composed_state_return_overload<+ Executors, Handler, Return, R(Args...)>+{+public:+ using derived_type = co_composed_state<Executors, Handler, Return>;+ using promise_type = co_composed_promise<Executors, Handler, Return>;+ using return_type = std::tuple<Args...>;++ void on_cancellation_complete_with(Args... args)+ {+ derived_type& state = *static_cast<derived_type*>(this);+ state.return_value_ = std::make_tuple(std::move(args)...);+ state.cancellation_on_suspend_fn(+ [](void* p)+ {+ auto& promise = *static_cast<promise_type*>(p);++ co_composed_handler_base<Executors, Handler,+ Return> composed_handler(promise);++ Handler handler(std::move(promise.state().handler_));+ return_type result(+ std::move(std::get<return_type>(promise.state().return_value_)));++ co_composed_handler_base<Executors, Handler,+ Return>(std::move(composed_handler));++ std::apply(std::move(handler), std::move(result));+ });+ }+};++template <typename Executors, typename Handler, typename Return>+class co_composed_state_return;++template <typename Executors, typename Handler, typename... Signatures>+class co_composed_state_return<+ Executors, Handler, co_composed_returns<Signatures...>>+ : public co_composed_state_return_overload<Executors,+ Handler, co_composed_returns<Signatures...>, Signatures>...+{+public:+ using co_composed_state_return_overload<Executors,+ Handler, co_composed_returns<Signatures...>,+ Signatures>::on_cancellation_complete_with...;++private:+ template <typename, typename, typename, typename>+ friend class co_composed_promise_return_overload;+ template <typename, typename, typename, typename>+ friend class co_composed_state_return_overload;++ std::variant<std::monostate,+ typename co_composed_state_return_overload<+ Executors, Handler, co_composed_returns<Signatures...>,+ Signatures>::return_type...> return_value_;+};++template <typename Executors, typename Handler,+ typename Return, typename... Signatures>+struct co_composed_state_default_cancellation_on_suspend_impl;++template <typename Executors, typename Handler, typename Return>+struct co_composed_state_default_cancellation_on_suspend_impl<+ Executors, Handler, Return>+{+ static constexpr void (*fn())(void*)+ {+ return nullptr;+ }+};++template <typename Executors, typename Handler, typename Return,+ typename R, typename... Args, typename... Signatures>+struct co_composed_state_default_cancellation_on_suspend_impl<+ Executors, Handler, Return, R(Args...), Signatures...>+{+ static constexpr void (*fn())(void*)+ {+ return co_composed_state_default_cancellation_on_suspend_impl<+ Executors, Handler, Return, Signatures...>::fn();+ }+};++template <typename Executors, typename Handler, typename Return,+ typename R, typename... Args, typename... Signatures>+struct co_composed_state_default_cancellation_on_suspend_impl<Executors,+ Handler, Return, R(asio::error_code, Args...), Signatures...>+{+ using promise_type = co_composed_promise<Executors, Handler, Return>;+ using return_type = std::tuple<asio::error_code, Args...>;++ static constexpr void (*fn())(void*)+ {+ if constexpr ((is_constructible<Args>::value && ...))+ {+ return [](void* p)+ {+ auto& promise = *static_cast<promise_type*>(p);++ co_composed_handler_base<Executors, Handler,+ Return> composed_handler(promise);++ Handler handler(std::move(promise.state().handler_));++ co_composed_handler_base<Executors, Handler,+ Return>(std::move(composed_handler));++ std::move(handler)(+ asio::error_code(asio::error::operation_aborted),+ Args{}...);+ };+ }+ else+ {+ return co_composed_state_default_cancellation_on_suspend_impl<+ Executors, Handler, Return, Signatures...>::fn();+ }+ }+};++template <typename Executors, typename Handler, typename Return,+ typename R, typename... Args, typename... Signatures>+struct co_composed_state_default_cancellation_on_suspend_impl<Executors,+ Handler, Return, R(std::exception_ptr, Args...), Signatures...>+{+ using promise_type = co_composed_promise<Executors, Handler, Return>;+ using return_type = std::tuple<std::exception_ptr, Args...>;++ static constexpr void (*fn())(void*)+ {+ if constexpr ((is_constructible<Args>::value && ...))+ {+ return [](void* p)+ {+ auto& promise = *static_cast<promise_type*>(p);++ co_composed_handler_base<Executors, Handler,+ Return> composed_handler(promise);++ Handler handler(std::move(promise.state().handler_));++ co_composed_handler_base<Executors, Handler,+ Return>(std::move(composed_handler));++ std::move(handler)(+ std::make_exception_ptr(+ asio::system_error(+ asio::error::operation_aborted, "co_await")),+ Args{}...);+ };+ }+ else+ {+ return co_composed_state_default_cancellation_on_suspend_impl<+ Executors, Handler, Return, Signatures...>::fn();+ }+ }+};++template <typename Executors, typename Handler, typename Return>+struct co_composed_state_default_cancellation_on_suspend;++template <typename Executors, typename Handler, typename... Signatures>+struct co_composed_state_default_cancellation_on_suspend<+ Executors, Handler, co_composed_returns<Signatures...>>+ : co_composed_state_default_cancellation_on_suspend_impl<Executors,+ Handler, co_composed_returns<Signatures...>, Signatures...>+{+};++template <typename Executors, typename Handler, typename Return>+class co_composed_state_cancellation+{+public:+ using cancellation_slot_type = cancellation_slot;++ cancellation_slot_type get_cancellation_slot() const noexcept+ {+ return cancellation_state_.slot();+ }++ cancellation_state get_cancellation_state() const noexcept+ {+ return cancellation_state_;+ }++ void reset_cancellation_state()+ {+ cancellation_state_ = cancellation_state(+ (get_associated_cancellation_slot)(+ static_cast<co_composed_state<Executors, Handler, Return>*>(+ this)->handler()));+ }++ template <typename Filter>+ void reset_cancellation_state(Filter filter)+ {+ cancellation_state_ = cancellation_state(+ (get_associated_cancellation_slot)(+ static_cast<co_composed_state<Executors, Handler, Return>*>(+ this)->handler()), filter, filter);+ }++ template <typename InFilter, typename OutFilter>+ void reset_cancellation_state(InFilter&& in_filter, OutFilter&& out_filter)+ {+ cancellation_state_ = cancellation_state(+ (get_associated_cancellation_slot)(+ static_cast<co_composed_state<Executors, Handler, Return>*>(+ this)->handler()),+ std::forward<InFilter>(in_filter),+ std::forward<OutFilter>(out_filter));+ }++ cancellation_type_t cancelled() const noexcept+ {+ return cancellation_state_.cancelled();+ }++ void clear_cancellation_slot() noexcept+ {+ cancellation_state_.slot().clear();+ }++ [[nodiscard]] bool throw_if_cancelled() const noexcept+ {+ return throw_if_cancelled_;+ }++ void throw_if_cancelled(bool b) noexcept+ {+ throw_if_cancelled_ = b;+ }++ [[nodiscard]] bool complete_if_cancelled() const noexcept+ {+ return complete_if_cancelled_;+ }++ void complete_if_cancelled(bool b) noexcept+ {+ complete_if_cancelled_ = b;+ }++private:+ template <typename, typename, typename>+ friend class co_composed_promise;+ template <typename, typename, typename, typename>+ friend class co_composed_state_return_overload;++ void cancellation_on_suspend_fn(void (*fn)(void*))+ {+ cancellation_on_suspend_fn_ = fn;+ }++ void check_for_cancellation_on_transform()+ {+ if (throw_if_cancelled_ && !!cancelled())+ throw_error(asio::error::operation_aborted, "co_await");+ }++ bool check_for_cancellation_on_suspend(+ co_composed_promise<Executors, Handler, Return>& promise) noexcept+ {+ if (complete_if_cancelled_ && !!cancelled() && cancellation_on_suspend_fn_)+ {+ promise.state().work_.reset();+ promise.state().on_suspend_->fn_ = cancellation_on_suspend_fn_;+ promise.state().on_suspend_->arg_ = &promise;+ return false;+ }+ return true;+ }++ cancellation_state cancellation_state_;+ void (*cancellation_on_suspend_fn_)(void*) =+ co_composed_state_default_cancellation_on_suspend<+ Executors, Handler, Return>::fn();+ bool throw_if_cancelled_ = false;+ bool complete_if_cancelled_ = true;+};++template <typename Executors, typename Handler, typename Return>+ requires is_same<+ typename associated_cancellation_slot<+ Handler, cancellation_slot+ >::asio_associated_cancellation_slot_is_unspecialised,+ void>::value+class co_composed_state_cancellation<Executors, Handler, Return>+{+public:+ void reset_cancellation_state()+ {+ }++ template <typename Filter>+ void reset_cancellation_state(Filter)+ {+ }++ template <typename InFilter, typename OutFilter>+ void reset_cancellation_state(InFilter&&, OutFilter&&)+ {+ }++ cancellation_type_t cancelled() const noexcept+ {+ return cancellation_type::none;+ }++ void clear_cancellation_slot() noexcept+ {+ }++ [[nodiscard]] bool throw_if_cancelled() const noexcept+ {+ return false;+ }++ void throw_if_cancelled(bool) noexcept+ {+ }++ [[nodiscard]] bool complete_if_cancelled() const noexcept+ {+ return false;+ }++ void complete_if_cancelled(bool) noexcept+ {+ }++private:+ template <typename, typename, typename>+ friend class co_composed_promise;+ template <typename, typename, typename, typename>+ friend class co_composed_state_return_overload;++ void cancellation_on_suspend_fn(void (*)(void*))+ {+ }++ void check_for_cancellation_on_transform() noexcept+ {+ }++ bool check_for_cancellation_on_suspend(+ co_composed_promise<Executors, Handler, Return>&) noexcept+ {+ return true;+ }+};++template <typename Executors, typename Handler, typename Return>+class co_composed_state+ : public co_composed_state_return<Executors, Handler, Return>,+ public co_composed_state_cancellation<Executors, Handler, Return>+{+public:+ using io_executor_type = typename composed_work_guard<+ typename composed_work<Executors>::head_type>::executor_type;++ template <typename H>+ co_composed_state(composed_io_executors<Executors>&& executors,+ H&& h, co_composed_on_suspend& on_suspend)+ : work_(std::move(executors)),+ handler_(std::forward<H>(h)),+ on_suspend_(&on_suspend)+ {+ this->reset_cancellation_state(enable_terminal_cancellation());+ }++ io_executor_type get_io_executor() const noexcept+ {+ return work_.head_.get_executor();+ }++ template <typename... Args>+ [[nodiscard]] co_composed_completion<Args...> complete(Args&&... args)+ requires requires { declval<Handler>()(std::forward<Args>(args)...); }+ {+ return co_composed_completion<Args...>(std::forward<Args>(args)...);+ }++ const Handler& handler() const noexcept+ {+ return handler_;+ }++private:+ template <typename, typename, typename>+ friend class co_composed_handler_base;+ template <typename, typename, typename>+ friend class co_composed_promise;+ template <typename, typename, typename, typename>+ friend class co_composed_promise_return_overload;+ template <typename, typename, typename>+ friend class co_composed_state_cancellation;+ template <typename, typename, typename, typename>+ friend class co_composed_state_return_overload;+ template <typename, typename, typename, typename...>+ friend struct co_composed_state_default_cancellation_on_suspend_impl;++ composed_work<Executors> work_;+ Handler handler_;+ co_composed_on_suspend* on_suspend_;+};++template <typename Executors, typename Handler, typename Return>+class co_composed_handler_cancellation+{+public:+ using cancellation_slot_type = cancellation_slot;++ cancellation_slot_type get_cancellation_slot() const noexcept+ {+ return static_cast<+ const co_composed_handler_base<Executors, Handler, Return>*>(+ this)->promise().state().get_cancellation_slot();+ }+};++template <typename Executors, typename Handler, typename Return>+ requires is_same<+ typename associated_cancellation_slot<+ Handler, cancellation_slot+ >::asio_associated_cancellation_slot_is_unspecialised,+ void>::value+class co_composed_handler_cancellation<Executors, Handler, Return>+{+};++template <typename Executors, typename Handler, typename Return>+class co_composed_handler_base :+ public co_composed_handler_cancellation<Executors, Handler, Return>+{+public:+ co_composed_handler_base(+ co_composed_promise<Executors, Handler, Return>& p) noexcept+ : p_(&p)+ {+ }++ co_composed_handler_base(co_composed_handler_base&& other) noexcept+ : p_(std::exchange(other.p_, nullptr))+ {+ }++ ~co_composed_handler_base()+ {+ if (p_) [[unlikely]]+ p_->destroy();+ }++ co_composed_promise<Executors, Handler, Return>& promise() const noexcept+ {+ return *p_;+ }++protected:+ void resume(void* result)+ {+ co_composed_on_suspend on_suspend{};+ std::exchange(p_, nullptr)->resume(p_, result, on_suspend);+ if (on_suspend.fn_)+ on_suspend.fn_(on_suspend.arg_);+ }++private:+ co_composed_promise<Executors, Handler, Return>* p_;+};++template <typename Executors, typename Handler,+ typename Return, typename Signature>+class co_composed_handler;++template <typename Executors, typename Handler,+ typename Return, typename R, typename... Args>+class co_composed_handler<Executors, Handler, Return, R(Args...)>+ : public co_composed_handler_base<Executors, Handler, Return>+{+public:+ using co_composed_handler_base<Executors,+ Handler, Return>::co_composed_handler_base;++ using result_type = std::tuple<typename decay<Args>::type...>;++ template <typename... T>+ void operator()(T&&... args)+ {+ result_type result(std::forward<T>(args)...);+ this->resume(&result);+ }++ static auto on_resume(void* result)+ {+ auto& args = *static_cast<result_type*>(result);+ if constexpr (sizeof...(Args) == 0)+ return;+ else if constexpr (sizeof...(Args) == 1)+ return std::move(std::get<0>(args));+ else+ return std::move(args);+ }+};++template <typename Executors, typename Handler,+ typename Return, typename R, typename... Args>+class co_composed_handler<Executors, Handler,+ Return, R(asio::error_code, Args...)>+ : public co_composed_handler_base<Executors, Handler, Return>+{+public:+ using co_composed_handler_base<Executors,+ Handler, Return>::co_composed_handler_base;++ using args_type = std::tuple<typename decay<Args>::type...>;+ using result_type = std::tuple<asio::error_code, args_type>;++ template <typename... T>+ void operator()(const asio::error_code& ec, T&&... args)+ {+ result_type result(ec, args_type(std::forward<T>(args)...));+ this->resume(&result);+ }++ static auto on_resume(void* result)+ {+ auto& [ec, args] = *static_cast<result_type*>(result);+ throw_error(ec);+ if constexpr (sizeof...(Args) == 0)+ return;+ else if constexpr (sizeof...(Args) == 1)+ return std::move(std::get<0>(args));+ else+ return std::move(args);+ }+};++template <typename Executors, typename Handler,+ typename Return, typename R, typename... Args>+class co_composed_handler<Executors, Handler,+ Return, R(std::exception_ptr, Args...)>+ : public co_composed_handler_base<Executors, Handler, Return>+{+public:+ using co_composed_handler_base<Executors,+ Handler, Return>::co_composed_handler_base;++ using args_type = std::tuple<typename decay<Args>::type...>;+ using result_type = std::tuple<std::exception_ptr, args_type>;++ template <typename... T>+ void operator()(std::exception_ptr ex, T&&... args)+ {+ result_type result(std::move(ex), args_type(std::forward<T>(args)...));+ this->resume(&result);+ }++ static auto on_resume(void* result)+ {+ auto& [ex, args] = *static_cast<result_type*>(result);+ if (ex)+ std::rethrow_exception(ex);+ if constexpr (sizeof...(Args) == 0)+ return;+ else if constexpr (sizeof...(Args) == 1)+ return std::move(std::get<0>(args));+ else+ return std::move(args);+ }+};++template <typename Executors, typename Handler, typename Return>+class co_composed_promise_return;++template <typename Executors, typename Handler>+class co_composed_promise_return<Executors, Handler, co_composed_returns<>>+{+public:+ auto final_suspend() noexcept+ {+ return suspend_never();+ }++ void return_void() noexcept+ {+ }+};++template <typename Executors, typename Handler,+ typename Return, typename Signature>+class co_composed_promise_return_overload;++template <typename Executors, typename Handler,+ typename Return, typename R, typename... Args>+class co_composed_promise_return_overload<+ Executors, Handler, Return, R(Args...)>+{+public:+ using derived_type = co_composed_promise<Executors, Handler, Return>;+ using return_type = std::tuple<Args...>;++ void return_value(std::tuple<Args...>&& value)+ {+ derived_type& promise = *static_cast<derived_type*>(this);+ promise.state().return_value_ = std::move(value);+ promise.state().work_.reset();+ promise.state().on_suspend_->arg_ = this;+ promise.state().on_suspend_->fn_ =+ [](void* p)+ {+ auto& promise = *static_cast<derived_type*>(p);++ co_composed_handler_base<Executors, Handler,+ Return> composed_handler(promise);++ Handler handler(std::move(promise.state().handler_));+ return_type result(+ std::move(std::get<return_type>(promise.state().return_value_)));++ co_composed_handler_base<Executors, Handler,+ Return>(std::move(composed_handler));++ std::apply(std::move(handler), std::move(result));+ };+ }+};++template <typename Executors, typename Handler, typename... Signatures>+class co_composed_promise_return<Executors,+ Handler, co_composed_returns<Signatures...>>+ : public co_composed_promise_return_overload<Executors,+ Handler, co_composed_returns<Signatures...>, Signatures>...+{+public:+ auto final_suspend() noexcept+ {+ return suspend_always();+ }++ using co_composed_promise_return_overload<Executors, Handler,+ co_composed_returns<Signatures...>, Signatures>::return_value...;++private:+ template <typename, typename, typename, typename>+ friend class co_composed_promise_return_overload;+};++template <typename Executors, typename Handler, typename Return>+class co_composed_promise+ : public co_composed_promise_return<Executors, Handler, Return>+{+public:+ template <typename... Args>+ void* operator new(std::size_t size,+ co_composed_state<Executors, Handler, Return>& state, Args&&...)+ {+ block_allocator_type allocator(+ (get_associated_allocator)(state.handler_,+ recycling_allocator<void>()));++ block* base_ptr = std::allocator_traits<block_allocator_type>::allocate(+ allocator, blocks(sizeof(allocator_type)) + blocks(size));++ new (static_cast<void*>(base_ptr)) allocator_type(std::move(allocator));++ return base_ptr + blocks(sizeof(allocator_type));+ }++ template <typename C, typename... Args>+ void* operator new(std::size_t size, C&&,+ co_composed_state<Executors, Handler, Return>& state, Args&&...)+ {+ return co_composed_promise::operator new(size, state);+ }++ void operator delete(void* ptr, std::size_t size)+ {+ block* base_ptr = static_cast<block*>(ptr) - blocks(sizeof(allocator_type));++ allocator_type* allocator_ptr = std::launder(+ static_cast<allocator_type*>(static_cast<void*>(base_ptr)));++ block_allocator_type block_allocator(std::move(*allocator_ptr));+ allocator_ptr->~allocator_type();++ std::allocator_traits<block_allocator_type>::deallocate(block_allocator,+ base_ptr, blocks(sizeof(allocator_type)) + blocks(size));+ }++ template <typename... Args>+ co_composed_promise(+ co_composed_state<Executors, Handler, Return>& state, Args&&...)+ : state_(state)+ {+ }++ template <typename C, typename... Args>+ co_composed_promise(C&&,+ co_composed_state<Executors, Handler, Return>& state, Args&&...)+ : state_(state)+ {+ }++ void destroy() noexcept+ {+ coroutine_handle<co_composed_promise>::from_promise(*this).destroy();+ }++ void resume(co_composed_promise*& owner, void* result,+ co_composed_on_suspend& on_suspend)+ {+ state_.on_suspend_ = &on_suspend;+ state_.clear_cancellation_slot();+ owner_ = &owner;+ result_ = result;+ coroutine_handle<co_composed_promise>::from_promise(*this).resume();+ }++ co_composed_state<Executors, Handler, Return>& state() noexcept+ {+ return state_;+ }++ void get_return_object() noexcept+ {+ }++ auto initial_suspend() noexcept+ {+ return suspend_never();+ }++ void unhandled_exception()+ {+ if (owner_)+ *owner_ = this;+ throw;+ }++ template <async_operation Op>+ auto await_transform(Op&& op+#if defined(ASIO_ENABLE_HANDLER_TRACKING)+# if defined(ASIO_HAS_SOURCE_LOCATION)+ , asio::detail::source_location location+ = asio::detail::source_location::current()+# endif // defined(ASIO_HAS_SOURCE_LOCATION)+#endif // defined(ASIO_ENABLE_HANDLER_TRACKING)+ )+ {+ class [[nodiscard]] awaitable+ {+ public:+ awaitable(Op&& op, co_composed_promise& promise+#if defined(ASIO_ENABLE_HANDLER_TRACKING)+# if defined(ASIO_HAS_SOURCE_LOCATION)+ , const asio::detail::source_location& location+# endif // defined(ASIO_HAS_SOURCE_LOCATION)+#endif // defined(ASIO_ENABLE_HANDLER_TRACKING)+ )+ : op_(std::forward<Op>(op)),+ promise_(promise)+#if defined(ASIO_ENABLE_HANDLER_TRACKING)+# if defined(ASIO_HAS_SOURCE_LOCATION)+ , location_(location)+# endif // defined(ASIO_HAS_SOURCE_LOCATION)+#endif // defined(ASIO_ENABLE_HANDLER_TRACKING)+ {+ }++ constexpr bool await_ready() const noexcept+ {+ return false;+ }++ void await_suspend(coroutine_handle<co_composed_promise>)+ {+ if (promise_.state_.check_for_cancellation_on_suspend(promise_))+ {+ promise_.state_.on_suspend_->arg_ = this;+ promise_.state_.on_suspend_->fn_ =+ [](void* p)+ {+#if defined(ASIO_ENABLE_HANDLER_TRACKING)+# if defined(ASIO_HAS_SOURCE_LOCATION)+ ASIO_HANDLER_LOCATION((+ static_cast<awaitable*>(p)->location_.file_name(),+ static_cast<awaitable*>(p)->location_.line(),+ static_cast<awaitable*>(p)->location_.function_name()));+# endif // defined(ASIO_HAS_SOURCE_LOCATION)+#endif // defined(ASIO_ENABLE_HANDLER_TRACKING)+ std::forward<Op>(static_cast<awaitable*>(p)->op_)(+ co_composed_handler<Executors, Handler,+ Return, completion_signature_of_t<Op>>(+ static_cast<awaitable*>(p)->promise_));+ };+ }+ }++ auto await_resume()+ {+ return co_composed_handler<Executors, Handler, Return,+ completion_signature_of_t<Op>>::on_resume(promise_.result_);+ }++ private:+ Op&& op_;+ co_composed_promise& promise_;+#if defined(ASIO_ENABLE_HANDLER_TRACKING)+# if defined(ASIO_HAS_SOURCE_LOCATION)+ asio::detail::source_location location_;+# endif // defined(ASIO_HAS_SOURCE_LOCATION)+#endif // defined(ASIO_ENABLE_HANDLER_TRACKING)+ };++ state_.check_for_cancellation_on_transform();+ return awaitable{std::forward<Op>(op), *this+#if defined(ASIO_ENABLE_HANDLER_TRACKING)+# if defined(ASIO_HAS_SOURCE_LOCATION)+ , location+# endif // defined(ASIO_HAS_SOURCE_LOCATION)+#endif // defined(ASIO_ENABLE_HANDLER_TRACKING)+ };+ }++ template <typename... Args>+ auto yield_value(co_composed_completion<Args...>&& result)+ {+ class [[nodiscard]] awaitable+ {+ public:+ awaitable(co_composed_completion<Args...>&& result,+ co_composed_promise& promise)+ : result_(std::move(result)),+ promise_(promise)+ {+ }++ constexpr bool await_ready() const noexcept+ {+ return false;+ }++ void await_suspend(coroutine_handle<co_composed_promise>)+ {+ promise_.state_.work_.reset();+ promise_.state_.on_suspend_->arg_ = this;+ promise_.state_.on_suspend_->fn_ =+ [](void* p)+ {+ awaitable& a = *static_cast<awaitable*>(p);++ co_composed_handler_base<Executors, Handler,+ Return> composed_handler(a.promise_);++ Handler handler(std::move(a.promise_.state_.handler_));+ std::tuple<typename decay<Args>::type...> result(+ std::move(static_cast<std::tuple<Args&&...>>(a.result_)));++ co_composed_handler_base<Executors, Handler,+ Return>(std::move(composed_handler));++ std::apply(std::move(handler), std::move(result));+ };+ }++ void await_resume() noexcept+ {+ }++ private:+ co_composed_completion<Args...> result_;+ co_composed_promise& promise_;+ };++ return awaitable{std::move(result), *this};+ }++private:+ using allocator_type =+ associated_allocator_t<Handler, recycling_allocator<void>>;++ union block+ {+ std::max_align_t max_align;+ alignas(allocator_type) char pad[alignof(allocator_type)];+ };++ using block_allocator_type =+ typename std::allocator_traits<allocator_type>+ ::template rebind_alloc<block>;++ static constexpr std::size_t blocks(std::size_t size)+ {+ return (size + sizeof(block) - 1) / sizeof(block);+ }++ co_composed_state<Executors, Handler, Return>& state_;+ co_composed_promise** owner_ = nullptr;+ void* result_ = nullptr;+};++template <typename Implementation, typename Executors, typename... Signatures>+class initiate_co_composed+{+public:+ using executor_type = typename composed_io_executors<Executors>::head_type;++ template <typename I>+ initiate_co_composed(I&& impl, composed_io_executors<Executors>&& executors)+ : implementation_(std::forward<I>(impl)),+ executors_(std::move(executors))+ {+ }++ executor_type get_executor() const noexcept+ {+ return executors_.head_;+ }++ template <typename Handler, typename... InitArgs>+ void operator()(Handler&& handler, InitArgs&&... init_args) const &+ {+ using handler_type = typename decay<Handler>::type;+ using returns_type = co_composed_returns<Signatures...>;+ co_composed_on_suspend on_suspend{};+ implementation_(+ co_composed_state<Executors, handler_type, returns_type>(+ executors_, std::forward<Handler>(handler), on_suspend),+ std::forward<InitArgs>(init_args)...);+ if (on_suspend.fn_)+ on_suspend.fn_(on_suspend.arg_);+ }++ template <typename Handler, typename... InitArgs>+ void operator()(Handler&& handler, InitArgs&&... init_args) &&+ {+ using handler_type = typename decay<Handler>::type;+ using returns_type = co_composed_returns<Signatures...>;+ co_composed_on_suspend on_suspend{};+ std::move(implementation_)(+ co_composed_state<Executors, handler_type, returns_type>(+ std::move(executors_), std::forward<Handler>(handler), on_suspend),+ std::forward<InitArgs>(init_args)...);+ if (on_suspend.fn_)+ on_suspend.fn_(on_suspend.arg_);+ }++private:+ Implementation implementation_;+ composed_io_executors<Executors> executors_;+};++template <typename... Signatures, typename Implementation, typename Executors>+inline initiate_co_composed<Implementation, Executors, Signatures...>+make_initiate_co_composed(Implementation&& implementation,+ composed_io_executors<Executors>&& executors)+{+ return initiate_co_composed<+ typename decay<Implementation>::type, Executors, Signatures...>(+ std::forward<Implementation>(implementation), std::move(executors));+}++} // namespace detail++template <completion_signature... Signatures,+ typename Implementation, typename... IoObjectsOrExecutors>+inline auto co_composed(Implementation&& implementation,+ IoObjectsOrExecutors&&... io_objects_or_executors)+{+ return detail::make_initiate_co_composed<Signatures...>(+ std::forward<Implementation>(implementation),+ detail::make_composed_io_executors(+ detail::get_composed_io_executor(+ std::forward<IoObjectsOrExecutors>(+ io_objects_or_executors))...));+}++} // namespace experimental++#if !defined(GENERATING_DOCUMENTATION)++template <template <typename, typename> class Associator,+ typename Executors, typename Handler, typename Return,+ typename Signature, typename DefaultCandidate>+struct associator<Associator,+ experimental::detail::co_composed_handler<+ Executors, Handler, Return, Signature>,+ DefaultCandidate>+ : Associator<Handler, DefaultCandidate>+{+ static typename Associator<Handler, DefaultCandidate>::type+ get(const experimental::detail::co_composed_handler<+ Executors, Handler, Return, Signature>& h) ASIO_NOEXCEPT+ {+ return Associator<Handler, DefaultCandidate>::get(+ h.promise().state().handler());+ }++ static ASIO_AUTO_RETURN_TYPE_PREFIX2(+ typename Associator<Handler, DefaultCandidate>::type)+ get(const experimental::detail::co_composed_handler<+ Executors, Handler, Return, Signature>& h,+ const DefaultCandidate& c) ASIO_NOEXCEPT+ ASIO_AUTO_RETURN_TYPE_SUFFIX((+ Associator<Handler, DefaultCandidate>::get(+ h.promise().state().handler(), c)))+ {+ return Associator<Handler, DefaultCandidate>::get(+ h.promise().state().handler(), c);+ }+};++#endif // !defined(GENERATING_DOCUMENTATION)++} // namespace asio++#if !defined(GENERATING_DOCUMENTATION)+# if defined(ASIO_HAS_STD_COROUTINE)+namespace std {+# else // defined(ASIO_HAS_STD_COROUTINE)+namespace std { namespace experimental {+# endif // defined(ASIO_HAS_STD_COROUTINE)++template <typename C, typename Executors,+ typename Handler, typename Return, typename... Args>+struct coroutine_traits<void, C&,+ asio::experimental::detail::co_composed_state<+ Executors, Handler, Return>,+ Args...>+{+ using promise_type =+ asio::experimental::detail::co_composed_promise<+ Executors, Handler, Return>;+};++template <typename C, typename Executors,+ typename Handler, typename Return, typename... Args>+struct coroutine_traits<void, C&&,+ asio::experimental::detail::co_composed_state<+ Executors, Handler, Return>,+ Args...>+{+ using promise_type =+ asio::experimental::detail::co_composed_promise<+ Executors, Handler, Return>;+};++template <typename Executors, typename Handler,+ typename Return, typename... Args>+struct coroutine_traits<void,+ asio::experimental::detail::co_composed_state<+ Executors, Handler, Return>,+ Args...>+{+ using promise_type =+ asio::experimental::detail::co_composed_promise<+ Executors, Handler, Return>;+};++# if defined(ASIO_HAS_STD_COROUTINE)+} // namespace std+# else // defined(ASIO_HAS_STD_COROUTINE)+}} // namespace std::experimental+# endif // defined(ASIO_HAS_STD_COROUTINE)+#endif // !defined(GENERATING_DOCUMENTATION)++#include "asio/detail/pop_options.hpp"++#endif // ASIO_IMPL_EXPERIMENTAL_CO_COMPOSED_HPP
+ link/modules/asio-standalone/asio/include/asio/experimental/impl/coro.hpp view
@@ -0,0 +1,1222 @@+//+// experimental/impl/coro.hpp+// ~~~~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2021-2023 Klemens D. Morgenstern+// (klemens dot morgenstern at gmx dot net)+//+// Distributed under the Boost Software License, Version 1.0. (See accompanying+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)++//+#ifndef ASIO_EXPERIMENTAL_IMPL_CORO_HPP+#define ASIO_EXPERIMENTAL_IMPL_CORO_HPP++#if defined(_MSC_VER) && (_MSC_VER >= 1200)+# pragma once+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)++#include "asio/detail/config.hpp"+#include "asio/append.hpp"+#include "asio/associated_cancellation_slot.hpp"+#include "asio/bind_allocator.hpp"+#include "asio/deferred.hpp"+#include "asio/experimental/detail/coro_completion_handler.hpp"+#include "asio/detail/push_options.hpp"++namespace asio {+namespace experimental {++template <typename Yield, typename Return,+ typename Executor, typename Allocator>+struct coro;++namespace detail {++struct coro_cancellation_source+{+ cancellation_slot slot;+ cancellation_state state;+ bool throw_if_cancelled_ = true;++ void reset_cancellation_state()+ {+ state = cancellation_state(slot);+ }++ template <typename Filter>+ void reset_cancellation_state(ASIO_MOVE_ARG(Filter) filter)+ {+ state = cancellation_state(slot, ASIO_MOVE_CAST(Filter)(filter));+ }++ template <typename InFilter, typename OutFilter>+ void reset_cancellation_state(ASIO_MOVE_ARG(InFilter) in_filter,+ ASIO_MOVE_ARG(OutFilter) out_filter)+ {+ state = cancellation_state(slot,+ ASIO_MOVE_CAST(InFilter)(in_filter),+ ASIO_MOVE_CAST(OutFilter)(out_filter));+ }++ bool throw_if_cancelled() const+ {+ return throw_if_cancelled_;+ }++ void throw_if_cancelled(bool value)+ {+ throw_if_cancelled_ = value;+ }+};++template <typename Signature, typename Return,+ typename Executor, typename Allocator>+struct coro_promise;++template <typename T>+struct is_noexcept : std::false_type+{+};++template <typename Return, typename... Args>+struct is_noexcept<Return(Args...)> : std::false_type+{+};++template <typename Return, typename... Args>+struct is_noexcept<Return(Args...) noexcept> : std::true_type+{+};++template <typename T>+constexpr bool is_noexcept_v = is_noexcept<T>::value;++template <typename T>+struct coro_error;++template <>+struct coro_error<asio::error_code>+{+ static asio::error_code invalid()+ {+ return asio::error::fault;+ }++ static asio::error_code cancelled()+ {+ return asio::error::operation_aborted;+ }++ static asio::error_code interrupted()+ {+ return asio::error::interrupted;+ }++ static asio::error_code done()+ {+ return asio::error::broken_pipe;+ }+};++template <>+struct coro_error<std::exception_ptr>+{+ static std::exception_ptr invalid()+ {+ return std::make_exception_ptr(+ asio::system_error(+ coro_error<asio::error_code>::invalid()));+ }++ static std::exception_ptr cancelled()+ {+ return std::make_exception_ptr(+ asio::system_error(+ coro_error<asio::error_code>::cancelled()));+ }++ static std::exception_ptr interrupted()+ {+ return std::make_exception_ptr(+ asio::system_error(+ coro_error<asio::error_code>::interrupted()));+ }++ static std::exception_ptr done()+ {+ return std::make_exception_ptr(+ asio::system_error(+ coro_error<asio::error_code>::done()));+ }+};++template <typename T, typename Coroutine >+struct coro_with_arg+{+ using coro_t = Coroutine;+ T value;+ coro_t& coro;++ struct awaitable_t+ {+ T value;+ coro_t& coro;++ constexpr static bool await_ready() { return false; }++ template <typename Y, typename R, typename E, typename A>+ auto await_suspend(coroutine_handle<coro_promise<Y, R, E, A>> h)+ -> coroutine_handle<>+ {+ auto& hp = h.promise();++ if constexpr (!coro_promise<Y, R, E, A>::is_noexcept)+ {+ if ((hp.cancel->state.cancelled() != cancellation_type::none)+ && hp.cancel->throw_if_cancelled_)+ {+ asio::detail::throw_error(+ asio::error::operation_aborted, "coro-cancelled");+ }+ }++ if (hp.get_executor() == coro.get_executor())+ {+ coro.coro_->awaited_from = h;+ coro.coro_->reset_error();+ coro.coro_->input_ = std::move(value);+ coro.coro_->cancel = hp.cancel;+ return coro.coro_->get_handle();+ }+ else+ {+ coro.coro_->awaited_from =+ dispatch_coroutine(+ asio::prefer(hp.get_executor(),+ execution::outstanding_work.tracked),+ [h]() mutable { h.resume(); }).handle;++ coro.coro_->reset_error();+ coro.coro_->input_ = std::move(value);++ struct cancel_handler+ {+ using src = std::pair<cancellation_signal,+ detail::coro_cancellation_source>;++ std::shared_ptr<src> st = std::make_shared<src>();++ cancel_handler(E e, coro_t& coro) : e(e), coro_(coro.coro_)+ {+ st->second.state =+ cancellation_state(st->second.slot = st->first.slot());+ }++ E e;+ typename coro_t::promise_type* coro_;++ void operator()(cancellation_type ct)+ {+ asio::dispatch(e, [ct, st = st]() mutable+ {+ auto & [sig, state] = *st;+ sig.emit(ct);+ });+ }+ };++ if (hp.cancel->state.slot().is_connected())+ {+ hp.cancel->state.slot().template emplace<cancel_handler>(+ coro.get_executor(), coro);+ }++ auto hh = detail::coroutine_handle<+ typename coro_t::promise_type>::from_promise(*coro.coro_);++ return dispatch_coroutine(+ coro.coro_->get_executor(), [hh]() mutable { hh.resume(); }).handle;+ }+ }++ auto await_resume() -> typename coro_t::result_type+ {+ coro.coro_->cancel = nullptr;+ coro.coro_->rethrow_if();+ return std::move(coro.coro_->result_);+ }+ };++ template <typename CompletionToken>+ auto async_resume(CompletionToken&& token) &&+ {+ return coro.async_resume(std::move(value),+ std::forward<CompletionToken>(token));+ }++ auto operator co_await() &&+ {+ return awaitable_t{std::move(value), coro};+ }+};++template <bool IsNoexcept>+struct coro_promise_error;++template <>+struct coro_promise_error<false>+{+ std::exception_ptr error_;++ void reset_error()+ {+ error_ = std::exception_ptr{};+ }++ void unhandled_exception()+ {+ error_ = std::current_exception();+ }++ void rethrow_if()+ {+ if (error_)+ std::rethrow_exception(error_);+ }+};++#if defined(__GNUC__)+# pragma GCC diagnostic push+# if defined(__clang__)+# pragma GCC diagnostic ignored "-Wexceptions"+# else+# pragma GCC diagnostic ignored "-Wterminate"+# endif+#elif defined(_MSC_VER)+# pragma warning(push)+# pragma warning (disable:4297)+#endif++template <>+struct coro_promise_error<true>+{+ void reset_error()+ {+ }++ void unhandled_exception() noexcept+ {+ throw;+ }++ void rethrow_if()+ {+ }+};++#if defined(__GNUC__)+# pragma GCC diagnostic pop+#elif defined(_MSC_VER)+# pragma warning(pop)+#endif++template <typename T = void>+struct yield_input+{+ T& value;+ coroutine_handle<> awaited_from{noop_coroutine()};++ bool await_ready() const noexcept+ {+ return false;+ }++ template <typename U>+ coroutine_handle<> await_suspend(coroutine_handle<U>) noexcept+ {+ return std::exchange(awaited_from, noop_coroutine());+ }++ T await_resume() const noexcept+ {+ return std::move(value);+ }+};++template <>+struct yield_input<void>+{+ coroutine_handle<> awaited_from{noop_coroutine()};++ bool await_ready() const noexcept+ {+ return false;+ }++ auto await_suspend(coroutine_handle<>) noexcept+ {+ return std::exchange(awaited_from, noop_coroutine());+ }++ constexpr void await_resume() const noexcept+ {+ }+};++struct coro_awaited_from+{+ coroutine_handle<> awaited_from{noop_coroutine()};++ auto final_suspend() noexcept+ {+ struct suspendor+ {+ coroutine_handle<> awaited_from;++ constexpr static bool await_ready() noexcept+ {+ return false;+ }++ auto await_suspend(coroutine_handle<>) noexcept+ {+ return std::exchange(awaited_from, noop_coroutine());+ }++ constexpr static void await_resume() noexcept+ {+ }+ };++ return suspendor{std::exchange(awaited_from, noop_coroutine())};+ }++ ~coro_awaited_from()+ {+ awaited_from.resume();+ }//must be on the right executor+};++template <typename Yield, typename Input, typename Return>+struct coro_promise_exchange : coro_awaited_from+{+ using result_type = coro_result_t<Yield, Return>;++ result_type result_;+ Input input_;++ auto yield_value(Yield&& y)+ {+ result_ = std::move(y);+ return yield_input<Input>{std::move(input_),+ std::exchange(awaited_from, noop_coroutine())};+ }++ auto yield_value(const Yield& y)+ {+ result_ = y;+ return yield_input<Input>{std::move(input_),+ std::exchange(awaited_from, noop_coroutine())};+ }++ void return_value(const Return& r)+ {+ result_ = r;+ }++ void return_value(Return&& r)+ {+ result_ = std::move(r);+ }+};++template <typename YieldReturn>+struct coro_promise_exchange<YieldReturn, void, YieldReturn> : coro_awaited_from+{+ using result_type = coro_result_t<YieldReturn, YieldReturn>;++ result_type result_;++ auto yield_value(const YieldReturn& y)+ {+ result_ = y;+ return yield_input<void>{std::exchange(awaited_from, noop_coroutine())};+ }++ auto yield_value(YieldReturn&& y)+ {+ result_ = std::move(y);+ return yield_input<void>{std::exchange(awaited_from, noop_coroutine())};+ }++ void return_value(const YieldReturn& r)+ {+ result_ = r;+ }++ void return_value(YieldReturn&& r)+ {+ result_ = std::move(r);+ }+};++template <typename Yield, typename Return>+struct coro_promise_exchange<Yield, void, Return> : coro_awaited_from+{+ using result_type = coro_result_t<Yield, Return>;++ result_type result_;++ auto yield_value(const Yield& y)+ {+ result_.template emplace<0>(y);+ return yield_input<void>{std::exchange(awaited_from, noop_coroutine())};+ }++ auto yield_value(Yield&& y)+ {+ result_.template emplace<0>(std::move(y));+ return yield_input<void>{std::exchange(awaited_from, noop_coroutine())};+ }++ void return_value(const Return& r)+ {+ result_.template emplace<1>(r);+ }++ void return_value(Return&& r)+ {+ result_.template emplace<1>(std::move(r));+ }+};++template <typename Yield, typename Input>+struct coro_promise_exchange<Yield, Input, void> : coro_awaited_from+{+ using result_type = coro_result_t<Yield, void>;++ result_type result_;+ Input input_;++ auto yield_value(Yield&& y)+ {+ result_ = std::move(y);+ return yield_input<Input>{input_,+ std::exchange(awaited_from, noop_coroutine())};+ }++ auto yield_value(const Yield& y)+ {+ result_ = y;+ return yield_input<Input>{input_,+ std::exchange(awaited_from, noop_coroutine())};+ }++ void return_void()+ {+ result_.reset();+ }+};++template <typename Return>+struct coro_promise_exchange<void, void, Return> : coro_awaited_from+{+ using result_type = coro_result_t<void, Return>;++ result_type result_;++ void yield_value();++ void return_value(const Return& r)+ {+ result_ = r;+ }++ void return_value(Return&& r)+ {+ result_ = std::move(r);+ }+};++template <>+struct coro_promise_exchange<void, void, void> : coro_awaited_from+{+ void return_void() {}++ void yield_value();+};++template <typename Yield>+struct coro_promise_exchange<Yield, void, void> : coro_awaited_from+{+ using result_type = coro_result_t<Yield, void>;++ result_type result_;++ auto yield_value(const Yield& y)+ {+ result_ = y;+ return yield_input<void>{std::exchange(awaited_from, noop_coroutine())};+ }++ auto yield_value(Yield&& y)+ {+ result_ = std::move(y);+ return yield_input<void>{std::exchange(awaited_from, noop_coroutine())};+ }++ void return_void()+ {+ result_.reset();+ }+};++template <typename Yield, typename Return,+ typename Executor, typename Allocator>+struct coro_promise final :+ coro_promise_allocator<Allocator>,+ coro_promise_error<coro_traits<Yield, Return, Executor>::is_noexcept>,+ coro_promise_exchange<+ typename coro_traits<Yield, Return, Executor>::yield_type,+ typename coro_traits<Yield, Return, Executor>::input_type,+ typename coro_traits<Yield, Return, Executor>::return_type>+{+ using coro_type = coro<Yield, Return, Executor, Allocator>;++ auto handle()+ {+ return coroutine_handle<coro_promise>::from_promise(this);+ }++ using executor_type = Executor;++ executor_type executor_;++ std::optional<coro_cancellation_source> cancel_source;+ coro_cancellation_source * cancel;++ using cancellation_slot_type = asio::cancellation_slot;++ cancellation_slot_type get_cancellation_slot() const noexcept+ {+ return cancel ? cancel->slot : cancellation_slot_type{};+ }++ using allocator_type =+ typename std::allocator_traits<associated_allocator_t<Executor>>::+ template rebind_alloc<std::byte>;+ using traits = coro_traits<Yield, Return, Executor>;++ using input_type = typename traits::input_type;+ using yield_type = typename traits::yield_type;+ using return_type = typename traits::return_type;+ using error_type = typename traits::error_type;+ using result_type = typename traits::result_type;+ constexpr static bool is_noexcept = traits::is_noexcept;++ auto get_executor() const -> Executor+ {+ return executor_;+ }++ auto get_handle()+ {+ return coroutine_handle<coro_promise>::from_promise(*this);+ }++ template <typename... Args>+ coro_promise(Executor executor, Args&&... args) noexcept+ : coro_promise_allocator<Allocator>(+ executor, std::forward<Args>(args)...),+ executor_(std::move(executor))+ {+ }++ template <typename First, typename... Args>+ coro_promise(First&& f, Executor executor, Args&&... args) noexcept+ : coro_promise_allocator<Allocator>(+ f, executor, std::forward<Args>(args)...),+ executor_(std::move(executor))+ {+ }++ template <typename First, detail::execution_context Context, typename... Args>+ coro_promise(First&& f, Context&& ctx, Args&&... args) noexcept+ : coro_promise_allocator<Allocator>(+ f, ctx, std::forward<Args>(args)...),+ executor_(ctx.get_executor())+ {+ }++ template <detail::execution_context Context, typename... Args>+ coro_promise(Context&& ctx, Args&&... args) noexcept+ : coro_promise_allocator<Allocator>(+ ctx, std::forward<Args>(args)...),+ executor_(ctx.get_executor())+ {+ }++ auto get_return_object()+ {+ return coro<Yield, Return, Executor, Allocator>{this};+ }++ auto initial_suspend() noexcept+ {+ return suspend_always{};+ }++ using coro_promise_exchange<+ typename coro_traits<Yield, Return, Executor>::yield_type,+ typename coro_traits<Yield, Return, Executor>::input_type,+ typename coro_traits<Yield, Return, Executor>::return_type>::yield_value;++ auto await_transform(this_coro::executor_t) const+ {+ struct exec_helper+ {+ const executor_type& value;++ constexpr static bool await_ready() noexcept+ {+ return true;+ }++ constexpr static void await_suspend(coroutine_handle<>) noexcept+ {+ }++ executor_type await_resume() const noexcept+ {+ return value;+ }+ };++ return exec_helper{executor_};+ }++ auto await_transform(this_coro::cancellation_state_t) const+ {+ struct exec_helper+ {+ const asio::cancellation_state& value;++ constexpr static bool await_ready() noexcept+ {+ return true;+ }++ constexpr static void await_suspend(coroutine_handle<>) noexcept+ {+ }++ asio::cancellation_state await_resume() const noexcept+ {+ return value;+ }+ };+ assert(cancel);+ return exec_helper{cancel->state};+ }++ // This await transformation resets the associated cancellation state.+ auto await_transform(this_coro::reset_cancellation_state_0_t) noexcept+ {+ struct result+ {+ detail::coro_cancellation_source * src_;++ bool await_ready() const noexcept+ {+ return true;+ }++ void await_suspend(coroutine_handle<void>) noexcept+ {+ }++ auto await_resume() const+ {+ return src_->reset_cancellation_state();+ }+ };++ return result{cancel};+ }++ // This await transformation resets the associated cancellation state.+ template <typename Filter>+ auto await_transform(+ this_coro::reset_cancellation_state_1_t<Filter> reset) noexcept+ {+ struct result+ {+ detail::coro_cancellation_source* src_;+ Filter filter_;++ bool await_ready() const noexcept+ {+ return true;+ }++ void await_suspend(coroutine_handle<void>) noexcept+ {+ }++ auto await_resume()+ {+ return src_->reset_cancellation_state(+ ASIO_MOVE_CAST(Filter)(filter_));+ }+ };++ return result{cancel, ASIO_MOVE_CAST(Filter)(reset.filter)};+ }++ // This await transformation resets the associated cancellation state.+ template <typename InFilter, typename OutFilter>+ auto await_transform(+ this_coro::reset_cancellation_state_2_t<InFilter, OutFilter> reset)+ noexcept+ {+ struct result+ {+ detail::coro_cancellation_source* src_;+ InFilter in_filter_;+ OutFilter out_filter_;++ bool await_ready() const noexcept+ {+ return true;+ }++ void await_suspend(coroutine_handle<void>) noexcept+ {+ }++ auto await_resume()+ {+ return src_->reset_cancellation_state(+ ASIO_MOVE_CAST(InFilter)(in_filter_),+ ASIO_MOVE_CAST(OutFilter)(out_filter_));+ }+ };++ return result{cancel,+ ASIO_MOVE_CAST(InFilter)(reset.in_filter),+ ASIO_MOVE_CAST(OutFilter)(reset.out_filter)};+ }++ // This await transformation determines whether cancellation is propagated as+ // an exception.+ auto await_transform(this_coro::throw_if_cancelled_0_t) noexcept+ requires (!is_noexcept)+ {+ struct result+ {+ detail::coro_cancellation_source* src_;++ bool await_ready() const noexcept+ {+ return true;+ }++ void await_suspend(coroutine_handle<void>) noexcept+ {+ }++ auto await_resume()+ {+ return src_->throw_if_cancelled();+ }+ };++ return result{cancel};+ }++ // This await transformation sets whether cancellation is propagated as an+ // exception.+ auto await_transform(+ this_coro::throw_if_cancelled_1_t throw_if_cancelled) noexcept+ requires (!is_noexcept)+ {+ struct result+ {+ detail::coro_cancellation_source* src_;+ bool value_;++ bool await_ready() const noexcept+ {+ return true;+ }++ void await_suspend(coroutine_handle<void>) noexcept+ {+ }++ auto await_resume()+ {+ src_->throw_if_cancelled(value_);+ }+ };++ return result{cancel, throw_if_cancelled.value};+ }++ template <typename Yield_, typename Return_,+ typename Executor_, typename Allocator_>+ auto await_transform(coro<Yield_, Return_, Executor_, Allocator_>& kr)+ -> decltype(auto)+ {+ return kr;+ }++ template <typename Yield_, typename Return_,+ typename Executor_, typename Allocator_>+ auto await_transform(coro<Yield_, Return_, Executor_, Allocator_>&& kr)+ {+ return std::move(kr);+ }++ template <typename T_, typename Coroutine >+ auto await_transform(coro_with_arg<T_, Coroutine>&& kr) -> decltype(auto)+ {+ return std::move(kr);+ }++ template <typename T_>+ requires requires(T_ t) {{ t.async_wait(deferred) }; }+ auto await_transform(T_& t) -> decltype(auto)+ {+ return await_transform(t.async_wait(deferred));+ }++ template <typename Op>+ auto await_transform(Op&& op,+ typename constraint<is_async_operation<Op>::value>::type = 0)+ {+ if ((cancel->state.cancelled() != cancellation_type::none)+ && cancel->throw_if_cancelled_)+ {+ asio::detail::throw_error(+ asio::error::operation_aborted, "coro-cancelled");+ }+ using signature = typename completion_signature_of<Op>::type;+ using result_type = detail::coro_completion_handler_type_t<signature>;+ using handler_type =+ typename detail::coro_completion_handler_type<signature>::template+ completion_handler<coro_promise>;++ struct aw_t+ {+ Op op;+ std::optional<result_type> result;++ constexpr static bool await_ready()+ {+ return false;+ }++ void await_suspend(coroutine_handle<coro_promise> h)+ {+ std::move(op)(handler_type{h, result});+ }++ auto await_resume()+ {+ if constexpr (is_noexcept)+ {+ if constexpr (std::tuple_size_v<result_type> == 0u)+ return;+ else if constexpr (std::tuple_size_v<result_type> == 1u)+ return std::get<0>(std::move(result).value());+ else+ return std::move(result).value();+ }+ else+ return detail::coro_interpret_result(std::move(result).value());+ }+ };++ return aw_t{std::move(op), {}};+ }+};++} // namespace detail++template <typename Yield, typename Return,+ typename Executor, typename Allocator>+struct coro<Yield, Return, Executor, Allocator>::awaitable_t+{+ coro& coro_;++ constexpr static bool await_ready() { return false; }++ template <typename Y, typename R, typename E, typename A>+ auto await_suspend(+ detail::coroutine_handle<detail::coro_promise<Y, R, E, A>> h)+ -> detail::coroutine_handle<>+ {+ auto& hp = h.promise();++ if constexpr (!detail::coro_promise<Y, R, E, A>::is_noexcept)+ {+ if ((hp.cancel->state.cancelled() != cancellation_type::none)+ && hp.cancel->throw_if_cancelled_)+ {+ asio::detail::throw_error(+ asio::error::operation_aborted, "coro-cancelled");+ }+ }++ if (hp.get_executor() == coro_.get_executor())+ {+ coro_.coro_->awaited_from = h;+ coro_.coro_->cancel = hp.cancel;+ coro_.coro_->reset_error();++ return coro_.coro_->get_handle();+ }+ else+ {+ coro_.coro_->awaited_from = detail::dispatch_coroutine(+ asio::prefer(hp.get_executor(),+ execution::outstanding_work.tracked),+ [h]() mutable+ {+ h.resume();+ }).handle;++ coro_.coro_->reset_error();++ struct cancel_handler+ {+ std::shared_ptr<std::pair<cancellation_signal,+ detail::coro_cancellation_source>> st = std::make_shared<+ std::pair<cancellation_signal, detail::coro_cancellation_source>>();++ cancel_handler(E e, coro& coro) : e(e), coro_(coro.coro_)+ {+ st->second.state = cancellation_state(+ st->second.slot = st->first.slot());+ }++ E e;+ typename coro::promise_type* coro_;++ void operator()(cancellation_type ct)+ {+ asio::dispatch(e,+ [ct, st = st]() mutable+ {+ auto & [sig, state] = *st;+ sig.emit(ct);+ });+ }+ };++ if (hp.cancel->state.slot().is_connected())+ {+ hp.cancel->state.slot().template emplace<cancel_handler>(+ coro_.get_executor(), coro_);+ }++ auto hh = detail::coroutine_handle<+ detail::coro_promise<Yield, Return, Executor, Allocator>>::from_promise(+ *coro_.coro_);++ return detail::dispatch_coroutine(+ coro_.coro_->get_executor(),+ [hh]() mutable { hh.resume(); }).handle;+ }+ }++ auto await_resume() -> result_type+ {+ coro_.coro_->cancel = nullptr;+ coro_.coro_->rethrow_if();+ if constexpr (!std::is_void_v<result_type>)+ return std::move(coro_.coro_->result_);+ }+};++template <typename Yield, typename Return,+ typename Executor, typename Allocator>+struct coro<Yield, Return, Executor, Allocator>::initiate_async_resume+{+ typedef Executor executor_type;+ typedef Allocator allocator_type;+ typedef asio::cancellation_slot cancellation_slot_type;++ explicit initiate_async_resume(coro* self)+ : coro_(self->coro_)+ {+ }++ executor_type get_executor() const noexcept+ {+ return coro_->get_executor();+ }++ allocator_type get_allocator() const noexcept+ {+ return coro_->get_allocator();+ }++ template <typename E, typename WaitHandler>+ auto handle(E exec, WaitHandler&& handler,+ std::true_type /* error is noexcept */,+ std::true_type /* result is void */) //noexcept+ {+ return [this, coro = coro_,+ h = std::forward<WaitHandler>(handler),+ exec = std::move(exec)]() mutable+ {+ assert(coro);++ auto ch = detail::coroutine_handle<promise_type>::from_promise(*coro);+ assert(ch && !ch.done());++ coro->awaited_from = post_coroutine(std::move(exec), std::move(h));+ coro->reset_error();+ ch.resume();+ };+ }++ template <typename E, typename WaitHandler>+ requires (!std::is_void_v<result_type>)+ auto handle(E exec, WaitHandler&& handler,+ std::true_type /* error is noexcept */,+ std::false_type /* result is void */) //noexcept+ {+ return [coro = coro_,+ h = std::forward<WaitHandler>(handler),+ exec = std::move(exec)]() mutable+ {+ assert(coro);++ auto ch = detail::coroutine_handle<promise_type>::from_promise(*coro);+ assert(ch && !ch.done());++ coro->awaited_from = detail::post_coroutine(+ exec, std::move(h), coro->result_).handle;+ coro->reset_error();+ ch.resume();+ };+ }++ template <typename E, typename WaitHandler>+ auto handle(E exec, WaitHandler&& handler,+ std::false_type /* error is noexcept */,+ std::true_type /* result is void */)+ {+ return [coro = coro_,+ h = std::forward<WaitHandler>(handler),+ exec = std::move(exec)]() mutable+ {+ if (!coro)+ return asio::post(exec,+ asio::append(std::move(h),+ detail::coro_error<error_type>::invalid()));++ auto ch = detail::coroutine_handle<promise_type>::from_promise(*coro);+ if (!ch)+ return asio::post(exec,+ asio::append(std::move(h),+ detail::coro_error<error_type>::invalid()));+ else if (ch.done())+ return asio::post(exec,+ asio::append(std::move(h),+ detail::coro_error<error_type>::done()));+ else+ {+ coro->awaited_from = detail::post_coroutine(+ exec, std::move(h), coro->error_).handle;+ coro->reset_error();+ ch.resume();+ }+ };+ }++ template <typename E, typename WaitHandler>+ auto handle(E exec, WaitHandler&& handler,+ std::false_type /* error is noexcept */,+ std::false_type /* result is void */)+ {+ return [coro = coro_,+ h = std::forward<WaitHandler>(handler),+ exec = std::move(exec)]() mutable+ {+ if (!coro)+ return asio::post(exec,+ asio::append(std::move(h),+ detail::coro_error<error_type>::invalid(), result_type{}));++ auto ch =+ detail::coroutine_handle<promise_type>::from_promise(*coro);+ if (!ch)+ return asio::post(exec,+ asio::append(std::move(h),+ detail::coro_error<error_type>::invalid(), result_type{}));+ else if (ch.done())+ return asio::post(exec,+ asio::append(std::move(h),+ detail::coro_error<error_type>::done(), result_type{}));+ else+ {+ coro->awaited_from = detail::post_coroutine(+ exec, std::move(h), coro->error_, coro->result_).handle;+ coro->reset_error();+ ch.resume();+ }+ };+ }++ template <typename WaitHandler>+ void operator()(WaitHandler&& handler)+ {+ const auto exec = asio::prefer(+ get_associated_executor(handler, get_executor()),+ execution::outstanding_work.tracked);++ coro_->cancel = &coro_->cancel_source.emplace();+ coro_->cancel->state = cancellation_state(+ coro_->cancel->slot = get_associated_cancellation_slot(handler));+ asio::dispatch(get_executor(),+ handle(exec, std::forward<WaitHandler>(handler),+ std::integral_constant<bool, is_noexcept>{},+ std::is_void<result_type>{}));+ }++ template <typename WaitHandler, typename Input>+ void operator()(WaitHandler&& handler, Input&& input)+ {+ const auto exec = asio::prefer(+ get_associated_executor(handler, get_executor()),+ execution::outstanding_work.tracked);++ coro_->cancel = &coro_->cancel_source.emplace();+ coro_->cancel->state = cancellation_state(+ coro_->cancel->slot = get_associated_cancellation_slot(handler));+ asio::dispatch(get_executor(),+ [h = handle(exec, std::forward<WaitHandler>(handler),+ std::integral_constant<bool, is_noexcept>{},+ std::is_void<result_type>{}),+ in = std::forward<Input>(input), coro = coro_]() mutable+ {+ coro->input_ = std::move(in);+ std::move(h)();+ });+ }++private:+ typename coro::promise_type* coro_;+};++} // namespace experimental+} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // ASIO_EXPERIMENTAL_IMPL_CORO_HPP
+ link/modules/asio-standalone/asio/include/asio/experimental/impl/parallel_group.hpp view
@@ -0,0 +1,792 @@+//+// experimental/impl/parallel_group.hpp+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com)+//+// Distributed under the Boost Software License, Version 1.0. (See accompanying+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)+//++#ifndef ASIO_IMPL_EXPERIMENTAL_PARALLEL_GROUP_HPP+#define ASIO_IMPL_EXPERIMENTAL_PARALLEL_GROUP_HPP++#if defined(_MSC_VER) && (_MSC_VER >= 1200)+# pragma once+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)++#include "asio/detail/config.hpp"+#include <atomic>+#include <deque>+#include <memory>+#include <new>+#include <tuple>+#include "asio/associated_cancellation_slot.hpp"+#include "asio/detail/recycling_allocator.hpp"+#include "asio/detail/type_traits.hpp"+#include "asio/dispatch.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {+namespace experimental {+namespace detail {++// Stores the result from an individual asynchronous operation.+template <typename T, typename = void>+struct parallel_group_op_result+{+public:+ parallel_group_op_result()+ : has_value_(false)+ {+ }++ parallel_group_op_result(parallel_group_op_result&& other)+ : has_value_(other.has_value_)+ {+ if (has_value_)+ new (&u_.value_) T(std::move(other.get()));+ }++ ~parallel_group_op_result()+ {+ if (has_value_)+ u_.value_.~T();+ }++ T& get() noexcept+ {+ return u_.value_;+ }++ template <typename... Args>+ void emplace(Args&&... args)+ {+ new (&u_.value_) T(std::forward<Args>(args)...);+ has_value_ = true;+ }++private:+ union u+ {+ u() {}+ ~u() {}+ char c_;+ T value_;+ } u_;+ bool has_value_;+};++// Proxy completion handler for the group of parallel operatations. Unpacks and+// concatenates the individual operations' results, and invokes the user's+// completion handler.+template <typename Handler, typename... Ops>+struct parallel_group_completion_handler+{+ typedef typename decay<+ typename prefer_result<+ typename associated_executor<Handler>::type,+ execution::outstanding_work_t::tracked_t+ >::type+ >::type executor_type;++ parallel_group_completion_handler(Handler&& h)+ : handler_(std::move(h)),+ executor_(+ asio::prefer(+ asio::get_associated_executor(handler_),+ execution::outstanding_work.tracked))+ {+ }++ executor_type get_executor() const noexcept+ {+ return executor_;+ }++ void operator()()+ {+ this->invoke(asio::detail::make_index_sequence<sizeof...(Ops)>());+ }++ template <std::size_t... I>+ void invoke(asio::detail::index_sequence<I...>)+ {+ this->invoke(std::tuple_cat(std::move(std::get<I>(args_).get())...));+ }++ template <typename... Args>+ void invoke(std::tuple<Args...>&& args)+ {+ this->invoke(std::move(args),+ asio::detail::index_sequence_for<Args...>());+ }++ template <typename... Args, std::size_t... I>+ void invoke(std::tuple<Args...>&& args,+ asio::detail::index_sequence<I...>)+ {+ std::move(handler_)(completion_order_, std::move(std::get<I>(args))...);+ }++ Handler handler_;+ executor_type executor_;+ std::array<std::size_t, sizeof...(Ops)> completion_order_{};+ std::tuple<+ parallel_group_op_result<+ typename parallel_op_signature_as_tuple<+ typename completion_signature_of<Ops>::type+ >::type+ >...+ > args_{};+};++// Shared state for the parallel group.+template <typename Condition, typename Handler, typename... Ops>+struct parallel_group_state+{+ parallel_group_state(Condition&& c, Handler&& h)+ : cancellation_condition_(std::move(c)),+ handler_(std::move(h))+ {+ }++ // The number of operations that have completed so far. Used to determine the+ // order of completion.+ std::atomic<unsigned int> completed_{0};++ // The non-none cancellation type that resulted from a cancellation condition.+ // Stored here for use by the group's initiating function.+ std::atomic<cancellation_type_t> cancel_type_{cancellation_type::none};++ // The number of cancellations that have been requested, either on completion+ // of the operations within the group, or via the cancellation slot for the+ // group operation. Initially set to the number of operations to prevent+ // cancellation signals from being emitted until after all of the group's+ // operations' initiating functions have completed.+ std::atomic<unsigned int> cancellations_requested_{sizeof...(Ops)};++ // The number of operations that are yet to complete. Used to determine when+ // it is safe to invoke the user's completion handler.+ std::atomic<unsigned int> outstanding_{sizeof...(Ops)};++ // The cancellation signals for each operation in the group.+ asio::cancellation_signal cancellation_signals_[sizeof...(Ops)];++ // The cancellation condition is used to determine whether the results from an+ // individual operation warrant a cancellation request for the whole group.+ Condition cancellation_condition_;++ // The proxy handler to be invoked once all operations in the group complete.+ parallel_group_completion_handler<Handler, Ops...> handler_;+};++// Handler for an individual operation within the parallel group.+template <std::size_t I, typename Condition, typename Handler, typename... Ops>+struct parallel_group_op_handler+{+ typedef asio::cancellation_slot cancellation_slot_type;++ parallel_group_op_handler(+ std::shared_ptr<parallel_group_state<Condition, Handler, Ops...> > state)+ : state_(std::move(state))+ {+ }++ cancellation_slot_type get_cancellation_slot() const noexcept+ {+ return state_->cancellation_signals_[I].slot();+ }++ template <typename... Args>+ void operator()(Args... args)+ {+ // Capture this operation into the completion order.+ state_->handler_.completion_order_[state_->completed_++] = I;++ // Determine whether the results of this operation require cancellation of+ // the whole group.+ cancellation_type_t cancel_type = state_->cancellation_condition_(args...);++ // Capture the result of the operation into the proxy completion handler.+ std::get<I>(state_->handler_.args_).emplace(std::move(args)...);++ if (cancel_type != cancellation_type::none)+ {+ // Save the type for potential use by the group's initiating function.+ state_->cancel_type_ = cancel_type;++ // If we are the first operation to request cancellation, emit a signal+ // for each operation in the group.+ if (state_->cancellations_requested_++ == 0)+ for (std::size_t i = 0; i < sizeof...(Ops); ++i)+ if (i != I)+ state_->cancellation_signals_[i].emit(cancel_type);+ }++ // If this is the last outstanding operation, invoke the user's handler.+ if (--state_->outstanding_ == 0)+ asio::dispatch(std::move(state_->handler_));+ }++ std::shared_ptr<parallel_group_state<Condition, Handler, Ops...> > state_;+};++// Handler for an individual operation within the parallel group that has an+// explicitly specified executor.+template <typename Executor, std::size_t I,+ typename Condition, typename Handler, typename... Ops>+struct parallel_group_op_handler_with_executor :+ parallel_group_op_handler<I, Condition, Handler, Ops...>+{+ typedef parallel_group_op_handler<I, Condition, Handler, Ops...> base_type;+ typedef asio::cancellation_slot cancellation_slot_type;+ typedef Executor executor_type;++ parallel_group_op_handler_with_executor(+ std::shared_ptr<parallel_group_state<Condition, Handler, Ops...> > state,+ executor_type ex)+ : parallel_group_op_handler<I, Condition, Handler, Ops...>(std::move(state))+ {+ cancel_proxy_ =+ &this->state_->cancellation_signals_[I].slot().template+ emplace<cancel_proxy>(this->state_, std::move(ex));+ }++ cancellation_slot_type get_cancellation_slot() const noexcept+ {+ return cancel_proxy_->signal_.slot();+ }++ executor_type get_executor() const noexcept+ {+ return cancel_proxy_->executor_;+ }++ // Proxy handler that forwards the emitted signal to the correct executor.+ struct cancel_proxy+ {+ cancel_proxy(+ std::shared_ptr<parallel_group_state<+ Condition, Handler, Ops...> > state,+ executor_type ex)+ : state_(std::move(state)),+ executor_(std::move(ex))+ {+ }++ void operator()(cancellation_type_t type)+ {+ if (auto state = state_.lock())+ {+ asio::cancellation_signal* sig = &signal_;+ asio::dispatch(executor_,+ [state, sig, type]{ sig->emit(type); });+ }+ }++ std::weak_ptr<parallel_group_state<Condition, Handler, Ops...> > state_;+ asio::cancellation_signal signal_;+ executor_type executor_;+ };++ cancel_proxy* cancel_proxy_;+};++// Helper to launch an operation using the correct executor, if any.+template <std::size_t I, typename Op, typename = void>+struct parallel_group_op_launcher+{+ template <typename Condition, typename Handler, typename... Ops>+ static void launch(Op& op,+ const std::shared_ptr<parallel_group_state<+ Condition, Handler, Ops...> >& state)+ {+ typedef typename associated_executor<Op>::type ex_type;+ ex_type ex = asio::get_associated_executor(op);+ std::move(op)(+ parallel_group_op_handler_with_executor<ex_type, I,+ Condition, Handler, Ops...>(state, std::move(ex)));+ }+};++// Specialised launcher for operations that specify no executor.+template <std::size_t I, typename Op>+struct parallel_group_op_launcher<I, Op,+ typename enable_if<+ is_same<+ typename associated_executor<+ Op>::asio_associated_executor_is_unspecialised,+ void+ >::value+ >::type>+{+ template <typename Condition, typename Handler, typename... Ops>+ static void launch(Op& op,+ const std::shared_ptr<parallel_group_state<+ Condition, Handler, Ops...> >& state)+ {+ std::move(op)(+ parallel_group_op_handler<I, Condition, Handler, Ops...>(state));+ }+};++template <typename Condition, typename Handler, typename... Ops>+struct parallel_group_cancellation_handler+{+ parallel_group_cancellation_handler(+ std::shared_ptr<parallel_group_state<Condition, Handler, Ops...> > state)+ : state_(std::move(state))+ {+ }++ void operator()(cancellation_type_t cancel_type)+ {+ // If we are the first place to request cancellation, i.e. no operation has+ // yet completed and requested cancellation, emit a signal for each+ // operation in the group.+ if (cancel_type != cancellation_type::none)+ if (auto state = state_.lock())+ if (state->cancellations_requested_++ == 0)+ for (std::size_t i = 0; i < sizeof...(Ops); ++i)+ state->cancellation_signals_[i].emit(cancel_type);+ }++ std::weak_ptr<parallel_group_state<Condition, Handler, Ops...> > state_;+};++template <typename Condition, typename Handler,+ typename... Ops, std::size_t... I>+void parallel_group_launch(Condition cancellation_condition, Handler handler,+ std::tuple<Ops...>& ops, asio::detail::index_sequence<I...>)+{+ // Get the user's completion handler's cancellation slot, so that we can allow+ // cancellation of the entire group.+ typename associated_cancellation_slot<Handler>::type slot+ = asio::get_associated_cancellation_slot(handler);++ // Create the shared state for the operation.+ typedef parallel_group_state<Condition, Handler, Ops...> state_type;+ std::shared_ptr<state_type> state = std::allocate_shared<state_type>(+ asio::detail::recycling_allocator<state_type,+ asio::detail::thread_info_base::parallel_group_tag>(),+ std::move(cancellation_condition), std::move(handler));++ // Initiate each individual operation in the group.+ int fold[] = { 0,+ ( parallel_group_op_launcher<I, Ops>::launch(std::get<I>(ops), state),+ 0 )...+ };+ (void)fold;++ // Check if any of the operations has already requested cancellation, and if+ // so, emit a signal for each operation in the group.+ if ((state->cancellations_requested_ -= sizeof...(Ops)) > 0)+ for (auto& signal : state->cancellation_signals_)+ signal.emit(state->cancel_type_);++ // Register a handler with the user's completion handler's cancellation slot.+ if (slot.is_connected())+ slot.template emplace<+ parallel_group_cancellation_handler<+ Condition, Handler, Ops...> >(state);+}++// Proxy completion handler for the ranged group of parallel operatations.+// Unpacks and recombines the individual operations' results, and invokes the+// user's completion handler.+template <typename Handler, typename Op, typename Allocator>+struct ranged_parallel_group_completion_handler+{+ typedef typename decay<+ typename prefer_result<+ typename associated_executor<Handler>::type,+ execution::outstanding_work_t::tracked_t+ >::type+ >::type executor_type;++ typedef typename parallel_op_signature_as_tuple<+ typename completion_signature_of<Op>::type+ >::type op_tuple_type;++ typedef parallel_group_op_result<op_tuple_type> op_result_type;++ ranged_parallel_group_completion_handler(Handler&& h,+ std::size_t size, const Allocator& allocator)+ : handler_(std::move(h)),+ executor_(+ asio::prefer(+ asio::get_associated_executor(handler_),+ execution::outstanding_work.tracked)),+ allocator_(allocator),+ completion_order_(size, 0,+ ASIO_REBIND_ALLOC(Allocator, std::size_t)(allocator)),+ args_(ASIO_REBIND_ALLOC(Allocator, op_result_type)(allocator))+ {+ for (std::size_t i = 0; i < size; ++i)+ args_.emplace_back();+ }++ executor_type get_executor() const noexcept+ {+ return executor_;+ }++ void operator()()+ {+ this->invoke(+ asio::detail::make_index_sequence<+ std::tuple_size<op_tuple_type>::value>());+ }++ template <std::size_t... I>+ void invoke(asio::detail::index_sequence<I...>)+ {+ typedef typename parallel_op_signature_as_tuple<+ typename ranged_parallel_group_signature<+ typename completion_signature_of<Op>::type,+ Allocator+ >::raw_type+ >::type vectors_type;++ // Construct all result vectors using the supplied allocator.+ vectors_type vectors{+ typename std::tuple_element<I, vectors_type>::type(+ ASIO_REBIND_ALLOC(Allocator, int)(allocator_))...};++ // Reserve sufficient space in each of the result vectors.+ int reserve_fold[] = { 0,+ ( std::get<I>(vectors).reserve(completion_order_.size()),+ 0 )...+ };+ (void)reserve_fold;++ // Copy the results from all operations into the result vectors.+ for (std::size_t idx = 0; idx < completion_order_.size(); ++idx)+ {+ int pushback_fold[] = { 0,+ ( std::get<I>(vectors).push_back(+ std::move(std::get<I>(args_[idx].get()))),+ 0 )...+ };+ (void)pushback_fold;+ }++ std::move(handler_)(completion_order_, std::move(std::get<I>(vectors))...);+ }++ Handler handler_;+ executor_type executor_;+ Allocator allocator_;+ std::vector<std::size_t,+ ASIO_REBIND_ALLOC(Allocator, std::size_t)> completion_order_;+ std::deque<op_result_type,+ ASIO_REBIND_ALLOC(Allocator, op_result_type)> args_;+};++// Shared state for the parallel group.+template <typename Condition, typename Handler, typename Op, typename Allocator>+struct ranged_parallel_group_state+{+ ranged_parallel_group_state(Condition&& c, Handler&& h,+ std::size_t size, const Allocator& allocator)+ : cancellations_requested_(size),+ outstanding_(size),+ cancellation_signals_(+ ASIO_REBIND_ALLOC(Allocator,+ asio::cancellation_signal)(allocator)),+ cancellation_condition_(std::move(c)),+ handler_(std::move(h), size, allocator)+ {+ for (std::size_t i = 0; i < size; ++i)+ cancellation_signals_.emplace_back();+ }++ // The number of operations that have completed so far. Used to determine the+ // order of completion.+ std::atomic<unsigned int> completed_{0};++ // The non-none cancellation type that resulted from a cancellation condition.+ // Stored here for use by the group's initiating function.+ std::atomic<cancellation_type_t> cancel_type_{cancellation_type::none};++ // The number of cancellations that have been requested, either on completion+ // of the operations within the group, or via the cancellation slot for the+ // group operation. Initially set to the number of operations to prevent+ // cancellation signals from being emitted until after all of the group's+ // operations' initiating functions have completed.+ std::atomic<unsigned int> cancellations_requested_;++ // The number of operations that are yet to complete. Used to determine when+ // it is safe to invoke the user's completion handler.+ std::atomic<unsigned int> outstanding_;++ // The cancellation signals for each operation in the group.+ std::deque<asio::cancellation_signal,+ ASIO_REBIND_ALLOC(Allocator, asio::cancellation_signal)>+ cancellation_signals_;++ // The cancellation condition is used to determine whether the results from an+ // individual operation warrant a cancellation request for the whole group.+ Condition cancellation_condition_;++ // The proxy handler to be invoked once all operations in the group complete.+ ranged_parallel_group_completion_handler<Handler, Op, Allocator> handler_;+};++// Handler for an individual operation within the parallel group.+template <typename Condition, typename Handler, typename Op, typename Allocator>+struct ranged_parallel_group_op_handler+{+ typedef asio::cancellation_slot cancellation_slot_type;++ ranged_parallel_group_op_handler(+ std::shared_ptr<ranged_parallel_group_state<+ Condition, Handler, Op, Allocator> > state,+ std::size_t idx)+ : state_(std::move(state)),+ idx_(idx)+ {+ }++ cancellation_slot_type get_cancellation_slot() const noexcept+ {+ return state_->cancellation_signals_[idx_].slot();+ }++ template <typename... Args>+ void operator()(Args... args)+ {+ // Capture this operation into the completion order.+ state_->handler_.completion_order_[state_->completed_++] = idx_;++ // Determine whether the results of this operation require cancellation of+ // the whole group.+ cancellation_type_t cancel_type = state_->cancellation_condition_(args...);++ // Capture the result of the operation into the proxy completion handler.+ state_->handler_.args_[idx_].emplace(std::move(args)...);++ if (cancel_type != cancellation_type::none)+ {+ // Save the type for potential use by the group's initiating function.+ state_->cancel_type_ = cancel_type;++ // If we are the first operation to request cancellation, emit a signal+ // for each operation in the group.+ if (state_->cancellations_requested_++ == 0)+ for (std::size_t i = 0; i < state_->cancellation_signals_.size(); ++i)+ if (i != idx_)+ state_->cancellation_signals_[i].emit(cancel_type);+ }++ // If this is the last outstanding operation, invoke the user's handler.+ if (--state_->outstanding_ == 0)+ asio::dispatch(std::move(state_->handler_));+ }++ std::shared_ptr<ranged_parallel_group_state<+ Condition, Handler, Op, Allocator> > state_;+ std::size_t idx_;+};++// Handler for an individual operation within the parallel group that has an+// explicitly specified executor.+template <typename Executor, typename Condition,+ typename Handler, typename Op, typename Allocator>+struct ranged_parallel_group_op_handler_with_executor :+ ranged_parallel_group_op_handler<Condition, Handler, Op, Allocator>+{+ typedef ranged_parallel_group_op_handler<+ Condition, Handler, Op, Allocator> base_type;+ typedef asio::cancellation_slot cancellation_slot_type;+ typedef Executor executor_type;++ ranged_parallel_group_op_handler_with_executor(+ std::shared_ptr<ranged_parallel_group_state<+ Condition, Handler, Op, Allocator> > state,+ executor_type ex, std::size_t idx)+ : ranged_parallel_group_op_handler<Condition, Handler, Op, Allocator>(+ std::move(state), idx)+ {+ cancel_proxy_ =+ &this->state_->cancellation_signals_[idx].slot().template+ emplace<cancel_proxy>(this->state_, std::move(ex));+ }++ cancellation_slot_type get_cancellation_slot() const noexcept+ {+ return cancel_proxy_->signal_.slot();+ }++ executor_type get_executor() const noexcept+ {+ return cancel_proxy_->executor_;+ }++ // Proxy handler that forwards the emitted signal to the correct executor.+ struct cancel_proxy+ {+ cancel_proxy(+ std::shared_ptr<ranged_parallel_group_state<+ Condition, Handler, Op, Allocator> > state,+ executor_type ex)+ : state_(std::move(state)),+ executor_(std::move(ex))+ {+ }++ void operator()(cancellation_type_t type)+ {+ if (auto state = state_.lock())+ {+ asio::cancellation_signal* sig = &signal_;+ asio::dispatch(executor_,+ [state, sig, type]{ sig->emit(type); });+ }+ }++ std::weak_ptr<ranged_parallel_group_state<+ Condition, Handler, Op, Allocator> > state_;+ asio::cancellation_signal signal_;+ executor_type executor_;+ };++ cancel_proxy* cancel_proxy_;+};++template <typename Condition, typename Handler, typename Op, typename Allocator>+struct ranged_parallel_group_cancellation_handler+{+ ranged_parallel_group_cancellation_handler(+ std::shared_ptr<ranged_parallel_group_state<+ Condition, Handler, Op, Allocator> > state)+ : state_(std::move(state))+ {+ }++ void operator()(cancellation_type_t cancel_type)+ {+ // If we are the first place to request cancellation, i.e. no operation has+ // yet completed and requested cancellation, emit a signal for each+ // operation in the group.+ if (cancel_type != cancellation_type::none)+ if (auto state = state_.lock())+ if (state->cancellations_requested_++ == 0)+ for (std::size_t i = 0; i < state->cancellation_signals_.size(); ++i)+ state->cancellation_signals_[i].emit(cancel_type);+ }++ std::weak_ptr<ranged_parallel_group_state<+ Condition, Handler, Op, Allocator> > state_;+};++template <typename Condition, typename Handler,+ typename Range, typename Allocator>+void ranged_parallel_group_launch(Condition cancellation_condition,+ Handler handler, Range&& range, const Allocator& allocator)+{+ // Get the user's completion handler's cancellation slot, so that we can allow+ // cancellation of the entire group.+ typename associated_cancellation_slot<Handler>::type slot+ = asio::get_associated_cancellation_slot(handler);++ // The type of the asynchronous operation.+ typedef typename std::decay<decltype(+ *std::declval<typename Range::iterator>())>::type op_type;++ // Create the shared state for the operation.+ typedef ranged_parallel_group_state<Condition,+ Handler, op_type, Allocator> state_type;+ std::shared_ptr<state_type> state = std::allocate_shared<state_type>(+ asio::detail::recycling_allocator<state_type,+ asio::detail::thread_info_base::parallel_group_tag>(),+ std::move(cancellation_condition),+ std::move(handler), range.size(), allocator);++ std::size_t idx = 0;+ for (auto&& op : std::forward<Range>(range))+ {+ typedef typename associated_executor<op_type>::type ex_type;+ ex_type ex = asio::get_associated_executor(op);+ std::move(op)(+ ranged_parallel_group_op_handler_with_executor<+ ex_type, Condition, Handler, op_type, Allocator>(+ state, std::move(ex), idx++));+ }++ // Check if any of the operations has already requested cancellation, and if+ // so, emit a signal for each operation in the group.+ if ((state->cancellations_requested_ -= range.size()) > 0)+ for (auto& signal : state->cancellation_signals_)+ signal.emit(state->cancel_type_);++ // Register a handler with the user's completion handler's cancellation slot.+ if (slot.is_connected())+ slot.template emplace<+ ranged_parallel_group_cancellation_handler<+ Condition, Handler, op_type, Allocator> >(state);+}++} // namespace detail+} // namespace experimental++template <template <typename, typename> class Associator,+ typename Handler, typename... Ops, typename DefaultCandidate>+struct associator<Associator,+ experimental::detail::parallel_group_completion_handler<Handler, Ops...>,+ DefaultCandidate>+ : Associator<Handler, DefaultCandidate>+{+ static typename Associator<Handler, DefaultCandidate>::type+ get(const experimental::detail::parallel_group_completion_handler<+ Handler, Ops...>& h) ASIO_NOEXCEPT+ {+ return Associator<Handler, DefaultCandidate>::get(h.handler_);+ }++ static ASIO_AUTO_RETURN_TYPE_PREFIX2(+ typename Associator<Handler, DefaultCandidate>::type)+ get(const experimental::detail::parallel_group_completion_handler<+ Handler, Ops...>& h,+ const DefaultCandidate& c) ASIO_NOEXCEPT+ ASIO_AUTO_RETURN_TYPE_SUFFIX((+ Associator<Handler, DefaultCandidate>::get(h.handler_, c)))+ {+ return Associator<Handler, DefaultCandidate>::get(h.handler_, c);+ }+};++template <template <typename, typename> class Associator, typename Handler,+ typename Op, typename Allocator, typename DefaultCandidate>+struct associator<Associator,+ experimental::detail::ranged_parallel_group_completion_handler<+ Handler, Op, Allocator>,+ DefaultCandidate>+ : Associator<Handler, DefaultCandidate>+{+ static typename Associator<Handler, DefaultCandidate>::type+ get(const experimental::detail::ranged_parallel_group_completion_handler<+ Handler, Op, Allocator>& h) ASIO_NOEXCEPT+ {+ return Associator<Handler, DefaultCandidate>::get(h.handler_);+ }++ static ASIO_AUTO_RETURN_TYPE_PREFIX2(+ typename Associator<Handler, DefaultCandidate>::type)+ get(const experimental::detail::ranged_parallel_group_completion_handler<+ Handler, Op, Allocator>& h,+ const DefaultCandidate& c) ASIO_NOEXCEPT+ ASIO_AUTO_RETURN_TYPE_SUFFIX((+ Associator<Handler, DefaultCandidate>::get(h.handler_, c)))+ {+ return Associator<Handler, DefaultCandidate>::get(h.handler_, c);+ }+};++} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // ASIO_IMPL_EXPERIMENTAL_PARALLEL_GROUP_HPP
+ link/modules/asio-standalone/asio/include/asio/experimental/impl/promise.hpp view
@@ -0,0 +1,254 @@+//+// experimental/impl/promise.hpp+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2021-2023 Klemens D. Morgenstern+// (klemens dot morgenstern at gmx dot net)+//+// Distributed under the Boost Software License, Version 1.0. (See accompanying+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)+//+#ifndef ASIO_EXPERIMENTAL_IMPL_PROMISE_HPP+#define ASIO_EXPERIMENTAL_IMPL_PROMISE_HPP++#if defined(_MSC_VER) && (_MSC_VER >= 1200)+# pragma once+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)++#include "asio/detail/config.hpp"+#include "asio/cancellation_signal.hpp"+#include "asio/detail/utility.hpp"+#include <tuple>++#include "asio/detail/push_options.hpp"++namespace asio {+namespace experimental {++template<typename Signature = void(),+ typename Executor = asio::any_io_executor,+ typename Allocator = std::allocator<void>>+struct promise;++namespace detail {++template<typename Signature, typename Executor, typename Allocator>+struct promise_impl;++template<typename... Ts, typename Executor, typename Allocator>+struct promise_impl<void(Ts...), Executor, Allocator>+{+ using result_type = std::tuple<Ts...>;++ promise_impl(Allocator allocator, Executor executor)+ : allocator(std::move(allocator)), executor(std::move(executor))+ {+ }++ promise_impl(const promise_impl&) = delete;++ ~promise_impl()+ {+ if (completion)+ this->cancel_();++ if (done)+ reinterpret_cast<result_type*>(&result)->~result_type();+ }++ typename aligned_storage<sizeof(result_type),+ alignof(result_type)>::type result;+ std::atomic<bool> done{false};+ cancellation_signal cancel;+ Allocator allocator;+ Executor executor;++ template<typename Func, std::size_t... Idx>+ void apply_impl(Func f, asio::detail::index_sequence<Idx...>)+ {+ auto& result_type = *reinterpret_cast<promise_impl::result_type*>(&result);+ f(std::get<Idx>(std::move(result_type))...);+ }++ using allocator_type = Allocator;+ allocator_type get_allocator() {return allocator;}++ using executor_type = Executor;+ executor_type get_executor() {return executor;}++ template<typename Func>+ void apply(Func f)+ {+ apply_impl(std::forward<Func>(f),+ asio::detail::make_index_sequence<sizeof...(Ts)>{});+ }++ struct completion_base+ {+ virtual void invoke(Ts&&...ts) = 0;+ };++ template<typename Alloc, typename WaitHandler_>+ struct completion_impl final : completion_base+ {+ WaitHandler_ handler;+ Alloc allocator;+ void invoke(Ts&&... ts)+ {+ auto h = std::move(handler);++ using alloc_t = typename std::allocator_traits<+ typename asio::decay<Alloc>::type>::template+ rebind_alloc<completion_impl>;++ alloc_t alloc_{allocator};+ this->~completion_impl();+ std::allocator_traits<alloc_t>::deallocate(alloc_, this, 1u);+ std::move(h)(std::forward<Ts>(ts)...);+ }++ template<typename Alloc_, typename Handler_>+ completion_impl(Alloc_&& alloc, Handler_&& wh)+ : handler(std::forward<Handler_>(wh)),+ allocator(std::forward<Alloc_>(alloc))+ {+ }+ };++ completion_base* completion = nullptr;+ typename asio::aligned_storage<sizeof(void*) * 4,+ alignof(completion_base)>::type completion_opt;++ template<typename Alloc, typename Handler>+ void set_completion(Alloc&& alloc, Handler&& handler)+ {+ if (completion)+ cancel_();++ using impl_t = completion_impl<+ typename asio::decay<Alloc>::type, Handler>;+ using alloc_t = typename std::allocator_traits<+ typename asio::decay<Alloc>::type>::template rebind_alloc<impl_t>;++ alloc_t alloc_{alloc};+ auto p = std::allocator_traits<alloc_t>::allocate(alloc_, 1u);+ completion = new (p) impl_t(std::forward<Alloc>(alloc),+ std::forward<Handler>(handler));+ }++ template<typename... T_>+ void complete(T_&&... ts)+ {+ assert(completion);+ std::exchange(completion, nullptr)->invoke(std::forward<T_>(ts)...);+ }++ template<std::size_t... Idx>+ void complete_with_result_impl(asio::detail::index_sequence<Idx...>)+ {+ auto& result_type = *reinterpret_cast<promise_impl::result_type*>(&result);+ this->complete(std::get<Idx>(std::move(result_type))...);+ }++ void complete_with_result()+ {+ complete_with_result_impl(+ asio::detail::make_index_sequence<sizeof...(Ts)>{});+ }++ template<typename... T_>+ void cancel_impl_(std::exception_ptr*, T_*...)+ {+ complete(+ std::make_exception_ptr(+ asio::system_error(+ asio::error::operation_aborted)),+ T_{}...);+ }++ template<typename... T_>+ void cancel_impl_(asio::error_code*, T_*...)+ {+ complete(asio::error::operation_aborted, T_{}...);+ }++ template<typename... T_>+ void cancel_impl_(T_*...)+ {+ complete(T_{}...);+ }++ void cancel_()+ {+ cancel_impl_(static_cast<Ts*>(nullptr)...);+ }+};++template<typename Signature = void(),+ typename Executor = asio::any_io_executor,+ typename Allocator = any_io_executor>+struct promise_handler;++template<typename... Ts, typename Executor, typename Allocator>+struct promise_handler<void(Ts...), Executor, Allocator>+{+ using promise_type = promise<void(Ts...), Executor, Allocator>;++ promise_handler(+ Allocator allocator, Executor executor) // get_associated_allocator(exec)+ : impl_(+ std::allocate_shared<promise_impl<void(Ts...), Executor, Allocator>>(+ allocator, allocator, executor))+ {+ }++ std::shared_ptr<promise_impl<void(Ts...), Executor, Allocator>> impl_;++ using cancellation_slot_type = cancellation_slot;++ cancellation_slot_type get_cancellation_slot() const noexcept+ {+ return impl_->cancel.slot();+ }++ using allocator_type = Allocator;++ allocator_type get_allocator() const noexcept+ {+ return impl_->get_allocator();+ }++ using executor_type = Executor;++ Executor get_executor() const noexcept+ {+ return impl_->get_executor();+ }++ auto make_promise() -> promise<void(Ts...), executor_type, allocator_type>+ {+ return promise<void(Ts...), executor_type, allocator_type>{impl_};+ }++ void operator()(std::remove_reference_t<Ts>... ts)+ {+ assert(impl_);++ using result_type = typename promise_impl<+ void(Ts...), allocator_type, executor_type>::result_type ;++ new (&impl_->result) result_type(std::move(ts)...);+ impl_->done = true;++ if (impl_->completion)+ impl_->complete_with_result();+ }+};++} // namespace detail+} // namespace experimental+} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // ASIO_EXPERIMENTAL_IMPL_PROMISE_HPP
+ link/modules/asio-standalone/asio/include/asio/experimental/impl/use_coro.hpp view
@@ -0,0 +1,214 @@+//+// experimental/impl/use_coro.hpp+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2021-2023 Klemens D. Morgenstern+// (klemens dot morgenstern at gmx dot net)+//+// Distributed under the Boost Software License, Version 1.0. (See accompanying+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)+//++#ifndef ASIO_EXPERIMENTAL_IMPL_USE_CORO_HPP+#define ASIO_EXPERIMENTAL_IMPL_USE_CORO_HPP++#if defined(_MSC_VER) && (_MSC_VER >= 1200)+# pragma once+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)++#include "asio/deferred.hpp"+#include "asio/experimental/coro.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {++#if !defined(GENERATING_DOCUMENTATION)++template <typename Allocator, typename R>+struct async_result<experimental::use_coro_t<Allocator>, R()>+{+ template <typename Initiation, typename... InitArgs>+ static auto initiate_impl(Initiation initiation,+ std::allocator_arg_t, Allocator, InitArgs... args)+ -> experimental::coro<void() noexcept, void,+ asio::associated_executor_t<Initiation>, Allocator>+ {+ co_await deferred_async_operation<R(), Initiation, InitArgs...>(+ deferred_init_tag{}, std::move(initiation), std::move(args)...);+ }++ template <typename... InitArgs>+ static auto initiate_impl(asio::detail::initiation_archetype<R()>,+ std::allocator_arg_t, Allocator, InitArgs... args)+ -> experimental::coro<void(), void,+ asio::any_io_executor, Allocator>;++ template <typename Initiation, typename... InitArgs>+ static auto initiate(Initiation initiation,+ experimental::use_coro_t<Allocator> tk, InitArgs&&... args)+ {+ return initiate_impl(std::move(initiation), std::allocator_arg,+ tk.get_allocator(), std::forward<InitArgs>(args)...);+ }+};++template <typename Allocator, typename R>+struct async_result<+ experimental::use_coro_t<Allocator>, R(asio::error_code)>+{+ template <typename Initiation, typename... InitArgs>+ static auto initiate_impl(Initiation initiation,+ std::allocator_arg_t, Allocator, InitArgs... args)+ -> experimental::coro<void() noexcept, void,+ asio::associated_executor_t<Initiation>, Allocator>+ {+ co_await deferred_async_operation<+ R(asio::error_code), Initiation, InitArgs...>(+ deferred_init_tag{}, std::move(initiation), std::move(args)...);+ }++ template <typename... InitArgs>+ static auto initiate_impl(+ asio::detail::initiation_archetype<R(asio::error_code)>,+ std::allocator_arg_t, Allocator, InitArgs... args)+ -> experimental::coro<void(), void,+ asio::any_io_executor, Allocator>;++ template <typename Initiation, typename... InitArgs>+ static auto initiate(Initiation initiation,+ experimental::use_coro_t<Allocator> tk, InitArgs&&... args)+ {+ return initiate_impl(std::move(initiation), std::allocator_arg,+ tk.get_allocator(), std::forward<InitArgs>(args)...);+ }+};++template <typename Allocator, typename R>+struct async_result<+ experimental::use_coro_t<Allocator>, R(std::exception_ptr)>+{+ template <typename Initiation, typename... InitArgs>+ static auto initiate_impl(Initiation initiation,+ std::allocator_arg_t, Allocator, InitArgs... args)+ -> experimental::coro<void(), void,+ asio::associated_executor_t<Initiation>, Allocator>+ {+ co_await deferred_async_operation<+ R(std::exception_ptr), Initiation, InitArgs...>(+ deferred_init_tag{}, std::move(initiation), std::move(args)...);+ }++ template <typename... InitArgs>+ static auto initiate_impl(+ asio::detail::initiation_archetype<R(std::exception_ptr)>,+ std::allocator_arg_t, Allocator, InitArgs... args)+ -> experimental::coro<void(), void,+ asio::any_io_executor, Allocator>;++ template <typename Initiation, typename... InitArgs>+ static auto initiate(Initiation initiation,+ experimental::use_coro_t<Allocator> tk, InitArgs&&... args)+ {+ return initiate_impl(std::move(initiation), std::allocator_arg,+ tk.get_allocator(), std::forward<InitArgs>(args)...);+ }+};++template <typename Allocator, typename R, typename T>+struct async_result<experimental::use_coro_t<Allocator>, R(T)>+{++ template <typename Initiation, typename... InitArgs>+ static auto initiate_impl(Initiation initiation,+ std::allocator_arg_t, Allocator, InitArgs... args)+ -> experimental::coro<void() noexcept, T,+ asio::associated_executor_t<Initiation>, Allocator>+ {+ co_return co_await deferred_async_operation<R(T), Initiation, InitArgs...>(+ deferred_init_tag{}, std::move(initiation), std::move(args)...);+ }++ template <typename... InitArgs>+ static auto initiate_impl(asio::detail::initiation_archetype<R(T)>,+ std::allocator_arg_t, Allocator, InitArgs... args)+ -> experimental::coro<void() noexcept, T,+ asio::any_io_executor, Allocator>;++ template <typename Initiation, typename... InitArgs>+ static auto initiate(Initiation initiation,+ experimental::use_coro_t<Allocator> tk, InitArgs&&... args)+ {+ return initiate_impl(std::move(initiation), std::allocator_arg,+ tk.get_allocator(), std::forward<InitArgs>(args)...);+ }+};++template <typename Allocator, typename R, typename T>+struct async_result<+ experimental::use_coro_t<Allocator>, R(asio::error_code, T)>+{+ template <typename Initiation, typename... InitArgs>+ static auto initiate_impl(Initiation initiation,+ std::allocator_arg_t, Allocator, InitArgs... args)+ -> experimental::coro<void(), T,+ asio::associated_executor_t<Initiation>, Allocator>+ {+ co_return co_await deferred_async_operation<+ R(asio::error_code, T), Initiation, InitArgs...>(+ deferred_init_tag{}, std::move(initiation), std::move(args)...);+ }++ template <typename... InitArgs>+ static auto initiate_impl(+ asio::detail::initiation_archetype<+ R(asio::error_code, T)>,+ std::allocator_arg_t, Allocator, InitArgs... args)+ -> experimental::coro<void(), T, asio::any_io_executor, Allocator>;++ template <typename Initiation, typename... InitArgs>+ static auto initiate(Initiation initiation,+ experimental::use_coro_t<Allocator> tk, InitArgs&&... args)+ {+ return initiate_impl(std::move(initiation), std::allocator_arg,+ tk.get_allocator(), std::forward<InitArgs>(args)...);+ }+};++template <typename Allocator, typename R, typename T>+struct async_result<+ experimental::use_coro_t<Allocator>, R(std::exception_ptr, T)>+{+ template <typename Initiation, typename... InitArgs>+ static auto initiate_impl(Initiation initiation,+ std::allocator_arg_t, Allocator, InitArgs... args)+ -> experimental::coro<void(), T,+ asio::associated_executor_t<Initiation>, Allocator>+ {+ co_return co_await deferred_async_operation<+ R(std::exception_ptr, T), Initiation, InitArgs...>(+ deferred_init_tag{}, std::move(initiation), std::move(args)...);+ }++ template <typename... InitArgs>+ static auto initiate_impl(+ asio::detail::initiation_archetype<R(std::exception_ptr, T)>,+ std::allocator_arg_t, Allocator, InitArgs... args)+ -> experimental::coro<void(), T, asio::any_io_executor, Allocator>;++ template <typename Initiation, typename... InitArgs>+ static auto initiate(Initiation initiation,+ experimental::use_coro_t<Allocator> tk, InitArgs&&... args)+ {+ return initiate_impl(std::move(initiation), std::allocator_arg,+ tk.get_allocator(), std::forward<InitArgs>(args)...);+ }+};++#endif // !defined(GENERATING_DOCUMENTATION)++} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // ASIO_EXPERIMENTAL_IMPL_USE_CORO_HPP
+ link/modules/asio-standalone/asio/include/asio/experimental/impl/use_promise.hpp view
@@ -0,0 +1,66 @@+//+// experimental/impl/use_promise.hpp+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2021-2023 Klemens D. Morgenstern+// (klemens dot morgenstern at gmx dot net)+//+// Distributed under the Boost Software License, Version 1.0. (See accompanying+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)+//++#ifndef ASIO_EXPERIMENTAL_IMPL_USE_PROMISE_HPP+#define ASIO_EXPERIMENTAL_IMPL_USE_PROMISE_HPP++#if defined(_MSC_VER) && (_MSC_VER >= 1200)+# pragma once+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)++#include "asio/detail/config.hpp"+#include <memory>+#include "asio/async_result.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {+namespace experimental {++template <typename Allocator>+struct use_promise_t;++namespace detail {++template<typename Signature, typename Executor, typename Allocator>+struct promise_handler;++} // namespace detail+} // namespace experimental++#if !defined(GENERATING_DOCUMENTATION)++template <typename Allocator, typename R, typename... Args>+struct async_result<experimental::use_promise_t<Allocator>, R(Args...)>+{+ template <typename Initiation, typename... InitArgs>+ static auto initiate(Initiation initiation,+ experimental::use_promise_t<Allocator> up, InitArgs... args)+ -> experimental::promise<void(typename decay<Args>::type...),+ asio::associated_executor_t<Initiation>, Allocator>+ {+ using handler_type = experimental::detail::promise_handler<+ void(typename decay<Args>::type...),+ asio::associated_executor_t<Initiation>, Allocator>;++ handler_type ht{up.get_allocator(), get_associated_executor(initiation)};+ std::move(initiation)(ht, std::move(args)...);+ return ht.make_promise();+ }+};++#endif // !defined(GENERATING_DOCUMENTATION)++} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // ASIO_EXPERIMENTAL_IMPL_USE_PROMISE_HPP
+ link/modules/asio-standalone/asio/include/asio/experimental/parallel_group.hpp view
@@ -0,0 +1,461 @@+//+// experimental/parallel_group.hpp+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com)+//+// Distributed under the Boost Software License, Version 1.0. (See accompanying+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)+//++#ifndef ASIO_EXPERIMENTAL_PARALLEL_GROUP_HPP+#define ASIO_EXPERIMENTAL_PARALLEL_GROUP_HPP++#if defined(_MSC_VER) && (_MSC_VER >= 1200)+# pragma once+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)++#include "asio/detail/config.hpp"+#include <vector>+#include "asio/detail/array.hpp"+#include "asio/detail/memory.hpp"+#include "asio/detail/utility.hpp"+#include "asio/experimental/cancellation_condition.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {+namespace experimental {+namespace detail {++// Helper trait for getting a tuple from a completion signature.++template <typename Signature>+struct parallel_op_signature_as_tuple;++template <typename R, typename... Args>+struct parallel_op_signature_as_tuple<R(Args...)>+{+ typedef std::tuple<typename decay<Args>::type...> type;+};++// Helper trait for concatenating completion signatures.++template <std::size_t N, typename Offsets, typename... Signatures>+struct parallel_group_signature;++template <std::size_t N, typename R0, typename... Args0>+struct parallel_group_signature<N, R0(Args0...)>+{+ typedef asio::detail::array<std::size_t, N> order_type;+ typedef R0 raw_type(Args0...);+ typedef R0 type(order_type, Args0...);+};++template <std::size_t N,+ typename R0, typename... Args0,+ typename R1, typename... Args1>+struct parallel_group_signature<N, R0(Args0...), R1(Args1...)>+{+ typedef asio::detail::array<std::size_t, N> order_type;+ typedef R0 raw_type(Args0..., Args1...);+ typedef R0 type(order_type, Args0..., Args1...);+};++template <std::size_t N, typename Sig0,+ typename Sig1, typename... SigN>+struct parallel_group_signature<N, Sig0, Sig1, SigN...>+{+ typedef asio::detail::array<std::size_t, N> order_type;+ typedef typename parallel_group_signature<N,+ typename parallel_group_signature<N, Sig0, Sig1>::raw_type,+ SigN...>::raw_type raw_type;+ typedef typename parallel_group_signature<N,+ typename parallel_group_signature<N, Sig0, Sig1>::raw_type,+ SigN...>::type type;+};++template <typename Condition, typename Handler,+ typename... Ops, std::size_t... I>+void parallel_group_launch(Condition cancellation_condition, Handler handler,+ std::tuple<Ops...>& ops, asio::detail::index_sequence<I...>);++// Helper trait for determining ranged parallel group completion signatures.++template <typename Signature, typename Allocator>+struct ranged_parallel_group_signature;++template <typename R, typename... Args, typename Allocator>+struct ranged_parallel_group_signature<R(Args...), Allocator>+{+ typedef std::vector<std::size_t,+ ASIO_REBIND_ALLOC(Allocator, std::size_t)> order_type;+ typedef R raw_type(+ std::vector<Args, ASIO_REBIND_ALLOC(Allocator, Args)>...);+ typedef R type(order_type,+ std::vector<Args, ASIO_REBIND_ALLOC(Allocator, Args)>...);+};++template <typename Condition, typename Handler,+ typename Range, typename Allocator>+void ranged_parallel_group_launch(Condition cancellation_condition,+ Handler handler, Range&& range, const Allocator& allocator);++char (¶llel_group_has_iterator_helper(...))[2];++template <typename T>+char parallel_group_has_iterator_helper(T*, typename T::iterator* = 0);++template <typename T>+struct parallel_group_has_iterator_typedef+{+ enum { value = (sizeof((parallel_group_has_iterator_helper)((T*)(0))) == 1) };+};++} // namespace detail++/// Type trait used to determine whether a type is a range of asynchronous+/// operations that can be used with with @c make_parallel_group.+template <typename T>+struct is_async_operation_range+{+#if defined(GENERATING_DOCUMENTATION)+ /// The value member is true if the type may be used as a range of+ /// asynchronous operations.+ static const bool value;+#else+ enum+ {+ value = detail::parallel_group_has_iterator_typedef<T>::value+ };+#endif+};++/// A group of asynchronous operations that may be launched in parallel.+/**+ * See the documentation for asio::experimental::make_parallel_group for+ * a usage example.+ */+template <typename... Ops>+class parallel_group+{+private:+ struct initiate_async_wait+ {+ template <typename Handler, typename Condition>+ void operator()(Handler&& h, Condition&& c, std::tuple<Ops...>&& ops) const+ {+ detail::parallel_group_launch(+ std::forward<Condition>(c), std::forward<Handler>(h),+ ops, asio::detail::index_sequence_for<Ops...>());+ }+ };++ std::tuple<Ops...> ops_;++public:+ /// Constructor.+ explicit parallel_group(Ops... ops)+ : ops_(std::move(ops)...)+ {+ }++ /// The completion signature for the group of operations.+ typedef typename detail::parallel_group_signature<sizeof...(Ops),+ typename completion_signature_of<Ops>::type...>::type signature;++ /// Initiate an asynchronous wait for the group of operations.+ /**+ * Launches the group and asynchronously waits for completion.+ *+ * @param cancellation_condition A function object, called on completion of+ * an operation within the group, that is used to determine whether to cancel+ * the remaining operations. The function object is passed the arguments of+ * the completed operation's handler. To trigger cancellation of the remaining+ * operations, it must return a asio::cancellation_type value other+ * than <tt>asio::cancellation_type::none</tt>.+ *+ * @param token A @ref completion_token whose signature is comprised of+ * a @c std::array<std::size_t, N> indicating the completion order of the+ * operations, followed by all operations' completion handler arguments.+ *+ * The library provides the following @c cancellation_condition types:+ *+ * @li asio::experimental::wait_for_all+ * @li asio::experimental::wait_for_one+ * @li asio::experimental::wait_for_one_error+ * @li asio::experimental::wait_for_one_success+ */+ template <typename CancellationCondition,+ ASIO_COMPLETION_TOKEN_FOR(signature) CompletionToken>+ ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX(CompletionToken, signature)+ async_wait(CancellationCondition cancellation_condition,+ CompletionToken&& token)+ ASIO_INITFN_AUTO_RESULT_TYPE_SUFFIX((+ asio::async_initiate<CompletionToken, signature>(+ declval<initiate_async_wait>(), token,+ std::move(cancellation_condition), std::move(ops_))))+ {+ return asio::async_initiate<CompletionToken, signature>(+ initiate_async_wait(), token,+ std::move(cancellation_condition), std::move(ops_));+ }+};++/// Create a group of operations that may be launched in parallel.+/**+ * For example:+ * @code asio::experimental::make_parallel_group(+ * [&](auto token)+ * {+ * return in.async_read_some(asio::buffer(data), token);+ * },+ * [&](auto token)+ * {+ * return timer.async_wait(token);+ * }+ * ).async_wait(+ * asio::experimental::wait_for_all(),+ * [](+ * std::array<std::size_t, 2> completion_order,+ * std::error_code ec1, std::size_t n1,+ * std::error_code ec2+ * )+ * {+ * switch (completion_order[0])+ * {+ * case 0:+ * {+ * std::cout << "descriptor finished: " << ec1 << ", " << n1 << "\n";+ * }+ * break;+ * case 1:+ * {+ * std::cout << "timer finished: " << ec2 << "\n";+ * }+ * break;+ * }+ * }+ * );+ * @endcode+ */+template <typename... Ops>+ASIO_NODISCARD inline parallel_group<Ops...>+make_parallel_group(Ops... ops)+{+ return parallel_group<Ops...>(std::move(ops)...);+}++/// A range-based group of asynchronous operations that may be launched in+/// parallel.+/**+ * See the documentation for asio::experimental::make_parallel_group for+ * a usage example.+ */+template <typename Range, typename Allocator = std::allocator<void> >+class ranged_parallel_group+{+private:+ struct initiate_async_wait+ {+ template <typename Handler, typename Condition>+ void operator()(Handler&& h, Condition&& c,+ Range&& range, const Allocator& allocator) const+ {+ detail::ranged_parallel_group_launch(std::move(c),+ std::move(h), std::forward<Range>(range), allocator);+ }+ };++ Range range_;+ Allocator allocator_;++public:+ /// Constructor.+ explicit ranged_parallel_group(Range range,+ const Allocator& allocator = Allocator())+ : range_(std::move(range)),+ allocator_(allocator)+ {+ }++ /// The completion signature for the group of operations.+ typedef typename detail::ranged_parallel_group_signature<+ typename completion_signature_of<+ typename std::decay<+ decltype(*std::declval<typename Range::iterator>())>::type>::type,+ Allocator>::type signature;++ /// Initiate an asynchronous wait for the group of operations.+ /**+ * Launches the group and asynchronously waits for completion.+ *+ * @param cancellation_condition A function object, called on completion of+ * an operation within the group, that is used to determine whether to cancel+ * the remaining operations. The function object is passed the arguments of+ * the completed operation's handler. To trigger cancellation of the remaining+ * operations, it must return a asio::cancellation_type value other+ * than <tt>asio::cancellation_type::none</tt>.+ *+ * @param token A @ref completion_token whose signature is comprised of+ * a @c std::vector<std::size_t, Allocator> indicating the completion order of+ * the operations, followed by a vector for each of the completion signature's+ * arguments.+ *+ * The library provides the following @c cancellation_condition types:+ *+ * @li asio::experimental::wait_for_all+ * @li asio::experimental::wait_for_one+ * @li asio::experimental::wait_for_one_error+ * @li asio::experimental::wait_for_one_success+ */+ template <typename CancellationCondition,+ ASIO_COMPLETION_TOKEN_FOR(signature) CompletionToken>+ ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX(CompletionToken, signature)+ async_wait(CancellationCondition cancellation_condition,+ CompletionToken&& token)+ ASIO_INITFN_AUTO_RESULT_TYPE_SUFFIX((+ asio::async_initiate<CompletionToken, signature>(+ declval<initiate_async_wait>(), token,+ std::move(cancellation_condition),+ std::move(range_), allocator_)))+ {+ return asio::async_initiate<CompletionToken, signature>(+ initiate_async_wait(), token,+ std::move(cancellation_condition),+ std::move(range_), allocator_);+ }+};++/// Create a group of operations that may be launched in parallel.+/**+ * @param range A range containing the operations to be launched.+ *+ * For example:+ * @code+ * using op_type = decltype(+ * socket1.async_read_some(+ * asio::buffer(data1),+ * asio::deferred+ * )+ * );+ *+ * std::vector<op_type> ops;+ *+ * ops.push_back(+ * socket1.async_read_some(+ * asio::buffer(data1),+ * asio::deferred+ * )+ * );+ *+ * ops.push_back(+ * socket2.async_read_some(+ * asio::buffer(data2),+ * asio::deferred+ * )+ * );+ *+ * asio::experimental::make_parallel_group(ops).async_wait(+ * asio::experimental::wait_for_all(),+ * [](+ * std::vector<std::size_t> completion_order,+ * std::vector<std::error_code> e,+ * std::vector<std::size_t> n+ * )+ * {+ * for (std::size_t i = 0; i < completion_order.size(); ++i)+ * {+ * std::size_t idx = completion_order[i];+ * std::cout << "socket " << idx << " finished: ";+ * std::cout << e[idx] << ", " << n[idx] << "\n";+ * }+ * }+ * );+ * @endcode+ */+template <typename Range>+ASIO_NODISCARD inline+ranged_parallel_group<typename std::decay<Range>::type>+make_parallel_group(Range&& range,+ typename constraint<+ is_async_operation_range<typename std::decay<Range>::type>::value+ >::type = 0)+{+ return ranged_parallel_group<typename std::decay<Range>::type>(+ std::forward<Range>(range));+}++/// Create a group of operations that may be launched in parallel.+/**+ * @param allocator Specifies the allocator to be used with the result vectors.+ *+ * @param range A range containing the operations to be launched.+ *+ * For example:+ * @code+ * using op_type = decltype(+ * socket1.async_read_some(+ * asio::buffer(data1),+ * asio::deferred+ * )+ * );+ *+ * std::vector<op_type> ops;+ *+ * ops.push_back(+ * socket1.async_read_some(+ * asio::buffer(data1),+ * asio::deferred+ * )+ * );+ *+ * ops.push_back(+ * socket2.async_read_some(+ * asio::buffer(data2),+ * asio::deferred+ * )+ * );+ *+ * asio::experimental::make_parallel_group(+ * std::allocator_arg_t,+ * my_allocator,+ * ops+ * ).async_wait(+ * asio::experimental::wait_for_all(),+ * [](+ * std::vector<std::size_t> completion_order,+ * std::vector<std::error_code> e,+ * std::vector<std::size_t> n+ * )+ * {+ * for (std::size_t i = 0; i < completion_order.size(); ++i)+ * {+ * std::size_t idx = completion_order[i];+ * std::cout << "socket " << idx << " finished: ";+ * std::cout << e[idx] << ", " << n[idx] << "\n";+ * }+ * }+ * );+ * @endcode+ */+template <typename Allocator, typename Range>+ASIO_NODISCARD inline+ranged_parallel_group<typename std::decay<Range>::type, Allocator>+make_parallel_group(allocator_arg_t, const Allocator& allocator, Range&& range,+ typename constraint<+ is_async_operation_range<typename std::decay<Range>::type>::value+ >::type = 0)+{+ return ranged_parallel_group<typename std::decay<Range>::type, Allocator>(+ std::forward<Range>(range), allocator);+}++} // namespace experimental+} // namespace asio++#include "asio/detail/pop_options.hpp"++#include "asio/experimental/impl/parallel_group.hpp"++#endif // ASIO_EXPERIMENTAL_PARALLEL_GROUP_HPP
+ link/modules/asio-standalone/asio/include/asio/experimental/prepend.hpp view
@@ -0,0 +1,36 @@+//+// experimental/prepend.hpp+// ~~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com)+//+// Distributed under the Boost Software License, Version 1.0. (See accompanying+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)+//++#ifndef ASIO_EXPERIMENTAL_PREPEND_HPP+#define ASIO_EXPERIMENTAL_PREPEND_HPP++#if defined(_MSC_VER) && (_MSC_VER >= 1200)+# pragma once+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)++#include "asio/detail/config.hpp"+#include "asio/prepend.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {+namespace experimental {++#if !defined(ASIO_NO_DEPRECATED)+using asio::prepend_t;+using asio::prepend;+#endif // !defined(ASIO_NO_DEPRECATED)++} // namespace experimental+} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // ASIO_EXPERIMENTAL_PREPEND_HPP
+ link/modules/asio-standalone/asio/include/asio/experimental/promise.hpp view
@@ -0,0 +1,224 @@+//+// experimental/promise.hpp+// ~~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2021-2023 Klemens D. Morgenstern+// (klemens dot morgenstern at gmx dot net)+//+// Distributed under the Boost Software License, Version 1.0. (See accompanying+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)+//++#ifndef ASIO_EXPERIMENTAL_PROMISE_HPP+#define ASIO_EXPERIMENTAL_PROMISE_HPP++#if defined(_MSC_VER) && (_MSC_VER >= 1200)+# pragma once+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)++#include "asio/detail/config.hpp"+#include "asio/detail/type_traits.hpp"+#include "asio/any_io_executor.hpp"+#include "asio/associated_cancellation_slot.hpp"+#include "asio/associated_executor.hpp"+#include "asio/bind_executor.hpp"+#include "asio/cancellation_signal.hpp"+#include "asio/dispatch.hpp"+#include "asio/experimental/impl/promise.hpp"+#include "asio/post.hpp"++#include <algorithm>++#include "asio/detail/push_options.hpp"++namespace asio {+namespace experimental {++template <typename T>+struct is_promise : std::false_type {};++template <typename ... Ts>+struct is_promise<promise<Ts...>> : std::true_type {};++template <typename T>+constexpr bool is_promise_v = is_promise<T>::value;++template <typename ... Ts>+struct promise_value_type+{+ using type = std::tuple<Ts...>;+};++template <typename T>+struct promise_value_type<T>+{+ using type = T;+};++template <>+struct promise_value_type<>+{+ using type = std::tuple<>;+};++#if defined(GENERATING_DOCUMENTATION)+/// A disposable handle for an eager operation.+/**+ * @tparam Signature The signature of the operation.+ *+ * @tparam Executor The executor to be used by the promise (taken from the+ * operation).+ *+ * @tparam Allocator The allocator used for the promise. Can be set through+ * use_allocator.+ *+ * A promise can be used to initiate an asynchronous option that can be+ * completed later. If the promise gets destroyed before completion, the+ * operation gets a cancel signal and the result is ignored.+ *+ * A promise fulfills the requirements of async_operation.+ *+ * @par Examples+ * Reading and writing from one coroutine.+ * @code+ * awaitable<void> read_write_some(asio::ip::tcp::socket & sock,+ * asio::mutable_buffer read_buf, asio::const_buffer to_write)+ * {+ * auto p = asio::async_read(read_buf, asio::use_awaitable);+ * co_await asio::async_write_some(to_write, asio::deferred);+ * co_await p;+ * }+ * @endcode+ */+template<typename Signature = void(),+ typename Executor = asio::any_io_executor,+ typename Allocator = std::allocator<void>>+struct promise+#else+template <typename ... Ts, typename Executor, typename Allocator>+struct promise<void(Ts...), Executor, Allocator>+#endif // defined(GENERATING_DOCUMENTATION)+{+ /// The value that's returned by the promise.+ using value_type = typename promise_value_type<Ts...>::type;++ /// Cancel the promise. Usually done through the destructor.+ void cancel(cancellation_type level = cancellation_type::all)+ {+ if (impl_ && !impl_->done)+ {+ asio::dispatch(impl_->executor,+ [level, impl = impl_]{ impl->cancel.emit(level); });+ }+ }++ /// Check if the promise is completed already.+ bool completed() const noexcept+ {+ return impl_ && impl_->done;+ }++ /// Wait for the promise to become ready.+ template <ASIO_COMPLETION_TOKEN_FOR(void(Ts...)) CompletionToken>+ inline ASIO_INITFN_AUTO_RESULT_TYPE(CompletionToken, void(Ts...))+ operator()(CompletionToken&& token)+ {+ assert(impl_);++ return async_initiate<CompletionToken, void(Ts...)>(+ initiate_async_wait{impl_}, token);+ }++ promise() = delete;+ promise(const promise& ) = delete;+ promise(promise&& ) noexcept = default;++ /// Destruct the promise and cancel the operation.+ /**+ * It is safe to destruct a promise of a promise that didn't complete.+ */+ ~promise() { cancel(); }+++private:+#if !defined(GENERATING_DOCUMENTATION)+ template <typename, typename, typename> friend struct promise;+ friend struct detail::promise_handler<void(Ts...), Executor, Allocator>;+#endif // !defined(GENERATING_DOCUMENTATION)++ std::shared_ptr<detail::promise_impl<+ void(Ts...), Executor, Allocator>> impl_;++ promise(+ std::shared_ptr<detail::promise_impl<+ void(Ts...), Executor, Allocator>> impl)+ : impl_(impl)+ {+ }++ struct initiate_async_wait+ {+ std::shared_ptr<detail::promise_impl<+ void(Ts...), Executor, Allocator>> self_;++ template <typename WaitHandler>+ void operator()(WaitHandler&& handler) const+ {+ const auto alloc = get_associated_allocator(+ handler, self_->get_allocator());++ auto cancel = get_associated_cancellation_slot(handler);++ if (self_->done)+ {+ auto exec = asio::get_associated_executor(+ handler, self_->get_executor());++ asio::post(exec,+ [self = std::move(self_),+ handler = std::forward<WaitHandler>(handler)]() mutable+ {+ self->apply(std::move(handler));+ });+ }+ else+ {+ if (cancel.is_connected())+ {+ struct cancel_handler+ {+ std::weak_ptr<detail::promise_impl<+ void(Ts...), Executor, Allocator>> self;++ cancel_handler(+ std::weak_ptr<detail::promise_impl<+ void(Ts...), Executor, Allocator>> self)+ : self(std::move(self))+ {+ }++ void operator()(cancellation_type level) const+ {+ if (auto p = self.lock())+ {+ p->cancel.emit(level);+ p->cancel_();+ }+ }+ };+ cancel.template emplace<cancel_handler>(self_);+ }++ self_->set_completion(alloc, std::forward<WaitHandler>(handler));+ }+ }+ };+};++} // namespace experimental++} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // ASIO_EXPERIMENTAL_PROMISE_HPP
+ link/modules/asio-standalone/asio/include/asio/experimental/use_coro.hpp view
@@ -0,0 +1,195 @@+//+// experimental/use_coro.hpp+// ~~~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2021-2023 Klemens D. Morgenstern+// (klemens dot morgenstern at gmx dot net)+//+// Distributed under the Boost Software License, Version 1.0. (See accompanying+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)+//++#ifndef ASIO_EXPERIMENTAL_USE_CORO_HPP+#define ASIO_EXPERIMENTAL_USE_CORO_HPP++#if defined(_MSC_VER) && (_MSC_VER >= 1200)+# pragma once+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)++#include "asio/detail/config.hpp"+#include <memory>+#include "asio/deferred.hpp"+#include "asio/detail/source_location.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {++class any_io_executor;++namespace experimental {++/// A @ref completion_token that creates another coro for the task completion.+/**+ * The @c use_coro_t class, with its value @c use_coro, is used to represent an+ * operation that can be awaited by the current resumable coroutine. This+ * completion token may be passed as a handler to an asynchronous operation.+ * For example:+ *+ * @code coro<void> my_coroutine(tcp::socket my_socket)+ * {+ * std::size_t n = co_await my_socket.async_read_some(buffer, use_coro);+ * ...+ * } @endcode+ *+ * When used with co_await, the initiating function (@c async_read_some in the+ * above example) suspends the current coroutine. The coroutine is resumed when+ * the asynchronous operation completes, and the result of the operation is+ * returned.+ *+ * Note that this token is not the most efficient (use @c asio::deferred+ * for that) but does provide type erasure, as it will always return a @c coro.+ */+template <typename Allocator = std::allocator<void>>+struct use_coro_t+{++ /// The allocator type. The allocator is used when constructing the+ /// @c std::promise object for a given asynchronous operation.+ typedef Allocator allocator_type;++ /// Default constructor.+ ASIO_CONSTEXPR use_coro_t(+ allocator_type allocator = allocator_type{}+#if defined(ASIO_ENABLE_HANDLER_TRACKING)+# if defined(ASIO_HAS_SOURCE_LOCATION)+ , asio::detail::source_location location =+ asio::detail::source_location::current()+# endif // defined(ASIO_HAS_SOURCE_LOCATION)+#endif // defined(ASIO_ENABLE_HANDLER_TRACKING)+ )+ : allocator_(allocator)+#if defined(ASIO_ENABLE_HANDLER_TRACKING)+# if defined(ASIO_HAS_SOURCE_LOCATION)+ , file_name_(location.file_name()),+ line_(location.line()),+ function_name_(location.function_name())+# else // defined(ASIO_HAS_SOURCE_LOCATION)+ , file_name_(0),+ line_(0),+ function_name_(0)+# endif // defined(ASIO_HAS_SOURCE_LOCATION)+#endif // defined(ASIO_ENABLE_HANDLER_TRACKING)+ {+ }+++ /// Specify an alternate allocator.+ template <typename OtherAllocator>+ use_coro_t<OtherAllocator> rebind(const OtherAllocator& allocator) const+ {+ return use_future_t<OtherAllocator>(allocator);+ }++ /// Obtain allocator.+ allocator_type get_allocator() const+ {+ return allocator_;+ }++ /// Constructor used to specify file name, line, and function name.+ ASIO_CONSTEXPR use_coro_t(const char* file_name,+ int line, const char* function_name,+ allocator_type allocator = allocator_type{}) :+#if defined(ASIO_ENABLE_HANDLER_TRACKING)+ file_name_(file_name),+ line_(line),+ function_name_(function_name),+#endif // defined(ASIO_ENABLE_HANDLER_TRACKING)+ allocator_(allocator)+ {+#if !defined(ASIO_ENABLE_HANDLER_TRACKING)+ (void)file_name;+ (void)line;+ (void)function_name;+#endif // !defined(ASIO_ENABLE_HANDLER_TRACKING)+ }++ /// Adapts an executor to add the @c use_coro_t completion token as the+ /// default.+ template <typename InnerExecutor>+ struct executor_with_default : InnerExecutor+ {+ /// Specify @c use_coro_t as the default completion token type.+ typedef use_coro_t default_completion_token_type;++ /// Construct the adapted executor from the inner executor type.+ template <typename InnerExecutor1>+ executor_with_default(const InnerExecutor1& ex,+ typename constraint<+ conditional<+ !is_same<InnerExecutor1, executor_with_default>::value,+ is_convertible<InnerExecutor1, InnerExecutor>,+ false_type+ >::type::value+ >::type = 0) ASIO_NOEXCEPT+ : InnerExecutor(ex)+ {+ }+ };++ /// Type alias to adapt an I/O object to use @c use_coro_t as its+ /// default completion token type.+#if defined(ASIO_HAS_ALIAS_TEMPLATES) \+ || defined(GENERATING_DOCUMENTATION)+ template <typename T>+ using as_default_on_t = typename T::template rebind_executor<+ executor_with_default<typename T::executor_type> >::other;+#endif // defined(ASIO_HAS_ALIAS_TEMPLATES)+ // || defined(GENERATING_DOCUMENTATION)++ /// Function helper to adapt an I/O object to use @c use_coro_t as its+ /// default completion token type.+ template <typename T>+ static typename decay<T>::type::template rebind_executor<+ executor_with_default<typename decay<T>::type::executor_type>+ >::other+ as_default_on(ASIO_MOVE_ARG(T) object)+ {+ return typename decay<T>::type::template rebind_executor<+ executor_with_default<typename decay<T>::type::executor_type>+ >::other(ASIO_MOVE_CAST(T)(object));+ }++#if defined(ASIO_ENABLE_HANDLER_TRACKING)+ const char* file_name_;+ int line_;+ const char* function_name_;+#endif // defined(ASIO_ENABLE_HANDLER_TRACKING)++private:+ Allocator allocator_;+};++/// A @ref completion_token object that represents the currently executing+/// resumable coroutine.+/**+ * See the documentation for asio::use_coro_t for a usage example.+ */+#if defined(GENERATING_DOCUMENTATION)+constexpr use_coro_t<> use_coro;+#elif defined(ASIO_HAS_CONSTEXPR)+constexpr use_coro_t<> use_coro(0, 0, 0);+#elif defined(ASIO_MSVC)+__declspec(selectany) use_coro_t<> use_coro(0, 0, 0);+#endif++} // namespace experimental+} // namespace asio++#include "asio/detail/pop_options.hpp"++#include "asio/experimental/impl/use_coro.hpp"+#include "asio/experimental/coro.hpp"++#endif // ASIO_EXPERIMENTAL_USE_CORO_HPP
+ link/modules/asio-standalone/asio/include/asio/experimental/use_promise.hpp view
@@ -0,0 +1,111 @@+//+// experimental/use_promise.hpp+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2021-2023 Klemens D. Morgenstern+// (klemens dot morgenstern at gmx dot net)+//+// Distributed under the Boost Software License, Version 1.0. (See accompanying+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)+//++#ifndef ASIO_EXPERIMENTAL_USE_PROMISE_HPP+#define ASIO_EXPERIMENTAL_USE_PROMISE_HPP++#if defined(_MSC_VER) && (_MSC_VER >= 1200)+# pragma once+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)++#include "asio/detail/config.hpp"+#include <memory>+#include "asio/detail/type_traits.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {+namespace experimental {++template <typename Allocator = std::allocator<void>>+struct use_promise_t+{+ /// The allocator type. The allocator is used when constructing the+ /// @c promise object for a given asynchronous operation.+ typedef Allocator allocator_type;++ /// Construct using default-constructed allocator.+ ASIO_CONSTEXPR use_promise_t()+ {+ }++ /// Construct using specified allocator.+ explicit use_promise_t(const Allocator& allocator)+ : allocator_(allocator)+ {+ }++ /// Obtain allocator.+ allocator_type get_allocator() const ASIO_NOEXCEPT+ {+ return allocator_;+ }++ /// Adapts an executor to add the @c use_promise_t completion token as the+ /// default.+ template <typename InnerExecutor>+ struct executor_with_default : InnerExecutor+ {+ /// Specify @c use_promise_t as the default completion token type.+ typedef use_promise_t<Allocator> default_completion_token_type;++ /// Construct the adapted executor from the inner executor type.+ executor_with_default(const InnerExecutor& ex) ASIO_NOEXCEPT+ : InnerExecutor(ex)+ {+ }++ /// Convert the specified executor to the inner executor type, then use+ /// that to construct the adapted executor.+ template <typename OtherExecutor>+ executor_with_default(const OtherExecutor& ex,+ typename constraint<+ is_convertible<OtherExecutor, InnerExecutor>::value+ >::type = 0) ASIO_NOEXCEPT+ : InnerExecutor(ex)+ {+ }+ };++ /// Function helper to adapt an I/O object to use @c use_promise_t as its+ /// default completion token type.+ template <typename T>+ static typename decay<T>::type::template rebind_executor<+ executor_with_default<typename decay<T>::type::executor_type>+ >::other+ as_default_on(ASIO_MOVE_ARG(T) object)+ {+ return typename decay<T>::type::template rebind_executor<+ executor_with_default<typename decay<T>::type::executor_type>+ >::other(ASIO_MOVE_CAST(T)(object));+ }++ /// Specify an alternate allocator.+ template <typename OtherAllocator>+ use_promise_t<OtherAllocator> rebind(const OtherAllocator& allocator) const+ {+ return use_promise_t<OtherAllocator>(allocator);+ }++private:+ Allocator allocator_;+};++constexpr use_promise_t<> use_promise;++} // namespace experimental+} // namespace asio++#include "asio/detail/pop_options.hpp"++#include "asio/experimental/impl/use_promise.hpp"++#endif // ASIO_EXPERIMENTAL_USE_CORO_HPP
+ link/modules/asio-standalone/asio/include/asio/file_base.hpp view
@@ -0,0 +1,166 @@+//+// file_base.hpp+// ~~~~~~~~~~~~~+//+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com)+//+// Distributed under the Boost Software License, Version 1.0. (See accompanying+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)+//++#ifndef ASIO_FILE_BASE_HPP+#define ASIO_FILE_BASE_HPP++#if defined(_MSC_VER) && (_MSC_VER >= 1200)+# pragma once+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)++#include "asio/detail/config.hpp"++#if defined(ASIO_HAS_FILE) \+ || defined(GENERATING_DOCUMENTATION)++#if !defined(ASIO_WINDOWS)+# include <fcntl.h>+#endif // !defined(ASIO_WINDOWS)++#include "asio/detail/push_options.hpp"++namespace asio {++/// The file_base class is used as a base for the basic_stream_file and+/// basic_random_access_file class templates so that we have a common place to+/// define flags.+class file_base+{+public:+#if defined(GENERATING_DOCUMENTATION)+ /// A bitmask type (C++ Std [lib.bitmask.types]).+ typedef unspecified flags;++ /// Open the file for reading.+ static const flags read_only = implementation_defined;++ /// Open the file for writing.+ static const flags write_only = implementation_defined;++ /// Open the file for reading and writing.+ static const flags read_write = implementation_defined;++ /// Open the file in append mode.+ static const flags append = implementation_defined;++ /// Create the file if it does not exist.+ static const flags create = implementation_defined;++ /// Ensure a new file is created. Must be combined with @c create.+ static const flags exclusive = implementation_defined;++ /// Open the file with any existing contents truncated.+ static const flags truncate = implementation_defined;++ /// Open the file so that write operations automatically synchronise the file+ /// data and metadata to disk.+ static const flags sync_all_on_write = implementation_defined;+#else+ enum flags+ {+#if defined(ASIO_WINDOWS)+ read_only = 1,+ write_only = 2,+ read_write = 4,+ append = 8,+ create = 16,+ exclusive = 32,+ truncate = 64,+ sync_all_on_write = 128+#else // defined(ASIO_WINDOWS)+ read_only = O_RDONLY,+ write_only = O_WRONLY,+ read_write = O_RDWR,+ append = O_APPEND,+ create = O_CREAT,+ exclusive = O_EXCL,+ truncate = O_TRUNC,+ sync_all_on_write = O_SYNC+#endif // defined(ASIO_WINDOWS)+ };++ // Implement bitmask operations as shown in C++ Std [lib.bitmask.types].++ friend flags operator&(flags x, flags y)+ {+ return static_cast<flags>(+ static_cast<unsigned int>(x) & static_cast<unsigned int>(y));+ }++ friend flags operator|(flags x, flags y)+ {+ return static_cast<flags>(+ static_cast<unsigned int>(x) | static_cast<unsigned int>(y));+ }++ friend flags operator^(flags x, flags y)+ {+ return static_cast<flags>(+ static_cast<unsigned int>(x) ^ static_cast<unsigned int>(y));+ }++ friend flags operator~(flags x)+ {+ return static_cast<flags>(~static_cast<unsigned int>(x));+ }++ friend flags& operator&=(flags& x, flags y)+ {+ x = x & y;+ return x;+ }++ friend flags& operator|=(flags& x, flags y)+ {+ x = x | y;+ return x;+ }++ friend flags& operator^=(flags& x, flags y)+ {+ x = x ^ y;+ return x;+ }+#endif++ /// Basis for seeking in a file.+ enum seek_basis+ {+#if defined(GENERATING_DOCUMENTATION)+ /// Seek to an absolute position.+ seek_set = implementation_defined,++ /// Seek to an offset relative to the current file position.+ seek_cur = implementation_defined,++ /// Seek to an offset relative to the end of the file.+ seek_end = implementation_defined+#else+ seek_set = SEEK_SET,+ seek_cur = SEEK_CUR,+ seek_end = SEEK_END+#endif+ };++protected:+ /// Protected destructor to prevent deletion through this type.+ ~file_base()+ {+ }+};++} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // defined(ASIO_HAS_FILE)+ // || defined(GENERATING_DOCUMENTATION)++#endif // ASIO_FILE_BASE_HPP
link/modules/asio-standalone/asio/include/asio/generic/basic_endpoint.hpp view
@@ -2,7 +2,7 @@ // generic/basic_endpoint.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/generic/datagram_protocol.hpp view
@@ -2,7 +2,7 @@ // generic/datagram_protocol.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/generic/detail/endpoint.hpp view
@@ -2,7 +2,7 @@ // generic/detail/endpoint.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/generic/detail/impl/endpoint.ipp view
@@ -2,7 +2,7 @@ // generic/detail/impl/endpoint.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/generic/raw_protocol.hpp view
@@ -2,7 +2,7 @@ // generic/raw_protocol.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/generic/seq_packet_protocol.hpp view
@@ -2,7 +2,7 @@ // generic/seq_packet_protocol.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/generic/stream_protocol.hpp view
@@ -2,7 +2,7 @@ // generic/stream_protocol.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/handler_alloc_hook.hpp view
@@ -2,7 +2,7 @@ // handler_alloc_hook.hpp // ~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/handler_continuation_hook.hpp view
@@ -2,7 +2,7 @@ // handler_continuation_hook.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/handler_invoke_hook.hpp view
@@ -2,7 +2,7 @@ // handler_invoke_hook.hpp // ~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/high_resolution_timer.hpp view
@@ -2,7 +2,7 @@ // high_resolution_timer.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+ link/modules/asio-standalone/asio/include/asio/impl/any_completion_executor.ipp view
@@ -0,0 +1,130 @@+//+// impl/any_completion_executor.ipp+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com)+//+// Distributed under the Boost Software License, Version 1.0. (See accompanying+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)+//++#ifndef ASIO_IMPL_ANY_COMPLETION_EXECUTOR_IPP+#define ASIO_IMPL_ANY_COMPLETION_EXECUTOR_IPP++#if defined(_MSC_VER) && (_MSC_VER >= 1200)+# pragma once+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)++#include "asio/detail/config.hpp"++#if !defined(ASIO_USE_TS_EXECUTOR_AS_DEFAULT)++#include "asio/any_completion_executor.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {++any_completion_executor::any_completion_executor() ASIO_NOEXCEPT+ : base_type()+{+}++any_completion_executor::any_completion_executor(nullptr_t) ASIO_NOEXCEPT+ : base_type(nullptr_t())+{+}++any_completion_executor::any_completion_executor(+ const any_completion_executor& e) ASIO_NOEXCEPT+ : base_type(static_cast<const base_type&>(e))+{+}++any_completion_executor::any_completion_executor(std::nothrow_t,+ const any_completion_executor& e) ASIO_NOEXCEPT+ : base_type(static_cast<const base_type&>(e))+{+}++#if defined(ASIO_HAS_MOVE)+any_completion_executor::any_completion_executor(+ any_completion_executor&& e) ASIO_NOEXCEPT+ : base_type(static_cast<base_type&&>(e))+{+}++any_completion_executor::any_completion_executor(std::nothrow_t,+ any_completion_executor&& e) ASIO_NOEXCEPT+ : base_type(static_cast<base_type&&>(e))+{+}+#endif // defined(ASIO_HAS_MOVE)++any_completion_executor& any_completion_executor::operator=(+ const any_completion_executor& e) ASIO_NOEXCEPT+{+ base_type::operator=(static_cast<const base_type&>(e));+ return *this;+}++#if defined(ASIO_HAS_MOVE)+any_completion_executor& any_completion_executor::operator=(+ any_completion_executor&& e) ASIO_NOEXCEPT+{+ base_type::operator=(static_cast<base_type&&>(e));+ return *this;+}+#endif // defined(ASIO_HAS_MOVE)++any_completion_executor& any_completion_executor::operator=(nullptr_t)+{+ base_type::operator=(nullptr_t());+ return *this;+}++any_completion_executor::~any_completion_executor()+{+}++void any_completion_executor::swap(+ any_completion_executor& other) ASIO_NOEXCEPT+{+ static_cast<base_type&>(*this).swap(static_cast<base_type&>(other));+}++template <>+any_completion_executor any_completion_executor::prefer(+ const execution::outstanding_work_t::tracked_t& p, int) const+{+ return static_cast<const base_type&>(*this).prefer(p);+}++template <>+any_completion_executor any_completion_executor::prefer(+ const execution::outstanding_work_t::untracked_t& p, int) const+{+ return static_cast<const base_type&>(*this).prefer(p);+}++template <>+any_completion_executor any_completion_executor::prefer(+ const execution::relationship_t::fork_t& p, int) const+{+ return static_cast<const base_type&>(*this).prefer(p);+}++template <>+any_completion_executor any_completion_executor::prefer(+ const execution::relationship_t::continuation_t& p, int) const+{+ return static_cast<const base_type&>(*this).prefer(p);+}++} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // !defined(ASIO_USE_TS_EXECUTOR_AS_DEFAULT)++#endif // ASIO_IMPL_ANY_COMPLETION_EXECUTOR_IPP
+ link/modules/asio-standalone/asio/include/asio/impl/any_io_executor.ipp view
@@ -0,0 +1,141 @@+//+// impl/any_io_executor.ipp+// ~~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com)+//+// Distributed under the Boost Software License, Version 1.0. (See accompanying+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)+//++#ifndef ASIO_IMPL_ANY_IO_EXECUTOR_IPP+#define ASIO_IMPL_ANY_IO_EXECUTOR_IPP++#if defined(_MSC_VER) && (_MSC_VER >= 1200)+# pragma once+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)++#include "asio/detail/config.hpp"++#if !defined(ASIO_USE_TS_EXECUTOR_AS_DEFAULT)++#include "asio/any_io_executor.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {++any_io_executor::any_io_executor() ASIO_NOEXCEPT+ : base_type()+{+}++any_io_executor::any_io_executor(nullptr_t) ASIO_NOEXCEPT+ : base_type(nullptr_t())+{+}++any_io_executor::any_io_executor(const any_io_executor& e) ASIO_NOEXCEPT+ : base_type(static_cast<const base_type&>(e))+{+}++any_io_executor::any_io_executor(std::nothrow_t,+ const any_io_executor& e) ASIO_NOEXCEPT+ : base_type(static_cast<const base_type&>(e))+{+}++#if defined(ASIO_HAS_MOVE)+any_io_executor::any_io_executor(any_io_executor&& e) ASIO_NOEXCEPT+ : base_type(static_cast<base_type&&>(e))+{+}++any_io_executor::any_io_executor(std::nothrow_t,+ any_io_executor&& e) ASIO_NOEXCEPT+ : base_type(static_cast<base_type&&>(e))+{+}+#endif // defined(ASIO_HAS_MOVE)++any_io_executor& any_io_executor::operator=(+ const any_io_executor& e) ASIO_NOEXCEPT+{+ base_type::operator=(static_cast<const base_type&>(e));+ return *this;+}++#if defined(ASIO_HAS_MOVE)+any_io_executor& any_io_executor::operator=(+ any_io_executor&& e) ASIO_NOEXCEPT+{+ base_type::operator=(static_cast<base_type&&>(e));+ return *this;+}+#endif // defined(ASIO_HAS_MOVE)++any_io_executor& any_io_executor::operator=(nullptr_t)+{+ base_type::operator=(nullptr_t());+ return *this;+}++any_io_executor::~any_io_executor()+{+}++void any_io_executor::swap(any_io_executor& other) ASIO_NOEXCEPT+{+ static_cast<base_type&>(*this).swap(static_cast<base_type&>(other));+}++template <>+any_io_executor any_io_executor::require(+ const execution::blocking_t::never_t& p, int) const+{+ return static_cast<const base_type&>(*this).require(p);+}++template <>+any_io_executor any_io_executor::prefer(+ const execution::blocking_t::possibly_t& p, int) const+{+ return static_cast<const base_type&>(*this).prefer(p);+}++template <>+any_io_executor any_io_executor::prefer(+ const execution::outstanding_work_t::tracked_t& p, int) const+{+ return static_cast<const base_type&>(*this).prefer(p);+}++template <>+any_io_executor any_io_executor::prefer(+ const execution::outstanding_work_t::untracked_t& p, int) const+{+ return static_cast<const base_type&>(*this).prefer(p);+}++template <>+any_io_executor any_io_executor::prefer(+ const execution::relationship_t::fork_t& p, int) const+{+ return static_cast<const base_type&>(*this).prefer(p);+}++template <>+any_io_executor any_io_executor::prefer(+ const execution::relationship_t::continuation_t& p, int) const+{+ return static_cast<const base_type&>(*this).prefer(p);+}++} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // !defined(ASIO_USE_TS_EXECUTOR_AS_DEFAULT)++#endif // ASIO_IMPL_ANY_IO_EXECUTOR_IPP
+ link/modules/asio-standalone/asio/include/asio/impl/append.hpp view
@@ -0,0 +1,225 @@+//+// impl/append.hpp+// ~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com)+//+// Distributed under the Boost Software License, Version 1.0. (See accompanying+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)+//++#ifndef ASIO_IMPL_APPEND_HPP+#define ASIO_IMPL_APPEND_HPP++#if defined(_MSC_VER) && (_MSC_VER >= 1200)+# pragma once+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)++#include "asio/detail/config.hpp"++#include "asio/associator.hpp"+#include "asio/async_result.hpp"+#include "asio/detail/handler_alloc_helpers.hpp"+#include "asio/detail/handler_cont_helpers.hpp"+#include "asio/detail/handler_invoke_helpers.hpp"+#include "asio/detail/type_traits.hpp"+#include "asio/detail/utility.hpp"+#include "asio/detail/variadic_templates.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {+namespace detail {++// Class to adapt an append_t as a completion handler.+template <typename Handler, typename... Values>+class append_handler+{+public:+ typedef void result_type;++ template <typename H>+ append_handler(ASIO_MOVE_ARG(H) handler, std::tuple<Values...> values)+ : handler_(ASIO_MOVE_CAST(H)(handler)),+ values_(ASIO_MOVE_CAST(std::tuple<Values...>)(values))+ {+ }++ template <typename... Args>+ void operator()(ASIO_MOVE_ARG(Args)... args)+ {+ this->invoke(+ index_sequence_for<Values...>{},+ ASIO_MOVE_CAST(Args)(args)...);+ }++ template <std::size_t... I, typename... Args>+ void invoke(index_sequence<I...>, ASIO_MOVE_ARG(Args)... args)+ {+ ASIO_MOVE_OR_LVALUE(Handler)(handler_)(+ ASIO_MOVE_CAST(Args)(args)...,+ ASIO_MOVE_CAST(Values)(std::get<I>(values_))...);+ }++//private:+ Handler handler_;+ std::tuple<Values...> values_;+};++template <typename Handler>+inline asio_handler_allocate_is_deprecated+asio_handler_allocate(std::size_t size,+ append_handler<Handler>* this_handler)+{+#if defined(ASIO_NO_DEPRECATED)+ asio_handler_alloc_helpers::allocate(size, this_handler->handler_);+ return asio_handler_allocate_is_no_longer_used();+#else // defined(ASIO_NO_DEPRECATED)+ return asio_handler_alloc_helpers::allocate(+ size, this_handler->handler_);+#endif // defined(ASIO_NO_DEPRECATED)+}++template <typename Handler>+inline asio_handler_deallocate_is_deprecated+asio_handler_deallocate(void* pointer, std::size_t size,+ append_handler<Handler>* this_handler)+{+ asio_handler_alloc_helpers::deallocate(+ pointer, size, this_handler->handler_);+#if defined(ASIO_NO_DEPRECATED)+ return asio_handler_deallocate_is_no_longer_used();+#endif // defined(ASIO_NO_DEPRECATED)+}++template <typename Handler>+inline bool asio_handler_is_continuation(+ append_handler<Handler>* this_handler)+{+ return asio_handler_cont_helpers::is_continuation(+ this_handler->handler_);+}++template <typename Function, typename Handler>+inline asio_handler_invoke_is_deprecated+asio_handler_invoke(Function& function,+ append_handler<Handler>* this_handler)+{+ asio_handler_invoke_helpers::invoke(+ function, this_handler->handler_);+#if defined(ASIO_NO_DEPRECATED)+ return asio_handler_invoke_is_no_longer_used();+#endif // defined(ASIO_NO_DEPRECATED)+}++template <typename Function, typename Handler>+inline asio_handler_invoke_is_deprecated+asio_handler_invoke(const Function& function,+ append_handler<Handler>* this_handler)+{+ asio_handler_invoke_helpers::invoke(+ function, this_handler->handler_);+#if defined(ASIO_NO_DEPRECATED)+ return asio_handler_invoke_is_no_longer_used();+#endif // defined(ASIO_NO_DEPRECATED)+}++template <typename Signature, typename... Values>+struct append_signature;++template <typename R, typename... Args, typename... Values>+struct append_signature<R(Args...), Values...>+{+ typedef R type(typename decay<Args>::type..., Values...);+};++} // namespace detail++#if !defined(GENERATING_DOCUMENTATION)++template <typename CompletionToken, typename... Values, typename Signature>+struct async_result<+ append_t<CompletionToken, Values...>, Signature>+ : async_result<CompletionToken,+ typename detail::append_signature<+ Signature, Values...>::type>+{+ typedef typename detail::append_signature<+ Signature, Values...>::type signature;++ template <typename Initiation>+ struct init_wrapper+ {+ init_wrapper(Initiation init)+ : initiation_(ASIO_MOVE_CAST(Initiation)(init))+ {+ }++ template <typename Handler, typename... Args>+ void operator()(+ ASIO_MOVE_ARG(Handler) handler,+ std::tuple<Values...> values,+ ASIO_MOVE_ARG(Args)... args)+ {+ ASIO_MOVE_CAST(Initiation)(initiation_)(+ detail::append_handler<+ typename decay<Handler>::type, Values...>(+ ASIO_MOVE_CAST(Handler)(handler),+ ASIO_MOVE_CAST(std::tuple<Values...>)(values)),+ ASIO_MOVE_CAST(Args)(args)...);+ }++ Initiation initiation_;+ };++ template <typename Initiation, typename RawCompletionToken, typename... Args>+ static ASIO_INITFN_DEDUCED_RESULT_TYPE(CompletionToken, signature,+ (async_initiate<CompletionToken, signature>(+ declval<init_wrapper<typename decay<Initiation>::type> >(),+ declval<CompletionToken&>(),+ declval<std::tuple<Values...> >(),+ declval<ASIO_MOVE_ARG(Args)>()...)))+ initiate(+ ASIO_MOVE_ARG(Initiation) initiation,+ ASIO_MOVE_ARG(RawCompletionToken) token,+ ASIO_MOVE_ARG(Args)... args)+ {+ return async_initiate<CompletionToken, signature>(+ init_wrapper<typename decay<Initiation>::type>(+ ASIO_MOVE_CAST(Initiation)(initiation)),+ token.token_,+ ASIO_MOVE_CAST(std::tuple<Values...>)(token.values_),+ ASIO_MOVE_CAST(Args)(args)...);+ }+};++template <template <typename, typename> class Associator,+ typename Handler, typename... Values, typename DefaultCandidate>+struct associator<Associator,+ detail::append_handler<Handler, Values...>, DefaultCandidate>+ : Associator<Handler, DefaultCandidate>+{+ static typename Associator<Handler, DefaultCandidate>::type+ get(const detail::append_handler<Handler, Values...>& h) ASIO_NOEXCEPT+ {+ return Associator<Handler, DefaultCandidate>::get(h.handler_);+ }++ static ASIO_AUTO_RETURN_TYPE_PREFIX2(+ typename Associator<Handler, DefaultCandidate>::type)+ get(const detail::append_handler<Handler, Values...>& h,+ const DefaultCandidate& c) ASIO_NOEXCEPT+ ASIO_AUTO_RETURN_TYPE_SUFFIX((+ Associator<Handler, DefaultCandidate>::get(h.handler_, c)))+ {+ return Associator<Handler, DefaultCandidate>::get(h.handler_, c);+ }+};++#endif // !defined(GENERATING_DOCUMENTATION)++} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // ASIO_IMPL_APPEND_HPP
+ link/modules/asio-standalone/asio/include/asio/impl/as_tuple.hpp view
@@ -0,0 +1,320 @@+//+// impl/as_tuple.hpp+// ~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com)+//+// Distributed under the Boost Software License, Version 1.0. (See accompanying+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)+//++#ifndef ASIO_IMPL_AS_TUPLE_HPP+#define ASIO_IMPL_AS_TUPLE_HPP++#if defined(_MSC_VER) && (_MSC_VER >= 1200)+# pragma once+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)++#include "asio/detail/config.hpp"++#include <tuple>++#include "asio/associator.hpp"+#include "asio/async_result.hpp"+#include "asio/detail/handler_alloc_helpers.hpp"+#include "asio/detail/handler_cont_helpers.hpp"+#include "asio/detail/handler_invoke_helpers.hpp"+#include "asio/detail/type_traits.hpp"+#include "asio/detail/variadic_templates.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {+namespace detail {++// Class to adapt a as_tuple_t as a completion handler.+template <typename Handler>+class as_tuple_handler+{+public:+ typedef void result_type;++ template <typename CompletionToken>+ as_tuple_handler(as_tuple_t<CompletionToken> e)+ : handler_(ASIO_MOVE_CAST(CompletionToken)(e.token_))+ {+ }++ template <typename RedirectedHandler>+ as_tuple_handler(ASIO_MOVE_ARG(RedirectedHandler) h)+ : handler_(ASIO_MOVE_CAST(RedirectedHandler)(h))+ {+ }++ template <typename... Args>+ void operator()(ASIO_MOVE_ARG(Args)... args)+ {+ ASIO_MOVE_OR_LVALUE(Handler)(handler_)(+ std::make_tuple(ASIO_MOVE_CAST(Args)(args)...));+ }++//private:+ Handler handler_;+};++template <typename Handler>+inline asio_handler_allocate_is_deprecated+asio_handler_allocate(std::size_t size,+ as_tuple_handler<Handler>* this_handler)+{+#if defined(ASIO_NO_DEPRECATED)+ asio_handler_alloc_helpers::allocate(size, this_handler->handler_);+ return asio_handler_allocate_is_no_longer_used();+#else // defined(ASIO_NO_DEPRECATED)+ return asio_handler_alloc_helpers::allocate(+ size, this_handler->handler_);+#endif // defined(ASIO_NO_DEPRECATED)+}++template <typename Handler>+inline asio_handler_deallocate_is_deprecated+asio_handler_deallocate(void* pointer, std::size_t size,+ as_tuple_handler<Handler>* this_handler)+{+ asio_handler_alloc_helpers::deallocate(+ pointer, size, this_handler->handler_);+#if defined(ASIO_NO_DEPRECATED)+ return asio_handler_deallocate_is_no_longer_used();+#endif // defined(ASIO_NO_DEPRECATED)+}++template <typename Handler>+inline bool asio_handler_is_continuation(+ as_tuple_handler<Handler>* this_handler)+{+ return asio_handler_cont_helpers::is_continuation(+ this_handler->handler_);+}++template <typename Function, typename Handler>+inline asio_handler_invoke_is_deprecated+asio_handler_invoke(Function& function,+ as_tuple_handler<Handler>* this_handler)+{+ asio_handler_invoke_helpers::invoke(+ function, this_handler->handler_);+#if defined(ASIO_NO_DEPRECATED)+ return asio_handler_invoke_is_no_longer_used();+#endif // defined(ASIO_NO_DEPRECATED)+}++template <typename Function, typename Handler>+inline asio_handler_invoke_is_deprecated+asio_handler_invoke(const Function& function,+ as_tuple_handler<Handler>* this_handler)+{+ asio_handler_invoke_helpers::invoke(+ function, this_handler->handler_);+#if defined(ASIO_NO_DEPRECATED)+ return asio_handler_invoke_is_no_longer_used();+#endif // defined(ASIO_NO_DEPRECATED)+}++template <typename Signature>+struct as_tuple_signature;++template <typename R, typename... Args>+struct as_tuple_signature<R(Args...)>+{+ typedef R type(std::tuple<typename decay<Args>::type...>);+};++#if defined(ASIO_HAS_REF_QUALIFIED_FUNCTIONS)++template <typename R, typename... Args>+struct as_tuple_signature<R(Args...) &>+{+ typedef R type(std::tuple<typename decay<Args>::type...>) &;+};++template <typename R, typename... Args>+struct as_tuple_signature<R(Args...) &&>+{+ typedef R type(std::tuple<typename decay<Args>::type...>) &&;+};++# if defined(ASIO_HAS_NOEXCEPT_FUNCTION_TYPE)++template <typename R, typename... Args>+struct as_tuple_signature<R(Args...) noexcept>+{+ typedef R type(std::tuple<typename decay<Args>::type...>) noexcept;+};++template <typename R, typename... Args>+struct as_tuple_signature<R(Args...) & noexcept>+{+ typedef R type(std::tuple<typename decay<Args>::type...>) & noexcept;+};++template <typename R, typename... Args>+struct as_tuple_signature<R(Args...) && noexcept>+{+ typedef R type(std::tuple<typename decay<Args>::type...>) && noexcept;+};++# endif // defined(ASIO_HAS_NOEXCEPT_FUNCTION_TYPE)+#endif // defined(ASIO_HAS_REF_QUALIFIED_FUNCTIONS)++} // namespace detail++#if !defined(GENERATING_DOCUMENTATION)++template <typename CompletionToken, typename... Signatures>+struct async_result<as_tuple_t<CompletionToken>, Signatures...>+ : async_result<CompletionToken,+ typename detail::as_tuple_signature<Signatures>::type...>+{+ template <typename Initiation>+ struct init_wrapper+ {+ init_wrapper(Initiation init)+ : initiation_(ASIO_MOVE_CAST(Initiation)(init))+ {+ }++ template <typename Handler, typename... Args>+ void operator()(+ ASIO_MOVE_ARG(Handler) handler,+ ASIO_MOVE_ARG(Args)... args)+ {+ ASIO_MOVE_CAST(Initiation)(initiation_)(+ detail::as_tuple_handler<+ typename decay<Handler>::type>(+ ASIO_MOVE_CAST(Handler)(handler)),+ ASIO_MOVE_CAST(Args)(args)...);+ }++ Initiation initiation_;+ };++ template <typename Initiation, typename RawCompletionToken, typename... Args>+ static ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX(CompletionToken,+ typename detail::as_tuple_signature<Signatures>::type...)+ initiate(+ ASIO_MOVE_ARG(Initiation) initiation,+ ASIO_MOVE_ARG(RawCompletionToken) token,+ ASIO_MOVE_ARG(Args)... args)+ ASIO_INITFN_AUTO_RESULT_TYPE_SUFFIX((+ async_initiate<+ typename conditional<+ is_const<typename remove_reference<RawCompletionToken>::type>::value,+ const CompletionToken, CompletionToken>::type,+ typename detail::as_tuple_signature<Signatures>::type...>(+ init_wrapper<typename decay<Initiation>::type>(+ ASIO_MOVE_CAST(Initiation)(initiation)),+ token.token_, ASIO_MOVE_CAST(Args)(args)...)))+ {+ return async_initiate<+ typename conditional<+ is_const<typename remove_reference<RawCompletionToken>::type>::value,+ const CompletionToken, CompletionToken>::type,+ typename detail::as_tuple_signature<Signatures>::type...>(+ init_wrapper<typename decay<Initiation>::type>(+ ASIO_MOVE_CAST(Initiation)(initiation)),+ token.token_, ASIO_MOVE_CAST(Args)(args)...);+ }+};++#if defined(ASIO_MSVC)++// Workaround for MSVC internal compiler error.++template <typename CompletionToken, typename Signature>+struct async_result<as_tuple_t<CompletionToken>, Signature>+ : async_result<CompletionToken,+ typename detail::as_tuple_signature<Signature>::type>+{+ template <typename Initiation>+ struct init_wrapper+ {+ init_wrapper(Initiation init)+ : initiation_(ASIO_MOVE_CAST(Initiation)(init))+ {+ }++ template <typename Handler, typename... Args>+ void operator()(+ ASIO_MOVE_ARG(Handler) handler,+ ASIO_MOVE_ARG(Args)... args)+ {+ ASIO_MOVE_CAST(Initiation)(initiation_)(+ detail::as_tuple_handler<+ typename decay<Handler>::type>(+ ASIO_MOVE_CAST(Handler)(handler)),+ ASIO_MOVE_CAST(Args)(args)...);+ }++ Initiation initiation_;+ };++ template <typename Initiation, typename RawCompletionToken, typename... Args>+ static ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX(CompletionToken,+ typename detail::as_tuple_signature<Signatures>::type...)+ initiate(+ ASIO_MOVE_ARG(Initiation) initiation,+ ASIO_MOVE_ARG(RawCompletionToken) token,+ ASIO_MOVE_ARG(Args)... args)+ ASIO_INITFN_AUTO_RESULT_TYPE_SUFFIX((+ async_initiate<+ typename conditional<+ is_const<typename remove_reference<RawCompletionToken>::type>::value,+ const CompletionToken, CompletionToken>::type,+ typename detail::as_tuple_signature<Signature>::type>(+ init_wrapper<typename decay<Initiation>::type>(+ ASIO_MOVE_CAST(Initiation)(initiation)),+ token.token_, ASIO_MOVE_CAST(Args)(args)...)))+ {+ return async_initiate<+ typename conditional<+ is_const<typename remove_reference<RawCompletionToken>::type>::value,+ const CompletionToken, CompletionToken>::type,+ typename detail::as_tuple_signature<Signature>::type>(+ init_wrapper<typename decay<Initiation>::type>(+ ASIO_MOVE_CAST(Initiation)(initiation)),+ token.token_, ASIO_MOVE_CAST(Args)(args)...);+ }+};++#endif // defined(ASIO_MSVC)++template <template <typename, typename> class Associator,+ typename Handler, typename DefaultCandidate>+struct associator<Associator,+ detail::as_tuple_handler<Handler>, DefaultCandidate>+ : Associator<Handler, DefaultCandidate>+{+ static typename Associator<Handler, DefaultCandidate>::type+ get(const detail::as_tuple_handler<Handler>& h) ASIO_NOEXCEPT+ {+ return Associator<Handler, DefaultCandidate>::get(h.handler_);+ }++ static ASIO_AUTO_RETURN_TYPE_PREFIX2(+ typename Associator<Handler, DefaultCandidate>::type)+ get(const detail::as_tuple_handler<Handler>& h,+ const DefaultCandidate& c) ASIO_NOEXCEPT+ ASIO_AUTO_RETURN_TYPE_SUFFIX((+ Associator<Handler, DefaultCandidate>::get(h.handler_, c)))+ {+ return Associator<Handler, DefaultCandidate>::get(h.handler_, c);+ }+};++#endif // !defined(GENERATING_DOCUMENTATION)++} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // ASIO_IMPL_AS_TUPLE_HPP
link/modules/asio-standalone/asio/include/asio/impl/awaitable.hpp view
@@ -2,7 +2,7 @@ // impl/awaitable.hpp // ~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -19,19 +19,32 @@ #include <exception> #include <new> #include <tuple>-#include <utility>+#include "asio/cancellation_signal.hpp"+#include "asio/cancellation_state.hpp" #include "asio/detail/thread_context.hpp" #include "asio/detail/thread_info_base.hpp"+#include "asio/detail/throw_error.hpp" #include "asio/detail/type_traits.hpp"+#include "asio/error.hpp" #include "asio/post.hpp" #include "asio/system_error.hpp" #include "asio/this_coro.hpp" +#if defined(ASIO_ENABLE_HANDLER_TRACKING)+# if defined(ASIO_HAS_SOURCE_LOCATION)+# include "asio/detail/source_location.hpp"+# endif // defined(ASIO_HAS_SOURCE_LOCATION)+#endif // defined(ASIO_ENABLE_HANDLER_TRACKING)+ #include "asio/detail/push_options.hpp" namespace asio { namespace detail { +struct awaitable_thread_has_context_switched {};+template <typename, typename> class awaitable_async_op_handler;+template <typename, typename, typename> class awaitable_async_op;+ // An awaitable_thread represents a thread-of-execution that is composed of one // or more "stack frames", with each frame represented by an awaitable_frame. // All execution occurs in the context of the awaitable_thread's executor. An@@ -77,7 +90,7 @@ { return asio::detail::thread_info_base::allocate( asio::detail::thread_info_base::awaitable_frame_tag(),- asio::detail::thread_context::thread_call_stack::top(),+ asio::detail::thread_context::top_of_thread_call_stack(), size); } @@ -85,7 +98,7 @@ { asio::detail::thread_info_base::deallocate( asio::detail::thread_info_base::awaitable_frame_tag(),- asio::detail::thread_context::thread_call_stack::top(),+ asio::detail::thread_context::top_of_thread_call_stack(), pointer, size); } #endif // !defined(ASIO_DISABLE_AWAITABLE_FRAME_RECYCLING)@@ -111,7 +124,7 @@ void await_suspend(coroutine_handle<void>) noexcept {- this_->pop_frame();+ this->this_->pop_frame(); } void await_resume() const noexcept@@ -146,12 +159,45 @@ } } + void clear_cancellation_slot()+ {+ this->attached_thread_->entry_point()->cancellation_state_.slot().clear();+ }+ template <typename T> auto await_transform(awaitable<T, Executor> a) const {+ if (attached_thread_->entry_point()->throw_if_cancelled_)+ if (!!attached_thread_->get_cancellation_state().cancelled())+ throw_error(asio::error::operation_aborted, "co_await"); return a; } + template <typename Op>+ auto await_transform(Op&& op,+ typename constraint<is_async_operation<Op>::value>::type = 0+#if defined(ASIO_ENABLE_HANDLER_TRACKING)+# if defined(ASIO_HAS_SOURCE_LOCATION)+ , detail::source_location location = detail::source_location::current()+# endif // defined(ASIO_HAS_SOURCE_LOCATION)+#endif // defined(ASIO_ENABLE_HANDLER_TRACKING)+ )+ {+ if (attached_thread_->entry_point()->throw_if_cancelled_)+ if (!!attached_thread_->get_cancellation_state().cancelled())+ throw_error(asio::error::operation_aborted, "co_await");++ return awaitable_async_op<typename completion_signature_of<Op>::type,+ typename decay<Op>::type, Executor>{+ std::forward<Op>(op), this+#if defined(ASIO_ENABLE_HANDLER_TRACKING)+# if defined(ASIO_HAS_SOURCE_LOCATION)+ , location+# endif // defined(ASIO_HAS_SOURCE_LOCATION)+#endif // defined(ASIO_ENABLE_HANDLER_TRACKING)+ };+ }+ // This await transformation obtains the associated executor of the thread of // execution. auto await_transform(this_coro::executor_t) noexcept@@ -178,6 +224,175 @@ return result{this}; } + // This await transformation obtains the associated cancellation state of the+ // thread of execution.+ auto await_transform(this_coro::cancellation_state_t) noexcept+ {+ struct result+ {+ awaitable_frame_base* this_;++ bool await_ready() const noexcept+ {+ return true;+ }++ void await_suspend(coroutine_handle<void>) noexcept+ {+ }++ auto await_resume() const noexcept+ {+ return this_->attached_thread_->get_cancellation_state();+ }+ };++ return result{this};+ }++ // This await transformation resets the associated cancellation state.+ auto await_transform(this_coro::reset_cancellation_state_0_t) noexcept+ {+ struct result+ {+ awaitable_frame_base* this_;++ bool await_ready() const noexcept+ {+ return true;+ }++ void await_suspend(coroutine_handle<void>) noexcept+ {+ }++ auto await_resume() const+ {+ return this_->attached_thread_->reset_cancellation_state();+ }+ };++ return result{this};+ }++ // This await transformation resets the associated cancellation state.+ template <typename Filter>+ auto await_transform(+ this_coro::reset_cancellation_state_1_t<Filter> reset) noexcept+ {+ struct result+ {+ awaitable_frame_base* this_;+ Filter filter_;++ bool await_ready() const noexcept+ {+ return true;+ }++ void await_suspend(coroutine_handle<void>) noexcept+ {+ }++ auto await_resume()+ {+ return this_->attached_thread_->reset_cancellation_state(+ ASIO_MOVE_CAST(Filter)(filter_));+ }+ };++ return result{this, ASIO_MOVE_CAST(Filter)(reset.filter)};+ }++ // This await transformation resets the associated cancellation state.+ template <typename InFilter, typename OutFilter>+ auto await_transform(+ this_coro::reset_cancellation_state_2_t<InFilter, OutFilter> reset)+ noexcept+ {+ struct result+ {+ awaitable_frame_base* this_;+ InFilter in_filter_;+ OutFilter out_filter_;++ bool await_ready() const noexcept+ {+ return true;+ }++ void await_suspend(coroutine_handle<void>) noexcept+ {+ }++ auto await_resume()+ {+ return this_->attached_thread_->reset_cancellation_state(+ ASIO_MOVE_CAST(InFilter)(in_filter_),+ ASIO_MOVE_CAST(OutFilter)(out_filter_));+ }+ };++ return result{this,+ ASIO_MOVE_CAST(InFilter)(reset.in_filter),+ ASIO_MOVE_CAST(OutFilter)(reset.out_filter)};+ }++ // This await transformation determines whether cancellation is propagated as+ // an exception.+ auto await_transform(this_coro::throw_if_cancelled_0_t)+ noexcept+ {+ struct result+ {+ awaitable_frame_base* this_;++ bool await_ready() const noexcept+ {+ return true;+ }++ void await_suspend(coroutine_handle<void>) noexcept+ {+ }++ auto await_resume()+ {+ return this_->attached_thread_->throw_if_cancelled();+ }+ };++ return result{this};+ }++ // This await transformation sets whether cancellation is propagated as an+ // exception.+ auto await_transform(this_coro::throw_if_cancelled_1_t throw_if_cancelled)+ noexcept+ {+ struct result+ {+ awaitable_frame_base* this_;+ bool value_;++ bool await_ready() const noexcept+ {+ return true;+ }++ void await_suspend(coroutine_handle<void>) noexcept+ {+ }++ auto await_resume()+ {+ this_->attached_thread_->throw_if_cancelled(value_);+ }+ };++ return result{this, throw_if_cancelled.value};+ }+ // This await transformation is used to run an async operation's initiation // function object after the coroutine has been suspended. This ensures that // immediate resumption of the coroutine in another thread does not cause a@@ -189,7 +404,7 @@ typename result_of<Function(awaitable_frame_base*)>::type, awaitable_thread<Executor>* >::value- >::type* = 0)+ >::type* = nullptr) { struct result {@@ -203,7 +418,12 @@ void await_suspend(coroutine_handle<void>) noexcept {- function_(this_);+ this_->after_suspend(+ [](void* arg)+ {+ result* r = static_cast<result*>(arg);+ r->function_(r->this_);+ }, this); } void await_resume() const noexcept@@ -214,6 +434,31 @@ return result{std::move(f), this}; } + // Access the awaitable thread's has_context_switched_ flag.+ auto await_transform(detail::awaitable_thread_has_context_switched) noexcept+ {+ struct result+ {+ awaitable_frame_base* this_;++ bool await_ready() const noexcept+ {+ return true;+ }++ void await_suspend(coroutine_handle<void>) noexcept+ {+ }++ bool& await_resume() const noexcept+ {+ return this_->attached_thread_->entry_point()->has_context_switched_;+ }+ };++ return result{this};+ }+ void attach_thread(awaitable_thread<Executor>* handler) noexcept { attached_thread_ = handler;@@ -221,6 +466,7 @@ awaitable_thread<Executor>* detach_thread() noexcept {+ attached_thread_->entry_point()->has_context_switched_ = true; return std::exchange(attached_thread_, nullptr); } @@ -228,7 +474,7 @@ { caller_ = caller; attached_thread_ = caller_->attached_thread_;- attached_thread_->top_of_stack_ = this;+ attached_thread_->entry_point()->top_of_stack_ = this; caller_->attached_thread_ = nullptr; } @@ -236,16 +482,32 @@ { if (caller_) caller_->attached_thread_ = attached_thread_;- attached_thread_->top_of_stack_ = caller_;+ attached_thread_->entry_point()->top_of_stack_ = caller_; attached_thread_ = nullptr; caller_ = nullptr; } + struct resume_context+ {+ void (*after_suspend_fn_)(void*) = nullptr;+ void *after_suspend_arg_ = nullptr;+ };+ void resume() {+ resume_context context;+ resume_context_ = &context; coro_.resume();+ if (context.after_suspend_fn_)+ context.after_suspend_fn_(context.after_suspend_arg_); } + void after_suspend(void (*fn)(void*), void* arg)+ {+ resume_context_->after_suspend_fn_ = fn;+ resume_context_->after_suspend_arg_ = arg;+ }+ void destroy() { coro_.destroy();@@ -256,6 +518,7 @@ awaitable_thread<Executor>* attached_thread_ = nullptr; awaitable_frame_base<Executor>* caller_ = nullptr; std::exception_ptr pending_exception_ = nullptr;+ resume_context* resume_context_ = nullptr; }; template <typename T, typename Executor>@@ -331,25 +594,88 @@ } }; +struct awaitable_thread_entry_point {};+ template <typename Executor>+class awaitable_frame<awaitable_thread_entry_point, Executor>+ : public awaitable_frame_base<Executor>+{+public:+ awaitable_frame()+ : top_of_stack_(0),+ has_executor_(false),+ has_context_switched_(false),+ throw_if_cancelled_(true)+ {+ }++ ~awaitable_frame()+ {+ if (has_executor_)+ u_.executor_.~Executor();+ }++ awaitable<awaitable_thread_entry_point, Executor> get_return_object()+ {+ this->coro_ = coroutine_handle<awaitable_frame>::from_promise(*this);+ return awaitable<awaitable_thread_entry_point, Executor>(this);+ };++ void return_void()+ {+ }++ void get()+ {+ this->caller_ = nullptr;+ this->rethrow_exception();+ }++private:+ template <typename> friend class awaitable_frame_base;+ template <typename, typename> friend class awaitable_async_op_handler;+ template <typename, typename> friend class awaitable_handler_base;+ template <typename> friend class awaitable_thread;++ union u+ {+ u() {}+ ~u() {}+ char c_;+ Executor executor_;+ } u_;++ awaitable_frame_base<Executor>* top_of_stack_;+ asio::cancellation_slot parent_cancellation_slot_;+ asio::cancellation_state cancellation_state_;+ bool has_executor_;+ bool has_context_switched_;+ bool throw_if_cancelled_;+};++template <typename Executor> class awaitable_thread { public: typedef Executor executor_type;+ typedef cancellation_slot cancellation_slot_type; // Construct from the entry point of a new thread of execution.- awaitable_thread(awaitable<void, Executor> p, const Executor& ex)- : bottom_of_stack_(std::move(p)),- top_of_stack_(bottom_of_stack_.frame_),- executor_(ex)+ awaitable_thread(awaitable<awaitable_thread_entry_point, Executor> p,+ const Executor& ex, cancellation_slot parent_cancel_slot,+ cancellation_state cancel_state)+ : bottom_of_stack_(std::move(p)) {+ bottom_of_stack_.frame_->top_of_stack_ = bottom_of_stack_.frame_;+ new (&bottom_of_stack_.frame_->u_.executor_) Executor(ex);+ bottom_of_stack_.frame_->has_executor_ = true;+ bottom_of_stack_.frame_->parent_cancellation_slot_ = parent_cancel_slot;+ bottom_of_stack_.frame_->cancellation_state_ = cancel_state; } // Transfer ownership from another awaitable_thread. awaitable_thread(awaitable_thread&& other) noexcept- : bottom_of_stack_(std::move(other.bottom_of_stack_)),- top_of_stack_(std::exchange(other.top_of_stack_, nullptr)),- executor_(std::move(other.executor_))+ : bottom_of_stack_(std::move(other.bottom_of_stack_)) { } @@ -360,23 +686,74 @@ if (bottom_of_stack_.valid()) { // Coroutine "stack unwinding" must be performed through the executor.- (post)(executor_,+ auto* bottom_frame = bottom_of_stack_.frame_;+ (post)(bottom_frame->u_.executor_, [a = std::move(bottom_of_stack_)]() mutable {- awaitable<void, Executor>(std::move(a));+ (void)awaitable<awaitable_thread_entry_point, Executor>(+ std::move(a)); }); } } + awaitable_frame<awaitable_thread_entry_point, Executor>* entry_point()+ {+ return bottom_of_stack_.frame_;+ }+ executor_type get_executor() const noexcept {- return executor_;+ return bottom_of_stack_.frame_->u_.executor_; } + cancellation_state get_cancellation_state() const noexcept+ {+ return bottom_of_stack_.frame_->cancellation_state_;+ }++ void reset_cancellation_state()+ {+ bottom_of_stack_.frame_->cancellation_state_ =+ cancellation_state(bottom_of_stack_.frame_->parent_cancellation_slot_);+ }++ template <typename Filter>+ void reset_cancellation_state(ASIO_MOVE_ARG(Filter) filter)+ {+ bottom_of_stack_.frame_->cancellation_state_ =+ cancellation_state(bottom_of_stack_.frame_->parent_cancellation_slot_,+ ASIO_MOVE_CAST(Filter)(filter));+ }++ template <typename InFilter, typename OutFilter>+ void reset_cancellation_state(ASIO_MOVE_ARG(InFilter) in_filter,+ ASIO_MOVE_ARG(OutFilter) out_filter)+ {+ bottom_of_stack_.frame_->cancellation_state_ =+ cancellation_state(bottom_of_stack_.frame_->parent_cancellation_slot_,+ ASIO_MOVE_CAST(InFilter)(in_filter),+ ASIO_MOVE_CAST(OutFilter)(out_filter));+ }++ bool throw_if_cancelled() const+ {+ return bottom_of_stack_.frame_->throw_if_cancelled_;+ }++ void throw_if_cancelled(bool value)+ {+ bottom_of_stack_.frame_->throw_if_cancelled_ = value;+ }++ cancellation_slot_type get_cancellation_slot() const noexcept+ {+ return bottom_of_stack_.frame_->cancellation_state_.slot();+ }+ // Launch a new thread of execution. void launch() {- top_of_stack_->attach_thread(this);+ bottom_of_stack_.frame_->top_of_stack_->attach_thread(this); pump(); } @@ -387,17 +764,399 @@ // has been transferred to another resumable_thread object. void pump() {- do top_of_stack_->resume(); while (top_of_stack_);- if (bottom_of_stack_.valid())+ do+ bottom_of_stack_.frame_->top_of_stack_->resume();+ while (bottom_of_stack_.frame_ && bottom_of_stack_.frame_->top_of_stack_);++ if (bottom_of_stack_.frame_) {- awaitable<void, Executor> a(std::move(bottom_of_stack_));+ awaitable<awaitable_thread_entry_point, Executor> a(+ std::move(bottom_of_stack_)); a.frame_->rethrow_exception(); } } - awaitable<void, Executor> bottom_of_stack_;- awaitable_frame_base<Executor>* top_of_stack_;- executor_type executor_;+ awaitable<awaitable_thread_entry_point, Executor> bottom_of_stack_;+};++template <typename Signature, typename Executor>+class awaitable_async_op_handler;++template <typename R, typename Executor>+class awaitable_async_op_handler<R(), Executor>+ : public awaitable_thread<Executor>+{+public:+ struct result_type {};++ awaitable_async_op_handler(+ awaitable_thread<Executor>* h, result_type&)+ : awaitable_thread<Executor>(std::move(*h))+ {+ }++ void operator()()+ {+ this->entry_point()->top_of_stack_->attach_thread(this);+ this->entry_point()->top_of_stack_->clear_cancellation_slot();+ this->pump();+ }++ static void resume(result_type&)+ {+ }+};++template <typename R, typename Executor>+class awaitable_async_op_handler<R(asio::error_code), Executor>+ : public awaitable_thread<Executor>+{+public:+ typedef asio::error_code* result_type;++ awaitable_async_op_handler(+ awaitable_thread<Executor>* h, result_type& result)+ : awaitable_thread<Executor>(std::move(*h)),+ result_(result)+ {+ }++ void operator()(asio::error_code ec)+ {+ result_ = &ec;+ this->entry_point()->top_of_stack_->attach_thread(this);+ this->entry_point()->top_of_stack_->clear_cancellation_slot();+ this->pump();+ }++ static void resume(result_type& result)+ {+ throw_error(*result);+ }++private:+ result_type& result_;+};++template <typename R, typename Executor>+class awaitable_async_op_handler<R(std::exception_ptr), Executor>+ : public awaitable_thread<Executor>+{+public:+ typedef std::exception_ptr* result_type;++ awaitable_async_op_handler(+ awaitable_thread<Executor>* h, result_type& result)+ : awaitable_thread<Executor>(std::move(*h)),+ result_(result)+ {+ }++ void operator()(std::exception_ptr ex)+ {+ result_ = &ex;+ this->entry_point()->top_of_stack_->attach_thread(this);+ this->entry_point()->top_of_stack_->clear_cancellation_slot();+ this->pump();+ }++ static void resume(result_type& result)+ {+ if (*result)+ {+ std::exception_ptr ex = std::exchange(*result, nullptr);+ std::rethrow_exception(ex);+ }+ }++private:+ result_type& result_;+};++template <typename R, typename T, typename Executor>+class awaitable_async_op_handler<R(T), Executor>+ : public awaitable_thread<Executor>+{+public:+ typedef T* result_type;++ awaitable_async_op_handler(+ awaitable_thread<Executor>* h, result_type& result)+ : awaitable_thread<Executor>(std::move(*h)),+ result_(result)+ {+ }++ void operator()(T result)+ {+ result_ = &result;+ this->entry_point()->top_of_stack_->attach_thread(this);+ this->entry_point()->top_of_stack_->clear_cancellation_slot();+ this->pump();+ }++ static T resume(result_type& result)+ {+ return std::move(*result);+ }++private:+ result_type& result_;+};++template <typename R, typename T, typename Executor>+class awaitable_async_op_handler<R(asio::error_code, T), Executor>+ : public awaitable_thread<Executor>+{+public:+ struct result_type+ {+ asio::error_code* ec_;+ T* value_;+ };++ awaitable_async_op_handler(+ awaitable_thread<Executor>* h, result_type& result)+ : awaitable_thread<Executor>(std::move(*h)),+ result_(result)+ {+ }++ void operator()(asio::error_code ec, T value)+ {+ result_.ec_ = &ec;+ result_.value_ = &value;+ this->entry_point()->top_of_stack_->attach_thread(this);+ this->entry_point()->top_of_stack_->clear_cancellation_slot();+ this->pump();+ }++ static T resume(result_type& result)+ {+ throw_error(*result.ec_);+ return std::move(*result.value_);+ }++private:+ result_type& result_;+};++template <typename R, typename T, typename Executor>+class awaitable_async_op_handler<R(std::exception_ptr, T), Executor>+ : public awaitable_thread<Executor>+{+public:+ struct result_type+ {+ std::exception_ptr* ex_;+ T* value_;+ };++ awaitable_async_op_handler(+ awaitable_thread<Executor>* h, result_type& result)+ : awaitable_thread<Executor>(std::move(*h)),+ result_(result)+ {+ }++ void operator()(std::exception_ptr ex, T value)+ {+ result_.ex_ = &ex;+ result_.value_ = &value;+ this->entry_point()->top_of_stack_->attach_thread(this);+ this->entry_point()->top_of_stack_->clear_cancellation_slot();+ this->pump();+ }++ static T resume(result_type& result)+ {+ if (*result.ex_)+ {+ std::exception_ptr ex = std::exchange(*result.ex_, nullptr);+ std::rethrow_exception(ex);+ }+ return std::move(*result.value_);+ }++private:+ result_type& result_;+};++template <typename R, typename... Ts, typename Executor>+class awaitable_async_op_handler<R(Ts...), Executor>+ : public awaitable_thread<Executor>+{+public:+ typedef std::tuple<Ts...>* result_type;++ awaitable_async_op_handler(+ awaitable_thread<Executor>* h, result_type& result)+ : awaitable_thread<Executor>(std::move(*h)),+ result_(result)+ {+ }++ template <typename... Args>+ void operator()(Args&&... args)+ {+ std::tuple<Ts...> result(std::forward<Args>(args)...);+ result_ = &result;+ this->entry_point()->top_of_stack_->attach_thread(this);+ this->entry_point()->top_of_stack_->clear_cancellation_slot();+ this->pump();+ }++ static std::tuple<Ts...> resume(result_type& result)+ {+ return std::move(*result);+ }++private:+ result_type& result_;+};++template <typename R, typename... Ts, typename Executor>+class awaitable_async_op_handler<R(asio::error_code, Ts...), Executor>+ : public awaitable_thread<Executor>+{+public:+ struct result_type+ {+ asio::error_code* ec_;+ std::tuple<Ts...>* value_;+ };++ awaitable_async_op_handler(+ awaitable_thread<Executor>* h, result_type& result)+ : awaitable_thread<Executor>(std::move(*h)),+ result_(result)+ {+ }++ template <typename... Args>+ void operator()(asio::error_code ec, Args&&... args)+ {+ result_.ec_ = &ec;+ std::tuple<Ts...> value(std::forward<Args>(args)...);+ result_.value_ = &value;+ this->entry_point()->top_of_stack_->attach_thread(this);+ this->entry_point()->top_of_stack_->clear_cancellation_slot();+ this->pump();+ }++ static std::tuple<Ts...> resume(result_type& result)+ {+ throw_error(*result.ec_);+ return std::move(*result.value_);+ }++private:+ result_type& result_;+};++template <typename R, typename... Ts, typename Executor>+class awaitable_async_op_handler<R(std::exception_ptr, Ts...), Executor>+ : public awaitable_thread<Executor>+{+public:+ struct result_type+ {+ std::exception_ptr* ex_;+ std::tuple<Ts...>* value_;+ };++ awaitable_async_op_handler(+ awaitable_thread<Executor>* h, result_type& result)+ : awaitable_thread<Executor>(std::move(*h)),+ result_(result)+ {+ }++ template <typename... Args>+ void operator()(std::exception_ptr ex, Args&&... args)+ {+ result_.ex_ = &ex;+ std::tuple<Ts...> value(std::forward<Args>(args)...);+ result_.value_ = &value;+ this->entry_point()->top_of_stack_->attach_thread(this);+ this->entry_point()->top_of_stack_->clear_cancellation_slot();+ this->pump();+ }++ static std::tuple<Ts...> resume(result_type& result)+ {+ if (*result.ex_)+ {+ std::exception_ptr ex = std::exchange(*result.ex_, nullptr);+ std::rethrow_exception(ex);+ }+ return std::move(*result.value_);+ }++private:+ result_type& result_;+};++template <typename Signature, typename Op, typename Executor>+class awaitable_async_op+{+public:+ typedef awaitable_async_op_handler<Signature, Executor> handler_type;++ awaitable_async_op(Op&& o, awaitable_frame_base<Executor>* frame+#if defined(ASIO_ENABLE_HANDLER_TRACKING)+# if defined(ASIO_HAS_SOURCE_LOCATION)+ , const detail::source_location& location+# endif // defined(ASIO_HAS_SOURCE_LOCATION)+#endif // defined(ASIO_ENABLE_HANDLER_TRACKING)+ )+ : op_(std::forward<Op>(o)),+ frame_(frame),+ result_()+#if defined(ASIO_ENABLE_HANDLER_TRACKING)+# if defined(ASIO_HAS_SOURCE_LOCATION)+ , location_(location)+# endif // defined(ASIO_HAS_SOURCE_LOCATION)+#endif // defined(ASIO_ENABLE_HANDLER_TRACKING)+ {+ }++ bool await_ready() const noexcept+ {+ return false;+ }++ void await_suspend(coroutine_handle<void>)+ {+ frame_->after_suspend(+ [](void* arg)+ {+ awaitable_async_op* self = static_cast<awaitable_async_op*>(arg);+#if defined(ASIO_ENABLE_HANDLER_TRACKING)+# if defined(ASIO_HAS_SOURCE_LOCATION)+ ASIO_HANDLER_LOCATION((self->location_.file_name(),+ self->location_.line(), self->location_.function_name()));+# endif // defined(ASIO_HAS_SOURCE_LOCATION)+#endif // defined(ASIO_ENABLE_HANDLER_TRACKING)+ std::forward<Op&&>(self->op_)(+ handler_type(self->frame_->detach_thread(), self->result_));+ }, this);+ }++ auto await_resume()+ {+ return handler_type::resume(result_);+ }++private:+ Op&& op_;+ awaitable_frame_base<Executor>* frame_;+ typename handler_type::result_type result_;+#if defined(ASIO_ENABLE_HANDLER_TRACKING)+# if defined(ASIO_HAS_SOURCE_LOCATION)+ detail::source_location location_;+# endif // defined(ASIO_HAS_SOURCE_LOCATION)+#endif // defined(ASIO_ENABLE_HANDLER_TRACKING) }; } // namespace detail
link/modules/asio-standalone/asio/include/asio/impl/buffered_read_stream.hpp view
@@ -2,7 +2,7 @@ // impl/buffered_read_stream.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -15,8 +15,7 @@ # pragma once #endif // defined(_MSC_VER) && (_MSC_VER >= 1200) -#include "asio/associated_allocator.hpp"-#include "asio/associated_executor.hpp"+#include "asio/associator.hpp" #include "asio/detail/handler_alloc_helpers.hpp" #include "asio/detail/handler_cont_helpers.hpp" #include "asio/detail/handler_invoke_helpers.hpp"@@ -91,7 +90,7 @@ const std::size_t bytes_transferred) { storage_.resize(previous_size_ + bytes_transferred);- handler_(ec, bytes_transferred);+ ASIO_MOVE_OR_LVALUE(ReadHandler)(handler_)(ec, bytes_transferred); } //private:@@ -202,29 +201,27 @@ #if !defined(GENERATING_DOCUMENTATION) -template <typename ReadHandler, typename Allocator>-struct associated_allocator<- detail::buffered_fill_handler<ReadHandler>, Allocator>+template <template <typename, typename> class Associator,+ typename ReadHandler, typename DefaultCandidate>+struct associator<Associator,+ detail::buffered_fill_handler<ReadHandler>,+ DefaultCandidate>+ : Associator<ReadHandler, DefaultCandidate> {- typedef typename associated_allocator<ReadHandler, Allocator>::type type;-- static type get(const detail::buffered_fill_handler<ReadHandler>& h,- const Allocator& a = Allocator()) ASIO_NOEXCEPT+ static typename Associator<ReadHandler, DefaultCandidate>::type+ get(const detail::buffered_fill_handler<ReadHandler>& h) ASIO_NOEXCEPT {- return associated_allocator<ReadHandler, Allocator>::get(h.handler_, a);+ return Associator<ReadHandler, DefaultCandidate>::get(h.handler_); }-}; -template <typename ReadHandler, typename Executor>-struct associated_executor<- detail::buffered_fill_handler<ReadHandler>, Executor>-{- typedef typename associated_executor<ReadHandler, Executor>::type type;-- static type get(const detail::buffered_fill_handler<ReadHandler>& h,- const Executor& ex = Executor()) ASIO_NOEXCEPT+ static ASIO_AUTO_RETURN_TYPE_PREFIX2(+ typename Associator<ReadHandler, DefaultCandidate>::type)+ get(const detail::buffered_fill_handler<ReadHandler>& h,+ const DefaultCandidate& c) ASIO_NOEXCEPT+ ASIO_AUTO_RETURN_TYPE_SUFFIX((+ Associator<ReadHandler, DefaultCandidate>::get(h.handler_, c))) {- return associated_executor<ReadHandler, Executor>::get(h.handler_, ex);+ return Associator<ReadHandler, DefaultCandidate>::get(h.handler_, c); } }; @@ -234,10 +231,15 @@ template < ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code, std::size_t)) ReadHandler>-ASIO_INITFN_AUTO_RESULT_TYPE(ReadHandler,+ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX(ReadHandler, void (asio::error_code, std::size_t)) buffered_read_stream<Stream>::async_fill( ASIO_MOVE_ARG(ReadHandler) handler)+ ASIO_INITFN_AUTO_RESULT_TYPE_SUFFIX((+ async_initiate<ReadHandler,+ void (asio::error_code, std::size_t)>(+ declval<detail::initiate_async_buffered_fill<Stream> >(),+ handler, declval<detail::buffered_stream_storage*>()))) { return async_initiate<ReadHandler, void (asio::error_code, std::size_t)>(@@ -312,14 +314,14 @@ if (ec || storage_.empty()) { const std::size_t length = 0;- handler_(ec, length);+ ASIO_MOVE_OR_LVALUE(ReadHandler)(handler_)(ec, length); } else { const std::size_t bytes_copied = asio::buffer_copy( buffers_, storage_.data(), storage_.size()); storage_.consume(bytes_copied);- handler_(ec, bytes_copied);+ ASIO_MOVE_OR_LVALUE(ReadHandler)(handler_)(ec, bytes_copied); } } @@ -447,37 +449,30 @@ #if !defined(GENERATING_DOCUMENTATION) -template <typename MutableBufferSequence,- typename ReadHandler, typename Allocator>-struct associated_allocator<+template <template <typename, typename> class Associator,+ typename MutableBufferSequence, typename ReadHandler,+ typename DefaultCandidate>+struct associator<Associator, detail::buffered_read_some_handler<MutableBufferSequence, ReadHandler>,- Allocator>+ DefaultCandidate>+ : Associator<ReadHandler, DefaultCandidate> {- typedef typename associated_allocator<ReadHandler, Allocator>::type type;-- static type get(- const detail::buffered_read_some_handler<- MutableBufferSequence, ReadHandler>& h,- const Allocator& a = Allocator()) ASIO_NOEXCEPT+ static typename Associator<ReadHandler, DefaultCandidate>::type+ get(const detail::buffered_read_some_handler<+ MutableBufferSequence, ReadHandler>& h) ASIO_NOEXCEPT {- return associated_allocator<ReadHandler, Allocator>::get(h.handler_, a);+ return Associator<ReadHandler, DefaultCandidate>::get(h.handler_); }-}; -template <typename MutableBufferSequence,- typename ReadHandler, typename Executor>-struct associated_executor<- detail::buffered_read_some_handler<MutableBufferSequence, ReadHandler>,- Executor>-{- typedef typename associated_executor<ReadHandler, Executor>::type type;-- static type get(- const detail::buffered_read_some_handler<+ static ASIO_AUTO_RETURN_TYPE_PREFIX2(+ typename Associator<ReadHandler, DefaultCandidate>::type)+ get(const detail::buffered_read_some_handler< MutableBufferSequence, ReadHandler>& h,- const Executor& ex = Executor()) ASIO_NOEXCEPT+ const DefaultCandidate& c) ASIO_NOEXCEPT+ ASIO_AUTO_RETURN_TYPE_SUFFIX((+ Associator<ReadHandler, DefaultCandidate>::get(h.handler_, c))) {- return associated_executor<ReadHandler, Executor>::get(h.handler_, ex);+ return Associator<ReadHandler, DefaultCandidate>::get(h.handler_, c); } }; @@ -487,11 +482,16 @@ template <typename MutableBufferSequence, ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code, std::size_t)) ReadHandler>-ASIO_INITFN_AUTO_RESULT_TYPE(ReadHandler,+ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX(ReadHandler, void (asio::error_code, std::size_t)) buffered_read_stream<Stream>::async_read_some( const MutableBufferSequence& buffers, ASIO_MOVE_ARG(ReadHandler) handler)+ ASIO_INITFN_AUTO_RESULT_TYPE_SUFFIX((+ async_initiate<ReadHandler,+ void (asio::error_code, std::size_t)>(+ declval<detail::initiate_async_buffered_read_some<Stream> >(),+ handler, declval<detail::buffered_stream_storage*>(), buffers))) { return async_initiate<ReadHandler, void (asio::error_code, std::size_t)>(
link/modules/asio-standalone/asio/include/asio/impl/buffered_write_stream.hpp view
@@ -2,7 +2,7 @@ // impl/buffered_write_stream.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -15,8 +15,7 @@ # pragma once #endif // defined(_MSC_VER) && (_MSC_VER >= 1200) -#include "asio/associated_allocator.hpp"-#include "asio/associated_executor.hpp"+#include "asio/associator.hpp" #include "asio/detail/handler_alloc_helpers.hpp" #include "asio/detail/handler_cont_helpers.hpp" #include "asio/detail/handler_invoke_helpers.hpp"@@ -77,7 +76,7 @@ const std::size_t bytes_written) { storage_.consume(bytes_written);- handler_(ec, bytes_written);+ ASIO_MOVE_OR_LVALUE(WriteHandler)(handler_)(ec, bytes_written); } //private:@@ -182,29 +181,27 @@ #if !defined(GENERATING_DOCUMENTATION) -template <typename WriteHandler, typename Allocator>-struct associated_allocator<- detail::buffered_flush_handler<WriteHandler>, Allocator>+template <template <typename, typename> class Associator,+ typename WriteHandler, typename DefaultCandidate>+struct associator<Associator,+ detail::buffered_flush_handler<WriteHandler>,+ DefaultCandidate>+ : Associator<WriteHandler, DefaultCandidate> {- typedef typename associated_allocator<WriteHandler, Allocator>::type type;-- static type get(const detail::buffered_flush_handler<WriteHandler>& h,- const Allocator& a = Allocator()) ASIO_NOEXCEPT+ static typename Associator<WriteHandler, DefaultCandidate>::type+ get(const detail::buffered_flush_handler<WriteHandler>& h) ASIO_NOEXCEPT {- return associated_allocator<WriteHandler, Allocator>::get(h.handler_, a);+ return Associator<WriteHandler, DefaultCandidate>::get(h.handler_); }-}; -template <typename WriteHandler, typename Executor>-struct associated_executor<- detail::buffered_flush_handler<WriteHandler>, Executor>-{- typedef typename associated_executor<WriteHandler, Executor>::type type;-- static type get(const detail::buffered_flush_handler<WriteHandler>& h,- const Executor& ex = Executor()) ASIO_NOEXCEPT+ static ASIO_AUTO_RETURN_TYPE_PREFIX2(+ typename Associator<WriteHandler, DefaultCandidate>::type)+ get(const detail::buffered_flush_handler<WriteHandler>& h,+ const DefaultCandidate& c) ASIO_NOEXCEPT+ ASIO_AUTO_RETURN_TYPE_SUFFIX((+ Associator<WriteHandler, DefaultCandidate>::get(h.handler_, c))) {- return associated_executor<WriteHandler, Executor>::get(h.handler_, ex);+ return Associator<WriteHandler, DefaultCandidate>::get(h.handler_, c); } }; @@ -214,10 +211,15 @@ template < ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code, std::size_t)) WriteHandler>-ASIO_INITFN_AUTO_RESULT_TYPE(WriteHandler,+ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX(WriteHandler, void (asio::error_code, std::size_t)) buffered_write_stream<Stream>::async_flush( ASIO_MOVE_ARG(WriteHandler) handler)+ ASIO_INITFN_AUTO_RESULT_TYPE_SUFFIX((+ async_initiate<WriteHandler,+ void (asio::error_code, std::size_t)>(+ declval<detail::initiate_async_buffered_flush<Stream> >(),+ handler, declval<detail::buffered_stream_storage*>()))) { return async_initiate<WriteHandler, void (asio::error_code, std::size_t)>(@@ -292,7 +294,7 @@ if (ec) { const std::size_t length = 0;- handler_(ec, length);+ ASIO_MOVE_OR_LVALUE(WriteHandler)(handler_)(ec, length); } else {@@ -305,7 +307,7 @@ storage_.resize(orig_size + length); const std::size_t bytes_copied = asio::buffer_copy( storage_.data() + orig_size, buffers_, length);- handler_(ec, bytes_copied);+ ASIO_MOVE_OR_LVALUE(WriteHandler)(handler_)(ec, bytes_copied); } } @@ -433,37 +435,30 @@ #if !defined(GENERATING_DOCUMENTATION) -template <typename ConstBufferSequence,- typename WriteHandler, typename Allocator>-struct associated_allocator<+template <template <typename, typename> class Associator,+ typename ConstBufferSequence, typename WriteHandler,+ typename DefaultCandidate>+struct associator<Associator, detail::buffered_write_some_handler<ConstBufferSequence, WriteHandler>,- Allocator>+ DefaultCandidate>+ : Associator<WriteHandler, DefaultCandidate> {- typedef typename associated_allocator<WriteHandler, Allocator>::type type;-- static type get(- const detail::buffered_write_some_handler<- ConstBufferSequence, WriteHandler>& h,- const Allocator& a = Allocator()) ASIO_NOEXCEPT+ static typename Associator<WriteHandler, DefaultCandidate>::type+ get(const detail::buffered_write_some_handler<+ ConstBufferSequence, WriteHandler>& h) ASIO_NOEXCEPT {- return associated_allocator<WriteHandler, Allocator>::get(h.handler_, a);+ return Associator<WriteHandler, DefaultCandidate>::get(h.handler_); }-}; -template <typename ConstBufferSequence,- typename WriteHandler, typename Executor>-struct associated_executor<- detail::buffered_write_some_handler<ConstBufferSequence, WriteHandler>,- Executor>-{- typedef typename associated_executor<WriteHandler, Executor>::type type;-- static type get(- const detail::buffered_write_some_handler<+ static ASIO_AUTO_RETURN_TYPE_PREFIX2(+ typename Associator<WriteHandler, DefaultCandidate>::type)+ get(const detail::buffered_write_some_handler< ConstBufferSequence, WriteHandler>& h,- const Executor& ex = Executor()) ASIO_NOEXCEPT+ const DefaultCandidate& c) ASIO_NOEXCEPT+ ASIO_AUTO_RETURN_TYPE_SUFFIX((+ Associator<WriteHandler, DefaultCandidate>::get(h.handler_, c))) {- return associated_executor<WriteHandler, Executor>::get(h.handler_, ex);+ return Associator<WriteHandler, DefaultCandidate>::get(h.handler_, c); } }; @@ -473,11 +468,16 @@ template <typename ConstBufferSequence, ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code, std::size_t)) WriteHandler>-ASIO_INITFN_AUTO_RESULT_TYPE(WriteHandler,+ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX(WriteHandler, void (asio::error_code, std::size_t)) buffered_write_stream<Stream>::async_write_some( const ConstBufferSequence& buffers, ASIO_MOVE_ARG(WriteHandler) handler)+ ASIO_INITFN_AUTO_RESULT_TYPE_SUFFIX((+ async_initiate<WriteHandler,+ void (asio::error_code, std::size_t)>(+ declval<detail::initiate_async_buffered_write_some<Stream> >(),+ handler, declval<detail::buffered_stream_storage*>(), buffers))) { return async_initiate<WriteHandler, void (asio::error_code, std::size_t)>(
+ link/modules/asio-standalone/asio/include/asio/impl/cancellation_signal.ipp view
@@ -0,0 +1,96 @@+//+// impl/cancellation_signal.ipp+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com)+//+// Distributed under the Boost Software License, Version 1.0. (See accompanying+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)+//++#ifndef ASIO_IMPL_CANCELLATION_SIGNAL_IPP+#define ASIO_IMPL_CANCELLATION_SIGNAL_IPP++#if defined(_MSC_VER) && (_MSC_VER >= 1200)+# pragma once+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)++#include "asio/detail/config.hpp"+#include "asio/cancellation_signal.hpp"+#include "asio/detail/thread_context.hpp"+#include "asio/detail/thread_info_base.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {++cancellation_signal::~cancellation_signal()+{+ if (handler_)+ {+ std::pair<void*, std::size_t> mem = handler_->destroy();+ detail::thread_info_base::deallocate(+ detail::thread_info_base::cancellation_signal_tag(),+ detail::thread_context::top_of_thread_call_stack(),+ mem.first, mem.second);+ }+}++void cancellation_slot::clear()+{+ if (handler_ != 0 && *handler_ != 0)+ {+ std::pair<void*, std::size_t> mem = (*handler_)->destroy();+ detail::thread_info_base::deallocate(+ detail::thread_info_base::cancellation_signal_tag(),+ detail::thread_context::top_of_thread_call_stack(),+ mem.first, mem.second);+ *handler_ = 0;+ }+}++std::pair<void*, std::size_t> cancellation_slot::prepare_memory(+ std::size_t size, std::size_t align)+{+ assert(handler_);+ std::pair<void*, std::size_t> mem;+ if (*handler_)+ {+ mem = (*handler_)->destroy();+ *handler_ = 0;+ }+ if (size > mem.second+ || reinterpret_cast<std::size_t>(mem.first) % align != 0)+ {+ if (mem.first)+ {+ detail::thread_info_base::deallocate(+ detail::thread_info_base::cancellation_signal_tag(),+ detail::thread_context::top_of_thread_call_stack(),+ mem.first, mem.second);+ }+ mem.first = detail::thread_info_base::allocate(+ detail::thread_info_base::cancellation_signal_tag(),+ detail::thread_context::top_of_thread_call_stack(),+ size, align);+ mem.second = size;+ }+ return mem;+}++cancellation_slot::auto_delete_helper::~auto_delete_helper()+{+ if (mem.first)+ {+ detail::thread_info_base::deallocate(+ detail::thread_info_base::cancellation_signal_tag(),+ detail::thread_context::top_of_thread_call_stack(),+ mem.first, mem.second);+ }+}++} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // ASIO_IMPL_CANCELLATION_SIGNAL_IPP
link/modules/asio-standalone/asio/include/asio/impl/co_spawn.hpp view
@@ -2,7 +2,7 @@ // impl/co_spawn.hpp // ~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -16,6 +16,7 @@ #endif // defined(_MSC_VER) && (_MSC_VER >= 1200) #include "asio/detail/config.hpp"+#include "asio/associated_cancellation_slot.hpp" #include "asio/awaitable.hpp" #include "asio/dispatch.hpp" #include "asio/execution/outstanding_work.hpp"@@ -76,16 +77,18 @@ } template <typename T, typename Executor, typename F, typename Handler>-awaitable<void, Executor> co_spawn_entry_point(+awaitable<awaitable_thread_entry_point, Executor> co_spawn_entry_point( awaitable<T, Executor>*, Executor ex, F f, Handler handler) { auto spawn_work = make_co_spawn_work_guard(ex); auto handler_work = make_co_spawn_work_guard( asio::get_associated_executor(handler, ex)); - (void) co_await (post)(spawn_work.get_executor(),- use_awaitable_t<Executor>{});+ (void) co_await (dispatch)(+ use_awaitable_t<Executor>{__FILE__, __LINE__, "co_spawn_entry_point"}); + (co_await awaitable_thread_has_context_switched{}) = false;+ std::exception_ptr e = nullptr; bool done = false; try {@@ -93,36 +96,56 @@ done = true; + bool switched = (co_await awaitable_thread_has_context_switched{});+ if (!switched)+ {+ (void) co_await (post)(+ use_awaitable_t<Executor>{__FILE__,+ __LINE__, "co_spawn_entry_point"});+ }+ (dispatch)(handler_work.get_executor(), [handler = std::move(handler), t = std::move(t)]() mutable {- handler(std::exception_ptr(), std::move(t));+ std::move(handler)(std::exception_ptr(), std::move(t)); });++ co_return; } catch (...) { if (done) throw; - (dispatch)(handler_work.get_executor(),- [handler = std::move(handler), e = std::current_exception()]() mutable- {- handler(e, T());- });+ e = std::current_exception(); }++ bool switched = (co_await awaitable_thread_has_context_switched{});+ if (!switched)+ {+ (void) co_await (post)(+ use_awaitable_t<Executor>{__FILE__, __LINE__, "co_spawn_entry_point"});+ }++ (dispatch)(handler_work.get_executor(),+ [handler = std::move(handler), e]() mutable+ {+ std::move(handler)(e, T());+ }); } template <typename Executor, typename F, typename Handler>-awaitable<void, Executor> co_spawn_entry_point(+awaitable<awaitable_thread_entry_point, Executor> co_spawn_entry_point( awaitable<void, Executor>*, Executor ex, F f, Handler handler) { auto spawn_work = make_co_spawn_work_guard(ex); auto handler_work = make_co_spawn_work_guard( asio::get_associated_executor(handler, ex)); - (void) co_await (post)(spawn_work.get_executor(),+ (void) co_await (dispatch)( use_awaitable_t<Executor>{__FILE__, __LINE__, "co_spawn_entry_point"}); + (co_await awaitable_thread_has_context_switched{}) = false; std::exception_ptr e = nullptr; try {@@ -133,10 +156,17 @@ e = std::current_exception(); } + bool switched = (co_await awaitable_thread_has_context_switched{});+ if (!switched)+ {+ (void) co_await (post)(+ use_awaitable_t<Executor>{__FILE__, __LINE__, "co_spawn_entry_point"});+ }+ (dispatch)(handler_work.get_executor(), [handler = std::move(handler), e]() mutable {- handler(e);+ std::move(handler)(e); }); } @@ -158,6 +188,61 @@ awaitable<T, Executor> awaitable_; }; +template <typename Handler, typename Executor, typename = void>+class co_spawn_cancellation_handler+{+public:+ co_spawn_cancellation_handler(const Handler&, const Executor& ex)+ : ex_(ex)+ {+ }++ cancellation_slot slot()+ {+ return signal_.slot();+ }++ void operator()(cancellation_type_t type)+ {+ cancellation_signal* sig = &signal_;+ asio::dispatch(ex_, [sig, type]{ sig->emit(type); });+ }++private:+ cancellation_signal signal_;+ Executor ex_;+};+++template <typename Handler, typename Executor>+class co_spawn_cancellation_handler<Handler, Executor,+ typename enable_if<+ is_same<+ typename associated_executor<Handler,+ Executor>::asio_associated_executor_is_unspecialised,+ void+ >::value+ >::type>+{+public:+ co_spawn_cancellation_handler(const Handler&, const Executor&)+ {+ }++ cancellation_slot slot()+ {+ return signal_.slot();+ }++ void operator()(cancellation_type_t type)+ {+ signal_.emit(type);+ }++private:+ cancellation_signal signal_;+};+ template <typename Executor> class initiate_co_spawn {@@ -179,10 +264,26 @@ void operator()(Handler&& handler, F&& f) const { typedef typename result_of<F()>::type awaitable_type;+ typedef typename decay<Handler>::type handler_type;+ typedef co_spawn_cancellation_handler<+ handler_type, Executor> cancel_handler_type; + auto slot = asio::get_associated_cancellation_slot(handler);+ cancel_handler_type* cancel_handler = slot.is_connected()+ ? &slot.template emplace<cancel_handler_type>(handler, ex_)+ : nullptr;++ cancellation_slot proxy_slot(+ cancel_handler+ ? cancel_handler->slot()+ : cancellation_slot());++ cancellation_state cancel_state(proxy_slot);+ auto a = (co_spawn_entry_point)(static_cast<awaitable_type*>(nullptr), ex_, std::forward<F>(f), std::forward<Handler>(handler));- awaitable_handler<executor_type, void>(std::move(a), ex_).launch();+ awaitable_handler<executor_type, void>(std::move(a),+ ex_, proxy_slot, cancel_state).launch(); } private:@@ -198,10 +299,10 @@ CompletionToken, void(std::exception_ptr, T)) co_spawn(const Executor& ex, awaitable<T, AwaitableExecutor> a, CompletionToken&& token,- typename enable_if<+ typename constraint< (is_executor<Executor>::value || execution::is_executor<Executor>::value) && is_convertible<Executor, AwaitableExecutor>::value- >::type*)+ >::type) { return async_initiate<CompletionToken, void(std::exception_ptr, T)>( detail::initiate_co_spawn<AwaitableExecutor>(AwaitableExecutor(ex)),@@ -215,10 +316,10 @@ CompletionToken, void(std::exception_ptr)) co_spawn(const Executor& ex, awaitable<void, AwaitableExecutor> a, CompletionToken&& token,- typename enable_if<+ typename constraint< (is_executor<Executor>::value || execution::is_executor<Executor>::value) && is_convertible<Executor, AwaitableExecutor>::value- >::type*)+ >::type) { return async_initiate<CompletionToken, void(std::exception_ptr)>( detail::initiate_co_spawn<AwaitableExecutor>(AwaitableExecutor(ex)),@@ -233,11 +334,11 @@ CompletionToken, void(std::exception_ptr, T)) co_spawn(ExecutionContext& ctx, awaitable<T, AwaitableExecutor> a, CompletionToken&& token,- typename enable_if<+ typename constraint< is_convertible<ExecutionContext&, execution_context&>::value && is_convertible<typename ExecutionContext::executor_type, AwaitableExecutor>::value- >::type*)+ >::type) { return (co_spawn)(ctx.get_executor(), std::move(a), std::forward<CompletionToken>(token));@@ -250,11 +351,11 @@ CompletionToken, void(std::exception_ptr)) co_spawn(ExecutionContext& ctx, awaitable<void, AwaitableExecutor> a, CompletionToken&& token,- typename enable_if<+ typename constraint< is_convertible<ExecutionContext&, execution_context&>::value && is_convertible<typename ExecutionContext::executor_type, AwaitableExecutor>::value- >::type*)+ >::type) { return (co_spawn)(ctx.get_executor(), std::move(a), std::forward<CompletionToken>(token));@@ -266,9 +367,9 @@ inline ASIO_INITFN_AUTO_RESULT_TYPE(CompletionToken, typename detail::awaitable_signature<typename result_of<F()>::type>::type) co_spawn(const Executor& ex, F&& f, CompletionToken&& token,- typename enable_if<+ typename constraint< is_executor<Executor>::value || execution::is_executor<Executor>::value- >::type*)+ >::type) { return async_initiate<CompletionToken, typename detail::awaitable_signature<typename result_of<F()>::type>::type>(@@ -283,9 +384,9 @@ inline ASIO_INITFN_AUTO_RESULT_TYPE(CompletionToken, typename detail::awaitable_signature<typename result_of<F()>::type>::type) co_spawn(ExecutionContext& ctx, F&& f, CompletionToken&& token,- typename enable_if<+ typename constraint< is_convertible<ExecutionContext&, execution_context&>::value- >::type*)+ >::type) { return (co_spawn)(ctx.get_executor(), std::forward<F>(f), std::forward<CompletionToken>(token));
− link/modules/asio-standalone/asio/include/asio/impl/compose.hpp
@@ -1,635 +0,0 @@-//-// impl/compose.hpp-// ~~~~~~~~~~~~~~~~-//-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)-//-// Distributed under the Boost Software License, Version 1.0. (See accompanying-// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)-//--#ifndef ASIO_IMPL_COMPOSE_HPP-#define ASIO_IMPL_COMPOSE_HPP--#if defined(_MSC_VER) && (_MSC_VER >= 1200)-# pragma once-#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)--#include "asio/detail/config.hpp"-#include "asio/associated_executor.hpp"-#include "asio/detail/handler_alloc_helpers.hpp"-#include "asio/detail/handler_cont_helpers.hpp"-#include "asio/detail/handler_invoke_helpers.hpp"-#include "asio/detail/type_traits.hpp"-#include "asio/detail/variadic_templates.hpp"-#include "asio/execution/executor.hpp"-#include "asio/execution/outstanding_work.hpp"-#include "asio/executor_work_guard.hpp"-#include "asio/is_executor.hpp"-#include "asio/system_executor.hpp"--#include "asio/detail/push_options.hpp"--namespace asio {--namespace detail-{- template <typename Executor, typename = void>- class composed_work_guard- {- public:- typedef typename decay<- typename prefer_result<Executor,- execution::outstanding_work_t::tracked_t- >::type- >::type executor_type;-- composed_work_guard(const Executor& ex)- : executor_(asio::prefer(ex, execution::outstanding_work.tracked))- {- }-- void reset()- {- }-- executor_type get_executor() const ASIO_NOEXCEPT- {- return executor_;- }-- private:- executor_type executor_;- };--#if !defined(ASIO_NO_TS_EXECUTORS)-- template <typename Executor>- struct composed_work_guard<Executor,- typename enable_if<- !execution::is_executor<Executor>::value- >::type> : executor_work_guard<Executor>- {- composed_work_guard(const Executor& ex)- : executor_work_guard<Executor>(ex)- {- }- };--#endif // !defined(ASIO_NO_TS_EXECUTORS)-- template <typename>- struct composed_io_executors;-- template <>- struct composed_io_executors<void()>- {- composed_io_executors() ASIO_NOEXCEPT- : head_(system_executor())- {- }-- typedef system_executor head_type;- system_executor head_;- };-- inline composed_io_executors<void()> make_composed_io_executors()- {- return composed_io_executors<void()>();- }-- template <typename Head>- struct composed_io_executors<void(Head)>- {- explicit composed_io_executors(const Head& ex) ASIO_NOEXCEPT- : head_(ex)- {- }-- typedef Head head_type;- Head head_;- };-- template <typename Head>- inline composed_io_executors<void(Head)>- make_composed_io_executors(const Head& head)- {- return composed_io_executors<void(Head)>(head);- }--#if defined(ASIO_HAS_VARIADIC_TEMPLATES)-- template <typename Head, typename... Tail>- struct composed_io_executors<void(Head, Tail...)>- {- explicit composed_io_executors(const Head& head,- const Tail&... tail) ASIO_NOEXCEPT- : head_(head),- tail_(tail...)- {- }-- void reset()- {- head_.reset();- tail_.reset();- }-- typedef Head head_type;- Head head_;- composed_io_executors<void(Tail...)> tail_;- };-- template <typename Head, typename... Tail>- inline composed_io_executors<void(Head, Tail...)>- make_composed_io_executors(const Head& head, const Tail&... tail)- {- return composed_io_executors<void(Head, Tail...)>(head, tail...);- }--#else // defined(ASIO_HAS_VARIADIC_TEMPLATES)--#define ASIO_PRIVATE_COMPOSED_IO_EXECUTORS_DEF(n) \- template <typename Head, ASIO_VARIADIC_TPARAMS(n)> \- struct composed_io_executors<void(Head, ASIO_VARIADIC_TARGS(n))> \- { \- explicit composed_io_executors(const Head& head, \- ASIO_VARIADIC_CONSTREF_PARAMS(n)) ASIO_NOEXCEPT \- : head_(head), \- tail_(ASIO_VARIADIC_BYVAL_ARGS(n)) \- { \- } \- \- void reset() \- { \- head_.reset(); \- tail_.reset(); \- } \- \- typedef Head head_type; \- Head head_; \- composed_io_executors<void(ASIO_VARIADIC_TARGS(n))> tail_; \- }; \- \- template <typename Head, ASIO_VARIADIC_TPARAMS(n)> \- inline composed_io_executors<void(Head, ASIO_VARIADIC_TARGS(n))> \- make_composed_io_executors(const Head& head, \- ASIO_VARIADIC_CONSTREF_PARAMS(n)) \- { \- return composed_io_executors< \- void(Head, ASIO_VARIADIC_TARGS(n))>( \- head, ASIO_VARIADIC_BYVAL_ARGS(n)); \- } \- /**/- ASIO_VARIADIC_GENERATE(ASIO_PRIVATE_COMPOSED_IO_EXECUTORS_DEF)-#undef ASIO_PRIVATE_COMPOSED_IO_EXECUTORS_DEF--#endif // defined(ASIO_HAS_VARIADIC_TEMPLATES)-- template <typename>- struct composed_work;-- template <>- struct composed_work<void()>- {- typedef composed_io_executors<void()> executors_type;-- composed_work(const executors_type&) ASIO_NOEXCEPT- : head_(system_executor())- {- }-- void reset()- {- head_.reset();- }-- typedef system_executor head_type;- composed_work_guard<system_executor> head_;- };-- template <typename Head>- struct composed_work<void(Head)>- {- typedef composed_io_executors<void(Head)> executors_type;-- explicit composed_work(const executors_type& ex) ASIO_NOEXCEPT- : head_(ex.head_)- {- }-- void reset()- {- head_.reset();- }-- typedef Head head_type;- composed_work_guard<Head> head_;- };--#if defined(ASIO_HAS_VARIADIC_TEMPLATES)-- template <typename Head, typename... Tail>- struct composed_work<void(Head, Tail...)>- {- typedef composed_io_executors<void(Head, Tail...)> executors_type;-- explicit composed_work(const executors_type& ex) ASIO_NOEXCEPT- : head_(ex.head_),- tail_(ex.tail_)- {- }-- void reset()- {- head_.reset();- tail_.reset();- }-- typedef Head head_type;- composed_work_guard<Head> head_;- composed_work<void(Tail...)> tail_;- };--#else // defined(ASIO_HAS_VARIADIC_TEMPLATES)--#define ASIO_PRIVATE_COMPOSED_WORK_DEF(n) \- template <typename Head, ASIO_VARIADIC_TPARAMS(n)> \- struct composed_work<void(Head, ASIO_VARIADIC_TARGS(n))> \- { \- typedef composed_io_executors<void(Head, \- ASIO_VARIADIC_TARGS(n))> executors_type; \- \- explicit composed_work(const executors_type& ex) ASIO_NOEXCEPT \- : head_(ex.head_), \- tail_(ex.tail_) \- { \- } \- \- void reset() \- { \- head_.reset(); \- tail_.reset(); \- } \- \- typedef Head head_type; \- composed_work_guard<Head> head_; \- composed_work<void(ASIO_VARIADIC_TARGS(n))> tail_; \- }; \- /**/- ASIO_VARIADIC_GENERATE(ASIO_PRIVATE_COMPOSED_WORK_DEF)-#undef ASIO_PRIVATE_COMPOSED_WORK_DEF--#endif // defined(ASIO_HAS_VARIADIC_TEMPLATES)--#if defined(ASIO_HAS_VARIADIC_TEMPLATES)- template <typename Impl, typename Work, typename Handler, typename Signature>- class composed_op;-- template <typename Impl, typename Work, typename Handler,- typename R, typename... Args>- class composed_op<Impl, Work, Handler, R(Args...)>-#else // defined(ASIO_HAS_VARIADIC_TEMPLATES)- template <typename Impl, typename Work, typename Handler, typename Signature>- class composed_op-#endif // defined(ASIO_HAS_VARIADIC_TEMPLATES)- {- public:- template <typename I, typename W, typename H>- composed_op(ASIO_MOVE_ARG(I) impl,- ASIO_MOVE_ARG(W) work,- ASIO_MOVE_ARG(H) handler)- : impl_(ASIO_MOVE_CAST(I)(impl)),- work_(ASIO_MOVE_CAST(W)(work)),- handler_(ASIO_MOVE_CAST(H)(handler)),- invocations_(0)- {- }--#if defined(ASIO_HAS_MOVE)- composed_op(composed_op&& other)- : impl_(ASIO_MOVE_CAST(Impl)(other.impl_)),- work_(ASIO_MOVE_CAST(Work)(other.work_)),- handler_(ASIO_MOVE_CAST(Handler)(other.handler_)),- invocations_(other.invocations_)- {- }-#endif // defined(ASIO_HAS_MOVE)-- typedef typename associated_executor<Handler,- typename composed_work_guard<- typename Work::head_type- >::executor_type- >::type executor_type;-- executor_type get_executor() const ASIO_NOEXCEPT- {- return (get_associated_executor)(handler_, work_.head_.get_executor());- }-- typedef typename associated_allocator<Handler,- std::allocator<void> >::type allocator_type;-- allocator_type get_allocator() const ASIO_NOEXCEPT- {- return (get_associated_allocator)(handler_, std::allocator<void>());- }--#if defined(ASIO_HAS_VARIADIC_TEMPLATES)-- template<typename... T>- void operator()(ASIO_MOVE_ARG(T)... t)- {- if (invocations_ < ~0u)- ++invocations_;- impl_(*this, ASIO_MOVE_CAST(T)(t)...);- }-- void complete(Args... args)- {- this->work_.reset();- this->handler_(ASIO_MOVE_CAST(Args)(args)...);- }--#else // defined(ASIO_HAS_VARIADIC_TEMPLATES)-- void operator()()- {- if (invocations_ < ~0u)- ++invocations_;- impl_(*this);- }-- void complete()- {- this->work_.reset();- this->handler_();- }--#define ASIO_PRIVATE_COMPOSED_OP_DEF(n) \- template<ASIO_VARIADIC_TPARAMS(n)> \- void operator()(ASIO_VARIADIC_MOVE_PARAMS(n)) \- { \- if (invocations_ < ~0u) \- ++invocations_; \- impl_(*this, ASIO_VARIADIC_MOVE_ARGS(n)); \- } \- \- template<ASIO_VARIADIC_TPARAMS(n)> \- void complete(ASIO_VARIADIC_MOVE_PARAMS(n)) \- { \- this->work_.reset(); \- this->handler_(ASIO_VARIADIC_MOVE_ARGS(n)); \- } \- /**/- ASIO_VARIADIC_GENERATE(ASIO_PRIVATE_COMPOSED_OP_DEF)-#undef ASIO_PRIVATE_COMPOSED_OP_DEF--#endif // defined(ASIO_HAS_VARIADIC_TEMPLATES)-- //private:- Impl impl_;- Work work_;- Handler handler_;- unsigned invocations_;- };-- template <typename Impl, typename Work, typename Handler, typename Signature>- inline asio_handler_allocate_is_deprecated- asio_handler_allocate(std::size_t size,- composed_op<Impl, Work, Handler, Signature>* this_handler)- {-#if defined(ASIO_NO_DEPRECATED)- asio_handler_alloc_helpers::allocate(size, this_handler->handler_);- return asio_handler_allocate_is_no_longer_used();-#else // defined(ASIO_NO_DEPRECATED)- return asio_handler_alloc_helpers::allocate(- size, this_handler->handler_);-#endif // defined(ASIO_NO_DEPRECATED)- }-- template <typename Impl, typename Work, typename Handler, typename Signature>- inline asio_handler_deallocate_is_deprecated- asio_handler_deallocate(void* pointer, std::size_t size,- composed_op<Impl, Work, Handler, Signature>* this_handler)- {- asio_handler_alloc_helpers::deallocate(- pointer, size, this_handler->handler_);-#if defined(ASIO_NO_DEPRECATED)- return asio_handler_deallocate_is_no_longer_used();-#endif // defined(ASIO_NO_DEPRECATED)- }-- template <typename Impl, typename Work, typename Handler, typename Signature>- inline bool asio_handler_is_continuation(- composed_op<Impl, Work, Handler, Signature>* this_handler)- {- return this_handler->invocations_ > 1 ? true- : asio_handler_cont_helpers::is_continuation(- this_handler->handler_);- }-- template <typename Function, typename Impl,- typename Work, typename Handler, typename Signature>- inline asio_handler_invoke_is_deprecated- asio_handler_invoke(Function& function,- composed_op<Impl, Work, Handler, Signature>* this_handler)- {- asio_handler_invoke_helpers::invoke(- function, this_handler->handler_);-#if defined(ASIO_NO_DEPRECATED)- return asio_handler_invoke_is_no_longer_used();-#endif // defined(ASIO_NO_DEPRECATED)- }-- template <typename Function, typename Impl,- typename Work, typename Handler, typename Signature>- inline asio_handler_invoke_is_deprecated- asio_handler_invoke(const Function& function,- composed_op<Impl, Work, Handler, Signature>* this_handler)- {- asio_handler_invoke_helpers::invoke(- function, this_handler->handler_);-#if defined(ASIO_NO_DEPRECATED)- return asio_handler_invoke_is_no_longer_used();-#endif // defined(ASIO_NO_DEPRECATED)- }-- template <typename Signature, typename Executors>- class initiate_composed_op- {- public:- typedef typename composed_io_executors<Executors>::head_type executor_type;-- template <typename T>- explicit initiate_composed_op(int, ASIO_MOVE_ARG(T) executors)- : executors_(ASIO_MOVE_CAST(T)(executors))- {- }-- executor_type get_executor() const ASIO_NOEXCEPT- {- return executors_.head_;- }-- template <typename Handler, typename Impl>- void operator()(ASIO_MOVE_ARG(Handler) handler,- ASIO_MOVE_ARG(Impl) impl) const- {- composed_op<typename decay<Impl>::type, composed_work<Executors>,- typename decay<Handler>::type, Signature>(- ASIO_MOVE_CAST(Impl)(impl),- composed_work<Executors>(executors_),- ASIO_MOVE_CAST(Handler)(handler))();- }-- private:- composed_io_executors<Executors> executors_;- };-- template <typename Signature, typename Executors>- inline initiate_composed_op<Signature, Executors> make_initiate_composed_op(- ASIO_MOVE_ARG(composed_io_executors<Executors>) executors)- {- return initiate_composed_op<Signature, Executors>(0,- ASIO_MOVE_CAST(composed_io_executors<Executors>)(executors));- }-- template <typename IoObject>- inline typename IoObject::executor_type- get_composed_io_executor(IoObject& io_object,- typename enable_if<- !is_executor<IoObject>::value- && !execution::is_executor<IoObject>::value- >::type* = 0)- {- return io_object.get_executor();- }-- template <typename Executor>- inline const Executor& get_composed_io_executor(const Executor& ex,- typename enable_if<- is_executor<Executor>::value- || execution::is_executor<Executor>::value- >::type* = 0)- {- return ex;- }-} // namespace detail--#if !defined(GENERATING_DOCUMENTATION)-#if defined(ASIO_HAS_VARIADIC_TEMPLATES)--template <typename CompletionToken, typename Signature,- typename Implementation, typename... IoObjectsOrExecutors>-ASIO_INITFN_AUTO_RESULT_TYPE(CompletionToken, Signature)-async_compose(ASIO_MOVE_ARG(Implementation) implementation,- ASIO_NONDEDUCED_MOVE_ARG(CompletionToken) token,- ASIO_MOVE_ARG(IoObjectsOrExecutors)... io_objects_or_executors)-{- return async_initiate<CompletionToken, Signature>(- detail::make_initiate_composed_op<Signature>(- detail::make_composed_io_executors(- detail::get_composed_io_executor(- ASIO_MOVE_CAST(IoObjectsOrExecutors)(- io_objects_or_executors))...)),- token, ASIO_MOVE_CAST(Implementation)(implementation));-}--#else // defined(ASIO_HAS_VARIADIC_TEMPLATES)--template <typename CompletionToken, typename Signature, typename Implementation>-ASIO_INITFN_AUTO_RESULT_TYPE(CompletionToken, Signature)-async_compose(ASIO_MOVE_ARG(Implementation) implementation,- ASIO_NONDEDUCED_MOVE_ARG(CompletionToken) token)-{- return async_initiate<CompletionToken, Signature>(- detail::make_initiate_composed_op<Signature>(- detail::make_composed_io_executors()),- token, ASIO_MOVE_CAST(Implementation)(implementation));-}--# define ASIO_PRIVATE_GET_COMPOSED_IO_EXECUTOR(n) \- ASIO_PRIVATE_GET_COMPOSED_IO_EXECUTOR_##n--# define ASIO_PRIVATE_GET_COMPOSED_IO_EXECUTOR_1 \- detail::get_composed_io_executor(ASIO_MOVE_CAST(T1)(x1))-# define ASIO_PRIVATE_GET_COMPOSED_IO_EXECUTOR_2 \- detail::get_composed_io_executor(ASIO_MOVE_CAST(T1)(x1)), \- detail::get_composed_io_executor(ASIO_MOVE_CAST(T2)(x2))-# define ASIO_PRIVATE_GET_COMPOSED_IO_EXECUTOR_3 \- detail::get_composed_io_executor(ASIO_MOVE_CAST(T1)(x1)), \- detail::get_composed_io_executor(ASIO_MOVE_CAST(T2)(x2)), \- detail::get_composed_io_executor(ASIO_MOVE_CAST(T3)(x3))-# define ASIO_PRIVATE_GET_COMPOSED_IO_EXECUTOR_4 \- detail::get_composed_io_executor(ASIO_MOVE_CAST(T1)(x1)), \- detail::get_composed_io_executor(ASIO_MOVE_CAST(T2)(x2)), \- detail::get_composed_io_executor(ASIO_MOVE_CAST(T3)(x3)), \- detail::get_composed_io_executor(ASIO_MOVE_CAST(T4)(x4))-# define ASIO_PRIVATE_GET_COMPOSED_IO_EXECUTOR_5 \- detail::get_composed_io_executor(ASIO_MOVE_CAST(T1)(x1)), \- detail::get_composed_io_executor(ASIO_MOVE_CAST(T2)(x2)), \- detail::get_composed_io_executor(ASIO_MOVE_CAST(T3)(x3)), \- detail::get_composed_io_executor(ASIO_MOVE_CAST(T4)(x4)), \- detail::get_composed_io_executor(ASIO_MOVE_CAST(T5)(x5))-# define ASIO_PRIVATE_GET_COMPOSED_IO_EXECUTOR_6 \- detail::get_composed_io_executor(ASIO_MOVE_CAST(T1)(x1)), \- detail::get_composed_io_executor(ASIO_MOVE_CAST(T2)(x2)), \- detail::get_composed_io_executor(ASIO_MOVE_CAST(T3)(x3)), \- detail::get_composed_io_executor(ASIO_MOVE_CAST(T4)(x4)), \- detail::get_composed_io_executor(ASIO_MOVE_CAST(T5)(x5)), \- detail::get_composed_io_executor(ASIO_MOVE_CAST(T6)(x6))-# define ASIO_PRIVATE_GET_COMPOSED_IO_EXECUTOR_7 \- detail::get_composed_io_executor(ASIO_MOVE_CAST(T1)(x1)), \- detail::get_composed_io_executor(ASIO_MOVE_CAST(T2)(x2)), \- detail::get_composed_io_executor(ASIO_MOVE_CAST(T3)(x3)), \- detail::get_composed_io_executor(ASIO_MOVE_CAST(T4)(x4)), \- detail::get_composed_io_executor(ASIO_MOVE_CAST(T5)(x5)), \- detail::get_composed_io_executor(ASIO_MOVE_CAST(T6)(x6)), \- detail::get_composed_io_executor(ASIO_MOVE_CAST(T7)(x7))-# define ASIO_PRIVATE_GET_COMPOSED_IO_EXECUTOR_8 \- detail::get_composed_io_executor(ASIO_MOVE_CAST(T1)(x1)), \- detail::get_composed_io_executor(ASIO_MOVE_CAST(T2)(x2)), \- detail::get_composed_io_executor(ASIO_MOVE_CAST(T3)(x3)), \- detail::get_composed_io_executor(ASIO_MOVE_CAST(T4)(x4)), \- detail::get_composed_io_executor(ASIO_MOVE_CAST(T5)(x5)), \- detail::get_composed_io_executor(ASIO_MOVE_CAST(T6)(x6)), \- detail::get_composed_io_executor(ASIO_MOVE_CAST(T7)(x7)), \- detail::get_composed_io_executor(ASIO_MOVE_CAST(T8)(x8))--#define ASIO_PRIVATE_ASYNC_COMPOSE_DEF(n) \- template <typename CompletionToken, typename Signature, \- typename Implementation, ASIO_VARIADIC_TPARAMS(n)> \- ASIO_INITFN_AUTO_RESULT_TYPE(CompletionToken, Signature) \- async_compose(ASIO_MOVE_ARG(Implementation) implementation, \- ASIO_NONDEDUCED_MOVE_ARG(CompletionToken) token, \- ASIO_VARIADIC_MOVE_PARAMS(n)) \- { \- return async_initiate<CompletionToken, Signature>( \- detail::make_initiate_composed_op<Signature>( \- detail::make_composed_io_executors( \- ASIO_PRIVATE_GET_COMPOSED_IO_EXECUTOR(n))), \- token, ASIO_MOVE_CAST(Implementation)(implementation)); \- } \- /**/- ASIO_VARIADIC_GENERATE(ASIO_PRIVATE_ASYNC_COMPOSE_DEF)-#undef ASIO_PRIVATE_ASYNC_COMPOSE_DEF--#undef ASIO_PRIVATE_GET_COMPOSED_IO_EXECUTOR-#undef ASIO_PRIVATE_GET_COMPOSED_IO_EXECUTOR_1-#undef ASIO_PRIVATE_GET_COMPOSED_IO_EXECUTOR_2-#undef ASIO_PRIVATE_GET_COMPOSED_IO_EXECUTOR_3-#undef ASIO_PRIVATE_GET_COMPOSED_IO_EXECUTOR_4-#undef ASIO_PRIVATE_GET_COMPOSED_IO_EXECUTOR_5-#undef ASIO_PRIVATE_GET_COMPOSED_IO_EXECUTOR_6-#undef ASIO_PRIVATE_GET_COMPOSED_IO_EXECUTOR_7-#undef ASIO_PRIVATE_GET_COMPOSED_IO_EXECUTOR_8--#endif // defined(ASIO_HAS_VARIADIC_TEMPLATES)-#endif // !defined(GENERATING_DOCUMENTATION)--} // namespace asio--#include "asio/detail/pop_options.hpp"--#endif // ASIO_IMPL_COMPOSE_HPP
link/modules/asio-standalone/asio/include/asio/impl/connect.hpp view
@@ -2,7 +2,7 @@ // impl/connect.hpp // ~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -16,8 +16,8 @@ #endif // defined(_MSC_VER) && (_MSC_VER >= 1200) #include <algorithm>-#include "asio/associated_allocator.hpp"-#include "asio/associated_executor.hpp"+#include "asio/associator.hpp"+#include "asio/detail/base_from_cancellation_state.hpp" #include "asio/detail/bind_handler.hpp" #include "asio/detail/handler_alloc_helpers.hpp" #include "asio/detail/handler_cont_helpers.hpp"@@ -26,6 +26,7 @@ #include "asio/detail/handler_type_requirements.hpp" #include "asio/detail/non_const_lvalue.hpp" #include "asio/detail/throw_error.hpp"+#include "asio/detail/type_traits.hpp" #include "asio/error.hpp" #include "asio/post.hpp" @@ -73,9 +74,9 @@ static const bool value = sizeof(asio_connect_condition_check(- (*static_cast<legacy_connect_condition_helper<T, Iterator>*>(0))(- *static_cast<const asio::error_code*>(0),- *static_cast<const Iterator*>(0)))) != 1;+ (declval<legacy_connect_condition_helper<T, Iterator> >())(+ declval<const asio::error_code>(),+ declval<const Iterator>()))) != 1; }; template <typename ConnectCondition, typename Iterator>@@ -105,8 +106,8 @@ template <typename Protocol, typename Executor, typename EndpointSequence> typename Protocol::endpoint connect(basic_socket<Protocol, Executor>& s, const EndpointSequence& endpoints,- typename enable_if<is_endpoint_sequence<- EndpointSequence>::value>::type*)+ typename constraint<is_endpoint_sequence<+ EndpointSequence>::value>::type) { asio::error_code ec; typename Protocol::endpoint result = connect(s, endpoints, ec);@@ -117,8 +118,8 @@ template <typename Protocol, typename Executor, typename EndpointSequence> typename Protocol::endpoint connect(basic_socket<Protocol, Executor>& s, const EndpointSequence& endpoints, asio::error_code& ec,- typename enable_if<is_endpoint_sequence<- EndpointSequence>::value>::type*)+ typename constraint<is_endpoint_sequence<+ EndpointSequence>::value>::type) { return detail::deref_connect_result<Protocol>( connect(s, endpoints.begin(), endpoints.end(),@@ -128,7 +129,7 @@ #if !defined(ASIO_NO_DEPRECATED) template <typename Protocol, typename Executor, typename Iterator> Iterator connect(basic_socket<Protocol, Executor>& s, Iterator begin,- typename enable_if<!is_endpoint_sequence<Iterator>::value>::type*)+ typename constraint<!is_endpoint_sequence<Iterator>::value>::type) { asio::error_code ec; Iterator result = connect(s, begin, ec);@@ -139,7 +140,7 @@ template <typename Protocol, typename Executor, typename Iterator> inline Iterator connect(basic_socket<Protocol, Executor>& s, Iterator begin, asio::error_code& ec,- typename enable_if<!is_endpoint_sequence<Iterator>::value>::type*)+ typename constraint<!is_endpoint_sequence<Iterator>::value>::type) { return connect(s, begin, Iterator(), detail::default_connect_condition(), ec); }@@ -166,8 +167,8 @@ typename EndpointSequence, typename ConnectCondition> typename Protocol::endpoint connect(basic_socket<Protocol, Executor>& s, const EndpointSequence& endpoints, ConnectCondition connect_condition,- typename enable_if<is_endpoint_sequence<- EndpointSequence>::value>::type*)+ typename constraint<is_endpoint_sequence<+ EndpointSequence>::value>::type) { asio::error_code ec; typename Protocol::endpoint result = connect(@@ -181,8 +182,8 @@ typename Protocol::endpoint connect(basic_socket<Protocol, Executor>& s, const EndpointSequence& endpoints, ConnectCondition connect_condition, asio::error_code& ec,- typename enable_if<is_endpoint_sequence<- EndpointSequence>::value>::type*)+ typename constraint<is_endpoint_sequence<+ EndpointSequence>::value>::type) { return detail::deref_connect_result<Protocol>( connect(s, endpoints.begin(), endpoints.end(),@@ -194,7 +195,7 @@ typename Iterator, typename ConnectCondition> Iterator connect(basic_socket<Protocol, Executor>& s, Iterator begin, ConnectCondition connect_condition,- typename enable_if<!is_endpoint_sequence<Iterator>::value>::type*)+ typename constraint<!is_endpoint_sequence<Iterator>::value>::type) { asio::error_code ec; Iterator result = connect(s, begin, connect_condition, ec);@@ -207,7 +208,7 @@ inline Iterator connect(basic_socket<Protocol, Executor>& s, Iterator begin, ConnectCondition connect_condition, asio::error_code& ec,- typename enable_if<!is_endpoint_sequence<Iterator>::value>::type*)+ typename constraint<!is_endpoint_sequence<Iterator>::value>::type) { return connect(s, begin, Iterator(), connect_condition, ec); }@@ -294,14 +295,18 @@ template <typename Protocol, typename Executor, typename EndpointSequence, typename ConnectCondition, typename RangeConnectHandler>- class range_connect_op : base_from_connect_condition<ConnectCondition>+ class range_connect_op+ : public base_from_cancellation_state<RangeConnectHandler>,+ base_from_connect_condition<ConnectCondition> { public: range_connect_op(basic_socket<Protocol, Executor>& sock, const EndpointSequence& endpoints, const ConnectCondition& connect_condition, RangeConnectHandler& handler)- : base_from_connect_condition<ConnectCondition>(connect_condition),+ : base_from_cancellation_state<RangeConnectHandler>(+ handler, enable_partial_cancellation()),+ base_from_connect_condition<ConnectCondition>(connect_condition), socket_(sock), endpoints_(endpoints), index_(0),@@ -312,7 +317,8 @@ #if defined(ASIO_HAS_MOVE) range_connect_op(const range_connect_op& other)- : base_from_connect_condition<ConnectCondition>(other),+ : base_from_cancellation_state<RangeConnectHandler>(other),+ base_from_connect_condition<ConnectCondition>(other), socket_(other.socket_), endpoints_(other.endpoints_), index_(other.index_),@@ -322,7 +328,10 @@ } range_connect_op(range_connect_op&& other)- : base_from_connect_condition<ConnectCondition>(other),+ : base_from_cancellation_state<RangeConnectHandler>(+ ASIO_MOVE_CAST(base_from_cancellation_state<+ RangeConnectHandler>)(other)),+ base_from_connect_condition<ConnectCondition>(other), socket_(other.socket_), endpoints_(other.endpoints_), index_(other.index_),@@ -388,11 +397,18 @@ if (!ec) break; + if (this->cancelled() != cancellation_type::none)+ {+ ec = asio::error::operation_aborted;+ break;+ }+ ++iter; ++index_; } - handler_(static_cast<const asio::error_code&>(ec),+ ASIO_MOVE_OR_LVALUE(RangeConnectHandler)(handler_)(+ static_cast<const asio::error_code&>(ec), static_cast<const typename Protocol::endpoint&>( ec || iter == end ? typename Protocol::endpoint() : *iter)); }@@ -515,14 +531,18 @@ template <typename Protocol, typename Executor, typename Iterator, typename ConnectCondition, typename IteratorConnectHandler>- class iterator_connect_op : base_from_connect_condition<ConnectCondition>+ class iterator_connect_op+ : public base_from_cancellation_state<IteratorConnectHandler>,+ base_from_connect_condition<ConnectCondition> { public: iterator_connect_op(basic_socket<Protocol, Executor>& sock, const Iterator& begin, const Iterator& end, const ConnectCondition& connect_condition, IteratorConnectHandler& handler)- : base_from_connect_condition<ConnectCondition>(connect_condition),+ : base_from_cancellation_state<IteratorConnectHandler>(+ handler, enable_partial_cancellation()),+ base_from_connect_condition<ConnectCondition>(connect_condition), socket_(sock), iter_(begin), end_(end),@@ -533,7 +553,8 @@ #if defined(ASIO_HAS_MOVE) iterator_connect_op(const iterator_connect_op& other)- : base_from_connect_condition<ConnectCondition>(other),+ : base_from_cancellation_state<IteratorConnectHandler>(other),+ base_from_connect_condition<ConnectCondition>(other), socket_(other.socket_), iter_(other.iter_), end_(other.end_),@@ -543,7 +564,10 @@ } iterator_connect_op(iterator_connect_op&& other)- : base_from_connect_condition<ConnectCondition>(other),+ : base_from_cancellation_state<IteratorConnectHandler>(+ ASIO_MOVE_CAST(base_from_cancellation_state<+ IteratorConnectHandler>)(other)),+ base_from_connect_condition<ConnectCondition>(other), socket_(other.socket_), iter_(other.iter_), end_(other.end_),@@ -595,10 +619,17 @@ if (!ec) break; + if (this->cancelled() != cancellation_type::none)+ {+ ec = asio::error::operation_aborted;+ break;+ }+ ++iter_; } - handler_(static_cast<const asio::error_code&>(ec),+ ASIO_MOVE_OR_LVALUE(IteratorConnectHandler)(handler_)(+ static_cast<const asio::error_code&>(ec), static_cast<const Iterator&>(iter_)); } }@@ -723,86 +754,66 @@ #if !defined(GENERATING_DOCUMENTATION) -template <typename Protocol, typename Executor, typename EndpointSequence,- typename ConnectCondition, typename RangeConnectHandler, typename Allocator>-struct associated_allocator<- detail::range_connect_op<Protocol, Executor, EndpointSequence,- ConnectCondition, RangeConnectHandler>, Allocator>+template <template <typename, typename> class Associator,+ typename Protocol, typename Executor, typename EndpointSequence,+ typename ConnectCondition, typename RangeConnectHandler,+ typename DefaultCandidate>+struct associator<Associator,+ detail::range_connect_op<Protocol, Executor,+ EndpointSequence, ConnectCondition, RangeConnectHandler>,+ DefaultCandidate>+ : Associator<RangeConnectHandler, DefaultCandidate> {- typedef typename associated_allocator<- RangeConnectHandler, Allocator>::type type;-- static type get(- const detail::range_connect_op<Protocol, Executor, EndpointSequence,- ConnectCondition, RangeConnectHandler>& h,- const Allocator& a = Allocator()) ASIO_NOEXCEPT+ static typename Associator<RangeConnectHandler, DefaultCandidate>::type+ get(const detail::range_connect_op<Protocol, Executor, EndpointSequence,+ ConnectCondition, RangeConnectHandler>& h) ASIO_NOEXCEPT {- return associated_allocator<RangeConnectHandler,- Allocator>::get(h.handler_, a);+ return Associator<RangeConnectHandler, DefaultCandidate>::get(h.handler_); }-}; -template <typename Protocol, typename Executor, typename EndpointSequence,- typename ConnectCondition, typename RangeConnectHandler, typename Executor1>-struct associated_executor<- detail::range_connect_op<Protocol, Executor, EndpointSequence,- ConnectCondition, RangeConnectHandler>, Executor1>- : detail::associated_executor_forwarding_base<RangeConnectHandler, Executor1>-{- typedef typename associated_executor<- RangeConnectHandler, Executor1>::type type;-- static type get(- const detail::range_connect_op<Protocol, Executor, EndpointSequence,- ConnectCondition, RangeConnectHandler>& h,- const Executor1& ex = Executor1()) ASIO_NOEXCEPT+ static ASIO_AUTO_RETURN_TYPE_PREFIX2(+ typename Associator<RangeConnectHandler, DefaultCandidate>::type)+ get(const detail::range_connect_op<Protocol, Executor,+ EndpointSequence, ConnectCondition, RangeConnectHandler>& h,+ const DefaultCandidate& c) ASIO_NOEXCEPT+ ASIO_AUTO_RETURN_TYPE_SUFFIX((+ Associator<RangeConnectHandler, DefaultCandidate>::get(+ h.handler_, c))) {- return associated_executor<RangeConnectHandler,- Executor1>::get(h.handler_, ex);+ return Associator<RangeConnectHandler, DefaultCandidate>::get(+ h.handler_, c); } }; -template <typename Protocol, typename Executor, typename Iterator,+template <template <typename, typename> class Associator,+ typename Protocol, typename Executor, typename Iterator, typename ConnectCondition, typename IteratorConnectHandler,- typename Allocator>-struct associated_allocator<+ typename DefaultCandidate>+struct associator<Associator, detail::iterator_connect_op<Protocol, Executor, Iterator, ConnectCondition, IteratorConnectHandler>,- Allocator>+ DefaultCandidate>+ : Associator<IteratorConnectHandler, DefaultCandidate> {- typedef typename associated_allocator<- IteratorConnectHandler, Allocator>::type type;-- static type get(- const detail::iterator_connect_op<Protocol, Executor,- Iterator, ConnectCondition, IteratorConnectHandler>& h,- const Allocator& a = Allocator()) ASIO_NOEXCEPT+ static typename Associator<IteratorConnectHandler, DefaultCandidate>::type+ get(const detail::iterator_connect_op<Protocol, Executor, Iterator,+ ConnectCondition, IteratorConnectHandler>& h) ASIO_NOEXCEPT {- return associated_allocator<IteratorConnectHandler,- Allocator>::get(h.handler_, a);+ return Associator<IteratorConnectHandler, DefaultCandidate>::get(+ h.handler_); }-}; -template <typename Protocol, typename Executor, typename Iterator,- typename ConnectCondition, typename IteratorConnectHandler,- typename Executor1>-struct associated_executor<- detail::iterator_connect_op<Protocol, Executor,- Iterator, ConnectCondition, IteratorConnectHandler>,- Executor1>- : detail::associated_executor_forwarding_base<- IteratorConnectHandler, Executor1>-{- typedef typename associated_executor<- IteratorConnectHandler, Executor1>::type type;-- static type get(- const detail::iterator_connect_op<Protocol, Executor,+ static ASIO_AUTO_RETURN_TYPE_PREFIX2(+ typename Associator<IteratorConnectHandler, DefaultCandidate>::type)+ get(const detail::iterator_connect_op<Protocol, Executor, Iterator, ConnectCondition, IteratorConnectHandler>& h,- const Executor1& ex = Executor1()) ASIO_NOEXCEPT+ const DefaultCandidate& c) ASIO_NOEXCEPT+ ASIO_AUTO_RETURN_TYPE_SUFFIX((+ Associator<IteratorConnectHandler, DefaultCandidate>::get(+ h.handler_, c))) {- return associated_executor<IteratorConnectHandler,- Executor1>::get(h.handler_, ex);+ return Associator<IteratorConnectHandler, DefaultCandidate>::get(+ h.handler_, c); } }; @@ -810,103 +821,135 @@ template <typename Protocol, typename Executor, typename EndpointSequence, ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code,- typename Protocol::endpoint)) RangeConnectHandler>-inline ASIO_INITFN_AUTO_RESULT_TYPE(RangeConnectHandler,+ typename Protocol::endpoint)) RangeConnectToken>+inline ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX(RangeConnectToken, void (asio::error_code, typename Protocol::endpoint)) async_connect(basic_socket<Protocol, Executor>& s, const EndpointSequence& endpoints,- ASIO_MOVE_ARG(RangeConnectHandler) handler,- typename enable_if<is_endpoint_sequence<- EndpointSequence>::value>::type*)+ ASIO_MOVE_ARG(RangeConnectToken) token,+ typename constraint<is_endpoint_sequence<+ EndpointSequence>::value>::type)+ ASIO_INITFN_AUTO_RESULT_TYPE_SUFFIX((+ async_initiate<RangeConnectToken,+ void (asio::error_code, typename Protocol::endpoint)>(+ declval<detail::initiate_async_range_connect<Protocol, Executor> >(),+ token, endpoints, declval<detail::default_connect_condition>()))) {- return async_initiate<RangeConnectHandler,+ return async_initiate<RangeConnectToken, void (asio::error_code, typename Protocol::endpoint)>( detail::initiate_async_range_connect<Protocol, Executor>(s),- handler, endpoints, detail::default_connect_condition());+ token, endpoints, detail::default_connect_condition()); } #if !defined(ASIO_NO_DEPRECATED) template <typename Protocol, typename Executor, typename Iterator, ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code,- Iterator)) IteratorConnectHandler>-inline ASIO_INITFN_AUTO_RESULT_TYPE(IteratorConnectHandler,+ Iterator)) IteratorConnectToken>+inline ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX(IteratorConnectToken, void (asio::error_code, Iterator)) async_connect(basic_socket<Protocol, Executor>& s, Iterator begin,- ASIO_MOVE_ARG(IteratorConnectHandler) handler,- typename enable_if<!is_endpoint_sequence<Iterator>::value>::type*)+ ASIO_MOVE_ARG(IteratorConnectToken) token,+ typename constraint<!is_endpoint_sequence<Iterator>::value>::type)+ ASIO_INITFN_AUTO_RESULT_TYPE_SUFFIX((+ async_initiate<IteratorConnectToken,+ void (asio::error_code, Iterator)>(+ declval<detail::initiate_async_iterator_connect<Protocol, Executor> >(),+ token, begin, Iterator(),+ declval<detail::default_connect_condition>()))) {- return async_initiate<IteratorConnectHandler,+ return async_initiate<IteratorConnectToken, void (asio::error_code, Iterator)>( detail::initiate_async_iterator_connect<Protocol, Executor>(s),- handler, begin, Iterator(), detail::default_connect_condition());+ token, begin, Iterator(),+ detail::default_connect_condition()); } #endif // !defined(ASIO_NO_DEPRECATED) template <typename Protocol, typename Executor, typename Iterator, ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code,- Iterator)) IteratorConnectHandler>-inline ASIO_INITFN_AUTO_RESULT_TYPE(IteratorConnectHandler,+ Iterator)) IteratorConnectToken>+inline ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX(IteratorConnectToken, void (asio::error_code, Iterator)) async_connect(basic_socket<Protocol, Executor>& s, Iterator begin, Iterator end,- ASIO_MOVE_ARG(IteratorConnectHandler) handler)+ ASIO_MOVE_ARG(IteratorConnectToken) token)+ ASIO_INITFN_AUTO_RESULT_TYPE_SUFFIX((+ async_initiate<IteratorConnectToken,+ void (asio::error_code, Iterator)>(+ declval<detail::initiate_async_iterator_connect<Protocol, Executor> >(),+ token, begin, end, declval<detail::default_connect_condition>()))) {- return async_initiate<IteratorConnectHandler,+ return async_initiate<IteratorConnectToken, void (asio::error_code, Iterator)>( detail::initiate_async_iterator_connect<Protocol, Executor>(s),- handler, begin, end, detail::default_connect_condition());+ token, begin, end, detail::default_connect_condition()); } template <typename Protocol, typename Executor, typename EndpointSequence, typename ConnectCondition, ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code,- typename Protocol::endpoint)) RangeConnectHandler>-inline ASIO_INITFN_AUTO_RESULT_TYPE(RangeConnectHandler,+ typename Protocol::endpoint)) RangeConnectToken>+inline ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX(RangeConnectToken, void (asio::error_code, typename Protocol::endpoint)) async_connect(basic_socket<Protocol, Executor>& s, const EndpointSequence& endpoints, ConnectCondition connect_condition,- ASIO_MOVE_ARG(RangeConnectHandler) handler,- typename enable_if<is_endpoint_sequence<- EndpointSequence>::value>::type*)+ ASIO_MOVE_ARG(RangeConnectToken) token,+ typename constraint<is_endpoint_sequence<+ EndpointSequence>::value>::type)+ ASIO_INITFN_AUTO_RESULT_TYPE_SUFFIX((+ async_initiate<RangeConnectToken,+ void (asio::error_code, typename Protocol::endpoint)>(+ declval<detail::initiate_async_range_connect<Protocol, Executor> >(),+ token, endpoints, connect_condition))) {- return async_initiate<RangeConnectHandler,+ return async_initiate<RangeConnectToken, void (asio::error_code, typename Protocol::endpoint)>( detail::initiate_async_range_connect<Protocol, Executor>(s),- handler, endpoints, connect_condition);+ token, endpoints, connect_condition); } #if !defined(ASIO_NO_DEPRECATED) template <typename Protocol, typename Executor, typename Iterator, typename ConnectCondition, ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code,- Iterator)) IteratorConnectHandler>-inline ASIO_INITFN_AUTO_RESULT_TYPE(IteratorConnectHandler,+ Iterator)) IteratorConnectToken>+inline ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX(IteratorConnectToken, void (asio::error_code, Iterator)) async_connect(basic_socket<Protocol, Executor>& s, Iterator begin, ConnectCondition connect_condition,- ASIO_MOVE_ARG(IteratorConnectHandler) handler,- typename enable_if<!is_endpoint_sequence<Iterator>::value>::type*)+ ASIO_MOVE_ARG(IteratorConnectToken) token,+ typename constraint<!is_endpoint_sequence<Iterator>::value>::type)+ ASIO_INITFN_AUTO_RESULT_TYPE_SUFFIX((+ async_initiate<IteratorConnectToken,+ void (asio::error_code, Iterator)>(+ declval<detail::initiate_async_iterator_connect<Protocol, Executor> >(),+ token, begin, Iterator(), connect_condition))) {- return async_initiate<IteratorConnectHandler,+ return async_initiate<IteratorConnectToken, void (asio::error_code, Iterator)>( detail::initiate_async_iterator_connect<Protocol, Executor>(s),- handler, begin, Iterator(), connect_condition);+ token, begin, Iterator(), connect_condition); } #endif // !defined(ASIO_NO_DEPRECATED) template <typename Protocol, typename Executor, typename Iterator, typename ConnectCondition, ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code,- Iterator)) IteratorConnectHandler>-inline ASIO_INITFN_AUTO_RESULT_TYPE(IteratorConnectHandler,+ Iterator)) IteratorConnectToken>+inline ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX(IteratorConnectToken, void (asio::error_code, Iterator)) async_connect(basic_socket<Protocol, Executor>& s, Iterator begin, Iterator end, ConnectCondition connect_condition,- ASIO_MOVE_ARG(IteratorConnectHandler) handler)+ ASIO_MOVE_ARG(IteratorConnectToken) token)+ ASIO_INITFN_AUTO_RESULT_TYPE_SUFFIX((+ async_initiate<IteratorConnectToken,+ void (asio::error_code, Iterator)>(+ declval<detail::initiate_async_iterator_connect<Protocol, Executor> >(),+ token, begin, end, connect_condition))) {- return async_initiate<IteratorConnectHandler,+ return async_initiate<IteratorConnectToken, void (asio::error_code, Iterator)>( detail::initiate_async_iterator_connect<Protocol, Executor>(s),- handler, begin, end, connect_condition);+ token, begin, end, connect_condition); } } // namespace asio
+ link/modules/asio-standalone/asio/include/asio/impl/connect_pipe.hpp view
@@ -0,0 +1,73 @@+//+// impl/connect_pipe.hpp+// ~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com)+//+// Distributed under the Boost Software License, Version 1.0. (See accompanying+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)+//++#ifndef ASIO_IMPL_CONNECT_PIPE_HPP+#define ASIO_IMPL_CONNECT_PIPE_HPP++#if defined(_MSC_VER) && (_MSC_VER >= 1200)+# pragma once+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)++#include "asio/detail/config.hpp"++#if defined(ASIO_HAS_PIPE)++#include "asio/connect_pipe.hpp"+#include "asio/detail/throw_error.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {++template <typename Executor1, typename Executor2>+void connect_pipe(basic_readable_pipe<Executor1>& read_end,+ basic_writable_pipe<Executor2>& write_end)+{+ asio::error_code ec;+ asio::connect_pipe(read_end, write_end, ec);+ asio::detail::throw_error(ec, "connect_pipe");+}++template <typename Executor1, typename Executor2>+ASIO_SYNC_OP_VOID connect_pipe(basic_readable_pipe<Executor1>& read_end,+ basic_writable_pipe<Executor2>& write_end, asio::error_code& ec)+{+ detail::native_pipe_handle p[2];+ detail::create_pipe(p, ec);+ if (ec)+ ASIO_SYNC_OP_VOID_RETURN(ec);++ read_end.assign(p[0], ec);+ if (ec)+ {+ detail::close_pipe(p[0]);+ detail::close_pipe(p[1]);+ ASIO_SYNC_OP_VOID_RETURN(ec);+ }++ write_end.assign(p[1], ec);+ if (ec)+ {+ asio::error_code temp_ec;+ read_end.close(temp_ec);+ detail::close_pipe(p[1]);+ ASIO_SYNC_OP_VOID_RETURN(ec);+ }++ ASIO_SYNC_OP_VOID_RETURN(ec);+}++} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // defined(ASIO_HAS_PIPE)++#endif // ASIO_IMPL_CONNECT_PIPE_HPP
+ link/modules/asio-standalone/asio/include/asio/impl/connect_pipe.ipp view
@@ -0,0 +1,149 @@+//+// impl/connect_pipe.ipp+// ~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2021 Klemens D. Morgenstern+// (klemens dot morgenstern at gmx dot net)+//+// Distributed under the Boost Software License, Version 1.0. (See accompanying+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)+//++#ifndef ASIO_IMPL_CONNECT_PIPE_IPP+#define ASIO_IMPL_CONNECT_PIPE_IPP++#if defined(_MSC_VER) && (_MSC_VER >= 1200)+# pragma once+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)++#include "asio/detail/config.hpp"++#if defined(ASIO_HAS_PIPE)++#include "asio/connect_pipe.hpp"++#if defined(ASIO_HAS_IOCP)+# include <cstdio>+# if _WIN32_WINNT >= 0x601+# include <bcrypt.h>+# if !defined(ASIO_NO_DEFAULT_LINKED_LIBS)+# if defined(_MSC_VER)+# pragma comment(lib, "bcrypt.lib")+# endif // defined(_MSC_VER)+# endif // !defined(ASIO_NO_DEFAULT_LINKED_LIBS)+# endif // _WIN32_WINNT >= 0x601+#else // defined(ASIO_HAS_IOCP)+# include "asio/detail/descriptor_ops.hpp"+#endif // defined(ASIO_HAS_IOCP)++#include "asio/detail/push_options.hpp"++namespace asio {+namespace detail {++void create_pipe(native_pipe_handle p[2], asio::error_code& ec)+{+#if defined(ASIO_HAS_IOCP)+ using namespace std; // For sprintf and memcmp.++ static long counter1 = 0;+ static long counter2 = 0;++ long n1 = ::InterlockedIncrement(&counter1);+ long n2 = (static_cast<unsigned long>(n1) % 0x10000000) == 0+ ? ::InterlockedIncrement(&counter2)+ : ::InterlockedExchangeAdd(&counter2, 0);++ wchar_t pipe_name[128];+#if defined(ASIO_HAS_SECURE_RTL)+ swprintf_s(+#else // defined(ASIO_HAS_SECURE_RTL)+ _snwprintf(+#endif // defined(ASIO_HAS_SECURE_RTL)+ pipe_name, 128,+ L"\\\\.\\pipe\\asio-A0812896-741A-484D-AF23-BE51BF620E22-%u-%ld-%ld",+ static_cast<unsigned int>(::GetCurrentProcessId()), n1, n2);++ p[0] = ::CreateNamedPipeW(pipe_name,+ PIPE_ACCESS_INBOUND | FILE_FLAG_OVERLAPPED,+ 0, 1, 8192, 8192, 0, 0);++ if (p[0] == INVALID_HANDLE_VALUE)+ {+ DWORD last_error = ::GetLastError();+ ec.assign(last_error, asio::error::get_system_category());+ return;+ }++ p[1] = ::CreateFileW(pipe_name, GENERIC_WRITE, 0,+ 0, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, 0);++ if (p[1] == INVALID_HANDLE_VALUE)+ {+ DWORD last_error = ::GetLastError();+ ::CloseHandle(p[0]);+ ec.assign(last_error, asio::error::get_system_category());+ return;+ }++# if _WIN32_WINNT >= 0x601+ unsigned char nonce[16];+ if (::BCryptGenRandom(0, nonce, sizeof(nonce),+ BCRYPT_USE_SYSTEM_PREFERRED_RNG) != 0)+ {+ ec = asio::error::connection_aborted;+ ::CloseHandle(p[0]);+ ::CloseHandle(p[1]);+ return;+ }++ DWORD bytes_written = 0;+ BOOL ok = ::WriteFile(p[1], nonce, sizeof(nonce), &bytes_written, 0);+ if (!ok || bytes_written != sizeof(nonce))+ {+ ec = asio::error::connection_aborted;+ ::CloseHandle(p[0]);+ ::CloseHandle(p[1]);+ return;+ }++ unsigned char nonce_check[sizeof(nonce)];+ DWORD bytes_read = 0;+ ok = ::ReadFile(p[0], nonce_check, sizeof(nonce), &bytes_read, 0);+ if (!ok || bytes_read != sizeof(nonce)+ || memcmp(nonce, nonce_check, sizeof(nonce)) != 0)+ {+ ec = asio::error::connection_aborted;+ ::CloseHandle(p[0]);+ ::CloseHandle(p[1]);+ return;+ }+#endif // _WIN32_WINNT >= 0x601++ asio::error::clear(ec);+#else // defined(ASIO_HAS_IOCP)+ int result = ::pipe(p);+ detail::descriptor_ops::get_last_error(ec, result != 0);+#endif // defined(ASIO_HAS_IOCP)+}++void close_pipe(native_pipe_handle p)+{+#if defined(ASIO_HAS_IOCP)+ ::CloseHandle(p);+#else // defined(ASIO_HAS_IOCP)+ asio::error_code ignored_ec;+ detail::descriptor_ops::state_type state = 0;+ detail::descriptor_ops::close(p, state, ignored_ec);+#endif // defined(ASIO_HAS_IOCP)+}++} // namespace detail+} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // defined(ASIO_HAS_PIPE)++#endif // ASIO_IMPL_CONNECT_PIPE_IPP
+ link/modules/asio-standalone/asio/include/asio/impl/consign.hpp view
@@ -0,0 +1,202 @@+//+// impl/consign.hpp+// ~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com)+//+// Distributed under the Boost Software License, Version 1.0. (See accompanying+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)+//++#ifndef ASIO_IMPL_CONSIGN_HPP+#define ASIO_IMPL_CONSIGN_HPP++#if defined(_MSC_VER) && (_MSC_VER >= 1200)+# pragma once+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)++#include "asio/detail/config.hpp"++#include "asio/associator.hpp"+#include "asio/async_result.hpp"+#include "asio/detail/handler_alloc_helpers.hpp"+#include "asio/detail/handler_cont_helpers.hpp"+#include "asio/detail/handler_invoke_helpers.hpp"+#include "asio/detail/type_traits.hpp"+#include "asio/detail/utility.hpp"+#include "asio/detail/variadic_templates.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {+namespace detail {++// Class to adapt a consign_t as a completion handler.+template <typename Handler, typename... Values>+class consign_handler+{+public:+ typedef void result_type;++ template <typename H>+ consign_handler(ASIO_MOVE_ARG(H) handler, std::tuple<Values...> values)+ : handler_(ASIO_MOVE_CAST(H)(handler)),+ values_(ASIO_MOVE_CAST(std::tuple<Values...>)(values))+ {+ }++ template <typename... Args>+ void operator()(ASIO_MOVE_ARG(Args)... args)+ {+ ASIO_MOVE_OR_LVALUE(Handler)(handler_)(+ ASIO_MOVE_CAST(Args)(args)...);+ }++//private:+ Handler handler_;+ std::tuple<Values...> values_;+};++template <typename Handler>+inline asio_handler_allocate_is_deprecated+asio_handler_allocate(std::size_t size,+ consign_handler<Handler>* this_handler)+{+#if defined(ASIO_NO_DEPRECATED)+ asio_handler_alloc_helpers::allocate(size, this_handler->handler_);+ return asio_handler_allocate_is_no_longer_used();+#else // defined(ASIO_NO_DEPRECATED)+ return asio_handler_alloc_helpers::allocate(+ size, this_handler->handler_);+#endif // defined(ASIO_NO_DEPRECATED)+}++template <typename Handler>+inline asio_handler_deallocate_is_deprecated+asio_handler_deallocate(void* pointer, std::size_t size,+ consign_handler<Handler>* this_handler)+{+ asio_handler_alloc_helpers::deallocate(+ pointer, size, this_handler->handler_);+#if defined(ASIO_NO_DEPRECATED)+ return asio_handler_deallocate_is_no_longer_used();+#endif // defined(ASIO_NO_DEPRECATED)+}++template <typename Handler>+inline bool asio_handler_is_continuation(+ consign_handler<Handler>* this_handler)+{+ return asio_handler_cont_helpers::is_continuation(+ this_handler->handler_);+}++template <typename Function, typename Handler>+inline asio_handler_invoke_is_deprecated+asio_handler_invoke(Function& function,+ consign_handler<Handler>* this_handler)+{+ asio_handler_invoke_helpers::invoke(+ function, this_handler->handler_);+#if defined(ASIO_NO_DEPRECATED)+ return asio_handler_invoke_is_no_longer_used();+#endif // defined(ASIO_NO_DEPRECATED)+}++template <typename Function, typename Handler>+inline asio_handler_invoke_is_deprecated+asio_handler_invoke(const Function& function,+ consign_handler<Handler>* this_handler)+{+ asio_handler_invoke_helpers::invoke(+ function, this_handler->handler_);+#if defined(ASIO_NO_DEPRECATED)+ return asio_handler_invoke_is_no_longer_used();+#endif // defined(ASIO_NO_DEPRECATED)+}++} // namespace detail++#if !defined(GENERATING_DOCUMENTATION)++template <typename CompletionToken, typename... Values, typename... Signatures>+struct async_result<+ consign_t<CompletionToken, Values...>, Signatures...>+ : async_result<CompletionToken, Signatures...>+{+ template <typename Initiation>+ struct init_wrapper+ {+ init_wrapper(Initiation init)+ : initiation_(ASIO_MOVE_CAST(Initiation)(init))+ {+ }++ template <typename Handler, typename... Args>+ void operator()(+ ASIO_MOVE_ARG(Handler) handler,+ std::tuple<Values...> values,+ ASIO_MOVE_ARG(Args)... args)+ {+ ASIO_MOVE_CAST(Initiation)(initiation_)(+ detail::consign_handler<+ typename decay<Handler>::type, Values...>(+ ASIO_MOVE_CAST(Handler)(handler),+ ASIO_MOVE_CAST(std::tuple<Values...>)(values)),+ ASIO_MOVE_CAST(Args)(args)...);+ }++ Initiation initiation_;+ };++ template <typename Initiation, typename RawCompletionToken, typename... Args>+ static ASIO_INITFN_DEDUCED_RESULT_TYPE(CompletionToken, Signatures...,+ (async_initiate<CompletionToken, Signatures...>(+ declval<init_wrapper<typename decay<Initiation>::type> >(),+ declval<CompletionToken&>(),+ declval<std::tuple<Values...> >(),+ declval<ASIO_MOVE_ARG(Args)>()...)))+ initiate(+ ASIO_MOVE_ARG(Initiation) initiation,+ ASIO_MOVE_ARG(RawCompletionToken) token,+ ASIO_MOVE_ARG(Args)... args)+ {+ return async_initiate<CompletionToken, Signatures...>(+ init_wrapper<typename decay<Initiation>::type>(+ ASIO_MOVE_CAST(Initiation)(initiation)),+ token.token_,+ ASIO_MOVE_CAST(std::tuple<Values...>)(token.values_),+ ASIO_MOVE_CAST(Args)(args)...);+ }+};++template <template <typename, typename> class Associator,+ typename Handler, typename... Values, typename DefaultCandidate>+struct associator<Associator,+ detail::consign_handler<Handler, Values...>, DefaultCandidate>+ : Associator<Handler, DefaultCandidate>+{+ static typename Associator<Handler, DefaultCandidate>::type+ get(const detail::consign_handler<Handler, Values...>& h) ASIO_NOEXCEPT+ {+ return Associator<Handler, DefaultCandidate>::get(h.handler_);+ }++ static ASIO_AUTO_RETURN_TYPE_PREFIX2(+ typename Associator<Handler, DefaultCandidate>::type)+ get(const detail::consign_handler<Handler, Values...>& h,+ const DefaultCandidate& c) ASIO_NOEXCEPT+ ASIO_AUTO_RETURN_TYPE_SUFFIX((+ Associator<Handler, DefaultCandidate>::get(h.handler_, c)))+ {+ return Associator<Handler, DefaultCandidate>::get(h.handler_, c);+ }+};++#endif // !defined(GENERATING_DOCUMENTATION)++} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // ASIO_IMPL_CONSIGN_HPP
− link/modules/asio-standalone/asio/include/asio/impl/defer.hpp
@@ -1,248 +0,0 @@-//-// impl/defer.hpp-// ~~~~~~~~~~~~~~-//-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)-//-// Distributed under the Boost Software License, Version 1.0. (See accompanying-// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)-//--#ifndef ASIO_IMPL_DEFER_HPP-#define ASIO_IMPL_DEFER_HPP--#if defined(_MSC_VER) && (_MSC_VER >= 1200)-# pragma once-#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)--#include "asio/detail/config.hpp"-#include "asio/associated_allocator.hpp"-#include "asio/associated_executor.hpp"-#include "asio/detail/work_dispatcher.hpp"-#include "asio/execution/allocator.hpp"-#include "asio/execution/blocking.hpp"-#include "asio/execution/relationship.hpp"-#include "asio/prefer.hpp"-#include "asio/require.hpp"--#include "asio/detail/push_options.hpp"--namespace asio {-namespace detail {--class initiate_defer-{-public:- template <typename CompletionHandler>- void operator()(ASIO_MOVE_ARG(CompletionHandler) handler,- typename enable_if<- execution::is_executor<- typename associated_executor<- typename decay<CompletionHandler>::type- >::type- >::value- >::type* = 0) const- {- typedef typename decay<CompletionHandler>::type handler_t;-- typename associated_executor<handler_t>::type ex(- (get_associated_executor)(handler));-- typename associated_allocator<handler_t>::type alloc(- (get_associated_allocator)(handler));-- execution::execute(- asio::prefer(- asio::require(ex, execution::blocking.never),- execution::relationship.continuation,- execution::allocator(alloc)),- ASIO_MOVE_CAST(CompletionHandler)(handler));- }-- template <typename CompletionHandler>- void operator()(ASIO_MOVE_ARG(CompletionHandler) handler,- typename enable_if<- !execution::is_executor<- typename associated_executor<- typename decay<CompletionHandler>::type- >::type- >::value- >::type* = 0) const- {- typedef typename decay<CompletionHandler>::type handler_t;-- typename associated_executor<handler_t>::type ex(- (get_associated_executor)(handler));-- typename associated_allocator<handler_t>::type alloc(- (get_associated_allocator)(handler));-- ex.defer(ASIO_MOVE_CAST(CompletionHandler)(handler), alloc);- }-};--template <typename Executor>-class initiate_defer_with_executor-{-public:- typedef Executor executor_type;-- explicit initiate_defer_with_executor(const Executor& ex)- : ex_(ex)- {- }-- executor_type get_executor() const ASIO_NOEXCEPT- {- return ex_;- }-- template <typename CompletionHandler>- void operator()(ASIO_MOVE_ARG(CompletionHandler) handler,- typename enable_if<- execution::is_executor<- typename conditional<true, executor_type, CompletionHandler>::type- >::value- &&- !detail::is_work_dispatcher_required<- typename decay<CompletionHandler>::type,- Executor- >::value- >::type* = 0) const- {- typedef typename decay<CompletionHandler>::type handler_t;-- typename associated_allocator<handler_t>::type alloc(- (get_associated_allocator)(handler));-- execution::execute(- asio::prefer(- asio::require(ex_, execution::blocking.never),- execution::relationship.continuation,- execution::allocator(alloc)),- ASIO_MOVE_CAST(CompletionHandler)(handler));- }-- template <typename CompletionHandler>- void operator()(ASIO_MOVE_ARG(CompletionHandler) handler,- typename enable_if<- execution::is_executor<- typename conditional<true, executor_type, CompletionHandler>::type- >::value- &&- detail::is_work_dispatcher_required<- typename decay<CompletionHandler>::type,- Executor- >::value- >::type* = 0) const- {- typedef typename decay<CompletionHandler>::type handler_t;-- typedef typename associated_executor<- handler_t, Executor>::type handler_ex_t;- handler_ex_t handler_ex((get_associated_executor)(handler, ex_));-- typename associated_allocator<handler_t>::type alloc(- (get_associated_allocator)(handler));-- execution::execute(- asio::prefer(- asio::require(ex_, execution::blocking.never),- execution::relationship.continuation,- execution::allocator(alloc)),- detail::work_dispatcher<handler_t, handler_ex_t>(- ASIO_MOVE_CAST(CompletionHandler)(handler), handler_ex));- }-- template <typename CompletionHandler>- void operator()(ASIO_MOVE_ARG(CompletionHandler) handler,- typename enable_if<- !execution::is_executor<- typename conditional<true, executor_type, CompletionHandler>::type- >::value- &&- !detail::is_work_dispatcher_required<- typename decay<CompletionHandler>::type,- Executor- >::value- >::type* = 0) const- {- typedef typename decay<CompletionHandler>::type handler_t;-- typename associated_allocator<handler_t>::type alloc(- (get_associated_allocator)(handler));-- ex_.defer(ASIO_MOVE_CAST(CompletionHandler)(handler), alloc);- }-- template <typename CompletionHandler>- void operator()(ASIO_MOVE_ARG(CompletionHandler) handler,- typename enable_if<- !execution::is_executor<- typename conditional<true, executor_type, CompletionHandler>::type- >::value- &&- detail::is_work_dispatcher_required<- typename decay<CompletionHandler>::type,- Executor- >::value- >::type* = 0) const- {- typedef typename decay<CompletionHandler>::type handler_t;-- typedef typename associated_executor<- handler_t, Executor>::type handler_ex_t;- handler_ex_t handler_ex((get_associated_executor)(handler, ex_));-- typename associated_allocator<handler_t>::type alloc(- (get_associated_allocator)(handler));-- ex_.defer(detail::work_dispatcher<handler_t, handler_ex_t>(- ASIO_MOVE_CAST(CompletionHandler)(handler),- handler_ex), alloc);- }--private:- Executor ex_;-};--} // namespace detail--template <ASIO_COMPLETION_TOKEN_FOR(void()) CompletionToken>-ASIO_INITFN_AUTO_RESULT_TYPE(CompletionToken, void()) defer(- ASIO_MOVE_ARG(CompletionToken) token)-{- return async_initiate<CompletionToken, void()>(- detail::initiate_defer(), token);-}--template <typename Executor,- ASIO_COMPLETION_TOKEN_FOR(void()) CompletionToken>-ASIO_INITFN_AUTO_RESULT_TYPE(CompletionToken, void()) defer(- const Executor& ex, ASIO_MOVE_ARG(CompletionToken) token,- typename enable_if<- execution::is_executor<Executor>::value || is_executor<Executor>::value- >::type*)-{- return async_initiate<CompletionToken, void()>(- detail::initiate_defer_with_executor<Executor>(ex), token);-}--template <typename ExecutionContext,- ASIO_COMPLETION_TOKEN_FOR(void()) CompletionToken>-inline ASIO_INITFN_AUTO_RESULT_TYPE(CompletionToken, void()) defer(- ExecutionContext& ctx, ASIO_MOVE_ARG(CompletionToken) token,- typename enable_if<is_convertible<- ExecutionContext&, execution_context&>::value>::type*)-{- return async_initiate<CompletionToken, void()>(- detail::initiate_defer_with_executor<- typename ExecutionContext::executor_type>(- ctx.get_executor()), token);-}--} // namespace asio--#include "asio/detail/pop_options.hpp"--#endif // ASIO_IMPL_DEFER_HPP
+ link/modules/asio-standalone/asio/include/asio/impl/deferred.hpp view
@@ -0,0 +1,156 @@+//+// impl/deferred.hpp+// ~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com)+//+// Distributed under the Boost Software License, Version 1.0. (See accompanying+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)+//++#ifndef ASIO_IMPL_DEFERRED_HPP+#define ASIO_IMPL_DEFERRED_HPP++#if defined(_MSC_VER) && (_MSC_VER >= 1200)+# pragma once+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)++#include "asio/detail/push_options.hpp"++namespace asio {++#if !defined(GENERATING_DOCUMENTATION)++template <typename Signature>+class async_result<deferred_t, Signature>+{+public:+ template <typename Initiation, typename... InitArgs>+ static deferred_async_operation<Signature, Initiation, InitArgs...>+ initiate(ASIO_MOVE_ARG(Initiation) initiation,+ deferred_t, ASIO_MOVE_ARG(InitArgs)... args)+ {+ return deferred_async_operation<+ Signature, Initiation, InitArgs...>(+ deferred_init_tag{},+ ASIO_MOVE_CAST(Initiation)(initiation),+ ASIO_MOVE_CAST(InitArgs)(args)...);+ }+};++template <typename... Signatures>+class async_result<deferred_t, Signatures...>+{+public:+ template <typename Initiation, typename... InitArgs>+ static deferred_async_operation<+ deferred_signatures<Signatures...>, Initiation, InitArgs...>+ initiate(ASIO_MOVE_ARG(Initiation) initiation,+ deferred_t, ASIO_MOVE_ARG(InitArgs)... args)+ {+ return deferred_async_operation<+ deferred_signatures<Signatures...>, Initiation, InitArgs...>(+ deferred_init_tag{},+ ASIO_MOVE_CAST(Initiation)(initiation),+ ASIO_MOVE_CAST(InitArgs)(args)...);+ }+};++template <typename Function, typename Signature>+class async_result<deferred_function<Function>, Signature>+{+public:+ template <typename Initiation, typename... InitArgs>+ static auto initiate(ASIO_MOVE_ARG(Initiation) initiation,+ deferred_function<Function> token,+ ASIO_MOVE_ARG(InitArgs)... init_args)+ -> decltype(+ deferred_sequence<+ deferred_async_operation<+ Signature, Initiation, InitArgs...>,+ Function>(deferred_init_tag{},+ deferred_async_operation<+ Signature, Initiation, InitArgs...>(+ deferred_init_tag{},+ ASIO_MOVE_CAST(Initiation)(initiation),+ ASIO_MOVE_CAST(InitArgs)(init_args)...),+ ASIO_MOVE_CAST(Function)(token.function_)))+ {+ return deferred_sequence<+ deferred_async_operation<+ Signature, Initiation, InitArgs...>,+ Function>(deferred_init_tag{},+ deferred_async_operation<+ Signature, Initiation, InitArgs...>(+ deferred_init_tag{},+ ASIO_MOVE_CAST(Initiation)(initiation),+ ASIO_MOVE_CAST(InitArgs)(init_args)...),+ ASIO_MOVE_CAST(Function)(token.function_));+ }+};++template <typename Function, typename... Signatures>+class async_result<deferred_function<Function>, Signatures...>+{+public:+ template <typename Initiation, typename... InitArgs>+ static auto initiate(ASIO_MOVE_ARG(Initiation) initiation,+ deferred_function<Function> token,+ ASIO_MOVE_ARG(InitArgs)... init_args)+ -> decltype(+ deferred_sequence<+ deferred_async_operation<+ deferred_signatures<Signatures...>, Initiation, InitArgs...>,+ Function>(deferred_init_tag{},+ deferred_async_operation<+ deferred_signatures<Signatures...>, Initiation, InitArgs...>(+ deferred_init_tag{},+ ASIO_MOVE_CAST(Initiation)(initiation),+ ASIO_MOVE_CAST(InitArgs)(init_args)...),+ ASIO_MOVE_CAST(Function)(token.function_)))+ {+ return deferred_sequence<+ deferred_async_operation<+ deferred_signatures<Signatures...>, Initiation, InitArgs...>,+ Function>(deferred_init_tag{},+ deferred_async_operation<+ deferred_signatures<Signatures...>, Initiation, InitArgs...>(+ deferred_init_tag{},+ ASIO_MOVE_CAST(Initiation)(initiation),+ ASIO_MOVE_CAST(InitArgs)(init_args)...),+ ASIO_MOVE_CAST(Function)(token.function_));+ }+};++template <template <typename, typename> class Associator,+ typename Handler, typename Tail, typename DefaultCandidate>+struct associator<Associator,+ detail::deferred_sequence_handler<Handler, Tail>,+ DefaultCandidate>+ : Associator<Handler, DefaultCandidate>+{+ static typename Associator<Handler, DefaultCandidate>::type+ get(const detail::deferred_sequence_handler<Handler, Tail>& h)+ ASIO_NOEXCEPT+ {+ return Associator<Handler, DefaultCandidate>::get(h.handler_);+ }++ static ASIO_AUTO_RETURN_TYPE_PREFIX2(+ typename Associator<Handler, DefaultCandidate>::type)+ get(const detail::deferred_sequence_handler<Handler, Tail>& h,+ const DefaultCandidate& c) ASIO_NOEXCEPT+ ASIO_AUTO_RETURN_TYPE_SUFFIX((+ Associator<Handler, DefaultCandidate>::get(h.handler_, c)))+ {+ return Associator<Handler, DefaultCandidate>::get(h.handler_, c);+ }+};++#endif // !defined(GENERATING_DOCUMENTATION)++} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // ASIO_IMPL_DEFERRED_HPP
link/modules/asio-standalone/asio/include/asio/impl/detached.hpp view
@@ -2,7 +2,7 @@ // impl/detached.hpp // ~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
− link/modules/asio-standalone/asio/include/asio/impl/dispatch.hpp
@@ -1,243 +0,0 @@-//-// impl/dispatch.hpp-// ~~~~~~~~~~~~~~~~~-//-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)-//-// Distributed under the Boost Software License, Version 1.0. (See accompanying-// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)-//--#ifndef ASIO_IMPL_DISPATCH_HPP-#define ASIO_IMPL_DISPATCH_HPP--#if defined(_MSC_VER) && (_MSC_VER >= 1200)-# pragma once-#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)--#include "asio/detail/config.hpp"-#include "asio/associated_allocator.hpp"-#include "asio/associated_executor.hpp"-#include "asio/detail/work_dispatcher.hpp"-#include "asio/execution/allocator.hpp"-#include "asio/execution/blocking.hpp"-#include "asio/prefer.hpp"--#include "asio/detail/push_options.hpp"--namespace asio {-namespace detail {--class initiate_dispatch-{-public:- template <typename CompletionHandler>- void operator()(ASIO_MOVE_ARG(CompletionHandler) handler,- typename enable_if<- execution::is_executor<- typename associated_executor<- typename decay<CompletionHandler>::type- >::type- >::value- >::type* = 0) const- {- typedef typename decay<CompletionHandler>::type handler_t;-- typename associated_executor<handler_t>::type ex(- (get_associated_executor)(handler));-- typename associated_allocator<handler_t>::type alloc(- (get_associated_allocator)(handler));-- execution::execute(- asio::prefer(ex,- execution::blocking.possibly,- execution::allocator(alloc)),- ASIO_MOVE_CAST(CompletionHandler)(handler));- }-- template <typename CompletionHandler>- void operator()(ASIO_MOVE_ARG(CompletionHandler) handler,- typename enable_if<- !execution::is_executor<- typename associated_executor<- typename decay<CompletionHandler>::type- >::type- >::value- >::type* = 0) const- {- typedef typename decay<CompletionHandler>::type handler_t;-- typename associated_executor<handler_t>::type ex(- (get_associated_executor)(handler));-- typename associated_allocator<handler_t>::type alloc(- (get_associated_allocator)(handler));-- ex.dispatch(ASIO_MOVE_CAST(CompletionHandler)(handler), alloc);- }-};--template <typename Executor>-class initiate_dispatch_with_executor-{-public:- typedef Executor executor_type;-- explicit initiate_dispatch_with_executor(const Executor& ex)- : ex_(ex)- {- }-- executor_type get_executor() const ASIO_NOEXCEPT- {- return ex_;- }-- template <typename CompletionHandler>- void operator()(ASIO_MOVE_ARG(CompletionHandler) handler,- typename enable_if<- execution::is_executor<- typename conditional<true, executor_type, CompletionHandler>::type- >::value- &&- !detail::is_work_dispatcher_required<- typename decay<CompletionHandler>::type,- Executor- >::value- >::type* = 0) const- {- typedef typename decay<CompletionHandler>::type handler_t;-- typename associated_allocator<handler_t>::type alloc(- (get_associated_allocator)(handler));-- execution::execute(- asio::prefer(ex_,- execution::blocking.possibly,- execution::allocator(alloc)),- ASIO_MOVE_CAST(CompletionHandler)(handler));- }-- template <typename CompletionHandler>- void operator()(ASIO_MOVE_ARG(CompletionHandler) handler,- typename enable_if<- execution::is_executor<- typename conditional<true, executor_type, CompletionHandler>::type- >::value- &&- detail::is_work_dispatcher_required<- typename decay<CompletionHandler>::type,- Executor- >::value- >::type* = 0) const- {- typedef typename decay<CompletionHandler>::type handler_t;-- typedef typename associated_executor<- handler_t, Executor>::type handler_ex_t;- handler_ex_t handler_ex((get_associated_executor)(handler, ex_));-- typename associated_allocator<handler_t>::type alloc(- (get_associated_allocator)(handler));-- execution::execute(- asio::prefer(ex_,- execution::blocking.possibly,- execution::allocator(alloc)),- detail::work_dispatcher<handler_t, handler_ex_t>(- ASIO_MOVE_CAST(CompletionHandler)(handler), handler_ex));- }-- template <typename CompletionHandler>- void operator()(ASIO_MOVE_ARG(CompletionHandler) handler,- typename enable_if<- !execution::is_executor<- typename conditional<true, executor_type, CompletionHandler>::type- >::value- &&- !detail::is_work_dispatcher_required<- typename decay<CompletionHandler>::type,- Executor- >::value- >::type* = 0) const- {- typedef typename decay<CompletionHandler>::type handler_t;-- typename associated_allocator<handler_t>::type alloc(- (get_associated_allocator)(handler));-- ex_.dispatch(ASIO_MOVE_CAST(CompletionHandler)(handler), alloc);- }-- template <typename CompletionHandler>- void operator()(ASIO_MOVE_ARG(CompletionHandler) handler,- typename enable_if<- !execution::is_executor<- typename conditional<true, executor_type, CompletionHandler>::type- >::value- &&- detail::is_work_dispatcher_required<- typename decay<CompletionHandler>::type,- Executor- >::value- >::type* = 0) const- {- typedef typename decay<CompletionHandler>::type handler_t;-- typedef typename associated_executor<- handler_t, Executor>::type handler_ex_t;- handler_ex_t handler_ex((get_associated_executor)(handler, ex_));-- typename associated_allocator<handler_t>::type alloc(- (get_associated_allocator)(handler));-- ex_.dispatch(detail::work_dispatcher<handler_t, handler_ex_t>(- ASIO_MOVE_CAST(CompletionHandler)(handler),- handler_ex), alloc);- }--private:- Executor ex_;-};--} // namespace detail--template <ASIO_COMPLETION_TOKEN_FOR(void()) CompletionToken>-ASIO_INITFN_AUTO_RESULT_TYPE(CompletionToken, void()) dispatch(- ASIO_MOVE_ARG(CompletionToken) token)-{- return async_initiate<CompletionToken, void()>(- detail::initiate_dispatch(), token);-}--template <typename Executor,- ASIO_COMPLETION_TOKEN_FOR(void()) CompletionToken>-ASIO_INITFN_AUTO_RESULT_TYPE(CompletionToken, void()) dispatch(- const Executor& ex, ASIO_MOVE_ARG(CompletionToken) token,- typename enable_if<- execution::is_executor<Executor>::value || is_executor<Executor>::value- >::type*)-{- return async_initiate<CompletionToken, void()>(- detail::initiate_dispatch_with_executor<Executor>(ex), token);-}--template <typename ExecutionContext,- ASIO_COMPLETION_TOKEN_FOR(void()) CompletionToken>-inline ASIO_INITFN_AUTO_RESULT_TYPE(CompletionToken, void()) dispatch(- ExecutionContext& ctx, ASIO_MOVE_ARG(CompletionToken) token,- typename enable_if<is_convertible<- ExecutionContext&, execution_context&>::value>::type*)-{- return async_initiate<CompletionToken, void()>(- detail::initiate_dispatch_with_executor<- typename ExecutionContext::executor_type>(- ctx.get_executor()), token);-}--} // namespace asio--#include "asio/detail/pop_options.hpp"--#endif // ASIO_IMPL_DISPATCH_HPP
link/modules/asio-standalone/asio/include/asio/impl/error.ipp view
@@ -2,7 +2,7 @@ // impl/error.ipp // ~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/impl/error_code.ipp view
@@ -2,7 +2,7 @@ // impl/error_code.ipp // ~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/impl/execution_context.hpp view
@@ -2,7 +2,7 @@ // impl/execution_context.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/impl/execution_context.ipp view
@@ -2,7 +2,7 @@ // impl/execution_context.ipp // ~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/impl/executor.hpp view
@@ -2,7 +2,7 @@ // impl/executor.hpp // ~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -22,7 +22,6 @@ #include "asio/detail/atomic_count.hpp" #include "asio/detail/global.hpp" #include "asio/detail/memory.hpp"-#include "asio/detail/recycling_allocator.hpp" #include "asio/executor.hpp" #include "asio/system_executor.hpp"
link/modules/asio-standalone/asio/include/asio/impl/executor.ipp view
@@ -2,7 +2,7 @@ // impl/executor.ipp // ~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/impl/handler_alloc_hook.ipp view
@@ -2,7 +2,7 @@ // impl/handler_alloc_hook.ipp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -16,6 +16,7 @@ #endif // defined(_MSC_VER) && (_MSC_VER >= 1200) #include "asio/detail/config.hpp"+#include "asio/detail/memory.hpp" #include "asio/detail/thread_context.hpp" #include "asio/detail/thread_info_base.hpp" #include "asio/handler_alloc_hook.hpp"@@ -32,9 +33,9 @@ return asio_handler_allocate_is_no_longer_used(); #elif !defined(ASIO_DISABLE_SMALL_BLOCK_RECYCLING) return detail::thread_info_base::allocate(- detail::thread_context::thread_call_stack::top(), size);+ detail::thread_context::top_of_thread_call_stack(), size); #else // !defined(ASIO_DISABLE_SMALL_BLOCK_RECYCLING)- return ::operator new(size);+ return aligned_new(ASIO_DEFAULT_ALIGN, size); #endif // !defined(ASIO_DISABLE_SMALL_BLOCK_RECYCLING) } @@ -47,10 +48,10 @@ return asio_handler_deallocate_is_no_longer_used(); #elif !defined(ASIO_DISABLE_SMALL_BLOCK_RECYCLING) detail::thread_info_base::deallocate(- detail::thread_context::thread_call_stack::top(), pointer, size);+ detail::thread_context::top_of_thread_call_stack(), pointer, size); #else // !defined(ASIO_DISABLE_SMALL_BLOCK_RECYCLING) (void)size;- ::operator delete(pointer);+ aligned_delete(pointer); #endif // !defined(ASIO_DISABLE_SMALL_BLOCK_RECYCLING) }
link/modules/asio-standalone/asio/include/asio/impl/io_context.hpp view
@@ -2,7 +2,7 @@ // impl/io_context.hpp // ~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -20,7 +20,6 @@ #include "asio/detail/fenced_block.hpp" #include "asio/detail/handler_type_requirements.hpp" #include "asio/detail/non_const_lvalue.hpp"-#include "asio/detail/recycling_allocator.hpp" #include "asio/detail/service_registry.hpp" #include "asio/detail/throw_error.hpp" #include "asio/detail/type_traits.hpp"@@ -155,8 +154,11 @@ }; template <typename LegacyCompletionHandler>-ASIO_INITFN_AUTO_RESULT_TYPE(LegacyCompletionHandler, void ())+ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX(LegacyCompletionHandler, void ()) io_context::dispatch(ASIO_MOVE_ARG(LegacyCompletionHandler) handler)+ ASIO_INITFN_AUTO_RESULT_TYPE_SUFFIX((+ async_initiate<LegacyCompletionHandler, void ()>(+ declval<initiate_dispatch>(), handler, this))) { return async_initiate<LegacyCompletionHandler, void ()>( initiate_dispatch(), handler, this);@@ -194,8 +196,11 @@ }; template <typename LegacyCompletionHandler>-ASIO_INITFN_AUTO_RESULT_TYPE(LegacyCompletionHandler, void ())+ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX(LegacyCompletionHandler, void ()) io_context::post(ASIO_MOVE_ARG(LegacyCompletionHandler) handler)+ ASIO_INITFN_AUTO_RESULT_TYPE_SUFFIX((+ async_initiate<LegacyCompletionHandler, void ()>(+ declval<initiate_post>(), handler, this))) { return async_initiate<LegacyCompletionHandler, void ()>( initiate_post(), handler, this);@@ -214,21 +219,20 @@ #endif // !defined(ASIO_NO_DEPRECATED) -template <typename Allocator, unsigned int Bits>+template <typename Allocator, uintptr_t Bits> io_context::basic_executor_type<Allocator, Bits>& io_context::basic_executor_type<Allocator, Bits>::operator=( const basic_executor_type& other) ASIO_NOEXCEPT { if (this != &other) {- io_context* old_io_context = io_context_;- io_context_ = other.io_context_;- allocator_ = other.allocator_;- bits_ = other.bits_;+ static_cast<Allocator&>(*this) = static_cast<const Allocator&>(other);+ io_context* old_io_context = context_ptr();+ target_ = other.target_; if (Bits & outstanding_work_tracked) {- if (io_context_)- io_context_->impl_.work_started();+ if (context_ptr())+ context_ptr()->impl_.work_started(); if (old_io_context) old_io_context->impl_.work_finished(); }@@ -237,31 +241,35 @@ } #if defined(ASIO_HAS_MOVE)-template <typename Allocator, unsigned int Bits>+template <typename Allocator, uintptr_t Bits> io_context::basic_executor_type<Allocator, Bits>& io_context::basic_executor_type<Allocator, Bits>::operator=( basic_executor_type&& other) ASIO_NOEXCEPT { if (this != &other) {- io_context_ = other.io_context_;- allocator_ = std::move(other.allocator_);- bits_ = other.bits_;+ static_cast<Allocator&>(*this) = static_cast<Allocator&&>(other);+ io_context* old_io_context = context_ptr();+ target_ = other.target_; if (Bits & outstanding_work_tracked)- other.io_context_ = 0;+ {+ other.target_ = 0;+ if (old_io_context)+ old_io_context->impl_.work_finished();+ } } return *this; } #endif // defined(ASIO_HAS_MOVE) -template <typename Allocator, unsigned int Bits>+template <typename Allocator, uintptr_t Bits> inline bool io_context::basic_executor_type<Allocator, Bits>::running_in_this_thread() const ASIO_NOEXCEPT {- return io_context_->impl_.can_dispatch();+ return context_ptr()->impl_.can_dispatch(); } -template <typename Allocator, unsigned int Bits>+template <typename Allocator, uintptr_t Bits> template <typename Function> void io_context::basic_executor_type<Allocator, Bits>::execute( ASIO_MOVE_ARG(Function) f) const@@ -270,7 +278,7 @@ // Invoke immediately if the blocking.possibly property is enabled and we are // already inside the thread pool.- if ((bits_ & blocking_never) == 0 && io_context_->impl_.can_dispatch())+ if ((bits() & blocking_never) == 0 && context_ptr()->impl_.can_dispatch()) { // Make a local, non-const copy of the function. function_type tmp(ASIO_MOVE_CAST(Function)(f));@@ -289,7 +297,7 @@ } catch (...) {- io_context_->impl_.capture_current_exception();+ context_ptr()->impl_.capture_current_exception(); return; } #endif // defined(ASIO_HAS_STD_EXCEPTION_PTR)@@ -298,41 +306,43 @@ // Allocate and construct an operation to wrap the function. typedef detail::executor_op<function_type, Allocator, detail::operation> op;- typename op::ptr p = { detail::addressof(allocator_),- op::ptr::allocate(allocator_), 0 };- p.p = new (p.v) op(ASIO_MOVE_CAST(Function)(f), allocator_);+ typename op::ptr p = {+ detail::addressof(static_cast<const Allocator&>(*this)),+ op::ptr::allocate(static_cast<const Allocator&>(*this)), 0 };+ p.p = new (p.v) op(ASIO_MOVE_CAST(Function)(f),+ static_cast<const Allocator&>(*this)); - ASIO_HANDLER_CREATION((*io_context_, *p.p,- "io_context", io_context_, 0, "execute"));+ ASIO_HANDLER_CREATION((*context_ptr(), *p.p,+ "io_context", context_ptr(), 0, "execute")); - io_context_->impl_.post_immediate_completion(p.p,- (bits_ & relationship_continuation) != 0);+ context_ptr()->impl_.post_immediate_completion(p.p,+ (bits() & relationship_continuation) != 0); p.v = p.p = 0; } #if !defined(ASIO_NO_TS_EXECUTORS)-template <typename Allocator, unsigned int Bits>+template <typename Allocator, uintptr_t Bits> inline io_context& io_context::basic_executor_type< Allocator, Bits>::context() const ASIO_NOEXCEPT {- return *io_context_;+ return *context_ptr(); } -template <typename Allocator, unsigned int Bits>+template <typename Allocator, uintptr_t Bits> inline void io_context::basic_executor_type<Allocator, Bits>::on_work_started() const ASIO_NOEXCEPT {- io_context_->impl_.work_started();+ context_ptr()->impl_.work_started(); } -template <typename Allocator, unsigned int Bits>+template <typename Allocator, uintptr_t Bits> inline void io_context::basic_executor_type<Allocator, Bits>::on_work_finished() const ASIO_NOEXCEPT {- io_context_->impl_.work_finished();+ context_ptr()->impl_.work_finished(); } -template <typename Allocator, unsigned int Bits>+template <typename Allocator, uintptr_t Bits> template <typename Function, typename OtherAllocator> void io_context::basic_executor_type<Allocator, Bits>::dispatch( ASIO_MOVE_ARG(Function) f, const OtherAllocator& a) const@@ -340,7 +350,7 @@ typedef typename decay<Function>::type function_type; // Invoke immediately if we are already inside the thread pool.- if (io_context_->impl_.can_dispatch())+ if (context_ptr()->impl_.can_dispatch()) { // Make a local, non-const copy of the function. function_type tmp(ASIO_MOVE_CAST(Function)(f));@@ -356,14 +366,14 @@ typename op::ptr p = { detail::addressof(a), op::ptr::allocate(a), 0 }; p.p = new (p.v) op(ASIO_MOVE_CAST(Function)(f), a); - ASIO_HANDLER_CREATION((*io_context_, *p.p,- "io_context", io_context_, 0, "dispatch"));+ ASIO_HANDLER_CREATION((*context_ptr(), *p.p,+ "io_context", context_ptr(), 0, "dispatch")); - io_context_->impl_.post_immediate_completion(p.p, false);+ context_ptr()->impl_.post_immediate_completion(p.p, false); p.v = p.p = 0; } -template <typename Allocator, unsigned int Bits>+template <typename Allocator, uintptr_t Bits> template <typename Function, typename OtherAllocator> void io_context::basic_executor_type<Allocator, Bits>::post( ASIO_MOVE_ARG(Function) f, const OtherAllocator& a) const@@ -376,14 +386,14 @@ typename op::ptr p = { detail::addressof(a), op::ptr::allocate(a), 0 }; p.p = new (p.v) op(ASIO_MOVE_CAST(Function)(f), a); - ASIO_HANDLER_CREATION((*io_context_, *p.p,- "io_context", io_context_, 0, "post"));+ ASIO_HANDLER_CREATION((*context_ptr(), *p.p,+ "io_context", context_ptr(), 0, "post")); - io_context_->impl_.post_immediate_completion(p.p, false);+ context_ptr()->impl_.post_immediate_completion(p.p, false); p.v = p.p = 0; } -template <typename Allocator, unsigned int Bits>+template <typename Allocator, uintptr_t Bits> template <typename Function, typename OtherAllocator> void io_context::basic_executor_type<Allocator, Bits>::defer( ASIO_MOVE_ARG(Function) f, const OtherAllocator& a) const@@ -396,10 +406,10 @@ typename op::ptr p = { detail::addressof(a), op::ptr::allocate(a), 0 }; p.p = new (p.v) op(ASIO_MOVE_CAST(Function)(f), a); - ASIO_HANDLER_CREATION((*io_context_, *p.p,- "io_context", io_context_, 0, "defer"));+ ASIO_HANDLER_CREATION((*context_ptr(), *p.p,+ "io_context", context_ptr(), 0, "defer")); - io_context_->impl_.post_immediate_completion(p.p, true);+ context_ptr()->impl_.post_immediate_completion(p.p, true); p.v = p.p = 0; } #endif // !defined(ASIO_NO_TS_EXECUTORS)
link/modules/asio-standalone/asio/include/asio/impl/io_context.ipp view
@@ -2,7 +2,7 @@ // impl/io_context.ipp // ~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -54,6 +54,7 @@ io_context::~io_context() {+ shutdown(); } io_context::count_type io_context::run()
link/modules/asio-standalone/asio/include/asio/impl/multiple_exceptions.ipp view
@@ -2,7 +2,7 @@ // impl/multiple_exceptions.ipp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
− link/modules/asio-standalone/asio/include/asio/impl/post.hpp
@@ -1,248 +0,0 @@-//-// impl/post.hpp-// ~~~~~~~~~~~~~-//-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)-//-// Distributed under the Boost Software License, Version 1.0. (See accompanying-// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)-//--#ifndef ASIO_IMPL_POST_HPP-#define ASIO_IMPL_POST_HPP--#if defined(_MSC_VER) && (_MSC_VER >= 1200)-# pragma once-#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)--#include "asio/detail/config.hpp"-#include "asio/associated_allocator.hpp"-#include "asio/associated_executor.hpp"-#include "asio/detail/work_dispatcher.hpp"-#include "asio/execution/allocator.hpp"-#include "asio/execution/blocking.hpp"-#include "asio/execution/relationship.hpp"-#include "asio/prefer.hpp"-#include "asio/require.hpp"--#include "asio/detail/push_options.hpp"--namespace asio {-namespace detail {--class initiate_post-{-public:- template <typename CompletionHandler>- void operator()(ASIO_MOVE_ARG(CompletionHandler) handler,- typename enable_if<- execution::is_executor<- typename associated_executor<- typename decay<CompletionHandler>::type- >::type- >::value- >::type* = 0) const- {- typedef typename decay<CompletionHandler>::type handler_t;-- typename associated_executor<handler_t>::type ex(- (get_associated_executor)(handler));-- typename associated_allocator<handler_t>::type alloc(- (get_associated_allocator)(handler));-- execution::execute(- asio::prefer(- asio::require(ex, execution::blocking.never),- execution::relationship.fork,- execution::allocator(alloc)),- ASIO_MOVE_CAST(CompletionHandler)(handler));- }-- template <typename CompletionHandler>- void operator()(ASIO_MOVE_ARG(CompletionHandler) handler,- typename enable_if<- !execution::is_executor<- typename associated_executor<- typename decay<CompletionHandler>::type- >::type- >::value- >::type* = 0) const- {- typedef typename decay<CompletionHandler>::type handler_t;-- typename associated_executor<handler_t>::type ex(- (get_associated_executor)(handler));-- typename associated_allocator<handler_t>::type alloc(- (get_associated_allocator)(handler));-- ex.post(ASIO_MOVE_CAST(CompletionHandler)(handler), alloc);- }-};--template <typename Executor>-class initiate_post_with_executor-{-public:- typedef Executor executor_type;-- explicit initiate_post_with_executor(const Executor& ex)- : ex_(ex)- {- }-- executor_type get_executor() const ASIO_NOEXCEPT- {- return ex_;- }-- template <typename CompletionHandler>- void operator()(ASIO_MOVE_ARG(CompletionHandler) handler,- typename enable_if<- execution::is_executor<- typename conditional<true, executor_type, CompletionHandler>::type- >::value- &&- !detail::is_work_dispatcher_required<- typename decay<CompletionHandler>::type,- Executor- >::value- >::type* = 0) const- {- typedef typename decay<CompletionHandler>::type handler_t;-- typename associated_allocator<handler_t>::type alloc(- (get_associated_allocator)(handler));-- execution::execute(- asio::prefer(- asio::require(ex_, execution::blocking.never),- execution::relationship.fork,- execution::allocator(alloc)),- ASIO_MOVE_CAST(CompletionHandler)(handler));- }-- template <typename CompletionHandler>- void operator()(ASIO_MOVE_ARG(CompletionHandler) handler,- typename enable_if<- execution::is_executor<- typename conditional<true, executor_type, CompletionHandler>::type- >::value- &&- detail::is_work_dispatcher_required<- typename decay<CompletionHandler>::type,- Executor- >::value- >::type* = 0) const- {- typedef typename decay<CompletionHandler>::type handler_t;-- typedef typename associated_executor<- handler_t, Executor>::type handler_ex_t;- handler_ex_t handler_ex((get_associated_executor)(handler, ex_));-- typename associated_allocator<handler_t>::type alloc(- (get_associated_allocator)(handler));-- execution::execute(- asio::prefer(- asio::require(ex_, execution::blocking.never),- execution::relationship.fork,- execution::allocator(alloc)),- detail::work_dispatcher<handler_t, handler_ex_t>(- ASIO_MOVE_CAST(CompletionHandler)(handler), handler_ex));- }-- template <typename CompletionHandler>- void operator()(ASIO_MOVE_ARG(CompletionHandler) handler,- typename enable_if<- !execution::is_executor<- typename conditional<true, executor_type, CompletionHandler>::type- >::value- &&- !detail::is_work_dispatcher_required<- typename decay<CompletionHandler>::type,- Executor- >::value- >::type* = 0) const- {- typedef typename decay<CompletionHandler>::type handler_t;-- typename associated_allocator<handler_t>::type alloc(- (get_associated_allocator)(handler));-- ex_.post(ASIO_MOVE_CAST(CompletionHandler)(handler), alloc);- }-- template <typename CompletionHandler>- void operator()(ASIO_MOVE_ARG(CompletionHandler) handler,- typename enable_if<- !execution::is_executor<- typename conditional<true, executor_type, CompletionHandler>::type- >::value- &&- detail::is_work_dispatcher_required<- typename decay<CompletionHandler>::type,- Executor- >::value- >::type* = 0) const- {- typedef typename decay<CompletionHandler>::type handler_t;-- typedef typename associated_executor<- handler_t, Executor>::type handler_ex_t;- handler_ex_t handler_ex((get_associated_executor)(handler, ex_));-- typename associated_allocator<handler_t>::type alloc(- (get_associated_allocator)(handler));-- ex_.post(detail::work_dispatcher<handler_t, handler_ex_t>(- ASIO_MOVE_CAST(CompletionHandler)(handler),- handler_ex), alloc);- }--private:- Executor ex_;-};--} // namespace detail--template <ASIO_COMPLETION_TOKEN_FOR(void()) CompletionToken>-ASIO_INITFN_AUTO_RESULT_TYPE(CompletionToken, void()) post(- ASIO_MOVE_ARG(CompletionToken) token)-{- return async_initiate<CompletionToken, void()>(- detail::initiate_post(), token);-}--template <typename Executor,- ASIO_COMPLETION_TOKEN_FOR(void()) CompletionToken>-ASIO_INITFN_AUTO_RESULT_TYPE(CompletionToken, void()) post(- const Executor& ex, ASIO_MOVE_ARG(CompletionToken) token,- typename enable_if<- execution::is_executor<Executor>::value || is_executor<Executor>::value- >::type*)-{- return async_initiate<CompletionToken, void()>(- detail::initiate_post_with_executor<Executor>(ex), token);-}--template <typename ExecutionContext,- ASIO_COMPLETION_TOKEN_FOR(void()) CompletionToken>-inline ASIO_INITFN_AUTO_RESULT_TYPE(CompletionToken, void()) post(- ExecutionContext& ctx, ASIO_MOVE_ARG(CompletionToken) token,- typename enable_if<is_convertible<- ExecutionContext&, execution_context&>::value>::type*)-{- return async_initiate<CompletionToken, void()>(- detail::initiate_post_with_executor<- typename ExecutionContext::executor_type>(- ctx.get_executor()), token);-}--} // namespace asio--#include "asio/detail/pop_options.hpp"--#endif // ASIO_IMPL_POST_HPP
+ link/modules/asio-standalone/asio/include/asio/impl/prepend.hpp view
@@ -0,0 +1,225 @@+//+// impl/prepend.hpp+// ~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com)+//+// Distributed under the Boost Software License, Version 1.0. (See accompanying+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)+//++#ifndef ASIO_IMPL_PREPEND_HPP+#define ASIO_IMPL_PREPEND_HPP++#if defined(_MSC_VER) && (_MSC_VER >= 1200)+# pragma once+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)++#include "asio/detail/config.hpp"++#include "asio/associator.hpp"+#include "asio/async_result.hpp"+#include "asio/detail/handler_alloc_helpers.hpp"+#include "asio/detail/handler_cont_helpers.hpp"+#include "asio/detail/handler_invoke_helpers.hpp"+#include "asio/detail/type_traits.hpp"+#include "asio/detail/utility.hpp"+#include "asio/detail/variadic_templates.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {+namespace detail {++// Class to adapt a prepend_t as a completion handler.+template <typename Handler, typename... Values>+class prepend_handler+{+public:+ typedef void result_type;++ template <typename H>+ prepend_handler(ASIO_MOVE_ARG(H) handler, std::tuple<Values...> values)+ : handler_(ASIO_MOVE_CAST(H)(handler)),+ values_(ASIO_MOVE_CAST(std::tuple<Values...>)(values))+ {+ }++ template <typename... Args>+ void operator()(ASIO_MOVE_ARG(Args)... args)+ {+ this->invoke(+ index_sequence_for<Values...>{},+ ASIO_MOVE_CAST(Args)(args)...);+ }++ template <std::size_t... I, typename... Args>+ void invoke(index_sequence<I...>, ASIO_MOVE_ARG(Args)... args)+ {+ ASIO_MOVE_OR_LVALUE(Handler)(handler_)(+ ASIO_MOVE_CAST(Values)(std::get<I>(values_))...,+ ASIO_MOVE_CAST(Args)(args)...);+ }++//private:+ Handler handler_;+ std::tuple<Values...> values_;+};++template <typename Handler>+inline asio_handler_allocate_is_deprecated+asio_handler_allocate(std::size_t size,+ prepend_handler<Handler>* this_handler)+{+#if defined(ASIO_NO_DEPRECATED)+ asio_handler_alloc_helpers::allocate(size, this_handler->handler_);+ return asio_handler_allocate_is_no_longer_used();+#else // defined(ASIO_NO_DEPRECATED)+ return asio_handler_alloc_helpers::allocate(+ size, this_handler->handler_);+#endif // defined(ASIO_NO_DEPRECATED)+}++template <typename Handler>+inline asio_handler_deallocate_is_deprecated+asio_handler_deallocate(void* pointer, std::size_t size,+ prepend_handler<Handler>* this_handler)+{+ asio_handler_alloc_helpers::deallocate(+ pointer, size, this_handler->handler_);+#if defined(ASIO_NO_DEPRECATED)+ return asio_handler_deallocate_is_no_longer_used();+#endif // defined(ASIO_NO_DEPRECATED)+}++template <typename Handler>+inline bool asio_handler_is_continuation(+ prepend_handler<Handler>* this_handler)+{+ return asio_handler_cont_helpers::is_continuation(+ this_handler->handler_);+}++template <typename Function, typename Handler>+inline asio_handler_invoke_is_deprecated+asio_handler_invoke(Function& function,+ prepend_handler<Handler>* this_handler)+{+ asio_handler_invoke_helpers::invoke(+ function, this_handler->handler_);+#if defined(ASIO_NO_DEPRECATED)+ return asio_handler_invoke_is_no_longer_used();+#endif // defined(ASIO_NO_DEPRECATED)+}++template <typename Function, typename Handler>+inline asio_handler_invoke_is_deprecated+asio_handler_invoke(const Function& function,+ prepend_handler<Handler>* this_handler)+{+ asio_handler_invoke_helpers::invoke(+ function, this_handler->handler_);+#if defined(ASIO_NO_DEPRECATED)+ return asio_handler_invoke_is_no_longer_used();+#endif // defined(ASIO_NO_DEPRECATED)+}++template <typename Signature, typename... Values>+struct prepend_signature;++template <typename R, typename... Args, typename... Values>+struct prepend_signature<R(Args...), Values...>+{+ typedef R type(Values..., typename decay<Args>::type...);+};++} // namespace detail++#if !defined(GENERATING_DOCUMENTATION)++template <typename CompletionToken, typename... Values, typename Signature>+struct async_result<+ prepend_t<CompletionToken, Values...>, Signature>+ : async_result<CompletionToken,+ typename detail::prepend_signature<+ Signature, Values...>::type>+{+ typedef typename detail::prepend_signature<+ Signature, Values...>::type signature;++ template <typename Initiation>+ struct init_wrapper+ {+ init_wrapper(Initiation init)+ : initiation_(ASIO_MOVE_CAST(Initiation)(init))+ {+ }++ template <typename Handler, typename... Args>+ void operator()(+ ASIO_MOVE_ARG(Handler) handler,+ std::tuple<Values...> values,+ ASIO_MOVE_ARG(Args)... args)+ {+ ASIO_MOVE_CAST(Initiation)(initiation_)(+ detail::prepend_handler<+ typename decay<Handler>::type, Values...>(+ ASIO_MOVE_CAST(Handler)(handler),+ ASIO_MOVE_CAST(std::tuple<Values...>)(values)),+ ASIO_MOVE_CAST(Args)(args)...);+ }++ Initiation initiation_;+ };++ template <typename Initiation, typename RawCompletionToken, typename... Args>+ static ASIO_INITFN_DEDUCED_RESULT_TYPE(CompletionToken, signature,+ (async_initiate<CompletionToken, signature>(+ declval<init_wrapper<typename decay<Initiation>::type> >(),+ declval<CompletionToken&>(),+ declval<std::tuple<Values...> >(),+ declval<ASIO_MOVE_ARG(Args)>()...)))+ initiate(+ ASIO_MOVE_ARG(Initiation) initiation,+ ASIO_MOVE_ARG(RawCompletionToken) token,+ ASIO_MOVE_ARG(Args)... args)+ {+ return async_initiate<CompletionToken, signature>(+ init_wrapper<typename decay<Initiation>::type>(+ ASIO_MOVE_CAST(Initiation)(initiation)),+ token.token_,+ ASIO_MOVE_CAST(std::tuple<Values...>)(token.values_),+ ASIO_MOVE_CAST(Args)(args)...);+ }+};++template <template <typename, typename> class Associator,+ typename Handler, typename... Values, typename DefaultCandidate>+struct associator<Associator,+ detail::prepend_handler<Handler, Values...>, DefaultCandidate>+ : Associator<Handler, DefaultCandidate>+{+ static typename Associator<Handler, DefaultCandidate>::type+ get(const detail::prepend_handler<Handler, Values...>& h) ASIO_NOEXCEPT+ {+ return Associator<Handler, DefaultCandidate>::get(h.handler_);+ }++ static ASIO_AUTO_RETURN_TYPE_PREFIX2(+ typename Associator<Handler, DefaultCandidate>::type)+ get(const detail::prepend_handler<Handler, Values...>& h,+ const DefaultCandidate& c) ASIO_NOEXCEPT+ ASIO_AUTO_RETURN_TYPE_SUFFIX((+ Associator<Handler, DefaultCandidate>::get(h.handler_, c)))+ {+ return Associator<Handler, DefaultCandidate>::get(h.handler_, c);+ }+};++#endif // !defined(GENERATING_DOCUMENTATION)++} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // ASIO_IMPL_PREPEND_HPP
link/modules/asio-standalone/asio/include/asio/impl/read.hpp view
@@ -2,7 +2,7 @@ // impl/read.hpp // ~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -16,11 +16,10 @@ #endif // defined(_MSC_VER) && (_MSC_VER >= 1200) #include <algorithm>-#include "asio/associated_allocator.hpp"-#include "asio/associated_executor.hpp"+#include "asio/associator.hpp" #include "asio/buffer.hpp"-#include "asio/completion_condition.hpp" #include "asio/detail/array_fwd.hpp"+#include "asio/detail/base_from_cancellation_state.hpp" #include "asio/detail/base_from_completion_cond.hpp" #include "asio/detail/bind_handler.hpp" #include "asio/detail/consuming_buffers.hpp"@@ -42,7 +41,7 @@ { template <typename SyncReadStream, typename MutableBufferSequence, typename MutableBufferIterator, typename CompletionCondition>- std::size_t read_buffer_sequence(SyncReadStream& s,+ std::size_t read_buffer_seq(SyncReadStream& s, const MutableBufferSequence& buffers, const MutableBufferIterator&, CompletionCondition completion_condition, asio::error_code& ec) {@@ -57,7 +56,7 @@ else break; }- return tmp.total_consumed();;+ return tmp.total_consumed(); } } // namespace detail @@ -65,20 +64,20 @@ typename CompletionCondition> std::size_t read(SyncReadStream& s, const MutableBufferSequence& buffers, CompletionCondition completion_condition, asio::error_code& ec,- typename enable_if<+ typename constraint< is_mutable_buffer_sequence<MutableBufferSequence>::value- >::type*)+ >::type) {- return detail::read_buffer_sequence(s, buffers,+ return detail::read_buffer_seq(s, buffers, asio::buffer_sequence_begin(buffers), ASIO_MOVE_CAST(CompletionCondition)(completion_condition), ec); } template <typename SyncReadStream, typename MutableBufferSequence> inline std::size_t read(SyncReadStream& s, const MutableBufferSequence& buffers,- typename enable_if<+ typename constraint< is_mutable_buffer_sequence<MutableBufferSequence>::value- >::type*)+ >::type) { asio::error_code ec; std::size_t bytes_transferred = read(s, buffers, transfer_all(), ec);@@ -89,9 +88,9 @@ template <typename SyncReadStream, typename MutableBufferSequence> inline std::size_t read(SyncReadStream& s, const MutableBufferSequence& buffers, asio::error_code& ec,- typename enable_if<+ typename constraint< is_mutable_buffer_sequence<MutableBufferSequence>::value- >::type*)+ >::type) { return read(s, buffers, transfer_all(), ec); }@@ -100,9 +99,9 @@ typename CompletionCondition> inline std::size_t read(SyncReadStream& s, const MutableBufferSequence& buffers, CompletionCondition completion_condition,- typename enable_if<+ typename constraint< is_mutable_buffer_sequence<MutableBufferSequence>::value- >::type*)+ >::type) { asio::error_code ec; std::size_t bytes_transferred = read(s, buffers,@@ -118,10 +117,12 @@ std::size_t read(SyncReadStream& s, ASIO_MOVE_ARG(DynamicBuffer_v1) buffers, CompletionCondition completion_condition, asio::error_code& ec,- typename enable_if<+ typename constraint< is_dynamic_buffer_v1<typename decay<DynamicBuffer_v1>::type>::value- && !is_dynamic_buffer_v2<typename decay<DynamicBuffer_v1>::type>::value- >::type*)+ >::type,+ typename constraint<+ !is_dynamic_buffer_v2<typename decay<DynamicBuffer_v1>::type>::value+ >::type) { typename decay<DynamicBuffer_v1>::type b( ASIO_MOVE_CAST(DynamicBuffer_v1)(buffers));@@ -150,10 +151,12 @@ template <typename SyncReadStream, typename DynamicBuffer_v1> inline std::size_t read(SyncReadStream& s, ASIO_MOVE_ARG(DynamicBuffer_v1) buffers,- typename enable_if<+ typename constraint< is_dynamic_buffer_v1<typename decay<DynamicBuffer_v1>::type>::value- && !is_dynamic_buffer_v2<typename decay<DynamicBuffer_v1>::type>::value- >::type*)+ >::type,+ typename constraint<+ !is_dynamic_buffer_v2<typename decay<DynamicBuffer_v1>::type>::value+ >::type) { asio::error_code ec; std::size_t bytes_transferred = read(s,@@ -166,10 +169,12 @@ inline std::size_t read(SyncReadStream& s, ASIO_MOVE_ARG(DynamicBuffer_v1) buffers, asio::error_code& ec,- typename enable_if<+ typename constraint< is_dynamic_buffer_v1<typename decay<DynamicBuffer_v1>::type>::value- && !is_dynamic_buffer_v2<typename decay<DynamicBuffer_v1>::type>::value- >::type*)+ >::type,+ typename constraint<+ !is_dynamic_buffer_v2<typename decay<DynamicBuffer_v1>::type>::value+ >::type) { return read(s, ASIO_MOVE_CAST(DynamicBuffer_v1)(buffers), transfer_all(), ec);@@ -180,10 +185,12 @@ inline std::size_t read(SyncReadStream& s, ASIO_MOVE_ARG(DynamicBuffer_v1) buffers, CompletionCondition completion_condition,- typename enable_if<+ typename constraint< is_dynamic_buffer_v1<typename decay<DynamicBuffer_v1>::type>::value- && !is_dynamic_buffer_v2<typename decay<DynamicBuffer_v1>::type>::value- >::type*)+ >::type,+ typename constraint<+ !is_dynamic_buffer_v2<typename decay<DynamicBuffer_v1>::type>::value+ >::type) { asio::error_code ec; std::size_t bytes_transferred = read(s,@@ -239,9 +246,9 @@ typename CompletionCondition> std::size_t read(SyncReadStream& s, DynamicBuffer_v2 buffers, CompletionCondition completion_condition, asio::error_code& ec,- typename enable_if<+ typename constraint< is_dynamic_buffer_v2<DynamicBuffer_v2>::value- >::type*)+ >::type) { DynamicBuffer_v2& b = buffers; @@ -271,9 +278,9 @@ template <typename SyncReadStream, typename DynamicBuffer_v2> inline std::size_t read(SyncReadStream& s, DynamicBuffer_v2 buffers,- typename enable_if<+ typename constraint< is_dynamic_buffer_v2<DynamicBuffer_v2>::value- >::type*)+ >::type) { asio::error_code ec; std::size_t bytes_transferred = read(s,@@ -285,9 +292,9 @@ template <typename SyncReadStream, typename DynamicBuffer_v2> inline std::size_t read(SyncReadStream& s, DynamicBuffer_v2 buffers, asio::error_code& ec,- typename enable_if<+ typename constraint< is_dynamic_buffer_v2<DynamicBuffer_v2>::value- >::type*)+ >::type) { return read(s, ASIO_MOVE_CAST(DynamicBuffer_v2)(buffers), transfer_all(), ec);@@ -297,9 +304,9 @@ typename CompletionCondition> inline std::size_t read(SyncReadStream& s, DynamicBuffer_v2 buffers, CompletionCondition completion_condition,- typename enable_if<+ typename constraint< is_dynamic_buffer_v2<DynamicBuffer_v2>::value- >::type*)+ >::type) { asio::error_code ec; std::size_t bytes_transferred = read(s,@@ -315,13 +322,15 @@ typename MutableBufferIterator, typename CompletionCondition, typename ReadHandler> class read_op- : detail::base_from_completion_cond<CompletionCondition>+ : public base_from_cancellation_state<ReadHandler>,+ base_from_completion_cond<CompletionCondition> { public: read_op(AsyncReadStream& stream, const MutableBufferSequence& buffers, CompletionCondition& completion_condition, ReadHandler& handler)- : detail::base_from_completion_cond<- CompletionCondition>(completion_condition),+ : base_from_cancellation_state<ReadHandler>(+ handler, enable_partial_cancellation()),+ base_from_completion_cond<CompletionCondition>(completion_condition), stream_(stream), buffers_(buffers), start_(0),@@ -331,7 +340,8 @@ #if defined(ASIO_HAS_MOVE) read_op(const read_op& other)- : detail::base_from_completion_cond<CompletionCondition>(other),+ : base_from_cancellation_state<ReadHandler>(other),+ base_from_completion_cond<CompletionCondition>(other), stream_(other.stream_), buffers_(other.buffers_), start_(other.start_),@@ -340,8 +350,11 @@ } read_op(read_op&& other)- : detail::base_from_completion_cond<CompletionCondition>(- ASIO_MOVE_CAST(detail::base_from_completion_cond<+ : base_from_cancellation_state<ReadHandler>(+ ASIO_MOVE_CAST(base_from_cancellation_state<+ ReadHandler>)(other)),+ base_from_completion_cond<CompletionCondition>(+ ASIO_MOVE_CAST(base_from_completion_cond< CompletionCondition>)(other)), stream_(other.stream_), buffers_(ASIO_MOVE_CAST(buffers_type)(other.buffers_)),@@ -351,7 +364,7 @@ } #endif // defined(ASIO_HAS_MOVE) - void operator()(const asio::error_code& ec,+ void operator()(asio::error_code ec, std::size_t bytes_transferred, int start = 0) { std::size_t max_size;@@ -359,7 +372,7 @@ { case 1: max_size = this->check_for_completion(ec, buffers_.total_consumed());- do+ for (;;) { { ASIO_HANDLER_LOCATION((__FILE__, __LINE__, "async_read"));@@ -371,9 +384,18 @@ if ((!ec && bytes_transferred == 0) || buffers_.empty()) break; max_size = this->check_for_completion(ec, buffers_.total_consumed());- } while (max_size > 0);+ if (max_size == 0)+ break;+ if (this->cancelled() != cancellation_type::none)+ {+ ec = error::operation_aborted;+ break;+ }+ } - handler_(ec, buffers_.total_consumed());+ ASIO_MOVE_OR_LVALUE(ReadHandler)(handler_)(+ static_cast<const asio::error_code&>(ec),+ static_cast<const std::size_t&>(buffers_.total_consumed())); } } @@ -464,23 +486,23 @@ template <typename AsyncReadStream, typename MutableBufferSequence, typename MutableBufferIterator, typename CompletionCondition, typename ReadHandler>- inline void start_read_buffer_sequence_op(AsyncReadStream& stream,+ inline void start_read_op(AsyncReadStream& stream, const MutableBufferSequence& buffers, const MutableBufferIterator&, CompletionCondition& completion_condition, ReadHandler& handler) {- detail::read_op<AsyncReadStream, MutableBufferSequence,+ read_op<AsyncReadStream, MutableBufferSequence, MutableBufferIterator, CompletionCondition, ReadHandler>( stream, buffers, completion_condition, handler)( asio::error_code(), 0, 1); } template <typename AsyncReadStream>- class initiate_async_read_buffer_sequence+ class initiate_async_read { public: typedef typename AsyncReadStream::executor_type executor_type; - explicit initiate_async_read_buffer_sequence(AsyncReadStream& stream)+ explicit initiate_async_read(AsyncReadStream& stream) : stream_(stream) { }@@ -502,7 +524,7 @@ non_const_lvalue<ReadHandler> handler2(handler); non_const_lvalue<CompletionCondition> completion_cond2(completion_cond);- start_read_buffer_sequence_op(stream_, buffers,+ start_read_op(stream_, buffers, asio::buffer_sequence_begin(buffers), completion_cond2.value, handler2.value); }@@ -514,42 +536,33 @@ #if !defined(GENERATING_DOCUMENTATION) -template <typename AsyncReadStream, typename MutableBufferSequence,+template <template <typename, typename> class Associator,+ typename AsyncReadStream, typename MutableBufferSequence, typename MutableBufferIterator, typename CompletionCondition,- typename ReadHandler, typename Allocator>-struct associated_allocator<+ typename ReadHandler, typename DefaultCandidate>+struct associator<Associator, detail::read_op<AsyncReadStream, MutableBufferSequence, MutableBufferIterator, CompletionCondition, ReadHandler>,- Allocator>+ DefaultCandidate>+ : Associator<ReadHandler, DefaultCandidate> {- typedef typename associated_allocator<ReadHandler, Allocator>::type type;-- static type get(- const detail::read_op<AsyncReadStream, MutableBufferSequence,- MutableBufferIterator, CompletionCondition, ReadHandler>& h,- const Allocator& a = Allocator()) ASIO_NOEXCEPT+ static typename Associator<ReadHandler, DefaultCandidate>::type+ get(const detail::read_op<AsyncReadStream, MutableBufferSequence,+ MutableBufferIterator, CompletionCondition, ReadHandler>& h)+ ASIO_NOEXCEPT {- return associated_allocator<ReadHandler, Allocator>::get(h.handler_, a);+ return Associator<ReadHandler, DefaultCandidate>::get(h.handler_); }-}; -template <typename AsyncReadStream, typename MutableBufferSequence,- typename MutableBufferIterator, typename CompletionCondition,- typename ReadHandler, typename Executor>-struct associated_executor<- detail::read_op<AsyncReadStream, MutableBufferSequence,- MutableBufferIterator, CompletionCondition, ReadHandler>,- Executor>- : detail::associated_executor_forwarding_base<ReadHandler, Executor>-{- typedef typename associated_executor<ReadHandler, Executor>::type type;-- static type get(- const detail::read_op<AsyncReadStream, MutableBufferSequence,+ static ASIO_AUTO_RETURN_TYPE_PREFIX2(+ typename Associator<ReadHandler, DefaultCandidate>::type)+ get(const detail::read_op<AsyncReadStream, MutableBufferSequence, MutableBufferIterator, CompletionCondition, ReadHandler>& h,- const Executor& ex = Executor()) ASIO_NOEXCEPT+ const DefaultCandidate& c) ASIO_NOEXCEPT+ ASIO_AUTO_RETURN_TYPE_SUFFIX((+ Associator<ReadHandler, DefaultCandidate>::get(h.handler_, c))) {- return associated_executor<ReadHandler, Executor>::get(h.handler_, ex);+ return Associator<ReadHandler, DefaultCandidate>::get(h.handler_, c); } }; @@ -558,37 +571,49 @@ template <typename AsyncReadStream, typename MutableBufferSequence, typename CompletionCondition, ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code,- std::size_t)) ReadHandler>-inline ASIO_INITFN_AUTO_RESULT_TYPE(ReadHandler,+ std::size_t)) ReadToken>+inline ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX(ReadToken, void (asio::error_code, std::size_t)) async_read(AsyncReadStream& s, const MutableBufferSequence& buffers, CompletionCondition completion_condition,- ASIO_MOVE_ARG(ReadHandler) handler,- typename enable_if<+ ASIO_MOVE_ARG(ReadToken) token,+ typename constraint< is_mutable_buffer_sequence<MutableBufferSequence>::value- >::type*)+ >::type)+ ASIO_INITFN_AUTO_RESULT_TYPE_SUFFIX((+ async_initiate<ReadToken,+ void (asio::error_code, std::size_t)>(+ declval<detail::initiate_async_read<AsyncReadStream> >(),+ token, buffers,+ ASIO_MOVE_CAST(CompletionCondition)(completion_condition)))) {- return async_initiate<ReadHandler,+ return async_initiate<ReadToken, void (asio::error_code, std::size_t)>(- detail::initiate_async_read_buffer_sequence<AsyncReadStream>(s), handler,- buffers, ASIO_MOVE_CAST(CompletionCondition)(completion_condition));+ detail::initiate_async_read<AsyncReadStream>(s),+ token, buffers,+ ASIO_MOVE_CAST(CompletionCondition)(completion_condition)); } template <typename AsyncReadStream, typename MutableBufferSequence, ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code,- std::size_t)) ReadHandler>-inline ASIO_INITFN_AUTO_RESULT_TYPE(ReadHandler,+ std::size_t)) ReadToken>+inline ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX(ReadToken, void (asio::error_code, std::size_t)) async_read(AsyncReadStream& s, const MutableBufferSequence& buffers,- ASIO_MOVE_ARG(ReadHandler) handler,- typename enable_if<+ ASIO_MOVE_ARG(ReadToken) token,+ typename constraint< is_mutable_buffer_sequence<MutableBufferSequence>::value- >::type*)+ >::type)+ ASIO_INITFN_AUTO_RESULT_TYPE_SUFFIX((+ async_initiate<ReadToken,+ void (asio::error_code, std::size_t)>(+ declval<detail::initiate_async_read<AsyncReadStream> >(),+ token, buffers, transfer_all()))) {- return async_initiate<ReadHandler,+ return async_initiate<ReadToken, void (asio::error_code, std::size_t)>(- detail::initiate_async_read_buffer_sequence<AsyncReadStream>(s),- handler, buffers, transfer_all());+ detail::initiate_async_read<AsyncReadStream>(s),+ token, buffers, transfer_all()); } #if !defined(ASIO_NO_DYNAMIC_BUFFER_V1)@@ -598,15 +623,17 @@ template <typename AsyncReadStream, typename DynamicBuffer_v1, typename CompletionCondition, typename ReadHandler> class read_dynbuf_v1_op- : detail::base_from_completion_cond<CompletionCondition>+ : public base_from_cancellation_state<ReadHandler>,+ base_from_completion_cond<CompletionCondition> { public: template <typename BufferSequence> read_dynbuf_v1_op(AsyncReadStream& stream, ASIO_MOVE_ARG(BufferSequence) buffers, CompletionCondition& completion_condition, ReadHandler& handler)- : detail::base_from_completion_cond<- CompletionCondition>(completion_condition),+ : base_from_cancellation_state<ReadHandler>(+ handler, enable_partial_cancellation()),+ base_from_completion_cond<CompletionCondition>(completion_condition), stream_(stream), buffers_(ASIO_MOVE_CAST(BufferSequence)(buffers)), start_(0),@@ -617,7 +644,8 @@ #if defined(ASIO_HAS_MOVE) read_dynbuf_v1_op(const read_dynbuf_v1_op& other)- : detail::base_from_completion_cond<CompletionCondition>(other),+ : base_from_cancellation_state<ReadHandler>(other),+ base_from_completion_cond<CompletionCondition>(other), stream_(other.stream_), buffers_(other.buffers_), start_(other.start_),@@ -627,8 +655,11 @@ } read_dynbuf_v1_op(read_dynbuf_v1_op&& other)- : detail::base_from_completion_cond<CompletionCondition>(- ASIO_MOVE_CAST(detail::base_from_completion_cond<+ : base_from_cancellation_state<ReadHandler>(+ ASIO_MOVE_CAST(base_from_cancellation_state<+ ReadHandler>)(other)),+ base_from_completion_cond<CompletionCondition>(+ ASIO_MOVE_CAST(base_from_completion_cond< CompletionCondition>)(other)), stream_(other.stream_), buffers_(ASIO_MOVE_CAST(DynamicBuffer_v1)(other.buffers_)),@@ -639,7 +670,7 @@ } #endif // defined(ASIO_HAS_MOVE) - void operator()(const asio::error_code& ec,+ void operator()(asio::error_code ec, std::size_t bytes_transferred, int start = 0) { std::size_t max_size, bytes_available;@@ -670,9 +701,16 @@ buffers_.max_size() - buffers_.size())); if ((!ec && bytes_transferred == 0) || bytes_available == 0) break;+ if (this->cancelled() != cancellation_type::none)+ {+ ec = error::operation_aborted;+ break;+ } } - handler_(ec, static_cast<const std::size_t&>(total_transferred_));+ ASIO_MOVE_OR_LVALUE(ReadHandler)(handler_)(+ static_cast<const asio::error_code&>(ec),+ static_cast<const std::size_t&>(total_transferred_)); } } @@ -797,40 +835,32 @@ #if !defined(GENERATING_DOCUMENTATION) -template <typename AsyncReadStream, typename DynamicBuffer_v1,- typename CompletionCondition, typename ReadHandler, typename Allocator>-struct associated_allocator<+template <template <typename, typename> class Associator,+ typename AsyncReadStream, typename DynamicBuffer_v1,+ typename CompletionCondition, typename ReadHandler,+ typename DefaultCandidate>+struct associator<Associator, detail::read_dynbuf_v1_op<AsyncReadStream, DynamicBuffer_v1, CompletionCondition, ReadHandler>,- Allocator>+ DefaultCandidate>+ : Associator<ReadHandler, DefaultCandidate> {- typedef typename associated_allocator<ReadHandler, Allocator>::type type;-- static type get(- const detail::read_dynbuf_v1_op<AsyncReadStream,- DynamicBuffer_v1, CompletionCondition, ReadHandler>& h,- const Allocator& a = Allocator()) ASIO_NOEXCEPT+ static typename Associator<ReadHandler, DefaultCandidate>::type+ get(const detail::read_dynbuf_v1_op<AsyncReadStream, DynamicBuffer_v1,+ CompletionCondition, ReadHandler>& h) ASIO_NOEXCEPT {- return associated_allocator<ReadHandler, Allocator>::get(h.handler_, a);+ return Associator<ReadHandler, DefaultCandidate>::get(h.handler_); }-}; -template <typename AsyncReadStream, typename DynamicBuffer_v1,- typename CompletionCondition, typename ReadHandler, typename Executor>-struct associated_executor<- detail::read_dynbuf_v1_op<AsyncReadStream,- DynamicBuffer_v1, CompletionCondition, ReadHandler>,- Executor>- : detail::associated_executor_forwarding_base<ReadHandler, Executor>-{- typedef typename associated_executor<ReadHandler, Executor>::type type;-- static type get(- const detail::read_dynbuf_v1_op<AsyncReadStream,+ static ASIO_AUTO_RETURN_TYPE_PREFIX2(+ typename Associator<ReadHandler, DefaultCandidate>::type)+ get(const detail::read_dynbuf_v1_op<AsyncReadStream, DynamicBuffer_v1, CompletionCondition, ReadHandler>& h,- const Executor& ex = Executor()) ASIO_NOEXCEPT+ const DefaultCandidate& c) ASIO_NOEXCEPT+ ASIO_AUTO_RETURN_TYPE_SUFFIX((+ Associator<ReadHandler, DefaultCandidate>::get(h.handler_, c))) {- return associated_executor<ReadHandler, Executor>::get(h.handler_, ex);+ return Associator<ReadHandler, DefaultCandidate>::get(h.handler_, c); } }; @@ -838,41 +868,59 @@ template <typename AsyncReadStream, typename DynamicBuffer_v1, ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code,- std::size_t)) ReadHandler>-inline ASIO_INITFN_AUTO_RESULT_TYPE(ReadHandler,+ std::size_t)) ReadToken>+inline ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX(ReadToken, void (asio::error_code, std::size_t)) async_read(AsyncReadStream& s, ASIO_MOVE_ARG(DynamicBuffer_v1) buffers,- ASIO_MOVE_ARG(ReadHandler) handler,- typename enable_if<+ ASIO_MOVE_ARG(ReadToken) token,+ typename constraint< is_dynamic_buffer_v1<typename decay<DynamicBuffer_v1>::type>::value- && !is_dynamic_buffer_v2<typename decay<DynamicBuffer_v1>::type>::value- >::type*)+ >::type,+ typename constraint<+ !is_dynamic_buffer_v2<typename decay<DynamicBuffer_v1>::type>::value+ >::type)+ ASIO_INITFN_AUTO_RESULT_TYPE_SUFFIX((+ async_initiate<ReadToken,+ void (asio::error_code, std::size_t)>(+ declval<detail::initiate_async_read_dynbuf_v1<AsyncReadStream> >(),+ token, ASIO_MOVE_CAST(DynamicBuffer_v1)(buffers),+ transfer_all()))) {- return async_read(s,- ASIO_MOVE_CAST(DynamicBuffer_v1)(buffers),- transfer_all(), ASIO_MOVE_CAST(ReadHandler)(handler));+ return async_initiate<ReadToken,+ void (asio::error_code, std::size_t)>(+ detail::initiate_async_read_dynbuf_v1<AsyncReadStream>(s),+ token, ASIO_MOVE_CAST(DynamicBuffer_v1)(buffers),+ transfer_all()); } template <typename AsyncReadStream, typename DynamicBuffer_v1, typename CompletionCondition, ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code,- std::size_t)) ReadHandler>-inline ASIO_INITFN_AUTO_RESULT_TYPE(ReadHandler,+ std::size_t)) ReadToken>+inline ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX(ReadToken, void (asio::error_code, std::size_t)) async_read(AsyncReadStream& s, ASIO_MOVE_ARG(DynamicBuffer_v1) buffers, CompletionCondition completion_condition,- ASIO_MOVE_ARG(ReadHandler) handler,- typename enable_if<+ ASIO_MOVE_ARG(ReadToken) token,+ typename constraint< is_dynamic_buffer_v1<typename decay<DynamicBuffer_v1>::type>::value- && !is_dynamic_buffer_v2<typename decay<DynamicBuffer_v1>::type>::value- >::type*)+ >::type,+ typename constraint<+ !is_dynamic_buffer_v2<typename decay<DynamicBuffer_v1>::type>::value+ >::type)+ ASIO_INITFN_AUTO_RESULT_TYPE_SUFFIX((+ async_initiate<ReadToken,+ void (asio::error_code, std::size_t)>(+ declval<detail::initiate_async_read_dynbuf_v1<AsyncReadStream> >(),+ token, ASIO_MOVE_CAST(DynamicBuffer_v1)(buffers),+ ASIO_MOVE_CAST(CompletionCondition)(completion_condition)))) {- return async_initiate<ReadHandler,+ return async_initiate<ReadToken, void (asio::error_code, std::size_t)>( detail::initiate_async_read_dynbuf_v1<AsyncReadStream>(s),- handler, ASIO_MOVE_CAST(DynamicBuffer_v1)(buffers),+ token, ASIO_MOVE_CAST(DynamicBuffer_v1)(buffers), ASIO_MOVE_CAST(CompletionCondition)(completion_condition)); } @@ -881,29 +929,36 @@ template <typename AsyncReadStream, typename Allocator, ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code,- std::size_t)) ReadHandler>-inline ASIO_INITFN_AUTO_RESULT_TYPE(ReadHandler,+ std::size_t)) ReadToken>+inline ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX(ReadToken, void (asio::error_code, std::size_t)) async_read(AsyncReadStream& s, basic_streambuf<Allocator>& b,- ASIO_MOVE_ARG(ReadHandler) handler)+ ASIO_MOVE_ARG(ReadToken) token)+ ASIO_INITFN_AUTO_RESULT_TYPE_SUFFIX((+ async_read(s, basic_streambuf_ref<Allocator>(b),+ ASIO_MOVE_CAST(ReadToken)(token)))) { return async_read(s, basic_streambuf_ref<Allocator>(b),- ASIO_MOVE_CAST(ReadHandler)(handler));+ ASIO_MOVE_CAST(ReadToken)(token)); } template <typename AsyncReadStream, typename Allocator, typename CompletionCondition, ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code,- std::size_t)) ReadHandler>-inline ASIO_INITFN_AUTO_RESULT_TYPE(ReadHandler,+ std::size_t)) ReadToken>+inline ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX(ReadToken, void (asio::error_code, std::size_t)) async_read(AsyncReadStream& s, basic_streambuf<Allocator>& b, CompletionCondition completion_condition,- ASIO_MOVE_ARG(ReadHandler) handler)+ ASIO_MOVE_ARG(ReadToken) token)+ ASIO_INITFN_AUTO_RESULT_TYPE_SUFFIX((+ async_read(s, basic_streambuf_ref<Allocator>(b),+ ASIO_MOVE_CAST(CompletionCondition)(completion_condition),+ ASIO_MOVE_CAST(ReadToken)(token)))) { return async_read(s, basic_streambuf_ref<Allocator>(b), ASIO_MOVE_CAST(CompletionCondition)(completion_condition),- ASIO_MOVE_CAST(ReadHandler)(handler));+ ASIO_MOVE_CAST(ReadToken)(token)); } #endif // !defined(ASIO_NO_IOSTREAM)@@ -915,15 +970,17 @@ template <typename AsyncReadStream, typename DynamicBuffer_v2, typename CompletionCondition, typename ReadHandler> class read_dynbuf_v2_op- : detail::base_from_completion_cond<CompletionCondition>+ : public base_from_cancellation_state<ReadHandler>,+ base_from_completion_cond<CompletionCondition> { public: template <typename BufferSequence> read_dynbuf_v2_op(AsyncReadStream& stream, ASIO_MOVE_ARG(BufferSequence) buffers, CompletionCondition& completion_condition, ReadHandler& handler)- : detail::base_from_completion_cond<- CompletionCondition>(completion_condition),+ : base_from_cancellation_state<ReadHandler>(+ handler, enable_partial_cancellation()),+ base_from_completion_cond<CompletionCondition>(completion_condition), stream_(stream), buffers_(ASIO_MOVE_CAST(BufferSequence)(buffers)), start_(0),@@ -935,7 +992,8 @@ #if defined(ASIO_HAS_MOVE) read_dynbuf_v2_op(const read_dynbuf_v2_op& other)- : detail::base_from_completion_cond<CompletionCondition>(other),+ : base_from_cancellation_state<ReadHandler>(other),+ base_from_completion_cond<CompletionCondition>(other), stream_(other.stream_), buffers_(other.buffers_), start_(other.start_),@@ -946,8 +1004,11 @@ } read_dynbuf_v2_op(read_dynbuf_v2_op&& other)- : detail::base_from_completion_cond<CompletionCondition>(- ASIO_MOVE_CAST(detail::base_from_completion_cond<+ : base_from_cancellation_state<ReadHandler>(+ ASIO_MOVE_CAST(base_from_cancellation_state<+ ReadHandler>)(other)),+ base_from_completion_cond<CompletionCondition>(+ ASIO_MOVE_CAST(base_from_completion_cond< CompletionCondition>)(other)), stream_(other.stream_), buffers_(ASIO_MOVE_CAST(DynamicBuffer_v2)(other.buffers_)),@@ -959,7 +1020,7 @@ } #endif // defined(ASIO_HAS_MOVE) - void operator()(const asio::error_code& ec,+ void operator()(asio::error_code ec, std::size_t bytes_transferred, int start = 0) { std::size_t max_size, pos;@@ -992,9 +1053,16 @@ buffers_.max_size() - buffers_.size())); if ((!ec && bytes_transferred == 0) || bytes_available_ == 0) break;+ if (this->cancelled() != cancellation_type::none)+ {+ ec = error::operation_aborted;+ break;+ } } - handler_(ec, static_cast<const std::size_t&>(total_transferred_));+ ASIO_MOVE_OR_LVALUE(ReadHandler)(handler_)(+ static_cast<const asio::error_code&>(ec),+ static_cast<const std::size_t&>(total_transferred_)); } } @@ -1120,40 +1188,32 @@ #if !defined(GENERATING_DOCUMENTATION) -template <typename AsyncReadStream, typename DynamicBuffer_v2,- typename CompletionCondition, typename ReadHandler, typename Allocator>-struct associated_allocator<+template <template <typename, typename> class Associator,+ typename AsyncReadStream, typename DynamicBuffer_v2,+ typename CompletionCondition, typename ReadHandler,+ typename DefaultCandidate>+struct associator<Associator, detail::read_dynbuf_v2_op<AsyncReadStream, DynamicBuffer_v2, CompletionCondition, ReadHandler>,- Allocator>+ DefaultCandidate>+ : Associator<ReadHandler, DefaultCandidate> {- typedef typename associated_allocator<ReadHandler, Allocator>::type type;-- static type get(- const detail::read_dynbuf_v2_op<AsyncReadStream,- DynamicBuffer_v2, CompletionCondition, ReadHandler>& h,- const Allocator& a = Allocator()) ASIO_NOEXCEPT+ static typename Associator<ReadHandler, DefaultCandidate>::type+ get(const detail::read_dynbuf_v2_op<AsyncReadStream, DynamicBuffer_v2,+ CompletionCondition, ReadHandler>& h) ASIO_NOEXCEPT {- return associated_allocator<ReadHandler, Allocator>::get(h.handler_, a);+ return Associator<ReadHandler, DefaultCandidate>::get(h.handler_); }-}; -template <typename AsyncReadStream, typename DynamicBuffer_v2,- typename CompletionCondition, typename ReadHandler, typename Executor>-struct associated_executor<- detail::read_dynbuf_v2_op<AsyncReadStream,- DynamicBuffer_v2, CompletionCondition, ReadHandler>,- Executor>- : detail::associated_executor_forwarding_base<ReadHandler, Executor>-{- typedef typename associated_executor<ReadHandler, Executor>::type type;-- static type get(- const detail::read_dynbuf_v2_op<AsyncReadStream,+ static ASIO_AUTO_RETURN_TYPE_PREFIX2(+ typename Associator<ReadHandler, DefaultCandidate>::type)+ get(const detail::read_dynbuf_v2_op<AsyncReadStream, DynamicBuffer_v2, CompletionCondition, ReadHandler>& h,- const Executor& ex = Executor()) ASIO_NOEXCEPT+ const DefaultCandidate& c) ASIO_NOEXCEPT+ ASIO_AUTO_RETURN_TYPE_SUFFIX((+ Associator<ReadHandler, DefaultCandidate>::get(h.handler_, c))) {- return associated_executor<ReadHandler, Executor>::get(h.handler_, ex);+ return Associator<ReadHandler, DefaultCandidate>::get(h.handler_, c); } }; @@ -1161,37 +1221,51 @@ template <typename AsyncReadStream, typename DynamicBuffer_v2, ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code,- std::size_t)) ReadHandler>-inline ASIO_INITFN_AUTO_RESULT_TYPE(ReadHandler,+ std::size_t)) ReadToken>+inline ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX(ReadToken, void (asio::error_code, std::size_t)) async_read(AsyncReadStream& s, DynamicBuffer_v2 buffers,- ASIO_MOVE_ARG(ReadHandler) handler,- typename enable_if<+ ASIO_MOVE_ARG(ReadToken) token,+ typename constraint< is_dynamic_buffer_v2<DynamicBuffer_v2>::value- >::type*)+ >::type)+ ASIO_INITFN_AUTO_RESULT_TYPE_SUFFIX((+ async_initiate<ReadToken,+ void (asio::error_code, std::size_t)>(+ declval<detail::initiate_async_read_dynbuf_v2<AsyncReadStream> >(),+ token, ASIO_MOVE_CAST(DynamicBuffer_v2)(buffers),+ transfer_all()))) {- return async_read(s,- ASIO_MOVE_CAST(DynamicBuffer_v2)(buffers),- transfer_all(), ASIO_MOVE_CAST(ReadHandler)(handler));+ return async_initiate<ReadToken,+ void (asio::error_code, std::size_t)>(+ detail::initiate_async_read_dynbuf_v2<AsyncReadStream>(s),+ token, ASIO_MOVE_CAST(DynamicBuffer_v2)(buffers),+ transfer_all()); } template <typename AsyncReadStream, typename DynamicBuffer_v2, typename CompletionCondition, ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code,- std::size_t)) ReadHandler>-inline ASIO_INITFN_AUTO_RESULT_TYPE(ReadHandler,+ std::size_t)) ReadToken>+inline ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX(ReadToken, void (asio::error_code, std::size_t)) async_read(AsyncReadStream& s, DynamicBuffer_v2 buffers, CompletionCondition completion_condition,- ASIO_MOVE_ARG(ReadHandler) handler,- typename enable_if<+ ASIO_MOVE_ARG(ReadToken) token,+ typename constraint< is_dynamic_buffer_v2<DynamicBuffer_v2>::value- >::type*)+ >::type)+ ASIO_INITFN_AUTO_RESULT_TYPE_SUFFIX((+ async_initiate<ReadToken,+ void (asio::error_code, std::size_t)>(+ declval<detail::initiate_async_read_dynbuf_v2<AsyncReadStream> >(),+ token, ASIO_MOVE_CAST(DynamicBuffer_v2)(buffers),+ ASIO_MOVE_CAST(CompletionCondition)(completion_condition)))) {- return async_initiate<ReadHandler,+ return async_initiate<ReadToken, void (asio::error_code, std::size_t)>( detail::initiate_async_read_dynbuf_v2<AsyncReadStream>(s),- handler, ASIO_MOVE_CAST(DynamicBuffer_v2)(buffers),+ token, ASIO_MOVE_CAST(DynamicBuffer_v2)(buffers), ASIO_MOVE_CAST(CompletionCondition)(completion_condition)); }
link/modules/asio-standalone/asio/include/asio/impl/read_at.hpp view
@@ -2,7 +2,7 @@ // impl/read_at.hpp // ~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -16,11 +16,10 @@ #endif // defined(_MSC_VER) && (_MSC_VER >= 1200) #include <algorithm>-#include "asio/associated_allocator.hpp"-#include "asio/associated_executor.hpp"+#include "asio/associator.hpp" #include "asio/buffer.hpp"-#include "asio/completion_condition.hpp" #include "asio/detail/array_fwd.hpp"+#include "asio/detail/base_from_cancellation_state.hpp" #include "asio/detail/base_from_completion_cond.hpp" #include "asio/detail/bind_handler.hpp" #include "asio/detail/consuming_buffers.hpp"@@ -61,7 +60,7 @@ else break; }- return tmp.total_consumed();;+ return tmp.total_consumed(); } } // namespace detail @@ -176,14 +175,16 @@ typename MutableBufferSequence, typename MutableBufferIterator, typename CompletionCondition, typename ReadHandler> class read_at_op- : detail::base_from_completion_cond<CompletionCondition>+ : public base_from_cancellation_state<ReadHandler>,+ base_from_completion_cond<CompletionCondition> { public: read_at_op(AsyncRandomAccessReadDevice& device, uint64_t offset, const MutableBufferSequence& buffers, CompletionCondition& completion_condition, ReadHandler& handler)- : detail::base_from_completion_cond<- CompletionCondition>(completion_condition),+ : base_from_cancellation_state<ReadHandler>(+ handler, enable_partial_cancellation()),+ base_from_completion_cond<CompletionCondition>(completion_condition), device_(device), offset_(offset), buffers_(buffers),@@ -194,7 +195,8 @@ #if defined(ASIO_HAS_MOVE) read_at_op(const read_at_op& other)- : detail::base_from_completion_cond<CompletionCondition>(other),+ : base_from_cancellation_state<ReadHandler>(other),+ base_from_completion_cond<CompletionCondition>(other), device_(other.device_), offset_(other.offset_), buffers_(other.buffers_),@@ -204,8 +206,11 @@ } read_at_op(read_at_op&& other)- : detail::base_from_completion_cond<CompletionCondition>(- ASIO_MOVE_CAST(detail::base_from_completion_cond<+ : base_from_cancellation_state<ReadHandler>(+ ASIO_MOVE_CAST(base_from_cancellation_state<+ ReadHandler>)(other)),+ base_from_completion_cond<CompletionCondition>(+ ASIO_MOVE_CAST(base_from_completion_cond< CompletionCondition>)(other)), device_(other.device_), offset_(other.offset_),@@ -216,7 +221,7 @@ } #endif // defined(ASIO_HAS_MOVE) - void operator()(const asio::error_code& ec,+ void operator()(asio::error_code ec, std::size_t bytes_transferred, int start = 0) { std::size_t max_size;@@ -224,7 +229,7 @@ { case 1: max_size = this->check_for_completion(ec, buffers_.total_consumed());- do+ for (;;) { { ASIO_HANDLER_LOCATION((__FILE__, __LINE__, "async_read_at"));@@ -237,9 +242,18 @@ if ((!ec && bytes_transferred == 0) || buffers_.empty()) break; max_size = this->check_for_completion(ec, buffers_.total_consumed());- } while (max_size > 0);+ if (max_size == 0)+ break;+ if (this->cancelled() != cancellation_type::none)+ {+ ec = asio::error::operation_aborted;+ break;+ }+ } - handler_(ec, buffers_.total_consumed());+ ASIO_MOVE_OR_LVALUE(ReadHandler)(handler_)(+ static_cast<const asio::error_code&>(ec),+ static_cast<const std::size_t&>(buffers_.total_consumed())); } } @@ -331,7 +345,7 @@ template <typename AsyncRandomAccessReadDevice, typename MutableBufferSequence, typename MutableBufferIterator, typename CompletionCondition, typename ReadHandler>- inline void start_read_at_buffer_sequence_op(AsyncRandomAccessReadDevice& d,+ inline void start_read_at_op(AsyncRandomAccessReadDevice& d, uint64_t offset, const MutableBufferSequence& buffers, const MutableBufferIterator&, CompletionCondition& completion_condition, ReadHandler& handler)@@ -343,13 +357,12 @@ } template <typename AsyncRandomAccessReadDevice>- class initiate_async_read_at_buffer_sequence+ class initiate_async_read_at { public: typedef typename AsyncRandomAccessReadDevice::executor_type executor_type; - explicit initiate_async_read_at_buffer_sequence(- AsyncRandomAccessReadDevice& device)+ explicit initiate_async_read_at(AsyncRandomAccessReadDevice& device) : device_(device) { }@@ -371,7 +384,7 @@ non_const_lvalue<ReadHandler> handler2(handler); non_const_lvalue<CompletionCondition> completion_cond2(completion_cond);- start_read_at_buffer_sequence_op(device_, offset, buffers,+ start_read_at_op(device_, offset, buffers, asio::buffer_sequence_begin(buffers), completion_cond2.value, handler2.value); }@@ -383,44 +396,34 @@ #if !defined(GENERATING_DOCUMENTATION) -template <typename AsyncRandomAccessReadDevice,- typename MutableBufferSequence, typename MutableBufferIterator,- typename CompletionCondition, typename ReadHandler, typename Allocator>-struct associated_allocator<+template <template <typename, typename> class Associator,+ typename AsyncRandomAccessReadDevice, typename MutableBufferSequence,+ typename MutableBufferIterator, typename CompletionCondition,+ typename ReadHandler, typename DefaultCandidate>+struct associator<Associator, detail::read_at_op<AsyncRandomAccessReadDevice, MutableBufferSequence,- MutableBufferIterator, CompletionCondition, ReadHandler>,- Allocator>+ MutableBufferIterator, CompletionCondition, ReadHandler>,+ DefaultCandidate>+ : Associator<ReadHandler, DefaultCandidate> {- typedef typename associated_allocator<ReadHandler, Allocator>::type type;-- static type get(- const detail::read_at_op<AsyncRandomAccessReadDevice,- MutableBufferSequence, MutableBufferIterator,- CompletionCondition, ReadHandler>& h,- const Allocator& a = Allocator()) ASIO_NOEXCEPT+ static typename Associator<ReadHandler, DefaultCandidate>::type+ get(const detail::read_at_op<AsyncRandomAccessReadDevice,+ MutableBufferSequence, MutableBufferIterator,+ CompletionCondition, ReadHandler>& h) ASIO_NOEXCEPT {- return associated_allocator<ReadHandler, Allocator>::get(h.handler_, a);+ return Associator<ReadHandler, DefaultCandidate>::get(h.handler_); }-}; -template <typename AsyncRandomAccessReadDevice,- typename MutableBufferSequence, typename MutableBufferIterator,- typename CompletionCondition, typename ReadHandler, typename Executor>-struct associated_executor<- detail::read_at_op<AsyncRandomAccessReadDevice, MutableBufferSequence,- MutableBufferIterator, CompletionCondition, ReadHandler>,- Executor>- : detail::associated_executor_forwarding_base<ReadHandler, Executor>-{- typedef typename associated_executor<ReadHandler, Executor>::type type;-- static type get(- const detail::read_at_op<AsyncRandomAccessReadDevice,- MutableBufferSequence, MutableBufferIterator,- CompletionCondition, ReadHandler>& h,- const Executor& ex = Executor()) ASIO_NOEXCEPT+ static ASIO_AUTO_RETURN_TYPE_PREFIX2(+ typename Associator<ReadHandler, DefaultCandidate>::type)+ get(const detail::read_at_op<AsyncRandomAccessReadDevice,+ MutableBufferSequence, MutableBufferIterator,+ CompletionCondition, ReadHandler>& h,+ const DefaultCandidate& c) ASIO_NOEXCEPT+ ASIO_AUTO_RETURN_TYPE_SUFFIX((+ Associator<ReadHandler, DefaultCandidate>::get(h.handler_, c))) {- return associated_executor<ReadHandler, Executor>::get(h.handler_, ex);+ return Associator<ReadHandler, DefaultCandidate>::get(h.handler_, c); } }; @@ -429,36 +432,45 @@ template <typename AsyncRandomAccessReadDevice, typename MutableBufferSequence, typename CompletionCondition, ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code,- std::size_t)) ReadHandler>-inline ASIO_INITFN_AUTO_RESULT_TYPE(ReadHandler,+ std::size_t)) ReadToken>+inline ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX(ReadToken, void (asio::error_code, std::size_t)) async_read_at(AsyncRandomAccessReadDevice& d, uint64_t offset, const MutableBufferSequence& buffers, CompletionCondition completion_condition,- ASIO_MOVE_ARG(ReadHandler) handler)+ ASIO_MOVE_ARG(ReadToken) token)+ ASIO_INITFN_AUTO_RESULT_TYPE_SUFFIX((+ async_initiate<ReadToken,+ void (asio::error_code, std::size_t)>(+ declval<detail::initiate_async_read_at<AsyncRandomAccessReadDevice> >(),+ token, offset, buffers,+ ASIO_MOVE_CAST(CompletionCondition)(completion_condition)))) {- return async_initiate<ReadHandler,+ return async_initiate<ReadToken, void (asio::error_code, std::size_t)>(- detail::initiate_async_read_at_buffer_sequence<- AsyncRandomAccessReadDevice>(d),- handler, offset, buffers,+ detail::initiate_async_read_at<AsyncRandomAccessReadDevice>(d),+ token, offset, buffers, ASIO_MOVE_CAST(CompletionCondition)(completion_condition)); } template <typename AsyncRandomAccessReadDevice, typename MutableBufferSequence, ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code,- std::size_t)) ReadHandler>-inline ASIO_INITFN_AUTO_RESULT_TYPE(ReadHandler,+ std::size_t)) ReadToken>+inline ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX(ReadToken, void (asio::error_code, std::size_t)) async_read_at(AsyncRandomAccessReadDevice& d, uint64_t offset, const MutableBufferSequence& buffers,- ASIO_MOVE_ARG(ReadHandler) handler)+ ASIO_MOVE_ARG(ReadToken) token)+ ASIO_INITFN_AUTO_RESULT_TYPE_SUFFIX((+ async_initiate<ReadToken,+ void (asio::error_code, std::size_t)>(+ declval<detail::initiate_async_read_at<AsyncRandomAccessReadDevice> >(),+ token, offset, buffers, transfer_all()))) {- return async_initiate<ReadHandler,+ return async_initiate<ReadToken, void (asio::error_code, std::size_t)>(- detail::initiate_async_read_at_buffer_sequence<- AsyncRandomAccessReadDevice>(d),- handler, offset, buffers, transfer_all());+ detail::initiate_async_read_at<AsyncRandomAccessReadDevice>(d),+ token, offset, buffers, transfer_all()); } #if !defined(ASIO_NO_EXTENSIONS)@@ -469,14 +481,16 @@ template <typename AsyncRandomAccessReadDevice, typename Allocator, typename CompletionCondition, typename ReadHandler> class read_at_streambuf_op- : detail::base_from_completion_cond<CompletionCondition>+ : public base_from_cancellation_state<ReadHandler>,+ base_from_completion_cond<CompletionCondition> { public: read_at_streambuf_op(AsyncRandomAccessReadDevice& device, uint64_t offset, basic_streambuf<Allocator>& streambuf, CompletionCondition& completion_condition, ReadHandler& handler)- : detail::base_from_completion_cond<- CompletionCondition>(completion_condition),+ : base_from_cancellation_state<ReadHandler>(+ handler, enable_partial_cancellation()),+ base_from_completion_cond<CompletionCondition>(completion_condition), device_(device), offset_(offset), streambuf_(streambuf),@@ -488,7 +502,8 @@ #if defined(ASIO_HAS_MOVE) read_at_streambuf_op(const read_at_streambuf_op& other)- : detail::base_from_completion_cond<CompletionCondition>(other),+ : base_from_cancellation_state<ReadHandler>(other),+ base_from_completion_cond<CompletionCondition>(other), device_(other.device_), offset_(other.offset_), streambuf_(other.streambuf_),@@ -499,8 +514,11 @@ } read_at_streambuf_op(read_at_streambuf_op&& other)- : detail::base_from_completion_cond<CompletionCondition>(- ASIO_MOVE_CAST(detail::base_from_completion_cond<+ : base_from_cancellation_state<ReadHandler>(+ ASIO_MOVE_CAST(base_from_cancellation_state<+ ReadHandler>)(other)),+ base_from_completion_cond<CompletionCondition>(+ ASIO_MOVE_CAST(base_from_completion_cond< CompletionCondition>)(other)), device_(other.device_), offset_(other.offset_),@@ -512,7 +530,7 @@ } #endif // defined(ASIO_HAS_MOVE) - void operator()(const asio::error_code& ec,+ void operator()(asio::error_code ec, std::size_t bytes_transferred, int start = 0) { std::size_t max_size, bytes_available;@@ -536,9 +554,16 @@ bytes_available = read_size_helper(streambuf_, max_size); if ((!ec && bytes_transferred == 0) || bytes_available == 0) break;+ if (this->cancelled() != cancellation_type::none)+ {+ ec = asio::error::operation_aborted;+ break;+ } } - handler_(ec, static_cast<const std::size_t&>(total_transferred_));+ ASIO_MOVE_OR_LVALUE(ReadHandler)(handler_)(+ static_cast<const asio::error_code&>(ec),+ static_cast<const std::size_t&>(total_transferred_)); } } @@ -662,40 +687,32 @@ #if !defined(GENERATING_DOCUMENTATION) -template <typename AsyncRandomAccessReadDevice, typename Allocator,- typename CompletionCondition, typename ReadHandler, typename Allocator1>-struct associated_allocator<+template <template <typename, typename> class Associator,+ typename AsyncRandomAccessReadDevice, typename Executor,+ typename CompletionCondition, typename ReadHandler,+ typename DefaultCandidate>+struct associator<Associator, detail::read_at_streambuf_op<AsyncRandomAccessReadDevice,- Allocator, CompletionCondition, ReadHandler>,- Allocator1>+ Executor, CompletionCondition, ReadHandler>,+ DefaultCandidate>+ : Associator<ReadHandler, DefaultCandidate> {- typedef typename associated_allocator<ReadHandler, Allocator1>::type type;-- static type get(- const detail::read_at_streambuf_op<AsyncRandomAccessReadDevice,- Allocator, CompletionCondition, ReadHandler>& h,- const Allocator1& a = Allocator1()) ASIO_NOEXCEPT+ static typename Associator<ReadHandler, DefaultCandidate>::type+ get(const detail::read_at_streambuf_op<AsyncRandomAccessReadDevice,+ Executor, CompletionCondition, ReadHandler>& h) ASIO_NOEXCEPT {- return associated_allocator<ReadHandler, Allocator1>::get(h.handler_, a);+ return Associator<ReadHandler, DefaultCandidate>::get(h.handler_); }-}; -template <typename AsyncRandomAccessReadDevice, typename Executor,- typename CompletionCondition, typename ReadHandler, typename Executor1>-struct associated_executor<- detail::read_at_streambuf_op<AsyncRandomAccessReadDevice,- Executor, CompletionCondition, ReadHandler>,- Executor1>- : detail::associated_executor_forwarding_base<ReadHandler, Executor>-{- typedef typename associated_executor<ReadHandler, Executor1>::type type;-- static type get(- const detail::read_at_streambuf_op<AsyncRandomAccessReadDevice,+ static ASIO_AUTO_RETURN_TYPE_PREFIX2(+ typename Associator<ReadHandler, DefaultCandidate>::type)+ get(const detail::read_at_streambuf_op<AsyncRandomAccessReadDevice, Executor, CompletionCondition, ReadHandler>& h,- const Executor1& ex = Executor1()) ASIO_NOEXCEPT+ const DefaultCandidate& c) ASIO_NOEXCEPT+ ASIO_AUTO_RETURN_TYPE_SUFFIX((+ Associator<ReadHandler, DefaultCandidate>::get(h.handler_, c))) {- return associated_executor<ReadHandler, Executor1>::get(h.handler_, ex);+ return Associator<ReadHandler, DefaultCandidate>::get(h.handler_, c); } }; @@ -704,34 +721,47 @@ template <typename AsyncRandomAccessReadDevice, typename Allocator, typename CompletionCondition, ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code,- std::size_t)) ReadHandler>-inline ASIO_INITFN_AUTO_RESULT_TYPE(ReadHandler,+ std::size_t)) ReadToken>+inline ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX(ReadToken, void (asio::error_code, std::size_t)) async_read_at(AsyncRandomAccessReadDevice& d, uint64_t offset, asio::basic_streambuf<Allocator>& b, CompletionCondition completion_condition,- ASIO_MOVE_ARG(ReadHandler) handler)+ ASIO_MOVE_ARG(ReadToken) token)+ ASIO_INITFN_AUTO_RESULT_TYPE_SUFFIX((+ async_initiate<ReadToken,+ void (asio::error_code, std::size_t)>(+ declval<detail::initiate_async_read_at_streambuf<+ AsyncRandomAccessReadDevice> >(),+ token, offset, &b,+ ASIO_MOVE_CAST(CompletionCondition)(completion_condition)))) {- return async_initiate<ReadHandler,+ return async_initiate<ReadToken, void (asio::error_code, std::size_t)>( detail::initiate_async_read_at_streambuf<AsyncRandomAccessReadDevice>(d),- handler, offset, &b,+ token, offset, &b, ASIO_MOVE_CAST(CompletionCondition)(completion_condition)); } template <typename AsyncRandomAccessReadDevice, typename Allocator, ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code,- std::size_t)) ReadHandler>-inline ASIO_INITFN_AUTO_RESULT_TYPE(ReadHandler,+ std::size_t)) ReadToken>+inline ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX(ReadToken, void (asio::error_code, std::size_t)) async_read_at(AsyncRandomAccessReadDevice& d, uint64_t offset, asio::basic_streambuf<Allocator>& b,- ASIO_MOVE_ARG(ReadHandler) handler)+ ASIO_MOVE_ARG(ReadToken) token)+ ASIO_INITFN_AUTO_RESULT_TYPE_SUFFIX((+ async_initiate<ReadToken,+ void (asio::error_code, std::size_t)>(+ declval<detail::initiate_async_read_at_streambuf<+ AsyncRandomAccessReadDevice> >(),+ token, offset, &b, transfer_all()))) {- return async_initiate<ReadHandler,+ return async_initiate<ReadToken, void (asio::error_code, std::size_t)>( detail::initiate_async_read_at_streambuf<AsyncRandomAccessReadDevice>(d),- handler, offset, &b, transfer_all());+ token, offset, &b, transfer_all()); } #endif // !defined(ASIO_NO_IOSTREAM)
link/modules/asio-standalone/asio/include/asio/impl/read_until.hpp view
@@ -2,7 +2,7 @@ // impl/read_until.hpp // ~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -19,10 +19,10 @@ #include <string> #include <vector> #include <utility>-#include "asio/associated_allocator.hpp"-#include "asio/associated_executor.hpp"+#include "asio/associator.hpp" #include "asio/buffer.hpp" #include "asio/buffers_iterator.hpp"+#include "asio/detail/base_from_cancellation_state.hpp" #include "asio/detail/bind_handler.hpp" #include "asio/detail/handler_alloc_helpers.hpp" #include "asio/detail/handler_cont_helpers.hpp"@@ -77,10 +77,12 @@ template <typename SyncReadStream, typename DynamicBuffer_v1> inline std::size_t read_until(SyncReadStream& s, ASIO_MOVE_ARG(DynamicBuffer_v1) buffers, char delim,- typename enable_if<+ typename constraint< is_dynamic_buffer_v1<typename decay<DynamicBuffer_v1>::type>::value- && !is_dynamic_buffer_v2<typename decay<DynamicBuffer_v1>::type>::value- >::type*)+ >::type,+ typename constraint<+ !is_dynamic_buffer_v2<typename decay<DynamicBuffer_v1>::type>::value+ >::type) { asio::error_code ec; std::size_t bytes_transferred = read_until(s,@@ -93,10 +95,12 @@ std::size_t read_until(SyncReadStream& s, ASIO_MOVE_ARG(DynamicBuffer_v1) buffers, char delim, asio::error_code& ec,- typename enable_if<+ typename constraint< is_dynamic_buffer_v1<typename decay<DynamicBuffer_v1>::type>::value- && !is_dynamic_buffer_v2<typename decay<DynamicBuffer_v1>::type>::value- >::type*)+ >::type,+ typename constraint<+ !is_dynamic_buffer_v2<typename decay<DynamicBuffer_v1>::type>::value+ >::type) { typename decay<DynamicBuffer_v1>::type b( ASIO_MOVE_CAST(DynamicBuffer_v1)(buffers));@@ -147,10 +151,12 @@ inline std::size_t read_until(SyncReadStream& s, ASIO_MOVE_ARG(DynamicBuffer_v1) buffers, ASIO_STRING_VIEW_PARAM delim,- typename enable_if<+ typename constraint< is_dynamic_buffer_v1<typename decay<DynamicBuffer_v1>::type>::value- && !is_dynamic_buffer_v2<typename decay<DynamicBuffer_v1>::type>::value- >::type*)+ >::type,+ typename constraint<+ !is_dynamic_buffer_v2<typename decay<DynamicBuffer_v1>::type>::value+ >::type) { asio::error_code ec; std::size_t bytes_transferred = read_until(s,@@ -163,10 +169,12 @@ std::size_t read_until(SyncReadStream& s, ASIO_MOVE_ARG(DynamicBuffer_v1) buffers, ASIO_STRING_VIEW_PARAM delim, asio::error_code& ec,- typename enable_if<+ typename constraint< is_dynamic_buffer_v1<typename decay<DynamicBuffer_v1>::type>::value- && !is_dynamic_buffer_v2<typename decay<DynamicBuffer_v1>::type>::value- >::type*)+ >::type,+ typename constraint<+ !is_dynamic_buffer_v2<typename decay<DynamicBuffer_v1>::type>::value+ >::type) { typename decay<DynamicBuffer_v1>::type b( ASIO_MOVE_CAST(DynamicBuffer_v1)(buffers));@@ -229,10 +237,12 @@ inline std::size_t read_until(SyncReadStream& s, ASIO_MOVE_ARG(DynamicBuffer_v1) buffers, const boost::regex& expr,- typename enable_if<+ typename constraint< is_dynamic_buffer_v1<typename decay<DynamicBuffer_v1>::type>::value- && !is_dynamic_buffer_v2<typename decay<DynamicBuffer_v1>::type>::value- >::type*)+ >::type,+ typename constraint<+ !is_dynamic_buffer_v2<typename decay<DynamicBuffer_v1>::type>::value+ >::type) { asio::error_code ec; std::size_t bytes_transferred = read_until(s,@@ -245,10 +255,12 @@ std::size_t read_until(SyncReadStream& s, ASIO_MOVE_ARG(DynamicBuffer_v1) buffers, const boost::regex& expr, asio::error_code& ec,- typename enable_if<+ typename constraint< is_dynamic_buffer_v1<typename decay<DynamicBuffer_v1>::type>::value- && !is_dynamic_buffer_v2<typename decay<DynamicBuffer_v1>::type>::value- >::type*)+ >::type,+ typename constraint<+ !is_dynamic_buffer_v2<typename decay<DynamicBuffer_v1>::type>::value+ >::type) { typename decay<DynamicBuffer_v1>::type b( ASIO_MOVE_CAST(DynamicBuffer_v1)(buffers));@@ -313,11 +325,15 @@ inline std::size_t read_until(SyncReadStream& s, ASIO_MOVE_ARG(DynamicBuffer_v1) buffers, MatchCondition match_condition,- typename enable_if<+ typename constraint< is_match_condition<MatchCondition>::value- && is_dynamic_buffer_v1<typename decay<DynamicBuffer_v1>::type>::value- && !is_dynamic_buffer_v2<typename decay<DynamicBuffer_v1>::type>::value- >::type*)+ >::type,+ typename constraint<+ is_dynamic_buffer_v1<typename decay<DynamicBuffer_v1>::type>::value+ >::type,+ typename constraint<+ !is_dynamic_buffer_v2<typename decay<DynamicBuffer_v1>::type>::value+ >::type) { asio::error_code ec; std::size_t bytes_transferred = read_until(s,@@ -332,11 +348,15 @@ std::size_t read_until(SyncReadStream& s, ASIO_MOVE_ARG(DynamicBuffer_v1) buffers, MatchCondition match_condition, asio::error_code& ec,- typename enable_if<+ typename constraint< is_match_condition<MatchCondition>::value- && is_dynamic_buffer_v1<typename decay<DynamicBuffer_v1>::type>::value- && !is_dynamic_buffer_v2<typename decay<DynamicBuffer_v1>::type>::value- >::type*)+ >::type,+ typename constraint<+ is_dynamic_buffer_v1<typename decay<DynamicBuffer_v1>::type>::value+ >::type,+ typename constraint<+ !is_dynamic_buffer_v2<typename decay<DynamicBuffer_v1>::type>::value+ >::type) { typename decay<DynamicBuffer_v1>::type b( ASIO_MOVE_CAST(DynamicBuffer_v1)(buffers));@@ -443,7 +463,7 @@ template <typename SyncReadStream, typename Allocator, typename MatchCondition> inline std::size_t read_until(SyncReadStream& s, asio::basic_streambuf<Allocator>& b, MatchCondition match_condition,- typename enable_if<is_match_condition<MatchCondition>::value>::type*)+ typename constraint<is_match_condition<MatchCondition>::value>::type) { return read_until(s, basic_streambuf_ref<Allocator>(b), match_condition); }@@ -452,7 +472,7 @@ inline std::size_t read_until(SyncReadStream& s, asio::basic_streambuf<Allocator>& b, MatchCondition match_condition, asio::error_code& ec,- typename enable_if<is_match_condition<MatchCondition>::value>::type*)+ typename constraint<is_match_condition<MatchCondition>::value>::type) { return read_until(s, basic_streambuf_ref<Allocator>(b), match_condition, ec); }@@ -464,9 +484,9 @@ template <typename SyncReadStream, typename DynamicBuffer_v2> inline std::size_t read_until(SyncReadStream& s, DynamicBuffer_v2 buffers, char delim,- typename enable_if<+ typename constraint< is_dynamic_buffer_v2<DynamicBuffer_v2>::value- >::type*)+ >::type) { asio::error_code ec; std::size_t bytes_transferred = read_until(s,@@ -478,9 +498,9 @@ template <typename SyncReadStream, typename DynamicBuffer_v2> std::size_t read_until(SyncReadStream& s, DynamicBuffer_v2 buffers, char delim, asio::error_code& ec,- typename enable_if<+ typename constraint< is_dynamic_buffer_v2<DynamicBuffer_v2>::value- >::type*)+ >::type) { DynamicBuffer_v2& b = buffers; @@ -533,9 +553,9 @@ template <typename SyncReadStream, typename DynamicBuffer_v2> inline std::size_t read_until(SyncReadStream& s, DynamicBuffer_v2 buffers, ASIO_STRING_VIEW_PARAM delim,- typename enable_if<+ typename constraint< is_dynamic_buffer_v2<DynamicBuffer_v2>::value- >::type*)+ >::type) { asio::error_code ec; std::size_t bytes_transferred = read_until(s,@@ -547,9 +567,9 @@ template <typename SyncReadStream, typename DynamicBuffer_v2> std::size_t read_until(SyncReadStream& s, DynamicBuffer_v2 buffers, ASIO_STRING_VIEW_PARAM delim, asio::error_code& ec,- typename enable_if<+ typename constraint< is_dynamic_buffer_v2<DynamicBuffer_v2>::value- >::type*)+ >::type) { DynamicBuffer_v2& b = buffers; @@ -614,9 +634,9 @@ template <typename SyncReadStream, typename DynamicBuffer_v2> inline std::size_t read_until(SyncReadStream& s, DynamicBuffer_v2 buffers, const boost::regex& expr,- typename enable_if<+ typename constraint< is_dynamic_buffer_v2<DynamicBuffer_v2>::value- >::type*)+ >::type) { asio::error_code ec; std::size_t bytes_transferred = read_until(s,@@ -628,9 +648,9 @@ template <typename SyncReadStream, typename DynamicBuffer_v2> std::size_t read_until(SyncReadStream& s, DynamicBuffer_v2 buffers, const boost::regex& expr, asio::error_code& ec,- typename enable_if<+ typename constraint< is_dynamic_buffer_v2<DynamicBuffer_v2>::value- >::type*)+ >::type) { DynamicBuffer_v2& b = buffers; @@ -697,10 +717,12 @@ typename DynamicBuffer_v2, typename MatchCondition> inline std::size_t read_until(SyncReadStream& s, DynamicBuffer_v2 buffers, MatchCondition match_condition,- typename enable_if<+ typename constraint< is_match_condition<MatchCondition>::value- && is_dynamic_buffer_v2<DynamicBuffer_v2>::value- >::type*)+ >::type,+ typename constraint<+ is_dynamic_buffer_v2<DynamicBuffer_v2>::value+ >::type) { asio::error_code ec; std::size_t bytes_transferred = read_until(s,@@ -714,10 +736,12 @@ typename DynamicBuffer_v2, typename MatchCondition> std::size_t read_until(SyncReadStream& s, DynamicBuffer_v2 buffers, MatchCondition match_condition, asio::error_code& ec,- typename enable_if<+ typename constraint< is_match_condition<MatchCondition>::value- && is_dynamic_buffer_v2<DynamicBuffer_v2>::value- >::type*)+ >::type,+ typename constraint<+ is_dynamic_buffer_v2<DynamicBuffer_v2>::value+ >::type) { DynamicBuffer_v2& b = buffers; @@ -781,13 +805,16 @@ template <typename AsyncReadStream, typename DynamicBuffer_v1, typename ReadHandler> class read_until_delim_op_v1+ : public base_from_cancellation_state<ReadHandler> { public: template <typename BufferSequence> read_until_delim_op_v1(AsyncReadStream& stream, ASIO_MOVE_ARG(BufferSequence) buffers, char delim, ReadHandler& handler)- : stream_(stream),+ : base_from_cancellation_state<ReadHandler>(+ handler, enable_partial_cancellation()),+ stream_(stream), buffers_(ASIO_MOVE_CAST(BufferSequence)(buffers)), delim_(delim), start_(0),@@ -798,7 +825,8 @@ #if defined(ASIO_HAS_MOVE) read_until_delim_op_v1(const read_until_delim_op_v1& other)- : stream_(other.stream_),+ : base_from_cancellation_state<ReadHandler>(other),+ stream_(other.stream_), buffers_(other.buffers_), delim_(other.delim_), start_(other.start_),@@ -808,7 +836,10 @@ } read_until_delim_op_v1(read_until_delim_op_v1&& other)- : stream_(other.stream_),+ : base_from_cancellation_state<ReadHandler>(+ ASIO_MOVE_CAST(base_from_cancellation_state<+ ReadHandler>)(other)),+ stream_(other.stream_), buffers_(ASIO_MOVE_CAST(DynamicBuffer_v1)(other.buffers_)), delim_(other.delim_), start_(other.start_),@@ -818,7 +849,7 @@ } #endif // defined(ASIO_HAS_MOVE) - void operator()(const asio::error_code& ec,+ void operator()(asio::error_code ec, std::size_t bytes_transferred, int start = 0) { const std::size_t not_found = (std::numeric_limits<std::size_t>::max)();@@ -882,6 +913,11 @@ buffers_.commit(bytes_transferred); if (ec || bytes_transferred == 0) break;+ if (this->cancelled() != cancellation_type::none)+ {+ ec = error::operation_aborted;+ break;+ } } const asio::error_code result_ec =@@ -892,7 +928,7 @@ (ec || search_position_ == not_found) ? 0 : search_position_; - handler_(result_ec, result_n);+ ASIO_MOVE_OR_LVALUE(ReadHandler)(handler_)(result_ec, result_n); } } @@ -1014,40 +1050,31 @@ #if !defined(GENERATING_DOCUMENTATION) -template <typename AsyncReadStream, typename DynamicBuffer_v1,- typename ReadHandler, typename Allocator>-struct associated_allocator<+template <template <typename, typename> class Associator,+ typename AsyncReadStream, typename DynamicBuffer_v1,+ typename ReadHandler, typename DefaultCandidate>+struct associator<Associator, detail::read_until_delim_op_v1<AsyncReadStream, DynamicBuffer_v1, ReadHandler>,- Allocator>+ DefaultCandidate>+ : Associator<ReadHandler, DefaultCandidate> {- typedef typename associated_allocator<ReadHandler, Allocator>::type type;-- static type get(- const detail::read_until_delim_op_v1<AsyncReadStream,- DynamicBuffer_v1, ReadHandler>& h,- const Allocator& a = Allocator()) ASIO_NOEXCEPT+ static typename Associator<ReadHandler, DefaultCandidate>::type+ get(const detail::read_until_delim_op_v1<AsyncReadStream,+ DynamicBuffer_v1, ReadHandler>& h) ASIO_NOEXCEPT {- return associated_allocator<ReadHandler, Allocator>::get(h.handler_, a);+ return Associator<ReadHandler, DefaultCandidate>::get(h.handler_); }-}; -template <typename AsyncReadStream, typename DynamicBuffer_v1,- typename ReadHandler, typename Executor>-struct associated_executor<- detail::read_until_delim_op_v1<AsyncReadStream,- DynamicBuffer_v1, ReadHandler>,- Executor>- : detail::associated_executor_forwarding_base<ReadHandler, Executor>-{- typedef typename associated_executor<ReadHandler, Executor>::type type;-- static type get(- const detail::read_until_delim_op_v1<AsyncReadStream,+ static ASIO_AUTO_RETURN_TYPE_PREFIX2(+ typename Associator<ReadHandler, DefaultCandidate>::type)+ get(const detail::read_until_delim_op_v1<AsyncReadStream, DynamicBuffer_v1, ReadHandler>& h,- const Executor& ex = Executor()) ASIO_NOEXCEPT+ const DefaultCandidate& c) ASIO_NOEXCEPT+ ASIO_AUTO_RETURN_TYPE_SUFFIX((+ Associator<ReadHandler, DefaultCandidate>::get(h.handler_, c))) {- return associated_executor<ReadHandler, Executor>::get(h.handler_, ex);+ return Associator<ReadHandler, DefaultCandidate>::get(h.handler_, c); } }; @@ -1055,21 +1082,28 @@ template <typename AsyncReadStream, typename DynamicBuffer_v1, ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code,- std::size_t)) ReadHandler>-ASIO_INITFN_AUTO_RESULT_TYPE(ReadHandler,+ std::size_t)) ReadToken>+ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX(ReadToken, void (asio::error_code, std::size_t)) async_read_until(AsyncReadStream& s, ASIO_MOVE_ARG(DynamicBuffer_v1) buffers,- char delim, ASIO_MOVE_ARG(ReadHandler) handler,- typename enable_if<+ char delim, ASIO_MOVE_ARG(ReadToken) token,+ typename constraint< is_dynamic_buffer_v1<typename decay<DynamicBuffer_v1>::type>::value- && !is_dynamic_buffer_v2<typename decay<DynamicBuffer_v1>::type>::value- >::type*)+ >::type,+ typename constraint<+ !is_dynamic_buffer_v2<typename decay<DynamicBuffer_v1>::type>::value+ >::type)+ ASIO_INITFN_AUTO_RESULT_TYPE_SUFFIX((+ async_initiate<ReadToken,+ void (asio::error_code, std::size_t)>(+ declval<detail::initiate_async_read_until_delim_v1<AsyncReadStream> >(),+ token, ASIO_MOVE_CAST(DynamicBuffer_v1)(buffers), delim))) {- return async_initiate<ReadHandler,+ return async_initiate<ReadToken, void (asio::error_code, std::size_t)>( detail::initiate_async_read_until_delim_v1<AsyncReadStream>(s),- handler, ASIO_MOVE_CAST(DynamicBuffer_v1)(buffers), delim);+ token, ASIO_MOVE_CAST(DynamicBuffer_v1)(buffers), delim); } namespace detail@@ -1077,13 +1111,16 @@ template <typename AsyncReadStream, typename DynamicBuffer_v1, typename ReadHandler> class read_until_delim_string_op_v1+ : public base_from_cancellation_state<ReadHandler> { public: template <typename BufferSequence> read_until_delim_string_op_v1(AsyncReadStream& stream, ASIO_MOVE_ARG(BufferSequence) buffers, const std::string& delim, ReadHandler& handler)- : stream_(stream),+ : base_from_cancellation_state<ReadHandler>(+ handler, enable_partial_cancellation()),+ stream_(stream), buffers_(ASIO_MOVE_CAST(BufferSequence)(buffers)), delim_(delim), start_(0),@@ -1094,7 +1131,8 @@ #if defined(ASIO_HAS_MOVE) read_until_delim_string_op_v1(const read_until_delim_string_op_v1& other)- : stream_(other.stream_),+ : base_from_cancellation_state<ReadHandler>(other),+ stream_(other.stream_), buffers_(other.buffers_), delim_(other.delim_), start_(other.start_),@@ -1104,7 +1142,10 @@ } read_until_delim_string_op_v1(read_until_delim_string_op_v1&& other)- : stream_(other.stream_),+ : base_from_cancellation_state<ReadHandler>(+ ASIO_MOVE_CAST(base_from_cancellation_state<+ ReadHandler>)(other)),+ stream_(other.stream_), buffers_(ASIO_MOVE_CAST(DynamicBuffer_v1)(other.buffers_)), delim_(ASIO_MOVE_CAST(std::string)(other.delim_)), start_(other.start_),@@ -1114,7 +1155,7 @@ } #endif // defined(ASIO_HAS_MOVE) - void operator()(const asio::error_code& ec,+ void operator()(asio::error_code ec, std::size_t bytes_transferred, int start = 0) { const std::size_t not_found = (std::numeric_limits<std::size_t>::max)();@@ -1189,6 +1230,11 @@ buffers_.commit(bytes_transferred); if (ec || bytes_transferred == 0) break;+ if (this->cancelled() != cancellation_type::none)+ {+ ec = error::operation_aborted;+ break;+ } } const asio::error_code result_ec =@@ -1199,7 +1245,7 @@ (ec || search_position_ == not_found) ? 0 : search_position_; - handler_(result_ec, result_n);+ ASIO_MOVE_OR_LVALUE(ReadHandler)(handler_)(result_ec, result_n); } } @@ -1321,40 +1367,31 @@ #if !defined(GENERATING_DOCUMENTATION) -template <typename AsyncReadStream, typename DynamicBuffer_v1,- typename ReadHandler, typename Allocator>-struct associated_allocator<+template <template <typename, typename> class Associator,+ typename AsyncReadStream, typename DynamicBuffer_v1,+ typename ReadHandler, typename DefaultCandidate>+struct associator<Associator, detail::read_until_delim_string_op_v1<AsyncReadStream, DynamicBuffer_v1, ReadHandler>,- Allocator>+ DefaultCandidate>+ : Associator<ReadHandler, DefaultCandidate> {- typedef typename associated_allocator<ReadHandler, Allocator>::type type;-- static type get(- const detail::read_until_delim_string_op_v1<AsyncReadStream,- DynamicBuffer_v1, ReadHandler>& h,- const Allocator& a = Allocator()) ASIO_NOEXCEPT+ static typename Associator<ReadHandler, DefaultCandidate>::type+ get(const detail::read_until_delim_string_op_v1<AsyncReadStream,+ DynamicBuffer_v1, ReadHandler>& h) ASIO_NOEXCEPT {- return associated_allocator<ReadHandler, Allocator>::get(h.handler_, a);+ return Associator<ReadHandler, DefaultCandidate>::get(h.handler_); }-}; -template <typename AsyncReadStream, typename DynamicBuffer_v1,- typename ReadHandler, typename Executor>-struct associated_executor<- detail::read_until_delim_string_op_v1<AsyncReadStream,- DynamicBuffer_v1, ReadHandler>,- Executor>- : detail::associated_executor_forwarding_base<ReadHandler, Executor>-{- typedef typename associated_executor<ReadHandler, Executor>::type type;-- static type get(- const detail::read_until_delim_string_op_v1<AsyncReadStream,+ static ASIO_AUTO_RETURN_TYPE_PREFIX2(+ typename Associator<ReadHandler, DefaultCandidate>::type)+ get(const detail::read_until_delim_string_op_v1<AsyncReadStream, DynamicBuffer_v1, ReadHandler>& h,- const Executor& ex = Executor()) ASIO_NOEXCEPT+ const DefaultCandidate& c) ASIO_NOEXCEPT+ ASIO_AUTO_RETURN_TYPE_SUFFIX((+ Associator<ReadHandler, DefaultCandidate>::get(h.handler_, c))) {- return associated_executor<ReadHandler, Executor>::get(h.handler_, ex);+ return Associator<ReadHandler, DefaultCandidate>::get(h.handler_, c); } }; @@ -1362,22 +1399,31 @@ template <typename AsyncReadStream, typename DynamicBuffer_v1, ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code,- std::size_t)) ReadHandler>-ASIO_INITFN_AUTO_RESULT_TYPE(ReadHandler,+ std::size_t)) ReadToken>+ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX(ReadToken, void (asio::error_code, std::size_t)) async_read_until(AsyncReadStream& s, ASIO_MOVE_ARG(DynamicBuffer_v1) buffers, ASIO_STRING_VIEW_PARAM delim,- ASIO_MOVE_ARG(ReadHandler) handler,- typename enable_if<+ ASIO_MOVE_ARG(ReadToken) token,+ typename constraint< is_dynamic_buffer_v1<typename decay<DynamicBuffer_v1>::type>::value- && !is_dynamic_buffer_v2<typename decay<DynamicBuffer_v1>::type>::value- >::type*)+ >::type,+ typename constraint<+ !is_dynamic_buffer_v2<typename decay<DynamicBuffer_v1>::type>::value+ >::type)+ ASIO_INITFN_AUTO_RESULT_TYPE_SUFFIX((+ async_initiate<ReadToken,+ void (asio::error_code, std::size_t)>(+ declval<detail::initiate_async_read_until_delim_string_v1<+ AsyncReadStream> >(),+ token, ASIO_MOVE_CAST(DynamicBuffer_v1)(buffers),+ static_cast<std::string>(delim)))) {- return async_initiate<ReadHandler,+ return async_initiate<ReadToken, void (asio::error_code, std::size_t)>( detail::initiate_async_read_until_delim_string_v1<AsyncReadStream>(s),- handler, ASIO_MOVE_CAST(DynamicBuffer_v1)(buffers),+ token, ASIO_MOVE_CAST(DynamicBuffer_v1)(buffers), static_cast<std::string>(delim)); } @@ -1389,13 +1435,16 @@ template <typename AsyncReadStream, typename DynamicBuffer_v1, typename RegEx, typename ReadHandler> class read_until_expr_op_v1+ : public base_from_cancellation_state<ReadHandler> { public: template <typename BufferSequence> read_until_expr_op_v1(AsyncReadStream& stream, ASIO_MOVE_ARG(BufferSequence) buffers, const boost::regex& expr, ReadHandler& handler)- : stream_(stream),+ : base_from_cancellation_state<ReadHandler>(+ handler, enable_partial_cancellation()),+ stream_(stream), buffers_(ASIO_MOVE_CAST(BufferSequence)(buffers)), expr_(expr), start_(0),@@ -1406,7 +1455,8 @@ #if defined(ASIO_HAS_MOVE) read_until_expr_op_v1(const read_until_expr_op_v1& other)- : stream_(other.stream_),+ : base_from_cancellation_state<ReadHandler>(other),+ stream_(other.stream_), buffers_(other.buffers_), expr_(other.expr_), start_(other.start_),@@ -1416,7 +1466,10 @@ } read_until_expr_op_v1(read_until_expr_op_v1&& other)- : stream_(other.stream_),+ : base_from_cancellation_state<ReadHandler>(+ ASIO_MOVE_CAST(base_from_cancellation_state<+ ReadHandler>)(other)),+ stream_(other.stream_), buffers_(ASIO_MOVE_CAST(DynamicBuffer_v1)(other.buffers_)), expr_(other.expr_), start_(other.start_),@@ -1426,7 +1479,7 @@ } #endif // defined(ASIO_HAS_MOVE) - void operator()(const asio::error_code& ec,+ void operator()(asio::error_code ec, std::size_t bytes_transferred, int start = 0) { const std::size_t not_found = (std::numeric_limits<std::size_t>::max)();@@ -1504,6 +1557,11 @@ buffers_.commit(bytes_transferred); if (ec || bytes_transferred == 0) break;+ if (this->cancelled() != cancellation_type::none)+ {+ ec = error::operation_aborted;+ break;+ } } const asio::error_code result_ec =@@ -1514,7 +1572,7 @@ (ec || search_position_ == not_found) ? 0 : search_position_; - handler_(result_ec, result_n);+ ASIO_MOVE_OR_LVALUE(ReadHandler)(handler_)(result_ec, result_n); } } @@ -1635,40 +1693,31 @@ #if !defined(GENERATING_DOCUMENTATION) -template <typename AsyncReadStream, typename DynamicBuffer_v1,- typename RegEx, typename ReadHandler, typename Allocator>-struct associated_allocator<+template <template <typename, typename> class Associator,+ typename AsyncReadStream, typename DynamicBuffer_v1,+ typename RegEx, typename ReadHandler, typename DefaultCandidate>+struct associator<Associator, detail::read_until_expr_op_v1<AsyncReadStream, DynamicBuffer_v1, RegEx, ReadHandler>,- Allocator>+ DefaultCandidate>+ : Associator<ReadHandler, DefaultCandidate> {- typedef typename associated_allocator<ReadHandler, Allocator>::type type;-- static type get(- const detail::read_until_expr_op_v1<AsyncReadStream,- DynamicBuffer_v1, RegEx, ReadHandler>& h,- const Allocator& a = Allocator()) ASIO_NOEXCEPT+ static typename Associator<ReadHandler, DefaultCandidate>::type+ get(const detail::read_until_expr_op_v1<AsyncReadStream,+ DynamicBuffer_v1, RegEx, ReadHandler>& h) ASIO_NOEXCEPT {- return associated_allocator<ReadHandler, Allocator>::get(h.handler_, a);+ return Associator<ReadHandler, DefaultCandidate>::get(h.handler_); }-}; -template <typename AsyncReadStream, typename DynamicBuffer_v1,- typename RegEx, typename ReadHandler, typename Executor>-struct associated_executor<- detail::read_until_expr_op_v1<AsyncReadStream,- DynamicBuffer_v1, RegEx, ReadHandler>,- Executor>- : detail::associated_executor_forwarding_base<ReadHandler, Executor>-{- typedef typename associated_executor<ReadHandler, Executor>::type type;-- static type get(- const detail::read_until_expr_op_v1<AsyncReadStream,+ static ASIO_AUTO_RETURN_TYPE_PREFIX2(+ typename Associator<ReadHandler, DefaultCandidate>::type)+ get(const detail::read_until_expr_op_v1<AsyncReadStream, DynamicBuffer_v1, RegEx, ReadHandler>& h,- const Executor& ex = Executor()) ASIO_NOEXCEPT+ const DefaultCandidate& c) ASIO_NOEXCEPT+ ASIO_AUTO_RETURN_TYPE_SUFFIX((+ Associator<ReadHandler, DefaultCandidate>::get(h.handler_, c))) {- return associated_executor<ReadHandler, Executor>::get(h.handler_, ex);+ return Associator<ReadHandler, DefaultCandidate>::get(h.handler_, c); } }; @@ -1676,22 +1725,29 @@ template <typename AsyncReadStream, typename DynamicBuffer_v1, ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code,- std::size_t)) ReadHandler>-ASIO_INITFN_AUTO_RESULT_TYPE(ReadHandler,+ std::size_t)) ReadToken>+ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX(ReadToken, void (asio::error_code, std::size_t)) async_read_until(AsyncReadStream& s, ASIO_MOVE_ARG(DynamicBuffer_v1) buffers, const boost::regex& expr,- ASIO_MOVE_ARG(ReadHandler) handler,- typename enable_if<+ ASIO_MOVE_ARG(ReadToken) token,+ typename constraint< is_dynamic_buffer_v1<typename decay<DynamicBuffer_v1>::type>::value- && !is_dynamic_buffer_v2<typename decay<DynamicBuffer_v1>::type>::value- >::type*)+ >::type,+ typename constraint<+ !is_dynamic_buffer_v2<typename decay<DynamicBuffer_v1>::type>::value+ >::type)+ ASIO_INITFN_AUTO_RESULT_TYPE_SUFFIX((+ async_initiate<ReadToken,+ void (asio::error_code, std::size_t)>(+ declval<detail::initiate_async_read_until_expr_v1<AsyncReadStream> >(),+ token, ASIO_MOVE_CAST(DynamicBuffer_v1)(buffers), expr))) {- return async_initiate<ReadHandler,+ return async_initiate<ReadToken, void (asio::error_code, std::size_t)>( detail::initiate_async_read_until_expr_v1<AsyncReadStream>(s),- handler, ASIO_MOVE_CAST(DynamicBuffer_v1)(buffers), expr);+ token, ASIO_MOVE_CAST(DynamicBuffer_v1)(buffers), expr); } #endif // defined(ASIO_HAS_BOOST_REGEX)@@ -1701,13 +1757,16 @@ template <typename AsyncReadStream, typename DynamicBuffer_v1, typename MatchCondition, typename ReadHandler> class read_until_match_op_v1+ : public base_from_cancellation_state<ReadHandler> { public: template <typename BufferSequence> read_until_match_op_v1(AsyncReadStream& stream, ASIO_MOVE_ARG(BufferSequence) buffers, MatchCondition match_condition, ReadHandler& handler)- : stream_(stream),+ : base_from_cancellation_state<ReadHandler>(+ handler, enable_partial_cancellation()),+ stream_(stream), buffers_(ASIO_MOVE_CAST(BufferSequence)(buffers)), match_condition_(match_condition), start_(0),@@ -1718,7 +1777,8 @@ #if defined(ASIO_HAS_MOVE) read_until_match_op_v1(const read_until_match_op_v1& other)- : stream_(other.stream_),+ : base_from_cancellation_state<ReadHandler>(other),+ stream_(other.stream_), buffers_(other.buffers_), match_condition_(other.match_condition_), start_(other.start_),@@ -1728,7 +1788,10 @@ } read_until_match_op_v1(read_until_match_op_v1&& other)- : stream_(other.stream_),+ : base_from_cancellation_state<ReadHandler>(+ ASIO_MOVE_CAST(base_from_cancellation_state<+ ReadHandler>)(other)),+ stream_(other.stream_), buffers_(ASIO_MOVE_CAST(DynamicBuffer_v1)(other.buffers_)), match_condition_(other.match_condition_), start_(other.start_),@@ -1738,7 +1801,7 @@ } #endif // defined(ASIO_HAS_MOVE) - void operator()(const asio::error_code& ec,+ void operator()(asio::error_code ec, std::size_t bytes_transferred, int start = 0) { const std::size_t not_found = (std::numeric_limits<std::size_t>::max)();@@ -1812,6 +1875,11 @@ buffers_.commit(bytes_transferred); if (ec || bytes_transferred == 0) break;+ if (this->cancelled() != cancellation_type::none)+ {+ ec = error::operation_aborted;+ break;+ } } const asio::error_code result_ec =@@ -1822,7 +1890,7 @@ (ec || search_position_ == not_found) ? 0 : search_position_; - handler_(result_ec, result_n);+ ASIO_MOVE_OR_LVALUE(ReadHandler)(handler_)(result_ec, result_n); } } @@ -1947,40 +2015,31 @@ #if !defined(GENERATING_DOCUMENTATION) -template <typename AsyncReadStream, typename DynamicBuffer_v1,- typename MatchCondition, typename ReadHandler, typename Allocator>-struct associated_allocator<+template <template <typename, typename> class Associator,+ typename AsyncReadStream, typename DynamicBuffer_v1,+ typename MatchCondition, typename ReadHandler, typename DefaultCandidate>+struct associator<Associator, detail::read_until_match_op_v1<AsyncReadStream, DynamicBuffer_v1, MatchCondition, ReadHandler>,- Allocator>+ DefaultCandidate>+ : Associator<ReadHandler, DefaultCandidate> {- typedef typename associated_allocator<ReadHandler, Allocator>::type type;-- static type get(- const detail::read_until_match_op_v1<AsyncReadStream,- DynamicBuffer_v1, MatchCondition, ReadHandler>& h,- const Allocator& a = Allocator()) ASIO_NOEXCEPT+ static typename Associator<ReadHandler, DefaultCandidate>::type+ get(const detail::read_until_match_op_v1<AsyncReadStream,+ DynamicBuffer_v1, MatchCondition, ReadHandler>& h) ASIO_NOEXCEPT {- return associated_allocator<ReadHandler, Allocator>::get(h.handler_, a);+ return Associator<ReadHandler, DefaultCandidate>::get(h.handler_); }-}; -template <typename AsyncReadStream, typename DynamicBuffer_v1,- typename MatchCondition, typename ReadHandler, typename Executor>-struct associated_executor<- detail::read_until_match_op_v1<AsyncReadStream,- DynamicBuffer_v1, MatchCondition, ReadHandler>,- Executor>- : detail::associated_executor_forwarding_base<ReadHandler, Executor>-{- typedef typename associated_executor<ReadHandler, Executor>::type type;-- static type get(- const detail::read_until_match_op_v1<AsyncReadStream,+ static ASIO_AUTO_RETURN_TYPE_PREFIX2(+ typename Associator<ReadHandler, DefaultCandidate>::type)+ get(const detail::read_until_match_op_v1<AsyncReadStream, DynamicBuffer_v1, MatchCondition, ReadHandler>& h,- const Executor& ex = Executor()) ASIO_NOEXCEPT+ const DefaultCandidate& c) ASIO_NOEXCEPT+ ASIO_AUTO_RETURN_TYPE_SUFFIX((+ Associator<ReadHandler, DefaultCandidate>::get(h.handler_, c))) {- return associated_executor<ReadHandler, Executor>::get(h.handler_, ex);+ return Associator<ReadHandler, DefaultCandidate>::get(h.handler_, c); } }; @@ -1989,82 +2048,105 @@ template <typename AsyncReadStream, typename DynamicBuffer_v1, typename MatchCondition, ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code,- std::size_t)) ReadHandler>-ASIO_INITFN_AUTO_RESULT_TYPE(ReadHandler,+ std::size_t)) ReadToken>+ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX(ReadToken, void (asio::error_code, std::size_t)) async_read_until(AsyncReadStream& s, ASIO_MOVE_ARG(DynamicBuffer_v1) buffers,- MatchCondition match_condition, ASIO_MOVE_ARG(ReadHandler) handler,- typename enable_if<+ MatchCondition match_condition, ASIO_MOVE_ARG(ReadToken) token,+ typename constraint< is_match_condition<MatchCondition>::value- && is_dynamic_buffer_v1<typename decay<DynamicBuffer_v1>::type>::value- && !is_dynamic_buffer_v2<typename decay<DynamicBuffer_v1>::type>::value- >::type*)+ >::type,+ typename constraint<+ is_dynamic_buffer_v1<typename decay<DynamicBuffer_v1>::type>::value+ >::type,+ typename constraint<+ !is_dynamic_buffer_v2<typename decay<DynamicBuffer_v1>::type>::value+ >::type)+ ASIO_INITFN_AUTO_RESULT_TYPE_SUFFIX((+ async_initiate<ReadToken,+ void (asio::error_code, std::size_t)>(+ declval<detail::initiate_async_read_until_match_v1<AsyncReadStream> >(),+ token, ASIO_MOVE_CAST(DynamicBuffer_v1)(buffers),+ match_condition))) {- return async_initiate<ReadHandler,+ return async_initiate<ReadToken, void (asio::error_code, std::size_t)>(- detail::initiate_async_read_until_match_v1<AsyncReadStream>(s), handler,- ASIO_MOVE_CAST(DynamicBuffer_v1)(buffers), match_condition);+ detail::initiate_async_read_until_match_v1<AsyncReadStream>(s),+ token, ASIO_MOVE_CAST(DynamicBuffer_v1)(buffers),+ match_condition); } #if !defined(ASIO_NO_IOSTREAM) template <typename AsyncReadStream, typename Allocator, ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code,- std::size_t)) ReadHandler>-inline ASIO_INITFN_AUTO_RESULT_TYPE(ReadHandler,+ std::size_t)) ReadToken>+inline ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX(ReadToken, void (asio::error_code, std::size_t)) async_read_until(AsyncReadStream& s, asio::basic_streambuf<Allocator>& b,- char delim, ASIO_MOVE_ARG(ReadHandler) handler)+ char delim, ASIO_MOVE_ARG(ReadToken) token)+ ASIO_INITFN_AUTO_RESULT_TYPE_SUFFIX((+ async_read_until(s, basic_streambuf_ref<Allocator>(b),+ delim, ASIO_MOVE_CAST(ReadToken)(token)))) { return async_read_until(s, basic_streambuf_ref<Allocator>(b),- delim, ASIO_MOVE_CAST(ReadHandler)(handler));+ delim, ASIO_MOVE_CAST(ReadToken)(token)); } template <typename AsyncReadStream, typename Allocator, ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code,- std::size_t)) ReadHandler>-inline ASIO_INITFN_AUTO_RESULT_TYPE(ReadHandler,+ std::size_t)) ReadToken>+inline ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX(ReadToken, void (asio::error_code, std::size_t)) async_read_until(AsyncReadStream& s, asio::basic_streambuf<Allocator>& b, ASIO_STRING_VIEW_PARAM delim,- ASIO_MOVE_ARG(ReadHandler) handler)+ ASIO_MOVE_ARG(ReadToken) token)+ ASIO_INITFN_AUTO_RESULT_TYPE_SUFFIX((+ async_read_until(s, basic_streambuf_ref<Allocator>(b),+ delim, ASIO_MOVE_CAST(ReadToken)(token)))) { return async_read_until(s, basic_streambuf_ref<Allocator>(b),- delim, ASIO_MOVE_CAST(ReadHandler)(handler));+ delim, ASIO_MOVE_CAST(ReadToken)(token)); } #if defined(ASIO_HAS_BOOST_REGEX) template <typename AsyncReadStream, typename Allocator, ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code,- std::size_t)) ReadHandler>-inline ASIO_INITFN_AUTO_RESULT_TYPE(ReadHandler,+ std::size_t)) ReadToken>+inline ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX(ReadToken, void (asio::error_code, std::size_t)) async_read_until(AsyncReadStream& s, asio::basic_streambuf<Allocator>& b, const boost::regex& expr,- ASIO_MOVE_ARG(ReadHandler) handler)+ ASIO_MOVE_ARG(ReadToken) token)+ ASIO_INITFN_AUTO_RESULT_TYPE_SUFFIX((+ async_read_until(s, basic_streambuf_ref<Allocator>(b),+ expr, ASIO_MOVE_CAST(ReadToken)(token)))) { return async_read_until(s, basic_streambuf_ref<Allocator>(b),- expr, ASIO_MOVE_CAST(ReadHandler)(handler));+ expr, ASIO_MOVE_CAST(ReadToken)(token)); } #endif // defined(ASIO_HAS_BOOST_REGEX) template <typename AsyncReadStream, typename Allocator, typename MatchCondition, ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code,- std::size_t)) ReadHandler>-inline ASIO_INITFN_AUTO_RESULT_TYPE(ReadHandler,+ std::size_t)) ReadToken>+inline ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX(ReadToken, void (asio::error_code, std::size_t)) async_read_until(AsyncReadStream& s, asio::basic_streambuf<Allocator>& b,- MatchCondition match_condition, ASIO_MOVE_ARG(ReadHandler) handler,- typename enable_if<is_match_condition<MatchCondition>::value>::type*)+ MatchCondition match_condition, ASIO_MOVE_ARG(ReadToken) token,+ typename constraint<is_match_condition<MatchCondition>::value>::type)+ ASIO_INITFN_AUTO_RESULT_TYPE_SUFFIX((+ async_read_until(s, basic_streambuf_ref<Allocator>(b),+ match_condition, ASIO_MOVE_CAST(ReadToken)(token)))) { return async_read_until(s, basic_streambuf_ref<Allocator>(b),- match_condition, ASIO_MOVE_CAST(ReadHandler)(handler));+ match_condition, ASIO_MOVE_CAST(ReadToken)(token)); } #endif // !defined(ASIO_NO_IOSTREAM)@@ -2076,13 +2158,16 @@ template <typename AsyncReadStream, typename DynamicBuffer_v2, typename ReadHandler> class read_until_delim_op_v2+ : public base_from_cancellation_state<ReadHandler> { public: template <typename BufferSequence> read_until_delim_op_v2(AsyncReadStream& stream, ASIO_MOVE_ARG(BufferSequence) buffers, char delim, ReadHandler& handler)- : stream_(stream),+ : base_from_cancellation_state<ReadHandler>(+ handler, enable_partial_cancellation()),+ stream_(stream), buffers_(ASIO_MOVE_CAST(BufferSequence)(buffers)), delim_(delim), start_(0),@@ -2094,7 +2179,8 @@ #if defined(ASIO_HAS_MOVE) read_until_delim_op_v2(const read_until_delim_op_v2& other)- : stream_(other.stream_),+ : base_from_cancellation_state<ReadHandler>(other),+ stream_(other.stream_), buffers_(other.buffers_), delim_(other.delim_), start_(other.start_),@@ -2105,7 +2191,10 @@ } read_until_delim_op_v2(read_until_delim_op_v2&& other)- : stream_(other.stream_),+ : base_from_cancellation_state<ReadHandler>(+ ASIO_MOVE_CAST(base_from_cancellation_state<+ ReadHandler>)(other)),+ stream_(other.stream_), buffers_(ASIO_MOVE_CAST(DynamicBuffer_v2)(other.buffers_)), delim_(other.delim_), start_(other.start_),@@ -2116,7 +2205,7 @@ } #endif // defined(ASIO_HAS_MOVE) - void operator()(const asio::error_code& ec,+ void operator()(asio::error_code ec, std::size_t bytes_transferred, int start = 0) { const std::size_t not_found = (std::numeric_limits<std::size_t>::max)();@@ -2184,6 +2273,11 @@ buffers_.shrink(bytes_to_read_ - bytes_transferred); if (ec || bytes_transferred == 0) break;+ if (this->cancelled() != cancellation_type::none)+ {+ ec = error::operation_aborted;+ break;+ } } const asio::error_code result_ec =@@ -2194,7 +2288,7 @@ (ec || search_position_ == not_found) ? 0 : search_position_; - handler_(result_ec, result_n);+ ASIO_MOVE_OR_LVALUE(ReadHandler)(handler_)(result_ec, result_n); } } @@ -2316,40 +2410,31 @@ #if !defined(GENERATING_DOCUMENTATION) -template <typename AsyncReadStream, typename DynamicBuffer_v2,- typename ReadHandler, typename Allocator>-struct associated_allocator<+template <template <typename, typename> class Associator,+ typename AsyncReadStream, typename DynamicBuffer_v2,+ typename ReadHandler, typename DefaultCandidate>+struct associator<Associator, detail::read_until_delim_op_v2<AsyncReadStream, DynamicBuffer_v2, ReadHandler>,- Allocator>+ DefaultCandidate>+ : Associator<ReadHandler, DefaultCandidate> {- typedef typename associated_allocator<ReadHandler, Allocator>::type type;-- static type get(- const detail::read_until_delim_op_v2<AsyncReadStream,- DynamicBuffer_v2, ReadHandler>& h,- const Allocator& a = Allocator()) ASIO_NOEXCEPT+ static typename Associator<ReadHandler, DefaultCandidate>::type+ get(const detail::read_until_delim_op_v2<AsyncReadStream,+ DynamicBuffer_v2, ReadHandler>& h) ASIO_NOEXCEPT {- return associated_allocator<ReadHandler, Allocator>::get(h.handler_, a);+ return Associator<ReadHandler, DefaultCandidate>::get(h.handler_); }-}; -template <typename AsyncReadStream, typename DynamicBuffer_v2,- typename ReadHandler, typename Executor>-struct associated_executor<- detail::read_until_delim_op_v2<AsyncReadStream,- DynamicBuffer_v2, ReadHandler>,- Executor>- : detail::associated_executor_forwarding_base<ReadHandler, Executor>-{- typedef typename associated_executor<ReadHandler, Executor>::type type;-- static type get(- const detail::read_until_delim_op_v2<AsyncReadStream,+ static ASIO_AUTO_RETURN_TYPE_PREFIX2(+ typename Associator<ReadHandler, DefaultCandidate>::type)+ get(const detail::read_until_delim_op_v2<AsyncReadStream, DynamicBuffer_v2, ReadHandler>& h,- const Executor& ex = Executor()) ASIO_NOEXCEPT+ const DefaultCandidate& c) ASIO_NOEXCEPT+ ASIO_AUTO_RETURN_TYPE_SUFFIX((+ Associator<ReadHandler, DefaultCandidate>::get(h.handler_, c))) {- return associated_executor<ReadHandler, Executor>::get(h.handler_, ex);+ return Associator<ReadHandler, DefaultCandidate>::get(h.handler_, c); } }; @@ -2357,19 +2442,24 @@ template <typename AsyncReadStream, typename DynamicBuffer_v2, ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code,- std::size_t)) ReadHandler>-ASIO_INITFN_AUTO_RESULT_TYPE(ReadHandler,+ std::size_t)) ReadToken>+ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX(ReadToken, void (asio::error_code, std::size_t)) async_read_until(AsyncReadStream& s, DynamicBuffer_v2 buffers,- char delim, ASIO_MOVE_ARG(ReadHandler) handler,- typename enable_if<+ char delim, ASIO_MOVE_ARG(ReadToken) token,+ typename constraint< is_dynamic_buffer_v2<DynamicBuffer_v2>::value- >::type*)+ >::type)+ ASIO_INITFN_AUTO_RESULT_TYPE_SUFFIX((+ async_initiate<ReadToken,+ void (asio::error_code, std::size_t)>(+ declval<detail::initiate_async_read_until_delim_v2<AsyncReadStream> >(),+ token, ASIO_MOVE_CAST(DynamicBuffer_v2)(buffers), delim))) {- return async_initiate<ReadHandler,+ return async_initiate<ReadToken, void (asio::error_code, std::size_t)>( detail::initiate_async_read_until_delim_v2<AsyncReadStream>(s),- handler, ASIO_MOVE_CAST(DynamicBuffer_v2)(buffers), delim);+ token, ASIO_MOVE_CAST(DynamicBuffer_v2)(buffers), delim); } namespace detail@@ -2377,13 +2467,16 @@ template <typename AsyncReadStream, typename DynamicBuffer_v2, typename ReadHandler> class read_until_delim_string_op_v2+ : public base_from_cancellation_state<ReadHandler> { public: template <typename BufferSequence> read_until_delim_string_op_v2(AsyncReadStream& stream, ASIO_MOVE_ARG(BufferSequence) buffers, const std::string& delim, ReadHandler& handler)- : stream_(stream),+ : base_from_cancellation_state<ReadHandler>(+ handler, enable_partial_cancellation()),+ stream_(stream), buffers_(ASIO_MOVE_CAST(BufferSequence)(buffers)), delim_(delim), start_(0),@@ -2395,7 +2488,8 @@ #if defined(ASIO_HAS_MOVE) read_until_delim_string_op_v2(const read_until_delim_string_op_v2& other)- : stream_(other.stream_),+ : base_from_cancellation_state<ReadHandler>(other),+ stream_(other.stream_), buffers_(other.buffers_), delim_(other.delim_), start_(other.start_),@@ -2406,7 +2500,10 @@ } read_until_delim_string_op_v2(read_until_delim_string_op_v2&& other)- : stream_(other.stream_),+ : base_from_cancellation_state<ReadHandler>(+ ASIO_MOVE_CAST(base_from_cancellation_state<+ ReadHandler>)(other)),+ stream_(other.stream_), buffers_(ASIO_MOVE_CAST(DynamicBuffer_v2)(other.buffers_)), delim_(ASIO_MOVE_CAST(std::string)(other.delim_)), start_(other.start_),@@ -2417,7 +2514,7 @@ } #endif // defined(ASIO_HAS_MOVE) - void operator()(const asio::error_code& ec,+ void operator()(asio::error_code ec, std::size_t bytes_transferred, int start = 0) { const std::size_t not_found = (std::numeric_limits<std::size_t>::max)();@@ -2496,6 +2593,11 @@ buffers_.shrink(bytes_to_read_ - bytes_transferred); if (ec || bytes_transferred == 0) break;+ if (this->cancelled() != cancellation_type::none)+ {+ ec = error::operation_aborted;+ break;+ } } const asio::error_code result_ec =@@ -2506,7 +2608,7 @@ (ec || search_position_ == not_found) ? 0 : search_position_; - handler_(result_ec, result_n);+ ASIO_MOVE_OR_LVALUE(ReadHandler)(handler_)(result_ec, result_n); } } @@ -2629,40 +2731,31 @@ #if !defined(GENERATING_DOCUMENTATION) -template <typename AsyncReadStream, typename DynamicBuffer_v2,- typename ReadHandler, typename Allocator>-struct associated_allocator<+template <template <typename, typename> class Associator,+ typename AsyncReadStream, typename DynamicBuffer_v2,+ typename ReadHandler, typename DefaultCandidate>+struct associator<Associator, detail::read_until_delim_string_op_v2<AsyncReadStream, DynamicBuffer_v2, ReadHandler>,- Allocator>+ DefaultCandidate>+ : Associator<ReadHandler, DefaultCandidate> {- typedef typename associated_allocator<ReadHandler, Allocator>::type type;-- static type get(- const detail::read_until_delim_string_op_v2<AsyncReadStream,- DynamicBuffer_v2, ReadHandler>& h,- const Allocator& a = Allocator()) ASIO_NOEXCEPT+ static typename Associator<ReadHandler, DefaultCandidate>::type+ get(const detail::read_until_delim_string_op_v2<AsyncReadStream,+ DynamicBuffer_v2, ReadHandler>& h) ASIO_NOEXCEPT {- return associated_allocator<ReadHandler, Allocator>::get(h.handler_, a);+ return Associator<ReadHandler, DefaultCandidate>::get(h.handler_); }-}; -template <typename AsyncReadStream, typename DynamicBuffer_v2,- typename ReadHandler, typename Executor>-struct associated_executor<- detail::read_until_delim_string_op_v2<AsyncReadStream,- DynamicBuffer_v2, ReadHandler>,- Executor>- : detail::associated_executor_forwarding_base<ReadHandler, Executor>-{- typedef typename associated_executor<ReadHandler, Executor>::type type;-- static type get(- const detail::read_until_delim_string_op_v2<AsyncReadStream,+ static ASIO_AUTO_RETURN_TYPE_PREFIX2(+ typename Associator<ReadHandler, DefaultCandidate>::type)+ get(const detail::read_until_delim_string_op_v2<AsyncReadStream, DynamicBuffer_v2, ReadHandler>& h,- const Executor& ex = Executor()) ASIO_NOEXCEPT+ const DefaultCandidate& c) ASIO_NOEXCEPT+ ASIO_AUTO_RETURN_TYPE_SUFFIX((+ Associator<ReadHandler, DefaultCandidate>::get(h.handler_, c))) {- return associated_executor<ReadHandler, Executor>::get(h.handler_, ex);+ return Associator<ReadHandler, DefaultCandidate>::get(h.handler_, c); } }; @@ -2671,20 +2764,27 @@ template <typename AsyncReadStream, typename DynamicBuffer_v2, ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code,- std::size_t)) ReadHandler>-ASIO_INITFN_AUTO_RESULT_TYPE(ReadHandler,+ std::size_t)) ReadToken>+ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX(ReadToken, void (asio::error_code, std::size_t)) async_read_until(AsyncReadStream& s, DynamicBuffer_v2 buffers, ASIO_STRING_VIEW_PARAM delim,- ASIO_MOVE_ARG(ReadHandler) handler,- typename enable_if<+ ASIO_MOVE_ARG(ReadToken) token,+ typename constraint< is_dynamic_buffer_v2<DynamicBuffer_v2>::value- >::type*)+ >::type)+ ASIO_INITFN_AUTO_RESULT_TYPE_SUFFIX((+ async_initiate<ReadToken,+ void (asio::error_code, std::size_t)>(+ declval<detail::initiate_async_read_until_delim_string_v2<+ AsyncReadStream> >(),+ token, ASIO_MOVE_CAST(DynamicBuffer_v2)(buffers),+ static_cast<std::string>(delim)))) {- return async_initiate<ReadHandler,+ return async_initiate<ReadToken, void (asio::error_code, std::size_t)>( detail::initiate_async_read_until_delim_string_v2<AsyncReadStream>(s),- handler, ASIO_MOVE_CAST(DynamicBuffer_v2)(buffers),+ token, ASIO_MOVE_CAST(DynamicBuffer_v2)(buffers), static_cast<std::string>(delim)); } @@ -2696,13 +2796,16 @@ template <typename AsyncReadStream, typename DynamicBuffer_v2, typename RegEx, typename ReadHandler> class read_until_expr_op_v2+ : public base_from_cancellation_state<ReadHandler> { public: template <typename BufferSequence> read_until_expr_op_v2(AsyncReadStream& stream, ASIO_MOVE_ARG(BufferSequence) buffers, const boost::regex& expr, ReadHandler& handler)- : stream_(stream),+ : base_from_cancellation_state<ReadHandler>(+ handler, enable_partial_cancellation()),+ stream_(stream), buffers_(ASIO_MOVE_CAST(BufferSequence)(buffers)), expr_(expr), start_(0),@@ -2714,7 +2817,8 @@ #if defined(ASIO_HAS_MOVE) read_until_expr_op_v2(const read_until_expr_op_v2& other)- : stream_(other.stream_),+ : base_from_cancellation_state<ReadHandler>(other),+ stream_(other.stream_), buffers_(other.buffers_), expr_(other.expr_), start_(other.start_),@@ -2725,7 +2829,10 @@ } read_until_expr_op_v2(read_until_expr_op_v2&& other)- : stream_(other.stream_),+ : base_from_cancellation_state<ReadHandler>(+ ASIO_MOVE_CAST(base_from_cancellation_state<+ ReadHandler>)(other)),+ stream_(other.stream_), buffers_(ASIO_MOVE_CAST(DynamicBuffer_v2)(other.buffers_)), expr_(other.expr_), start_(other.start_),@@ -2736,7 +2843,7 @@ } #endif // defined(ASIO_HAS_MOVE) - void operator()(const asio::error_code& ec,+ void operator()(asio::error_code ec, std::size_t bytes_transferred, int start = 0) { const std::size_t not_found = (std::numeric_limits<std::size_t>::max)();@@ -2818,6 +2925,11 @@ buffers_.shrink(bytes_to_read_ - bytes_transferred); if (ec || bytes_transferred == 0) break;+ if (this->cancelled() != cancellation_type::none)+ {+ ec = error::operation_aborted;+ break;+ } } const asio::error_code result_ec =@@ -2828,7 +2940,7 @@ (ec || search_position_ == not_found) ? 0 : search_position_; - handler_(result_ec, result_n);+ ASIO_MOVE_OR_LVALUE(ReadHandler)(handler_)(result_ec, result_n); } } @@ -2951,40 +3063,31 @@ #if !defined(GENERATING_DOCUMENTATION) -template <typename AsyncReadStream, typename DynamicBuffer_v2,- typename RegEx, typename ReadHandler, typename Allocator>-struct associated_allocator<+template <template <typename, typename> class Associator,+ typename AsyncReadStream, typename DynamicBuffer_v2,+ typename RegEx, typename ReadHandler, typename DefaultCandidate>+struct associator<Associator, detail::read_until_expr_op_v2<AsyncReadStream, DynamicBuffer_v2, RegEx, ReadHandler>,- Allocator>+ DefaultCandidate>+ : Associator<ReadHandler, DefaultCandidate> {- typedef typename associated_allocator<ReadHandler, Allocator>::type type;-- static type get(- const detail::read_until_expr_op_v2<AsyncReadStream,- DynamicBuffer_v2, RegEx, ReadHandler>& h,- const Allocator& a = Allocator()) ASIO_NOEXCEPT+ static typename Associator<ReadHandler, DefaultCandidate>::type+ get(const detail::read_until_expr_op_v2<AsyncReadStream,+ DynamicBuffer_v2, RegEx, ReadHandler>& h) ASIO_NOEXCEPT {- return associated_allocator<ReadHandler, Allocator>::get(h.handler_, a);+ return Associator<ReadHandler, DefaultCandidate>::get(h.handler_); }-}; -template <typename AsyncReadStream, typename DynamicBuffer_v2,- typename RegEx, typename ReadHandler, typename Executor>-struct associated_executor<- detail::read_until_expr_op_v2<AsyncReadStream,- DynamicBuffer_v2, RegEx, ReadHandler>,- Executor>- : detail::associated_executor_forwarding_base<ReadHandler, Executor>-{- typedef typename associated_executor<ReadHandler, Executor>::type type;-- static type get(- const detail::read_until_expr_op_v2<AsyncReadStream,+ static ASIO_AUTO_RETURN_TYPE_PREFIX2(+ typename Associator<ReadHandler, DefaultCandidate>::type)+ get(const detail::read_until_expr_op_v2<AsyncReadStream, DynamicBuffer_v2, RegEx, ReadHandler>& h,- const Executor& ex = Executor()) ASIO_NOEXCEPT+ const DefaultCandidate& c) ASIO_NOEXCEPT+ ASIO_AUTO_RETURN_TYPE_SUFFIX((+ Associator<ReadHandler, DefaultCandidate>::get(h.handler_, c))) {- return associated_executor<ReadHandler, Executor>::get(h.handler_, ex);+ return Associator<ReadHandler, DefaultCandidate>::get(h.handler_, c); } }; @@ -2992,19 +3095,24 @@ template <typename AsyncReadStream, typename DynamicBuffer_v2, ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code,- std::size_t)) ReadHandler>-ASIO_INITFN_AUTO_RESULT_TYPE(ReadHandler,+ std::size_t)) ReadToken>+ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX(ReadToken, void (asio::error_code, std::size_t)) async_read_until(AsyncReadStream& s, DynamicBuffer_v2 buffers,- const boost::regex& expr, ASIO_MOVE_ARG(ReadHandler) handler,- typename enable_if<+ const boost::regex& expr, ASIO_MOVE_ARG(ReadToken) token,+ typename constraint< is_dynamic_buffer_v2<DynamicBuffer_v2>::value- >::type*)+ >::type)+ ASIO_INITFN_AUTO_RESULT_TYPE_SUFFIX((+ async_initiate<ReadToken,+ void (asio::error_code, std::size_t)>(+ declval<detail::initiate_async_read_until_expr_v2<AsyncReadStream> >(),+ token, ASIO_MOVE_CAST(DynamicBuffer_v2)(buffers), expr))) {- return async_initiate<ReadHandler,+ return async_initiate<ReadToken, void (asio::error_code, std::size_t)>( detail::initiate_async_read_until_expr_v2<AsyncReadStream>(s),- handler, ASIO_MOVE_CAST(DynamicBuffer_v2)(buffers), expr);+ token, ASIO_MOVE_CAST(DynamicBuffer_v2)(buffers), expr); } #endif // defined(ASIO_HAS_BOOST_REGEX)@@ -3014,13 +3122,16 @@ template <typename AsyncReadStream, typename DynamicBuffer_v2, typename MatchCondition, typename ReadHandler> class read_until_match_op_v2+ : public base_from_cancellation_state<ReadHandler> { public: template <typename BufferSequence> read_until_match_op_v2(AsyncReadStream& stream, ASIO_MOVE_ARG(BufferSequence) buffers, MatchCondition match_condition, ReadHandler& handler)- : stream_(stream),+ : base_from_cancellation_state<ReadHandler>(+ handler, enable_partial_cancellation()),+ stream_(stream), buffers_(ASIO_MOVE_CAST(BufferSequence)(buffers)), match_condition_(match_condition), start_(0),@@ -3032,7 +3143,8 @@ #if defined(ASIO_HAS_MOVE) read_until_match_op_v2(const read_until_match_op_v2& other)- : stream_(other.stream_),+ : base_from_cancellation_state<ReadHandler>(other),+ stream_(other.stream_), buffers_(other.buffers_), match_condition_(other.match_condition_), start_(other.start_),@@ -3043,7 +3155,10 @@ } read_until_match_op_v2(read_until_match_op_v2&& other)- : stream_(other.stream_),+ : base_from_cancellation_state<ReadHandler>(+ ASIO_MOVE_CAST(base_from_cancellation_state<+ ReadHandler>)(other)),+ stream_(other.stream_), buffers_(ASIO_MOVE_CAST(DynamicBuffer_v2)(other.buffers_)), match_condition_(other.match_condition_), start_(other.start_),@@ -3054,7 +3169,7 @@ } #endif // defined(ASIO_HAS_MOVE) - void operator()(const asio::error_code& ec,+ void operator()(asio::error_code ec, std::size_t bytes_transferred, int start = 0) { const std::size_t not_found = (std::numeric_limits<std::size_t>::max)();@@ -3132,6 +3247,11 @@ buffers_.shrink(bytes_to_read_ - bytes_transferred); if (ec || bytes_transferred == 0) break;+ if (this->cancelled() != cancellation_type::none)+ {+ ec = error::operation_aborted;+ break;+ } } const asio::error_code result_ec =@@ -3142,7 +3262,7 @@ (ec || search_position_ == not_found) ? 0 : search_position_; - handler_(result_ec, result_n);+ ASIO_MOVE_OR_LVALUE(ReadHandler)(handler_)(result_ec, result_n); } } @@ -3268,40 +3388,31 @@ #if !defined(GENERATING_DOCUMENTATION) -template <typename AsyncReadStream, typename DynamicBuffer_v2,- typename MatchCondition, typename ReadHandler, typename Allocator>-struct associated_allocator<+template <template <typename, typename> class Associator,+ typename AsyncReadStream, typename DynamicBuffer_v2,+ typename MatchCondition, typename ReadHandler, typename DefaultCandidate>+struct associator<Associator, detail::read_until_match_op_v2<AsyncReadStream, DynamicBuffer_v2, MatchCondition, ReadHandler>,- Allocator>+ DefaultCandidate>+ : Associator<ReadHandler, DefaultCandidate> {- typedef typename associated_allocator<ReadHandler, Allocator>::type type;-- static type get(- const detail::read_until_match_op_v2<AsyncReadStream,- DynamicBuffer_v2, MatchCondition, ReadHandler>& h,- const Allocator& a = Allocator()) ASIO_NOEXCEPT+ static typename Associator<ReadHandler, DefaultCandidate>::type+ get(const detail::read_until_match_op_v2<AsyncReadStream,+ DynamicBuffer_v2, MatchCondition, ReadHandler>& h) ASIO_NOEXCEPT {- return associated_allocator<ReadHandler, Allocator>::get(h.handler_, a);+ return Associator<ReadHandler, DefaultCandidate>::get(h.handler_); }-}; -template <typename AsyncReadStream, typename DynamicBuffer_v2,- typename MatchCondition, typename ReadHandler, typename Executor>-struct associated_executor<- detail::read_until_match_op_v2<AsyncReadStream,- DynamicBuffer_v2, MatchCondition, ReadHandler>,- Executor>- : detail::associated_executor_forwarding_base<ReadHandler, Executor>-{- typedef typename associated_executor<ReadHandler, Executor>::type type;-- static type get(- const detail::read_until_match_op_v2<AsyncReadStream,+ static ASIO_AUTO_RETURN_TYPE_PREFIX2(+ typename Associator<ReadHandler, DefaultCandidate>::type)+ get(const detail::read_until_match_op_v2<AsyncReadStream, DynamicBuffer_v2, MatchCondition, ReadHandler>& h,- const Executor& ex = Executor()) ASIO_NOEXCEPT+ const DefaultCandidate& c) ASIO_NOEXCEPT+ ASIO_AUTO_RETURN_TYPE_SUFFIX((+ Associator<ReadHandler, DefaultCandidate>::get(h.handler_, c))) {- return associated_executor<ReadHandler, Executor>::get(h.handler_, ex);+ return Associator<ReadHandler, DefaultCandidate>::get(h.handler_, c); } }; @@ -3310,20 +3421,29 @@ template <typename AsyncReadStream, typename DynamicBuffer_v2, typename MatchCondition, ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code,- std::size_t)) ReadHandler>-ASIO_INITFN_AUTO_RESULT_TYPE(ReadHandler,+ std::size_t)) ReadToken>+ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX(ReadToken, void (asio::error_code, std::size_t)) async_read_until(AsyncReadStream& s, DynamicBuffer_v2 buffers,- MatchCondition match_condition, ASIO_MOVE_ARG(ReadHandler) handler,- typename enable_if<+ MatchCondition match_condition, ASIO_MOVE_ARG(ReadToken) token,+ typename constraint< is_match_condition<MatchCondition>::value- && is_dynamic_buffer_v2<DynamicBuffer_v2>::value- >::type*)+ >::type,+ typename constraint<+ is_dynamic_buffer_v2<DynamicBuffer_v2>::value+ >::type)+ ASIO_INITFN_AUTO_RESULT_TYPE_SUFFIX((+ async_initiate<ReadToken,+ void (asio::error_code, std::size_t)>(+ declval<detail::initiate_async_read_until_match_v2<AsyncReadStream> >(),+ token, ASIO_MOVE_CAST(DynamicBuffer_v2)(buffers),+ match_condition))) {- return async_initiate<ReadHandler,+ return async_initiate<ReadToken, void (asio::error_code, std::size_t)>(- detail::initiate_async_read_until_match_v2<AsyncReadStream>(s), handler,- ASIO_MOVE_CAST(DynamicBuffer_v2)(buffers), match_condition);+ detail::initiate_async_read_until_match_v2<AsyncReadStream>(s),+ token, ASIO_MOVE_CAST(DynamicBuffer_v2)(buffers),+ match_condition); } #endif // !defined(ASIO_NO_EXTENSIONS)
link/modules/asio-standalone/asio/include/asio/impl/redirect_error.hpp view
@@ -2,7 +2,7 @@ // impl/redirect_error.hpp // ~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -16,8 +16,7 @@ #endif // defined(_MSC_VER) && (_MSC_VER >= 1200) #include "asio/detail/config.hpp"-#include "asio/associated_executor.hpp"-#include "asio/associated_allocator.hpp"+#include "asio/associator.hpp" #include "asio/async_result.hpp" #include "asio/detail/handler_alloc_helpers.hpp" #include "asio/detail/handler_cont_helpers.hpp"@@ -55,7 +54,7 @@ void operator()() {- handler_();+ ASIO_MOVE_OR_LVALUE(Handler)(handler_)(); } #if defined(ASIO_HAS_VARIADIC_TEMPLATES)@@ -66,7 +65,8 @@ >::type operator()(ASIO_MOVE_ARG(Arg) arg, ASIO_MOVE_ARG(Args)... args) {- handler_(ASIO_MOVE_CAST(Arg)(arg),+ ASIO_MOVE_OR_LVALUE(Handler)(handler_)(+ ASIO_MOVE_CAST(Arg)(arg), ASIO_MOVE_CAST(Args)(args)...); } @@ -75,7 +75,8 @@ ASIO_MOVE_ARG(Args)... args) { ec_ = ec;- handler_(ASIO_MOVE_CAST(Args)(args)...);+ ASIO_MOVE_OR_LVALUE(Handler)(handler_)(+ ASIO_MOVE_CAST(Args)(args)...); } #else // defined(ASIO_HAS_VARIADIC_TEMPLATES)@@ -86,13 +87,14 @@ >::type operator()(ASIO_MOVE_ARG(Arg) arg) {- handler_(ASIO_MOVE_CAST(Arg)(arg));+ ASIO_MOVE_OR_LVALUE(Handler)(handler_)(+ ASIO_MOVE_CAST(Arg)(arg)); } void operator()(const asio::error_code& ec) { ec_ = ec;- handler_();+ ASIO_MOVE_OR_LVALUE(Handler)(handler_)(); } #define ASIO_PRIVATE_REDIRECT_ERROR_DEF(n) \@@ -102,7 +104,8 @@ >::type \ operator()(ASIO_MOVE_ARG(Arg) arg, ASIO_VARIADIC_MOVE_PARAMS(n)) \ { \- handler_(ASIO_MOVE_CAST(Arg)(arg), \+ ASIO_MOVE_OR_LVALUE(Handler)(handler_)( \+ ASIO_MOVE_CAST(Arg)(arg), \ ASIO_VARIADIC_MOVE_ARGS(n)); \ } \ \@@ -111,7 +114,8 @@ ASIO_VARIADIC_MOVE_PARAMS(n)) \ { \ ec_ = ec; \- handler_(ASIO_VARIADIC_MOVE_ARGS(n)); \+ ASIO_MOVE_OR_LVALUE(Handler)(handler_)( \+ ASIO_VARIADIC_MOVE_ARGS(n)); \ } \ /**/ ASIO_VARIADIC_GENERATE(ASIO_PRIVATE_REDIRECT_ERROR_DEF)@@ -202,6 +206,78 @@ typedef R type(Args...); }; +# if defined(ASIO_HAS_REF_QUALIFIED_FUNCTIONS)++template <typename R, typename... Args>+struct redirect_error_signature<R(asio::error_code, Args...) &>+{+ typedef R type(Args...) &;+};++template <typename R, typename... Args>+struct redirect_error_signature<R(const asio::error_code&, Args...) &>+{+ typedef R type(Args...) &;+};++template <typename R, typename... Args>+struct redirect_error_signature<R(asio::error_code, Args...) &&>+{+ typedef R type(Args...) &&;+};++template <typename R, typename... Args>+struct redirect_error_signature<R(const asio::error_code&, Args...) &&>+{+ typedef R type(Args...) &&;+};++# if defined(ASIO_HAS_NOEXCEPT_FUNCTION_TYPE)++template <typename R, typename... Args>+struct redirect_error_signature<+ R(asio::error_code, Args...) noexcept>+{+ typedef R type(Args...) & noexcept;+};++template <typename R, typename... Args>+struct redirect_error_signature<+ R(const asio::error_code&, Args...) noexcept>+{+ typedef R type(Args...) & noexcept;+};++template <typename R, typename... Args>+struct redirect_error_signature<+ R(asio::error_code, Args...) & noexcept>+{+ typedef R type(Args...) & noexcept;+};++template <typename R, typename... Args>+struct redirect_error_signature<+ R(const asio::error_code&, Args...) & noexcept>+{+ typedef R type(Args...) & noexcept;+};++template <typename R, typename... Args>+struct redirect_error_signature<+ R(asio::error_code, Args...) && noexcept>+{+ typedef R type(Args...) && noexcept;+};++template <typename R, typename... Args>+struct redirect_error_signature<+ R(const asio::error_code&, Args...) && noexcept>+{+ typedef R type(Args...) && noexcept;+};++# endif // defined(ASIO_HAS_NOEXCEPT_FUNCTION_TYPE)+# endif // defined(ASIO_HAS_REF_QUALIFIED_FUNCTIONS) #else // defined(ASIO_HAS_VARIADIC_TEMPLATES) template <typename R>@@ -234,6 +310,161 @@ ASIO_VARIADIC_GENERATE(ASIO_PRIVATE_REDIRECT_ERROR_DEF) #undef ASIO_PRIVATE_REDIRECT_ERROR_DEF +# if defined(ASIO_HAS_REF_QUALIFIED_FUNCTIONS)++template <typename R>+struct redirect_error_signature<R(asio::error_code) &>+{+ typedef R type() &;+};++template <typename R>+struct redirect_error_signature<R(const asio::error_code&) &>+{+ typedef R type() &;+};++template <typename R>+struct redirect_error_signature<R(asio::error_code) &&>+{+ typedef R type() &&;+};++template <typename R>+struct redirect_error_signature<R(const asio::error_code&) &&>+{+ typedef R type() &&;+};++#define ASIO_PRIVATE_REDIRECT_ERROR_DEF(n) \+ template <typename R, ASIO_VARIADIC_TPARAMS(n)> \+ struct redirect_error_signature< \+ R(asio::error_code, ASIO_VARIADIC_TARGS(n)) &> \+ { \+ typedef R type(ASIO_VARIADIC_TARGS(n)) &; \+ }; \+ \+ template <typename R, ASIO_VARIADIC_TPARAMS(n)> \+ struct redirect_error_signature< \+ R(const asio::error_code&, ASIO_VARIADIC_TARGS(n)) &> \+ { \+ typedef R type(ASIO_VARIADIC_TARGS(n)) &; \+ }; \+ \+ template <typename R, ASIO_VARIADIC_TPARAMS(n)> \+ struct redirect_error_signature< \+ R(asio::error_code, ASIO_VARIADIC_TARGS(n)) &&> \+ { \+ typedef R type(ASIO_VARIADIC_TARGS(n)) &&; \+ }; \+ \+ template <typename R, ASIO_VARIADIC_TPARAMS(n)> \+ struct redirect_error_signature< \+ R(const asio::error_code&, ASIO_VARIADIC_TARGS(n)) &&> \+ { \+ typedef R type(ASIO_VARIADIC_TARGS(n)) &&; \+ }; \+ /**/+ ASIO_VARIADIC_GENERATE(ASIO_PRIVATE_REDIRECT_ERROR_DEF)+#undef ASIO_PRIVATE_REDIRECT_ERROR_DEF++# if defined(ASIO_HAS_NOEXCEPT_FUNCTION_TYPE)++template <typename R>+struct redirect_error_signature<+ R(asio::error_code) noexcept>+{+ typedef R type() noexcept;+};++template <typename R>+struct redirect_error_signature<+ R(const asio::error_code&) noexcept>+{+ typedef R type() noexcept;+};++template <typename R>+struct redirect_error_signature<+ R(asio::error_code) & noexcept>+{+ typedef R type() & noexcept;+};++template <typename R>+struct redirect_error_signature<+ R(const asio::error_code&) & noexcept>+{+ typedef R type() & noexcept;+};++template <typename R>+struct redirect_error_signature<+ R(asio::error_code) && noexcept>+{+ typedef R type() && noexcept;+};++template <typename R>+struct redirect_error_signature<+ R(const asio::error_code&) && noexcept>+{+ typedef R type() && noexcept;+};++#define ASIO_PRIVATE_REDIRECT_ERROR_DEF(n) \+ template <typename R, ASIO_VARIADIC_TPARAMS(n)> \+ struct redirect_error_signature< \+ R(asio::error_code, ASIO_VARIADIC_TARGS(n)) noexcept> \+ { \+ typedef R type(ASIO_VARIADIC_TARGS(n)) noexcept; \+ }; \+ \+ template <typename R, ASIO_VARIADIC_TPARAMS(n)> \+ struct redirect_error_signature< \+ R(const asio::error_code&, \+ ASIO_VARIADIC_TARGS(n)) noexcept> \+ { \+ typedef R type(ASIO_VARIADIC_TARGS(n)) noexcept; \+ }; \+ \+ template <typename R, ASIO_VARIADIC_TPARAMS(n)> \+ struct redirect_error_signature< \+ R(asio::error_code, \+ ASIO_VARIADIC_TARGS(n)) & noexcept> \+ { \+ typedef R type(ASIO_VARIADIC_TARGS(n)) & noexcept; \+ }; \+ \+ template <typename R, ASIO_VARIADIC_TPARAMS(n)> \+ struct redirect_error_signature< \+ R(const asio::error_code&, \+ ASIO_VARIADIC_TARGS(n)) & noexcept> \+ { \+ typedef R type(ASIO_VARIADIC_TARGS(n)) & noexcept; \+ }; \+ \+ template <typename R, ASIO_VARIADIC_TPARAMS(n)> \+ struct redirect_error_signature< \+ R(asio::error_code, \+ ASIO_VARIADIC_TARGS(n)) && noexcept> \+ { \+ typedef R type(ASIO_VARIADIC_TARGS(n)) && noexcept; \+ }; \+ \+ template <typename R, ASIO_VARIADIC_TPARAMS(n)> \+ struct redirect_error_signature< \+ R(const asio::error_code&, \+ ASIO_VARIADIC_TARGS(n)) && noexcept> \+ { \+ typedef R type(ASIO_VARIADIC_TARGS(n)) && noexcept; \+ }; \+ /**/+ ASIO_VARIADIC_GENERATE(ASIO_PRIVATE_REDIRECT_ERROR_DEF)+#undef ASIO_PRIVATE_REDIRECT_ERROR_DEF++# endif // defined(ASIO_HAS_NOEXCEPT_FUNCTION_TYPE)+# endif // defined(ASIO_HAS_REF_QUALIFIED_FUNCTIONS) #endif // defined(ASIO_HAS_VARIADIC_TEMPLATES) } // namespace detail@@ -242,29 +473,26 @@ template <typename CompletionToken, typename Signature> struct async_result<redirect_error_t<CompletionToken>, Signature>+ : async_result<CompletionToken,+ typename detail::redirect_error_signature<Signature>::type> {- typedef typename async_result<CompletionToken,- typename detail::redirect_error_signature<Signature>::type>- ::return_type return_type; - template <typename Initiation> struct init_wrapper {- template <typename Init>- init_wrapper(asio::error_code& ec, ASIO_MOVE_ARG(Init) init)- : ec_(ec),- initiation_(ASIO_MOVE_CAST(Init)(init))+ explicit init_wrapper(asio::error_code& ec)+ : ec_(ec) { } #if defined(ASIO_HAS_VARIADIC_TEMPLATES) - template <typename Handler, typename... Args>+ template <typename Handler, typename Initiation, typename... Args> void operator()( ASIO_MOVE_ARG(Handler) handler,- ASIO_MOVE_ARG(Args)... args)+ ASIO_MOVE_ARG(Initiation) initiation,+ ASIO_MOVE_ARG(Args)... args) const {- ASIO_MOVE_CAST(Initiation)(initiation_)(+ ASIO_MOVE_CAST(Initiation)(initiation)( detail::redirect_error_handler< typename decay<Handler>::type>( ec_, ASIO_MOVE_CAST(Handler)(handler)),@@ -273,23 +501,26 @@ #else // defined(ASIO_HAS_VARIADIC_TEMPLATES) - template <typename Handler>+ template <typename Handler, typename Initiation> void operator()(- ASIO_MOVE_ARG(Handler) handler)+ ASIO_MOVE_ARG(Handler) handler,+ ASIO_MOVE_ARG(Initiation) initiation) const {- ASIO_MOVE_CAST(Initiation)(initiation_)(+ ASIO_MOVE_CAST(Initiation)(initiation)( detail::redirect_error_handler< typename decay<Handler>::type>( ec_, ASIO_MOVE_CAST(Handler)(handler))); } #define ASIO_PRIVATE_INIT_WRAPPER_DEF(n) \- template <typename Handler, ASIO_VARIADIC_TPARAMS(n)> \+ template <typename Handler, typename Initiation, \+ ASIO_VARIADIC_TPARAMS(n)> \ void operator()( \ ASIO_MOVE_ARG(Handler) handler, \- ASIO_VARIADIC_MOVE_PARAMS(n)) \+ ASIO_MOVE_ARG(Initiation) initiation, \+ ASIO_VARIADIC_MOVE_PARAMS(n)) const \ { \- ASIO_MOVE_CAST(Initiation)(initiation_)( \+ ASIO_MOVE_CAST(Initiation)(initiation)( \ detail::redirect_error_handler< \ typename decay<Handler>::type>( \ ec_, ASIO_MOVE_CAST(Handler)(handler)), \@@ -302,51 +533,67 @@ #endif // defined(ASIO_HAS_VARIADIC_TEMPLATES) asio::error_code& ec_;- Initiation initiation_; }; #if defined(ASIO_HAS_VARIADIC_TEMPLATES) template <typename Initiation, typename RawCompletionToken, typename... Args>- static return_type initiate(+ static ASIO_INITFN_DEDUCED_RESULT_TYPE(CompletionToken,+ typename detail::redirect_error_signature<Signature>::type,+ (async_initiate<CompletionToken,+ typename detail::redirect_error_signature<Signature>::type>(+ declval<init_wrapper>(), declval<CompletionToken&>(),+ declval<Initiation>(), declval<ASIO_MOVE_ARG(Args)>()...)))+ initiate( ASIO_MOVE_ARG(Initiation) initiation, ASIO_MOVE_ARG(RawCompletionToken) token, ASIO_MOVE_ARG(Args)... args) { return async_initiate<CompletionToken, typename detail::redirect_error_signature<Signature>::type>(- init_wrapper<typename decay<Initiation>::type>(- token.ec_, ASIO_MOVE_CAST(Initiation)(initiation)),- token.token_, ASIO_MOVE_CAST(Args)(args)...);+ init_wrapper(token.ec_), token.token_,+ ASIO_MOVE_CAST(Initiation)(initiation),+ ASIO_MOVE_CAST(Args)(args)...); } #else // defined(ASIO_HAS_VARIADIC_TEMPLATES) template <typename Initiation, typename RawCompletionToken>- static return_type initiate(+ static ASIO_INITFN_DEDUCED_RESULT_TYPE(CompletionToken,+ typename detail::redirect_error_signature<Signature>::type,+ (async_initiate<CompletionToken,+ typename detail::redirect_error_signature<Signature>::type>(+ declval<init_wrapper>(), declval<CompletionToken&>(),+ declval<Initiation>())))+ initiate( ASIO_MOVE_ARG(Initiation) initiation, ASIO_MOVE_ARG(RawCompletionToken) token) { return async_initiate<CompletionToken, typename detail::redirect_error_signature<Signature>::type>(- init_wrapper<typename decay<Initiation>::type>(- token.ec_, ASIO_MOVE_CAST(Initiation)(initiation)),- token.token_);+ init_wrapper(token.ec_), token.token_,+ ASIO_MOVE_CAST(Initiation)(initiation)); } #define ASIO_PRIVATE_INITIATE_DEF(n) \ template <typename Initiation, typename RawCompletionToken, \ ASIO_VARIADIC_TPARAMS(n)> \- static return_type initiate( \+ static ASIO_INITFN_DEDUCED_RESULT_TYPE(CompletionToken, \+ typename detail::redirect_error_signature<Signature>::type, \+ (async_initiate<CompletionToken, \+ typename detail::redirect_error_signature<Signature>::type>( \+ declval<init_wrapper>(), declval<CompletionToken&>(), \+ declval<Initiation>(), ASIO_VARIADIC_DECLVAL(n)))) \+ initiate( \ ASIO_MOVE_ARG(Initiation) initiation, \ ASIO_MOVE_ARG(RawCompletionToken) token, \ ASIO_VARIADIC_MOVE_PARAMS(n)) \ { \ return async_initiate<CompletionToken, \ typename detail::redirect_error_signature<Signature>::type>( \- init_wrapper<typename decay<Initiation>::type>( \- token.ec_, ASIO_MOVE_CAST(Initiation)(initiation)), \- token.token_, ASIO_VARIADIC_MOVE_ARGS(n)); \+ init_wrapper(token.ec_), token.token_, \+ ASIO_MOVE_CAST(Initiation)(initiation), \+ ASIO_VARIADIC_MOVE_ARGS(n)); \ } \ /**/ ASIO_VARIADIC_GENERATE(ASIO_PRIVATE_INITIATE_DEF)@@ -355,29 +602,26 @@ #endif // defined(ASIO_HAS_VARIADIC_TEMPLATES) }; -template <typename Handler, typename Executor>-struct associated_executor<detail::redirect_error_handler<Handler>, Executor>+template <template <typename, typename> class Associator,+ typename Handler, typename DefaultCandidate>+struct associator<Associator,+ detail::redirect_error_handler<Handler>, DefaultCandidate>+ : Associator<Handler, DefaultCandidate> {- typedef typename associated_executor<Handler, Executor>::type type;-- static type get(- const detail::redirect_error_handler<Handler>& h,- const Executor& ex = Executor()) ASIO_NOEXCEPT+ static typename Associator<Handler, DefaultCandidate>::type+ get(const detail::redirect_error_handler<Handler>& h) ASIO_NOEXCEPT {- return associated_executor<Handler, Executor>::get(h.handler_, ex);+ return Associator<Handler, DefaultCandidate>::get(h.handler_); }-}; -template <typename Handler, typename Allocator>-struct associated_allocator<detail::redirect_error_handler<Handler>, Allocator>-{- typedef typename associated_allocator<Handler, Allocator>::type type;-- static type get(- const detail::redirect_error_handler<Handler>& h,- const Allocator& a = Allocator()) ASIO_NOEXCEPT+ static ASIO_AUTO_RETURN_TYPE_PREFIX2(+ typename Associator<Handler, DefaultCandidate>::type)+ get(const detail::redirect_error_handler<Handler>& h,+ const DefaultCandidate& c) ASIO_NOEXCEPT+ ASIO_AUTO_RETURN_TYPE_SUFFIX((+ Associator<Handler, DefaultCandidate>::get(h.handler_, c))) {- return associated_allocator<Handler, Allocator>::get(h.handler_, a);+ return Associator<Handler, DefaultCandidate>::get(h.handler_, c); } };
link/modules/asio-standalone/asio/include/asio/impl/serial_port_base.hpp view
@@ -2,7 +2,7 @@ // impl/serial_port_base.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // Copyright (c) 2008 Rep Invariant Systems, Inc. (info@repinvariant.com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying
link/modules/asio-standalone/asio/include/asio/impl/serial_port_base.ipp view
@@ -2,7 +2,7 @@ // impl/serial_port_base.ipp // ~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // Copyright (c) 2008 Rep Invariant Systems, Inc. (info@repinvariant.com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying
link/modules/asio-standalone/asio/include/asio/impl/spawn.hpp view
@@ -2,522 +2,1612 @@ // impl/spawn.hpp // ~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)-//-// Distributed under the Boost Software License, Version 1.0. (See accompanying-// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)-//--#ifndef ASIO_IMPL_SPAWN_HPP-#define ASIO_IMPL_SPAWN_HPP--#if defined(_MSC_VER) && (_MSC_VER >= 1200)-# pragma once-#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)--#include "asio/detail/config.hpp"-#include "asio/associated_allocator.hpp"-#include "asio/associated_executor.hpp"-#include "asio/async_result.hpp"-#include "asio/bind_executor.hpp"-#include "asio/detail/atomic_count.hpp"-#include "asio/detail/handler_alloc_helpers.hpp"-#include "asio/detail/handler_cont_helpers.hpp"-#include "asio/detail/handler_invoke_helpers.hpp"-#include "asio/detail/memory.hpp"-#include "asio/detail/noncopyable.hpp"-#include "asio/detail/type_traits.hpp"-#include "asio/system_error.hpp"--#include "asio/detail/push_options.hpp"--namespace asio {-namespace detail {-- template <typename Handler, typename T>- class coro_handler- {- public:- coro_handler(basic_yield_context<Handler> ctx)- : coro_(ctx.coro_.lock()),- ca_(ctx.ca_),- handler_(ctx.handler_),- ready_(0),- ec_(ctx.ec_),- value_(0)- {- }-- void operator()(T value)- {- *ec_ = asio::error_code();- *value_ = ASIO_MOVE_CAST(T)(value);- if (--*ready_ == 0)- (*coro_)();- }-- void operator()(asio::error_code ec, T value)- {- *ec_ = ec;- *value_ = ASIO_MOVE_CAST(T)(value);- if (--*ready_ == 0)- (*coro_)();- }-- //private:- shared_ptr<typename basic_yield_context<Handler>::callee_type> coro_;- typename basic_yield_context<Handler>::caller_type& ca_;- Handler handler_;- atomic_count* ready_;- asio::error_code* ec_;- T* value_;- };-- template <typename Handler>- class coro_handler<Handler, void>- {- public:- coro_handler(basic_yield_context<Handler> ctx)- : coro_(ctx.coro_.lock()),- ca_(ctx.ca_),- handler_(ctx.handler_),- ready_(0),- ec_(ctx.ec_)- {- }-- void operator()()- {- *ec_ = asio::error_code();- if (--*ready_ == 0)- (*coro_)();- }-- void operator()(asio::error_code ec)- {- *ec_ = ec;- if (--*ready_ == 0)- (*coro_)();- }-- //private:- shared_ptr<typename basic_yield_context<Handler>::callee_type> coro_;- typename basic_yield_context<Handler>::caller_type& ca_;- Handler handler_;- atomic_count* ready_;- asio::error_code* ec_;- };-- template <typename Handler, typename T>- inline asio_handler_allocate_is_deprecated- asio_handler_allocate(std::size_t size,- coro_handler<Handler, T>* this_handler)- {-#if defined(ASIO_NO_DEPRECATED)- asio_handler_alloc_helpers::allocate(size, this_handler->handler_);- return asio_handler_allocate_is_no_longer_used();-#else // defined(ASIO_NO_DEPRECATED)- return asio_handler_alloc_helpers::allocate(- size, this_handler->handler_);-#endif // defined(ASIO_NO_DEPRECATED)- }-- template <typename Handler, typename T>- inline asio_handler_deallocate_is_deprecated- asio_handler_deallocate(void* pointer, std::size_t size,- coro_handler<Handler, T>* this_handler)- {- asio_handler_alloc_helpers::deallocate(- pointer, size, this_handler->handler_);-#if defined(ASIO_NO_DEPRECATED)- return asio_handler_deallocate_is_no_longer_used();-#endif // defined(ASIO_NO_DEPRECATED)- }-- template <typename Handler, typename T>- inline bool asio_handler_is_continuation(coro_handler<Handler, T>*)- {- return true;- }-- template <typename Function, typename Handler, typename T>- inline asio_handler_invoke_is_deprecated- asio_handler_invoke(Function& function,- coro_handler<Handler, T>* this_handler)- {- asio_handler_invoke_helpers::invoke(- function, this_handler->handler_);-#if defined(ASIO_NO_DEPRECATED)- return asio_handler_invoke_is_no_longer_used();-#endif // defined(ASIO_NO_DEPRECATED)- }-- template <typename Function, typename Handler, typename T>- inline asio_handler_invoke_is_deprecated- asio_handler_invoke(const Function& function,- coro_handler<Handler, T>* this_handler)- {- asio_handler_invoke_helpers::invoke(- function, this_handler->handler_);-#if defined(ASIO_NO_DEPRECATED)- return asio_handler_invoke_is_no_longer_used();-#endif // defined(ASIO_NO_DEPRECATED)- }-- template <typename Handler, typename T>- class coro_async_result- {- public:- typedef coro_handler<Handler, T> completion_handler_type;- typedef T return_type;-- explicit coro_async_result(completion_handler_type& h)- : handler_(h),- ca_(h.ca_),- ready_(2)- {- h.ready_ = &ready_;- out_ec_ = h.ec_;- if (!out_ec_) h.ec_ = &ec_;- h.value_ = &value_;- }-- return_type get()- {- // Must not hold shared_ptr to coro while suspended.- handler_.coro_.reset();-- if (--ready_ != 0)- ca_();- if (!out_ec_ && ec_) throw asio::system_error(ec_);- return ASIO_MOVE_CAST(return_type)(value_);- }-- private:- completion_handler_type& handler_;- typename basic_yield_context<Handler>::caller_type& ca_;- atomic_count ready_;- asio::error_code* out_ec_;- asio::error_code ec_;- return_type value_;- };-- template <typename Handler>- class coro_async_result<Handler, void>- {- public:- typedef coro_handler<Handler, void> completion_handler_type;- typedef void return_type;-- explicit coro_async_result(completion_handler_type& h)- : handler_(h),- ca_(h.ca_),- ready_(2)- {- h.ready_ = &ready_;- out_ec_ = h.ec_;- if (!out_ec_) h.ec_ = &ec_;- }-- void get()- {- // Must not hold shared_ptr to coro while suspended.- handler_.coro_.reset();-- if (--ready_ != 0)- ca_();- if (!out_ec_ && ec_) throw asio::system_error(ec_);- }-- private:- completion_handler_type& handler_;- typename basic_yield_context<Handler>::caller_type& ca_;- atomic_count ready_;- asio::error_code* out_ec_;- asio::error_code ec_;- };--} // namespace detail--#if !defined(GENERATING_DOCUMENTATION)--template <typename Handler, typename ReturnType>-class async_result<basic_yield_context<Handler>, ReturnType()>- : public detail::coro_async_result<Handler, void>-{-public:- explicit async_result(- typename detail::coro_async_result<Handler,- void>::completion_handler_type& h)- : detail::coro_async_result<Handler, void>(h)- {- }-};--template <typename Handler, typename ReturnType, typename Arg1>-class async_result<basic_yield_context<Handler>, ReturnType(Arg1)>- : public detail::coro_async_result<Handler, typename decay<Arg1>::type>-{-public:- explicit async_result(- typename detail::coro_async_result<Handler,- typename decay<Arg1>::type>::completion_handler_type& h)- : detail::coro_async_result<Handler, typename decay<Arg1>::type>(h)- {- }-};--template <typename Handler, typename ReturnType>-class async_result<basic_yield_context<Handler>,- ReturnType(asio::error_code)>- : public detail::coro_async_result<Handler, void>-{-public:- explicit async_result(- typename detail::coro_async_result<Handler,- void>::completion_handler_type& h)- : detail::coro_async_result<Handler, void>(h)- {- }-};--template <typename Handler, typename ReturnType, typename Arg2>-class async_result<basic_yield_context<Handler>,- ReturnType(asio::error_code, Arg2)>- : public detail::coro_async_result<Handler, typename decay<Arg2>::type>-{-public:- explicit async_result(- typename detail::coro_async_result<Handler,- typename decay<Arg2>::type>::completion_handler_type& h)- : detail::coro_async_result<Handler, typename decay<Arg2>::type>(h)- {- }-};--template <typename Handler, typename T, typename Allocator>-struct associated_allocator<detail::coro_handler<Handler, T>, Allocator>-{- typedef typename associated_allocator<Handler, Allocator>::type type;-- static type get(const detail::coro_handler<Handler, T>& h,- const Allocator& a = Allocator()) ASIO_NOEXCEPT- {- return associated_allocator<Handler, Allocator>::get(h.handler_, a);- }-};--template <typename Handler, typename T, typename Executor>-struct associated_executor<detail::coro_handler<Handler, T>, Executor>-{- typedef typename associated_executor<Handler, Executor>::type type;-- static type get(const detail::coro_handler<Handler, T>& h,- const Executor& ex = Executor()) ASIO_NOEXCEPT- {- return associated_executor<Handler, Executor>::get(h.handler_, ex);- }-};--namespace detail {-- template <typename Handler, typename Function>- struct spawn_data : private noncopyable- {- template <typename Hand, typename Func>- spawn_data(ASIO_MOVE_ARG(Hand) handler,- bool call_handler, ASIO_MOVE_ARG(Func) function)- : handler_(ASIO_MOVE_CAST(Hand)(handler)),- call_handler_(call_handler),- function_(ASIO_MOVE_CAST(Func)(function))- {- }-- weak_ptr<typename basic_yield_context<Handler>::callee_type> coro_;- Handler handler_;- bool call_handler_;- Function function_;- };-- template <typename Handler, typename Function>- struct coro_entry_point- {- void operator()(typename basic_yield_context<Handler>::caller_type& ca)- {- shared_ptr<spawn_data<Handler, Function> > data(data_);-#if !defined(BOOST_COROUTINES_UNIDIRECT) && !defined(BOOST_COROUTINES_V2)- ca(); // Yield until coroutine pointer has been initialised.-#endif // !defined(BOOST_COROUTINES_UNIDIRECT) && !defined(BOOST_COROUTINES_V2)- const basic_yield_context<Handler> yield(- data->coro_, ca, data->handler_);-- (data->function_)(yield);- if (data->call_handler_)- (data->handler_)();- }-- shared_ptr<spawn_data<Handler, Function> > data_;- };-- template <typename Handler, typename Function>- struct spawn_helper- {- typedef typename associated_allocator<Handler>::type allocator_type;-- allocator_type get_allocator() const ASIO_NOEXCEPT- {- return (get_associated_allocator)(data_->handler_);- }-- typedef typename associated_executor<Handler>::type executor_type;-- executor_type get_executor() const ASIO_NOEXCEPT- {- return (get_associated_executor)(data_->handler_);- }-- void operator()()- {- typedef typename basic_yield_context<Handler>::callee_type callee_type;- coro_entry_point<Handler, Function> entry_point = { data_ };- shared_ptr<callee_type> coro(new callee_type(entry_point, attributes_));- data_->coro_ = coro;- (*coro)();- }-- shared_ptr<spawn_data<Handler, Function> > data_;- boost::coroutines::attributes attributes_;- };-- template <typename Function, typename Handler, typename Function1>- inline asio_handler_invoke_is_deprecated- asio_handler_invoke(Function& function,- spawn_helper<Handler, Function1>* this_handler)- {- asio_handler_invoke_helpers::invoke(- function, this_handler->data_->handler_);-#if defined(ASIO_NO_DEPRECATED)- return asio_handler_invoke_is_no_longer_used();-#endif // defined(ASIO_NO_DEPRECATED)- }-- template <typename Function, typename Handler, typename Function1>- inline asio_handler_invoke_is_deprecated- asio_handler_invoke(const Function& function,- spawn_helper<Handler, Function1>* this_handler)- {- asio_handler_invoke_helpers::invoke(- function, this_handler->data_->handler_);-#if defined(ASIO_NO_DEPRECATED)- return asio_handler_invoke_is_no_longer_used();-#endif // defined(ASIO_NO_DEPRECATED)- }-- inline void default_spawn_handler() {}--} // namespace detail--template <typename Function>-inline void spawn(ASIO_MOVE_ARG(Function) function,- const boost::coroutines::attributes& attributes)-{- typedef typename decay<Function>::type function_type;-- typename associated_executor<function_type>::type ex(- (get_associated_executor)(function));-- asio::spawn(ex, ASIO_MOVE_CAST(Function)(function), attributes);-}--template <typename Handler, typename Function>-void spawn(ASIO_MOVE_ARG(Handler) handler,- ASIO_MOVE_ARG(Function) function,- const boost::coroutines::attributes& attributes,- typename enable_if<- !is_executor<typename decay<Handler>::type>::value &&- !execution::is_executor<typename decay<Handler>::type>::value &&- !is_convertible<Handler&, execution_context&>::value>::type*)-{- typedef typename decay<Handler>::type handler_type;- typedef typename decay<Function>::type function_type;-- detail::spawn_helper<handler_type, function_type> helper;- helper.data_.reset(- new detail::spawn_data<handler_type, function_type>(- ASIO_MOVE_CAST(Handler)(handler), true,- ASIO_MOVE_CAST(Function)(function)));- helper.attributes_ = attributes;-- asio::dispatch(helper);-}--template <typename Handler, typename Function>-void spawn(basic_yield_context<Handler> ctx,- ASIO_MOVE_ARG(Function) function,- const boost::coroutines::attributes& attributes)-{- typedef typename decay<Function>::type function_type;-- Handler handler(ctx.handler_); // Explicit copy that might be moved from.-- detail::spawn_helper<Handler, function_type> helper;- helper.data_.reset(- new detail::spawn_data<Handler, function_type>(- ASIO_MOVE_CAST(Handler)(handler), false,- ASIO_MOVE_CAST(Function)(function)));- helper.attributes_ = attributes;-- asio::dispatch(helper);-}--template <typename Function, typename Executor>-inline void spawn(const Executor& ex,- ASIO_MOVE_ARG(Function) function,- const boost::coroutines::attributes& attributes,- typename enable_if<- is_executor<Executor>::value || execution::is_executor<Executor>::value- >::type*)-{- asio::spawn(asio::strand<Executor>(ex),- ASIO_MOVE_CAST(Function)(function), attributes);-}--template <typename Function, typename Executor>-inline void spawn(const strand<Executor>& ex,- ASIO_MOVE_ARG(Function) function,- const boost::coroutines::attributes& attributes)-{- asio::spawn(asio::bind_executor(- ex, &detail::default_spawn_handler),- ASIO_MOVE_CAST(Function)(function), attributes);-}--#if !defined(ASIO_NO_TS_EXECUTORS)--template <typename Function>-inline void spawn(const asio::io_context::strand& s,- ASIO_MOVE_ARG(Function) function,- const boost::coroutines::attributes& attributes)-{- asio::spawn(asio::bind_executor(- s, &detail::default_spawn_handler),- ASIO_MOVE_CAST(Function)(function), attributes);-}--#endif // !defined(ASIO_NO_TS_EXECUTORS)--template <typename Function, typename ExecutionContext>-inline void spawn(ExecutionContext& ctx,- ASIO_MOVE_ARG(Function) function,- const boost::coroutines::attributes& attributes,- typename enable_if<is_convertible<- ExecutionContext&, execution_context&>::value>::type*)-{- asio::spawn(ctx.get_executor(),- ASIO_MOVE_CAST(Function)(function), attributes);-}--#endif // !defined(GENERATING_DOCUMENTATION)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com)+//+// Distributed under the Boost Software License, Version 1.0. (See accompanying+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)+//++#ifndef ASIO_IMPL_SPAWN_HPP+#define ASIO_IMPL_SPAWN_HPP++#if defined(_MSC_VER) && (_MSC_VER >= 1200)+# pragma once+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)++#include "asio/detail/config.hpp"+#include "asio/associated_allocator.hpp"+#include "asio/associated_cancellation_slot.hpp"+#include "asio/associated_executor.hpp"+#include "asio/async_result.hpp"+#include "asio/bind_executor.hpp"+#include "asio/detail/atomic_count.hpp"+#include "asio/detail/bind_handler.hpp"+#include "asio/detail/handler_alloc_helpers.hpp"+#include "asio/detail/handler_cont_helpers.hpp"+#include "asio/detail/handler_invoke_helpers.hpp"+#include "asio/detail/memory.hpp"+#include "asio/detail/noncopyable.hpp"+#include "asio/detail/type_traits.hpp"+#include "asio/detail/utility.hpp"+#include "asio/detail/variadic_templates.hpp"+#include "asio/system_error.hpp"++#if defined(ASIO_HAS_STD_TUPLE)+# include <tuple>+#endif // defined(ASIO_HAS_STD_TUPLE)++#if defined(ASIO_HAS_BOOST_CONTEXT_FIBER)+# include <boost/context/fiber.hpp>+#endif // defined(ASIO_HAS_BOOST_CONTEXT_FIBER)++#include "asio/detail/push_options.hpp"++namespace asio {+namespace detail {++#if !defined(ASIO_NO_EXCEPTIONS)+inline void spawned_thread_rethrow(void* ex)+{+ if (*static_cast<exception_ptr*>(ex))+ rethrow_exception(*static_cast<exception_ptr*>(ex));+}+#endif // !defined(ASIO_NO_EXCEPTIONS)++#if defined(ASIO_HAS_BOOST_COROUTINE)++// Spawned thread implementation using Boost.Coroutine.+class spawned_coroutine_thread : public spawned_thread_base+{+public:+#if defined(BOOST_COROUTINES_UNIDIRECT) || defined(BOOST_COROUTINES_V2)+ typedef boost::coroutines::pull_coroutine<void> callee_type;+ typedef boost::coroutines::push_coroutine<void> caller_type;+#else+ typedef boost::coroutines::coroutine<void()> callee_type;+ typedef boost::coroutines::coroutine<void()> caller_type;+#endif++ spawned_coroutine_thread(caller_type& caller)+ : caller_(caller),+ on_suspend_fn_(0),+ on_suspend_arg_(0)+ {+ }++ template <typename F>+ static spawned_thread_base* spawn(ASIO_MOVE_ARG(F) f,+ const boost::coroutines::attributes& attributes,+ cancellation_slot parent_cancel_slot = cancellation_slot(),+ cancellation_state cancel_state = cancellation_state())+ {+ spawned_coroutine_thread* spawned_thread = 0;+ callee_type callee(entry_point<typename decay<F>::type>(+ ASIO_MOVE_CAST(F)(f), &spawned_thread), attributes);+ spawned_thread->callee_.swap(callee);+ spawned_thread->parent_cancellation_slot_ = parent_cancel_slot;+ spawned_thread->cancellation_state_ = cancel_state;+ return spawned_thread;+ }++ template <typename F>+ static spawned_thread_base* spawn(ASIO_MOVE_ARG(F) f,+ cancellation_slot parent_cancel_slot = cancellation_slot(),+ cancellation_state cancel_state = cancellation_state())+ {+ return spawn(ASIO_MOVE_CAST(F)(f), boost::coroutines::attributes(),+ parent_cancel_slot, cancel_state);+ }++ void resume()+ {+ callee_();+ if (on_suspend_fn_)+ {+ void (*fn)(void*) = on_suspend_fn_;+ void* arg = on_suspend_arg_;+ on_suspend_fn_ = 0;+ fn(arg);+ }+ }++ void suspend_with(void (*fn)(void*), void* arg)+ {+ if (throw_if_cancelled_)+ if (!!cancellation_state_.cancelled())+ throw_error(asio::error::operation_aborted, "yield");+ has_context_switched_ = true;+ on_suspend_fn_ = fn;+ on_suspend_arg_ = arg;+ caller_();+ }++ void destroy()+ {+ callee_type callee;+ callee.swap(callee_);+ if (terminal_)+ callee();+ }++private:+ template <typename Function>+ class entry_point+ {+ public:+ template <typename F>+ entry_point(ASIO_MOVE_ARG(F) f,+ spawned_coroutine_thread** spawned_thread_out)+ : function_(ASIO_MOVE_CAST(F)(f)),+ spawned_thread_out_(spawned_thread_out)+ {+ }++ void operator()(caller_type& caller)+ {+ Function function(ASIO_MOVE_CAST(Function)(function_));+ spawned_coroutine_thread spawned_thread(caller);+ *spawned_thread_out_ = &spawned_thread;+ spawned_thread_out_ = 0;+ spawned_thread.suspend();+#if !defined(ASIO_NO_EXCEPTIONS)+ try+#endif // !defined(ASIO_NO_EXCEPTIONS)+ {+ function(&spawned_thread);+ spawned_thread.terminal_ = true;+ spawned_thread.suspend();+ }+#if !defined(ASIO_NO_EXCEPTIONS)+ catch (const boost::coroutines::detail::forced_unwind&)+ {+ throw;+ }+ catch (...)+ {+ exception_ptr ex = current_exception();+ spawned_thread.terminal_ = true;+ spawned_thread.suspend_with(spawned_thread_rethrow, &ex);+ }+#endif // !defined(ASIO_NO_EXCEPTIONS)+ }++ private:+ Function function_;+ spawned_coroutine_thread** spawned_thread_out_;+ };++ caller_type& caller_;+ callee_type callee_;+ void (*on_suspend_fn_)(void*);+ void* on_suspend_arg_;+};++#endif // defined(ASIO_HAS_BOOST_COROUTINE)++#if defined(ASIO_HAS_BOOST_CONTEXT_FIBER)++// Spawned thread implementation using Boost.Context's fiber.+class spawned_fiber_thread : public spawned_thread_base+{+public:+ typedef boost::context::fiber fiber_type;++ spawned_fiber_thread(ASIO_MOVE_ARG(fiber_type) caller)+ : caller_(ASIO_MOVE_CAST(fiber_type)(caller)),+ on_suspend_fn_(0),+ on_suspend_arg_(0)+ {+ }++ template <typename StackAllocator, typename F>+ static spawned_thread_base* spawn(allocator_arg_t,+ ASIO_MOVE_ARG(StackAllocator) stack_allocator,+ ASIO_MOVE_ARG(F) f,+ cancellation_slot parent_cancel_slot = cancellation_slot(),+ cancellation_state cancel_state = cancellation_state())+ {+ spawned_fiber_thread* spawned_thread = 0;+ fiber_type callee(allocator_arg_t(),+ ASIO_MOVE_CAST(StackAllocator)(stack_allocator),+ entry_point<typename decay<F>::type>(+ ASIO_MOVE_CAST(F)(f), &spawned_thread));+ callee = fiber_type(ASIO_MOVE_CAST(fiber_type)(callee)).resume();+ spawned_thread->callee_ = ASIO_MOVE_CAST(fiber_type)(callee);+ spawned_thread->parent_cancellation_slot_ = parent_cancel_slot;+ spawned_thread->cancellation_state_ = cancel_state;+ return spawned_thread;+ }++ template <typename F>+ static spawned_thread_base* spawn(ASIO_MOVE_ARG(F) f,+ cancellation_slot parent_cancel_slot = cancellation_slot(),+ cancellation_state cancel_state = cancellation_state())+ {+ return spawn(allocator_arg_t(), boost::context::fixedsize_stack(),+ ASIO_MOVE_CAST(F)(f), parent_cancel_slot, cancel_state);+ }++ void resume()+ {+ callee_ = fiber_type(ASIO_MOVE_CAST(fiber_type)(callee_)).resume();+ if (on_suspend_fn_)+ {+ void (*fn)(void*) = on_suspend_fn_;+ void* arg = on_suspend_arg_;+ on_suspend_fn_ = 0;+ fn(arg);+ }+ }++ void suspend_with(void (*fn)(void*), void* arg)+ {+ if (throw_if_cancelled_)+ if (!!cancellation_state_.cancelled())+ throw_error(asio::error::operation_aborted, "yield");+ has_context_switched_ = true;+ on_suspend_fn_ = fn;+ on_suspend_arg_ = arg;+ caller_ = fiber_type(ASIO_MOVE_CAST(fiber_type)(caller_)).resume();+ }++ void destroy()+ {+ fiber_type callee = ASIO_MOVE_CAST(fiber_type)(callee_);+ if (terminal_)+ fiber_type(ASIO_MOVE_CAST(fiber_type)(callee)).resume();+ }++private:+ template <typename Function>+ class entry_point+ {+ public:+ template <typename F>+ entry_point(ASIO_MOVE_ARG(F) f,+ spawned_fiber_thread** spawned_thread_out)+ : function_(ASIO_MOVE_CAST(F)(f)),+ spawned_thread_out_(spawned_thread_out)+ {+ }++ fiber_type operator()(ASIO_MOVE_ARG(fiber_type) caller)+ {+ Function function(ASIO_MOVE_CAST(Function)(function_));+ spawned_fiber_thread spawned_thread(+ ASIO_MOVE_CAST(fiber_type)(caller));+ *spawned_thread_out_ = &spawned_thread;+ spawned_thread_out_ = 0;+ spawned_thread.suspend();+#if !defined(ASIO_NO_EXCEPTIONS)+ try+#endif // !defined(ASIO_NO_EXCEPTIONS)+ {+ function(&spawned_thread);+ spawned_thread.terminal_ = true;+ spawned_thread.suspend();+ }+#if !defined(ASIO_NO_EXCEPTIONS)+ catch (const boost::context::detail::forced_unwind&)+ {+ throw;+ }+ catch (...)+ {+ exception_ptr ex = current_exception();+ spawned_thread.terminal_ = true;+ spawned_thread.suspend_with(spawned_thread_rethrow, &ex);+ }+#endif // !defined(ASIO_NO_EXCEPTIONS)+ return ASIO_MOVE_CAST(fiber_type)(spawned_thread.caller_);+ }++ private:+ Function function_;+ spawned_fiber_thread** spawned_thread_out_;+ };++ fiber_type caller_;+ fiber_type callee_;+ void (*on_suspend_fn_)(void*);+ void* on_suspend_arg_;+};++#endif // defined(ASIO_HAS_BOOST_CONTEXT_FIBER)++#if defined(ASIO_HAS_BOOST_CONTEXT_FIBER)+typedef spawned_fiber_thread default_spawned_thread_type;+#elif defined(ASIO_HAS_BOOST_COROUTINE)+typedef spawned_coroutine_thread default_spawned_thread_type;+#else+# error No spawn() implementation available+#endif++// Helper class to perform the initial resume on the correct executor.+class spawned_thread_resumer+{+public:+ explicit spawned_thread_resumer(spawned_thread_base* spawned_thread)+ : spawned_thread_(spawned_thread)+ {+#if !defined(ASIO_HAS_MOVE)+ spawned_thread->detach();+ spawned_thread->attach(&spawned_thread_);+#endif // !defined(ASIO_HAS_MOVE)+ }++#if defined(ASIO_HAS_MOVE)++ spawned_thread_resumer(spawned_thread_resumer&& other) ASIO_NOEXCEPT+ : spawned_thread_(other.spawned_thread_)+ {+ other.spawned_thread_ = 0;+ }++#else // defined(ASIO_HAS_MOVE)++ spawned_thread_resumer(+ const spawned_thread_resumer& other) ASIO_NOEXCEPT+ : spawned_thread_(other.spawned_thread_)+ {+ spawned_thread_->detach();+ spawned_thread_->attach(&spawned_thread_);+ }++#endif // defined(ASIO_HAS_MOVE)++ ~spawned_thread_resumer()+ {+ if (spawned_thread_)+ spawned_thread_->destroy();+ }++ void operator()()+ {+#if defined(ASIO_HAS_MOVE)+ spawned_thread_->attach(&spawned_thread_);+#endif // defined(ASIO_HAS_MOVE)+ spawned_thread_->resume();+ }++private:+ spawned_thread_base* spawned_thread_;+};++// Helper class to ensure spawned threads are destroyed on the correct executor.+class spawned_thread_destroyer+{+public:+ explicit spawned_thread_destroyer(spawned_thread_base* spawned_thread)+ : spawned_thread_(spawned_thread)+ {+ spawned_thread->detach();+#if !defined(ASIO_HAS_MOVE)+ spawned_thread->attach(&spawned_thread_);+#endif // !defined(ASIO_HAS_MOVE)+ }++#if defined(ASIO_HAS_MOVE)++ spawned_thread_destroyer(spawned_thread_destroyer&& other) ASIO_NOEXCEPT+ : spawned_thread_(other.spawned_thread_)+ {+ other.spawned_thread_ = 0;+ }++#else // defined(ASIO_HAS_MOVE)++ spawned_thread_destroyer(+ const spawned_thread_destroyer& other) ASIO_NOEXCEPT+ : spawned_thread_(other.spawned_thread_)+ {+ spawned_thread_->detach();+ spawned_thread_->attach(&spawned_thread_);+ }++#endif // defined(ASIO_HAS_MOVE)++ ~spawned_thread_destroyer()+ {+ if (spawned_thread_)+ spawned_thread_->destroy();+ }++ void operator()()+ {+ if (spawned_thread_)+ {+ spawned_thread_->destroy();+ spawned_thread_ = 0;+ }+ }++private:+ spawned_thread_base* spawned_thread_;+};++// Base class for all completion handlers associated with a spawned thread.+template <typename Executor>+class spawn_handler_base+{+public:+ typedef Executor executor_type;+ typedef cancellation_slot cancellation_slot_type;++ spawn_handler_base(const basic_yield_context<Executor>& yield)+ : yield_(yield),+ spawned_thread_(yield.spawned_thread_)+ {+ spawned_thread_->detach();+#if !defined(ASIO_HAS_MOVE)+ spawned_thread_->attach(&spawned_thread_);+#endif // !defined(ASIO_HAS_MOVE)+ }++#if defined(ASIO_HAS_MOVE)++ spawn_handler_base(spawn_handler_base&& other) ASIO_NOEXCEPT+ : yield_(other.yield_),+ spawned_thread_(other.spawned_thread_)++ {+ other.spawned_thread_ = 0;+ }++#else // defined(ASIO_HAS_MOVE)++ spawn_handler_base(const spawn_handler_base& other) ASIO_NOEXCEPT+ : yield_(other.yield_),+ spawned_thread_(other.spawned_thread_)+ {+ spawned_thread_->detach();+ spawned_thread_->attach(&spawned_thread_);+ }++#endif // defined(ASIO_HAS_MOVE)++ ~spawn_handler_base()+ {+ if (spawned_thread_)+ (post)(yield_.executor_, spawned_thread_destroyer(spawned_thread_));+ }++ executor_type get_executor() const ASIO_NOEXCEPT+ {+ return yield_.executor_;+ }++ cancellation_slot_type get_cancellation_slot() const ASIO_NOEXCEPT+ {+ return spawned_thread_->get_cancellation_slot();+ }++ void resume()+ {+ spawned_thread_resumer resumer(spawned_thread_);+ spawned_thread_ = 0;+ resumer();+ }++protected:+ const basic_yield_context<Executor>& yield_;+ spawned_thread_base* spawned_thread_;+};++// Completion handlers for when basic_yield_context is used as a token.+template <typename Executor, typename Signature>+class spawn_handler;++template <typename Executor, typename R>+class spawn_handler<Executor, R()>+ : public spawn_handler_base<Executor>+{+public:+ typedef void return_type;++ struct result_type {};++ spawn_handler(const basic_yield_context<Executor>& yield, result_type&)+ : spawn_handler_base<Executor>(yield)+ {+ }++ void operator()()+ {+ this->resume();+ }++ static return_type on_resume(result_type&)+ {+ }+};++template <typename Executor, typename R>+class spawn_handler<Executor, R(asio::error_code)>+ : public spawn_handler_base<Executor>+{+public:+ typedef void return_type;+ typedef asio::error_code* result_type;++ spawn_handler(const basic_yield_context<Executor>& yield, result_type& result)+ : spawn_handler_base<Executor>(yield),+ result_(result)+ {+ }++ void operator()(asio::error_code ec)+ {+ if (this->yield_.ec_)+ {+ *this->yield_.ec_ = ec;+ result_ = 0;+ }+ else+ result_ = &ec;+ this->resume();+ }++ static return_type on_resume(result_type& result)+ {+ if (result)+ throw_error(*result);+ }++private:+ result_type& result_;+};++template <typename Executor, typename R>+class spawn_handler<Executor, R(exception_ptr)>+ : public spawn_handler_base<Executor>+{+public:+ typedef void return_type;+ typedef exception_ptr* result_type;++ spawn_handler(const basic_yield_context<Executor>& yield, result_type& result)+ : spawn_handler_base<Executor>(yield),+ result_(result)+ {+ }++ void operator()(exception_ptr ex)+ {+ result_ = &ex;+ this->resume();+ }++ static return_type on_resume(result_type& result)+ {+ if (result)+ rethrow_exception(*result);+ }++private:+ result_type& result_;+};++template <typename Executor, typename R, typename T>+class spawn_handler<Executor, R(T)>+ : public spawn_handler_base<Executor>+{+public:+ typedef T return_type;+ typedef return_type* result_type;++ spawn_handler(const basic_yield_context<Executor>& yield, result_type& result)+ : spawn_handler_base<Executor>(yield),+ result_(result)+ {+ }++ void operator()(T value)+ {+ result_ = &value;+ this->resume();+ }++ static return_type on_resume(result_type& result)+ {+ return ASIO_MOVE_CAST(return_type)(*result);+ }++private:+ result_type& result_;+};++template <typename Executor, typename R, typename T>+class spawn_handler<Executor, R(asio::error_code, T)>+ : public spawn_handler_base<Executor>+{+public:+ typedef T return_type;++ struct result_type+ {+ asio::error_code* ec_;+ return_type* value_;+ };++ spawn_handler(const basic_yield_context<Executor>& yield, result_type& result)+ : spawn_handler_base<Executor>(yield),+ result_(result)+ {+ }++ void operator()(asio::error_code ec, T value)+ {+ if (this->yield_.ec_)+ {+ *this->yield_.ec_ = ec;+ result_.ec_ = 0;+ }+ else+ result_.ec_ = &ec;+ result_.value_ = &value;+ this->resume();+ }++ static return_type on_resume(result_type& result)+ {+ if (result.ec_)+ throw_error(*result.ec_);+ return ASIO_MOVE_CAST(return_type)(*result.value_);+ }++private:+ result_type& result_;+};++template <typename Executor, typename R, typename T>+class spawn_handler<Executor, R(exception_ptr, T)>+ : public spawn_handler_base<Executor>+{+public:+ typedef T return_type;++ struct result_type+ {+ exception_ptr ex_;+ return_type* value_;+ };++ spawn_handler(const basic_yield_context<Executor>& yield, result_type& result)+ : spawn_handler_base<Executor>(yield),+ result_(result)+ {+ }++ void operator()(exception_ptr ex, T value)+ {+ result_.ex_ = &ex;+ result_.value_ = &value;+ this->resume();+ }++ static return_type on_resume(result_type& result)+ {+ if (result.ex_)+ rethrow_exception(*result.ex_);+ return ASIO_MOVE_CAST(return_type)(*result.value_);+ }++private:+ result_type& result_;+};++#if defined(ASIO_HAS_VARIADIC_TEMPLATES) \+ && defined(ASIO_HAS_STD_TUPLE)++template <typename Executor, typename R, typename... Ts>+class spawn_handler<Executor, R(Ts...)>+ : public spawn_handler_base<Executor>+{+public:+ typedef std::tuple<Ts...> return_type;++ typedef return_type* result_type;++ spawn_handler(const basic_yield_context<Executor>& yield, result_type& result)+ : spawn_handler_base<Executor>(yield),+ result_(result)+ {+ }++ template <typename... Args>+ void operator()(ASIO_MOVE_ARG(Args)... args)+ {+ return_type value(ASIO_MOVE_CAST(Args)(args)...);+ result_ = &value;+ this->resume();+ }++ static return_type on_resume(result_type& result)+ {+ return ASIO_MOVE_CAST(return_type)(*result);+ }++private:+ result_type& result_;+};++template <typename Executor, typename R, typename... Ts>+class spawn_handler<Executor, R(asio::error_code, Ts...)>+ : public spawn_handler_base<Executor>+{+public:+ typedef std::tuple<Ts...> return_type;++ struct result_type+ {+ asio::error_code* ec_;+ return_type* value_;+ };++ spawn_handler(const basic_yield_context<Executor>& yield, result_type& result)+ : spawn_handler_base<Executor>(yield),+ result_(result)+ {+ }++ template <typename... Args>+ void operator()(asio::error_code ec,+ ASIO_MOVE_ARG(Args)... args)+ {+ return_type value(ASIO_MOVE_CAST(Args)(args)...);+ if (this->yield_.ec_)+ {+ *this->yield_.ec_ = ec;+ result_.ec_ = 0;+ }+ else+ result_.ec_ = &ec;+ result_.value_ = &value;+ this->resume();+ }++ static return_type on_resume(result_type& result)+ {+ if (result.ec_)+ throw_error(*result.ec_);+ return ASIO_MOVE_CAST(return_type)(*result.value_);+ }++private:+ result_type& result_;+};++template <typename Executor, typename R, typename... Ts>+class spawn_handler<Executor, R(exception_ptr, Ts...)>+ : public spawn_handler_base<Executor>+{+public:+ typedef std::tuple<Ts...> return_type;++ struct result_type+ {+ exception_ptr ex_;+ return_type* value_;+ };++ spawn_handler(const basic_yield_context<Executor>& yield, result_type& result)+ : spawn_handler_base<Executor>(yield),+ result_(result)+ {+ }++ template <typename... Args>+ void operator()(exception_ptr ex, ASIO_MOVE_ARG(Args)... args)+ {+ return_type value(ASIO_MOVE_CAST(Args)(args)...);+ result_.ex_ = &ex;+ result_.value_ = &value;+ this->resume();+ }++ static return_type on_resume(result_type& result)+ {+ if (result.ex_)+ rethrow_exception(*result.ex_);+ return ASIO_MOVE_CAST(return_type)(*result.value_);+ }++private:+ result_type& result_;+};++#endif // defined(ASIO_HAS_VARIADIC_TEMPLATES)+ // && defined(ASIO_HAS_STD_TUPLE)++template <typename Executor, typename Signature>+inline bool asio_handler_is_continuation(spawn_handler<Executor, Signature>*)+{+ return true;+}++} // namespace detail++template <typename Executor, typename Signature>+class async_result<basic_yield_context<Executor>, Signature>+{+public:+ typedef typename detail::spawn_handler<Executor, Signature> handler_type;+ typedef typename handler_type::return_type return_type;++#if defined(ASIO_HAS_VARIADIC_TEMPLATES)+# if defined(ASIO_HAS_VARIADIC_LAMBDA_CAPTURES)++ template <typename Initiation, typename... InitArgs>+ static return_type initiate(ASIO_MOVE_ARG(Initiation) init,+ const basic_yield_context<Executor>& yield,+ ASIO_MOVE_ARG(InitArgs)... init_args)+ {+ typename handler_type::result_type result+ = typename handler_type::result_type();++ yield.spawned_thread_->suspend_with(+ [&]()+ {+ ASIO_MOVE_CAST(Initiation)(init)(+ handler_type(yield, result),+ ASIO_MOVE_CAST(InitArgs)(init_args)...);+ });++ return handler_type::on_resume(result);+ }++# else // defined(ASIO_HAS_VARIADIC_LAMBDA_CAPTURES)++ template <typename Initiation, typename... InitArgs>+ struct suspend_with_helper+ {+ typename handler_type::result_type& result_;+ ASIO_MOVE_ARG(Initiation) init_;+ const basic_yield_context<Executor>& yield_;+ std::tuple<ASIO_MOVE_ARG(InitArgs)...> init_args_;++ template <std::size_t... I>+ void do_invoke(detail::index_sequence<I...>)+ {+ ASIO_MOVE_CAST(Initiation)(init_)(+ handler_type(yield_, result_),+ ASIO_MOVE_CAST(InitArgs)(std::get<I>(init_args_))...);+ }++ void operator()()+ {+ this->do_invoke(detail::make_index_sequence<sizeof...(InitArgs)>());+ }+ };++ template <typename Initiation, typename... InitArgs>+ static return_type initiate(ASIO_MOVE_ARG(Initiation) init,+ const basic_yield_context<Executor>& yield,+ ASIO_MOVE_ARG(InitArgs)... init_args)+ {+ typename handler_type::result_type result+ = typename handler_type::result_type();++ yield.spawned_thread_->suspend_with(+ suspend_with_helper<Initiation, InitArgs...>{+ result, ASIO_MOVE_CAST(Initiation)(init), yield,+ std::tuple<ASIO_MOVE_ARG(InitArgs)...>(+ ASIO_MOVE_CAST(InitArgs)(init_args)...)});++ return handler_type::on_resume(result);+ }++# endif // defined(ASIO_HAS_VARIADIC_LAMBDA_CAPTURES)+#else // defined(ASIO_HAS_VARIADIC_TEMPLATES)++ template <typename Initiation>+ static return_type initiate(Initiation init,+ const basic_yield_context<Executor>& yield)+ {+ typename handler_type::result_type result+ = typename handler_type::result_type();++ struct on_suspend+ {+ Initiation& init_;+ const basic_yield_context<Executor>& yield_;+ typename handler_type::result_type& result_;++ void do_call()+ {+ ASIO_MOVE_CAST(Initiation)(init_)(+ handler_type(yield_, result_));+ }++ static void call(void* arg)+ {+ static_cast<on_suspend*>(arg)->do_call();+ }+ } o = { init, yield, result };++ yield.spawned_thread_->suspend_with(&on_suspend::call, &o);++ return handler_type::on_resume(result);+ }++#define ASIO_PRIVATE_ON_SUSPEND_MEMBERS(n) \+ ASIO_PRIVATE_ON_SUSPEND_MEMBERS_##n+#define ASIO_PRIVATE_ON_SUSPEND_MEMBERS_1 \+ T1& x1;+#define ASIO_PRIVATE_ON_SUSPEND_MEMBERS_2 \+ T1& x1; T2& x2;+#define ASIO_PRIVATE_ON_SUSPEND_MEMBERS_3 \+ T1& x1; T2& x2; T3& x3;+#define ASIO_PRIVATE_ON_SUSPEND_MEMBERS_4 \+ T1& x1; T2& x2; T3& x3; T4& x4;+#define ASIO_PRIVATE_ON_SUSPEND_MEMBERS_5 \+ T1& x1; T2& x2; T3& x3; T4& x4; T5& x5;+#define ASIO_PRIVATE_ON_SUSPEND_MEMBERS_6 \+ T1& x1; T2& x2; T3& x3; T4& x4; T5& x5; T6& x6;+#define ASIO_PRIVATE_ON_SUSPEND_MEMBERS_7 \+ T1& x1; T2& x2; T3& x3; T4& x4; T5& x5; T6& x6; T7& x7;+#define ASIO_PRIVATE_ON_SUSPEND_MEMBERS_8 \+ T1& x1; T2& x2; T3& x3; T4& x4; T5& x5; T6& x6; T7& x7; T8& x8;++#define ASIO_PRIVATE_INITIATE_DEF(n) \+ template <typename Initiation, ASIO_VARIADIC_TPARAMS(n)> \+ static return_type initiate(Initiation init, \+ const basic_yield_context<Executor>& yield, \+ ASIO_VARIADIC_BYVAL_PARAMS(n)) \+ { \+ typename handler_type::result_type result \+ = typename handler_type::result_type(); \+ \+ struct on_suspend \+ { \+ Initiation& init; \+ const basic_yield_context<Executor>& yield; \+ typename handler_type::result_type& result; \+ ASIO_PRIVATE_ON_SUSPEND_MEMBERS(n) \+ \+ void do_call() \+ { \+ ASIO_MOVE_CAST(Initiation)(init)( \+ handler_type(yield, result), \+ ASIO_VARIADIC_MOVE_ARGS(n)); \+ } \+ \+ static void call(void* arg) \+ { \+ static_cast<on_suspend*>(arg)->do_call(); \+ } \+ } o = { init, yield, result, ASIO_VARIADIC_BYVAL_ARGS(n) }; \+ \+ yield.spawned_thread_->suspend_with(&on_suspend::call, &o); \+ \+ return handler_type::on_resume(result); \+ } \+ /**/+ ASIO_VARIADIC_GENERATE(ASIO_PRIVATE_INITIATE_DEF)+#undef ASIO_PRIVATE_INITIATE_DEF+#undef ASIO_PRIVATE_ON_SUSPEND_MEMBERS+#undef ASIO_PRIVATE_ON_SUSPEND_MEMBERS_1+#undef ASIO_PRIVATE_ON_SUSPEND_MEMBERS_2+#undef ASIO_PRIVATE_ON_SUSPEND_MEMBERS_3+#undef ASIO_PRIVATE_ON_SUSPEND_MEMBERS_4+#undef ASIO_PRIVATE_ON_SUSPEND_MEMBERS_5+#undef ASIO_PRIVATE_ON_SUSPEND_MEMBERS_6+#undef ASIO_PRIVATE_ON_SUSPEND_MEMBERS_7+#undef ASIO_PRIVATE_ON_SUSPEND_MEMBERS_8++#endif // defined(ASIO_HAS_VARIADIC_TEMPLATES)+};++namespace detail {++template <typename Executor, typename Function, typename Handler>+class spawn_entry_point+{+public:+ template <typename F, typename H>+ spawn_entry_point(const Executor& ex,+ ASIO_MOVE_ARG(F) f, ASIO_MOVE_ARG(H) h)+ : executor_(ex),+ function_(ASIO_MOVE_CAST(F)(f)),+ handler_(ASIO_MOVE_CAST(H)(h)),+ work_(handler_, executor_)+ {+ }++ void operator()(spawned_thread_base* spawned_thread)+ {+ const basic_yield_context<Executor> yield(spawned_thread, executor_);+ this->call(yield,+ void_type<typename result_of<Function(+ basic_yield_context<Executor>)>::type>());+ }++private:+ void call(const basic_yield_context<Executor>& yield, void_type<void>)+ {+#if !defined(ASIO_NO_EXCEPTIONS)+ try+#endif // !defined(ASIO_NO_EXCEPTIONS)+ {+ function_(yield);+ if (!yield.spawned_thread_->has_context_switched())+ (post)(yield);+ detail::binder1<Handler, exception_ptr>+ handler(handler_, exception_ptr());+ work_.complete(handler, handler.handler_);+ }+#if !defined(ASIO_NO_EXCEPTIONS)+# if defined(ASIO_HAS_BOOST_CONTEXT_FIBER)+ catch (const boost::context::detail::forced_unwind&)+ {+ throw;+ }+# endif // defined(ASIO_HAS_BOOST_CONTEXT_FIBER)+# if defined(ASIO_HAS_BOOST_COROUTINE)+ catch (const boost::coroutines::detail::forced_unwind&)+ {+ throw;+ }+# endif // defined(ASIO_HAS_BOOST_COROUTINE)+ catch (...)+ {+ exception_ptr ex = current_exception();+ if (!yield.spawned_thread_->has_context_switched())+ (post)(yield);+ detail::binder1<Handler, exception_ptr> handler(handler_, ex);+ work_.complete(handler, handler.handler_);+ }+#endif // !defined(ASIO_NO_EXCEPTIONS)+ }++ template <typename T>+ void call(const basic_yield_context<Executor>& yield, void_type<T>)+ {+#if !defined(ASIO_NO_EXCEPTIONS)+ try+#endif // !defined(ASIO_NO_EXCEPTIONS)+ {+ T result(function_(yield));+ if (!yield.spawned_thread_->has_context_switched())+ (post)(yield);+ detail::binder2<Handler, exception_ptr, T>+ handler(handler_, exception_ptr(), ASIO_MOVE_CAST(T)(result));+ work_.complete(handler, handler.handler_);+ }+#if !defined(ASIO_NO_EXCEPTIONS)+# if defined(ASIO_HAS_BOOST_CONTEXT_FIBER)+ catch (const boost::context::detail::forced_unwind&)+ {+ throw;+ }+# endif // defined(ASIO_HAS_BOOST_CONTEXT_FIBER)+# if defined(ASIO_HAS_BOOST_COROUTINE)+ catch (const boost::coroutines::detail::forced_unwind&)+ {+ throw;+ }+# endif // defined(ASIO_HAS_BOOST_COROUTINE)+ catch (...)+ {+ exception_ptr ex = current_exception();+ if (!yield.spawned_thread_->has_context_switched())+ (post)(yield);+ detail::binder2<Handler, exception_ptr, T> handler(handler_, ex, T());+ work_.complete(handler, handler.handler_);+ }+#endif // !defined(ASIO_NO_EXCEPTIONS)+ }++ Executor executor_;+ Function function_;+ Handler handler_;+ handler_work<Handler, Executor> work_;+};++struct spawn_cancellation_signal_emitter+{+ cancellation_signal* signal_;+ cancellation_type_t type_;++ void operator()()+ {+ signal_->emit(type_);+ }+};++template <typename Handler, typename Executor, typename = void>+class spawn_cancellation_handler+{+public:+ spawn_cancellation_handler(const Handler&, const Executor& ex)+ : ex_(ex)+ {+ }++ cancellation_slot slot()+ {+ return signal_.slot();+ }++ void operator()(cancellation_type_t type)+ {+ spawn_cancellation_signal_emitter emitter = { &signal_, type };+ (dispatch)(ex_, emitter);+ }++private:+ cancellation_signal signal_;+ Executor ex_;+};+++template <typename Handler, typename Executor>+class spawn_cancellation_handler<Handler, Executor,+ typename enable_if<+ is_same<+ typename associated_executor<Handler,+ Executor>::asio_associated_executor_is_unspecialised,+ void+ >::value+ >::type>+{+public:+ spawn_cancellation_handler(const Handler&, const Executor&)+ {+ }++ cancellation_slot slot()+ {+ return signal_.slot();+ }++ void operator()(cancellation_type_t type)+ {+ signal_.emit(type);+ }++private:+ cancellation_signal signal_;+};++template <typename Executor>+class initiate_spawn+{+public:+ typedef Executor executor_type;++ explicit initiate_spawn(const executor_type& ex)+ : executor_(ex)+ {+ }++ executor_type get_executor() const ASIO_NOEXCEPT+ {+ return executor_;+ }++ template <typename Handler, typename F>+ void operator()(ASIO_MOVE_ARG(Handler) handler,+ ASIO_MOVE_ARG(F) f) const+ {+ typedef typename decay<Handler>::type handler_type;+ typedef typename decay<F>::type function_type;+ typedef spawn_cancellation_handler<+ handler_type, Executor> cancel_handler_type;++ typename associated_cancellation_slot<handler_type>::type slot+ = asio::get_associated_cancellation_slot(handler);++ cancel_handler_type* cancel_handler = slot.is_connected()+ ? &slot.template emplace<cancel_handler_type>(handler, executor_)+ : 0;++ cancellation_slot proxy_slot(+ cancel_handler+ ? cancel_handler->slot()+ : cancellation_slot());++ cancellation_state cancel_state(proxy_slot);++ (dispatch)(executor_,+ spawned_thread_resumer(+ default_spawned_thread_type::spawn(+ spawn_entry_point<Executor, function_type, handler_type>(+ executor_, ASIO_MOVE_CAST(F)(f),+ ASIO_MOVE_CAST(Handler)(handler)),+ proxy_slot, cancel_state)));+ }++#if defined(ASIO_HAS_BOOST_CONTEXT_FIBER)++ template <typename Handler, typename StackAllocator, typename F>+ void operator()(ASIO_MOVE_ARG(Handler) handler, allocator_arg_t,+ ASIO_MOVE_ARG(StackAllocator) stack_allocator,+ ASIO_MOVE_ARG(F) f) const+ {+ typedef typename decay<Handler>::type handler_type;+ typedef typename decay<F>::type function_type;+ typedef spawn_cancellation_handler<+ handler_type, Executor> cancel_handler_type;++ typename associated_cancellation_slot<handler_type>::type slot+ = asio::get_associated_cancellation_slot(handler);++ cancel_handler_type* cancel_handler = slot.is_connected()+ ? &slot.template emplace<cancel_handler_type>(handler, executor_)+ : 0;++ cancellation_slot proxy_slot(+ cancel_handler+ ? cancel_handler->slot()+ : cancellation_slot());++ cancellation_state cancel_state(proxy_slot);++ (dispatch)(executor_,+ spawned_thread_resumer(+ spawned_fiber_thread::spawn(allocator_arg_t(),+ ASIO_MOVE_CAST(StackAllocator)(stack_allocator),+ spawn_entry_point<Executor, function_type, handler_type>(+ executor_, ASIO_MOVE_CAST(F)(f),+ ASIO_MOVE_CAST(Handler)(handler)),+ proxy_slot, cancel_state)));+ }++#endif // defined(ASIO_HAS_BOOST_CONTEXT_FIBER)++private:+ executor_type executor_;+};++} // namespace detail++template <typename Executor, typename F,+ ASIO_COMPLETION_TOKEN_FOR(typename detail::spawn_signature<+ typename result_of<F(basic_yield_context<Executor>)>::type>::type)+ CompletionToken>+inline ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX(CompletionToken,+ typename detail::spawn_signature<+ typename result_of<F(basic_yield_context<Executor>)>::type>::type)+spawn(const Executor& ex, ASIO_MOVE_ARG(F) function,+ ASIO_MOVE_ARG(CompletionToken) token,+#if defined(ASIO_HAS_BOOST_COROUTINE)+ typename constraint<+ !is_same<+ typename decay<CompletionToken>::type,+ boost::coroutines::attributes+ >::value+ >::type,+#endif // defined(ASIO_HAS_BOOST_COROUTINE)+ typename constraint<+ is_executor<Executor>::value || execution::is_executor<Executor>::value+ >::type)+ ASIO_INITFN_AUTO_RESULT_TYPE_SUFFIX((+ async_initiate<CompletionToken,+ typename detail::spawn_signature<+ typename result_of<F(basic_yield_context<Executor>)>::type>::type>(+ declval<detail::initiate_spawn<Executor> >(),+ token, ASIO_MOVE_CAST(F)(function))))+{+ return async_initiate<CompletionToken,+ typename detail::spawn_signature<+ typename result_of<F(basic_yield_context<Executor>)>::type>::type>(+ detail::initiate_spawn<Executor>(ex),+ token, ASIO_MOVE_CAST(F)(function));+}++template <typename ExecutionContext, typename F,+ ASIO_COMPLETION_TOKEN_FOR(typename detail::spawn_signature<+ typename result_of<F(basic_yield_context<+ typename ExecutionContext::executor_type>)>::type>::type)+ CompletionToken>+inline ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX(CompletionToken,+ typename detail::spawn_signature<+ typename result_of<F(basic_yield_context<+ typename ExecutionContext::executor_type>)>::type>::type)+spawn(ExecutionContext& ctx, ASIO_MOVE_ARG(F) function,+ ASIO_MOVE_ARG(CompletionToken) token,+#if defined(ASIO_HAS_BOOST_COROUTINE)+ typename constraint<+ !is_same<+ typename decay<CompletionToken>::type,+ boost::coroutines::attributes+ >::value+ >::type,+#endif // defined(ASIO_HAS_BOOST_COROUTINE)+ typename constraint<+ is_convertible<ExecutionContext&, execution_context&>::value+ >::type)+ ASIO_INITFN_AUTO_RESULT_TYPE_SUFFIX((+ async_initiate<CompletionToken,+ typename detail::spawn_signature<+ typename result_of<F(basic_yield_context<+ typename ExecutionContext::executor_type>)>::type>::type>(+ declval<detail::initiate_spawn<+ typename ExecutionContext::executor_type> >(),+ token, ASIO_MOVE_CAST(F)(function))))+{+ return (spawn)(ctx.get_executor(), ASIO_MOVE_CAST(F)(function),+ ASIO_MOVE_CAST(CompletionToken)(token));+}++template <typename Executor, typename F,+ ASIO_COMPLETION_TOKEN_FOR(typename detail::spawn_signature<+ typename result_of<F(basic_yield_context<Executor>)>::type>::type)+ CompletionToken>+inline ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX(CompletionToken,+ typename detail::spawn_signature<+ typename result_of<F(basic_yield_context<Executor>)>::type>::type)+spawn(const basic_yield_context<Executor>& ctx,+ ASIO_MOVE_ARG(F) function,+ ASIO_MOVE_ARG(CompletionToken) token,+#if defined(ASIO_HAS_BOOST_COROUTINE)+ typename constraint<+ !is_same<+ typename decay<CompletionToken>::type,+ boost::coroutines::attributes+ >::value+ >::type,+#endif // defined(ASIO_HAS_BOOST_COROUTINE)+ typename constraint<+ is_executor<Executor>::value || execution::is_executor<Executor>::value+ >::type)+ ASIO_INITFN_AUTO_RESULT_TYPE_SUFFIX((+ async_initiate<CompletionToken,+ typename detail::spawn_signature<+ typename result_of<F(basic_yield_context<Executor>)>::type>::type>(+ declval<detail::initiate_spawn<Executor> >(),+ token, ASIO_MOVE_CAST(F)(function))))+{+ return (spawn)(ctx.get_executor(), ASIO_MOVE_CAST(F)(function),+ ASIO_MOVE_CAST(CompletionToken)(token));+}++#if defined(ASIO_HAS_BOOST_CONTEXT_FIBER)++template <typename Executor, typename StackAllocator, typename F,+ ASIO_COMPLETION_TOKEN_FOR(typename detail::spawn_signature<+ typename result_of<F(basic_yield_context<Executor>)>::type>::type)+ CompletionToken>+inline ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX(CompletionToken,+ typename detail::spawn_signature<+ typename result_of<F(basic_yield_context<Executor>)>::type>::type)+spawn(const Executor& ex, allocator_arg_t,+ ASIO_MOVE_ARG(StackAllocator) stack_allocator,+ ASIO_MOVE_ARG(F) function,+ ASIO_MOVE_ARG(CompletionToken) token,+ typename constraint<+ is_executor<Executor>::value || execution::is_executor<Executor>::value+ >::type)+ ASIO_INITFN_AUTO_RESULT_TYPE_SUFFIX((+ async_initiate<CompletionToken,+ typename detail::spawn_signature<+ typename result_of<F(basic_yield_context<Executor>)>::type>::type>(+ declval<detail::initiate_spawn<Executor> >(),+ token, allocator_arg_t(),+ ASIO_MOVE_CAST(StackAllocator)(stack_allocator),+ ASIO_MOVE_CAST(F)(function))))+{+ return async_initiate<CompletionToken,+ typename detail::spawn_signature<+ typename result_of<F(basic_yield_context<Executor>)>::type>::type>(+ detail::initiate_spawn<Executor>(ex), token, allocator_arg_t(),+ ASIO_MOVE_CAST(StackAllocator)(stack_allocator),+ ASIO_MOVE_CAST(F)(function));+}++template <typename ExecutionContext, typename StackAllocator, typename F,+ ASIO_COMPLETION_TOKEN_FOR(typename detail::spawn_signature<+ typename result_of<F(basic_yield_context<+ typename ExecutionContext::executor_type>)>::type>::type)+ CompletionToken>+inline ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX(CompletionToken,+ typename detail::spawn_signature<+ typename result_of<F(basic_yield_context<+ typename ExecutionContext::executor_type>)>::type>::type)+spawn(ExecutionContext& ctx, allocator_arg_t,+ ASIO_MOVE_ARG(StackAllocator) stack_allocator,+ ASIO_MOVE_ARG(F) function,+ ASIO_MOVE_ARG(CompletionToken) token,+ typename constraint<+ is_convertible<ExecutionContext&, execution_context&>::value+ >::type)+ ASIO_INITFN_AUTO_RESULT_TYPE_SUFFIX((+ async_initiate<CompletionToken,+ typename detail::spawn_signature<+ typename result_of<F(basic_yield_context<+ typename ExecutionContext::executor_type>)>::type>::type>(+ declval<detail::initiate_spawn<+ typename ExecutionContext::executor_type> >(),+ token, allocator_arg_t(),+ ASIO_MOVE_CAST(StackAllocator)(stack_allocator),+ ASIO_MOVE_CAST(F)(function))))+{+ return (spawn)(ctx.get_executor(), allocator_arg_t(),+ ASIO_MOVE_CAST(StackAllocator)(stack_allocator),+ ASIO_MOVE_CAST(F)(function),+ ASIO_MOVE_CAST(CompletionToken)(token));+}++template <typename Executor, typename StackAllocator, typename F,+ ASIO_COMPLETION_TOKEN_FOR(typename detail::spawn_signature<+ typename result_of<F(basic_yield_context<Executor>)>::type>::type)+ CompletionToken>+inline ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX(CompletionToken,+ typename detail::spawn_signature<+ typename result_of<F(basic_yield_context<Executor>)>::type>::type)+spawn(const basic_yield_context<Executor>& ctx, allocator_arg_t,+ ASIO_MOVE_ARG(StackAllocator) stack_allocator,+ ASIO_MOVE_ARG(F) function,+ ASIO_MOVE_ARG(CompletionToken) token,+ typename constraint<+ is_executor<Executor>::value || execution::is_executor<Executor>::value+ >::type)+ ASIO_INITFN_AUTO_RESULT_TYPE_SUFFIX((+ async_initiate<CompletionToken,+ typename detail::spawn_signature<+ typename result_of<F(basic_yield_context<Executor>)>::type>::type>(+ declval<detail::initiate_spawn<Executor> >(),+ token, allocator_arg_t(),+ ASIO_MOVE_CAST(StackAllocator)(stack_allocator),+ ASIO_MOVE_CAST(F)(function))))+{+ return (spawn)(ctx.get_executor(), allocator_arg_t(),+ ASIO_MOVE_CAST(StackAllocator)(stack_allocator),+ ASIO_MOVE_CAST(F)(function),+ ASIO_MOVE_CAST(CompletionToken)(token));+}++#endif // defined(ASIO_HAS_BOOST_CONTEXT_FIBER)++#if defined(ASIO_HAS_BOOST_COROUTINE)++namespace detail {++template <typename Executor, typename Function, typename Handler>+class old_spawn_entry_point+{+public:+ template <typename F, typename H>+ old_spawn_entry_point(const Executor& ex,+ ASIO_MOVE_ARG(F) f, ASIO_MOVE_ARG(H) h)+ : executor_(ex),+ function_(ASIO_MOVE_CAST(F)(f)),+ handler_(ASIO_MOVE_CAST(H)(h))+ {+ }++ void operator()(spawned_thread_base* spawned_thread)+ {+ const basic_yield_context<Executor> yield(spawned_thread, executor_);+ this->call(yield,+ void_type<typename result_of<Function(+ basic_yield_context<Executor>)>::type>());+ }++private:+ void call(const basic_yield_context<Executor>& yield, void_type<void>)+ {+ function_(yield);+ ASIO_MOVE_OR_LVALUE(Handler)(handler_)();+ }++ template <typename T>+ void call(const basic_yield_context<Executor>& yield, void_type<T>)+ {+ ASIO_MOVE_OR_LVALUE(Handler)(handler_)(function_(yield));+ }++ Executor executor_;+ Function function_;+ Handler handler_;+};++inline void default_spawn_handler() {}++} // namespace detail++template <typename Function>+inline void spawn(ASIO_MOVE_ARG(Function) function,+ const boost::coroutines::attributes& attributes)+{+ typedef typename decay<Function>::type function_type;++ typename associated_executor<function_type>::type ex(+ (get_associated_executor)(function));++ asio::spawn(ex, ASIO_MOVE_CAST(Function)(function), attributes);+}++template <typename Handler, typename Function>+void spawn(ASIO_MOVE_ARG(Handler) handler,+ ASIO_MOVE_ARG(Function) function,+ const boost::coroutines::attributes& attributes,+ typename constraint<+ !is_executor<typename decay<Handler>::type>::value &&+ !execution::is_executor<typename decay<Handler>::type>::value &&+ !is_convertible<Handler&, execution_context&>::value>::type)+{+ typedef typename decay<Handler>::type handler_type;+ typedef typename decay<Function>::type function_type;+ typedef typename associated_executor<handler_type>::type executor_type;++ executor_type ex((get_associated_executor)(handler));++ (dispatch)(ex,+ detail::spawned_thread_resumer(+ detail::spawned_coroutine_thread::spawn(+ detail::old_spawn_entry_point<executor_type,+ function_type, void (*)()>(+ ex, ASIO_MOVE_CAST(Function)(function),+ &detail::default_spawn_handler), attributes)));+}++template <typename Executor, typename Function>+void spawn(basic_yield_context<Executor> ctx,+ ASIO_MOVE_ARG(Function) function,+ const boost::coroutines::attributes& attributes)+{+ typedef typename decay<Function>::type function_type;++ (dispatch)(ctx.get_executor(),+ detail::spawned_thread_resumer(+ detail::spawned_coroutine_thread::spawn(+ detail::old_spawn_entry_point<Executor,+ function_type, void (*)()>(ctx.get_executor(),+ ASIO_MOVE_CAST(Function)(function),+ &detail::default_spawn_handler), attributes)));+}++template <typename Function, typename Executor>+inline void spawn(const Executor& ex,+ ASIO_MOVE_ARG(Function) function,+ const boost::coroutines::attributes& attributes,+ typename constraint<+ is_executor<Executor>::value || execution::is_executor<Executor>::value+ >::type)+{+ asio::spawn(asio::strand<Executor>(ex),+ ASIO_MOVE_CAST(Function)(function), attributes);+}++template <typename Function, typename Executor>+inline void spawn(const strand<Executor>& ex,+ ASIO_MOVE_ARG(Function) function,+ const boost::coroutines::attributes& attributes)+{+ asio::spawn(asio::bind_executor(+ ex, &detail::default_spawn_handler),+ ASIO_MOVE_CAST(Function)(function), attributes);+}++#if !defined(ASIO_NO_TS_EXECUTORS)++template <typename Function>+inline void spawn(const asio::io_context::strand& s,+ ASIO_MOVE_ARG(Function) function,+ const boost::coroutines::attributes& attributes)+{+ asio::spawn(asio::bind_executor(+ s, &detail::default_spawn_handler),+ ASIO_MOVE_CAST(Function)(function), attributes);+}++#endif // !defined(ASIO_NO_TS_EXECUTORS)++template <typename Function, typename ExecutionContext>+inline void spawn(ExecutionContext& ctx,+ ASIO_MOVE_ARG(Function) function,+ const boost::coroutines::attributes& attributes,+ typename constraint<is_convertible<+ ExecutionContext&, execution_context&>::value>::type)+{+ asio::spawn(ctx.get_executor(),+ ASIO_MOVE_CAST(Function)(function), attributes);+}++#endif // defined(ASIO_HAS_BOOST_COROUTINE) } // namespace asio
link/modules/asio-standalone/asio/include/asio/impl/src.hpp view
@@ -2,7 +2,7 @@ // impl/src.hpp // ~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -19,6 +19,10 @@ # error Do not compile Asio library source with ASIO_HEADER_ONLY defined #endif +#include "asio/impl/any_completion_executor.ipp"+#include "asio/impl/any_io_executor.ipp"+#include "asio/impl/cancellation_signal.ipp"+#include "asio/impl/connect_pipe.ipp" #include "asio/impl/error.ipp" #include "asio/impl/error_code.ipp" #include "asio/impl/execution_context.ipp"@@ -35,15 +39,19 @@ #include "asio/detail/impl/epoll_reactor.ipp" #include "asio/detail/impl/eventfd_select_interrupter.ipp" #include "asio/detail/impl/handler_tracking.ipp"+#include "asio/detail/impl/io_uring_descriptor_service.ipp"+#include "asio/detail/impl/io_uring_file_service.ipp"+#include "asio/detail/impl/io_uring_socket_service_base.ipp"+#include "asio/detail/impl/io_uring_service.ipp" #include "asio/detail/impl/kqueue_reactor.ipp" #include "asio/detail/impl/null_event.ipp" #include "asio/detail/impl/pipe_select_interrupter.ipp" #include "asio/detail/impl/posix_event.ipp" #include "asio/detail/impl/posix_mutex.ipp"+#include "asio/detail/impl/posix_serial_port_service.ipp" #include "asio/detail/impl/posix_thread.ipp" #include "asio/detail/impl/posix_tss_ptr.ipp" #include "asio/detail/impl/reactive_descriptor_service.ipp"-#include "asio/detail/impl/reactive_serial_port_service.ipp" #include "asio/detail/impl/reactive_socket_service_base.ipp" #include "asio/detail/impl/resolver_service_base.ipp" #include "asio/detail/impl/scheduler.ipp"@@ -54,9 +62,11 @@ #include "asio/detail/impl/socket_select_interrupter.ipp" #include "asio/detail/impl/strand_executor_service.ipp" #include "asio/detail/impl/strand_service.ipp"+#include "asio/detail/impl/thread_context.ipp" #include "asio/detail/impl/throw_error.ipp" #include "asio/detail/impl/timer_queue_ptime.ipp" #include "asio/detail/impl/timer_queue_set.ipp"+#include "asio/detail/impl/win_iocp_file_service.ipp" #include "asio/detail/impl/win_iocp_handle_service.ipp" #include "asio/detail/impl/win_iocp_io_context.ipp" #include "asio/detail/impl/win_iocp_serial_port_service.ipp"@@ -72,6 +82,7 @@ #include "asio/detail/impl/winsock_init.ipp" #include "asio/execution/impl/bad_executor.ipp" #include "asio/execution/impl/receiver_invocation_error.ipp"+#include "asio/experimental/impl/channel_error.ipp" #include "asio/generic/detail/impl/endpoint.ipp" #include "asio/ip/impl/address.ipp" #include "asio/ip/impl/address_v4.ipp"
link/modules/asio-standalone/asio/include/asio/impl/system_context.hpp view
@@ -2,7 +2,7 @@ // impl/system_context.hpp // ~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/impl/system_context.ipp view
@@ -2,7 +2,7 @@ // impl/system_context.ipp // ~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/impl/system_executor.hpp view
@@ -2,7 +2,7 @@ // impl/system_executor.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -17,7 +17,6 @@ #include "asio/detail/executor_op.hpp" #include "asio/detail/global.hpp"-#include "asio/detail/recycling_allocator.hpp" #include "asio/detail/type_traits.hpp" #include "asio/system_context.hpp"
link/modules/asio-standalone/asio/include/asio/impl/thread_pool.hpp view
@@ -2,7 +2,7 @@ // impl/thread_pool.hpp // ~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -20,7 +20,6 @@ #include "asio/detail/executor_op.hpp" #include "asio/detail/fenced_block.hpp" #include "asio/detail/non_const_lvalue.hpp"-#include "asio/detail/recycling_allocator.hpp" #include "asio/detail/type_traits.hpp" #include "asio/execution_context.hpp" @@ -76,11 +75,16 @@ { if (this != &other) {+ thread_pool* old_thread_pool = pool_; pool_ = other.pool_; allocator_ = std::move(other.allocator_); bits_ = other.bits_; if (Bits & outstanding_work_tracked)+ { other.pool_ = 0;+ if (old_thread_pool)+ old_thread_pool->scheduler_.work_finished();+ } } return *this; }
link/modules/asio-standalone/asio/include/asio/impl/thread_pool.ipp view
@@ -2,7 +2,7 @@ // impl/thread_pool.ipp // ~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -98,6 +98,7 @@ { stop(); join();+ shutdown(); } void thread_pool::stop()@@ -114,11 +115,11 @@ void thread_pool::join() {- if (!threads_.empty())- {+ if (num_threads_) scheduler_.work_finished();++ if (!threads_.empty()) threads_.join();- } } detail::scheduler& thread_pool::add_scheduler(detail::scheduler* s)
link/modules/asio-standalone/asio/include/asio/impl/use_awaitable.hpp view
@@ -2,7 +2,7 @@ // impl/use_awaitable.hpp // ~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -17,6 +17,7 @@ #include "asio/detail/config.hpp" #include "asio/async_result.hpp"+#include "asio/cancellation_signal.hpp" #include "asio/detail/push_options.hpp" @@ -32,8 +33,9 @@ typedef awaitable<T, Executor> awaitable_type; // Construct from the entry point of a new thread of execution.- awaitable_handler_base(awaitable<void, Executor> a, const Executor& ex)- : awaitable_thread<Executor>(std::move(a), ex)+ awaitable_handler_base(awaitable<awaitable_thread_entry_point, Executor> a,+ const Executor& ex, cancellation_slot pcs, cancellation_state cs)+ : awaitable_thread<Executor>(std::move(a), ex, pcs, cs) { } @@ -46,7 +48,8 @@ protected: awaitable_frame<T, Executor>* frame() noexcept {- return static_cast<awaitable_frame<T, Executor>*>(this->top_of_stack_);+ return static_cast<awaitable_frame<T, Executor>*>(+ this->entry_point()->top_of_stack_); } }; @@ -64,6 +67,7 @@ { this->frame()->attach_thread(this); this->frame()->return_void();+ this->frame()->clear_cancellation_slot(); this->frame()->pop_frame(); this->pump(); }@@ -83,6 +87,7 @@ this->frame()->set_error(ec); else this->frame()->return_void();+ this->frame()->clear_cancellation_slot(); this->frame()->pop_frame(); this->pump(); }@@ -102,6 +107,7 @@ this->frame()->set_except(ex); else this->frame()->return_void();+ this->frame()->clear_cancellation_slot(); this->frame()->pop_frame(); this->pump(); }@@ -119,6 +125,7 @@ { this->frame()->attach_thread(this); this->frame()->return_value(std::forward<Arg>(arg));+ this->frame()->clear_cancellation_slot(); this->frame()->pop_frame(); this->pump(); }@@ -139,6 +146,7 @@ this->frame()->set_error(ec); else this->frame()->return_value(std::forward<Arg>(arg));+ this->frame()->clear_cancellation_slot(); this->frame()->pop_frame(); this->pump(); }@@ -159,6 +167,7 @@ this->frame()->set_except(ex); else this->frame()->return_value(std::forward<Arg>(arg));+ this->frame()->clear_cancellation_slot(); this->frame()->pop_frame(); this->pump(); }@@ -177,6 +186,7 @@ { this->frame()->attach_thread(this); this->frame()->return_values(std::forward<Args>(args)...);+ this->frame()->clear_cancellation_slot(); this->frame()->pop_frame(); this->pump(); }@@ -198,6 +208,7 @@ this->frame()->set_error(ec); else this->frame()->return_values(std::forward<Args>(args)...);+ this->frame()->clear_cancellation_slot(); this->frame()->pop_frame(); this->pump(); }@@ -219,6 +230,7 @@ this->frame()->set_except(ex); else this->frame()->return_values(std::forward<Args>(args)...);+ this->frame()->clear_cancellation_slot(); this->frame()->pop_frame(); this->pump(); }@@ -228,6 +240,19 @@ #if !defined(GENERATING_DOCUMENTATION) +#if defined(_MSC_VER)+template <typename T>+T dummy_return()+{+ return std::move(*static_cast<T*>(nullptr));+}++template <>+inline void dummy_return()+{+}+#endif // defined(_MSC_VER)+ template <typename Executor, typename R, typename... Args> class async_result<use_awaitable_t<Executor>, R(Args...)> {@@ -236,31 +261,28 @@ Executor, typename decay<Args>::type...> handler_type; typedef typename handler_type::awaitable_type return_type; -#if defined(_MSC_VER)- template <typename T>- static T dummy_return()+ template <typename Initiation, typename... InitArgs>+#if defined(__APPLE_CC__) && (__clang_major__ == 13)+ __attribute__((noinline))+#endif // defined(__APPLE_CC__) && (__clang_major__ == 13)+ static handler_type* do_init(+ detail::awaitable_frame_base<Executor>* frame, Initiation& initiation,+ use_awaitable_t<Executor> u, InitArgs&... args) {- return std::move(*static_cast<T*>(nullptr));+ (void)u;+ ASIO_HANDLER_LOCATION((u.file_name_, u.line_, u.function_name_));+ handler_type handler(frame->detach_thread());+ std::move(initiation)(std::move(handler), std::move(args)...);+ return nullptr; } - template <>- static void dummy_return()- {- }-#endif // defined(_MSC_VER)- template <typename Initiation, typename... InitArgs> static return_type initiate(Initiation initiation, use_awaitable_t<Executor> u, InitArgs... args) {- (void)u;-- co_await [&](auto* frame)+ co_await [&] (auto* frame) {- ASIO_HANDLER_LOCATION((u.file_name_, u.line_, u.function_name_));- handler_type handler(frame->detach_thread());- std::move(initiation)(std::move(handler), std::move(args)...);- return static_cast<handler_type*>(nullptr);+ return do_init(frame, initiation, u, args...); }; for (;;) {} // Never reached.
link/modules/asio-standalone/asio/include/asio/impl/use_future.hpp view
@@ -2,7 +2,7 @@ // impl/use_future.hpp // ~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -211,6 +211,11 @@ { } + execution_context& query(execution::context_t) const ASIO_NOEXCEPT+ {+ return asio::query(system_executor(), execution::context);+ }+ static ASIO_CONSTEXPR Blocking query(execution::blocking_t) { return Blocking();@@ -231,9 +236,14 @@ template <typename F> void execute(ASIO_MOVE_ARG(F) f) const {+#if defined(ASIO_NO_DEPRECATED)+ asio::require(system_executor(), Blocking()).execute(+ promise_invoker<T, F>(p_, ASIO_MOVE_CAST(F)(f)));+#else // defined(ASIO_NO_DEPRECATED) execution::execute( asio::require(system_executor(), Blocking()), promise_invoker<T, F>(p_, ASIO_MOVE_CAST(F)(f)));+#endif // defined(ASIO_NO_DEPRECATED) } #if !defined(ASIO_NO_TS_EXECUTORS)@@ -963,7 +973,7 @@ #endif // !defined(ASIO_HAS_DEDUCED_EXECUTE_MEMBER_TRAIT) -#if !defined(ASIO_HAS_DEDUCED_QUERY_STATIC_CONSTEXPR_TRAIT)+#if !defined(ASIO_HAS_DEDUCED_QUERY_STATIC_CONSTEXPR_MEMBER_TRAIT) template <typename T, typename Blocking, typename Property> struct query_static_constexpr_member<@@ -987,7 +997,22 @@ } }; -#endif // !defined(ASIO_HAS_DEDUCED_QUERY_STATIC_CONSTEXPR_TRAIT)+#endif // !defined(ASIO_HAS_DEDUCED_QUERY_STATIC_CONSTEXPR_MEMBER_TRAIT)++#if !defined(ASIO_HAS_DEDUCED_QUERY_MEMBER_TRAIT)++template <typename T, typename Blocking>+struct query_member<+ asio::detail::promise_executor<T, Blocking>,+ execution::context_t+ >+{+ ASIO_STATIC_CONSTEXPR(bool, is_valid = true);+ ASIO_STATIC_CONSTEXPR(bool, is_noexcept = true);+ typedef asio::system_context& result_type;+};++#endif // !defined(ASIO_HAS_DEDUCED_QUERY_MEMBER_TRAIT) #if !defined(ASIO_HAS_DEDUCED_REQUIRE_MEMBER_TRAIT)
link/modules/asio-standalone/asio/include/asio/impl/write.hpp view
@@ -2,7 +2,7 @@ // impl/write.hpp // ~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -15,11 +15,10 @@ # pragma once #endif // defined(_MSC_VER) && (_MSC_VER >= 1200) -#include "asio/associated_allocator.hpp"-#include "asio/associated_executor.hpp"+#include "asio/associator.hpp" #include "asio/buffer.hpp"-#include "asio/completion_condition.hpp" #include "asio/detail/array_fwd.hpp"+#include "asio/detail/base_from_cancellation_state.hpp" #include "asio/detail/base_from_completion_cond.hpp" #include "asio/detail/bind_handler.hpp" #include "asio/detail/consuming_buffers.hpp"@@ -40,7 +39,7 @@ { template <typename SyncWriteStream, typename ConstBufferSequence, typename ConstBufferIterator, typename CompletionCondition>- std::size_t write_buffer_sequence(SyncWriteStream& s,+ std::size_t write(SyncWriteStream& s, const ConstBufferSequence& buffers, const ConstBufferIterator&, CompletionCondition completion_condition, asio::error_code& ec) {@@ -55,7 +54,7 @@ else break; }- return tmp.total_consumed();;+ return tmp.total_consumed(); } } // namespace detail @@ -63,20 +62,20 @@ typename CompletionCondition> inline std::size_t write(SyncWriteStream& s, const ConstBufferSequence& buffers, CompletionCondition completion_condition, asio::error_code& ec,- typename enable_if<+ typename constraint< is_const_buffer_sequence<ConstBufferSequence>::value- >::type*)+ >::type) {- return detail::write_buffer_sequence(s, buffers,+ return detail::write(s, buffers, asio::buffer_sequence_begin(buffers), ASIO_MOVE_CAST(CompletionCondition)(completion_condition), ec); } template <typename SyncWriteStream, typename ConstBufferSequence> inline std::size_t write(SyncWriteStream& s, const ConstBufferSequence& buffers,- typename enable_if<+ typename constraint< is_const_buffer_sequence<ConstBufferSequence>::value- >::type*)+ >::type) { asio::error_code ec; std::size_t bytes_transferred = write(s, buffers, transfer_all(), ec);@@ -87,9 +86,9 @@ template <typename SyncWriteStream, typename ConstBufferSequence> inline std::size_t write(SyncWriteStream& s, const ConstBufferSequence& buffers, asio::error_code& ec,- typename enable_if<+ typename constraint< is_const_buffer_sequence<ConstBufferSequence>::value- >::type*)+ >::type) { return write(s, buffers, transfer_all(), ec); }@@ -98,9 +97,9 @@ typename CompletionCondition> inline std::size_t write(SyncWriteStream& s, const ConstBufferSequence& buffers, CompletionCondition completion_condition,- typename enable_if<+ typename constraint< is_const_buffer_sequence<ConstBufferSequence>::value- >::type*)+ >::type) { asio::error_code ec; std::size_t bytes_transferred = write(s, buffers,@@ -116,10 +115,12 @@ std::size_t write(SyncWriteStream& s, ASIO_MOVE_ARG(DynamicBuffer_v1) buffers, CompletionCondition completion_condition, asio::error_code& ec,- typename enable_if<+ typename constraint< is_dynamic_buffer_v1<typename decay<DynamicBuffer_v1>::type>::value- && !is_dynamic_buffer_v2<typename decay<DynamicBuffer_v1>::type>::value- >::type*)+ >::type,+ typename constraint<+ !is_dynamic_buffer_v2<typename decay<DynamicBuffer_v1>::type>::value+ >::type) { typename decay<DynamicBuffer_v1>::type b( ASIO_MOVE_CAST(DynamicBuffer_v1)(buffers));@@ -133,10 +134,12 @@ template <typename SyncWriteStream, typename DynamicBuffer_v1> inline std::size_t write(SyncWriteStream& s, ASIO_MOVE_ARG(DynamicBuffer_v1) buffers,- typename enable_if<+ typename constraint< is_dynamic_buffer_v1<typename decay<DynamicBuffer_v1>::type>::value- && !is_dynamic_buffer_v2<typename decay<DynamicBuffer_v1>::type>::value- >::type*)+ >::type,+ typename constraint<+ !is_dynamic_buffer_v2<typename decay<DynamicBuffer_v1>::type>::value+ >::type) { asio::error_code ec; std::size_t bytes_transferred = write(s,@@ -150,10 +153,12 @@ inline std::size_t write(SyncWriteStream& s, ASIO_MOVE_ARG(DynamicBuffer_v1) buffers, asio::error_code& ec,- typename enable_if<+ typename constraint< is_dynamic_buffer_v1<typename decay<DynamicBuffer_v1>::type>::value- && !is_dynamic_buffer_v2<typename decay<DynamicBuffer_v1>::type>::value- >::type*)+ >::type,+ typename constraint<+ !is_dynamic_buffer_v2<typename decay<DynamicBuffer_v1>::type>::value+ >::type) { return write(s, ASIO_MOVE_CAST(DynamicBuffer_v1)(buffers), transfer_all(), ec);@@ -164,10 +169,12 @@ inline std::size_t write(SyncWriteStream& s, ASIO_MOVE_ARG(DynamicBuffer_v1) buffers, CompletionCondition completion_condition,- typename enable_if<+ typename constraint< is_dynamic_buffer_v1<typename decay<DynamicBuffer_v1>::type>::value- && !is_dynamic_buffer_v2<typename decay<DynamicBuffer_v1>::type>::value- >::type*)+ >::type,+ typename constraint<+ !is_dynamic_buffer_v2<typename decay<DynamicBuffer_v1>::type>::value+ >::type) { asio::error_code ec; std::size_t bytes_transferred = write(s,@@ -223,9 +230,9 @@ typename CompletionCondition> std::size_t write(SyncWriteStream& s, DynamicBuffer_v2 buffers, CompletionCondition completion_condition, asio::error_code& ec,- typename enable_if<+ typename constraint< is_dynamic_buffer_v2<DynamicBuffer_v2>::value- >::type*)+ >::type) { std::size_t bytes_transferred = write(s, buffers.data(0, buffers.size()), ASIO_MOVE_CAST(CompletionCondition)(completion_condition), ec);@@ -235,9 +242,9 @@ template <typename SyncWriteStream, typename DynamicBuffer_v2> inline std::size_t write(SyncWriteStream& s, DynamicBuffer_v2 buffers,- typename enable_if<+ typename constraint< is_dynamic_buffer_v2<DynamicBuffer_v2>::value- >::type*)+ >::type) { asio::error_code ec; std::size_t bytes_transferred = write(s,@@ -250,9 +257,9 @@ template <typename SyncWriteStream, typename DynamicBuffer_v2> inline std::size_t write(SyncWriteStream& s, DynamicBuffer_v2 buffers, asio::error_code& ec,- typename enable_if<+ typename constraint< is_dynamic_buffer_v2<DynamicBuffer_v2>::value- >::type*)+ >::type) { return write(s, ASIO_MOVE_CAST(DynamicBuffer_v2)(buffers), transfer_all(), ec);@@ -262,9 +269,9 @@ typename CompletionCondition> inline std::size_t write(SyncWriteStream& s, DynamicBuffer_v2 buffers, CompletionCondition completion_condition,- typename enable_if<+ typename constraint< is_dynamic_buffer_v2<DynamicBuffer_v2>::value- >::type*)+ >::type) { asio::error_code ec; std::size_t bytes_transferred = write(s,@@ -280,13 +287,15 @@ typename ConstBufferIterator, typename CompletionCondition, typename WriteHandler> class write_op- : detail::base_from_completion_cond<CompletionCondition>+ : public base_from_cancellation_state<WriteHandler>,+ base_from_completion_cond<CompletionCondition> { public: write_op(AsyncWriteStream& stream, const ConstBufferSequence& buffers, CompletionCondition& completion_condition, WriteHandler& handler)- : detail::base_from_completion_cond<- CompletionCondition>(completion_condition),+ : base_from_cancellation_state<WriteHandler>(+ handler, enable_partial_cancellation()),+ base_from_completion_cond<CompletionCondition>(completion_condition), stream_(stream), buffers_(buffers), start_(0),@@ -296,7 +305,8 @@ #if defined(ASIO_HAS_MOVE) write_op(const write_op& other)- : detail::base_from_completion_cond<CompletionCondition>(other),+ : base_from_cancellation_state<WriteHandler>(other),+ base_from_completion_cond<CompletionCondition>(other), stream_(other.stream_), buffers_(other.buffers_), start_(other.start_),@@ -305,8 +315,11 @@ } write_op(write_op&& other)- : detail::base_from_completion_cond<CompletionCondition>(- ASIO_MOVE_CAST(detail::base_from_completion_cond<+ : base_from_cancellation_state<WriteHandler>(+ ASIO_MOVE_CAST(base_from_cancellation_state<+ WriteHandler>)(other)),+ base_from_completion_cond<CompletionCondition>(+ ASIO_MOVE_CAST(base_from_completion_cond< CompletionCondition>)(other)), stream_(other.stream_), buffers_(ASIO_MOVE_CAST(buffers_type)(other.buffers_)),@@ -316,7 +329,7 @@ } #endif // defined(ASIO_HAS_MOVE) - void operator()(const asio::error_code& ec,+ void operator()(asio::error_code ec, std::size_t bytes_transferred, int start = 0) { std::size_t max_size;@@ -324,7 +337,7 @@ { case 1: max_size = this->check_for_completion(ec, buffers_.total_consumed());- do+ for (;;) { { ASIO_HANDLER_LOCATION((__FILE__, __LINE__, "async_write"));@@ -336,9 +349,18 @@ if ((!ec && bytes_transferred == 0) || buffers_.empty()) break; max_size = this->check_for_completion(ec, buffers_.total_consumed());- } while (max_size > 0);+ if (max_size == 0)+ break;+ if (this->cancelled() != cancellation_type::none)+ {+ ec = error::operation_aborted;+ break;+ }+ } - handler_(ec, buffers_.total_consumed());+ ASIO_MOVE_OR_LVALUE(WriteHandler)(handler_)(+ static_cast<const asio::error_code&>(ec),+ static_cast<const std::size_t&>(buffers_.total_consumed())); } } @@ -429,7 +451,7 @@ template <typename AsyncWriteStream, typename ConstBufferSequence, typename ConstBufferIterator, typename CompletionCondition, typename WriteHandler>- inline void start_write_buffer_sequence_op(AsyncWriteStream& stream,+ inline void start_write_op(AsyncWriteStream& stream, const ConstBufferSequence& buffers, const ConstBufferIterator&, CompletionCondition& completion_condition, WriteHandler& handler) {@@ -440,12 +462,12 @@ } template <typename AsyncWriteStream>- class initiate_async_write_buffer_sequence+ class initiate_async_write { public: typedef typename AsyncWriteStream::executor_type executor_type; - explicit initiate_async_write_buffer_sequence(AsyncWriteStream& stream)+ explicit initiate_async_write(AsyncWriteStream& stream) : stream_(stream) { }@@ -467,7 +489,7 @@ non_const_lvalue<WriteHandler> handler2(handler); non_const_lvalue<CompletionCondition> completion_cond2(completion_cond);- start_write_buffer_sequence_op(stream_, buffers,+ start_write_op(stream_, buffers, asio::buffer_sequence_begin(buffers), completion_cond2.value, handler2.value); }@@ -479,42 +501,33 @@ #if !defined(GENERATING_DOCUMENTATION) -template <typename AsyncWriteStream, typename ConstBufferSequence,+template <template <typename, typename> class Associator,+ typename AsyncWriteStream, typename ConstBufferSequence, typename ConstBufferIterator, typename CompletionCondition,- typename WriteHandler, typename Allocator>-struct associated_allocator<+ typename WriteHandler, typename DefaultCandidate>+struct associator<Associator, detail::write_op<AsyncWriteStream, ConstBufferSequence, ConstBufferIterator, CompletionCondition, WriteHandler>,- Allocator>+ DefaultCandidate>+ : Associator<WriteHandler, DefaultCandidate> {- typedef typename associated_allocator<WriteHandler, Allocator>::type type;-- static type get(- const detail::write_op<AsyncWriteStream, ConstBufferSequence,- ConstBufferIterator, CompletionCondition, WriteHandler>& h,- const Allocator& a = Allocator()) ASIO_NOEXCEPT+ static typename Associator<WriteHandler, DefaultCandidate>::type+ get(const detail::write_op<AsyncWriteStream, ConstBufferSequence,+ ConstBufferIterator, CompletionCondition, WriteHandler>& h)+ ASIO_NOEXCEPT {- return associated_allocator<WriteHandler, Allocator>::get(h.handler_, a);+ return Associator<WriteHandler, DefaultCandidate>::get(h.handler_); }-}; -template <typename AsyncWriteStream, typename ConstBufferSequence,- typename ConstBufferIterator, typename CompletionCondition,- typename WriteHandler, typename Executor>-struct associated_executor<- detail::write_op<AsyncWriteStream, ConstBufferSequence,- ConstBufferIterator, CompletionCondition, WriteHandler>,- Executor>- : detail::associated_executor_forwarding_base<WriteHandler, Executor>-{- typedef typename associated_executor<WriteHandler, Executor>::type type;-- static type get(- const detail::write_op<AsyncWriteStream, ConstBufferSequence,+ static ASIO_AUTO_RETURN_TYPE_PREFIX2(+ typename Associator<WriteHandler, DefaultCandidate>::type)+ get(const detail::write_op<AsyncWriteStream, ConstBufferSequence, ConstBufferIterator, CompletionCondition, WriteHandler>& h,- const Executor& ex = Executor()) ASIO_NOEXCEPT+ const DefaultCandidate& c) ASIO_NOEXCEPT+ ASIO_AUTO_RETURN_TYPE_SUFFIX((+ Associator<WriteHandler, DefaultCandidate>::get(h.handler_, c))) {- return associated_executor<WriteHandler, Executor>::get(h.handler_, ex);+ return Associator<WriteHandler, DefaultCandidate>::get(h.handler_, c); } }; @@ -523,38 +536,49 @@ template <typename AsyncWriteStream, typename ConstBufferSequence, typename CompletionCondition, ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code,- std::size_t)) WriteHandler>-inline ASIO_INITFN_AUTO_RESULT_TYPE(WriteHandler,+ std::size_t)) WriteToken>+inline ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX(WriteToken, void (asio::error_code, std::size_t)) async_write(AsyncWriteStream& s, const ConstBufferSequence& buffers, CompletionCondition completion_condition,- ASIO_MOVE_ARG(WriteHandler) handler,- typename enable_if<+ ASIO_MOVE_ARG(WriteToken) token,+ typename constraint< is_const_buffer_sequence<ConstBufferSequence>::value- >::type*)+ >::type)+ ASIO_INITFN_AUTO_RESULT_TYPE_SUFFIX((+ async_initiate<WriteToken,+ void (asio::error_code, std::size_t)>(+ declval<detail::initiate_async_write<AsyncWriteStream> >(),+ token, buffers,+ ASIO_MOVE_CAST(CompletionCondition)(completion_condition)))) {- return async_initiate<WriteHandler,+ return async_initiate<WriteToken, void (asio::error_code, std::size_t)>(- detail::initiate_async_write_buffer_sequence<AsyncWriteStream>(s),- handler, buffers,+ detail::initiate_async_write<AsyncWriteStream>(s),+ token, buffers, ASIO_MOVE_CAST(CompletionCondition)(completion_condition)); } template <typename AsyncWriteStream, typename ConstBufferSequence, ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code,- std::size_t)) WriteHandler>-inline ASIO_INITFN_AUTO_RESULT_TYPE(WriteHandler,+ std::size_t)) WriteToken>+inline ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX(WriteToken, void (asio::error_code, std::size_t)) async_write(AsyncWriteStream& s, const ConstBufferSequence& buffers,- ASIO_MOVE_ARG(WriteHandler) handler,- typename enable_if<+ ASIO_MOVE_ARG(WriteToken) token,+ typename constraint< is_const_buffer_sequence<ConstBufferSequence>::value- >::type*)+ >::type)+ ASIO_INITFN_AUTO_RESULT_TYPE_SUFFIX((+ async_initiate<WriteToken,+ void (asio::error_code, std::size_t)>(+ declval<detail::initiate_async_write<AsyncWriteStream> >(),+ token, buffers, transfer_all()))) {- return async_initiate<WriteHandler,+ return async_initiate<WriteToken, void (asio::error_code, std::size_t)>(- detail::initiate_async_write_buffer_sequence<AsyncWriteStream>(s),- handler, buffers, transfer_all());+ detail::initiate_async_write<AsyncWriteStream>(s),+ token, buffers, transfer_all()); } #if !defined(ASIO_NO_DYNAMIC_BUFFER_V1)@@ -609,7 +633,8 @@ ASIO_MOVE_CAST(write_dynbuf_v1_op)(*this)); return; default: buffers_.consume(bytes_transferred);- handler_(ec, static_cast<const std::size_t&>(bytes_transferred));+ ASIO_MOVE_OR_LVALUE(WriteHandler)(handler_)(ec,+ static_cast<const std::size_t&>(bytes_transferred)); } } @@ -733,40 +758,32 @@ #if !defined(GENERATING_DOCUMENTATION) -template <typename AsyncWriteStream, typename DynamicBuffer_v1,- typename CompletionCondition, typename WriteHandler, typename Allocator>-struct associated_allocator<+template <template <typename, typename> class Associator,+ typename AsyncWriteStream, typename DynamicBuffer_v1,+ typename CompletionCondition, typename WriteHandler,+ typename DefaultCandidate>+struct associator<Associator, detail::write_dynbuf_v1_op<AsyncWriteStream, DynamicBuffer_v1, CompletionCondition, WriteHandler>,- Allocator>+ DefaultCandidate>+ : Associator<WriteHandler, DefaultCandidate> {- typedef typename associated_allocator<WriteHandler, Allocator>::type type;-- static type get(- const detail::write_dynbuf_v1_op<AsyncWriteStream,- DynamicBuffer_v1, CompletionCondition, WriteHandler>& h,- const Allocator& a = Allocator()) ASIO_NOEXCEPT+ static typename Associator<WriteHandler, DefaultCandidate>::type+ get(const detail::write_dynbuf_v1_op<AsyncWriteStream, DynamicBuffer_v1,+ CompletionCondition, WriteHandler>& h) ASIO_NOEXCEPT {- return associated_allocator<WriteHandler, Allocator>::get(h.handler_, a);+ return Associator<WriteHandler, DefaultCandidate>::get(h.handler_); }-}; -template <typename AsyncWriteStream, typename DynamicBuffer_v1,- typename CompletionCondition, typename WriteHandler, typename Executor>-struct associated_executor<- detail::write_dynbuf_v1_op<AsyncWriteStream,- DynamicBuffer_v1, CompletionCondition, WriteHandler>,- Executor>- : detail::associated_executor_forwarding_base<WriteHandler, Executor>-{- typedef typename associated_executor<WriteHandler, Executor>::type type;-- static type get(- const detail::write_dynbuf_v1_op<AsyncWriteStream,+ static ASIO_AUTO_RETURN_TYPE_PREFIX2(+ typename Associator<WriteHandler, DefaultCandidate>::type)+ get(const detail::write_dynbuf_v1_op<AsyncWriteStream, DynamicBuffer_v1, CompletionCondition, WriteHandler>& h,- const Executor& ex = Executor()) ASIO_NOEXCEPT+ const DefaultCandidate& c) ASIO_NOEXCEPT+ ASIO_AUTO_RETURN_TYPE_SUFFIX((+ Associator<WriteHandler, DefaultCandidate>::get(h.handler_, c))) {- return associated_executor<WriteHandler, Executor>::get(h.handler_, ex);+ return Associator<WriteHandler, DefaultCandidate>::get(h.handler_, c); } }; @@ -774,41 +791,59 @@ template <typename AsyncWriteStream, typename DynamicBuffer_v1, ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code,- std::size_t)) WriteHandler>-inline ASIO_INITFN_AUTO_RESULT_TYPE(WriteHandler,+ std::size_t)) WriteToken>+inline ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX(WriteToken, void (asio::error_code, std::size_t)) async_write(AsyncWriteStream& s, ASIO_MOVE_ARG(DynamicBuffer_v1) buffers,- ASIO_MOVE_ARG(WriteHandler) handler,- typename enable_if<+ ASIO_MOVE_ARG(WriteToken) token,+ typename constraint< is_dynamic_buffer_v1<typename decay<DynamicBuffer_v1>::type>::value- && !is_dynamic_buffer_v2<typename decay<DynamicBuffer_v1>::type>::value- >::type*)+ >::type,+ typename constraint<+ !is_dynamic_buffer_v2<typename decay<DynamicBuffer_v1>::type>::value+ >::type)+ ASIO_INITFN_AUTO_RESULT_TYPE_SUFFIX((+ async_initiate<WriteToken,+ void (asio::error_code, std::size_t)>(+ declval<detail::initiate_async_write_dynbuf_v1<AsyncWriteStream> >(),+ token, ASIO_MOVE_CAST(DynamicBuffer_v1)(buffers),+ transfer_all()))) {- return async_write(s,- ASIO_MOVE_CAST(DynamicBuffer_v1)(buffers),- transfer_all(), ASIO_MOVE_CAST(WriteHandler)(handler));+ return async_initiate<WriteToken,+ void (asio::error_code, std::size_t)>(+ detail::initiate_async_write_dynbuf_v1<AsyncWriteStream>(s),+ token, ASIO_MOVE_CAST(DynamicBuffer_v1)(buffers),+ transfer_all()); } template <typename AsyncWriteStream, typename DynamicBuffer_v1, typename CompletionCondition, ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code,- std::size_t)) WriteHandler>-inline ASIO_INITFN_AUTO_RESULT_TYPE(WriteHandler,+ std::size_t)) WriteToken>+inline ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX(WriteToken, void (asio::error_code, std::size_t)) async_write(AsyncWriteStream& s, ASIO_MOVE_ARG(DynamicBuffer_v1) buffers, CompletionCondition completion_condition,- ASIO_MOVE_ARG(WriteHandler) handler,- typename enable_if<+ ASIO_MOVE_ARG(WriteToken) token,+ typename constraint< is_dynamic_buffer_v1<typename decay<DynamicBuffer_v1>::type>::value- && !is_dynamic_buffer_v2<typename decay<DynamicBuffer_v1>::type>::value- >::type*)+ >::type,+ typename constraint<+ !is_dynamic_buffer_v2<typename decay<DynamicBuffer_v1>::type>::value+ >::type)+ ASIO_INITFN_AUTO_RESULT_TYPE_SUFFIX((+ async_initiate<WriteToken,+ void (asio::error_code, std::size_t)>(+ declval<detail::initiate_async_write_dynbuf_v1<AsyncWriteStream> >(),+ token, ASIO_MOVE_CAST(DynamicBuffer_v1)(buffers),+ ASIO_MOVE_CAST(CompletionCondition)(completion_condition)))) {- return async_initiate<WriteHandler,+ return async_initiate<WriteToken, void (asio::error_code, std::size_t)>( detail::initiate_async_write_dynbuf_v1<AsyncWriteStream>(s),- handler, ASIO_MOVE_CAST(DynamicBuffer_v1)(buffers),+ token, ASIO_MOVE_CAST(DynamicBuffer_v1)(buffers), ASIO_MOVE_CAST(CompletionCondition)(completion_condition)); } @@ -817,31 +852,38 @@ template <typename AsyncWriteStream, typename Allocator, ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code,- std::size_t)) WriteHandler>-inline ASIO_INITFN_AUTO_RESULT_TYPE(WriteHandler,+ std::size_t)) WriteToken>+inline ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX(WriteToken, void (asio::error_code, std::size_t)) async_write(AsyncWriteStream& s, asio::basic_streambuf<Allocator>& b,- ASIO_MOVE_ARG(WriteHandler) handler)+ ASIO_MOVE_ARG(WriteToken) token)+ ASIO_INITFN_AUTO_RESULT_TYPE_SUFFIX((+ async_write(s, basic_streambuf_ref<Allocator>(b),+ ASIO_MOVE_CAST(WriteToken)(token)))) { return async_write(s, basic_streambuf_ref<Allocator>(b),- ASIO_MOVE_CAST(WriteHandler)(handler));+ ASIO_MOVE_CAST(WriteToken)(token)); } template <typename AsyncWriteStream, typename Allocator, typename CompletionCondition, ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code,- std::size_t)) WriteHandler>-inline ASIO_INITFN_AUTO_RESULT_TYPE(WriteHandler,+ std::size_t)) WriteToken>+inline ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX(WriteToken, void (asio::error_code, std::size_t)) async_write(AsyncWriteStream& s, asio::basic_streambuf<Allocator>& b, CompletionCondition completion_condition,- ASIO_MOVE_ARG(WriteHandler) handler)+ ASIO_MOVE_ARG(WriteToken) token)+ ASIO_INITFN_AUTO_RESULT_TYPE_SUFFIX((+ async_write(s, basic_streambuf_ref<Allocator>(b),+ ASIO_MOVE_CAST(CompletionCondition)(completion_condition),+ ASIO_MOVE_CAST(WriteToken)(token)))) { return async_write(s, basic_streambuf_ref<Allocator>(b), ASIO_MOVE_CAST(CompletionCondition)(completion_condition),- ASIO_MOVE_CAST(WriteHandler)(handler));+ ASIO_MOVE_CAST(WriteToken)(token)); } #endif // !defined(ASIO_NO_IOSTREAM)@@ -898,7 +940,8 @@ ASIO_MOVE_CAST(write_dynbuf_v2_op)(*this)); return; default: buffers_.consume(bytes_transferred);- handler_(ec, static_cast<const std::size_t&>(bytes_transferred));+ ASIO_MOVE_OR_LVALUE(WriteHandler)(handler_)(ec,+ static_cast<const std::size_t&>(bytes_transferred)); } } @@ -1022,40 +1065,32 @@ #if !defined(GENERATING_DOCUMENTATION) -template <typename AsyncWriteStream, typename DynamicBuffer_v2,- typename CompletionCondition, typename WriteHandler, typename Allocator>-struct associated_allocator<+template <template <typename, typename> class Associator,+ typename AsyncWriteStream, typename DynamicBuffer_v2,+ typename CompletionCondition, typename WriteHandler,+ typename DefaultCandidate>+struct associator<Associator, detail::write_dynbuf_v2_op<AsyncWriteStream, DynamicBuffer_v2, CompletionCondition, WriteHandler>,- Allocator>+ DefaultCandidate>+ : Associator<WriteHandler, DefaultCandidate> {- typedef typename associated_allocator<WriteHandler, Allocator>::type type;-- static type get(- const detail::write_dynbuf_v2_op<AsyncWriteStream,- DynamicBuffer_v2, CompletionCondition, WriteHandler>& h,- const Allocator& a = Allocator()) ASIO_NOEXCEPT+ static typename Associator<WriteHandler, DefaultCandidate>::type+ get(const detail::write_dynbuf_v2_op<AsyncWriteStream, DynamicBuffer_v2,+ CompletionCondition, WriteHandler>& h) ASIO_NOEXCEPT {- return associated_allocator<WriteHandler, Allocator>::get(h.handler_, a);+ return Associator<WriteHandler, DefaultCandidate>::get(h.handler_); }-}; -template <typename AsyncWriteStream, typename DynamicBuffer_v2,- typename CompletionCondition, typename WriteHandler, typename Executor>-struct associated_executor<- detail::write_dynbuf_v2_op<AsyncWriteStream,- DynamicBuffer_v2, CompletionCondition, WriteHandler>,- Executor>- : detail::associated_executor_forwarding_base<WriteHandler, Executor>-{- typedef typename associated_executor<WriteHandler, Executor>::type type;-- static type get(- const detail::write_dynbuf_v2_op<AsyncWriteStream,+ static ASIO_AUTO_RETURN_TYPE_PREFIX2(+ typename Associator<WriteHandler, DefaultCandidate>::type)+ get(const detail::write_dynbuf_v2_op<AsyncWriteStream, DynamicBuffer_v2, CompletionCondition, WriteHandler>& h,- const Executor& ex = Executor()) ASIO_NOEXCEPT+ const DefaultCandidate& c) ASIO_NOEXCEPT+ ASIO_AUTO_RETURN_TYPE_SUFFIX((+ Associator<WriteHandler, DefaultCandidate>::get(h.handler_, c))) {- return associated_executor<WriteHandler, Executor>::get(h.handler_, ex);+ return Associator<WriteHandler, DefaultCandidate>::get(h.handler_, c); } }; @@ -1063,37 +1098,51 @@ template <typename AsyncWriteStream, typename DynamicBuffer_v2, ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code,- std::size_t)) WriteHandler>-inline ASIO_INITFN_AUTO_RESULT_TYPE(WriteHandler,+ std::size_t)) WriteToken>+inline ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX(WriteToken, void (asio::error_code, std::size_t)) async_write(AsyncWriteStream& s, DynamicBuffer_v2 buffers,- ASIO_MOVE_ARG(WriteHandler) handler,- typename enable_if<+ ASIO_MOVE_ARG(WriteToken) token,+ typename constraint< is_dynamic_buffer_v2<DynamicBuffer_v2>::value- >::type*)+ >::type)+ ASIO_INITFN_AUTO_RESULT_TYPE_SUFFIX((+ async_initiate<WriteToken,+ void (asio::error_code, std::size_t)>(+ declval<detail::initiate_async_write_dynbuf_v2<AsyncWriteStream> >(),+ token, ASIO_MOVE_CAST(DynamicBuffer_v2)(buffers),+ transfer_all()))) {- return async_write(s,- ASIO_MOVE_CAST(DynamicBuffer_v2)(buffers),- transfer_all(), ASIO_MOVE_CAST(WriteHandler)(handler));+ return async_initiate<WriteToken,+ void (asio::error_code, std::size_t)>(+ detail::initiate_async_write_dynbuf_v2<AsyncWriteStream>(s),+ token, ASIO_MOVE_CAST(DynamicBuffer_v2)(buffers),+ transfer_all()); } template <typename AsyncWriteStream, typename DynamicBuffer_v2, typename CompletionCondition, ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code,- std::size_t)) WriteHandler>-inline ASIO_INITFN_AUTO_RESULT_TYPE(WriteHandler,+ std::size_t)) WriteToken>+inline ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX(WriteToken, void (asio::error_code, std::size_t)) async_write(AsyncWriteStream& s, DynamicBuffer_v2 buffers, CompletionCondition completion_condition,- ASIO_MOVE_ARG(WriteHandler) handler,- typename enable_if<+ ASIO_MOVE_ARG(WriteToken) token,+ typename constraint< is_dynamic_buffer_v2<DynamicBuffer_v2>::value- >::type*)+ >::type)+ ASIO_INITFN_AUTO_RESULT_TYPE_SUFFIX((+ async_initiate<WriteToken,+ void (asio::error_code, std::size_t)>(+ declval<detail::initiate_async_write_dynbuf_v2<AsyncWriteStream> >(),+ token, ASIO_MOVE_CAST(DynamicBuffer_v2)(buffers),+ ASIO_MOVE_CAST(CompletionCondition)(completion_condition)))) {- return async_initiate<WriteHandler,+ return async_initiate<WriteToken, void (asio::error_code, std::size_t)>( detail::initiate_async_write_dynbuf_v2<AsyncWriteStream>(s),- handler, ASIO_MOVE_CAST(DynamicBuffer_v2)(buffers),+ token, ASIO_MOVE_CAST(DynamicBuffer_v2)(buffers), ASIO_MOVE_CAST(CompletionCondition)(completion_condition)); }
link/modules/asio-standalone/asio/include/asio/impl/write_at.hpp view
@@ -2,7 +2,7 @@ // impl/write_at.hpp // ~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -15,11 +15,10 @@ # pragma once #endif // defined(_MSC_VER) && (_MSC_VER >= 1200) -#include "asio/associated_allocator.hpp"-#include "asio/associated_executor.hpp"+#include "asio/associator.hpp" #include "asio/buffer.hpp"-#include "asio/completion_condition.hpp" #include "asio/detail/array_fwd.hpp"+#include "asio/detail/base_from_cancellation_state.hpp" #include "asio/detail/base_from_completion_cond.hpp" #include "asio/detail/bind_handler.hpp" #include "asio/detail/consuming_buffers.hpp"@@ -59,7 +58,7 @@ else break; }- return tmp.total_consumed();;+ return tmp.total_consumed(); } } // namespace detail @@ -161,14 +160,16 @@ typename ConstBufferSequence, typename ConstBufferIterator, typename CompletionCondition, typename WriteHandler> class write_at_op- : detail::base_from_completion_cond<CompletionCondition>+ : public base_from_cancellation_state<WriteHandler>,+ base_from_completion_cond<CompletionCondition> { public: write_at_op(AsyncRandomAccessWriteDevice& device, uint64_t offset, const ConstBufferSequence& buffers, CompletionCondition& completion_condition, WriteHandler& handler)- : detail::base_from_completion_cond<- CompletionCondition>(completion_condition),+ : base_from_cancellation_state<WriteHandler>(+ handler, enable_partial_cancellation()),+ base_from_completion_cond<CompletionCondition>(completion_condition), device_(device), offset_(offset), buffers_(buffers),@@ -179,7 +180,8 @@ #if defined(ASIO_HAS_MOVE) write_at_op(const write_at_op& other)- : detail::base_from_completion_cond<CompletionCondition>(other),+ : base_from_cancellation_state<WriteHandler>(other),+ base_from_completion_cond<CompletionCondition>(other), device_(other.device_), offset_(other.offset_), buffers_(other.buffers_),@@ -189,8 +191,11 @@ } write_at_op(write_at_op&& other)- : detail::base_from_completion_cond<CompletionCondition>(- ASIO_MOVE_CAST(detail::base_from_completion_cond<+ : base_from_cancellation_state<WriteHandler>(+ ASIO_MOVE_CAST(base_from_cancellation_state<+ WriteHandler>)(other)),+ base_from_completion_cond<CompletionCondition>(+ ASIO_MOVE_CAST(base_from_completion_cond< CompletionCondition>)(other)), device_(other.device_), offset_(other.offset_),@@ -201,7 +206,7 @@ } #endif // defined(ASIO_HAS_MOVE) - void operator()(const asio::error_code& ec,+ void operator()(asio::error_code ec, std::size_t bytes_transferred, int start = 0) { std::size_t max_size;@@ -209,7 +214,7 @@ { case 1: max_size = this->check_for_completion(ec, buffers_.total_consumed());- do+ for (;;) { { ASIO_HANDLER_LOCATION((__FILE__, __LINE__, "async_write_at"));@@ -222,9 +227,18 @@ if ((!ec && bytes_transferred == 0) || buffers_.empty()) break; max_size = this->check_for_completion(ec, buffers_.total_consumed());- } while (max_size > 0);+ if (max_size == 0)+ break;+ if (this->cancelled() != cancellation_type::none)+ {+ ec = asio::error::operation_aborted;+ break;+ }+ } - handler_(ec, buffers_.total_consumed());+ ASIO_MOVE_OR_LVALUE(WriteHandler)(handler_)(+ static_cast<const asio::error_code&>(ec),+ static_cast<const std::size_t&>(buffers_.total_consumed())); } } @@ -316,7 +330,7 @@ template <typename AsyncRandomAccessWriteDevice, typename ConstBufferSequence, typename ConstBufferIterator, typename CompletionCondition, typename WriteHandler>- inline void start_write_at_buffer_sequence_op(AsyncRandomAccessWriteDevice& d,+ inline void start_write_at_op(AsyncRandomAccessWriteDevice& d, uint64_t offset, const ConstBufferSequence& buffers, const ConstBufferIterator&, CompletionCondition& completion_condition, WriteHandler& handler)@@ -328,13 +342,12 @@ } template <typename AsyncRandomAccessWriteDevice>- class initiate_async_write_at_buffer_sequence+ class initiate_async_write_at { public: typedef typename AsyncRandomAccessWriteDevice::executor_type executor_type; - explicit initiate_async_write_at_buffer_sequence(- AsyncRandomAccessWriteDevice& device)+ explicit initiate_async_write_at(AsyncRandomAccessWriteDevice& device) : device_(device) { }@@ -356,7 +369,7 @@ non_const_lvalue<WriteHandler> handler2(handler); non_const_lvalue<CompletionCondition> completion_cond2(completion_cond);- start_write_at_buffer_sequence_op(device_, offset, buffers,+ start_write_at_op(device_, offset, buffers, asio::buffer_sequence_begin(buffers), completion_cond2.value, handler2.value); }@@ -368,44 +381,34 @@ #if !defined(GENERATING_DOCUMENTATION) -template <typename AsyncRandomAccessWriteDevice,- typename ConstBufferSequence, typename ConstBufferIterator,- typename CompletionCondition, typename WriteHandler, typename Allocator>-struct associated_allocator<+template <template <typename, typename> class Associator,+ typename AsyncRandomAccessWriteDevice, typename ConstBufferSequence,+ typename ConstBufferIterator, typename CompletionCondition,+ typename WriteHandler, typename DefaultCandidate>+struct associator<Associator, detail::write_at_op<AsyncRandomAccessWriteDevice, ConstBufferSequence, ConstBufferIterator, CompletionCondition, WriteHandler>,- Allocator>+ DefaultCandidate>+ : Associator<WriteHandler, DefaultCandidate> {- typedef typename associated_allocator<WriteHandler, Allocator>::type type;-- static type get(- const detail::write_at_op<AsyncRandomAccessWriteDevice,+ static typename Associator<WriteHandler, DefaultCandidate>::type+ get(const detail::write_at_op<AsyncRandomAccessWriteDevice, ConstBufferSequence, ConstBufferIterator,- CompletionCondition, WriteHandler>& h,- const Allocator& a = Allocator()) ASIO_NOEXCEPT+ CompletionCondition, WriteHandler>& h) ASIO_NOEXCEPT {- return associated_allocator<WriteHandler, Allocator>::get(h.handler_, a);+ return Associator<WriteHandler, DefaultCandidate>::get(h.handler_); }-}; -template <typename AsyncRandomAccessWriteDevice,- typename ConstBufferSequence, typename ConstBufferIterator,- typename CompletionCondition, typename WriteHandler, typename Executor>-struct associated_executor<- detail::write_at_op<AsyncRandomAccessWriteDevice, ConstBufferSequence,- ConstBufferIterator, CompletionCondition, WriteHandler>,- Executor>- : detail::associated_executor_forwarding_base<WriteHandler, Executor>-{- typedef typename associated_executor<WriteHandler, Executor>::type type;-- static type get(- const detail::write_at_op<AsyncRandomAccessWriteDevice,+ static ASIO_AUTO_RETURN_TYPE_PREFIX2(+ typename Associator<WriteHandler, DefaultCandidate>::type)+ get(const detail::write_at_op<AsyncRandomAccessWriteDevice, ConstBufferSequence, ConstBufferIterator, CompletionCondition, WriteHandler>& h,- const Executor& ex = Executor()) ASIO_NOEXCEPT+ const DefaultCandidate& c) ASIO_NOEXCEPT+ ASIO_AUTO_RETURN_TYPE_SUFFIX((+ Associator<WriteHandler, DefaultCandidate>::get(h.handler_, c))) {- return associated_executor<WriteHandler, Executor>::get(h.handler_, ex);+ return Associator<WriteHandler, DefaultCandidate>::get(h.handler_, c); } }; @@ -414,36 +417,47 @@ template <typename AsyncRandomAccessWriteDevice, typename ConstBufferSequence, typename CompletionCondition, ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code,- std::size_t)) WriteHandler>-inline ASIO_INITFN_AUTO_RESULT_TYPE(WriteHandler,+ std::size_t)) WriteToken>+inline ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX(WriteToken, void (asio::error_code, std::size_t)) async_write_at(AsyncRandomAccessWriteDevice& d, uint64_t offset, const ConstBufferSequence& buffers, CompletionCondition completion_condition,- ASIO_MOVE_ARG(WriteHandler) handler)+ ASIO_MOVE_ARG(WriteToken) token)+ ASIO_INITFN_AUTO_RESULT_TYPE_SUFFIX((+ async_initiate<WriteToken,+ void (asio::error_code, std::size_t)>(+ declval<detail::initiate_async_write_at<+ AsyncRandomAccessWriteDevice> >(),+ token, offset, buffers,+ ASIO_MOVE_CAST(CompletionCondition)(completion_condition)))) {- return async_initiate<WriteHandler,+ return async_initiate<WriteToken, void (asio::error_code, std::size_t)>(- detail::initiate_async_write_at_buffer_sequence<- AsyncRandomAccessWriteDevice>(d),- handler, offset, buffers,+ detail::initiate_async_write_at<AsyncRandomAccessWriteDevice>(d),+ token, offset, buffers, ASIO_MOVE_CAST(CompletionCondition)(completion_condition)); } template <typename AsyncRandomAccessWriteDevice, typename ConstBufferSequence, ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code,- std::size_t)) WriteHandler>-inline ASIO_INITFN_AUTO_RESULT_TYPE(WriteHandler,+ std::size_t)) WriteToken>+inline ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX(WriteToken, void (asio::error_code, std::size_t)) async_write_at(AsyncRandomAccessWriteDevice& d, uint64_t offset, const ConstBufferSequence& buffers,- ASIO_MOVE_ARG(WriteHandler) handler)+ ASIO_MOVE_ARG(WriteToken) token)+ ASIO_INITFN_AUTO_RESULT_TYPE_SUFFIX((+ async_initiate<WriteToken,+ void (asio::error_code, std::size_t)>(+ declval<detail::initiate_async_write_at<+ AsyncRandomAccessWriteDevice> >(),+ token, offset, buffers, transfer_all()))) {- return async_initiate<WriteHandler,+ return async_initiate<WriteToken, void (asio::error_code, std::size_t)>(- detail::initiate_async_write_at_buffer_sequence<- AsyncRandomAccessWriteDevice>(d),- handler, offset, buffers, transfer_all());+ detail::initiate_async_write_at<AsyncRandomAccessWriteDevice>(d),+ token, offset, buffers, transfer_all()); } #if !defined(ASIO_NO_EXTENSIONS)@@ -481,7 +495,7 @@ const std::size_t bytes_transferred) { streambuf_.consume(bytes_transferred);- handler_(ec, bytes_transferred);+ ASIO_MOVE_OR_LVALUE(WriteHandler)(handler_)(ec, bytes_transferred); } //private:@@ -588,34 +602,28 @@ #if !defined(GENERATING_DOCUMENTATION) -template <typename Allocator, typename WriteHandler, typename Allocator1>-struct associated_allocator<- detail::write_at_streambuf_op<Allocator, WriteHandler>,- Allocator1>+template <template <typename, typename> class Associator,+ typename Executor, typename WriteHandler, typename DefaultCandidate>+struct associator<Associator,+ detail::write_at_streambuf_op<Executor, WriteHandler>,+ DefaultCandidate>+ : Associator<WriteHandler, DefaultCandidate> {- typedef typename associated_allocator<WriteHandler, Allocator1>::type type;-- static type get(- const detail::write_at_streambuf_op<Allocator, WriteHandler>& h,- const Allocator1& a = Allocator1()) ASIO_NOEXCEPT+ static typename Associator<WriteHandler, DefaultCandidate>::type+ get(const detail::write_at_streambuf_op<Executor, WriteHandler>& h)+ ASIO_NOEXCEPT {- return associated_allocator<WriteHandler, Allocator1>::get(h.handler_, a);+ return Associator<WriteHandler, DefaultCandidate>::get(h.handler_); }-}; -template <typename Executor, typename WriteHandler, typename Executor1>-struct associated_executor<- detail::write_at_streambuf_op<Executor, WriteHandler>,- Executor1>- : detail::associated_executor_forwarding_base<WriteHandler, Executor>-{- typedef typename associated_executor<WriteHandler, Executor1>::type type;-- static type get(- const detail::write_at_streambuf_op<Executor, WriteHandler>& h,- const Executor1& ex = Executor1()) ASIO_NOEXCEPT+ static ASIO_AUTO_RETURN_TYPE_PREFIX2(+ typename Associator<WriteHandler, DefaultCandidate>::type)+ get(const detail::write_at_streambuf_op<Executor, WriteHandler>& h,+ const DefaultCandidate& c) ASIO_NOEXCEPT+ ASIO_AUTO_RETURN_TYPE_SUFFIX((+ Associator<WriteHandler, DefaultCandidate>::get(h.handler_, c))) {- return associated_executor<WriteHandler, Executor1>::get(h.handler_, ex);+ return Associator<WriteHandler, DefaultCandidate>::get(h.handler_, c); } }; @@ -624,36 +632,49 @@ template <typename AsyncRandomAccessWriteDevice, typename Allocator, typename CompletionCondition, ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code,- std::size_t)) WriteHandler>-inline ASIO_INITFN_AUTO_RESULT_TYPE(WriteHandler,+ std::size_t)) WriteToken>+inline ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX(WriteToken, void (asio::error_code, std::size_t)) async_write_at(AsyncRandomAccessWriteDevice& d, uint64_t offset, asio::basic_streambuf<Allocator>& b, CompletionCondition completion_condition,- ASIO_MOVE_ARG(WriteHandler) handler)+ ASIO_MOVE_ARG(WriteToken) token)+ ASIO_INITFN_AUTO_RESULT_TYPE_SUFFIX((+ async_initiate<WriteToken,+ void (asio::error_code, std::size_t)>(+ declval<detail::initiate_async_write_at_streambuf<+ AsyncRandomAccessWriteDevice> >(),+ token, offset, &b,+ ASIO_MOVE_CAST(CompletionCondition)(completion_condition)))) {- return async_initiate<WriteHandler,+ return async_initiate<WriteToken, void (asio::error_code, std::size_t)>( detail::initiate_async_write_at_streambuf< AsyncRandomAccessWriteDevice>(d),- handler, offset, &b,+ token, offset, &b, ASIO_MOVE_CAST(CompletionCondition)(completion_condition)); } template <typename AsyncRandomAccessWriteDevice, typename Allocator, ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code,- std::size_t)) WriteHandler>-inline ASIO_INITFN_AUTO_RESULT_TYPE(WriteHandler,+ std::size_t)) WriteToken>+inline ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX(WriteToken, void (asio::error_code, std::size_t)) async_write_at(AsyncRandomAccessWriteDevice& d, uint64_t offset, asio::basic_streambuf<Allocator>& b,- ASIO_MOVE_ARG(WriteHandler) handler)+ ASIO_MOVE_ARG(WriteToken) token)+ ASIO_INITFN_AUTO_RESULT_TYPE_SUFFIX((+ async_initiate<WriteToken,+ void (asio::error_code, std::size_t)>(+ declval<detail::initiate_async_write_at_streambuf<+ AsyncRandomAccessWriteDevice> >(),+ token, offset, &b, transfer_all()))) {- return async_initiate<WriteHandler,+ return async_initiate<WriteToken, void (asio::error_code, std::size_t)>( detail::initiate_async_write_at_streambuf< AsyncRandomAccessWriteDevice>(d),- handler, offset, &b, transfer_all());+ token, offset, &b, transfer_all()); } #endif // !defined(ASIO_NO_IOSTREAM)
link/modules/asio-standalone/asio/include/asio/io_context.hpp view
@@ -2,7 +2,7 @@ // io_context.hpp // ~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -20,6 +20,8 @@ #include <stdexcept> #include <typeinfo> #include "asio/async_result.hpp"+#include "asio/detail/concurrency_hint.hpp"+#include "asio/detail/cstdint.hpp" #include "asio/detail/wrapped_handler.hpp" #include "asio/error_code.hpp" #include "asio/execution.hpp"@@ -56,9 +58,10 @@ struct io_context_bits {- ASIO_STATIC_CONSTEXPR(unsigned int, blocking_never = 1);- ASIO_STATIC_CONSTEXPR(unsigned int, relationship_continuation = 2);- ASIO_STATIC_CONSTEXPR(unsigned int, outstanding_work_tracked = 4);+ ASIO_STATIC_CONSTEXPR(uintptr_t, blocking_never = 1);+ ASIO_STATIC_CONSTEXPR(uintptr_t, relationship_continuation = 2);+ ASIO_STATIC_CONSTEXPR(uintptr_t, outstanding_work_tracked = 4);+ ASIO_STATIC_CONSTEXPR(uintptr_t, runtime_bits = 3); }; } // namespace detail @@ -166,30 +169,12 @@ * returning when there is no more work to do. For example, the io_context may * be being run in a background thread that is launched prior to the * application's asynchronous operations. The run() call may be kept running by- * creating an executor that tracks work against the io_context:- *- * @code asio::io_context io_context;- * auto work = asio::require(io_context.get_executor(),- * asio::execution::outstanding_work.tracked);- * ... @endcode- *- * If using C++03, which lacks automatic variable type deduction, you may- * compute the return type of the require call:- *- * @code asio::io_context io_context;- * typename asio::require_result<- * asio::io_context::executor_type,- * asio::exeution::outstanding_work_t::tracked_t>- * work = asio::require(io_context.get_executor(),- * asio::execution::outstanding_work.tracked);- * ... @endcode- *- * or store the result in the type-erasing executor wrapper, any_io_executor:+ * using the @ref make_work_guard function to create an object of type+ * asio::executor_work_guard<io_context::executor_type>: * * @code asio::io_context io_context;- * asio::any_io_executor work- * = asio::require(io_context.get_executor(),- * asio::execution::outstanding_work.tracked);+ * asio::executor_work_guard<asio::io_context::executor_type>+ * = asio::make_work_guard(io_context); * ... @endcode * * To effect a shutdown, the application will then need to call the io_context@@ -198,15 +183,13 @@ * permitting ready handlers to be dispatched. * * Alternatively, if the application requires that all operations and handlers- * be allowed to finish normally, store the work-tracking executor in an- * any_io_executor object, so that it may be explicitly reset.+ * be allowed to finish normally, the work object may be explicitly reset. * * @code asio::io_context io_context;- * asio::any_io_executor work- * = asio::require(io_context.get_executor(),- * asio::execution::outstanding_work.tracked);+ * asio::executor_work_guard<asio::io_context::executor_type>+ * = asio::make_work_guard(io_context); * ...- * work = asio::any_io_executor(); // Allow run() to exit. @endcode+ * work.reset(); // Allow run() to exit. @endcode */ class io_context : public execution_context@@ -217,11 +200,16 @@ friend class detail::win_iocp_overlapped_ptr; #endif +#if !defined(ASIO_NO_DEPRECATED)+ struct initiate_dispatch;+ struct initiate_post;+#endif // !defined(ASIO_NO_DEPRECATED)+ public:- template <typename Allocator, unsigned int Bits>+ template <typename Allocator, uintptr_t Bits> class basic_executor_type; - template <typename Allocator, unsigned int Bits>+ template <typename Allocator, uintptr_t Bits> friend class basic_executor_type; /// Executor used to submit functions to an io_context.@@ -400,7 +388,7 @@ ASIO_DECL count_type run_one(); #if !defined(ASIO_NO_DEPRECATED)- /// (Deprecated: Use non-error_code overlaod.) Run the io_context object's+ /// (Deprecated: Use non-error_code overload.) Run the io_context object's /// event processing loop to execute at most one handler. /** * The run_one() function blocks until one handler has been dispatched, or@@ -573,8 +561,11 @@ * throws an exception. */ template <typename LegacyCompletionHandler>- ASIO_INITFN_AUTO_RESULT_TYPE(LegacyCompletionHandler, void ())- dispatch(ASIO_MOVE_ARG(LegacyCompletionHandler) handler);+ ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX(LegacyCompletionHandler, void ())+ dispatch(ASIO_MOVE_ARG(LegacyCompletionHandler) handler)+ ASIO_INITFN_AUTO_RESULT_TYPE_SUFFIX((+ async_initiate<LegacyCompletionHandler, void ()>(+ declval<initiate_dispatch>(), handler, this))); /// (Deprecated: Use asio::post().) Request the io_context to invoke /// the given handler and return immediately.@@ -600,8 +591,11 @@ * throws an exception. */ template <typename LegacyCompletionHandler>- ASIO_INITFN_AUTO_RESULT_TYPE(LegacyCompletionHandler, void ())- post(ASIO_MOVE_ARG(LegacyCompletionHandler) handler);+ ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX(LegacyCompletionHandler, void ())+ post(ASIO_MOVE_ARG(LegacyCompletionHandler) handler)+ ASIO_INITFN_AUTO_RESULT_TYPE_SUFFIX((+ async_initiate<LegacyCompletionHandler, void ()>(+ declval<initiate_post>(), handler, this))); /// (Deprecated: Use asio::bind_executor().) Create a new handler that /// automatically dispatches the wrapped handler on the io_context.@@ -638,11 +632,6 @@ io_context(const io_context&) ASIO_DELETED; io_context& operator=(const io_context&) ASIO_DELETED; -#if !defined(ASIO_NO_DEPRECATED)- struct initiate_dispatch;- struct initiate_post;-#endif // !defined(ASIO_NO_DEPRECATED)- // Helper function to add the implementation. ASIO_DECL impl_type& add_impl(impl_type* impl); @@ -667,31 +656,30 @@ } // namespace detail /// Executor implementation type used to submit functions to an io_context.-template <typename Allocator, unsigned int Bits>-class io_context::basic_executor_type : detail::io_context_bits+template <typename Allocator, uintptr_t Bits>+class io_context::basic_executor_type :+ detail::io_context_bits, Allocator { public: /// Copy constructor. basic_executor_type( const basic_executor_type& other) ASIO_NOEXCEPT- : io_context_(other.io_context_),- allocator_(other.allocator_),- bits_(other.bits_)+ : Allocator(static_cast<const Allocator&>(other)),+ target_(other.target_) { if (Bits & outstanding_work_tracked)- if (io_context_)- io_context_->impl_.work_started();+ if (context_ptr())+ context_ptr()->impl_.work_started(); } #if defined(ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION) /// Move constructor. basic_executor_type(basic_executor_type&& other) ASIO_NOEXCEPT- : io_context_(other.io_context_),- allocator_(ASIO_MOVE_CAST(Allocator)(other.allocator_)),- bits_(other.bits_)+ : Allocator(ASIO_MOVE_CAST(Allocator)(other)),+ target_(other.target_) { if (Bits & outstanding_work_tracked)- other.io_context_ = 0;+ other.target_ = 0; } #endif // defined(ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION) @@ -699,8 +687,8 @@ ~basic_executor_type() ASIO_NOEXCEPT { if (Bits & outstanding_work_tracked)- if (io_context_)- io_context_->impl_.work_finished();+ if (context_ptr())+ context_ptr()->impl_.work_finished(); } /// Assignment operator.@@ -713,6 +701,12 @@ basic_executor_type&& other) ASIO_NOEXCEPT; #endif // defined(ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION) +#if !defined(GENERATING_DOCUMENTATION)+private:+ friend struct asio_require_fn::impl;+ friend struct asio_prefer_fn::impl;+#endif // !defined(GENERATING_DOCUMENTATION)+ /// Obtain an executor with the @c blocking.possibly property. /** * Do not call this function directly. It is intended for use with the@@ -726,8 +720,8 @@ ASIO_CONSTEXPR basic_executor_type require( execution::blocking_t::possibly_t) const {- return basic_executor_type(io_context_,- allocator_, bits_ & ~blocking_never);+ return basic_executor_type(context_ptr(),+ *this, bits() & ~blocking_never); } /// Obtain an executor with the @c blocking.never property.@@ -743,8 +737,8 @@ ASIO_CONSTEXPR basic_executor_type require( execution::blocking_t::never_t) const {- return basic_executor_type(io_context_,- allocator_, bits_ | blocking_never);+ return basic_executor_type(context_ptr(),+ *this, bits() | blocking_never); } /// Obtain an executor with the @c relationship.fork property.@@ -760,8 +754,8 @@ ASIO_CONSTEXPR basic_executor_type require( execution::relationship_t::fork_t) const {- return basic_executor_type(io_context_,- allocator_, bits_ & ~relationship_continuation);+ return basic_executor_type(context_ptr(),+ *this, bits() & ~relationship_continuation); } /// Obtain an executor with the @c relationship.continuation property.@@ -777,8 +771,8 @@ ASIO_CONSTEXPR basic_executor_type require( execution::relationship_t::continuation_t) const {- return basic_executor_type(io_context_,- allocator_, bits_ | relationship_continuation);+ return basic_executor_type(context_ptr(),+ *this, bits() | relationship_continuation); } /// Obtain an executor with the @c outstanding_work.tracked property.@@ -796,7 +790,7 @@ require(execution::outstanding_work_t::tracked_t) const { return basic_executor_type<Allocator, Bits | outstanding_work_tracked>(- io_context_, allocator_, bits_);+ context_ptr(), *this, bits()); } /// Obtain an executor with the @c outstanding_work.untracked property.@@ -814,7 +808,7 @@ require(execution::outstanding_work_t::untracked_t) const { return basic_executor_type<Allocator, Bits & ~outstanding_work_tracked>(- io_context_, allocator_, bits_);+ context_ptr(), *this, bits()); } /// Obtain an executor with the specified @c allocator property.@@ -832,7 +826,7 @@ require(execution::allocator_t<OtherAllocator> a) const { return basic_executor_type<OtherAllocator, Bits>(- io_context_, a.value(), bits_);+ context_ptr(), a.value(), bits()); } /// Obtain an executor with the default @c allocator property.@@ -849,9 +843,16 @@ require(execution::allocator_t<void>) const { return basic_executor_type<std::allocator<void>, Bits>(- io_context_, std::allocator<void>(), bits_);+ context_ptr(), std::allocator<void>(), bits()); } +#if !defined(GENERATING_DOCUMENTATION)+private:+ friend struct asio_query_fn::impl;+ friend struct asio::execution::detail::mapping_t<0>;+ friend struct asio::execution::detail::outstanding_work_t<0>;+#endif // !defined(GENERATING_DOCUMENTATION)+ /// Query the current value of the @c mapping property. /** * Do not call this function directly. It is intended for use with the@@ -881,7 +882,7 @@ */ io_context& query(execution::context_t) const ASIO_NOEXCEPT {- return *io_context_;+ return *context_ptr(); } /// Query the current value of the @c blocking property.@@ -898,7 +899,7 @@ ASIO_CONSTEXPR execution::blocking_t query( execution::blocking_t) const ASIO_NOEXCEPT {- return (bits_ & blocking_never)+ return (bits() & blocking_never) ? execution::blocking_t(execution::blocking.never) : execution::blocking_t(execution::blocking.possibly); }@@ -917,7 +918,7 @@ ASIO_CONSTEXPR execution::relationship_t query( execution::relationship_t) const ASIO_NOEXCEPT {- return (bits_ & relationship_continuation)+ return (bits() & relationship_continuation) ? execution::relationship_t(execution::relationship.continuation) : execution::relationship_t(execution::relationship.fork); }@@ -955,7 +956,7 @@ ASIO_CONSTEXPR Allocator query( execution::allocator_t<OtherAllocator>) const ASIO_NOEXCEPT {- return allocator_;+ return static_cast<const Allocator&>(*this); } /// Query the current value of the @c allocator property.@@ -971,9 +972,10 @@ ASIO_CONSTEXPR Allocator query( execution::allocator_t<void>) const ASIO_NOEXCEPT {- return allocator_;+ return static_cast<const Allocator&>(*this); } +public: /// Determine whether the io_context is running in the current thread. /** * @return @c true if the current thread is running the io_context. Otherwise@@ -988,9 +990,8 @@ friend bool operator==(const basic_executor_type& a, const basic_executor_type& b) ASIO_NOEXCEPT {- return a.io_context_ == b.io_context_- && a.allocator_ == b.allocator_- && a.bits_ == b.bits_;+ return a.target_ == b.target_+ && static_cast<const Allocator&>(a) == static_cast<const Allocator&>(b); } /// Compare two executors for inequality.@@ -1000,24 +1001,16 @@ friend bool operator!=(const basic_executor_type& a, const basic_executor_type& b) ASIO_NOEXCEPT {- return a.io_context_ != b.io_context_- || a.allocator_ != b.allocator_- || a.bits_ != b.bits_;+ return a.target_ != b.target_+ || static_cast<const Allocator&>(a) != static_cast<const Allocator&>(b); } /// Execution function.- /**- * Do not call this function directly. It is intended for use with the- * execution::execute customisation point.- *- * For example:- * @code auto ex = my_io_context.get_executor();- * execution::execute(ex, my_function_object); @endcode- */ template <typename Function> void execute(ASIO_MOVE_ARG(Function) f) const; #if !defined(ASIO_NO_TS_EXECUTORS)+public: /// Obtain the underlying execution context. io_context& context() const ASIO_NOEXCEPT; @@ -1096,38 +1089,40 @@ private: friend class io_context;- template <typename, unsigned int> friend class basic_executor_type;+ template <typename, uintptr_t> friend class basic_executor_type; // Constructor used by io_context::get_executor(). explicit basic_executor_type(io_context& i) ASIO_NOEXCEPT- : io_context_(&i),- allocator_(),- bits_(0)+ : Allocator(),+ target_(reinterpret_cast<uintptr_t>(&i)) { if (Bits & outstanding_work_tracked)- io_context_->impl_.work_started();+ context_ptr()->impl_.work_started(); } // Constructor used by require(). basic_executor_type(io_context* i,- const Allocator& a, unsigned int bits) ASIO_NOEXCEPT- : io_context_(i),- allocator_(a),- bits_(bits)+ const Allocator& a, uintptr_t bits) ASIO_NOEXCEPT+ : Allocator(a),+ target_(reinterpret_cast<uintptr_t>(i) | bits) { if (Bits & outstanding_work_tracked)- if (io_context_)- io_context_->impl_.work_started();+ if (context_ptr())+ context_ptr()->impl_.work_started(); } - // The underlying io_context.- io_context* io_context_;+ io_context* context_ptr() const ASIO_NOEXCEPT+ {+ return reinterpret_cast<io_context*>(target_ & ~runtime_bits);+ } - // The allocator used for execution functions.- Allocator allocator_;+ uintptr_t bits() const ASIO_NOEXCEPT+ {+ return target_ & runtime_bits;+ } - // The runtime-switched properties of the io_context executor.- unsigned int bits_;+ // The underlying io_context and runtime bits.+ uintptr_t target_; }; #if !defined(ASIO_NO_DEPRECATED)@@ -1258,7 +1253,7 @@ #if !defined(ASIO_HAS_DEDUCED_EQUALITY_COMPARABLE_TRAIT) -template <typename Allocator, unsigned int Bits>+template <typename Allocator, uintptr_t Bits> struct equality_comparable< asio::io_context::basic_executor_type<Allocator, Bits> >@@ -1271,7 +1266,7 @@ #if !defined(ASIO_HAS_DEDUCED_EXECUTE_MEMBER_TRAIT) -template <typename Allocator, unsigned int Bits, typename Function>+template <typename Allocator, uintptr_t Bits, typename Function> struct execute_member< asio::io_context::basic_executor_type<Allocator, Bits>, Function@@ -1286,7 +1281,7 @@ #if !defined(ASIO_HAS_DEDUCED_REQUIRE_MEMBER_TRAIT) -template <typename Allocator, unsigned int Bits>+template <typename Allocator, uintptr_t Bits> struct require_member< asio::io_context::basic_executor_type<Allocator, Bits>, asio::execution::blocking_t::possibly_t@@ -1298,7 +1293,7 @@ Allocator, Bits> result_type; }; -template <typename Allocator, unsigned int Bits>+template <typename Allocator, uintptr_t Bits> struct require_member< asio::io_context::basic_executor_type<Allocator, Bits>, asio::execution::blocking_t::never_t@@ -1310,7 +1305,7 @@ Allocator, Bits> result_type; }; -template <typename Allocator, unsigned int Bits>+template <typename Allocator, uintptr_t Bits> struct require_member< asio::io_context::basic_executor_type<Allocator, Bits>, asio::execution::relationship_t::fork_t@@ -1322,7 +1317,7 @@ Allocator, Bits> result_type; }; -template <typename Allocator, unsigned int Bits>+template <typename Allocator, uintptr_t Bits> struct require_member< asio::io_context::basic_executor_type<Allocator, Bits>, asio::execution::relationship_t::continuation_t@@ -1334,7 +1329,7 @@ Allocator, Bits> result_type; }; -template <typename Allocator, unsigned int Bits>+template <typename Allocator, uintptr_t Bits> struct require_member< asio::io_context::basic_executor_type<Allocator, Bits>, asio::execution::outstanding_work_t::tracked_t@@ -1346,7 +1341,7 @@ Allocator, Bits | outstanding_work_tracked> result_type; }; -template <typename Allocator, unsigned int Bits>+template <typename Allocator, uintptr_t Bits> struct require_member< asio::io_context::basic_executor_type<Allocator, Bits>, asio::execution::outstanding_work_t::untracked_t@@ -1358,7 +1353,7 @@ Allocator, Bits & ~outstanding_work_tracked> result_type; }; -template <typename Allocator, unsigned int Bits>+template <typename Allocator, uintptr_t Bits> struct require_member< asio::io_context::basic_executor_type<Allocator, Bits>, asio::execution::allocator_t<void>@@ -1370,7 +1365,7 @@ std::allocator<void>, Bits> result_type; }; -template <unsigned int Bits,+template <uintptr_t Bits, typename Allocator, typename OtherAllocator> struct require_member< asio::io_context::basic_executor_type<Allocator, Bits>,@@ -1387,7 +1382,7 @@ #if !defined(ASIO_HAS_DEDUCED_QUERY_STATIC_CONSTEXPR_MEMBER_TRAIT) -template <typename Allocator, unsigned int Bits, typename Property>+template <typename Allocator, uintptr_t Bits, typename Property> struct query_static_constexpr_member< asio::io_context::basic_executor_type<Allocator, Bits>, Property,@@ -1411,7 +1406,7 @@ } }; -template <typename Allocator, unsigned int Bits, typename Property>+template <typename Allocator, uintptr_t Bits, typename Property> struct query_static_constexpr_member< asio::io_context::basic_executor_type<Allocator, Bits>, Property,@@ -1437,7 +1432,7 @@ #if !defined(ASIO_HAS_DEDUCED_QUERY_MEMBER_TRAIT) -template <typename Allocator, unsigned int Bits, typename Property>+template <typename Allocator, uintptr_t Bits, typename Property> struct query_member< asio::io_context::basic_executor_type<Allocator, Bits>, Property,@@ -1454,7 +1449,7 @@ typedef asio::execution::blocking_t result_type; }; -template <typename Allocator, unsigned int Bits, typename Property>+template <typename Allocator, uintptr_t Bits, typename Property> struct query_member< asio::io_context::basic_executor_type<Allocator, Bits>, Property,@@ -1471,7 +1466,7 @@ typedef asio::execution::relationship_t result_type; }; -template <typename Allocator, unsigned int Bits>+template <typename Allocator, uintptr_t Bits> struct query_member< asio::io_context::basic_executor_type<Allocator, Bits>, asio::execution::context_t@@ -1482,7 +1477,7 @@ typedef asio::io_context& result_type; }; -template <typename Allocator, unsigned int Bits>+template <typename Allocator, uintptr_t Bits> struct query_member< asio::io_context::basic_executor_type<Allocator, Bits>, asio::execution::allocator_t<void>@@ -1493,7 +1488,7 @@ typedef Allocator result_type; }; -template <typename Allocator, unsigned int Bits, typename OtherAllocator>+template <typename Allocator, uintptr_t Bits, typename OtherAllocator> struct query_member< asio::io_context::basic_executor_type<Allocator, Bits>, asio::execution::allocator_t<OtherAllocator>@@ -1507,6 +1502,15 @@ #endif // !defined(ASIO_HAS_DEDUCED_QUERY_MEMBER_TRAIT) } // namespace traits++namespace execution {++template <>+struct is_executor<io_context> : false_type+{+};++} // namespace execution #endif // !defined(GENERATING_DOCUMENTATION)
link/modules/asio-standalone/asio/include/asio/io_context_strand.hpp view
@@ -2,7 +2,7 @@ // io_context_strand.hpp // ~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -88,6 +88,12 @@ */ class io_context::strand {+private:+#if !defined(ASIO_NO_DEPRECATED)+ struct initiate_dispatch;+ struct initiate_post;+#endif // !defined(ASIO_NO_DEPRECATED)+ public: /// Constructor. /**@@ -183,8 +189,11 @@ * @code void handler(); @endcode */ template <typename LegacyCompletionHandler>- ASIO_INITFN_AUTO_RESULT_TYPE(LegacyCompletionHandler, void ())+ ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX(LegacyCompletionHandler, void ()) dispatch(ASIO_MOVE_ARG(LegacyCompletionHandler) handler)+ ASIO_INITFN_AUTO_RESULT_TYPE_SUFFIX((+ async_initiate<LegacyCompletionHandler, void ()>(+ declval<initiate_dispatch>(), handler, this))) { return async_initiate<LegacyCompletionHandler, void ()>( initiate_dispatch(), handler, this);@@ -230,8 +239,11 @@ * @code void handler(); @endcode */ template <typename LegacyCompletionHandler>- ASIO_INITFN_AUTO_RESULT_TYPE(LegacyCompletionHandler, void ())+ ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX(LegacyCompletionHandler, void ()) post(ASIO_MOVE_ARG(LegacyCompletionHandler) handler)+ ASIO_INITFN_AUTO_RESULT_TYPE_SUFFIX((+ async_initiate<LegacyCompletionHandler, void ()>(+ declval<initiate_post>(), handler, this))) { return async_initiate<LegacyCompletionHandler, void ()>( initiate_post(), handler, this);
link/modules/asio-standalone/asio/include/asio/io_service.hpp view
@@ -2,7 +2,7 @@ // io_service.hpp // ~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/io_service_strand.hpp view
@@ -2,7 +2,7 @@ // io_service_strand.hpp // ~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/ip/address.hpp view
@@ -2,7 +2,7 @@ // ip/address.hpp // ~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -25,6 +25,10 @@ #include "asio/ip/address_v6.hpp" #include "asio/ip/bad_address_cast.hpp" +#if defined(ASIO_HAS_STD_HASH)+# include <functional>+#endif // defined(ASIO_HAS_STD_HASH)+ #if !defined(ASIO_NO_IOSTREAM) # include <iosfwd> #endif // !defined(ASIO_NO_IOSTREAM)@@ -257,6 +261,24 @@ } // namespace ip } // namespace asio++#if defined(ASIO_HAS_STD_HASH)+namespace std {++template <>+struct hash<asio::ip::address>+{+ std::size_t operator()(const asio::ip::address& addr)+ const ASIO_NOEXCEPT+ {+ return addr.is_v4()+ ? std::hash<asio::ip::address_v4>()(addr.to_v4())+ : std::hash<asio::ip::address_v6>()(addr.to_v6());+ }+};++} // namespace std+#endif // defined(ASIO_HAS_STD_HASH) #include "asio/detail/pop_options.hpp"
link/modules/asio-standalone/asio/include/asio/ip/address_v4.hpp view
@@ -2,7 +2,7 @@ // ip/address_v4.hpp // ~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -24,6 +24,10 @@ #include "asio/detail/winsock_init.hpp" #include "asio/error_code.hpp" +#if defined(ASIO_HAS_STD_HASH)+# include <functional>+#endif // defined(ASIO_HAS_STD_HASH)+ #if !defined(ASIO_NO_IOSTREAM) # include <iosfwd> #endif // !defined(ASIO_NO_IOSTREAM)@@ -60,15 +64,31 @@ #endif /// Default constructor.+ /**+ * Initialises the @c address_v4 object such that:+ * @li <tt>to_bytes()</tt> yields <tt>{0, 0, 0, 0}</tt>; and+ * @li <tt>to_uint() == 0</tt>.+ */ address_v4() ASIO_NOEXCEPT { addr_.s_addr = 0; } /// Construct an address from raw bytes.+ /**+ * Initialises the @c address_v4 object such that <tt>to_bytes() ==+ * bytes</tt>.+ *+ * @throws out_of_range Thrown if any element in @c bytes is not in the range+ * <tt>0 - 0xFF</tt>. Note that no range checking is required for platforms+ * where <tt>std::numeric_limits<unsigned char>::max()</tt> is <tt>0xFF</tt>.+ */ ASIO_DECL explicit address_v4(const bytes_type& bytes); /// Construct an address from an unsigned integer in host byte order.+ /**+ * Initialises the @c address_v4 object such that <tt>to_uint() == addr</tt>.+ */ ASIO_DECL explicit address_v4(uint_type addr); /// Copy constructor.@@ -104,11 +124,12 @@ /// Get the address in bytes, in network byte order. ASIO_DECL bytes_type to_bytes() const ASIO_NOEXCEPT; - /// Get the address as an unsigned integer in host byte order+ /// Get the address as an unsigned integer in host byte order. ASIO_DECL uint_type to_uint() const ASIO_NOEXCEPT; #if !defined(ASIO_NO_DEPRECATED)- /// Get the address as an unsigned long in host byte order+ /// (Deprecated: Use to_uint().) Get the address as an unsigned long in host+ /// byte order. ASIO_DECL unsigned long to_ulong() const; #endif // !defined(ASIO_NO_DEPRECATED) @@ -140,9 +161,22 @@ #endif // !defined(ASIO_NO_DEPRECATED) /// Determine whether the address is a loopback address.+ /**+ * This function tests whether the address is in the address block+ * <tt>127.0.0.0/8</tt>, which corresponds to the address range+ * <tt>127.0.0.0 - 127.255.255.255</tt>.+ *+ * @returns <tt>(to_uint() & 0xFF000000) == 0x7F000000</tt>.+ */ ASIO_DECL bool is_loopback() const ASIO_NOEXCEPT; /// Determine whether the address is unspecified.+ /**+ * This function tests whether the address is the unspecified address+ * <tt>0.0.0.0</tt>.+ *+ * @returns <tt>to_uint() == 0</tt>.+ */ ASIO_DECL bool is_unspecified() const ASIO_NOEXCEPT; #if !defined(ASIO_NO_DEPRECATED)@@ -160,6 +194,13 @@ #endif // !defined(ASIO_NO_DEPRECATED) /// Determine whether the address is a multicast address.+ /**+ * This function tests whether the address is in the multicast address block+ * <tt>224.0.0.0/4</tt>, which corresponds to the address range+ * <tt>224.0.0.0 - 239.255.255.255</tt>.+ *+ * @returns <tt>(to_uint() & 0xF0000000) == 0xE0000000</tt>.+ */ ASIO_DECL bool is_multicast() const ASIO_NOEXCEPT; /// Compare two addresses for equality.@@ -177,6 +218,11 @@ } /// Compare addresses for ordering.+ /**+ * Compares two addresses in host byte order.+ *+ * @returns <tt>a1.to_uint() < a2.to_uint()</tt>.+ */ friend bool operator<(const address_v4& a1, const address_v4& a2) ASIO_NOEXCEPT {@@ -184,6 +230,11 @@ } /// Compare addresses for ordering.+ /**+ * Compares two addresses in host byte order.+ *+ * @returns <tt>a1.to_uint() > a2.to_uint()</tt>.+ */ friend bool operator>(const address_v4& a1, const address_v4& a2) ASIO_NOEXCEPT {@@ -191,6 +242,11 @@ } /// Compare addresses for ordering.+ /**+ * Compares two addresses in host byte order.+ *+ * @returns <tt>a1.to_uint() <= a2.to_uint()</tt>.+ */ friend bool operator<=(const address_v4& a1, const address_v4& a2) ASIO_NOEXCEPT {@@ -198,6 +254,11 @@ } /// Compare addresses for ordering.+ /**+ * Compares two addresses in host byte order.+ *+ * @returns <tt>a1.to_uint() >= a2.to_uint()</tt>.+ */ friend bool operator>=(const address_v4& a1, const address_v4& a2) ASIO_NOEXCEPT {@@ -205,18 +266,36 @@ } /// Obtain an address object that represents any address.+ /**+ * This functions returns an address that represents the "any" address+ * <tt>0.0.0.0</tt>.+ *+ * @returns A default-constructed @c address_v4 object.+ */ static address_v4 any() ASIO_NOEXCEPT { return address_v4(); } /// Obtain an address object that represents the loopback address.+ /**+ * This function returns an address that represents the well-known loopback+ * address <tt>127.0.0.1</tt>.+ *+ * @returns <tt>address_v4(0x7F000001)</tt>.+ */ static address_v4 loopback() ASIO_NOEXCEPT { return address_v4(0x7F000001); } /// Obtain an address object that represents the broadcast address.+ /**+ * This function returns an address that represents the broadcast address+ * <tt>255.255.255.255</tt>.+ *+ * @returns <tt>address_v4(0xFFFFFFFF)</tt>.+ */ static address_v4 broadcast() ASIO_NOEXCEPT { return address_v4(0xFFFFFFFF);@@ -324,6 +403,22 @@ } // namespace ip } // namespace asio++#if defined(ASIO_HAS_STD_HASH)+namespace std {++template <>+struct hash<asio::ip::address_v4>+{+ std::size_t operator()(const asio::ip::address_v4& addr)+ const ASIO_NOEXCEPT+ {+ return std::hash<unsigned int>()(addr.to_uint());+ }+};++} // namespace std+#endif // defined(ASIO_HAS_STD_HASH) #include "asio/detail/pop_options.hpp"
link/modules/asio-standalone/asio/include/asio/ip/address_v4_iterator.hpp view
@@ -2,7 +2,7 @@ // ip/address_v4_iterator.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/ip/address_v4_range.hpp view
@@ -2,7 +2,7 @@ // ip/address_v4_range.hpp // ~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/ip/address_v6.hpp view
@@ -2,7 +2,7 @@ // ip/address_v6.hpp // ~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -18,12 +18,17 @@ #include "asio/detail/config.hpp" #include <string> #include "asio/detail/array.hpp"+#include "asio/detail/cstdint.hpp" #include "asio/detail/socket_types.hpp" #include "asio/detail/string_view.hpp" #include "asio/detail/winsock_init.hpp" #include "asio/error_code.hpp" #include "asio/ip/address_v4.hpp" +#if defined(ASIO_HAS_STD_HASH)+# include <functional>+#endif // defined(ASIO_HAS_STD_HASH)+ #if !defined(ASIO_NO_IOSTREAM) # include <iosfwd> #endif // !defined(ASIO_NO_IOSTREAM)@@ -35,6 +40,9 @@ template <typename> class basic_address_iterator; +/// Type used for storing IPv6 scope IDs.+typedef uint_least32_t scope_id_type;+ /// Implements IP version 6 style addresses. /** * The asio::ip::address_v6 class provides the ability to use and@@ -59,11 +67,25 @@ #endif /// Default constructor.+ /**+ * Initialises the @c address_v6 object such that:+ * @li <tt>to_bytes()</tt> yields <tt>{0, 0, ..., 0}</tt>; and+ * @li <tt>scope_id() == 0</tt>.+ */ ASIO_DECL address_v6() ASIO_NOEXCEPT; /// Construct an address from raw bytes and scope ID.+ /**+ * Initialises the @c address_v6 object such that:+ * @li <tt>to_bytes() == bytes</tt>; and+ * @li <tt>this->scope_id() == scope_id</tt>.+ *+ * @throws out_of_range Thrown if any element in @c bytes is not in the range+ * <tt>0 - 0xFF</tt>. Note that no range checking is required for platforms+ * where <tt>std::numeric_limits<unsigned char>::max()</tt> is <tt>0xFF</tt>.+ */ ASIO_DECL explicit address_v6(const bytes_type& bytes,- unsigned long scope_id = 0);+ scope_id_type scope_id = 0); /// Copy constructor. ASIO_DECL address_v6(const address_v6& other) ASIO_NOEXCEPT;@@ -86,7 +108,7 @@ /** * Returns the scope ID associated with the IPv6 address. */- unsigned long scope_id() const ASIO_NOEXCEPT+ scope_id_type scope_id() const ASIO_NOEXCEPT { return scope_id_; }@@ -94,8 +116,10 @@ /// The scope ID of the address. /** * Modifies the scope ID associated with the IPv6 address.+ *+ * @param id The new scope ID. */- void scope_id(unsigned long id) ASIO_NOEXCEPT+ void scope_id(scope_id_type id) ASIO_NOEXCEPT { scope_id_ = id; }@@ -134,9 +158,17 @@ #endif // !defined(ASIO_NO_DEPRECATED) /// Determine whether the address is a loopback address.+ /**+ * This function tests whether the address is the loopback address+ * <tt>::1</tt>.+ */ ASIO_DECL bool is_loopback() const ASIO_NOEXCEPT; /// Determine whether the address is unspecified.+ /**+ * This function tests whether the address is the loopback address+ * <tt>::</tt>.+ */ ASIO_DECL bool is_unspecified() const ASIO_NOEXCEPT; /// Determine whether the address is link local.@@ -209,12 +241,22 @@ } /// Obtain an address object that represents any address.+ /**+ * This functions returns an address that represents the "any" address+ * <tt>::</tt>.+ *+ * @returns A default-constructed @c address_v6 object.+ */ static address_v6 any() ASIO_NOEXCEPT { return address_v6(); } /// Obtain an address object that represents the loopback address.+ /**+ * This function returns an address that represents the well-known loopback+ * address <tt>::1</tt>.+ */ ASIO_DECL static address_v6 loopback() ASIO_NOEXCEPT; #if !defined(ASIO_NO_DEPRECATED)@@ -232,7 +274,7 @@ asio::detail::in6_addr_type addr_; // The scope ID associated with the address.- unsigned long scope_id_;+ scope_id_type scope_id_; }; /// Create an IPv6 address from raw bytes and scope ID.@@ -240,7 +282,7 @@ * @relates address_v6 */ inline address_v6 make_address_v6(const address_v6::bytes_type& bytes,- unsigned long scope_id = 0)+ scope_id_type scope_id = 0) { return address_v6(bytes, scope_id); }@@ -330,6 +372,39 @@ } // namespace ip } // namespace asio++#if defined(ASIO_HAS_STD_HASH)+namespace std {++template <>+struct hash<asio::ip::address_v6>+{+ std::size_t operator()(const asio::ip::address_v6& addr)+ const ASIO_NOEXCEPT+ {+ const asio::ip::address_v6::bytes_type bytes = addr.to_bytes();+ std::size_t result = static_cast<std::size_t>(addr.scope_id());+ combine_4_bytes(result, &bytes[0]);+ combine_4_bytes(result, &bytes[4]);+ combine_4_bytes(result, &bytes[8]);+ combine_4_bytes(result, &bytes[12]);+ return result;+ }++private:+ static void combine_4_bytes(std::size_t& seed, const unsigned char* bytes)+ {+ const std::size_t bytes_hash =+ (static_cast<std::size_t>(bytes[0]) << 24) |+ (static_cast<std::size_t>(bytes[1]) << 16) |+ (static_cast<std::size_t>(bytes[2]) << 8) |+ (static_cast<std::size_t>(bytes[3]));+ seed ^= bytes_hash + 0x9e3779b9 + (seed << 6) + (seed >> 2);+ }+};++} // namespace std+#endif // defined(ASIO_HAS_STD_HASH) #include "asio/detail/pop_options.hpp"
link/modules/asio-standalone/asio/include/asio/ip/address_v6_iterator.hpp view
@@ -2,7 +2,7 @@ // ip/address_v6_iterator.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // Oliver Kowalke (oliver dot kowalke at gmail dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying
link/modules/asio-standalone/asio/include/asio/ip/address_v6_range.hpp view
@@ -2,7 +2,7 @@ // ip/address_v6_range.hpp // ~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // Oliver Kowalke (oliver dot kowalke at gmail dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying
link/modules/asio-standalone/asio/include/asio/ip/bad_address_cast.hpp view
@@ -2,7 +2,7 @@ // ip/bad_address_cast.hpp // ~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/ip/basic_endpoint.hpp view
@@ -2,7 +2,7 @@ // ip/basic_endpoint.hpp // ~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -16,9 +16,14 @@ #endif // defined(_MSC_VER) && (_MSC_VER >= 1200) #include "asio/detail/config.hpp"+#include "asio/detail/cstdint.hpp" #include "asio/ip/address.hpp" #include "asio/ip/detail/endpoint.hpp" +#if defined(ASIO_HAS_STD_HASH)+# include <functional>+#endif // defined(ASIO_HAS_STD_HASH)+ #if !defined(ASIO_NO_IOSTREAM) # include <iosfwd> #endif // !defined(ASIO_NO_IOSTREAM)@@ -28,6 +33,9 @@ namespace asio { namespace ip { +/// Type used for storing port numbers.+typedef uint_least16_t port_type;+ /// Describes an endpoint for a version-independent IP socket. /** * The asio::ip::basic_endpoint class template describes an endpoint that@@ -78,7 +86,7 @@ * @endcode */ basic_endpoint(const InternetProtocol& internet_protocol,- unsigned short port_num) ASIO_NOEXCEPT+ port_type port_num) ASIO_NOEXCEPT : impl_(internet_protocol.family(), port_num) { }@@ -87,7 +95,7 @@ /// constructor may be used for accepting connections on a specific interface /// or for making a connection to a remote endpoint. basic_endpoint(const asio::ip::address& addr,- unsigned short port_num) ASIO_NOEXCEPT+ port_type port_num) ASIO_NOEXCEPT : impl_(addr, port_num) { }@@ -162,14 +170,14 @@ /// Get the port associated with the endpoint. The port number is always in /// the host's byte order.- unsigned short port() const ASIO_NOEXCEPT+ port_type port() const ASIO_NOEXCEPT { return impl_.port(); } /// Set the port associated with the endpoint. The port number is always in /// the host's byte order.- void port(unsigned short port_num) ASIO_NOEXCEPT+ void port(port_type port_num) ASIO_NOEXCEPT { impl_.port(port_num); }@@ -256,6 +264,25 @@ } // namespace ip } // namespace asio++#if defined(ASIO_HAS_STD_HASH)+namespace std {++template <typename InternetProtocol>+struct hash<asio::ip::basic_endpoint<InternetProtocol> >+{+ std::size_t operator()(+ const asio::ip::basic_endpoint<InternetProtocol>& ep)+ const ASIO_NOEXCEPT+ {+ std::size_t hash1 = std::hash<asio::ip::address>()(ep.address());+ std::size_t hash2 = std::hash<unsigned short>()(ep.port());+ return hash1 ^ (hash2 + 0x9e3779b9 + (hash1 << 6) + (hash1 >> 2));+ }+};++} // namespace std+#endif // defined(ASIO_HAS_STD_HASH) #include "asio/detail/pop_options.hpp"
link/modules/asio-standalone/asio/include/asio/ip/basic_resolver.hpp view
@@ -2,7 +2,7 @@ // ip/basic_resolver.hpp // ~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -67,6 +67,9 @@ class basic_resolver : public resolver_base {+private:+ class initiate_async_resolve;+ public: /// The type of the executor associated with the object. typedef Executor executor_type;@@ -105,7 +108,7 @@ * resolver. */ explicit basic_resolver(const executor_type& ex)- : impl_(ex)+ : impl_(0, ex) { } @@ -119,10 +122,10 @@ */ template <typename ExecutionContext> explicit basic_resolver(ExecutionContext& context,- typename enable_if<+ typename constraint< is_convertible<ExecutionContext&, execution_context&>::value- >::type* = 0)- : impl_(context)+ >::type = 0)+ : impl_(0, 0, context) { } @@ -142,6 +145,29 @@ { } + // All resolvers have access to each other's implementations.+ template <typename InternetProtocol1, typename Executor1>+ friend class basic_resolver;++ /// Move-construct a basic_resolver from another.+ /**+ * This constructor moves a resolver from one object to another.+ *+ * @param other The other basic_resolver object from which the move will+ * occur.+ *+ * @note Following the move, the moved-from object is in the same state as if+ * constructed using the @c basic_resolver(const executor_type&) constructor.+ */+ template <typename Executor1>+ basic_resolver(basic_resolver<InternetProtocol, Executor1>&& other,+ typename constraint<+ is_convertible<Executor1, Executor>::value+ >::type = 0)+ : impl_(std::move(other.impl_))+ {+ }+ /// Move-assign a basic_resolver from another. /** * This assignment operator moves a resolver from one object to another.@@ -159,6 +185,29 @@ impl_ = std::move(other.impl_); return *this; }++ /// Move-assign a basic_resolver from another.+ /**+ * This assignment operator moves a resolver from one object to another.+ * Cancels any outstanding asynchronous operations associated with the target+ * object.+ *+ * @param other The other basic_resolver object from which the move will+ * occur.+ *+ * @note Following the move, the moved-from object is in the same state as if+ * constructed using the @c basic_resolver(const executor_type&) constructor.+ */+ template <typename Executor1>+ typename constraint<+ is_convertible<Executor1, Executor>::value,+ basic_resolver&+ >::type operator=(basic_resolver<InternetProtocol, Executor1>&& other)+ {+ basic_resolver tmp(std::move(other));+ impl_ = std::move(tmp.impl_);+ return *this;+ } #endif // defined(ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION) /// Destroys the resolver.@@ -601,38 +650,48 @@ /// Asynchronously perform forward resolution of a query to a list of entries. /** * This function is used to asynchronously resolve a query into a list of- * endpoint entries.+ * endpoint entries. It is an initiating function for an @ref+ * asynchronous_operation, and always returns immediately. * * @param q A query object that determines what endpoints will be returned. *- * @param handler The handler to be called when the resolve operation- * completes. Copies will be made of the handler as required. The function- * signature of the handler must be:+ * @param token The @ref completion_token that will be used to produce a+ * completion handler, which will be called when the resolve completes.+ * Potential completion tokens include @ref use_future, @ref use_awaitable,+ * @ref yield_context, or a function object with the correct completion+ * signature. The function signature of the completion handler must be: * @code void handler( * const asio::error_code& error, // Result of operation. * resolver::results_type results // Resolved endpoints as a range. * ); @endcode * Regardless of whether the asynchronous operation completes immediately or- * not, the handler will not be invoked from within this function. On- * immediate completion, invocation of the handler will be performed in a+ * not, the completion handler will not be invoked from within this function.+ * On immediate completion, invocation of the handler will be performed in a * manner equivalent to using asio::post(). * * A successful resolve operation is guaranteed to pass a non-empty range to * the handler.+ *+ * @par Completion Signature+ * @code void(asio::error_code, results_type) @endcode */ template < ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code,- results_type)) ResolveHandler+ results_type)) ResolveToken ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(executor_type)>- ASIO_INITFN_AUTO_RESULT_TYPE(ResolveHandler,+ ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX(ResolveToken, void (asio::error_code, results_type)) async_resolve(const query& q,- ASIO_MOVE_ARG(ResolveHandler) handler+ ASIO_MOVE_ARG(ResolveToken) token ASIO_DEFAULT_COMPLETION_TOKEN(executor_type))+ ASIO_INITFN_AUTO_RESULT_TYPE_SUFFIX((+ asio::async_initiate<ResolveToken,+ void (asio::error_code, results_type)>(+ declval<initiate_async_resolve>(), token, q))) {- return asio::async_initiate<ResolveHandler,+ return asio::async_initiate<ResolveToken, void (asio::error_code, results_type)>(- initiate_async_resolve(this), handler, q);+ initiate_async_resolve(this), token, q); } #endif // !defined(ASIO_NO_DEPRECATED) @@ -652,21 +711,26 @@ * be an empty string, in which case all resolved endpoints will have a port * number of 0. *- * @param handler The handler to be called when the resolve operation- * completes. Copies will be made of the handler as required. The function- * signature of the handler must be:+ * @param token The @ref completion_token that will be used to produce a+ * completion handler, which will be called when the resolve completes.+ * Potential completion tokens include @ref use_future, @ref use_awaitable,+ * @ref yield_context, or a function object with the correct completion+ * signature. The function signature of the completion handler must be: * @code void handler( * const asio::error_code& error, // Result of operation. * resolver::results_type results // Resolved endpoints as a range. * ); @endcode * Regardless of whether the asynchronous operation completes immediately or- * not, the handler will not be invoked from within this function. On- * immediate completion, invocation of the handler will be performed in a+ * not, the completion handler will not be invoked from within this function.+ * On immediate completion, invocation of the handler will be performed in a * manner equivalent to using asio::post(). * * A successful resolve operation is guaranteed to pass a non-empty range to * the handler. *+ * @par Completion Signature+ * @code void(asio::error_code, results_type) @endcode+ * * @note On POSIX systems, host names may be locally defined in the file * <tt>/etc/hosts</tt>. On Windows, host names may be defined in the file * <tt>c:\\windows\\system32\\drivers\\etc\\hosts</tt>. Remote host name@@ -680,23 +744,29 @@ */ template < ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code,- results_type)) ResolveHandler+ results_type)) ResolveToken ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(executor_type)>- ASIO_INITFN_AUTO_RESULT_TYPE(ResolveHandler,+ ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX(ResolveToken, void (asio::error_code, results_type)) async_resolve(ASIO_STRING_VIEW_PARAM host, ASIO_STRING_VIEW_PARAM service,- ASIO_MOVE_ARG(ResolveHandler) handler+ ASIO_MOVE_ARG(ResolveToken) token ASIO_DEFAULT_COMPLETION_TOKEN(executor_type))+ ASIO_INITFN_AUTO_RESULT_TYPE_SUFFIX((+ asio::async_initiate<ResolveToken,+ void (asio::error_code, results_type)>(+ declval<initiate_async_resolve>(), token,+ declval<basic_resolver_query<protocol_type>&>()))) { return async_resolve(host, service, resolver_base::flags(),- ASIO_MOVE_CAST(ResolveHandler)(handler));+ ASIO_MOVE_CAST(ResolveToken)(token)); } /// Asynchronously perform forward resolution of a query to a list of entries. /** * This function is used to resolve host and service names into a list of- * endpoint entries.+ * endpoint entries. It is an initiating function for an @ref+ * asynchronous_operation, and always returns immediately. * * @param host A string identifying a location. May be a descriptive name or * a numeric address string. If an empty string and the passive flag has been@@ -714,21 +784,26 @@ * remote hosts. See the @ref resolver_base documentation for the set of * available flags. *- * @param handler The handler to be called when the resolve operation- * completes. Copies will be made of the handler as required. The function- * signature of the handler must be:+ * @param token The @ref completion_token that will be used to produce a+ * completion handler, which will be called when the resolve completes.+ * Potential completion tokens include @ref use_future, @ref use_awaitable,+ * @ref yield_context, or a function object with the correct completion+ * signature. The function signature of the completion handler must be: * @code void handler( * const asio::error_code& error, // Result of operation. * resolver::results_type results // Resolved endpoints as a range. * ); @endcode * Regardless of whether the asynchronous operation completes immediately or- * not, the handler will not be invoked from within this function. On- * immediate completion, invocation of the handler will be performed in a+ * not, the completion handler will not be invoked from within this function.+ * On immediate completion, invocation of the handler will be performed in a * manner equivalent to using asio::post(). * * A successful resolve operation is guaranteed to pass a non-empty range to * the handler. *+ * @par Completion Signature+ * @code void(asio::error_code, results_type) @endcode+ * * @note On POSIX systems, host names may be locally defined in the file * <tt>/etc/hosts</tt>. On Windows, host names may be defined in the file * <tt>c:\\windows\\system32\\drivers\\etc\\hosts</tt>. Remote host name@@ -742,28 +817,34 @@ */ template < ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code,- results_type)) ResolveHandler+ results_type)) ResolveToken ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(executor_type)>- ASIO_INITFN_AUTO_RESULT_TYPE(ResolveHandler,+ ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX(ResolveToken, void (asio::error_code, results_type)) async_resolve(ASIO_STRING_VIEW_PARAM host, ASIO_STRING_VIEW_PARAM service, resolver_base::flags resolve_flags,- ASIO_MOVE_ARG(ResolveHandler) handler+ ASIO_MOVE_ARG(ResolveToken) token ASIO_DEFAULT_COMPLETION_TOKEN(executor_type))+ ASIO_INITFN_AUTO_RESULT_TYPE_SUFFIX((+ asio::async_initiate<ResolveToken,+ void (asio::error_code, results_type)>(+ declval<initiate_async_resolve>(), token,+ declval<basic_resolver_query<protocol_type>&>()))) { basic_resolver_query<protocol_type> q(static_cast<std::string>(host), static_cast<std::string>(service), resolve_flags); - return asio::async_initiate<ResolveHandler,+ return asio::async_initiate<ResolveToken, void (asio::error_code, results_type)>(- initiate_async_resolve(this), handler, q);+ initiate_async_resolve(this), token, q); } /// Asynchronously perform forward resolution of a query to a list of entries. /** * This function is used to resolve host and service names into a list of- * endpoint entries.+ * endpoint entries. It is an initiating function for an @ref+ * asynchronous_operation, and always returns immediately. * * @param protocol A protocol object, normally representing either the IPv4 or * IPv6 version of an internet protocol.@@ -779,21 +860,26 @@ * be an empty string, in which case all resolved endpoints will have a port * number of 0. *- * @param handler The handler to be called when the resolve operation- * completes. Copies will be made of the handler as required. The function- * signature of the handler must be:+ * @param token The @ref completion_token that will be used to produce a+ * completion handler, which will be called when the resolve completes.+ * Potential completion tokens include @ref use_future, @ref use_awaitable,+ * @ref yield_context, or a function object with the correct completion+ * signature. The function signature of the completion handler must be: * @code void handler( * const asio::error_code& error, // Result of operation. * resolver::results_type results // Resolved endpoints as a range. * ); @endcode * Regardless of whether the asynchronous operation completes immediately or- * not, the handler will not be invoked from within this function. On- * immediate completion, invocation of the handler will be performed in a+ * not, the completion handler will not be invoked from within this function.+ * On immediate completion, invocation of the handler will be performed in a * manner equivalent to using asio::post(). * * A successful resolve operation is guaranteed to pass a non-empty range to * the handler. *+ * @par Completion Signature+ * @code void(asio::error_code, results_type) @endcode+ * * @note On POSIX systems, host names may be locally defined in the file * <tt>/etc/hosts</tt>. On Windows, host names may be defined in the file * <tt>c:\\windows\\system32\\drivers\\etc\\hosts</tt>. Remote host name@@ -807,23 +893,29 @@ */ template < ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code,- results_type)) ResolveHandler+ results_type)) ResolveToken ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(executor_type)>- ASIO_INITFN_AUTO_RESULT_TYPE(ResolveHandler,+ ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX(ResolveToken, void (asio::error_code, results_type)) async_resolve(const protocol_type& protocol, ASIO_STRING_VIEW_PARAM host, ASIO_STRING_VIEW_PARAM service,- ASIO_MOVE_ARG(ResolveHandler) handler+ ASIO_MOVE_ARG(ResolveToken) token ASIO_DEFAULT_COMPLETION_TOKEN(executor_type))+ ASIO_INITFN_AUTO_RESULT_TYPE_SUFFIX((+ asio::async_initiate<ResolveToken,+ void (asio::error_code, results_type)>(+ declval<initiate_async_resolve>(), token,+ declval<basic_resolver_query<protocol_type>&>()))) { return async_resolve(protocol, host, service, resolver_base::flags(),- ASIO_MOVE_CAST(ResolveHandler)(handler));+ ASIO_MOVE_CAST(ResolveToken)(token)); } /// Asynchronously perform forward resolution of a query to a list of entries. /** * This function is used to resolve host and service names into a list of- * endpoint entries.+ * endpoint entries. It is an initiating function for an @ref+ * asynchronous_operation, and always returns immediately. * * @param protocol A protocol object, normally representing either the IPv4 or * IPv6 version of an internet protocol.@@ -844,21 +936,26 @@ * remote hosts. See the @ref resolver_base documentation for the set of * available flags. *- * @param handler The handler to be called when the resolve operation- * completes. Copies will be made of the handler as required. The function- * signature of the handler must be:+ * @param token The @ref completion_token that will be used to produce a+ * completion handler, which will be called when the resolve completes.+ * Potential completion tokens include @ref use_future, @ref use_awaitable,+ * @ref yield_context, or a function object with the correct completion+ * signature. The function signature of the completion handler must be: * @code void handler( * const asio::error_code& error, // Result of operation. * resolver::results_type results // Resolved endpoints as a range. * ); @endcode * Regardless of whether the asynchronous operation completes immediately or- * not, the handler will not be invoked from within this function. On- * immediate completion, invocation of the handler will be performed in a+ * not, the completion handler will not be invoked from within this function.+ * On immediate completion, invocation of the handler will be performed in a * manner equivalent to using asio::post(). * * A successful resolve operation is guaranteed to pass a non-empty range to * the handler. *+ * @par Completion Signature+ * @code void(asio::error_code, results_type) @endcode+ * * @note On POSIX systems, host names may be locally defined in the file * <tt>/etc/hosts</tt>. On Windows, host names may be defined in the file * <tt>c:\\windows\\system32\\drivers\\etc\\hosts</tt>. Remote host name@@ -872,23 +969,28 @@ */ template < ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code,- results_type)) ResolveHandler+ results_type)) ResolveToken ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(executor_type)>- ASIO_INITFN_AUTO_RESULT_TYPE(ResolveHandler,+ ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX(ResolveToken, void (asio::error_code, results_type)) async_resolve(const protocol_type& protocol, ASIO_STRING_VIEW_PARAM host, ASIO_STRING_VIEW_PARAM service, resolver_base::flags resolve_flags,- ASIO_MOVE_ARG(ResolveHandler) handler+ ASIO_MOVE_ARG(ResolveToken) token ASIO_DEFAULT_COMPLETION_TOKEN(executor_type))+ ASIO_INITFN_AUTO_RESULT_TYPE_SUFFIX((+ asio::async_initiate<ResolveToken,+ void (asio::error_code, results_type)>(+ declval<initiate_async_resolve>(), token,+ declval<basic_resolver_query<protocol_type>&>()))) { basic_resolver_query<protocol_type> q( protocol, static_cast<std::string>(host), static_cast<std::string>(service), resolve_flags); - return asio::async_initiate<ResolveHandler,+ return asio::async_initiate<ResolveToken, void (asio::error_code, results_type)>(- initiate_async_resolve(this), handler, q);+ initiate_async_resolve(this), token, q); } /// Perform reverse resolution of an endpoint to a list of entries.@@ -937,39 +1039,49 @@ /// entries. /** * This function is used to asynchronously resolve an endpoint into a list of- * endpoint entries.+ * endpoint entries. It is an initiating function for an @ref+ * asynchronous_operation, and always returns immediately. * * @param e An endpoint object that determines what endpoints will be * returned. *- * @param handler The handler to be called when the resolve operation- * completes. Copies will be made of the handler as required. The function- * signature of the handler must be:+ * @param token The @ref completion_token that will be used to produce a+ * completion handler, which will be called when the resolve completes.+ * Potential completion tokens include @ref use_future, @ref use_awaitable,+ * @ref yield_context, or a function object with the correct completion+ * signature. The function signature of the completion handler must be: * @code void handler( * const asio::error_code& error, // Result of operation. * resolver::results_type results // Resolved endpoints as a range. * ); @endcode * Regardless of whether the asynchronous operation completes immediately or- * not, the handler will not be invoked from within this function. On- * immediate completion, invocation of the handler will be performed in a+ * not, the completion handler will not be invoked from within this function.+ * On immediate completion, invocation of the handler will be performed in a * manner equivalent to using asio::post(). * * A successful resolve operation is guaranteed to pass a non-empty range to * the handler.+ *+ * @par Completion Signature+ * @code void(asio::error_code, results_type) @endcode */ template < ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code,- results_type)) ResolveHandler+ results_type)) ResolveToken ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(executor_type)>- ASIO_INITFN_AUTO_RESULT_TYPE(ResolveHandler,+ ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX(ResolveToken, void (asio::error_code, results_type)) async_resolve(const endpoint_type& e,- ASIO_MOVE_ARG(ResolveHandler) handler+ ASIO_MOVE_ARG(ResolveToken) token ASIO_DEFAULT_COMPLETION_TOKEN(executor_type))+ ASIO_INITFN_AUTO_RESULT_TYPE_SUFFIX((+ asio::async_initiate<ResolveToken,+ void (asio::error_code, results_type)>(+ declval<initiate_async_resolve>(), token, e))) {- return asio::async_initiate<ResolveHandler,+ return asio::async_initiate<ResolveToken, void (asio::error_code, results_type)>(- initiate_async_resolve(this), handler, e);+ initiate_async_resolve(this), token, e); } private:
link/modules/asio-standalone/asio/include/asio/ip/basic_resolver_entry.hpp view
@@ -2,7 +2,7 @@ // ip/basic_resolver_entry.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/ip/basic_resolver_iterator.hpp view
@@ -2,7 +2,7 @@ // ip/basic_resolver_iterator.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/ip/basic_resolver_query.hpp view
@@ -2,7 +2,7 @@ // ip/basic_resolver_query.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/ip/basic_resolver_results.hpp view
@@ -2,7 +2,7 @@ // ip/basic_resolver_results.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/ip/detail/endpoint.hpp view
@@ -2,7 +2,7 @@ // ip/detail/endpoint.hpp // ~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/ip/detail/impl/endpoint.ipp view
@@ -2,7 +2,7 @@ // ip/detail/impl/endpoint.ipp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/ip/detail/socket_option.hpp view
@@ -2,7 +2,7 @@ // detail/socket_option.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/ip/host_name.hpp view
@@ -2,7 +2,7 @@ // ip/host_name.hpp // ~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/ip/icmp.hpp view
@@ -2,7 +2,7 @@ // ip/icmp.hpp // ~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/ip/impl/address.hpp view
@@ -2,7 +2,7 @@ // ip/impl/address.hpp // ~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/ip/impl/address.ipp view
@@ -2,7 +2,7 @@ // ip/impl/address.ipp // ~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/ip/impl/address_v4.hpp view
@@ -2,7 +2,7 @@ // ip/impl/address_v4.hpp // ~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/ip/impl/address_v4.ipp view
@@ -2,7 +2,7 @@ // ip/impl/address_v4.ipp // ~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/ip/impl/address_v6.hpp view
@@ -2,7 +2,7 @@ // ip/impl/address_v6.hpp // ~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/ip/impl/address_v6.ipp view
@@ -2,7 +2,7 @@ // ip/impl/address_v6.ipp // ~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -38,7 +38,7 @@ } address_v6::address_v6(const address_v6::bytes_type& bytes,- unsigned long scope)+ scope_id_type scope) : scope_id_(scope) { #if UCHAR_MAX > 0xFF
link/modules/asio-standalone/asio/include/asio/ip/impl/basic_endpoint.hpp view
@@ -2,7 +2,7 @@ // ip/impl/basic_endpoint.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/ip/impl/host_name.ipp view
@@ -2,7 +2,7 @@ // ip/impl/host_name.ipp // ~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/ip/impl/network_v4.hpp view
@@ -2,7 +2,7 @@ // ip/impl/network_v4.hpp // ~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // Copyright (c) 2014 Oliver Kowalke (oliver dot kowalke at gmail dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying
link/modules/asio-standalone/asio/include/asio/ip/impl/network_v4.ipp view
@@ -2,7 +2,7 @@ // ip/impl/network_v4.ipp // ~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // Copyright (c) 2014 Oliver Kowalke (oliver dot kowalke at gmail dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying@@ -129,7 +129,9 @@ using namespace std; // For sprintf. ec = asio::error_code(); char prefix_len[16];-#if defined(ASIO_HAS_SECURE_RTL)+#if defined(ASIO_HAS_SNPRINTF)+ snprintf(prefix_len, sizeof(prefix_len), "/%u", prefix_length_);+#elif defined(ASIO_HAS_SECURE_RTL) sprintf_s(prefix_len, sizeof(prefix_len), "/%u", prefix_length_); #else // defined(ASIO_HAS_SECURE_RTL) sprintf(prefix_len, "/%u", prefix_length_);
link/modules/asio-standalone/asio/include/asio/ip/impl/network_v6.hpp view
@@ -2,7 +2,7 @@ // ip/impl/network_v6.hpp // ~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/ip/impl/network_v6.ipp view
@@ -2,7 +2,7 @@ // ip/impl/network_v6.ipp // ~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // Copyright (c) 2014 Oliver Kowalke (oliver dot kowalke at gmail dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying@@ -98,7 +98,9 @@ using namespace std; // For sprintf. ec = asio::error_code(); char prefix_len[16];-#if defined(ASIO_HAS_SECURE_RTL)+#if defined(ASIO_HAS_SNPRINTF)+ snprintf(prefix_len, sizeof(prefix_len), "/%u", prefix_length_);+#elif defined(ASIO_HAS_SECURE_RTL) sprintf_s(prefix_len, sizeof(prefix_len), "/%u", prefix_length_); #else // defined(ASIO_HAS_SECURE_RTL) sprintf(prefix_len, "/%u", prefix_length_);
link/modules/asio-standalone/asio/include/asio/ip/multicast.hpp view
@@ -2,7 +2,7 @@ // ip/multicast.hpp // ~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/ip/network_v4.hpp view
@@ -2,7 +2,7 @@ // ip/network_v4.hpp // ~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // Copyright (c) 2014 Oliver Kowalke (oliver dot kowalke at gmail dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying@@ -122,7 +122,7 @@ /// Obtain the true network address, omitting any host bits. network_v4 canonical() const ASIO_NOEXCEPT {- return network_v4(network(), netmask());+ return network_v4(network(), prefix_length()); } /// Test if network is a valid host address.
link/modules/asio-standalone/asio/include/asio/ip/network_v6.hpp view
@@ -2,7 +2,7 @@ // ip/network_v6.hpp // ~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // Copyright (c) 2014 Oliver Kowalke (oliver dot kowalke at gmail dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying
link/modules/asio-standalone/asio/include/asio/ip/resolver_base.hpp view
@@ -2,7 +2,7 @@ // ip/resolver_base.hpp // ~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/ip/resolver_query_base.hpp view
@@ -2,7 +2,7 @@ // ip/resolver_query_base.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/ip/tcp.hpp view
@@ -2,7 +2,7 @@ // ip/tcp.hpp // ~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/ip/udp.hpp view
@@ -2,7 +2,7 @@ // ip/udp.hpp // ~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/ip/unicast.hpp view
@@ -2,7 +2,7 @@ // ip/unicast.hpp // ~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/ip/v6_only.hpp view
@@ -2,7 +2,7 @@ // ip/v6_only.hpp // ~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -26,7 +26,7 @@ /// Socket option for determining whether an IPv6 socket supports IPv6 /// communication only. /**- * Implements the IPPROTO_IPV6/IP_V6ONLY socket option.+ * Implements the IPPROTO_IPV6/IPV6_V6ONLY socket option. * * @par Examples * Setting the option:
link/modules/asio-standalone/asio/include/asio/is_applicable_property.hpp view
@@ -2,7 +2,7 @@ // is_applicable_property.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+ link/modules/asio-standalone/asio/include/asio/is_contiguous_iterator.hpp view
@@ -0,0 +1,45 @@+//+// is_contiguous_iterator.hpp+// ~~~~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com)+//+// Distributed under the Boost Software License, Version 1.0. (See accompanying+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)+//++#ifndef ASIO_IS_CONTIGUOUS_ITERATOR_HPP+#define ASIO_IS_CONTIGUOUS_ITERATOR_HPP++#if defined(_MSC_VER) && (_MSC_VER >= 1200)+# pragma once+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)++#include "asio/detail/config.hpp"+#include <iterator>+#include "asio/detail/type_traits.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {++/// The is_contiguous_iterator class is a traits class that may be used to+/// determine whether a type is a contiguous iterator.+template <typename T>+struct is_contiguous_iterator :+#if defined(ASIO_HAS_STD_CONCEPTS) \+ || defined(GENERATING_DOCUMENTATION)+ integral_constant<bool, std::contiguous_iterator<T> >+#else // defined(ASIO_HAS_STD_CONCEPTS)+ // || defined(GENERATING_DOCUMENTATION)+ is_pointer<T>+#endif // defined(ASIO_HAS_STD_CONCEPTS)+ // || defined(GENERATING_DOCUMENTATION)+{+};++} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // ASIO_IS_CONTIGUOUS_ITERATOR_HPP
link/modules/asio-standalone/asio/include/asio/is_executor.hpp view
@@ -2,7 +2,7 @@ // is_executor.hpp // ~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/is_read_buffered.hpp view
@@ -2,7 +2,7 @@ // is_read_buffered.hpp // ~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/is_write_buffered.hpp view
@@ -2,7 +2,7 @@ // is_write_buffered.hpp // ~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/local/basic_endpoint.hpp view
@@ -2,7 +2,7 @@ // local/basic_endpoint.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // Derived from a public domain implementation written by Daniel Casimiro. // // Distributed under the Boost Software License, Version 1.0. (See accompanying
link/modules/asio-standalone/asio/include/asio/local/connect_pair.hpp view
@@ -2,7 +2,7 @@ // local/connect_pair.hpp // ~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/local/datagram_protocol.hpp view
@@ -2,7 +2,7 @@ // local/datagram_protocol.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/local/detail/endpoint.hpp view
@@ -2,7 +2,7 @@ // local/detail/endpoint.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // Derived from a public domain implementation written by Daniel Casimiro. // // Distributed under the Boost Software License, Version 1.0. (See accompanying
link/modules/asio-standalone/asio/include/asio/local/detail/impl/endpoint.ipp view
@@ -2,7 +2,7 @@ // local/detail/impl/endpoint.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // Derived from a public domain implementation written by Daniel Casimiro. // // Distributed under the Boost Software License, Version 1.0. (See accompanying@@ -112,17 +112,12 @@ asio::detail::throw_error(ec); } - using namespace std; // For memcpy.- data_.local = asio::detail::sockaddr_un_type();+ using namespace std; // For memset and memcpy.+ memset(&data_.local, 0, sizeof(asio::detail::sockaddr_un_type)); data_.local.sun_family = AF_UNIX; if (path_length > 0) memcpy(data_.local.sun_path, path_name, path_length); path_length_ = path_length;-- // NUL-terminate normal path names. Names that start with a NUL are in the- // UNIX domain protocol's "abstract namespace" and are not NUL-terminated.- if (path_length > 0 && data_.local.sun_path[0] == 0)- data_.local.sun_path[path_length] = 0; } } // namespace detail
+ link/modules/asio-standalone/asio/include/asio/local/seq_packet_protocol.hpp view
@@ -0,0 +1,84 @@+//+// local/seq_packet_protocol.hpp+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com)+//+// Distributed under the Boost Software License, Version 1.0. (See accompanying+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)+//++#ifndef ASIO_LOCAL_SEQ_PACKET_PROTOCOL_HPP+#define ASIO_LOCAL_SEQ_PACKET_PROTOCOL_HPP++#if defined(_MSC_VER) && (_MSC_VER >= 1200)+# pragma once+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)++#include "asio/detail/config.hpp"++#if defined(ASIO_HAS_LOCAL_SOCKETS) \+ || defined(GENERATING_DOCUMENTATION)++#include "asio/basic_socket_acceptor.hpp"+#include "asio/basic_seq_packet_socket.hpp"+#include "asio/detail/socket_types.hpp"+#include "asio/local/basic_endpoint.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {+namespace local {++/// Encapsulates the flags needed for seq_packet UNIX sockets.+/**+ * The asio::local::seq_packet_protocol class contains flags necessary+ * for sequenced packet UNIX domain sockets.+ *+ * @par Thread Safety+ * @e Distinct @e objects: Safe.@n+ * @e Shared @e objects: Safe.+ *+ * @par Concepts:+ * Protocol.+ */+class seq_packet_protocol+{+public:+ /// Obtain an identifier for the type of the protocol.+ int type() const ASIO_NOEXCEPT+ {+ return SOCK_SEQPACKET;+ }++ /// Obtain an identifier for the protocol.+ int protocol() const ASIO_NOEXCEPT+ {+ return 0;+ }++ /// Obtain an identifier for the protocol family.+ int family() const ASIO_NOEXCEPT+ {+ return AF_UNIX;+ }++ /// The type of a UNIX domain endpoint.+ typedef basic_endpoint<seq_packet_protocol> endpoint;++ /// The UNIX domain socket type.+ typedef basic_seq_packet_socket<seq_packet_protocol> socket;++ /// The UNIX domain acceptor type.+ typedef basic_socket_acceptor<seq_packet_protocol> acceptor;+};++} // namespace local+} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // defined(ASIO_HAS_LOCAL_SOCKETS)+ // || defined(GENERATING_DOCUMENTATION)++#endif // ASIO_LOCAL_SEQ_PACKET_PROTOCOL_HPP
link/modules/asio-standalone/asio/include/asio/local/stream_protocol.hpp view
@@ -2,7 +2,7 @@ // local/stream_protocol.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/multiple_exceptions.hpp view
@@ -2,7 +2,7 @@ // multiple_exceptions.hpp // ~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/packaged_task.hpp view
@@ -2,7 +2,7 @@ // packaged_task.hpp // ~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/placeholders.hpp view
@@ -2,7 +2,7 @@ // placeholders.hpp // ~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/posix/basic_descriptor.hpp view
@@ -2,7 +2,7 @@ // posix/basic_descriptor.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -25,12 +25,17 @@ #include "asio/detail/handler_type_requirements.hpp" #include "asio/detail/io_object_impl.hpp" #include "asio/detail/non_const_lvalue.hpp"-#include "asio/detail/reactive_descriptor_service.hpp" #include "asio/detail/throw_error.hpp" #include "asio/error.hpp" #include "asio/execution_context.hpp" #include "asio/posix/descriptor_base.hpp" +#if defined(ASIO_HAS_IO_URING_AS_DEFAULT)+# include "asio/detail/io_uring_descriptor_service.hpp"+#else // defined(ASIO_HAS_IO_URING_AS_DEFAULT)+# include "asio/detail/reactive_descriptor_service.hpp"+#endif // defined(ASIO_HAS_IO_URING_AS_DEFAULT)+ #if defined(ASIO_HAS_MOVE) # include <utility> #endif // defined(ASIO_HAS_MOVE)@@ -53,6 +58,9 @@ class basic_descriptor : public descriptor_base {+private:+ class initiate_async_wait;+ public: /// The type of the executor associated with the object. typedef Executor executor_type;@@ -68,10 +76,13 @@ /// The native representation of a descriptor. #if defined(GENERATING_DOCUMENTATION) typedef implementation_defined native_handle_type;-#else+#elif defined(ASIO_HAS_IO_URING_AS_DEFAULT)+ typedef detail::io_uring_descriptor_service::native_handle_type+ native_handle_type;+#else // defined(ASIO_HAS_IO_URING_AS_DEFAULT) typedef detail::reactive_descriptor_service::native_handle_type native_handle_type;-#endif+#endif // defined(ASIO_HAS_IO_URING_AS_DEFAULT) /// A descriptor is always the lowest layer. typedef basic_descriptor lowest_layer_type;@@ -85,7 +96,7 @@ * descriptor. */ explicit basic_descriptor(const executor_type& ex)- : impl_(ex)+ : impl_(0, ex) { } @@ -99,10 +110,11 @@ */ template <typename ExecutionContext> explicit basic_descriptor(ExecutionContext& context,- typename enable_if<- is_convertible<ExecutionContext&, execution_context&>::value- >::type* = 0)- : impl_(context)+ typename constraint<+ is_convertible<ExecutionContext&, execution_context&>::value,+ defaulted_constraint+ >::type = defaulted_constraint())+ : impl_(0, 0, context) { } @@ -121,7 +133,7 @@ */ basic_descriptor(const executor_type& ex, const native_handle_type& native_descriptor)- : impl_(ex)+ : impl_(0, ex) { asio::error_code ec; impl_.get_service().assign(impl_.get_implementation(),@@ -145,10 +157,10 @@ template <typename ExecutionContext> basic_descriptor(ExecutionContext& context, const native_handle_type& native_descriptor,- typename enable_if<+ typename constraint< is_convertible<ExecutionContext&, execution_context&>::value- >::type* = 0)- : impl_(context)+ >::type = 0)+ : impl_(0, 0, context) { asio::error_code ec; impl_.get_service().assign(impl_.get_implementation(),@@ -189,10 +201,58 @@ impl_ = std::move(other.impl_); return *this; }++ // All descriptors have access to each other's implementations.+ template <typename Executor1>+ friend class basic_descriptor;++ /// Move-construct a basic_descriptor from a descriptor of another executor+ /// type.+ /**+ * This constructor moves a descriptor from one object to another.+ *+ * @param other The other basic_descriptor object from which the move will+ * occur.+ *+ * @note Following the move, the moved-from object is in the same state as if+ * constructed using the @c basic_descriptor(const executor_type&)+ * constructor.+ */+ template <typename Executor1>+ basic_descriptor(basic_descriptor<Executor1>&& other,+ typename constraint<+ is_convertible<Executor1, Executor>::value,+ defaulted_constraint+ >::type = defaulted_constraint())+ : impl_(std::move(other.impl_))+ {+ }++ /// Move-assign a basic_descriptor from a descriptor of another executor type.+ /**+ * This assignment operator moves a descriptor from one object to another.+ *+ * @param other The other basic_descriptor object from which the move will+ * occur.+ *+ * @note Following the move, the moved-from object is in the same state as if+ * constructed using the @c basic_descriptor(const executor_type&)+ * constructor.+ */+ template <typename Executor1>+ typename constraint<+ is_convertible<Executor1, Executor>::value,+ basic_descriptor&+ >::type operator=(basic_descriptor<Executor1> && other)+ {+ basic_descriptor tmp(std::move(other));+ impl_ = std::move(tmp.impl_);+ return *this;+ } #endif // defined(ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION) /// Get the executor associated with the object.- executor_type get_executor() ASIO_NOEXCEPT+ const executor_type& get_executor() ASIO_NOEXCEPT { return impl_.get_executor(); }@@ -588,21 +648,28 @@ /// write, or to have pending error conditions. /** * This function is used to perform an asynchronous wait for a descriptor to- * enter a ready to read, write or error condition state.+ * enter a ready to read, write or error condition state. It is an initiating+ * function for an @ref asynchronous_operation, and always returns+ * immediately. * * @param w Specifies the desired descriptor state. *- * @param handler The handler to be called when the wait operation completes.- * Copies will be made of the handler as required. The function signature of- * the handler must be:+ * @param token The @ref completion_token that will be used to produce a+ * completion handler, which will be called when the wait completes.+ * Potential completion tokens include @ref use_future, @ref use_awaitable,+ * @ref yield_context, or a function object with the correct completion+ * signature. The function signature of the completion handler must be: * @code void handler(- * const asio::error_code& error // Result of operation+ * const asio::error_code& error // Result of operation. * ); @endcode * Regardless of whether the asynchronous operation completes immediately or- * not, the handler will not be invoked from within this function. On- * immediate completion, invocation of the handler will be performed in a+ * not, the completion handler will not be invoked from within this function.+ * On immediate completion, invocation of the handler will be performed in a * manner equivalent to using asio::post(). *+ * @par Completion Signature+ * @code void(asio::error_code) @endcode+ * * @par Example * @code * void wait_handler(const asio::error_code& error)@@ -621,18 +688,31 @@ * asio::posix::stream_descriptor::wait_read, * wait_handler); * @endcode+ *+ * @par Per-Operation Cancellation+ * This asynchronous operation supports cancellation for the following+ * asio::cancellation_type values:+ *+ * @li @c cancellation_type::terminal+ *+ * @li @c cancellation_type::partial+ *+ * @li @c cancellation_type::total */ template < ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code))- WaitHandler ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(executor_type)>- ASIO_INITFN_AUTO_RESULT_TYPE(WaitHandler,+ WaitToken ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(executor_type)>+ ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX(WaitToken, void (asio::error_code)) async_wait(wait_type w,- ASIO_MOVE_ARG(WaitHandler) handler+ ASIO_MOVE_ARG(WaitToken) token ASIO_DEFAULT_COMPLETION_TOKEN(executor_type))+ ASIO_INITFN_AUTO_RESULT_TYPE_SUFFIX((+ async_initiate<WaitToken, void (asio::error_code)>(+ declval<initiate_async_wait>(), token, w))) {- return async_initiate<WaitHandler, void (asio::error_code)>(- initiate_async_wait(this), handler, w);+ return async_initiate<WaitToken, void (asio::error_code)>(+ initiate_async_wait(this), token, w); } protected:@@ -646,7 +726,11 @@ { } +#if defined(ASIO_HAS_IO_URING_AS_DEFAULT)+ detail::io_object_impl<detail::io_uring_descriptor_service, Executor> impl_;+#else // defined(ASIO_HAS_IO_URING_AS_DEFAULT) detail::io_object_impl<detail::reactive_descriptor_service, Executor> impl_;+#endif // defined(ASIO_HAS_IO_URING_AS_DEFAULT) private: // Disallow copying and assignment.@@ -663,7 +747,7 @@ { } - executor_type get_executor() const ASIO_NOEXCEPT+ const executor_type& get_executor() const ASIO_NOEXCEPT { return self_->get_executor(); }
link/modules/asio-standalone/asio/include/asio/posix/basic_stream_descriptor.hpp view
@@ -2,7 +2,7 @@ // posix/basic_stream_descriptor.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -16,11 +16,13 @@ #endif // defined(_MSC_VER) && (_MSC_VER >= 1200) #include "asio/detail/config.hpp"-#include "asio/posix/descriptor.hpp"+#include "asio/posix/basic_descriptor.hpp" #if defined(ASIO_HAS_POSIX_STREAM_DESCRIPTOR) \ || defined(GENERATING_DOCUMENTATION) +#include "asio/detail/push_options.hpp"+ namespace asio { namespace posix { @@ -33,6 +35,12 @@ * @e Distinct @e objects: Safe.@n * @e Shared @e objects: Unsafe. *+ * Synchronous @c read_some and @c write_some operations are thread safe with+ * respect to each other, if the underlying operating system calls are also+ * thread safe. This means that it is permitted to perform concurrent calls to+ * these synchronous operations on a single descriptor object. Other synchronous+ * operations, such as @c close, are not thread safe.+ * * @par Concepts: * AsyncReadStream, AsyncWriteStream, Stream, SyncReadStream, SyncWriteStream. */@@ -40,6 +48,10 @@ class basic_stream_descriptor : public basic_descriptor<Executor> {+private:+ class initiate_async_write_some;+ class initiate_async_read_some;+ public: /// The type of the executor associated with the object. typedef Executor executor_type;@@ -83,9 +95,10 @@ */ template <typename ExecutionContext> explicit basic_stream_descriptor(ExecutionContext& context,- typename enable_if<- is_convertible<ExecutionContext&, execution_context&>::value- >::type* = 0)+ typename constraint<+ is_convertible<ExecutionContext&, execution_context&>::value,+ defaulted_constraint+ >::type = defaulted_constraint()) : basic_descriptor<Executor>(context) { }@@ -125,9 +138,9 @@ template <typename ExecutionContext> basic_stream_descriptor(ExecutionContext& context, const native_handle_type& native_descriptor,- typename enable_if<+ typename constraint< is_convertible<ExecutionContext&, execution_context&>::value- >::type* = 0)+ >::type = 0) : basic_descriptor<Executor>(context, native_descriptor) { }@@ -145,7 +158,7 @@ * constructor. */ basic_stream_descriptor(basic_stream_descriptor&& other) ASIO_NOEXCEPT- : descriptor(std::move(other))+ : basic_descriptor<Executor>(std::move(other)) { } @@ -163,9 +176,53 @@ */ basic_stream_descriptor& operator=(basic_stream_descriptor&& other) {- descriptor::operator=(std::move(other));+ basic_descriptor<Executor>::operator=(std::move(other)); return *this; }++ /// Move-construct a basic_stream_descriptor from a descriptor of another+ /// executor type.+ /**+ * This constructor moves a descriptor from one object to another.+ *+ * @param other The other basic_stream_descriptor object from which the move+ * will occur.+ *+ * @note Following the move, the moved-from object is in the same state as if+ * constructed using the @c basic_stream_descriptor(const executor_type&)+ * constructor.+ */+ template <typename Executor1>+ basic_stream_descriptor(basic_stream_descriptor<Executor1>&& other,+ typename constraint<+ is_convertible<Executor1, Executor>::value,+ defaulted_constraint+ >::type = defaulted_constraint())+ : basic_descriptor<Executor>(std::move(other))+ {+ }++ /// Move-assign a basic_stream_descriptor from a descriptor of another+ /// executor type.+ /**+ * This assignment operator moves a descriptor from one object to another.+ *+ * @param other The other basic_stream_descriptor object from which the move+ * will occur.+ *+ * @note Following the move, the moved-from object is in the same state as if+ * constructed using the @c basic_stream_descriptor(const executor_type&)+ * constructor.+ */+ template <typename Executor1>+ typename constraint<+ is_convertible<Executor1, Executor>::value,+ basic_stream_descriptor&+ >::type operator=(basic_stream_descriptor<Executor1> && other)+ {+ basic_descriptor<Executor>::operator=(std::move(other));+ return *this;+ } #endif // defined(ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION) /// Write some data to the descriptor.@@ -232,25 +289,31 @@ /// Start an asynchronous write. /** * This function is used to asynchronously write data to the stream- * descriptor. The function call always returns immediately.+ * descriptor. It is an initiating function for an @ref+ * asynchronous_operation, and always returns immediately. * * @param buffers One or more data buffers to be written to the descriptor. * Although the buffers object may be copied as necessary, ownership of the * underlying memory blocks is retained by the caller, which must guarantee- * that they remain valid until the handler is called.+ * that they remain valid until the completion handler is called. *- * @param handler The handler to be called when the write operation completes.- * Copies will be made of the handler as required. The function signature of- * the handler must be:+ * @param token The @ref completion_token that will be used to produce a+ * completion handler, which will be called when the write completes.+ * Potential completion tokens include @ref use_future, @ref use_awaitable,+ * @ref yield_context, or a function object with the correct completion+ * signature. The function signature of the completion handler must be: * @code void handler( * const asio::error_code& error, // Result of operation.- * std::size_t bytes_transferred // Number of bytes written.+ * std::size_t bytes_transferred // Number of bytes written. * ); @endcode * Regardless of whether the asynchronous operation completes immediately or- * not, the handler will not be invoked from within this function. On- * immediate completion, invocation of the handler will be performed in a+ * not, the completion handler will not be invoked from within this function.+ * On immediate completion, invocation of the handler will be performed in a * manner equivalent to using asio::post(). *+ * @par Completion Signature+ * @code void(asio::error_code, std::size_t) @endcode+ * * @note The write operation may not transmit all of the data to the peer. * Consider using the @ref async_write function if you need to ensure that all * data is written before the asynchronous operation completes.@@ -263,20 +326,34 @@ * See the @ref buffer documentation for information on writing multiple * buffers in one go, and how to use it with arrays, boost::array or * std::vector.+ *+ * @par Per-Operation Cancellation+ * This asynchronous operation supports cancellation for the following+ * asio::cancellation_type values:+ *+ * @li @c cancellation_type::terminal+ *+ * @li @c cancellation_type::partial+ *+ * @li @c cancellation_type::total */ template <typename ConstBufferSequence, ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code,- std::size_t)) WriteHandler+ std::size_t)) WriteToken ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(executor_type)>- ASIO_INITFN_AUTO_RESULT_TYPE(WriteHandler,+ ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX(WriteToken, void (asio::error_code, std::size_t)) async_write_some(const ConstBufferSequence& buffers,- ASIO_MOVE_ARG(WriteHandler) handler+ ASIO_MOVE_ARG(WriteToken) token ASIO_DEFAULT_COMPLETION_TOKEN(executor_type))+ ASIO_INITFN_AUTO_RESULT_TYPE_SUFFIX((+ async_initiate<WriteToken,+ void (asio::error_code, std::size_t)>(+ initiate_async_write_some(this), token, buffers))) {- return async_initiate<WriteHandler,+ return async_initiate<WriteToken, void (asio::error_code, std::size_t)>(- initiate_async_write_some(this), handler, buffers);+ initiate_async_write_some(this), token, buffers); } /// Read some data from the descriptor.@@ -345,25 +422,31 @@ /// Start an asynchronous read. /** * This function is used to asynchronously read data from the stream- * descriptor. The function call always returns immediately.+ * descriptor. It is an initiating function for an @ref+ * asynchronous_operation, and always returns immediately. * * @param buffers One or more buffers into which the data will be read. * Although the buffers object may be copied as necessary, ownership of the * underlying memory blocks is retained by the caller, which must guarantee- * that they remain valid until the handler is called.+ * that they remain valid until the completion handler is called. *- * @param handler The handler to be called when the read operation completes.- * Copies will be made of the handler as required. The function signature of- * the handler must be:+ * @param token The @ref completion_token that will be used to produce a+ * completion handler, which will be called when the read completes.+ * Potential completion tokens include @ref use_future, @ref use_awaitable,+ * @ref yield_context, or a function object with the correct completion+ * signature. The function signature of the completion handler must be: * @code void handler( * const asio::error_code& error, // Result of operation.- * std::size_t bytes_transferred // Number of bytes read.+ * std::size_t bytes_transferred // Number of bytes read. * ); @endcode * Regardless of whether the asynchronous operation completes immediately or- * not, the handler will not be invoked from within this function. On- * immediate completion, invocation of the handler will be performed in a+ * not, the completion handler will not be invoked from within this function.+ * On immediate completion, invocation of the handler will be performed in a * manner equivalent to using asio::post(). *+ * @par Completion Signature+ * @code void(asio::error_code, std::size_t) @endcode+ * * @note The read operation may not read all of the requested number of bytes. * Consider using the @ref async_read function if you need to ensure that the * requested amount of data is read before the asynchronous operation@@ -377,20 +460,34 @@ * See the @ref buffer documentation for information on reading into multiple * buffers in one go, and how to use it with arrays, boost::array or * std::vector.+ *+ * @par Per-Operation Cancellation+ * This asynchronous operation supports cancellation for the following+ * asio::cancellation_type values:+ *+ * @li @c cancellation_type::terminal+ *+ * @li @c cancellation_type::partial+ *+ * @li @c cancellation_type::total */ template <typename MutableBufferSequence, ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code,- std::size_t)) ReadHandler+ std::size_t)) ReadToken ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(executor_type)>- ASIO_INITFN_AUTO_RESULT_TYPE(ReadHandler,+ ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX(ReadToken, void (asio::error_code, std::size_t)) async_read_some(const MutableBufferSequence& buffers,- ASIO_MOVE_ARG(ReadHandler) handler+ ASIO_MOVE_ARG(ReadToken) token ASIO_DEFAULT_COMPLETION_TOKEN(executor_type))+ ASIO_INITFN_AUTO_RESULT_TYPE_SUFFIX((+ async_initiate<ReadToken,+ void (asio::error_code, std::size_t)>(+ declval<initiate_async_read_some>(), token, buffers))) {- return async_initiate<ReadHandler,+ return async_initiate<ReadToken, void (asio::error_code, std::size_t)>(- initiate_async_read_some(this), handler, buffers);+ initiate_async_read_some(this), token, buffers); } private:@@ -404,7 +501,7 @@ { } - executor_type get_executor() const ASIO_NOEXCEPT+ const executor_type& get_executor() const ASIO_NOEXCEPT { return self_->get_executor(); }@@ -437,7 +534,7 @@ { } - executor_type get_executor() const ASIO_NOEXCEPT+ const executor_type& get_executor() const ASIO_NOEXCEPT { return self_->get_executor(); }@@ -463,6 +560,8 @@ } // namespace posix } // namespace asio++#include "asio/detail/pop_options.hpp" #endif // defined(ASIO_HAS_POSIX_STREAM_DESCRIPTOR) // || defined(GENERATING_DOCUMENTATION)
link/modules/asio-standalone/asio/include/asio/posix/descriptor.hpp view
@@ -2,7 +2,7 @@ // posix/descriptor.hpp // ~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/posix/descriptor_base.hpp view
@@ -2,7 +2,7 @@ // posix/descriptor_base.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/posix/stream_descriptor.hpp view
@@ -2,7 +2,7 @@ // posix/stream_descriptor.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/post.hpp view
@@ -2,7 +2,7 @@ // post.hpp // ~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -17,10 +17,13 @@ #include "asio/detail/config.hpp" #include "asio/async_result.hpp"+#include "asio/detail/initiate_post.hpp" #include "asio/detail/type_traits.hpp" #include "asio/execution_context.hpp"+#include "asio/execution/blocking.hpp" #include "asio/execution/executor.hpp" #include "asio/is_executor.hpp"+#include "asio/require.hpp" #include "asio/detail/push_options.hpp" @@ -35,27 +38,54 @@ * The use of @c post(), rather than @ref defer(), indicates the caller's * preference that the function object be eagerly queued for execution. *- * This function has the following effects:+ * @param token The @ref completion_token that will be used to produce a+ * completion handler. The function signature of the completion handler must be:+ * @code void handler(); @endcode *- * @li Constructs a function object handler of type @c Handler, initialized- * with <tt>handler(forward<CompletionToken>(token))</tt>.+ * @returns This function returns <tt>async_initiate<NullaryToken,+ * void()>(Init{}, token)</tt>, where @c Init is a function object type defined+ * as: *- * @li Constructs an object @c result of type <tt>async_result<Handler></tt>,- * initializing the object as <tt>result(handler)</tt>.+ * @code class Init+ * {+ * public:+ * template <typename CompletionHandler>+ * void operator()(CompletionHandler&& completion_handler) const;+ * }; @endcode *- * @li Obtains the handler's associated executor object @c ex by performing- * <tt>get_associated_executor(handler)</tt>.+ * The function call operator of @c Init: *+ * @li Obtains the handler's associated executor object @c ex of type @c Ex by+ * performing @code auto ex = get_associated_executor(handler); @endcode+ * * @li Obtains the handler's associated allocator object @c alloc by performing- * <tt>get_associated_allocator(handler)</tt>.+ * @code auto alloc = get_associated_allocator(handler); @endcode *- * @li Performs <tt>ex.post(std::move(handler), alloc)</tt>.+ * @li If <tt>execution::is_executor<Ex>::value</tt> is true, performs+ * @code prefer(+ * require(ex, execution::blocking.never),+ * execution::relationship.fork,+ * execution::allocator(alloc)+ * ).execute(std::forward<CompletionHandler>(completion_handler)); @endcode *- * @li Returns <tt>result.get()</tt>.+ * @li If <tt>execution::is_executor<Ex>::value</tt> is false, performs+ * @code ex.post(+ * std::forward<CompletionHandler>(completion_handler),+ * alloc); @endcode+ *+ * @par Completion Signature+ * @code void() @endcode */-template <ASIO_COMPLETION_TOKEN_FOR(void()) CompletionToken>-ASIO_INITFN_AUTO_RESULT_TYPE(CompletionToken, void()) post(- ASIO_MOVE_ARG(CompletionToken) token);+template <ASIO_COMPLETION_TOKEN_FOR(void()) NullaryToken>+ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX(NullaryToken, void()) post(+ ASIO_MOVE_ARG(NullaryToken) token)+ ASIO_INITFN_AUTO_RESULT_TYPE_SUFFIX((+ async_initiate<NullaryToken, void()>(+ declval<detail::initiate_post>(), token)))+{+ return async_initiate<NullaryToken, void()>(+ detail::initiate_post(), token);+} /// Submits a completion token or function object for execution. /**@@ -66,61 +96,123 @@ * The use of @c post(), rather than @ref defer(), indicates the caller's * preference that the function object be eagerly queued for execution. *- * This function has the following effects:+ * @param ex The target executor. *- * @li Constructs a function object handler of type @c Handler, initialized- * with <tt>handler(forward<CompletionToken>(token))</tt>.+ * @param token The @ref completion_token that will be used to produce a+ * completion handler. The function signature of the completion handler must be:+ * @code void handler(); @endcode *- * @li Constructs an object @c result of type <tt>async_result<Handler></tt>,- * initializing the object as <tt>result(handler)</tt>.+ * @returns This function returns <tt>async_initiate<NullaryToken,+ * void()>(Init{ex}, token)</tt>, where @c Init is a function object type+ * defined as: *- * @li Obtains the handler's associated executor object @c ex1 by performing- * <tt>get_associated_executor(handler)</tt>.+ * @code class Init+ * {+ * public:+ * using executor_type = Executor;+ * explicit Init(const Executor& ex) : ex_(ex) {}+ * executor_type get_executor() const noexcept { return ex_; }+ * template <typename CompletionHandler>+ * void operator()(CompletionHandler&& completion_handler) const;+ * private:+ * Executor ex_; // exposition only+ * }; @endcode *- * @li Creates a work object @c w by performing <tt>make_work(ex1)</tt>.+ * The function call operator of @c Init: *+ * @li Obtains the handler's associated executor object @c ex1 of type @c Ex1 by+ * performing @code auto ex1 = get_associated_executor(handler, ex); @endcode+ * * @li Obtains the handler's associated allocator object @c alloc by performing- * <tt>get_associated_allocator(handler)</tt>.+ * @code auto alloc = get_associated_allocator(handler); @endcode *- * @li Constructs a function object @c f with a function call operator that- * performs <tt>ex1.dispatch(std::move(handler), alloc)</tt> followed by- * <tt>w.reset()</tt>.+ * @li If <tt>execution::is_executor<Ex1>::value</tt> is true, constructs a+ * function object @c f with a member @c executor_ that is initialised with+ * <tt>prefer(ex1, execution::outstanding_work.tracked)</tt>, a member @c+ * handler_ that is a decay-copy of @c completion_handler, and a function call+ * operator that performs:+ * @code auto a = get_associated_allocator(handler_);+ * prefer(executor_, execution::allocator(a)).execute(std::move(handler_));+ * @endcode *- * @li Performs <tt>Executor(ex).post(std::move(f), alloc)</tt>.+ * @li If <tt>execution::is_executor<Ex1>::value</tt> is false, constructs a+ * function object @c f with a member @c work_ that is initialised with+ * <tt>make_work_guard(ex1)</tt>, a member @c handler_ that is a decay-copy of+ * @c completion_handler, and a function call operator that performs:+ * @code auto a = get_associated_allocator(handler_);+ * work_.get_executor().dispatch(std::move(handler_), a);+ * work_.reset(); @endcode *- * @li Returns <tt>result.get()</tt>.+ * @li If <tt>execution::is_executor<Ex>::value</tt> is true, performs+ * @code prefer(+ * require(ex, execution::blocking.never),+ * execution::relationship.fork,+ * execution::allocator(alloc)+ * ).execute(std::move(f)); @endcode+ *+ * @li If <tt>execution::is_executor<Ex>::value</tt> is false, performs+ * @code ex.post(std::move(f), alloc); @endcode+ *+ * @par Completion Signature+ * @code void() @endcode */ template <typename Executor,- ASIO_COMPLETION_TOKEN_FOR(void()) CompletionToken+ ASIO_COMPLETION_TOKEN_FOR(void()) NullaryToken ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(Executor)>-ASIO_INITFN_AUTO_RESULT_TYPE(CompletionToken, void()) post(+ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX(NullaryToken, void()) post( const Executor& ex,- ASIO_MOVE_ARG(CompletionToken) token+ ASIO_MOVE_ARG(NullaryToken) token ASIO_DEFAULT_COMPLETION_TOKEN(Executor),- typename enable_if<- execution::is_executor<Executor>::value || is_executor<Executor>::value- >::type* = 0);+ typename constraint<+ (execution::is_executor<Executor>::value+ && can_require<Executor, execution::blocking_t::never_t>::value)+ || is_executor<Executor>::value+ >::type = 0)+ ASIO_INITFN_AUTO_RESULT_TYPE_SUFFIX((+ async_initiate<NullaryToken, void()>(+ declval<detail::initiate_post_with_executor<Executor> >(), token)))+{+ return async_initiate<NullaryToken, void()>(+ detail::initiate_post_with_executor<Executor>(ex), token);+} /// Submits a completion token or function object for execution. /**- * @returns <tt>post(ctx.get_executor(), forward<CompletionToken>(token))</tt>.+ * @param ctx An execution context, from which the target executor is obtained.+ *+ * @param token The @ref completion_token that will be used to produce a+ * completion handler. The function signature of the completion handler must be:+ * @code void handler(); @endcode+ *+ * @returns <tt>post(ctx.get_executor(), forward<NullaryToken>(token))</tt>.+ *+ * @par Completion Signature+ * @code void() @endcode */ template <typename ExecutionContext,- ASIO_COMPLETION_TOKEN_FOR(void()) CompletionToken+ ASIO_COMPLETION_TOKEN_FOR(void()) NullaryToken ASIO_DEFAULT_COMPLETION_TOKEN_TYPE( typename ExecutionContext::executor_type)>-ASIO_INITFN_AUTO_RESULT_TYPE(CompletionToken, void()) post(+ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX(NullaryToken, void()) post( ExecutionContext& ctx,- ASIO_MOVE_ARG(CompletionToken) token+ ASIO_MOVE_ARG(NullaryToken) token ASIO_DEFAULT_COMPLETION_TOKEN( typename ExecutionContext::executor_type),- typename enable_if<is_convertible<- ExecutionContext&, execution_context&>::value>::type* = 0);+ typename constraint<is_convertible<+ ExecutionContext&, execution_context&>::value>::type = 0)+ ASIO_INITFN_AUTO_RESULT_TYPE_SUFFIX((+ async_initiate<NullaryToken, void()>(+ declval<detail::initiate_post_with_executor<+ typename ExecutionContext::executor_type> >(), token)))+{+ return async_initiate<NullaryToken, void()>(+ detail::initiate_post_with_executor<+ typename ExecutionContext::executor_type>(+ ctx.get_executor()), token);+} } // namespace asio #include "asio/detail/pop_options.hpp"--#include "asio/impl/post.hpp" #endif // ASIO_POST_HPP
link/modules/asio-standalone/asio/include/asio/prefer.hpp view
@@ -2,7 +2,7 @@ // prefer.hpp // ~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -118,6 +118,7 @@ namespace asio_prefer_fn { +using asio::conditional; using asio::decay; using asio::declval; using asio::enable_if;@@ -143,7 +144,9 @@ ill_formed }; -template <typename T, typename Properties, typename = void>+template <typename Impl, typename T, typename Properties,+ typename = void, typename = void, typename = void, typename = void,+ typename = void, typename = void, typename = void> struct call_traits { ASIO_STATIC_CONSTEXPR(overload_type, overload = ill_formed);@@ -151,19 +154,19 @@ typedef void result_type; }; -template <typename T, typename Property>-struct call_traits<T, void(Property),+template <typename Impl, typename T, typename Property>+struct call_traits<Impl, T, void(Property), typename enable_if<- (- is_applicable_property<- typename decay<T>::type,- typename decay<Property>::type- >::value- &&- decay<Property>::type::is_preferable- &&- static_require<T, Property>::is_valid- )+ is_applicable_property<+ typename decay<T>::type,+ typename decay<Property>::type+ >::value+ >::type,+ typename enable_if<+ decay<Property>::type::is_preferable+ >::type,+ typename enable_if<+ static_require<T, Property>::is_valid >::type> { ASIO_STATIC_CONSTEXPR(overload_type, overload = identity);@@ -176,123 +179,137 @@ #endif // defined(ASIO_HAS_MOVE) }; -template <typename T, typename Property>-struct call_traits<T, void(Property),+template <typename Impl, typename T, typename Property>+struct call_traits<Impl, T, void(Property), typename enable_if<- (- is_applicable_property<- typename decay<T>::type,- typename decay<Property>::type- >::value- &&- decay<Property>::type::is_preferable- &&- !static_require<T, Property>::is_valid- &&- require_member<T, Property>::is_valid- )+ is_applicable_property<+ typename decay<T>::type,+ typename decay<Property>::type+ >::value+ >::type,+ typename enable_if<+ decay<Property>::type::is_preferable+ >::type,+ typename enable_if<+ !static_require<T, Property>::is_valid+ >::type,+ typename enable_if<+ require_member<typename Impl::template proxy<T>::type, Property>::is_valid >::type> :- require_member<T, Property>+ require_member<typename Impl::template proxy<T>::type, Property> { ASIO_STATIC_CONSTEXPR(overload_type, overload = call_require_member); }; -template <typename T, typename Property>-struct call_traits<T, void(Property),+template <typename Impl, typename T, typename Property>+struct call_traits<Impl, T, void(Property), typename enable_if<- (- is_applicable_property<- typename decay<T>::type,- typename decay<Property>::type- >::value- &&- decay<Property>::type::is_preferable- &&- !static_require<T, Property>::is_valid- &&- !require_member<T, Property>::is_valid- &&- require_free<T, Property>::is_valid- )+ is_applicable_property<+ typename decay<T>::type,+ typename decay<Property>::type+ >::value+ >::type,+ typename enable_if<+ decay<Property>::type::is_preferable+ >::type,+ typename enable_if<+ !static_require<T, Property>::is_valid+ >::type,+ typename enable_if<+ !require_member<typename Impl::template proxy<T>::type, Property>::is_valid+ >::type,+ typename enable_if<+ require_free<T, Property>::is_valid >::type> : require_free<T, Property> { ASIO_STATIC_CONSTEXPR(overload_type, overload = call_require_free); }; -template <typename T, typename Property>-struct call_traits<T, void(Property),+template <typename Impl, typename T, typename Property>+struct call_traits<Impl, T, void(Property), typename enable_if<- (- is_applicable_property<- typename decay<T>::type,- typename decay<Property>::type- >::value- &&- decay<Property>::type::is_preferable- &&- !static_require<T, Property>::is_valid- &&- !require_member<T, Property>::is_valid- &&- !require_free<T, Property>::is_valid- &&- prefer_member<T, Property>::is_valid- )+ is_applicable_property<+ typename decay<T>::type,+ typename decay<Property>::type+ >::value+ >::type,+ typename enable_if<+ decay<Property>::type::is_preferable+ >::type,+ typename enable_if<+ !static_require<T, Property>::is_valid+ >::type,+ typename enable_if<+ !require_member<typename Impl::template proxy<T>::type, Property>::is_valid+ >::type,+ typename enable_if<+ !require_free<T, Property>::is_valid+ >::type,+ typename enable_if<+ prefer_member<typename Impl::template proxy<T>::type, Property>::is_valid >::type> :- prefer_member<T, Property>+ prefer_member<typename Impl::template proxy<T>::type, Property> { ASIO_STATIC_CONSTEXPR(overload_type, overload = call_prefer_member); }; -template <typename T, typename Property>-struct call_traits<T, void(Property),+template <typename Impl, typename T, typename Property>+struct call_traits<Impl, T, void(Property), typename enable_if<- (- is_applicable_property<- typename decay<T>::type,- typename decay<Property>::type- >::value- &&- decay<Property>::type::is_preferable- &&- !static_require<T, Property>::is_valid- &&- !require_member<T, Property>::is_valid- &&- !require_free<T, Property>::is_valid- &&- !prefer_member<T, Property>::is_valid- &&- prefer_free<T, Property>::is_valid- )+ is_applicable_property<+ typename decay<T>::type,+ typename decay<Property>::type+ >::value+ >::type,+ typename enable_if<+ decay<Property>::type::is_preferable+ >::type,+ typename enable_if<+ !static_require<T, Property>::is_valid+ >::type,+ typename enable_if<+ !require_member<typename Impl::template proxy<T>::type, Property>::is_valid+ >::type,+ typename enable_if<+ !require_free<T, Property>::is_valid+ >::type,+ typename enable_if<+ !prefer_member<typename Impl::template proxy<T>::type, Property>::is_valid+ >::type,+ typename enable_if<+ prefer_free<T, Property>::is_valid >::type> : prefer_free<T, Property> { ASIO_STATIC_CONSTEXPR(overload_type, overload = call_prefer_free); }; -template <typename T, typename Property>-struct call_traits<T, void(Property),+template <typename Impl, typename T, typename Property>+struct call_traits<Impl, T, void(Property), typename enable_if<- (- is_applicable_property<- typename decay<T>::type,- typename decay<Property>::type- >::value- &&- decay<Property>::type::is_preferable- &&- !static_require<T, Property>::is_valid- &&- !require_member<T, Property>::is_valid- &&- !require_free<T, Property>::is_valid- &&- !prefer_member<T, Property>::is_valid- &&- !prefer_free<T, Property>::is_valid- )+ is_applicable_property<+ typename decay<T>::type,+ typename decay<Property>::type+ >::value+ >::type,+ typename enable_if<+ decay<Property>::type::is_preferable+ >::type,+ typename enable_if<+ !static_require<T, Property>::is_valid+ >::type,+ typename enable_if<+ !require_member<typename Impl::template proxy<T>::type, Property>::is_valid+ >::type,+ typename enable_if<+ !require_free<T, Property>::is_valid+ >::type,+ typename enable_if<+ !prefer_member<typename Impl::template proxy<T>::type, Property>::is_valid+ >::type,+ typename enable_if<+ !prefer_free<T, Property>::is_valid >::type> { ASIO_STATIC_CONSTEXPR(overload_type, overload = identity);@@ -305,13 +322,15 @@ #endif // defined(ASIO_HAS_MOVE) }; -template <typename T, typename P0, typename P1>-struct call_traits<T, void(P0, P1),+template <typename Impl, typename T, typename P0, typename P1>+struct call_traits<Impl, T, void(P0, P1), typename enable_if<- call_traits<T, void(P0)>::overload != ill_formed- &&+ call_traits<Impl, T, void(P0)>::overload != ill_formed+ >::type,+ typename enable_if< call_traits<- typename call_traits<T, void(P0)>::result_type,+ Impl,+ typename call_traits<Impl, T, void(P0)>::result_type, void(P1) >::overload != ill_formed >::type>@@ -320,29 +339,34 @@ ASIO_STATIC_CONSTEXPR(bool, is_noexcept = (- call_traits<T, void(P0)>::is_noexcept+ call_traits<Impl, T, void(P0)>::is_noexcept && call_traits<- typename call_traits<T, void(P0)>::result_type,+ Impl,+ typename call_traits<Impl, T, void(P0)>::result_type, void(P1) >::is_noexcept )); typedef typename decay< typename call_traits<- typename call_traits<T, void(P0)>::result_type,+ Impl,+ typename call_traits<Impl, T, void(P0)>::result_type, void(P1) >::result_type >::type result_type; }; -template <typename T, typename P0, typename P1, typename ASIO_ELLIPSIS PN>-struct call_traits<T, void(P0, P1, PN ASIO_ELLIPSIS),+template <typename Impl, typename T, typename P0,+ typename P1, typename ASIO_ELLIPSIS PN>+struct call_traits<Impl, T, void(P0, P1, PN ASIO_ELLIPSIS), typename enable_if<- call_traits<T, void(P0)>::overload != ill_formed- &&+ call_traits<Impl, T, void(P0)>::overload != ill_formed+ >::type,+ typename enable_if< call_traits<- typename call_traits<T, void(P0)>::result_type,+ Impl,+ typename call_traits<Impl, T, void(P0)>::result_type, void(P1, PN ASIO_ELLIPSIS) >::overload != ill_formed >::type>@@ -351,17 +375,19 @@ ASIO_STATIC_CONSTEXPR(bool, is_noexcept = (- call_traits<T, void(P0)>::is_noexcept+ call_traits<Impl, T, void(P0)>::is_noexcept && call_traits<- typename call_traits<T, void(P0)>::result_type,+ Impl,+ typename call_traits<Impl, T, void(P0)>::result_type, void(P1, PN ASIO_ELLIPSIS) >::is_noexcept )); typedef typename decay< typename call_traits<- typename call_traits<T, void(P0)>::result_type,+ Impl,+ typename call_traits<Impl, T, void(P0)>::result_type, void(P1, PN ASIO_ELLIPSIS) >::result_type >::type result_type;@@ -369,30 +395,70 @@ struct impl {+ template <typename T>+ struct proxy+ {+#if defined(ASIO_HAS_DEDUCED_REQUIRE_MEMBER_TRAIT) \+ && defined(ASIO_HAS_DEDUCED_PREFER_MEMBER_TRAIT)+ struct type+ {+ template <typename P>+ auto require(ASIO_MOVE_ARG(P) p)+ noexcept(+ noexcept(+ declval<typename conditional<true, T, P>::type>().require(+ ASIO_MOVE_CAST(P)(p))+ )+ )+ -> decltype(+ declval<typename conditional<true, T, P>::type>().require(+ ASIO_MOVE_CAST(P)(p))+ );++ template <typename P>+ auto prefer(ASIO_MOVE_ARG(P) p)+ noexcept(+ noexcept(+ declval<typename conditional<true, T, P>::type>().prefer(+ ASIO_MOVE_CAST(P)(p))+ )+ )+ -> decltype(+ declval<typename conditional<true, T, P>::type>().prefer(+ ASIO_MOVE_CAST(P)(p))+ );+ };+#else // defined(ASIO_HAS_DEDUCED_REQUIRE_MEMBER_TRAIT)+ // && defined(ASIO_HAS_DEDUCED_PREFER_MEMBER_TRAIT)+ typedef T type;+#endif // defined(ASIO_HAS_DEDUCED_REQUIRE_MEMBER_TRAIT)+ // && defined(ASIO_HAS_DEDUCED_PREFER_MEMBER_TRAIT)+ };+ template <typename T, typename Property> ASIO_NODISCARD ASIO_CONSTEXPR typename enable_if<- call_traits<T, void(Property)>::overload == identity,- typename call_traits<T, void(Property)>::result_type+ call_traits<impl, T, void(Property)>::overload == identity,+ typename call_traits<impl, T, void(Property)>::result_type >::type operator()( ASIO_MOVE_ARG(T) t, ASIO_MOVE_ARG(Property)) const ASIO_NOEXCEPT_IF((- call_traits<T, void(Property)>::is_noexcept))+ call_traits<impl, T, void(Property)>::is_noexcept)) { return ASIO_MOVE_CAST(T)(t); } template <typename T, typename Property> ASIO_NODISCARD ASIO_CONSTEXPR typename enable_if<- call_traits<T, void(Property)>::overload == call_require_member,- typename call_traits<T, void(Property)>::result_type+ call_traits<impl, T, void(Property)>::overload == call_require_member,+ typename call_traits<impl, T, void(Property)>::result_type >::type operator()( ASIO_MOVE_ARG(T) t, ASIO_MOVE_ARG(Property) p) const ASIO_NOEXCEPT_IF((- call_traits<T, void(Property)>::is_noexcept))+ call_traits<impl, T, void(Property)>::is_noexcept)) { return ASIO_MOVE_CAST(T)(t).require( ASIO_MOVE_CAST(Property)(p));@@ -400,14 +466,14 @@ template <typename T, typename Property> ASIO_NODISCARD ASIO_CONSTEXPR typename enable_if<- call_traits<T, void(Property)>::overload == call_require_free,- typename call_traits<T, void(Property)>::result_type+ call_traits<impl, T, void(Property)>::overload == call_require_free,+ typename call_traits<impl, T, void(Property)>::result_type >::type operator()( ASIO_MOVE_ARG(T) t, ASIO_MOVE_ARG(Property) p) const ASIO_NOEXCEPT_IF((- call_traits<T, void(Property)>::is_noexcept))+ call_traits<impl, T, void(Property)>::is_noexcept)) { return require( ASIO_MOVE_CAST(T)(t),@@ -416,14 +482,14 @@ template <typename T, typename Property> ASIO_NODISCARD ASIO_CONSTEXPR typename enable_if<- call_traits<T, void(Property)>::overload == call_prefer_member,- typename call_traits<T, void(Property)>::result_type+ call_traits<impl, T, void(Property)>::overload == call_prefer_member,+ typename call_traits<impl, T, void(Property)>::result_type >::type operator()( ASIO_MOVE_ARG(T) t, ASIO_MOVE_ARG(Property) p) const ASIO_NOEXCEPT_IF((- call_traits<T, void(Property)>::is_noexcept))+ call_traits<impl, T, void(Property)>::is_noexcept)) { return ASIO_MOVE_CAST(T)(t).prefer( ASIO_MOVE_CAST(Property)(p));@@ -431,14 +497,14 @@ template <typename T, typename Property> ASIO_NODISCARD ASIO_CONSTEXPR typename enable_if<- call_traits<T, void(Property)>::overload == call_prefer_free,- typename call_traits<T, void(Property)>::result_type+ call_traits<impl, T, void(Property)>::overload == call_prefer_free,+ typename call_traits<impl, T, void(Property)>::result_type >::type operator()( ASIO_MOVE_ARG(T) t, ASIO_MOVE_ARG(Property) p) const ASIO_NOEXCEPT_IF((- call_traits<T, void(Property)>::is_noexcept))+ call_traits<impl, T, void(Property)>::is_noexcept)) { return prefer( ASIO_MOVE_CAST(T)(t),@@ -447,15 +513,15 @@ template <typename T, typename P0, typename P1> ASIO_NODISCARD ASIO_CONSTEXPR typename enable_if<- call_traits<T, void(P0, P1)>::overload == two_props,- typename call_traits<T, void(P0, P1)>::result_type+ call_traits<impl, T, void(P0, P1)>::overload == two_props,+ typename call_traits<impl, T, void(P0, P1)>::result_type >::type operator()( ASIO_MOVE_ARG(T) t, ASIO_MOVE_ARG(P0) p0, ASIO_MOVE_ARG(P1) p1) const ASIO_NOEXCEPT_IF((- call_traits<T, void(P0, P1)>::is_noexcept))+ call_traits<impl, T, void(P0, P1)>::is_noexcept)) { return (*this)( (*this)(@@ -467,8 +533,10 @@ template <typename T, typename P0, typename P1, typename ASIO_ELLIPSIS PN> ASIO_NODISCARD ASIO_CONSTEXPR typename enable_if<- call_traits<T, void(P0, P1, PN ASIO_ELLIPSIS)>::overload == n_props,- typename call_traits<T, void(P0, P1, PN ASIO_ELLIPSIS)>::result_type+ call_traits<impl, T,+ void(P0, P1, PN ASIO_ELLIPSIS)>::overload == n_props,+ typename call_traits<impl, T,+ void(P0, P1, PN ASIO_ELLIPSIS)>::result_type >::type operator()( ASIO_MOVE_ARG(T) t,@@ -476,7 +544,7 @@ ASIO_MOVE_ARG(P1) p1, ASIO_MOVE_ARG(PN) ASIO_ELLIPSIS pn) const ASIO_NOEXCEPT_IF((- call_traits<T, void(P0, P1, PN ASIO_ELLIPSIS)>::is_noexcept))+ call_traits<impl, T, void(P0, P1, PN ASIO_ELLIPSIS)>::is_noexcept)) { return (*this)( (*this)(@@ -505,13 +573,16 @@ } // namespace +typedef asio_prefer_fn::impl prefer_t;+ #if defined(ASIO_HAS_VARIADIC_TEMPLATES) template <typename T, typename... Properties> struct can_prefer : integral_constant<bool,- asio_prefer_fn::call_traits<T, void(Properties...)>::overload- != asio_prefer_fn::ill_formed>+ asio_prefer_fn::call_traits<+ prefer_t, T, void(Properties...)>::overload+ != asio_prefer_fn::ill_formed> { }; @@ -521,24 +592,27 @@ typename P1 = void, typename P2 = void> struct can_prefer : integral_constant<bool,- asio_prefer_fn::call_traits<T, void(P0, P1, P2)>::overload- != asio_prefer_fn::ill_formed>+ asio_prefer_fn::call_traits<+ prefer_t, T, void(P0, P1, P2)>::overload+ != asio_prefer_fn::ill_formed> { }; template <typename T, typename P0, typename P1> struct can_prefer<T, P0, P1> : integral_constant<bool,- asio_prefer_fn::call_traits<T, void(P0, P1)>::overload- != asio_prefer_fn::ill_formed>+ asio_prefer_fn::call_traits<+ prefer_t, T, void(P0, P1)>::overload+ != asio_prefer_fn::ill_formed> { }; template <typename T, typename P0> struct can_prefer<T, P0> : integral_constant<bool,- asio_prefer_fn::call_traits<T, void(P0)>::overload- != asio_prefer_fn::ill_formed>+ asio_prefer_fn::call_traits<+ prefer_t, T, void(P0)>::overload+ != asio_prefer_fn::ill_formed> { }; @@ -563,7 +637,8 @@ template <typename T, typename... Properties> struct is_nothrow_prefer : integral_constant<bool,- asio_prefer_fn::call_traits<T, void(Properties...)>::is_noexcept>+ asio_prefer_fn::call_traits<+ prefer_t, T, void(Properties...)>::is_noexcept> { }; @@ -573,21 +648,24 @@ typename P1 = void, typename P2 = void> struct is_nothrow_prefer : integral_constant<bool,- asio_prefer_fn::call_traits<T, void(P0, P1, P2)>::is_noexcept>+ asio_prefer_fn::call_traits<+ prefer_t, T, void(P0, P1, P2)>::is_noexcept> { }; template <typename T, typename P0, typename P1> struct is_nothrow_prefer<T, P0, P1> : integral_constant<bool,- asio_prefer_fn::call_traits<T, void(P0, P1)>::is_noexcept>+ asio_prefer_fn::call_traits<+ prefer_t, T, void(P0, P1)>::is_noexcept> { }; template <typename T, typename P0> struct is_nothrow_prefer<T, P0> : integral_constant<bool,- asio_prefer_fn::call_traits<T, void(P0)>::is_noexcept>+ asio_prefer_fn::call_traits<+ prefer_t, T, void(P0)>::is_noexcept> { }; @@ -613,7 +691,7 @@ struct prefer_result { typedef typename asio_prefer_fn::call_traits<- T, void(Properties...)>::result_type type;+ prefer_t, T, void(Properties...)>::result_type type; }; #else // defined(ASIO_HAS_VARIADIC_TEMPLATES)@@ -623,21 +701,21 @@ struct prefer_result { typedef typename asio_prefer_fn::call_traits<- T, void(P0, P1, P2)>::result_type type;+ prefer_t, T, void(P0, P1, P2)>::result_type type; }; template <typename T, typename P0, typename P1> struct prefer_result<T, P0, P1> { typedef typename asio_prefer_fn::call_traits<- T, void(P0, P1)>::result_type type;+ prefer_t, T, void(P0, P1)>::result_type type; }; template <typename T, typename P0> struct prefer_result<T, P0> { typedef typename asio_prefer_fn::call_traits<- T, void(P0)>::result_type type;+ prefer_t, T, void(P0)>::result_type type; }; template <typename T>
+ link/modules/asio-standalone/asio/include/asio/prepend.hpp view
@@ -0,0 +1,78 @@+//+// prepend.hpp+// ~~~~~~~~~~~+//+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com)+//+// Distributed under the Boost Software License, Version 1.0. (See accompanying+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)+//++#ifndef ASIO_PREPEND_HPP+#define ASIO_PREPEND_HPP++#if defined(_MSC_VER) && (_MSC_VER >= 1200)+# pragma once+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)++#include "asio/detail/config.hpp"++#if (defined(ASIO_HAS_STD_TUPLE) \+ && defined(ASIO_HAS_VARIADIC_TEMPLATES)) \+ || defined(GENERATING_DOCUMENTATION)++#include <tuple>+#include "asio/detail/type_traits.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {++/// Completion token type used to specify that the completion handler+/// arguments should be passed additional values before the results of the+/// operation.+template <typename CompletionToken, typename... Values>+class prepend_t+{+public:+ /// Constructor.+ template <typename T, typename... V>+ ASIO_CONSTEXPR explicit prepend_t(+ ASIO_MOVE_ARG(T) completion_token,+ ASIO_MOVE_ARG(V)... values)+ : token_(ASIO_MOVE_CAST(T)(completion_token)),+ values_(ASIO_MOVE_CAST(V)(values)...)+ {+ }++//private:+ CompletionToken token_;+ std::tuple<Values...> values_;+};++/// Completion token type used to specify that the completion handler+/// arguments should be passed additional values before the results of the+/// operation.+template <typename CompletionToken, typename... Values>+ASIO_NODISCARD inline ASIO_CONSTEXPR prepend_t<+ typename decay<CompletionToken>::type, typename decay<Values>::type...>+prepend(ASIO_MOVE_ARG(CompletionToken) completion_token,+ ASIO_MOVE_ARG(Values)... values)+{+ return prepend_t<+ typename decay<CompletionToken>::type, typename decay<Values>::type...>(+ ASIO_MOVE_CAST(CompletionToken)(completion_token),+ ASIO_MOVE_CAST(Values)(values)...);+}++} // namespace asio++#include "asio/detail/pop_options.hpp"++#include "asio/impl/prepend.hpp"++#endif // (defined(ASIO_HAS_STD_TUPLE)+ // && defined(ASIO_HAS_VARIADIC_TEMPLATES))+ // || defined(GENERATING_DOCUMENTATION)++#endif // ASIO_PREPEND_HPP
link/modules/asio-standalone/asio/include/asio/query.hpp view
@@ -2,7 +2,7 @@ // query.hpp // ~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -100,6 +100,7 @@ namespace asio_query_fn { +using asio::conditional; using asio::decay; using asio::declval; using asio::enable_if;@@ -118,7 +119,8 @@ ill_formed }; -template <typename T, typename Properties, typename = void>+template <typename Impl, typename T, typename Properties,+ typename = void, typename = void, typename = void, typename = void> struct call_traits { ASIO_STATIC_CONSTEXPR(overload_type, overload = ill_formed);@@ -126,57 +128,57 @@ typedef void result_type; }; -template <typename T, typename Property>-struct call_traits<T, void(Property),+template <typename Impl, typename T, typename Property>+struct call_traits<Impl, T, void(Property), typename enable_if<- (- is_applicable_property<- typename decay<T>::type,- typename decay<Property>::type- >::value- &&- static_query<T, Property>::is_valid- )+ is_applicable_property<+ typename decay<T>::type,+ typename decay<Property>::type+ >::value+ >::type,+ typename enable_if<+ static_query<T, Property>::is_valid >::type> : static_query<T, Property> { ASIO_STATIC_CONSTEXPR(overload_type, overload = static_value); }; -template <typename T, typename Property>-struct call_traits<T, void(Property),+template <typename Impl, typename T, typename Property>+struct call_traits<Impl, T, void(Property), typename enable_if<- (- is_applicable_property<- typename decay<T>::type,- typename decay<Property>::type- >::value- &&- !static_query<T, Property>::is_valid- &&- query_member<T, Property>::is_valid- )+ is_applicable_property<+ typename decay<T>::type,+ typename decay<Property>::type+ >::value+ >::type,+ typename enable_if<+ !static_query<T, Property>::is_valid+ >::type,+ typename enable_if<+ query_member<typename Impl::template proxy<T>::type, Property>::is_valid >::type> :- query_member<T, Property>+ query_member<typename Impl::template proxy<T>::type, Property> { ASIO_STATIC_CONSTEXPR(overload_type, overload = call_member); }; -template <typename T, typename Property>-struct call_traits<T, void(Property),+template <typename Impl, typename T, typename Property>+struct call_traits<Impl, T, void(Property), typename enable_if<- (- is_applicable_property<- typename decay<T>::type,- typename decay<Property>::type- >::value- &&- !static_query<T, Property>::is_valid- &&- !query_member<T, Property>::is_valid- &&- query_free<T, Property>::is_valid- )+ is_applicable_property<+ typename decay<T>::type,+ typename decay<Property>::type+ >::value+ >::type,+ typename enable_if<+ !static_query<T, Property>::is_valid+ >::type,+ typename enable_if<+ !query_member<typename Impl::template proxy<T>::type, Property>::is_valid+ >::type,+ typename enable_if<+ query_free<T, Property>::is_valid >::type> : query_free<T, Property> {@@ -185,16 +187,40 @@ struct impl {+ template <typename T>+ struct proxy+ {+#if defined(ASIO_HAS_DEDUCED_QUERY_MEMBER_TRAIT)+ struct type+ {+ template <typename P>+ auto query(ASIO_MOVE_ARG(P) p)+ noexcept(+ noexcept(+ declval<typename conditional<true, T, P>::type>().query(+ ASIO_MOVE_CAST(P)(p))+ )+ )+ -> decltype(+ declval<typename conditional<true, T, P>::type>().query(+ ASIO_MOVE_CAST(P)(p))+ );+ };+#else // defined(ASIO_HAS_DEDUCED_QUERY_MEMBER_TRAIT)+ typedef T type;+#endif // defined(ASIO_HAS_DEDUCED_QUERY_MEMBER_TRAIT)+ };+ template <typename T, typename Property> ASIO_NODISCARD ASIO_CONSTEXPR typename enable_if<- call_traits<T, void(Property)>::overload == static_value,- typename call_traits<T, void(Property)>::result_type+ call_traits<impl, T, void(Property)>::overload == static_value,+ typename call_traits<impl, T, void(Property)>::result_type >::type operator()( ASIO_MOVE_ARG(T), ASIO_MOVE_ARG(Property)) const ASIO_NOEXCEPT_IF((- call_traits<T, void(Property)>::is_noexcept))+ call_traits<impl, T, void(Property)>::is_noexcept)) { return static_query< typename decay<T>::type,@@ -204,28 +230,28 @@ template <typename T, typename Property> ASIO_NODISCARD ASIO_CONSTEXPR typename enable_if<- call_traits<T, void(Property)>::overload == call_member,- typename call_traits<T, void(Property)>::result_type+ call_traits<impl, T, void(Property)>::overload == call_member,+ typename call_traits<impl, T, void(Property)>::result_type >::type operator()( ASIO_MOVE_ARG(T) t, ASIO_MOVE_ARG(Property) p) const ASIO_NOEXCEPT_IF((- call_traits<T, void(Property)>::is_noexcept))+ call_traits<impl, T, void(Property)>::is_noexcept)) { return ASIO_MOVE_CAST(T)(t).query(ASIO_MOVE_CAST(Property)(p)); } template <typename T, typename Property> ASIO_NODISCARD ASIO_CONSTEXPR typename enable_if<- call_traits<T, void(Property)>::overload == call_free,- typename call_traits<T, void(Property)>::result_type+ call_traits<impl, T, void(Property)>::overload == call_free,+ typename call_traits<impl, T, void(Property)>::result_type >::type operator()( ASIO_MOVE_ARG(T) t, ASIO_MOVE_ARG(Property) p) const ASIO_NOEXCEPT_IF((- call_traits<T, void(Property)>::is_noexcept))+ call_traits<impl, T, void(Property)>::is_noexcept)) { return query(ASIO_MOVE_CAST(T)(t), ASIO_MOVE_CAST(Property)(p)); }@@ -249,10 +275,12 @@ } // namespace +typedef asio_query_fn::impl query_t;+ template <typename T, typename Property> struct can_query : integral_constant<bool,- asio_query_fn::call_traits<T, void(Property)>::overload !=+ asio_query_fn::call_traits<query_t, T, void(Property)>::overload != asio_query_fn::ill_formed> { };@@ -268,7 +296,7 @@ template <typename T, typename Property> struct is_nothrow_query : integral_constant<bool,- asio_query_fn::call_traits<T, void(Property)>::is_noexcept>+ asio_query_fn::call_traits<query_t, T, void(Property)>::is_noexcept> { }; @@ -284,7 +312,7 @@ struct query_result { typedef typename asio_query_fn::call_traits<- T, void(Property)>::result_type type;+ query_t, T, void(Property)>::result_type type; }; } // namespace asio
+ link/modules/asio-standalone/asio/include/asio/random_access_file.hpp view
@@ -0,0 +1,35 @@+//+// random_access_file.hpp+// ~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com)+//+// Distributed under the Boost Software License, Version 1.0. (See accompanying+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)+//++#ifndef ASIO_RANDOM_ACCESS_FILE_HPP+#define ASIO_RANDOM_ACCESS_FILE_HPP++#if defined(_MSC_VER) && (_MSC_VER >= 1200)+# pragma once+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)++#include "asio/detail/config.hpp"++#if defined(ASIO_HAS_FILE) \+ || defined(GENERATING_DOCUMENTATION)++#include "asio/basic_random_access_file.hpp"++namespace asio {++/// Typedef for the typical usage of a random-access file.+typedef basic_random_access_file<> random_access_file;++} // namespace asio++#endif // defined(ASIO_HAS_FILE)+ // || defined(GENERATING_DOCUMENTATION)++#endif // ASIO_RANDOM_ACCESS_FILE_HPP
link/modules/asio-standalone/asio/include/asio/read.hpp view
@@ -2,7 +2,7 @@ // read.hpp // ~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -19,6 +19,7 @@ #include <cstddef> #include "asio/async_result.hpp" #include "asio/buffer.hpp"+#include "asio/completion_condition.hpp" #include "asio/error.hpp" #if !defined(ASIO_NO_EXTENSIONS)@@ -28,7 +29,16 @@ #include "asio/detail/push_options.hpp" namespace asio {+namespace detail { +template <typename> class initiate_async_read;+#if !defined(ASIO_NO_DYNAMIC_BUFFER_V1)+template <typename> class initiate_async_read_dynbuf_v1;+#endif // !defined(ASIO_NO_DYNAMIC_BUFFER_V1)+template <typename> class initiate_async_read_dynbuf_v2;++} // namespace detail+ /** * @defgroup read asio::read *@@ -75,9 +85,9 @@ */ template <typename SyncReadStream, typename MutableBufferSequence> std::size_t read(SyncReadStream& s, const MutableBufferSequence& buffers,- typename enable_if<+ typename constraint< is_mutable_buffer_sequence<MutableBufferSequence>::value- >::type* = 0);+ >::type = 0); /// Attempt to read a certain amount of data from a stream before returning. /**@@ -118,9 +128,9 @@ template <typename SyncReadStream, typename MutableBufferSequence> std::size_t read(SyncReadStream& s, const MutableBufferSequence& buffers, asio::error_code& ec,- typename enable_if<+ typename constraint< is_mutable_buffer_sequence<MutableBufferSequence>::value- >::type* = 0);+ >::type = 0); /// Attempt to read a certain amount of data from a stream before returning. /**@@ -172,9 +182,9 @@ typename CompletionCondition> std::size_t read(SyncReadStream& s, const MutableBufferSequence& buffers, CompletionCondition completion_condition,- typename enable_if<+ typename constraint< is_mutable_buffer_sequence<MutableBufferSequence>::value- >::type* = 0);+ >::type = 0); /// Attempt to read a certain amount of data from a stream before returning. /**@@ -219,9 +229,9 @@ typename CompletionCondition> std::size_t read(SyncReadStream& s, const MutableBufferSequence& buffers, CompletionCondition completion_condition, asio::error_code& ec,- typename enable_if<+ typename constraint< is_mutable_buffer_sequence<MutableBufferSequence>::value- >::type* = 0);+ >::type = 0); #if !defined(ASIO_NO_DYNAMIC_BUFFER_V1) @@ -255,10 +265,12 @@ template <typename SyncReadStream, typename DynamicBuffer_v1> std::size_t read(SyncReadStream& s, ASIO_MOVE_ARG(DynamicBuffer_v1) buffers,- typename enable_if<+ typename constraint< is_dynamic_buffer_v1<typename decay<DynamicBuffer_v1>::type>::value- && !is_dynamic_buffer_v2<typename decay<DynamicBuffer_v1>::type>::value- >::type* = 0);+ >::type = 0,+ typename constraint<+ !is_dynamic_buffer_v2<typename decay<DynamicBuffer_v1>::type>::value+ >::type = 0); /// Attempt to read a certain amount of data from a stream before returning. /**@@ -290,10 +302,12 @@ std::size_t read(SyncReadStream& s, ASIO_MOVE_ARG(DynamicBuffer_v1) buffers, asio::error_code& ec,- typename enable_if<+ typename constraint< is_dynamic_buffer_v1<typename decay<DynamicBuffer_v1>::type>::value- && !is_dynamic_buffer_v2<typename decay<DynamicBuffer_v1>::type>::value- >::type* = 0);+ >::type = 0,+ typename constraint<+ !is_dynamic_buffer_v2<typename decay<DynamicBuffer_v1>::type>::value+ >::type = 0); /// Attempt to read a certain amount of data from a stream before returning. /**@@ -336,10 +350,12 @@ std::size_t read(SyncReadStream& s, ASIO_MOVE_ARG(DynamicBuffer_v1) buffers, CompletionCondition completion_condition,- typename enable_if<+ typename constraint< is_dynamic_buffer_v1<typename decay<DynamicBuffer_v1>::type>::value- && !is_dynamic_buffer_v2<typename decay<DynamicBuffer_v1>::type>::value- >::type* = 0);+ >::type = 0,+ typename constraint<+ !is_dynamic_buffer_v2<typename decay<DynamicBuffer_v1>::type>::value+ >::type = 0); /// Attempt to read a certain amount of data from a stream before returning. /**@@ -383,10 +399,12 @@ std::size_t read(SyncReadStream& s, ASIO_MOVE_ARG(DynamicBuffer_v1) buffers, CompletionCondition completion_condition, asio::error_code& ec,- typename enable_if<+ typename constraint< is_dynamic_buffer_v1<typename decay<DynamicBuffer_v1>::type>::value- && !is_dynamic_buffer_v2<typename decay<DynamicBuffer_v1>::type>::value- >::type* = 0);+ >::type = 0,+ typename constraint<+ !is_dynamic_buffer_v2<typename decay<DynamicBuffer_v1>::type>::value+ >::type = 0); #if !defined(ASIO_NO_EXTENSIONS) #if !defined(ASIO_NO_IOSTREAM)@@ -564,9 +582,9 @@ */ template <typename SyncReadStream, typename DynamicBuffer_v2> std::size_t read(SyncReadStream& s, DynamicBuffer_v2 buffers,- typename enable_if<+ typename constraint< is_dynamic_buffer_v2<DynamicBuffer_v2>::value- >::type* = 0);+ >::type = 0); /// Attempt to read a certain amount of data from a stream before returning. /**@@ -597,9 +615,9 @@ template <typename SyncReadStream, typename DynamicBuffer_v2> std::size_t read(SyncReadStream& s, DynamicBuffer_v2 buffers, asio::error_code& ec,- typename enable_if<+ typename constraint< is_dynamic_buffer_v2<DynamicBuffer_v2>::value- >::type* = 0);+ >::type = 0); /// Attempt to read a certain amount of data from a stream before returning. /**@@ -641,9 +659,9 @@ typename CompletionCondition> std::size_t read(SyncReadStream& s, DynamicBuffer_v2 buffers, CompletionCondition completion_condition,- typename enable_if<+ typename constraint< is_dynamic_buffer_v2<DynamicBuffer_v2>::value- >::type* = 0);+ >::type = 0); /// Attempt to read a certain amount of data from a stream before returning. /**@@ -686,9 +704,9 @@ typename CompletionCondition> std::size_t read(SyncReadStream& s, DynamicBuffer_v2 buffers, CompletionCondition completion_condition, asio::error_code& ec,- typename enable_if<+ typename constraint< is_dynamic_buffer_v2<DynamicBuffer_v2>::value- >::type* = 0);+ >::type = 0); /*@}*/ /**@@ -703,9 +721,9 @@ /// stream. /** * This function is used to asynchronously read a certain number of bytes of- * data from a stream. The function call always returns immediately. The- * asynchronous operation will continue until one of the following conditions is- * true:+ * data from a stream. It is an initiating function for an @ref+ * asynchronous_operation, and always returns immediately. The asynchronous+ * operation will continue until one of the following conditions is true: * * @li The supplied buffers are full. That is, the bytes transferred is equal to * the sum of the buffer sizes.@@ -725,25 +743,30 @@ * of the buffer sizes indicates the maximum number of bytes to read from the * stream. Although the buffers object may be copied as necessary, ownership of * the underlying memory blocks is retained by the caller, which must guarantee- * that they remain valid until the handler is called.+ * that they remain valid until the completion handler is called. *- * @param handler The handler to be called when the read operation completes.- * Copies will be made of the handler as required. The function signature of the- * handler must be:+ * @param token The @ref completion_token that will be used to produce a+ * completion handler, which will be called when the read completes.+ * Potential completion tokens include @ref use_future, @ref use_awaitable,+ * @ref yield_context, or a function object with the correct completion+ * signature. The function signature of the completion handler must be: * @code void handler(- * const asio::error_code& error, // Result of operation.+ * // Result of operation.+ * const asio::error_code& error, *- * std::size_t bytes_transferred // Number of bytes copied into the- * // buffers. If an error occurred,- * // this will be the number of- * // bytes successfully transferred- * // prior to the error.+ * // Number of bytes copied into the buffers. If an error+ * // occurred, this will be the number of bytes successfully+ * // transferred prior to the error.+ * std::size_t bytes_transferred * ); @endcode * Regardless of whether the asynchronous operation completes immediately or- * not, the handler will not be invoked from within this function. On- * immediate completion, invocation of the handler will be performed in a+ * not, the completion handler will not be invoked from within this function.+ * On immediate completion, invocation of the handler will be performed in a * manner equivalent to using asio::post(). *+ * @par Completion Signature+ * @code void(asio::error_code, std::size_t) @endcode+ * * @par Example * To read into a single data buffer use the @ref buffer function as follows: * @code@@ -758,29 +781,45 @@ * s, buffers, * asio::transfer_all(), * handler); @endcode+ *+ * @par Per-Operation Cancellation+ * This asynchronous operation supports cancellation for the following+ * asio::cancellation_type values:+ *+ * @li @c cancellation_type::terminal+ *+ * @li @c cancellation_type::partial+ *+ * if they are also supported by the @c AsyncReadStream type's+ * @c async_read_some operation. */ template <typename AsyncReadStream, typename MutableBufferSequence, ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code,- std::size_t)) ReadHandler+ std::size_t)) ReadToken ASIO_DEFAULT_COMPLETION_TOKEN_TYPE( typename AsyncReadStream::executor_type)>-ASIO_INITFN_AUTO_RESULT_TYPE(ReadHandler,+ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX(ReadToken, void (asio::error_code, std::size_t)) async_read(AsyncReadStream& s, const MutableBufferSequence& buffers,- ASIO_MOVE_ARG(ReadHandler) handler+ ASIO_MOVE_ARG(ReadToken) token ASIO_DEFAULT_COMPLETION_TOKEN( typename AsyncReadStream::executor_type),- typename enable_if<+ typename constraint< is_mutable_buffer_sequence<MutableBufferSequence>::value- >::type* = 0);+ >::type = 0)+ ASIO_INITFN_AUTO_RESULT_TYPE_SUFFIX((+ async_initiate<ReadToken,+ void (asio::error_code, std::size_t)>(+ declval<detail::initiate_async_read<AsyncReadStream> >(),+ token, buffers, transfer_all()))); /// Start an asynchronous operation to read a certain amount of data from a /// stream. /** * This function is used to asynchronously read a certain number of bytes of- * data from a stream. The function call always returns immediately. The- * asynchronous operation will continue until one of the following conditions is- * true:+ * data from a stream. It is an initiating function for an @ref+ * asynchronous_operation, and always returns immediately. The asynchronous+ * operation will continue until one of the following conditions is true: * * @li The supplied buffers are full. That is, the bytes transferred is equal to * the sum of the buffer sizes.@@ -794,7 +833,7 @@ * of the buffer sizes indicates the maximum number of bytes to read from the * stream. Although the buffers object may be copied as necessary, ownership of * the underlying memory blocks is retained by the caller, which must guarantee- * that they remain valid until the handler is called.+ * that they remain valid until the completion handler is called. * * @param completion_condition The function object to be called to determine * whether the read operation is complete. The signature of the function object@@ -810,23 +849,28 @@ * return value indicates the maximum number of bytes to be read on the next * call to the stream's async_read_some function. *- * @param handler The handler to be called when the read operation completes.- * Copies will be made of the handler as required. The function signature of the- * handler must be:+ * @param token The @ref completion_token that will be used to produce a+ * completion handler, which will be called when the read completes.+ * Potential completion tokens include @ref use_future, @ref use_awaitable,+ * @ref yield_context, or a function object with the correct completion+ * signature. The function signature of the completion handler must be: * @code void handler(- * const asio::error_code& error, // Result of operation.+ * // Result of operation.+ * const asio::error_code& error, *- * std::size_t bytes_transferred // Number of bytes copied into the- * // buffers. If an error occurred,- * // this will be the number of- * // bytes successfully transferred- * // prior to the error.+ * // Number of bytes copied into the buffers. If an error+ * // occurred, this will be the number of bytes successfully+ * // transferred prior to the error.+ * std::size_t bytes_transferred * ); @endcode * Regardless of whether the asynchronous operation completes immediately or- * not, the handler will not be invoked from within this function. On- * immediate completion, invocation of the handler will be performed in a+ * not, the completion handler will not be invoked from within this function.+ * On immediate completion, invocation of the handler will be performed in a * manner equivalent to using asio::post(). *+ * @par Completion Signature+ * @code void(asio::error_code, std::size_t) @endcode+ * * @par Example * To read into a single data buffer use the @ref buffer function as follows: * @code asio::async_read(s,@@ -836,23 +880,40 @@ * See the @ref buffer documentation for information on reading into multiple * buffers in one go, and how to use it with arrays, boost::array or * std::vector.+ *+ * @par Per-Operation Cancellation+ * This asynchronous operation supports cancellation for the following+ * asio::cancellation_type values:+ *+ * @li @c cancellation_type::terminal+ *+ * @li @c cancellation_type::partial+ *+ * if they are also supported by the @c AsyncReadStream type's+ * @c async_read_some operation. */ template <typename AsyncReadStream, typename MutableBufferSequence, typename CompletionCondition, ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code,- std::size_t)) ReadHandler+ std::size_t)) ReadToken ASIO_DEFAULT_COMPLETION_TOKEN_TYPE( typename AsyncReadStream::executor_type)>-ASIO_INITFN_AUTO_RESULT_TYPE(ReadHandler,+ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX(ReadToken, void (asio::error_code, std::size_t)) async_read(AsyncReadStream& s, const MutableBufferSequence& buffers, CompletionCondition completion_condition,- ASIO_MOVE_ARG(ReadHandler) handler+ ASIO_MOVE_ARG(ReadToken) token ASIO_DEFAULT_COMPLETION_TOKEN( typename AsyncReadStream::executor_type),- typename enable_if<+ typename constraint< is_mutable_buffer_sequence<MutableBufferSequence>::value- >::type* = 0);+ >::type = 0)+ ASIO_INITFN_AUTO_RESULT_TYPE_SUFFIX((+ async_initiate<ReadToken,+ void (asio::error_code, std::size_t)>(+ declval<detail::initiate_async_read<AsyncReadStream> >(),+ token, buffers,+ ASIO_MOVE_CAST(CompletionCondition)(completion_condition)))); #if !defined(ASIO_NO_DYNAMIC_BUFFER_V1) @@ -860,9 +921,9 @@ /// stream. /** * This function is used to asynchronously read a certain number of bytes of- * data from a stream. The function call always returns immediately. The- * asynchronous operation will continue until one of the following conditions is- * true:+ * data from a stream. It is an initiating function for an @ref+ * asynchronous_operation, and always returns immediately. The asynchronous+ * operation will continue until one of the following conditions is true: * * @li The specified dynamic buffer sequence is full (that is, it has reached * maximum size).@@ -881,55 +942,79 @@ * @param buffers The dynamic buffer sequence into which the data will be read. * Although the buffers object may be copied as necessary, ownership of the * underlying memory blocks is retained by the caller, which must guarantee- * that they remain valid until the handler is called.+ * that they remain valid until the completion handler is called. *- * @param handler The handler to be called when the read operation completes.- * Copies will be made of the handler as required. The function signature of the- * handler must be:+ * @param token The @ref completion_token that will be used to produce a+ * completion handler, which will be called when the read completes.+ * Potential completion tokens include @ref use_future, @ref use_awaitable,+ * @ref yield_context, or a function object with the correct completion+ * signature. The function signature of the completion handler must be: * @code void handler(- * const asio::error_code& error, // Result of operation.+ * // Result of operation.+ * const asio::error_code& error, *- * std::size_t bytes_transferred // Number of bytes copied into the- * // buffers. If an error occurred,- * // this will be the number of- * // bytes successfully transferred- * // prior to the error.+ * // Number of bytes copied into the buffers. If an error+ * // occurred, this will be the number of bytes successfully+ * // transferred prior to the error.+ * std::size_t bytes_transferred * ); @endcode * Regardless of whether the asynchronous operation completes immediately or- * not, the handler will not be invoked from within this function. On- * immediate completion, invocation of the handler will be performed in a+ * not, the completion handler will not be invoked from within this function.+ * On immediate completion, invocation of the handler will be performed in a * manner equivalent to using asio::post(). *+ * @par Completion Signature+ * @code void(asio::error_code, std::size_t) @endcode+ * * @note This overload is equivalent to calling: * @code asio::async_read( * s, buffers, * asio::transfer_all(), * handler); @endcode+ *+ * @par Per-Operation Cancellation+ * This asynchronous operation supports cancellation for the following+ * asio::cancellation_type values:+ *+ * @li @c cancellation_type::terminal+ *+ * @li @c cancellation_type::partial+ *+ * if they are also supported by the @c AsyncReadStream type's+ * @c async_read_some operation. */ template <typename AsyncReadStream, typename DynamicBuffer_v1, ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code,- std::size_t)) ReadHandler+ std::size_t)) ReadToken ASIO_DEFAULT_COMPLETION_TOKEN_TYPE( typename AsyncReadStream::executor_type)>-ASIO_INITFN_AUTO_RESULT_TYPE(ReadHandler,+ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX(ReadToken, void (asio::error_code, std::size_t)) async_read(AsyncReadStream& s, ASIO_MOVE_ARG(DynamicBuffer_v1) buffers,- ASIO_MOVE_ARG(ReadHandler) handler+ ASIO_MOVE_ARG(ReadToken) token ASIO_DEFAULT_COMPLETION_TOKEN( typename AsyncReadStream::executor_type),- typename enable_if<+ typename constraint< is_dynamic_buffer_v1<typename decay<DynamicBuffer_v1>::type>::value- && !is_dynamic_buffer_v2<typename decay<DynamicBuffer_v1>::type>::value- >::type* = 0);+ >::type = 0,+ typename constraint<+ !is_dynamic_buffer_v2<typename decay<DynamicBuffer_v1>::type>::value+ >::type = 0)+ ASIO_INITFN_AUTO_RESULT_TYPE_SUFFIX((+ async_initiate<ReadToken,+ void (asio::error_code, std::size_t)>(+ declval<detail::initiate_async_read_dynbuf_v1<AsyncReadStream> >(),+ token, ASIO_MOVE_CAST(DynamicBuffer_v1)(buffers),+ transfer_all()))); /// Start an asynchronous operation to read a certain amount of data from a /// stream. /** * This function is used to asynchronously read a certain number of bytes of- * data from a stream. The function call always returns immediately. The- * asynchronous operation will continue until one of the following conditions is- * true:+ * data from a stream. It is an initiating function for an @ref+ * asynchronous_operation, and always returns immediately. The asynchronous+ * operation will continue until one of the following conditions is true: * * @li The specified dynamic buffer sequence is full (that is, it has reached * maximum size).@@ -948,7 +1033,7 @@ * @param buffers The dynamic buffer sequence into which the data will be read. * Although the buffers object may be copied as necessary, ownership of the * underlying memory blocks is retained by the caller, which must guarantee- * that they remain valid until the handler is called.+ * that they remain valid until the completion handler is called. * * @param completion_condition The function object to be called to determine * whether the read operation is complete. The signature of the function object@@ -964,41 +1049,65 @@ * return value indicates the maximum number of bytes to be read on the next * call to the stream's async_read_some function. *- * @param handler The handler to be called when the read operation completes.- * Copies will be made of the handler as required. The function signature of the- * handler must be:+ * @param token The @ref completion_token that will be used to produce a+ * completion handler, which will be called when the read completes.+ * Potential completion tokens include @ref use_future, @ref use_awaitable,+ * @ref yield_context, or a function object with the correct completion+ * signature. The function signature of the completion handler must be: * @code void handler(- * const asio::error_code& error, // Result of operation.+ * // Result of operation.+ * const asio::error_code& error, *- * std::size_t bytes_transferred // Number of bytes copied into the- * // buffers. If an error occurred,- * // this will be the number of- * // bytes successfully transferred- * // prior to the error.+ * // Number of bytes copied into the buffers. If an error+ * // occurred, this will be the number of bytes successfully+ * // transferred prior to the error.+ * std::size_t bytes_transferred * ); @endcode * Regardless of whether the asynchronous operation completes immediately or- * not, the handler will not be invoked from within this function. On- * immediate completion, invocation of the handler will be performed in a+ * not, the completion handler will not be invoked from within this function.+ * On immediate completion, invocation of the handler will be performed in a * manner equivalent to using asio::post().+ *+ * @par Completion Signature+ * @code void(asio::error_code, std::size_t) @endcode+ *+ * @par Per-Operation Cancellation+ * This asynchronous operation supports cancellation for the following+ * asio::cancellation_type values:+ *+ * @li @c cancellation_type::terminal+ *+ * @li @c cancellation_type::partial+ *+ * if they are also supported by the @c AsyncReadStream type's+ * @c async_read_some operation. */ template <typename AsyncReadStream, typename DynamicBuffer_v1, typename CompletionCondition, ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code,- std::size_t)) ReadHandler+ std::size_t)) ReadToken ASIO_DEFAULT_COMPLETION_TOKEN_TYPE( typename AsyncReadStream::executor_type)>-ASIO_INITFN_AUTO_RESULT_TYPE(ReadHandler,+ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX(ReadToken, void (asio::error_code, std::size_t)) async_read(AsyncReadStream& s, ASIO_MOVE_ARG(DynamicBuffer_v1) buffers, CompletionCondition completion_condition,- ASIO_MOVE_ARG(ReadHandler) handler+ ASIO_MOVE_ARG(ReadToken) token ASIO_DEFAULT_COMPLETION_TOKEN( typename AsyncReadStream::executor_type),- typename enable_if<+ typename constraint< is_dynamic_buffer_v1<typename decay<DynamicBuffer_v1>::type>::value- && !is_dynamic_buffer_v2<typename decay<DynamicBuffer_v1>::type>::value- >::type* = 0);+ >::type = 0,+ typename constraint<+ !is_dynamic_buffer_v2<typename decay<DynamicBuffer_v1>::type>::value+ >::type = 0)+ ASIO_INITFN_AUTO_RESULT_TYPE_SUFFIX((+ async_initiate<ReadToken,+ void (asio::error_code, std::size_t)>(+ declval<detail::initiate_async_read_dynbuf_v1<AsyncReadStream> >(),+ token, ASIO_MOVE_CAST(DynamicBuffer_v1)(buffers),+ ASIO_MOVE_CAST(CompletionCondition)(completion_condition)))); #if !defined(ASIO_NO_EXTENSIONS) #if !defined(ASIO_NO_IOSTREAM)@@ -1007,9 +1116,9 @@ /// stream. /** * This function is used to asynchronously read a certain number of bytes of- * data from a stream. The function call always returns immediately. The- * asynchronous operation will continue until one of the following conditions is- * true:+ * data from a stream. It is an initiating function for an @ref+ * asynchronous_operation, and always returns immediately. The asynchronous+ * operation will continue until one of the following conditions is true: * * @li The supplied buffer is full (that is, it has reached maximum size). *@@ -1026,50 +1135,69 @@ * * @param b A basic_streambuf object into which the data will be read. Ownership * of the streambuf is retained by the caller, which must guarantee that it- * remains valid until the handler is called.+ * remains valid until the completion handler is called. *- * @param handler The handler to be called when the read operation completes.- * Copies will be made of the handler as required. The function signature of the- * handler must be:+ * @param token The @ref completion_token that will be used to produce a+ * completion handler, which will be called when the read completes.+ * Potential completion tokens include @ref use_future, @ref use_awaitable,+ * @ref yield_context, or a function object with the correct completion+ * signature. The function signature of the completion handler must be: * @code void handler(- * const asio::error_code& error, // Result of operation.+ * // Result of operation.+ * const asio::error_code& error, *- * std::size_t bytes_transferred // Number of bytes copied into the- * // buffers. If an error occurred,- * // this will be the number of- * // bytes successfully transferred- * // prior to the error.+ * // Number of bytes copied into the buffers. If an error+ * // occurred, this will be the number of bytes successfully+ * // transferred prior to the error.+ * std::size_t bytes_transferred * ); @endcode * Regardless of whether the asynchronous operation completes immediately or- * not, the handler will not be invoked from within this function. On- * immediate completion, invocation of the handler will be performed in a+ * not, the completion handler will not be invoked from within this function.+ * On immediate completion, invocation of the handler will be performed in a * manner equivalent to using asio::post(). *+ * @par Completion Signature+ * @code void(asio::error_code, std::size_t) @endcode+ * * @note This overload is equivalent to calling: * @code asio::async_read( * s, b, * asio::transfer_all(), * handler); @endcode+ *+ * @par Per-Operation Cancellation+ * This asynchronous operation supports cancellation for the following+ * asio::cancellation_type values:+ *+ * @li @c cancellation_type::terminal+ *+ * @li @c cancellation_type::partial+ *+ * if they are also supported by the @c AsyncReadStream type's+ * @c async_read_some operation. */ template <typename AsyncReadStream, typename Allocator, ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code,- std::size_t)) ReadHandler+ std::size_t)) ReadToken ASIO_DEFAULT_COMPLETION_TOKEN_TYPE( typename AsyncReadStream::executor_type)>-ASIO_INITFN_AUTO_RESULT_TYPE(ReadHandler,+ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX(ReadToken, void (asio::error_code, std::size_t)) async_read(AsyncReadStream& s, basic_streambuf<Allocator>& b,- ASIO_MOVE_ARG(ReadHandler) handler+ ASIO_MOVE_ARG(ReadToken) token ASIO_DEFAULT_COMPLETION_TOKEN(- typename AsyncReadStream::executor_type));+ typename AsyncReadStream::executor_type))+ ASIO_INITFN_AUTO_RESULT_TYPE_SUFFIX((+ async_read(s, basic_streambuf_ref<Allocator>(b),+ ASIO_MOVE_CAST(ReadToken)(token)))); /// Start an asynchronous operation to read a certain amount of data from a /// stream. /** * This function is used to asynchronously read a certain number of bytes of- * data from a stream. The function call always returns immediately. The- * asynchronous operation will continue until one of the following conditions is- * true:+ * data from a stream. It is an initiating function for an @ref+ * asynchronous_operation, and always returns immediately. The asynchronous+ * operation will continue until one of the following conditions is true: * * @li The supplied buffer is full (that is, it has reached maximum size). *@@ -1086,7 +1214,7 @@ * * @param b A basic_streambuf object into which the data will be read. Ownership * of the streambuf is retained by the caller, which must guarantee that it- * remains valid until the handler is called.+ * remains valid until the completion handler is called. * * @param completion_condition The function object to be called to determine * whether the read operation is complete. The signature of the function object@@ -1102,36 +1230,56 @@ * return value indicates the maximum number of bytes to be read on the next * call to the stream's async_read_some function. *- * @param handler The handler to be called when the read operation completes.- * Copies will be made of the handler as required. The function signature of the- * handler must be:+ * @param token The @ref completion_token that will be used to produce a+ * completion handler, which will be called when the read completes.+ * Potential completion tokens include @ref use_future, @ref use_awaitable,+ * @ref yield_context, or a function object with the correct completion+ * signature. The function signature of the completion handler must be: * @code void handler(- * const asio::error_code& error, // Result of operation.+ * // Result of operation.+ * const asio::error_code& error, *- * std::size_t bytes_transferred // Number of bytes copied into the- * // buffers. If an error occurred,- * // this will be the number of- * // bytes successfully transferred- * // prior to the error.+ * // Number of bytes copied into the buffers. If an error+ * // occurred, this will be the number of bytes successfully+ * // transferred prior to the error.+ * std::size_t bytes_transferred * ); @endcode * Regardless of whether the asynchronous operation completes immediately or- * not, the handler will not be invoked from within this function. On- * immediate completion, invocation of the handler will be performed in a+ * not, the completion handler will not be invoked from within this function.+ * On immediate completion, invocation of the handler will be performed in a * manner equivalent to using asio::post().+ *+ * @par Completion Signature+ * @code void(asio::error_code, std::size_t) @endcode+ *+ * @par Per-Operation Cancellation+ * This asynchronous operation supports cancellation for the following+ * asio::cancellation_type values:+ *+ * @li @c cancellation_type::terminal+ *+ * @li @c cancellation_type::partial+ *+ * if they are also supported by the @c AsyncReadStream type's+ * @c async_read_some operation. */ template <typename AsyncReadStream, typename Allocator, typename CompletionCondition, ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code,- std::size_t)) ReadHandler+ std::size_t)) ReadToken ASIO_DEFAULT_COMPLETION_TOKEN_TYPE( typename AsyncReadStream::executor_type)>-ASIO_INITFN_AUTO_RESULT_TYPE(ReadHandler,+ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX(ReadToken, void (asio::error_code, std::size_t)) async_read(AsyncReadStream& s, basic_streambuf<Allocator>& b, CompletionCondition completion_condition,- ASIO_MOVE_ARG(ReadHandler) handler+ ASIO_MOVE_ARG(ReadToken) token ASIO_DEFAULT_COMPLETION_TOKEN(- typename AsyncReadStream::executor_type));+ typename AsyncReadStream::executor_type))+ ASIO_INITFN_AUTO_RESULT_TYPE_SUFFIX((+ async_read(s, basic_streambuf_ref<Allocator>(b),+ ASIO_MOVE_CAST(CompletionCondition)(completion_condition),+ ASIO_MOVE_CAST(ReadToken)(token)))); #endif // !defined(ASIO_NO_IOSTREAM) #endif // !defined(ASIO_NO_EXTENSIONS)@@ -1141,9 +1289,9 @@ /// stream. /** * This function is used to asynchronously read a certain number of bytes of- * data from a stream. The function call always returns immediately. The- * asynchronous operation will continue until one of the following conditions is- * true:+ * data from a stream. It is an initiating function for an @ref+ * asynchronous_operation, and always returns immediately. The asynchronous+ * operation will continue until one of the following conditions is true: * * @li The specified dynamic buffer sequence is full (that is, it has reached * maximum size).@@ -1162,53 +1310,75 @@ * @param buffers The dynamic buffer sequence into which the data will be read. * Although the buffers object may be copied as necessary, ownership of the * underlying memory blocks is retained by the caller, which must guarantee- * that they remain valid until the handler is called.+ * that they remain valid until the completion handler is called. *- * @param handler The handler to be called when the read operation completes.- * Copies will be made of the handler as required. The function signature of the- * handler must be:+ * @param token The @ref completion_token that will be used to produce a+ * completion handler, which will be called when the read completes.+ * Potential completion tokens include @ref use_future, @ref use_awaitable,+ * @ref yield_context, or a function object with the correct completion+ * signature. The function signature of the completion handler must be: * @code void handler(- * const asio::error_code& error, // Result of operation.+ * // Result of operation.+ * const asio::error_code& error, *- * std::size_t bytes_transferred // Number of bytes copied into the- * // buffers. If an error occurred,- * // this will be the number of- * // bytes successfully transferred- * // prior to the error.+ * // Number of bytes copied into the buffers. If an error+ * // occurred, this will be the number of bytes successfully+ * // transferred prior to the error.+ * std::size_t bytes_transferred * ); @endcode * Regardless of whether the asynchronous operation completes immediately or- * not, the handler will not be invoked from within this function. On- * immediate completion, invocation of the handler will be performed in a+ * not, the completion handler will not be invoked from within this function.+ * On immediate completion, invocation of the handler will be performed in a * manner equivalent to using asio::post(). *+ * @par Completion Signature+ * @code void(asio::error_code, std::size_t) @endcode+ * * @note This overload is equivalent to calling: * @code asio::async_read( * s, buffers, * asio::transfer_all(), * handler); @endcode+ *+ * @par Per-Operation Cancellation+ * This asynchronous operation supports cancellation for the following+ * asio::cancellation_type values:+ *+ * @li @c cancellation_type::terminal+ *+ * @li @c cancellation_type::partial+ *+ * if they are also supported by the @c AsyncReadStream type's+ * @c async_read_some operation. */ template <typename AsyncReadStream, typename DynamicBuffer_v2, ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code,- std::size_t)) ReadHandler+ std::size_t)) ReadToken ASIO_DEFAULT_COMPLETION_TOKEN_TYPE( typename AsyncReadStream::executor_type)>-ASIO_INITFN_AUTO_RESULT_TYPE(ReadHandler,+ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX(ReadToken, void (asio::error_code, std::size_t)) async_read(AsyncReadStream& s, DynamicBuffer_v2 buffers,- ASIO_MOVE_ARG(ReadHandler) handler+ ASIO_MOVE_ARG(ReadToken) token ASIO_DEFAULT_COMPLETION_TOKEN( typename AsyncReadStream::executor_type),- typename enable_if<+ typename constraint< is_dynamic_buffer_v2<DynamicBuffer_v2>::value- >::type* = 0);+ >::type = 0)+ ASIO_INITFN_AUTO_RESULT_TYPE_SUFFIX((+ async_initiate<ReadToken,+ void (asio::error_code, std::size_t)>(+ declval<detail::initiate_async_read_dynbuf_v2<AsyncReadStream> >(),+ token, ASIO_MOVE_CAST(DynamicBuffer_v2)(buffers),+ transfer_all()))); /// Start an asynchronous operation to read a certain amount of data from a /// stream. /** * This function is used to asynchronously read a certain number of bytes of- * data from a stream. The function call always returns immediately. The- * asynchronous operation will continue until one of the following conditions is- * true:+ * data from a stream. It is an initiating function for an @ref+ * asynchronous_operation, and always returns immediately. The asynchronous+ * operation will continue until one of the following conditions is true: * * @li The specified dynamic buffer sequence is full (that is, it has reached * maximum size).@@ -1227,7 +1397,7 @@ * @param buffers The dynamic buffer sequence into which the data will be read. * Although the buffers object may be copied as necessary, ownership of the * underlying memory blocks is retained by the caller, which must guarantee- * that they remain valid until the handler is called.+ * that they remain valid until the completion handler is called. * * @param completion_condition The function object to be called to determine * whether the read operation is complete. The signature of the function object@@ -1243,39 +1413,61 @@ * return value indicates the maximum number of bytes to be read on the next * call to the stream's async_read_some function. *- * @param handler The handler to be called when the read operation completes.- * Copies will be made of the handler as required. The function signature of the- * handler must be:+ * @param token The @ref completion_token that will be used to produce a+ * completion handler, which will be called when the read completes.+ * Potential completion tokens include @ref use_future, @ref use_awaitable,+ * @ref yield_context, or a function object with the correct completion+ * signature. The function signature of the completion handler must be: * @code void handler(- * const asio::error_code& error, // Result of operation.+ * // Result of operation.+ * const asio::error_code& error, *- * std::size_t bytes_transferred // Number of bytes copied into the- * // buffers. If an error occurred,- * // this will be the number of- * // bytes successfully transferred- * // prior to the error.+ * // Number of bytes copied into the buffers. If an error+ * // occurred, this will be the number of bytes successfully+ * // transferred prior to the error.+ * std::size_t bytes_transferred * ); @endcode * Regardless of whether the asynchronous operation completes immediately or- * not, the handler will not be invoked from within this function. On- * immediate completion, invocation of the handler will be performed in a+ * not, the completion handler will not be invoked from within this function.+ * On immediate completion, invocation of the handler will be performed in a * manner equivalent to using asio::post().+ *+ * @par Completion Signature+ * @code void(asio::error_code, std::size_t) @endcode+ *+ * @par Per-Operation Cancellation+ * This asynchronous operation supports cancellation for the following+ * asio::cancellation_type values:+ *+ * @li @c cancellation_type::terminal+ *+ * @li @c cancellation_type::partial+ *+ * if they are also supported by the @c AsyncReadStream type's+ * @c async_read_some operation. */ template <typename AsyncReadStream, typename DynamicBuffer_v2, typename CompletionCondition, ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code,- std::size_t)) ReadHandler+ std::size_t)) ReadToken ASIO_DEFAULT_COMPLETION_TOKEN_TYPE( typename AsyncReadStream::executor_type)>-ASIO_INITFN_AUTO_RESULT_TYPE(ReadHandler,+ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX(ReadToken, void (asio::error_code, std::size_t)) async_read(AsyncReadStream& s, DynamicBuffer_v2 buffers, CompletionCondition completion_condition,- ASIO_MOVE_ARG(ReadHandler) handler+ ASIO_MOVE_ARG(ReadToken) token ASIO_DEFAULT_COMPLETION_TOKEN( typename AsyncReadStream::executor_type),- typename enable_if<+ typename constraint< is_dynamic_buffer_v2<DynamicBuffer_v2>::value- >::type* = 0);+ >::type = 0)+ ASIO_INITFN_AUTO_RESULT_TYPE_SUFFIX((+ async_initiate<ReadToken,+ void (asio::error_code, std::size_t)>(+ declval<detail::initiate_async_read_dynbuf_v2<AsyncReadStream> >(),+ token, ASIO_MOVE_CAST(DynamicBuffer_v2)(buffers),+ ASIO_MOVE_CAST(CompletionCondition)(completion_condition)))); /*@}*/
link/modules/asio-standalone/asio/include/asio/read_at.hpp view
@@ -2,7 +2,7 @@ // read_at.hpp // ~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -18,6 +18,7 @@ #include "asio/detail/config.hpp" #include <cstddef> #include "asio/async_result.hpp"+#include "asio/completion_condition.hpp" #include "asio/detail/cstdint.hpp" #include "asio/error.hpp" @@ -28,7 +29,15 @@ #include "asio/detail/push_options.hpp" namespace asio {+namespace detail { +template <typename> class initiate_async_read_at;+#if !defined(ASIO_NO_IOSTREAM)+template <typename> class initiate_async_read_at_streambuf;+#endif // !defined(ASIO_NO_IOSTREAM)++} // namespace detail+ /** * @defgroup read_at asio::read_at *@@ -403,9 +412,10 @@ /// specified offset. /** * This function is used to asynchronously read a certain number of bytes of- * data from a random access device at the specified offset. The function call- * always returns immediately. The asynchronous operation will continue until- * one of the following conditions is true:+ * data from a random access device at the specified offset. It is an+ * initiating function for an @ref asynchronous_operation, and always returns+ * immediately. The asynchronous operation will continue until one of the+ * following conditions is true: * * @li The supplied buffers are full. That is, the bytes transferred is equal to * the sum of the buffer sizes.@@ -424,11 +434,13 @@ * of the buffer sizes indicates the maximum number of bytes to read from the * device. Although the buffers object may be copied as necessary, ownership of * the underlying memory blocks is retained by the caller, which must guarantee- * that they remain valid until the handler is called.+ * that they remain valid until the completion handler is called. *- * @param handler The handler to be called when the read operation completes.- * Copies will be made of the handler as required. The function signature of the- * handler must be:+ * @param token The @ref completion_token that will be used to produce a+ * completion handler, which will be called when the read completes.+ * Potential completion tokens include @ref use_future, @ref use_awaitable,+ * @ref yield_context, or a function object with the correct completion+ * signature. The function signature of the completion handler must be: * @code void handler( * // Result of operation. * const asio::error_code& error,@@ -439,10 +451,13 @@ * std::size_t bytes_transferred * ); @endcode * Regardless of whether the asynchronous operation completes immediately or- * not, the handler will not be invoked from within this function. On- * immediate completion, invocation of the handler will be performed in a+ * not, the completion handler will not be invoked from within this function.+ * On immediate completion, invocation of the handler will be performed in a * manner equivalent to using asio::post(). *+ * @par Completion Signature+ * @code void(asio::error_code, std::size_t) @endcode+ * * @par Example * To read into a single data buffer use the @ref buffer function as follows: * @code@@ -457,27 +472,44 @@ * d, 42, buffers, * asio::transfer_all(), * handler); @endcode+ *+ * @par Per-Operation Cancellation+ * This asynchronous operation supports cancellation for the following+ * asio::cancellation_type values:+ *+ * @li @c cancellation_type::terminal+ *+ * @li @c cancellation_type::partial+ *+ * if they are also supported by the @c AsyncRandomAccessReadDevice type's+ * async_read_some_at operation. */ template <typename AsyncRandomAccessReadDevice, typename MutableBufferSequence, ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code,- std::size_t)) ReadHandler+ std::size_t)) ReadToken ASIO_DEFAULT_COMPLETION_TOKEN_TYPE( typename AsyncRandomAccessReadDevice::executor_type)>-ASIO_INITFN_AUTO_RESULT_TYPE(ReadHandler,+ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX(ReadToken, void (asio::error_code, std::size_t)) async_read_at(AsyncRandomAccessReadDevice& d, uint64_t offset, const MutableBufferSequence& buffers,- ASIO_MOVE_ARG(ReadHandler) handler+ ASIO_MOVE_ARG(ReadToken) token ASIO_DEFAULT_COMPLETION_TOKEN(- typename AsyncRandomAccessReadDevice::executor_type));+ typename AsyncRandomAccessReadDevice::executor_type))+ ASIO_INITFN_AUTO_RESULT_TYPE_SUFFIX((+ async_initiate<ReadToken,+ void (asio::error_code, std::size_t)>(+ declval<detail::initiate_async_read_at<AsyncRandomAccessReadDevice> >(),+ token, offset, buffers, transfer_all()))); /// Start an asynchronous operation to read a certain amount of data at the /// specified offset. /** * This function is used to asynchronously read a certain number of bytes of- * data from a random access device at the specified offset. The function call- * always returns immediately. The asynchronous operation will continue until- * one of the following conditions is true:+ * data from a random access device at the specified offset. It is an+ * initiating function for an @ref asynchronous_operation, and always returns+ * immediately. The asynchronous operation will continue until one of the+ * following conditions is true: * * @li The supplied buffers are full. That is, the bytes transferred is equal to * the sum of the buffer sizes.@@ -493,7 +525,7 @@ * of the buffer sizes indicates the maximum number of bytes to read from the * device. Although the buffers object may be copied as necessary, ownership of * the underlying memory blocks is retained by the caller, which must guarantee- * that they remain valid until the handler is called.+ * that they remain valid until the completion handler is called. * * @param completion_condition The function object to be called to determine * whether the read operation is complete. The signature of the function object@@ -509,9 +541,11 @@ * return value indicates the maximum number of bytes to be read on the next * call to the device's async_read_some_at function. *- * @param handler The handler to be called when the read operation completes.- * Copies will be made of the handler as required. The function signature of the- * handler must be:+ * @param token The @ref completion_token that will be used to produce a+ * completion handler, which will be called when the read completes.+ * Potential completion tokens include @ref use_future, @ref use_awaitable,+ * @ref yield_context, or a function object with the correct completion+ * signature. The function signature of the completion handler must be: * @code void handler( * // Result of operation. * const asio::error_code& error,@@ -522,10 +556,13 @@ * std::size_t bytes_transferred * ); @endcode * Regardless of whether the asynchronous operation completes immediately or- * not, the handler will not be invoked from within this function. On- * immediate completion, invocation of the handler will be performed in a+ * not, the completion handler will not be invoked from within this function.+ * On immediate completion, invocation of the handler will be performed in a * manner equivalent to using asio::post(). *+ * @par Completion Signature+ * @code void(asio::error_code, std::size_t) @endcode+ * * @par Example * To read into a single data buffer use the @ref buffer function as follows: * @code asio::async_read_at(d, 42,@@ -535,21 +572,38 @@ * See the @ref buffer documentation for information on reading into multiple * buffers in one go, and how to use it with arrays, boost::array or * std::vector.+ *+ * @par Per-Operation Cancellation+ * This asynchronous operation supports cancellation for the following+ * asio::cancellation_type values:+ *+ * @li @c cancellation_type::terminal+ *+ * @li @c cancellation_type::partial+ *+ * if they are also supported by the @c AsyncRandomAccessReadDevice type's+ * async_read_some_at operation. */ template <typename AsyncRandomAccessReadDevice, typename MutableBufferSequence, typename CompletionCondition, ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code,- std::size_t)) ReadHandler+ std::size_t)) ReadToken ASIO_DEFAULT_COMPLETION_TOKEN_TYPE( typename AsyncRandomAccessReadDevice::executor_type)>-ASIO_INITFN_AUTO_RESULT_TYPE(ReadHandler,+ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX(ReadToken, void (asio::error_code, std::size_t)) async_read_at(AsyncRandomAccessReadDevice& d, uint64_t offset, const MutableBufferSequence& buffers, CompletionCondition completion_condition,- ASIO_MOVE_ARG(ReadHandler) handler+ ASIO_MOVE_ARG(ReadToken) token ASIO_DEFAULT_COMPLETION_TOKEN(- typename AsyncRandomAccessReadDevice::executor_type));+ typename AsyncRandomAccessReadDevice::executor_type))+ ASIO_INITFN_AUTO_RESULT_TYPE_SUFFIX((+ async_initiate<ReadToken,+ void (asio::error_code, std::size_t)>(+ declval<detail::initiate_async_read_at<AsyncRandomAccessReadDevice> >(),+ token, offset, buffers,+ ASIO_MOVE_CAST(CompletionCondition)(completion_condition)))); #if !defined(ASIO_NO_EXTENSIONS) #if !defined(ASIO_NO_IOSTREAM)@@ -558,9 +612,10 @@ /// specified offset. /** * This function is used to asynchronously read a certain number of bytes of- * data from a random access device at the specified offset. The function call- * always returns immediately. The asynchronous operation will continue until- * one of the following conditions is true:+ * data from a random access device at the specified offset. It is an+ * initiating function for an @ref asynchronous_operation, and always returns+ * immediately. The asynchronous operation will continue until one of the+ * following conditions is true: * * @li An error occurred. *@@ -574,11 +629,13 @@ * * @param b A basic_streambuf object into which the data will be read. Ownership * of the streambuf is retained by the caller, which must guarantee that it- * remains valid until the handler is called.+ * remains valid until the completion handler is called. *- * @param handler The handler to be called when the read operation completes.- * Copies will be made of the handler as required. The function signature of the- * handler must be:+ * @param token The @ref completion_token that will be used to produce a+ * completion handler, which will be called when the read completes.+ * Potential completion tokens include @ref use_future, @ref use_awaitable,+ * @ref yield_context, or a function object with the correct completion+ * signature. The function signature of the completion handler must be: * @code void handler( * // Result of operation. * const asio::error_code& error,@@ -589,36 +646,57 @@ * std::size_t bytes_transferred * ); @endcode * Regardless of whether the asynchronous operation completes immediately or- * not, the handler will not be invoked from within this function. On- * immediate completion, invocation of the handler will be performed in a+ * not, the completion handler will not be invoked from within this function.+ * On immediate completion, invocation of the handler will be performed in a * manner equivalent to using asio::post(). *+ * @par Completion Signature+ * @code void(asio::error_code, std::size_t) @endcode+ * * @note This overload is equivalent to calling: * @code asio::async_read_at( * d, 42, b, * asio::transfer_all(), * handler); @endcode+ *+ * @par Per-Operation Cancellation+ * This asynchronous operation supports cancellation for the following+ * asio::cancellation_type values:+ *+ * @li @c cancellation_type::terminal+ *+ * @li @c cancellation_type::partial+ *+ * if they are also supported by the @c AsyncRandomAccessReadDevice type's+ * async_read_some_at operation. */ template <typename AsyncRandomAccessReadDevice, typename Allocator, ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code,- std::size_t)) ReadHandler+ std::size_t)) ReadToken ASIO_DEFAULT_COMPLETION_TOKEN_TYPE( typename AsyncRandomAccessReadDevice::executor_type)>-ASIO_INITFN_AUTO_RESULT_TYPE(ReadHandler,+ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX(ReadToken, void (asio::error_code, std::size_t)) async_read_at(AsyncRandomAccessReadDevice& d, uint64_t offset, basic_streambuf<Allocator>& b,- ASIO_MOVE_ARG(ReadHandler) handler+ ASIO_MOVE_ARG(ReadToken) token ASIO_DEFAULT_COMPLETION_TOKEN(- typename AsyncRandomAccessReadDevice::executor_type));+ typename AsyncRandomAccessReadDevice::executor_type))+ ASIO_INITFN_AUTO_RESULT_TYPE_SUFFIX((+ async_initiate<ReadToken,+ void (asio::error_code, std::size_t)>(+ declval<detail::initiate_async_read_at_streambuf<+ AsyncRandomAccessReadDevice> >(),+ token, offset, &b, transfer_all()))); /// Start an asynchronous operation to read a certain amount of data at the /// specified offset. /** * This function is used to asynchronously read a certain number of bytes of- * data from a random access device at the specified offset. The function call- * always returns immediately. The asynchronous operation will continue until- * one of the following conditions is true:+ * data from a random access device at the specified offset. It is an+ * initiating function for an @ref asynchronous_operation, and always returns+ * immediately. The asynchronous operation will continue until one of the+ * following conditions is true: * * @li The completion_condition function object returns 0. *@@ -632,7 +710,7 @@ * * @param b A basic_streambuf object into which the data will be read. Ownership * of the streambuf is retained by the caller, which must guarantee that it- * remains valid until the handler is called.+ * remains valid until the completion handler is called. * * @param completion_condition The function object to be called to determine * whether the read operation is complete. The signature of the function object@@ -648,9 +726,11 @@ * return value indicates the maximum number of bytes to be read on the next * call to the device's async_read_some_at function. *- * @param handler The handler to be called when the read operation completes.- * Copies will be made of the handler as required. The function signature of the- * handler must be:+ * @param token The @ref completion_token that will be used to produce a+ * completion handler, which will be called when the read completes.+ * Potential completion tokens include @ref use_future, @ref use_awaitable,+ * @ref yield_context, or a function object with the correct completion+ * signature. The function signature of the completion handler must be: * @code void handler( * // Result of operation. * const asio::error_code& error,@@ -661,24 +741,45 @@ * std::size_t bytes_transferred * ); @endcode * Regardless of whether the asynchronous operation completes immediately or- * not, the handler will not be invoked from within this function. On- * immediate completion, invocation of the handler will be performed in a+ * not, the completion handler will not be invoked from within this function.+ * On immediate completion, invocation of the handler will be performed in a * manner equivalent to using asio::post().+ *+ * @par Completion Signature+ * @code void(asio::error_code, std::size_t) @endcode+ *+ * @par Per-Operation Cancellation+ * This asynchronous operation supports cancellation for the following+ * asio::cancellation_type values:+ *+ * @li @c cancellation_type::terminal+ *+ * @li @c cancellation_type::partial+ *+ * if they are also supported by the @c AsyncRandomAccessReadDevice type's+ * async_read_some_at operation. */ template <typename AsyncRandomAccessReadDevice, typename Allocator, typename CompletionCondition, ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code,- std::size_t)) ReadHandler+ std::size_t)) ReadToken ASIO_DEFAULT_COMPLETION_TOKEN_TYPE( typename AsyncRandomAccessReadDevice::executor_type)>-ASIO_INITFN_AUTO_RESULT_TYPE(ReadHandler,+ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX(ReadToken, void (asio::error_code, std::size_t)) async_read_at(AsyncRandomAccessReadDevice& d, uint64_t offset, basic_streambuf<Allocator>& b, CompletionCondition completion_condition,- ASIO_MOVE_ARG(ReadHandler) handler+ ASIO_MOVE_ARG(ReadToken) token ASIO_DEFAULT_COMPLETION_TOKEN(- typename AsyncRandomAccessReadDevice::executor_type));+ typename AsyncRandomAccessReadDevice::executor_type))+ ASIO_INITFN_AUTO_RESULT_TYPE_SUFFIX((+ async_initiate<ReadToken,+ void (asio::error_code, std::size_t)>(+ declval<detail::initiate_async_read_at_streambuf<+ AsyncRandomAccessReadDevice> >(),+ token, offset, &b,+ ASIO_MOVE_CAST(CompletionCondition)(completion_condition)))); #endif // !defined(ASIO_NO_IOSTREAM) #endif // !defined(ASIO_NO_EXTENSIONS)
link/modules/asio-standalone/asio/include/asio/read_until.hpp view
@@ -2,7 +2,7 @@ // read_until.hpp // ~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -32,19 +32,34 @@ #include "asio/detail/push_options.hpp" namespace asio {+namespace detail { -namespace detail+char (&has_result_type_helper(...))[2];++template <typename T>+char has_result_type_helper(T*, typename T::result_type* = 0);++template <typename T>+struct has_result_type {- char (&has_result_type_helper(...))[2];+ enum { value = (sizeof((has_result_type_helper)((T*)(0))) == 1) };+}; - template <typename T>- char has_result_type_helper(T*, typename T::result_type* = 0);+#if !defined(ASIO_NO_DYNAMIC_BUFFER_V1)+template <typename> class initiate_async_read_until_delim_v1;+template <typename> class initiate_async_read_until_delim_string_v1;+#if defined(ASIO_HAS_BOOST_REGEX)+template <typename> class initiate_async_read_until_expr_v1;+#endif // defined(ASIO_HAS_BOOST_REGEX)+template <typename> class initiate_async_read_until_match_v1;+#endif // !defined(ASIO_NO_DYNAMIC_BUFFER_V1)+template <typename> class initiate_async_read_until_delim_v2;+template <typename> class initiate_async_read_until_delim_string_v2;+#if defined(ASIO_HAS_BOOST_REGEX)+template <typename> class initiate_async_read_until_expr_v2;+#endif // defined(ASIO_HAS_BOOST_REGEX)+template <typename> class initiate_async_read_until_match_v2; - template <typename T>- struct has_result_type- {- enum { value = (sizeof((has_result_type_helper)((T*)(0))) == 1) };- }; } // namespace detail /// Type trait used to determine whether a type can be used as a match condition@@ -133,10 +148,12 @@ template <typename SyncReadStream, typename DynamicBuffer_v1> std::size_t read_until(SyncReadStream& s, ASIO_MOVE_ARG(DynamicBuffer_v1) buffers, char delim,- typename enable_if<+ typename constraint< is_dynamic_buffer_v1<typename decay<DynamicBuffer_v1>::type>::value- && !is_dynamic_buffer_v2<typename decay<DynamicBuffer_v1>::type>::value- >::type* = 0);+ >::type = 0,+ typename constraint<+ !is_dynamic_buffer_v2<typename decay<DynamicBuffer_v1>::type>::value+ >::type = 0); /// Read data into a dynamic buffer sequence until it contains a specified /// delimiter.@@ -176,10 +193,12 @@ std::size_t read_until(SyncReadStream& s, ASIO_MOVE_ARG(DynamicBuffer_v1) buffers, char delim, asio::error_code& ec,- typename enable_if<+ typename constraint< is_dynamic_buffer_v1<typename decay<DynamicBuffer_v1>::type>::value- && !is_dynamic_buffer_v2<typename decay<DynamicBuffer_v1>::type>::value- >::type* = 0);+ >::type = 0,+ typename constraint<+ !is_dynamic_buffer_v2<typename decay<DynamicBuffer_v1>::type>::value+ >::type = 0); /// Read data into a dynamic buffer sequence until it contains a specified /// delimiter.@@ -236,10 +255,12 @@ std::size_t read_until(SyncReadStream& s, ASIO_MOVE_ARG(DynamicBuffer_v1) buffers, ASIO_STRING_VIEW_PARAM delim,- typename enable_if<+ typename constraint< is_dynamic_buffer_v1<typename decay<DynamicBuffer_v1>::type>::value- && !is_dynamic_buffer_v2<typename decay<DynamicBuffer_v1>::type>::value- >::type* = 0);+ >::type = 0,+ typename constraint<+ !is_dynamic_buffer_v2<typename decay<DynamicBuffer_v1>::type>::value+ >::type = 0); /// Read data into a dynamic buffer sequence until it contains a specified /// delimiter.@@ -280,10 +301,12 @@ ASIO_MOVE_ARG(DynamicBuffer_v1) buffers, ASIO_STRING_VIEW_PARAM delim, asio::error_code& ec,- typename enable_if<+ typename constraint< is_dynamic_buffer_v1<typename decay<DynamicBuffer_v1>::type>::value- && !is_dynamic_buffer_v2<typename decay<DynamicBuffer_v1>::type>::value- >::type* = 0);+ >::type = 0,+ typename constraint<+ !is_dynamic_buffer_v2<typename decay<DynamicBuffer_v1>::type>::value+ >::type = 0); #if !defined(ASIO_NO_EXTENSIONS) #if defined(ASIO_HAS_BOOST_REGEX) \@@ -347,10 +370,12 @@ std::size_t read_until(SyncReadStream& s, ASIO_MOVE_ARG(DynamicBuffer_v1) buffers, const boost::regex& expr,- typename enable_if<+ typename constraint< is_dynamic_buffer_v1<typename decay<DynamicBuffer_v1>::type>::value- && !is_dynamic_buffer_v2<typename decay<DynamicBuffer_v1>::type>::value- >::type* = 0);+ >::type = 0,+ typename constraint<+ !is_dynamic_buffer_v2<typename decay<DynamicBuffer_v1>::type>::value+ >::type = 0); /// Read data into a dynamic buffer sequence until some part of the data it /// contains matches a regular expression.@@ -392,10 +417,12 @@ std::size_t read_until(SyncReadStream& s, ASIO_MOVE_ARG(DynamicBuffer_v1) buffers, const boost::regex& expr, asio::error_code& ec,- typename enable_if<+ typename constraint< is_dynamic_buffer_v1<typename decay<DynamicBuffer_v1>::type>::value- && !is_dynamic_buffer_v2<typename decay<DynamicBuffer_v1>::type>::value- >::type* = 0);+ >::type = 0,+ typename constraint<+ !is_dynamic_buffer_v2<typename decay<DynamicBuffer_v1>::type>::value+ >::type = 0); #endif // defined(ASIO_HAS_BOOST_REGEX) // || defined(GENERATING_DOCUMENTATION)@@ -507,11 +534,15 @@ std::size_t read_until(SyncReadStream& s, ASIO_MOVE_ARG(DynamicBuffer_v1) buffers, MatchCondition match_condition,- typename enable_if<+ typename constraint< is_match_condition<MatchCondition>::value- && is_dynamic_buffer_v1<typename decay<DynamicBuffer_v1>::type>::value- && !is_dynamic_buffer_v2<typename decay<DynamicBuffer_v1>::type>::value- >::type* = 0);+ >::type = 0,+ typename constraint<+ is_dynamic_buffer_v1<typename decay<DynamicBuffer_v1>::type>::value+ >::type = 0,+ typename constraint<+ !is_dynamic_buffer_v2<typename decay<DynamicBuffer_v1>::type>::value+ >::type = 0); /// Read data into a dynamic buffer sequence until a function object indicates a /// match.@@ -571,11 +602,15 @@ std::size_t read_until(SyncReadStream& s, ASIO_MOVE_ARG(DynamicBuffer_v1) buffers, MatchCondition match_condition, asio::error_code& ec,- typename enable_if<+ typename constraint< is_match_condition<MatchCondition>::value- && is_dynamic_buffer_v1<typename decay<DynamicBuffer_v1>::type>::value- && !is_dynamic_buffer_v2<typename decay<DynamicBuffer_v1>::type>::value- >::type* = 0);+ >::type = 0,+ typename constraint<+ is_dynamic_buffer_v1<typename decay<DynamicBuffer_v1>::type>::value+ >::type = 0,+ typename constraint<+ !is_dynamic_buffer_v2<typename decay<DynamicBuffer_v1>::type>::value+ >::type = 0); #if !defined(ASIO_NO_IOSTREAM) @@ -955,7 +990,7 @@ template <typename SyncReadStream, typename Allocator, typename MatchCondition> std::size_t read_until(SyncReadStream& s, asio::basic_streambuf<Allocator>& b, MatchCondition match_condition,- typename enable_if<is_match_condition<MatchCondition>::value>::type* = 0);+ typename constraint<is_match_condition<MatchCondition>::value>::type = 0); /// Read data into a streambuf until a function object indicates a match. /**@@ -1012,7 +1047,7 @@ std::size_t read_until(SyncReadStream& s, asio::basic_streambuf<Allocator>& b, MatchCondition match_condition, asio::error_code& ec,- typename enable_if<is_match_condition<MatchCondition>::value>::type* = 0);+ typename constraint<is_match_condition<MatchCondition>::value>::type = 0); #endif // !defined(ASIO_NO_IOSTREAM) #endif // !defined(ASIO_NO_EXTENSIONS)@@ -1073,9 +1108,9 @@ */ template <typename SyncReadStream, typename DynamicBuffer_v2> std::size_t read_until(SyncReadStream& s, DynamicBuffer_v2 buffers, char delim,- typename enable_if<+ typename constraint< is_dynamic_buffer_v2<DynamicBuffer_v2>::value- >::type* = 0);+ >::type = 0); /// Read data into a dynamic buffer sequence until it contains a specified /// delimiter.@@ -1114,9 +1149,9 @@ template <typename SyncReadStream, typename DynamicBuffer_v2> std::size_t read_until(SyncReadStream& s, DynamicBuffer_v2 buffers, char delim, asio::error_code& ec,- typename enable_if<+ typename constraint< is_dynamic_buffer_v2<DynamicBuffer_v2>::value- >::type* = 0);+ >::type = 0); /// Read data into a dynamic buffer sequence until it contains a specified /// delimiter.@@ -1172,9 +1207,9 @@ template <typename SyncReadStream, typename DynamicBuffer_v2> std::size_t read_until(SyncReadStream& s, DynamicBuffer_v2 buffers, ASIO_STRING_VIEW_PARAM delim,- typename enable_if<+ typename constraint< is_dynamic_buffer_v2<DynamicBuffer_v2>::value- >::type* = 0);+ >::type = 0); /// Read data into a dynamic buffer sequence until it contains a specified /// delimiter.@@ -1213,9 +1248,9 @@ template <typename SyncReadStream, typename DynamicBuffer_v2> std::size_t read_until(SyncReadStream& s, DynamicBuffer_v2 buffers, ASIO_STRING_VIEW_PARAM delim, asio::error_code& ec,- typename enable_if<+ typename constraint< is_dynamic_buffer_v2<DynamicBuffer_v2>::value- >::type* = 0);+ >::type = 0); #if !defined(ASIO_NO_EXTENSIONS) #if defined(ASIO_HAS_BOOST_REGEX) \@@ -1278,9 +1313,9 @@ template <typename SyncReadStream, typename DynamicBuffer_v2> std::size_t read_until(SyncReadStream& s, DynamicBuffer_v2 buffers, const boost::regex& expr,- typename enable_if<+ typename constraint< is_dynamic_buffer_v2<DynamicBuffer_v2>::value- >::type* = 0);+ >::type = 0); /// Read data into a dynamic buffer sequence until some part of the data it /// contains matches a regular expression.@@ -1321,9 +1356,9 @@ template <typename SyncReadStream, typename DynamicBuffer_v2> std::size_t read_until(SyncReadStream& s, DynamicBuffer_v2 buffers, const boost::regex& expr, asio::error_code& ec,- typename enable_if<+ typename constraint< is_dynamic_buffer_v2<DynamicBuffer_v2>::value- >::type* = 0);+ >::type = 0); #endif // defined(ASIO_HAS_BOOST_REGEX) // || defined(GENERATING_DOCUMENTATION)@@ -1434,10 +1469,12 @@ typename DynamicBuffer_v2, typename MatchCondition> std::size_t read_until(SyncReadStream& s, DynamicBuffer_v2 buffers, MatchCondition match_condition,- typename enable_if<+ typename constraint< is_match_condition<MatchCondition>::value- && is_dynamic_buffer_v2<DynamicBuffer_v2>::value- >::type* = 0);+ >::type = 0,+ typename constraint<+ is_dynamic_buffer_v2<DynamicBuffer_v2>::value+ >::type = 0); /// Read data into a dynamic buffer sequence until a function object indicates a /// match.@@ -1496,10 +1533,12 @@ typename DynamicBuffer_v2, typename MatchCondition> std::size_t read_until(SyncReadStream& s, DynamicBuffer_v2 buffers, MatchCondition match_condition, asio::error_code& ec,- typename enable_if<+ typename constraint< is_match_condition<MatchCondition>::value- && is_dynamic_buffer_v2<DynamicBuffer_v2>::value- >::type* = 0);+ >::type = 0,+ typename constraint<+ is_dynamic_buffer_v2<DynamicBuffer_v2>::value+ >::type = 0); #endif // !defined(ASIO_NO_EXTENSIONS) @@ -1521,9 +1560,9 @@ /** * This function is used to asynchronously read data into the specified dynamic * buffer sequence until the dynamic buffer sequence's get area contains the- * specified delimiter. The function call always returns immediately. The- * asynchronous operation will continue until one of the following conditions- * is true:+ * specified delimiter. It is an initiating function for an @ref+ * asynchronous_operation, and always returns immediately. The asynchronous+ * operation will continue until one of the following conditions is true: * * @li The get area of the dynamic buffer sequence contains the specified * delimiter.@@ -1544,27 +1583,31 @@ * @param buffers The dynamic buffer sequence into which the data will be read. * Although the buffers object may be copied as necessary, ownership of the * underlying memory blocks is retained by the caller, which must guarantee- * that they remain valid until the handler is called.+ * that they remain valid until the completion handler is called. * * @param delim The delimiter character. *- * @param handler The handler to be called when the read operation completes.- * Copies will be made of the handler as required. The function signature of the- * handler must be:+ * @param token The @ref completion_token that will be used to produce a+ * completion handler, which will be called when the read completes.+ * Potential completion tokens include @ref use_future, @ref use_awaitable,+ * @ref yield_context, or a function object with the correct completion+ * signature. The function signature of the completion handler must be: * @code void handler( * // Result of operation. * const asio::error_code& error, * * // The number of bytes in the dynamic buffer sequence's * // get area up to and including the delimiter.- * // 0 if an error occurred. * std::size_t bytes_transferred * ); @endcode * Regardless of whether the asynchronous operation completes immediately or- * not, the handler will not be invoked from within this function. On- * immediate completion, invocation of the handler will be performed in a+ * not, the completion handler will not be invoked from within this function.+ * On immediate completion, invocation of the handler will be performed in a * manner equivalent to using asio::post(). *+ * @par Completion Signature+ * @code void(asio::error_code, std::size_t) @endcode+ * * @note After a successful async_read_until operation, the dynamic buffer * sequence may contain additional data beyond the delimiter. An application * will typically leave that data in the dynamic buffer sequence for a@@ -1597,32 +1640,50 @@ * @code { 'd', 'e', ... } @endcode * This data may be the start of a new line, to be extracted by a subsequent * @c async_read_until operation.+ *+ * @par Per-Operation Cancellation+ * This asynchronous operation supports cancellation for the following+ * asio::cancellation_type values:+ *+ * @li @c cancellation_type::terminal+ *+ * @li @c cancellation_type::partial+ *+ * if they are also supported by the @c AsyncReadStream type's+ * @c async_read_some operation. */ template <typename AsyncReadStream, typename DynamicBuffer_v1, ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code,- std::size_t)) ReadHandler+ std::size_t)) ReadToken ASIO_DEFAULT_COMPLETION_TOKEN_TYPE( typename AsyncReadStream::executor_type)>-ASIO_INITFN_AUTO_RESULT_TYPE(ReadHandler,+ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX(ReadToken, void (asio::error_code, std::size_t)) async_read_until(AsyncReadStream& s, ASIO_MOVE_ARG(DynamicBuffer_v1) buffers, char delim,- ASIO_MOVE_ARG(ReadHandler) handler+ ASIO_MOVE_ARG(ReadToken) token ASIO_DEFAULT_COMPLETION_TOKEN( typename AsyncReadStream::executor_type),- typename enable_if<+ typename constraint< is_dynamic_buffer_v1<typename decay<DynamicBuffer_v1>::type>::value- && !is_dynamic_buffer_v2<typename decay<DynamicBuffer_v1>::type>::value- >::type* = 0);+ >::type = 0,+ typename constraint<+ !is_dynamic_buffer_v2<typename decay<DynamicBuffer_v1>::type>::value+ >::type = 0)+ ASIO_INITFN_AUTO_RESULT_TYPE_SUFFIX((+ async_initiate<ReadToken,+ void (asio::error_code, std::size_t)>(+ declval<detail::initiate_async_read_until_delim_v1<AsyncReadStream> >(),+ token, ASIO_MOVE_CAST(DynamicBuffer_v1)(buffers), delim))); /// Start an asynchronous operation to read data into a dynamic buffer sequence /// until it contains a specified delimiter. /** * This function is used to asynchronously read data into the specified dynamic * buffer sequence until the dynamic buffer sequence's get area contains the- * specified delimiter. The function call always returns immediately. The- * asynchronous operation will continue until one of the following conditions- * is true:+ * specified delimiter. It is an initiating function for an @ref+ * asynchronous_operation, and always returns immediately. The asynchronous+ * operation will continue until one of the following conditions is true: * * @li The get area of the dynamic buffer sequence contains the specified * delimiter.@@ -1643,27 +1704,31 @@ * @param buffers The dynamic buffer sequence into which the data will be read. * Although the buffers object may be copied as necessary, ownership of the * underlying memory blocks is retained by the caller, which must guarantee- * that they remain valid until the handler is called.+ * that they remain valid until the completion handler is called. * * @param delim The delimiter string. *- * @param handler The handler to be called when the read operation completes.- * Copies will be made of the handler as required. The function signature of the- * handler must be:+ * @param token The @ref completion_token that will be used to produce a+ * completion handler, which will be called when the read completes.+ * Potential completion tokens include @ref use_future, @ref use_awaitable,+ * @ref yield_context, or a function object with the correct completion+ * signature. The function signature of the completion handler must be: * @code void handler( * // Result of operation. * const asio::error_code& error, * * // The number of bytes in the dynamic buffer sequence's * // get area up to and including the delimiter.- * // 0 if an error occurred. * std::size_t bytes_transferred * ); @endcode * Regardless of whether the asynchronous operation completes immediately or- * not, the handler will not be invoked from within this function. On- * immediate completion, invocation of the handler will be performed in a+ * not, the completion handler will not be invoked from within this function.+ * On immediate completion, invocation of the handler will be performed in a * manner equivalent to using asio::post(). *+ * @par Completion Signature+ * @code void(asio::error_code, std::size_t) @endcode+ * * @note After a successful async_read_until operation, the dynamic buffer * sequence may contain additional data beyond the delimiter. An application * will typically leave that data in the dynamic buffer sequence for a@@ -1696,24 +1761,44 @@ * @code { 'd', 'e', ... } @endcode * This data may be the start of a new line, to be extracted by a subsequent * @c async_read_until operation.+ *+ * @par Per-Operation Cancellation+ * This asynchronous operation supports cancellation for the following+ * asio::cancellation_type values:+ *+ * @li @c cancellation_type::terminal+ *+ * @li @c cancellation_type::partial+ *+ * if they are also supported by the @c AsyncReadStream type's+ * @c async_read_some operation. */ template <typename AsyncReadStream, typename DynamicBuffer_v1, ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code,- std::size_t)) ReadHandler+ std::size_t)) ReadToken ASIO_DEFAULT_COMPLETION_TOKEN_TYPE( typename AsyncReadStream::executor_type)>-ASIO_INITFN_AUTO_RESULT_TYPE(ReadHandler,+ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX(ReadToken, void (asio::error_code, std::size_t)) async_read_until(AsyncReadStream& s, ASIO_MOVE_ARG(DynamicBuffer_v1) buffers, ASIO_STRING_VIEW_PARAM delim,- ASIO_MOVE_ARG(ReadHandler) handler+ ASIO_MOVE_ARG(ReadToken) token ASIO_DEFAULT_COMPLETION_TOKEN( typename AsyncReadStream::executor_type),- typename enable_if<+ typename constraint< is_dynamic_buffer_v1<typename decay<DynamicBuffer_v1>::type>::value- && !is_dynamic_buffer_v2<typename decay<DynamicBuffer_v1>::type>::value- >::type* = 0);+ >::type = 0,+ typename constraint<+ !is_dynamic_buffer_v2<typename decay<DynamicBuffer_v1>::type>::value+ >::type = 0)+ ASIO_INITFN_AUTO_RESULT_TYPE_SUFFIX((+ async_initiate<ReadToken,+ void (asio::error_code, std::size_t)>(+ declval<detail::initiate_async_read_until_delim_string_v1<+ AsyncReadStream> >(),+ token, ASIO_MOVE_CAST(DynamicBuffer_v1)(buffers),+ static_cast<std::string>(delim)))); #if !defined(ASIO_NO_EXTENSIONS) #if defined(ASIO_HAS_BOOST_REGEX) \@@ -1724,9 +1809,10 @@ /** * This function is used to asynchronously read data into the specified dynamic * buffer sequence until the dynamic buffer sequence's get area contains some- * data that matches a regular expression. The function call always returns- * immediately. The asynchronous operation will continue until one of the- * following conditions is true:+ * data that matches a regular expression. It is an initiating function for an+ * @ref asynchronous_operation, and always returns immediately. The+ * asynchronous operation will continue until one of the following conditions+ * is true: * * @li A substring of the dynamic buffer sequence's get area matches the regular * expression.@@ -1748,13 +1834,15 @@ * @param buffers The dynamic buffer sequence into which the data will be read. * Although the buffers object may be copied as necessary, ownership of the * underlying memory blocks is retained by the caller, which must guarantee- * that they remain valid until the handler is called.+ * that they remain valid until the completion handler is called. * * @param expr The regular expression. *- * @param handler The handler to be called when the read operation completes.- * Copies will be made of the handler as required. The function signature of the- * handler must be:+ * @param token The @ref completion_token that will be used to produce a+ * completion handler, which will be called when the read completes.+ * Potential completion tokens include @ref use_future, @ref use_awaitable,+ * @ref yield_context, or a function object with the correct completion+ * signature. The function signature of the completion handler must be: * @code void handler( * // Result of operation. * const asio::error_code& error,@@ -1766,10 +1854,13 @@ * std::size_t bytes_transferred * ); @endcode * Regardless of whether the asynchronous operation completes immediately or- * not, the handler will not be invoked from within this function. On- * immediate completion, invocation of the handler will be performed in a+ * not, the completion handler will not be invoked from within this function.+ * On immediate completion, invocation of the handler will be performed in a * manner equivalent to using asio::post(). *+ * @par Completion Signature+ * @code void(asio::error_code, std::size_t) @endcode+ * * @note After a successful async_read_until operation, the dynamic buffer * sequence may contain additional data beyond that which matched the regular * expression. An application will typically leave that data in the dynamic@@ -1803,24 +1894,42 @@ * @code { 'd', 'e', ... } @endcode * This data may be the start of a new line, to be extracted by a subsequent * @c async_read_until operation.+ *+ * @par Per-Operation Cancellation+ * This asynchronous operation supports cancellation for the following+ * asio::cancellation_type values:+ *+ * @li @c cancellation_type::terminal+ *+ * @li @c cancellation_type::partial+ *+ * if they are also supported by the @c AsyncReadStream type's+ * @c async_read_some operation. */ template <typename AsyncReadStream, typename DynamicBuffer_v1, ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code,- std::size_t)) ReadHandler+ std::size_t)) ReadToken ASIO_DEFAULT_COMPLETION_TOKEN_TYPE( typename AsyncReadStream::executor_type)>-ASIO_INITFN_AUTO_RESULT_TYPE(ReadHandler,+ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX(ReadToken, void (asio::error_code, std::size_t)) async_read_until(AsyncReadStream& s, ASIO_MOVE_ARG(DynamicBuffer_v1) buffers, const boost::regex& expr,- ASIO_MOVE_ARG(ReadHandler) handler+ ASIO_MOVE_ARG(ReadToken) token ASIO_DEFAULT_COMPLETION_TOKEN( typename AsyncReadStream::executor_type),- typename enable_if<+ typename constraint< is_dynamic_buffer_v1<typename decay<DynamicBuffer_v1>::type>::value- && !is_dynamic_buffer_v2<typename decay<DynamicBuffer_v1>::type>::value- >::type* = 0);+ >::type = 0,+ typename constraint<+ !is_dynamic_buffer_v2<typename decay<DynamicBuffer_v1>::type>::value+ >::type = 0)+ ASIO_INITFN_AUTO_RESULT_TYPE_SUFFIX((+ async_initiate<ReadToken,+ void (asio::error_code, std::size_t)>(+ declval<detail::initiate_async_read_until_expr_v1<AsyncReadStream> >(),+ token, ASIO_MOVE_CAST(DynamicBuffer_v1)(buffers), expr))); #endif // defined(ASIO_HAS_BOOST_REGEX) // || defined(GENERATING_DOCUMENTATION)@@ -1831,9 +1940,9 @@ * This function is used to asynchronously read data into the specified dynamic * buffer sequence until a user-defined match condition function object, when * applied to the data contained in the dynamic buffer sequence, indicates a- * successful match. The function call always returns immediately. The- * asynchronous operation will continue until one of the following conditions- * is true:+ * successful match. It is an initiating function for an @ref+ * asynchronous_operation, and always returns immediately. The asynchronous+ * operation will continue until one of the following conditions is true: * * @li The match condition function object returns a std::pair where the second * element evaluates to true.@@ -1854,7 +1963,7 @@ * @param buffers The dynamic buffer sequence into which the data will be read. * Although the buffers object may be copied as necessary, ownership of the * underlying memory blocks is retained by the caller, which must guarantee- * that they remain valid until the handler is called.+ * that they remain valid until the completion handler is called. * * @param match_condition The function object to be called to determine whether * a match exists. The signature of the function object must be:@@ -1871,9 +1980,11 @@ * @c second member of the return value is true if a match has been found, false * otherwise. *- * @param handler The handler to be called when the read operation completes.- * Copies will be made of the handler as required. The function signature of the- * handler must be:+ * @param token The @ref completion_token that will be used to produce a+ * completion handler, which will be called when the read completes.+ * Potential completion tokens include @ref use_future, @ref use_awaitable,+ * @ref yield_context, or a function object with the correct completion+ * signature. The function signature of the completion handler must be: * @code void handler( * // Result of operation. * const asio::error_code& error,@@ -1884,8 +1995,8 @@ * std::size_t bytes_transferred * ); @endcode * Regardless of whether the asynchronous operation completes immediately or- * not, the handler will not be invoked from within this function. On- * immediate completion, invocation of the handler will be performed in a+ * not, the completion handler will not be invoked from within this function.+ * On immediate completion, invocation of the handler will be performed in a * manner equivalent to using asio::post(). * * @note After a successful async_read_until operation, the dynamic buffer@@ -1893,6 +2004,9 @@ * object. An application will typically leave that data in the dynamic buffer * sequence for a subsequent async_read_until operation to examine. *+ * @par Completion Signature+ * @code void(asio::error_code, std::size_t) @endcode+ * * @note The default implementation of the @c is_match_condition type trait * evaluates to true for function pointers and function objects with a * @c result_type typedef. It must be specialised for other user-defined@@ -1952,26 +2066,47 @@ * std::string data; * asio::async_read_until(s, data, match_char('a'), handler); * @endcode+ *+ * @par Per-Operation Cancellation+ * This asynchronous operation supports cancellation for the following+ * asio::cancellation_type values:+ *+ * @li @c cancellation_type::terminal+ *+ * @li @c cancellation_type::partial+ *+ * if they are also supported by the @c AsyncReadStream type's+ * @c async_read_some operation. */ template <typename AsyncReadStream, typename DynamicBuffer_v1, typename MatchCondition, ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code,- std::size_t)) ReadHandler+ std::size_t)) ReadToken ASIO_DEFAULT_COMPLETION_TOKEN_TYPE( typename AsyncReadStream::executor_type)>-ASIO_INITFN_AUTO_RESULT_TYPE(ReadHandler,+ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX(ReadToken, void (asio::error_code, std::size_t)) async_read_until(AsyncReadStream& s, ASIO_MOVE_ARG(DynamicBuffer_v1) buffers, MatchCondition match_condition,- ASIO_MOVE_ARG(ReadHandler) handler+ ASIO_MOVE_ARG(ReadToken) token ASIO_DEFAULT_COMPLETION_TOKEN( typename AsyncReadStream::executor_type),- typename enable_if<+ typename constraint< is_match_condition<MatchCondition>::value- && is_dynamic_buffer_v1<typename decay<DynamicBuffer_v1>::type>::value- && !is_dynamic_buffer_v2<typename decay<DynamicBuffer_v1>::type>::value- >::type* = 0);+ >::type = 0,+ typename constraint<+ is_dynamic_buffer_v1<typename decay<DynamicBuffer_v1>::type>::value+ >::type = 0,+ typename constraint<+ !is_dynamic_buffer_v2<typename decay<DynamicBuffer_v1>::type>::value+ >::type = 0)+ ASIO_INITFN_AUTO_RESULT_TYPE_SUFFIX((+ async_initiate<ReadToken,+ void (asio::error_code, std::size_t)>(+ declval<detail::initiate_async_read_until_match_v1<AsyncReadStream> >(),+ token, ASIO_MOVE_CAST(DynamicBuffer_v1)(buffers),+ match_condition))); #if !defined(ASIO_NO_IOSTREAM) @@ -1980,8 +2115,9 @@ /** * This function is used to asynchronously read data into the specified * streambuf until the streambuf's get area contains the specified delimiter.- * The function call always returns immediately. The asynchronous operation- * will continue until one of the following conditions is true:+ * It is an initiating function for an @ref asynchronous_operation, and always+ * returns immediately. The asynchronous operation will continue until one of+ * the following conditions is true: * * @li The get area of the streambuf contains the specified delimiter. *@@ -2000,13 +2136,15 @@ * * @param b A streambuf object into which the data will be read. Ownership of * the streambuf is retained by the caller, which must guarantee that it remains- * valid until the handler is called.+ * valid until the completion handler is called. * * @param delim The delimiter character. *- * @param handler The handler to be called when the read operation completes.- * Copies will be made of the handler as required. The function signature of the- * handler must be:+ * @param token The @ref completion_token that will be used to produce a+ * completion handler, which will be called when the read completes.+ * Potential completion tokens include @ref use_future, @ref use_awaitable,+ * @ref yield_context, or a function object with the correct completion+ * signature. The function signature of the completion handler must be: * @code void handler( * // Result of operation. * const asio::error_code& error,@@ -2017,10 +2155,13 @@ * std::size_t bytes_transferred * ); @endcode * Regardless of whether the asynchronous operation completes immediately or- * not, the handler will not be invoked from within this function. On- * immediate completion, invocation of the handler will be performed in a+ * not, the completion handler will not be invoked from within this function.+ * On immediate completion, invocation of the handler will be performed in a * manner equivalent to using asio::post(). *+ * @par Completion Signature+ * @code void(asio::error_code, std::size_t) @endcode+ * * @note After a successful async_read_until operation, the streambuf may * contain additional data beyond the delimiter. An application will typically * leave that data in the streambuf for a subsequent async_read_until operation@@ -2052,27 +2193,42 @@ * @code { 'd', 'e', ... } @endcode * This data may be the start of a new line, to be extracted by a subsequent * @c async_read_until operation.+ *+ * @par Per-Operation Cancellation+ * This asynchronous operation supports cancellation for the following+ * asio::cancellation_type values:+ *+ * @li @c cancellation_type::terminal+ *+ * @li @c cancellation_type::partial+ *+ * if they are also supported by the @c AsyncReadStream type's+ * @c async_read_some operation. */ template <typename AsyncReadStream, typename Allocator, ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code,- std::size_t)) ReadHandler+ std::size_t)) ReadToken ASIO_DEFAULT_COMPLETION_TOKEN_TYPE( typename AsyncReadStream::executor_type)>-ASIO_INITFN_AUTO_RESULT_TYPE(ReadHandler,+ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX(ReadToken, void (asio::error_code, std::size_t)) async_read_until(AsyncReadStream& s, asio::basic_streambuf<Allocator>& b, char delim,- ASIO_MOVE_ARG(ReadHandler) handler+ ASIO_MOVE_ARG(ReadToken) token ASIO_DEFAULT_COMPLETION_TOKEN(- typename AsyncReadStream::executor_type));+ typename AsyncReadStream::executor_type))+ ASIO_INITFN_AUTO_RESULT_TYPE_SUFFIX((+ async_read_until(s, basic_streambuf_ref<Allocator>(b),+ delim, ASIO_MOVE_CAST(ReadToken)(token)))); /// Start an asynchronous operation to read data into a streambuf until it /// contains a specified delimiter. /** * This function is used to asynchronously read data into the specified * streambuf until the streambuf's get area contains the specified delimiter.- * The function call always returns immediately. The asynchronous operation- * will continue until one of the following conditions is true:+ * It is an initiating function for an @ref asynchronous_operation, and always+ * returns immediately. The asynchronous operation will continue until one of+ * the following conditions is true: * * @li The get area of the streambuf contains the specified delimiter. *@@ -2091,13 +2247,15 @@ * * @param b A streambuf object into which the data will be read. Ownership of * the streambuf is retained by the caller, which must guarantee that it remains- * valid until the handler is called.+ * valid until the completion handler is called. * * @param delim The delimiter string. *- * @param handler The handler to be called when the read operation completes.- * Copies will be made of the handler as required. The function signature of the- * handler must be:+ * @param token The @ref completion_token that will be used to produce a+ * completion handler, which will be called when the read completes.+ * Potential completion tokens include @ref use_future, @ref use_awaitable,+ * @ref yield_context, or a function object with the correct completion+ * signature. The function signature of the completion handler must be: * @code void handler( * // Result of operation. * const asio::error_code& error,@@ -2108,10 +2266,13 @@ * std::size_t bytes_transferred * ); @endcode * Regardless of whether the asynchronous operation completes immediately or- * not, the handler will not be invoked from within this function. On- * immediate completion, invocation of the handler will be performed in a+ * not, the completion handler will not be invoked from within this function.+ * On immediate completion, invocation of the handler will be performed in a * manner equivalent to using asio::post(). *+ * @par Completion Signature+ * @code void(asio::error_code, std::size_t) @endcode+ * * @note After a successful async_read_until operation, the streambuf may * contain additional data beyond the delimiter. An application will typically * leave that data in the streambuf for a subsequent async_read_until operation@@ -2143,20 +2304,34 @@ * @code { 'd', 'e', ... } @endcode * This data may be the start of a new line, to be extracted by a subsequent * @c async_read_until operation.+ *+ * @par Per-Operation Cancellation+ * This asynchronous operation supports cancellation for the following+ * asio::cancellation_type values:+ *+ * @li @c cancellation_type::terminal+ *+ * @li @c cancellation_type::partial+ *+ * if they are also supported by the @c AsyncReadStream type's+ * @c async_read_some operation. */ template <typename AsyncReadStream, typename Allocator, ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code,- std::size_t)) ReadHandler+ std::size_t)) ReadToken ASIO_DEFAULT_COMPLETION_TOKEN_TYPE( typename AsyncReadStream::executor_type)>-ASIO_INITFN_AUTO_RESULT_TYPE(ReadHandler,+ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX(ReadToken, void (asio::error_code, std::size_t)) async_read_until(AsyncReadStream& s, asio::basic_streambuf<Allocator>& b, ASIO_STRING_VIEW_PARAM delim,- ASIO_MOVE_ARG(ReadHandler) handler+ ASIO_MOVE_ARG(ReadToken) token ASIO_DEFAULT_COMPLETION_TOKEN(- typename AsyncReadStream::executor_type));+ typename AsyncReadStream::executor_type))+ ASIO_INITFN_AUTO_RESULT_TYPE_SUFFIX((+ async_read_until(s, basic_streambuf_ref<Allocator>(b),+ delim, ASIO_MOVE_CAST(ReadToken)(token)))); #if defined(ASIO_HAS_BOOST_REGEX) \ || defined(GENERATING_DOCUMENTATION)@@ -2166,9 +2341,9 @@ /** * This function is used to asynchronously read data into the specified * streambuf until the streambuf's get area contains some data that matches a- * regular expression. The function call always returns immediately. The- * asynchronous operation will continue until one of the following conditions- * is true:+ * regular expression. It is an initiating function for an @ref+ * asynchronous_operation, and always returns immediately. The asynchronous+ * operation will continue until one of the following conditions is true: * * @li A substring of the streambuf's get area matches the regular expression. *@@ -2188,13 +2363,15 @@ * * @param b A streambuf object into which the data will be read. Ownership of * the streambuf is retained by the caller, which must guarantee that it remains- * valid until the handler is called.+ * valid until the completion handler is called. * * @param expr The regular expression. *- * @param handler The handler to be called when the read operation completes.- * Copies will be made of the handler as required. The function signature of the- * handler must be:+ * @param token The @ref completion_token that will be used to produce a+ * completion handler, which will be called when the read completes.+ * Potential completion tokens include @ref use_future, @ref use_awaitable,+ * @ref yield_context, or a function object with the correct completion+ * signature. The function signature of the completion handler must be: * @code void handler( * // Result of operation. * const asio::error_code& error,@@ -2206,10 +2383,13 @@ * std::size_t bytes_transferred * ); @endcode * Regardless of whether the asynchronous operation completes immediately or- * not, the handler will not be invoked from within this function. On- * immediate completion, invocation of the handler will be performed in a+ * not, the completion handler will not be invoked from within this function.+ * On immediate completion, invocation of the handler will be performed in a * manner equivalent to using asio::post(). *+ * @par Completion Signature+ * @code void(asio::error_code, std::size_t) @endcode+ * * @note After a successful async_read_until operation, the streambuf may * contain additional data beyond that which matched the regular expression. An * application will typically leave that data in the streambuf for a subsequent@@ -2242,19 +2422,33 @@ * @code { 'd', 'e', ... } @endcode * This data may be the start of a new line, to be extracted by a subsequent * @c async_read_until operation.+ *+ * @par Per-Operation Cancellation+ * This asynchronous operation supports cancellation for the following+ * asio::cancellation_type values:+ *+ * @li @c cancellation_type::terminal+ *+ * @li @c cancellation_type::partial+ *+ * if they are also supported by the @c AsyncReadStream type's+ * @c async_read_some operation. */ template <typename AsyncReadStream, typename Allocator, ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code,- std::size_t)) ReadHandler+ std::size_t)) ReadToken ASIO_DEFAULT_COMPLETION_TOKEN_TYPE( typename AsyncReadStream::executor_type)>-ASIO_INITFN_AUTO_RESULT_TYPE(ReadHandler,+ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX(ReadToken, void (asio::error_code, std::size_t)) async_read_until(AsyncReadStream& s, asio::basic_streambuf<Allocator>& b, const boost::regex& expr,- ASIO_MOVE_ARG(ReadHandler) handler+ ASIO_MOVE_ARG(ReadToken) token ASIO_DEFAULT_COMPLETION_TOKEN(- typename AsyncReadStream::executor_type));+ typename AsyncReadStream::executor_type))+ ASIO_INITFN_AUTO_RESULT_TYPE_SUFFIX((+ async_read_until(s, basic_streambuf_ref<Allocator>(b),+ expr, ASIO_MOVE_CAST(ReadToken)(token)))); #endif // defined(ASIO_HAS_BOOST_REGEX) // || defined(GENERATING_DOCUMENTATION)@@ -2264,9 +2458,10 @@ /** * This function is used to asynchronously read data into the specified * streambuf until a user-defined match condition function object, when applied- * to the data contained in the streambuf, indicates a successful match. The- * function call always returns immediately. The asynchronous operation will- * continue until one of the following conditions is true:+ * to the data contained in the streambuf, indicates a successful match. It is+ * an initiating function for an @ref asynchronous_operation, and always+ * returns immediately. The asynchronous operation will continue until one of+ * the following conditions is true: * * @li The match condition function object returns a std::pair where the second * element evaluates to true.@@ -2301,9 +2496,11 @@ * @c second member of the return value is true if a match has been found, false * otherwise. *- * @param handler The handler to be called when the read operation completes.- * Copies will be made of the handler as required. The function signature of the- * handler must be:+ * @param token The @ref completion_token that will be used to produce a+ * completion handler, which will be called when the read completes.+ * Potential completion tokens include @ref use_future, @ref use_awaitable,+ * @ref yield_context, or a function object with the correct completion+ * signature. The function signature of the completion handler must be: * @code void handler( * // Result of operation. * const asio::error_code& error,@@ -2314,8 +2511,8 @@ * std::size_t bytes_transferred * ); @endcode * Regardless of whether the asynchronous operation completes immediately or- * not, the handler will not be invoked from within this function. On- * immediate completion, invocation of the handler will be performed in a+ * not, the completion handler will not be invoked from within this function.+ * On immediate completion, invocation of the handler will be performed in a * manner equivalent to using asio::post(). * * @note After a successful async_read_until operation, the streambuf may@@ -2323,6 +2520,9 @@ * application will typically leave that data in the streambuf for a subsequent * async_read_until operation to examine. *+ * @par Completion Signature+ * @code void(asio::error_code, std::size_t) @endcode+ * * @note The default implementation of the @c is_match_condition type trait * evaluates to true for function pointers and function objects with a * @c result_type typedef. It must be specialised for other user-defined@@ -2381,21 +2581,35 @@ * asio::streambuf b; * asio::async_read_until(s, b, match_char('a'), handler); * @endcode+ *+ * @par Per-Operation Cancellation+ * This asynchronous operation supports cancellation for the following+ * asio::cancellation_type values:+ *+ * @li @c cancellation_type::terminal+ *+ * @li @c cancellation_type::partial+ *+ * if they are also supported by the @c AsyncReadStream type's+ * @c async_read_some operation. */ template <typename AsyncReadStream, typename Allocator, typename MatchCondition, ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code,- std::size_t)) ReadHandler+ std::size_t)) ReadToken ASIO_DEFAULT_COMPLETION_TOKEN_TYPE( typename AsyncReadStream::executor_type)>-ASIO_INITFN_AUTO_RESULT_TYPE(ReadHandler,+ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX(ReadToken, void (asio::error_code, std::size_t)) async_read_until(AsyncReadStream& s, asio::basic_streambuf<Allocator>& b, MatchCondition match_condition,- ASIO_MOVE_ARG(ReadHandler) handler+ ASIO_MOVE_ARG(ReadToken) token ASIO_DEFAULT_COMPLETION_TOKEN( typename AsyncReadStream::executor_type),- typename enable_if<is_match_condition<MatchCondition>::value>::type* = 0);+ typename constraint<is_match_condition<MatchCondition>::value>::type = 0)+ ASIO_INITFN_AUTO_RESULT_TYPE_SUFFIX((+ async_read_until(s, basic_streambuf_ref<Allocator>(b),+ match_condition, ASIO_MOVE_CAST(ReadToken)(token)))); #endif // !defined(ASIO_NO_IOSTREAM) #endif // !defined(ASIO_NO_EXTENSIONS)@@ -2406,9 +2620,9 @@ /** * This function is used to asynchronously read data into the specified dynamic * buffer sequence until the dynamic buffer sequence's get area contains the- * specified delimiter. The function call always returns immediately. The- * asynchronous operation will continue until one of the following conditions- * is true:+ * specified delimiter. It is an initiating function for an @ref+ * asynchronous_operation, and always returns immediately. The asynchronous+ * operation will continue until one of the following conditions is true: * * @li The get area of the dynamic buffer sequence contains the specified * delimiter.@@ -2429,13 +2643,15 @@ * @param buffers The dynamic buffer sequence into which the data will be read. * Although the buffers object may be copied as necessary, ownership of the * underlying memory blocks is retained by the caller, which must guarantee- * that they remain valid until the handler is called.+ * that they remain valid until the completion handler is called. * * @param delim The delimiter character. *- * @param handler The handler to be called when the read operation completes.- * Copies will be made of the handler as required. The function signature of the- * handler must be:+ * @param token The @ref completion_token that will be used to produce a+ * completion handler, which will be called when the read completes.+ * Potential completion tokens include @ref use_future, @ref use_awaitable,+ * @ref yield_context, or a function object with the correct completion+ * signature. The function signature of the completion handler must be: * @code void handler( * // Result of operation. * const asio::error_code& error,@@ -2446,10 +2662,13 @@ * std::size_t bytes_transferred * ); @endcode * Regardless of whether the asynchronous operation completes immediately or- * not, the handler will not be invoked from within this function. On- * immediate completion, invocation of the handler will be performed in a+ * not, the completion handler will not be invoked from within this function.+ * On immediate completion, invocation of the handler will be performed in a * manner equivalent to using asio::post(). *+ * @par Completion Signature+ * @code void(asio::error_code, std::size_t) @endcode+ * * @note After a successful async_read_until operation, the dynamic buffer * sequence may contain additional data beyond the delimiter. An application * will typically leave that data in the dynamic buffer sequence for a@@ -2482,30 +2701,46 @@ * @code { 'd', 'e', ... } @endcode * This data may be the start of a new line, to be extracted by a subsequent * @c async_read_until operation.+ *+ * @par Per-Operation Cancellation+ * This asynchronous operation supports cancellation for the following+ * asio::cancellation_type values:+ *+ * @li @c cancellation_type::terminal+ *+ * @li @c cancellation_type::partial+ *+ * if they are also supported by the @c AsyncReadStream type's+ * @c async_read_some operation. */ template <typename AsyncReadStream, typename DynamicBuffer_v2, ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code,- std::size_t)) ReadHandler+ std::size_t)) ReadToken ASIO_DEFAULT_COMPLETION_TOKEN_TYPE( typename AsyncReadStream::executor_type)>-ASIO_INITFN_AUTO_RESULT_TYPE(ReadHandler,+ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX(ReadToken, void (asio::error_code, std::size_t)) async_read_until(AsyncReadStream& s, DynamicBuffer_v2 buffers, char delim,- ASIO_MOVE_ARG(ReadHandler) handler+ ASIO_MOVE_ARG(ReadToken) token ASIO_DEFAULT_COMPLETION_TOKEN( typename AsyncReadStream::executor_type),- typename enable_if<+ typename constraint< is_dynamic_buffer_v2<DynamicBuffer_v2>::value- >::type* = 0);+ >::type = 0)+ ASIO_INITFN_AUTO_RESULT_TYPE_SUFFIX((+ async_initiate<ReadToken,+ void (asio::error_code, std::size_t)>(+ declval<detail::initiate_async_read_until_delim_v2<AsyncReadStream> >(),+ token, ASIO_MOVE_CAST(DynamicBuffer_v2)(buffers), delim))); /// Start an asynchronous operation to read data into a dynamic buffer sequence /// until it contains a specified delimiter. /** * This function is used to asynchronously read data into the specified dynamic * buffer sequence until the dynamic buffer sequence's get area contains the- * specified delimiter. The function call always returns immediately. The- * asynchronous operation will continue until one of the following conditions- * is true:+ * specified delimiter. It is an initiating function for an @ref+ * asynchronous_operation, and always returns immediately. The asynchronous+ * operation will continue until one of the following conditions is true: * * @li The get area of the dynamic buffer sequence contains the specified * delimiter.@@ -2526,27 +2761,31 @@ * @param buffers The dynamic buffer sequence into which the data will be read. * Although the buffers object may be copied as necessary, ownership of the * underlying memory blocks is retained by the caller, which must guarantee- * that they remain valid until the handler is called.+ * that they remain valid until the completion handler is called. * * @param delim The delimiter string. *- * @param handler The handler to be called when the read operation completes.- * Copies will be made of the handler as required. The function signature of the- * handler must be:+ * @param token The @ref completion_token that will be used to produce a+ * completion handler, which will be called when the read completes.+ * Potential completion tokens include @ref use_future, @ref use_awaitable,+ * @ref yield_context, or a function object with the correct completion+ * signature. The function signature of the completion handler must be: * @code void handler( * // Result of operation. * const asio::error_code& error, * * // The number of bytes in the dynamic buffer sequence's * // get area up to and including the delimiter.- * // 0 if an error occurred. * std::size_t bytes_transferred * ); @endcode * Regardless of whether the asynchronous operation completes immediately or- * not, the handler will not be invoked from within this function. On- * immediate completion, invocation of the handler will be performed in a+ * not, the completion handler will not be invoked from within this function.+ * On immediate completion, invocation of the handler will be performed in a * manner equivalent to using asio::post(). *+ * @par Completion Signature+ * @code void(asio::error_code, std::size_t) @endcode+ * * @note After a successful async_read_until operation, the dynamic buffer * sequence may contain additional data beyond the delimiter. An application * will typically leave that data in the dynamic buffer sequence for a@@ -2579,22 +2818,40 @@ * @code { 'd', 'e', ... } @endcode * This data may be the start of a new line, to be extracted by a subsequent * @c async_read_until operation.+ *+ * @par Per-Operation Cancellation+ * This asynchronous operation supports cancellation for the following+ * asio::cancellation_type values:+ *+ * @li @c cancellation_type::terminal+ *+ * @li @c cancellation_type::partial+ *+ * if they are also supported by the @c AsyncReadStream type's+ * @c async_read_some operation. */ template <typename AsyncReadStream, typename DynamicBuffer_v2, ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code,- std::size_t)) ReadHandler+ std::size_t)) ReadToken ASIO_DEFAULT_COMPLETION_TOKEN_TYPE( typename AsyncReadStream::executor_type)>-ASIO_INITFN_AUTO_RESULT_TYPE(ReadHandler,+ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX(ReadToken, void (asio::error_code, std::size_t)) async_read_until(AsyncReadStream& s, DynamicBuffer_v2 buffers, ASIO_STRING_VIEW_PARAM delim,- ASIO_MOVE_ARG(ReadHandler) handler+ ASIO_MOVE_ARG(ReadToken) token ASIO_DEFAULT_COMPLETION_TOKEN( typename AsyncReadStream::executor_type),- typename enable_if<+ typename constraint< is_dynamic_buffer_v2<DynamicBuffer_v2>::value- >::type* = 0);+ >::type = 0)+ ASIO_INITFN_AUTO_RESULT_TYPE_SUFFIX((+ async_initiate<ReadToken,+ void (asio::error_code, std::size_t)>(+ declval<detail::initiate_async_read_until_delim_string_v2<+ AsyncReadStream> >(),+ token, ASIO_MOVE_CAST(DynamicBuffer_v2)(buffers),+ static_cast<std::string>(delim)))); #if !defined(ASIO_NO_EXTENSIONS) #if defined(ASIO_HAS_BOOST_REGEX) \@@ -2605,9 +2862,10 @@ /** * This function is used to asynchronously read data into the specified dynamic * buffer sequence until the dynamic buffer sequence's get area contains some- * data that matches a regular expression. The function call always returns- * immediately. The asynchronous operation will continue until one of the- * following conditions is true:+ * data that matches a regular expression. It is an initiating function for an+ * @ref asynchronous_operation, and always returns immediately. The+ * asynchronous operation will continue until one of the following conditions+ * is true: * * @li A substring of the dynamic buffer sequence's get area matches the regular * expression.@@ -2629,13 +2887,15 @@ * @param buffers The dynamic buffer sequence into which the data will be read. * Although the buffers object may be copied as necessary, ownership of the * underlying memory blocks is retained by the caller, which must guarantee- * that they remain valid until the handler is called.+ * that they remain valid until the completion handler is called. * * @param expr The regular expression. *- * @param handler The handler to be called when the read operation completes.- * Copies will be made of the handler as required. The function signature of the- * handler must be:+ * @param token The @ref completion_token that will be used to produce a+ * completion handler, which will be called when the read completes.+ * Potential completion tokens include @ref use_future, @ref use_awaitable,+ * @ref yield_context, or a function object with the correct completion+ * signature. The function signature of the completion handler must be: * @code void handler( * // Result of operation. * const asio::error_code& error,@@ -2647,10 +2907,13 @@ * std::size_t bytes_transferred * ); @endcode * Regardless of whether the asynchronous operation completes immediately or- * not, the handler will not be invoked from within this function. On- * immediate completion, invocation of the handler will be performed in a+ * not, the completion handler will not be invoked from within this function.+ * On immediate completion, invocation of the handler will be performed in a * manner equivalent to using asio::post(). *+ * @par Completion Signature+ * @code void(asio::error_code, std::size_t) @endcode+ * * @note After a successful async_read_until operation, the dynamic buffer * sequence may contain additional data beyond that which matched the regular * expression. An application will typically leave that data in the dynamic@@ -2684,22 +2947,38 @@ * @code { 'd', 'e', ... } @endcode * This data may be the start of a new line, to be extracted by a subsequent * @c async_read_until operation.+ *+ * @par Per-Operation Cancellation+ * This asynchronous operation supports cancellation for the following+ * asio::cancellation_type values:+ *+ * @li @c cancellation_type::terminal+ *+ * @li @c cancellation_type::partial+ *+ * if they are also supported by the @c AsyncReadStream type's+ * @c async_read_some operation. */ template <typename AsyncReadStream, typename DynamicBuffer_v2, ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code,- std::size_t)) ReadHandler+ std::size_t)) ReadToken ASIO_DEFAULT_COMPLETION_TOKEN_TYPE( typename AsyncReadStream::executor_type)>-ASIO_INITFN_AUTO_RESULT_TYPE(ReadHandler,+ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX(ReadToken, void (asio::error_code, std::size_t)) async_read_until(AsyncReadStream& s, DynamicBuffer_v2 buffers, const boost::regex& expr,- ASIO_MOVE_ARG(ReadHandler) handler+ ASIO_MOVE_ARG(ReadToken) token ASIO_DEFAULT_COMPLETION_TOKEN( typename AsyncReadStream::executor_type),- typename enable_if<+ typename constraint< is_dynamic_buffer_v2<DynamicBuffer_v2>::value- >::type* = 0);+ >::type = 0)+ ASIO_INITFN_AUTO_RESULT_TYPE_SUFFIX((+ async_initiate<ReadToken,+ void (asio::error_code, std::size_t)>(+ declval<detail::initiate_async_read_until_expr_v2<AsyncReadStream> >(),+ token, ASIO_MOVE_CAST(DynamicBuffer_v2)(buffers), expr))); #endif // defined(ASIO_HAS_BOOST_REGEX) // || defined(GENERATING_DOCUMENTATION)@@ -2710,9 +2989,9 @@ * This function is used to asynchronously read data into the specified dynamic * buffer sequence until a user-defined match condition function object, when * applied to the data contained in the dynamic buffer sequence, indicates a- * successful match. The function call always returns immediately. The- * asynchronous operation will continue until one of the following conditions- * is true:+ * successful match. It is an initiating function for an @ref+ * asynchronous_operation, and always returns immediately. The asynchronous+ * operation will continue until one of the following conditions is true: * * @li The match condition function object returns a std::pair where the second * element evaluates to true.@@ -2733,7 +3012,7 @@ * @param buffers The dynamic buffer sequence into which the data will be read. * Although the buffers object may be copied as necessary, ownership of the * underlying memory blocks is retained by the caller, which must guarantee- * that they remain valid until the handler is called.+ * that they remain valid until the completion handler is called. * * @param match_condition The function object to be called to determine whether * a match exists. The signature of the function object must be:@@ -2750,9 +3029,11 @@ * @c second member of the return value is true if a match has been found, false * otherwise. *- * @param handler The handler to be called when the read operation completes.- * Copies will be made of the handler as required. The function signature of the- * handler must be:+ * @param token The @ref completion_token that will be used to produce a+ * completion handler, which will be called when the read completes.+ * Potential completion tokens include @ref use_future, @ref use_awaitable,+ * @ref yield_context, or a function object with the correct completion+ * signature. The function signature of the completion handler must be: * @code void handler( * // Result of operation. * const asio::error_code& error,@@ -2763,8 +3044,8 @@ * std::size_t bytes_transferred * ); @endcode * Regardless of whether the asynchronous operation completes immediately or- * not, the handler will not be invoked from within this function. On- * immediate completion, invocation of the handler will be performed in a+ * not, the completion handler will not be invoked from within this function.+ * On immediate completion, invocation of the handler will be performed in a * manner equivalent to using asio::post(). * * @note After a successful async_read_until operation, the dynamic buffer@@ -2772,6 +3053,9 @@ * object. An application will typically leave that data in the dynamic buffer * sequence for a subsequent async_read_until operation to examine. *+ * @par Completion Signature+ * @code void(asio::error_code, std::size_t) @endcode+ * * @note The default implementation of the @c is_match_condition type trait * evaluates to true for function pointers and function objects with a * @c result_type typedef. It must be specialised for other user-defined@@ -2831,24 +3115,43 @@ * std::string data; * asio::async_read_until(s, data, match_char('a'), handler); * @endcode+ *+ * @par Per-Operation Cancellation+ * This asynchronous operation supports cancellation for the following+ * asio::cancellation_type values:+ *+ * @li @c cancellation_type::terminal+ *+ * @li @c cancellation_type::partial+ *+ * if they are also supported by the @c AsyncReadStream type's+ * @c async_read_some operation. */ template <typename AsyncReadStream, typename DynamicBuffer_v2, typename MatchCondition, ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code,- std::size_t)) ReadHandler+ std::size_t)) ReadToken ASIO_DEFAULT_COMPLETION_TOKEN_TYPE( typename AsyncReadStream::executor_type)>-ASIO_INITFN_AUTO_RESULT_TYPE(ReadHandler,+ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX(ReadToken, void (asio::error_code, std::size_t)) async_read_until(AsyncReadStream& s, DynamicBuffer_v2 buffers, MatchCondition match_condition,- ASIO_MOVE_ARG(ReadHandler) handler+ ASIO_MOVE_ARG(ReadToken) token ASIO_DEFAULT_COMPLETION_TOKEN( typename AsyncReadStream::executor_type),- typename enable_if<+ typename constraint< is_match_condition<MatchCondition>::value- && is_dynamic_buffer_v2<DynamicBuffer_v2>::value- >::type* = 0);+ >::type = 0,+ typename constraint<+ is_dynamic_buffer_v2<DynamicBuffer_v2>::value+ >::type = 0)+ ASIO_INITFN_AUTO_RESULT_TYPE_SUFFIX((+ async_initiate<ReadToken,+ void (asio::error_code, std::size_t)>(+ declval<detail::initiate_async_read_until_match_v2<AsyncReadStream> >(),+ token, ASIO_MOVE_CAST(DynamicBuffer_v2)(buffers),+ match_condition))); #endif // !defined(ASIO_NO_EXTENSIONS)
+ link/modules/asio-standalone/asio/include/asio/readable_pipe.hpp view
@@ -0,0 +1,35 @@+//+// readable_pipe.hpp+// ~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com)+//+// Distributed under the Boost Software License, Version 1.0. (See accompanying+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)+//++#ifndef ASIO_READABLE_PIPE_HPP+#define ASIO_READABLE_PIPE_HPP++#if defined(_MSC_VER) && (_MSC_VER >= 1200)+# pragma once+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)++#include "asio/detail/config.hpp"++#if defined(ASIO_HAS_PIPE) \+ || defined(GENERATING_DOCUMENTATION)++#include "asio/basic_readable_pipe.hpp"++namespace asio {++/// Typedef for the typical usage of a readable pipe.+typedef basic_readable_pipe<> readable_pipe;++} // namespace asio++#endif // defined(ASIO_HAS_PIPE)+ // || defined(GENERATING_DOCUMENTATION)++#endif // ASIO_READABLE_PIPE_HPP
+ link/modules/asio-standalone/asio/include/asio/recycling_allocator.hpp view
@@ -0,0 +1,138 @@+//+// recycling_allocator.hpp+// ~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com)+//+// Distributed under the Boost Software License, Version 1.0. (See accompanying+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)+//++#ifndef ASIO_RECYCLING_ALLOCATOR_HPP+#define ASIO_RECYCLING_ALLOCATOR_HPP++#if defined(_MSC_VER) && (_MSC_VER >= 1200)+# pragma once+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)++#include "asio/detail/config.hpp"+#include "asio/detail/recycling_allocator.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {++/// An allocator that caches memory blocks in thread-local storage for reuse.+/**+ * The @recycling_allocator uses a simple strategy where a limited number of+ * small memory blocks are cached in thread-local storage, if the current+ * thread is running an @c io_context or is part of a @c thread_pool.+ */+template <typename T>+class recycling_allocator+{+public:+ /// The type of object allocated by the recycling allocator.+ typedef T value_type;++ /// Rebind the allocator to another value_type.+ template <typename U>+ struct rebind+ {+ /// The rebound @c allocator type.+ typedef recycling_allocator<U> other;+ };++ /// Default constructor.+ ASIO_CONSTEXPR recycling_allocator() ASIO_NOEXCEPT+ {+ }++ /// Converting constructor.+ template <typename U>+ ASIO_CONSTEXPR recycling_allocator(+ const recycling_allocator<U>&) ASIO_NOEXCEPT+ {+ }++ /// Equality operator. Always returns true.+ ASIO_CONSTEXPR bool operator==(+ const recycling_allocator&) const ASIO_NOEXCEPT+ {+ return true;+ }++ /// Inequality operator. Always returns false.+ ASIO_CONSTEXPR bool operator!=(+ const recycling_allocator&) const ASIO_NOEXCEPT+ {+ return false;+ }++ /// Allocate memory for the specified number of values.+ T* allocate(std::size_t n)+ {+ return detail::recycling_allocator<T>().allocate(n);+ }++ /// Deallocate memory for the specified number of values.+ void deallocate(T* p, std::size_t n)+ {+ detail::recycling_allocator<T>().deallocate(p, n);+ }+};++/// A proto-allocator that caches memory blocks in thread-local storage for+/// reuse.+/**+ * The @recycling_allocator uses a simple strategy where a limited number of+ * small memory blocks are cached in thread-local storage, if the current+ * thread is running an @c io_context or is part of a @c thread_pool.+ */+template <>+class recycling_allocator<void>+{+public:+ /// No values are allocated by a proto-allocator.+ typedef void value_type;++ /// Rebind the allocator to another value_type.+ template <typename U>+ struct rebind+ {+ /// The rebound @c allocator type.+ typedef recycling_allocator<U> other;+ };++ /// Default constructor.+ ASIO_CONSTEXPR recycling_allocator() ASIO_NOEXCEPT+ {+ }++ /// Converting constructor.+ template <typename U>+ ASIO_CONSTEXPR recycling_allocator(+ const recycling_allocator<U>&) ASIO_NOEXCEPT+ {+ }++ /// Equality operator. Always returns true.+ ASIO_CONSTEXPR bool operator==(+ const recycling_allocator&) const ASIO_NOEXCEPT+ {+ return true;+ }++ /// Inequality operator. Always returns false.+ ASIO_CONSTEXPR bool operator!=(+ const recycling_allocator&) const ASIO_NOEXCEPT+ {+ return false;+ }+};++} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // ASIO_RECYCLING_ALLOCATOR_HPP
link/modules/asio-standalone/asio/include/asio/redirect_error.hpp view
@@ -2,7 +2,7 @@ // redirect_error.hpp // ~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -23,7 +23,7 @@ namespace asio { -/// Completion token type used to specify that an error produced by an+/// A @ref completion_token adapter used to specify that an error produced by an /// asynchronous operation is captured to an error_code variable. /** * The redirect_error_t class is used to indicate that any error_code produced@@ -47,7 +47,7 @@ asio::error_code& ec_; }; -/// Create a completion token to capture error_code values to a variable.+/// Adapt a @ref completion_token to capture error_code values to a variable. template <typename CompletionToken> inline redirect_error_t<typename decay<CompletionToken>::type> redirect_error( ASIO_MOVE_ARG(CompletionToken) completion_token,
+ link/modules/asio-standalone/asio/include/asio/registered_buffer.hpp view
@@ -0,0 +1,356 @@+//+// registered_buffer.hpp+// ~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com)+//+// Distributed under the Boost Software License, Version 1.0. (See accompanying+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)+//++#ifndef ASIO_REGISTERED_BUFFER_HPP+#define ASIO_REGISTERED_BUFFER_HPP++#if defined(_MSC_VER) && (_MSC_VER >= 1200)+# pragma once+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)++#include "asio/detail/config.hpp"+#include "asio/buffer.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {+namespace detail {++class buffer_registration_base;++} // namespace detail++class const_registered_buffer;++/// Type used to identify a registered buffer.+class registered_buffer_id+{+public:+ /// The native buffer identifier type.+ typedef int native_handle_type;++ /// Default constructor creates an invalid registered buffer identifier.+ registered_buffer_id() ASIO_NOEXCEPT+ : scope_(0),+ index_(-1)+ {+ }++ /// Get the native buffer identifier type.+ native_handle_type native_handle() const ASIO_NOEXCEPT+ {+ return index_;+ }++ /// Compare two IDs for equality.+ friend bool operator==(const registered_buffer_id& lhs,+ const registered_buffer_id& rhs) ASIO_NOEXCEPT+ {+ return lhs.scope_ == rhs.scope_ && lhs.index_ == rhs.index_;+ }++ /// Compare two IDs for equality.+ friend bool operator!=(const registered_buffer_id& lhs,+ const registered_buffer_id& rhs) ASIO_NOEXCEPT+ {+ return lhs.scope_ != rhs.scope_ || lhs.index_ != rhs.index_;+ }++private:+ friend class detail::buffer_registration_base;++ // Hidden constructor used by buffer registration.+ registered_buffer_id(const void* scope, int index) ASIO_NOEXCEPT+ : scope_(scope),+ index_(index)+ {+ }++ const void* scope_;+ int index_;+};++/// Holds a registered buffer over modifiable data.+/** + * Satisfies the @c MutableBufferSequence type requirements.+ */+class mutable_registered_buffer+{+public:+#if !defined(ASIO_HAS_DECLTYPE) \+ && !defined(GENERATING_DOCUMENTATION)+ typedef mutable_buffer value_type;+#endif // !defined(ASIO_HAS_DECLTYPE)+ // && !defined(GENERATING_DOCUMENTATION)++ /// Default constructor creates an invalid registered buffer.+ mutable_registered_buffer() ASIO_NOEXCEPT+ : buffer_(),+ id_()+ {+ }++ /// Get the underlying mutable buffer.+ const mutable_buffer& buffer() const ASIO_NOEXCEPT+ {+ return buffer_;+ }++ /// Get a pointer to the beginning of the memory range.+ /**+ * @returns <tt>buffer().data()</tt>.+ */+ void* data() const ASIO_NOEXCEPT+ {+ return buffer_.data();+ }++ /// Get the size of the memory range.+ /**+ * @returns <tt>buffer().size()</tt>.+ */+ std::size_t size() const ASIO_NOEXCEPT+ {+ return buffer_.size();+ }++ /// Get the registered buffer identifier.+ const registered_buffer_id& id() const ASIO_NOEXCEPT+ {+ return id_;+ }++ /// Move the start of the buffer by the specified number of bytes.+ mutable_registered_buffer& operator+=(std::size_t n) ASIO_NOEXCEPT+ {+ buffer_ += n;+ return *this;+ }++private:+ friend class detail::buffer_registration_base;++ // Hidden constructor used by buffer registration and operators.+ mutable_registered_buffer(const mutable_buffer& b,+ const registered_buffer_id& i) ASIO_NOEXCEPT+ : buffer_(b),+ id_(i)+ {+ }++#if !defined(GENERATING_DOCUMENTATION)+ friend mutable_registered_buffer buffer(+ const mutable_registered_buffer& b, std::size_t n) ASIO_NOEXCEPT;+#endif // !defined(GENERATING_DOCUMENTATION)++ mutable_buffer buffer_;+ registered_buffer_id id_;+};++/// Holds a registered buffer over non-modifiable data.+/** + * Satisfies the @c ConstBufferSequence type requirements.+ */+class const_registered_buffer+{+public:+#if !defined(ASIO_HAS_DECLTYPE) \+ && !defined(GENERATING_DOCUMENTATION)+ typedef const_buffer value_type;+#endif // !defined(ASIO_HAS_DECLTYPE)+ // && !defined(GENERATING_DOCUMENTATION)++ /// Default constructor creates an invalid registered buffer.+ const_registered_buffer() ASIO_NOEXCEPT+ : buffer_(),+ id_()+ {+ }++ /// Construct a non-modifiable buffer from a modifiable one.+ const_registered_buffer(+ const mutable_registered_buffer& b) ASIO_NOEXCEPT+ : buffer_(b.buffer()),+ id_(b.id())+ {+ }++ /// Get the underlying constant buffer.+ const const_buffer& buffer() const ASIO_NOEXCEPT+ {+ return buffer_;+ }++ /// Get a pointer to the beginning of the memory range.+ /**+ * @returns <tt>buffer().data()</tt>.+ */+ const void* data() const ASIO_NOEXCEPT+ {+ return buffer_.data();+ }++ /// Get the size of the memory range.+ /**+ * @returns <tt>buffer().size()</tt>.+ */+ std::size_t size() const ASIO_NOEXCEPT+ {+ return buffer_.size();+ }++ /// Get the registered buffer identifier.+ const registered_buffer_id& id() const ASIO_NOEXCEPT+ {+ return id_;+ }++ /// Move the start of the buffer by the specified number of bytes.+ const_registered_buffer& operator+=(std::size_t n) ASIO_NOEXCEPT+ {+ buffer_ += n;+ return *this;+ }++private:+ // Hidden constructor used by operators.+ const_registered_buffer(const const_buffer& b,+ const registered_buffer_id& i) ASIO_NOEXCEPT+ : buffer_(b),+ id_(i)+ {+ }++#if !defined(GENERATING_DOCUMENTATION)+ friend const_registered_buffer buffer(+ const const_registered_buffer& b, std::size_t n) ASIO_NOEXCEPT;+#endif // !defined(GENERATING_DOCUMENTATION)++ const_buffer buffer_;+ registered_buffer_id id_;+};++/** @addtogroup buffer_sequence_begin */++/// Get an iterator to the first element in a buffer sequence.+inline const mutable_buffer* buffer_sequence_begin(+ const mutable_registered_buffer& b) ASIO_NOEXCEPT+{+ return &b.buffer();+}++/// Get an iterator to the first element in a buffer sequence.+inline const const_buffer* buffer_sequence_begin(+ const const_registered_buffer& b) ASIO_NOEXCEPT+{+ return &b.buffer();+}++/** @} */+/** @addtogroup buffer_sequence_end */++/// Get an iterator to one past the end element in a buffer sequence.+inline const mutable_buffer* buffer_sequence_end(+ const mutable_registered_buffer& b) ASIO_NOEXCEPT+{+ return &b.buffer() + 1;+}++/// Get an iterator to one past the end element in a buffer sequence.+inline const const_buffer* buffer_sequence_end(+ const const_registered_buffer& b) ASIO_NOEXCEPT+{+ return &b.buffer() + 1;+}++/** @} */+/** @addtogroup buffer */++/// Obtain a buffer representing the entire registered buffer.+inline mutable_registered_buffer buffer(+ const mutable_registered_buffer& b) ASIO_NOEXCEPT+{+ return b;+}++/// Obtain a buffer representing the entire registered buffer.+inline const_registered_buffer buffer(+ const const_registered_buffer& b) ASIO_NOEXCEPT+{+ return b;+}++/// Obtain a buffer representing part of a registered buffer.+inline mutable_registered_buffer buffer(+ const mutable_registered_buffer& b, std::size_t n) ASIO_NOEXCEPT+{+ return mutable_registered_buffer(buffer(b.buffer_, n), b.id_);+}++/// Obtain a buffer representing part of a registered buffer.+inline const_registered_buffer buffer(+ const const_registered_buffer& b, std::size_t n) ASIO_NOEXCEPT+{+ return const_registered_buffer(buffer(b.buffer_, n), b.id_);+}++/** @} */++/// Create a new modifiable registered buffer that is offset from the start of+/// another.+/**+ * @relates mutable_registered_buffer+ */+inline mutable_registered_buffer operator+(+ const mutable_registered_buffer& b, std::size_t n) ASIO_NOEXCEPT+{+ mutable_registered_buffer tmp(b);+ tmp += n;+ return tmp;+}++/// Create a new modifiable buffer that is offset from the start of another.+/**+ * @relates mutable_registered_buffer+ */+inline mutable_registered_buffer operator+(std::size_t n,+ const mutable_registered_buffer& b) ASIO_NOEXCEPT+{+ return b + n;+}++/// Create a new non-modifiable registered buffer that is offset from the start+/// of another.+/**+ * @relates const_registered_buffer+ */+inline const_registered_buffer operator+(const const_registered_buffer& b,+ std::size_t n) ASIO_NOEXCEPT+{+ const_registered_buffer tmp(b);+ tmp += n;+ return tmp;+}++/// Create a new non-modifiable buffer that is offset from the start of another.+/**+ * @relates const_registered_buffer+ */+inline const_registered_buffer operator+(std::size_t n,+ const const_registered_buffer& b) ASIO_NOEXCEPT+{+ return b + n;+}++} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // ASIO_REGISTERED_BUFFER_HPP
link/modules/asio-standalone/asio/include/asio/require.hpp view
@@ -2,7 +2,7 @@ // require.hpp // ~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -107,6 +107,7 @@ namespace asio_require_fn { +using asio::conditional; using asio::decay; using asio::declval; using asio::enable_if;@@ -127,7 +128,8 @@ ill_formed }; -template <typename T, typename Properties, typename = void>+template <typename Impl, typename T, typename Properties, typename = void,+ typename = void, typename = void, typename = void, typename = void> struct call_traits { ASIO_STATIC_CONSTEXPR(overload_type, overload = ill_formed);@@ -135,19 +137,19 @@ typedef void result_type; }; -template <typename T, typename Property>-struct call_traits<T, void(Property),+template <typename Impl, typename T, typename Property>+struct call_traits<Impl, T, void(Property), typename enable_if<- (- is_applicable_property<- typename decay<T>::type,- typename decay<Property>::type- >::value- &&- decay<Property>::type::is_requirable- &&- static_require<T, Property>::is_valid- )+ is_applicable_property<+ typename decay<T>::type,+ typename decay<Property>::type+ >::value+ >::type,+ typename enable_if<+ decay<Property>::type::is_requirable+ >::type,+ typename enable_if<+ static_require<T, Property>::is_valid >::type> { ASIO_STATIC_CONSTEXPR(overload_type, overload = identity);@@ -160,57 +162,62 @@ #endif // defined(ASIO_HAS_MOVE) }; -template <typename T, typename Property>-struct call_traits<T, void(Property),+template <typename Impl, typename T, typename Property>+struct call_traits<Impl, T, void(Property), typename enable_if<- (- is_applicable_property<- typename decay<T>::type,- typename decay<Property>::type- >::value- &&- decay<Property>::type::is_requirable- &&- !static_require<T, Property>::is_valid- &&- require_member<T, Property>::is_valid- )+ is_applicable_property<+ typename decay<T>::type,+ typename decay<Property>::type+ >::value+ >::type,+ typename enable_if<+ decay<Property>::type::is_requirable+ >::type,+ typename enable_if<+ !static_require<T, Property>::is_valid+ >::type,+ typename enable_if<+ require_member<typename Impl::template proxy<T>::type, Property>::is_valid >::type> :- require_member<T, Property>+ require_member<typename Impl::template proxy<T>::type, Property> { ASIO_STATIC_CONSTEXPR(overload_type, overload = call_member); }; -template <typename T, typename Property>-struct call_traits<T, void(Property),+template <typename Impl, typename T, typename Property>+struct call_traits<Impl, T, void(Property), typename enable_if<- (- is_applicable_property<- typename decay<T>::type,- typename decay<Property>::type- >::value- &&- decay<Property>::type::is_requirable- &&- !static_require<T, Property>::is_valid- &&- !require_member<T, Property>::is_valid- &&- require_free<T, Property>::is_valid- )+ is_applicable_property<+ typename decay<T>::type,+ typename decay<Property>::type+ >::value+ >::type,+ typename enable_if<+ decay<Property>::type::is_requirable+ >::type,+ typename enable_if<+ !static_require<T, Property>::is_valid+ >::type,+ typename enable_if<+ !require_member<typename Impl::template proxy<T>::type, Property>::is_valid+ >::type,+ typename enable_if<+ require_free<T, Property>::is_valid >::type> : require_free<T, Property> { ASIO_STATIC_CONSTEXPR(overload_type, overload = call_free); }; -template <typename T, typename P0, typename P1>-struct call_traits<T, void(P0, P1),+template <typename Impl, typename T, typename P0, typename P1>+struct call_traits<Impl, T, void(P0, P1), typename enable_if<- call_traits<T, void(P0)>::overload != ill_formed- &&+ call_traits<Impl, T, void(P0)>::overload != ill_formed+ >::type,+ typename enable_if< call_traits<- typename call_traits<T, void(P0)>::result_type,+ Impl,+ typename call_traits<Impl, T, void(P0)>::result_type, void(P1) >::overload != ill_formed >::type>@@ -219,29 +226,34 @@ ASIO_STATIC_CONSTEXPR(bool, is_noexcept = (- call_traits<T, void(P0)>::is_noexcept+ call_traits<Impl, T, void(P0)>::is_noexcept && call_traits<- typename call_traits<T, void(P0)>::result_type,+ Impl,+ typename call_traits<Impl, T, void(P0)>::result_type, void(P1) >::is_noexcept )); typedef typename decay< typename call_traits<- typename call_traits<T, void(P0)>::result_type,+ Impl,+ typename call_traits<Impl, T, void(P0)>::result_type, void(P1) >::result_type >::type result_type; }; -template <typename T, typename P0, typename P1, typename ASIO_ELLIPSIS PN>-struct call_traits<T, void(P0, P1, PN ASIO_ELLIPSIS),+template <typename Impl, typename T, typename P0,+ typename P1, typename ASIO_ELLIPSIS PN>+struct call_traits<Impl, T, void(P0, P1, PN ASIO_ELLIPSIS), typename enable_if<- call_traits<T, void(P0)>::overload != ill_formed- &&+ call_traits<Impl, T, void(P0)>::overload != ill_formed+ >::type,+ typename enable_if< call_traits<- typename call_traits<T, void(P0)>::result_type,+ Impl,+ typename call_traits<Impl, T, void(P0)>::result_type, void(P1, PN ASIO_ELLIPSIS) >::overload != ill_formed >::type>@@ -250,17 +262,19 @@ ASIO_STATIC_CONSTEXPR(bool, is_noexcept = (- call_traits<T, void(P0)>::is_noexcept+ call_traits<Impl, T, void(P0)>::is_noexcept && call_traits<- typename call_traits<T, void(P0)>::result_type,+ Impl,+ typename call_traits<Impl, T, void(P0)>::result_type, void(P1, PN ASIO_ELLIPSIS) >::is_noexcept )); typedef typename decay< typename call_traits<- typename call_traits<T, void(P0)>::result_type,+ Impl,+ typename call_traits<Impl, T, void(P0)>::result_type, void(P1, PN ASIO_ELLIPSIS) >::result_type >::type result_type;@@ -268,30 +282,54 @@ struct impl {+ template <typename T>+ struct proxy+ {+#if defined(ASIO_HAS_DEDUCED_REQUIRE_MEMBER_TRAIT)+ struct type+ {+ template <typename P>+ auto require(ASIO_MOVE_ARG(P) p)+ noexcept(+ noexcept(+ declval<typename conditional<true, T, P>::type>().require(+ ASIO_MOVE_CAST(P)(p))+ )+ )+ -> decltype(+ declval<typename conditional<true, T, P>::type>().require(+ ASIO_MOVE_CAST(P)(p))+ );+ };+#else // defined(ASIO_HAS_DEDUCED_REQUIRE_MEMBER_TRAIT)+ typedef T type;+#endif // defined(ASIO_HAS_DEDUCED_REQUIRE_MEMBER_TRAIT)+ };+ template <typename T, typename Property> ASIO_NODISCARD ASIO_CONSTEXPR typename enable_if<- call_traits<T, void(Property)>::overload == identity,- typename call_traits<T, void(Property)>::result_type+ call_traits<impl, T, void(Property)>::overload == identity,+ typename call_traits<impl, T, void(Property)>::result_type >::type operator()( ASIO_MOVE_ARG(T) t, ASIO_MOVE_ARG(Property)) const ASIO_NOEXCEPT_IF((- call_traits<T, void(Property)>::is_noexcept))+ call_traits<impl, T, void(Property)>::is_noexcept)) { return ASIO_MOVE_CAST(T)(t); } template <typename T, typename Property> ASIO_NODISCARD ASIO_CONSTEXPR typename enable_if<- call_traits<T, void(Property)>::overload == call_member,- typename call_traits<T, void(Property)>::result_type+ call_traits<impl, T, void(Property)>::overload == call_member,+ typename call_traits<impl, T, void(Property)>::result_type >::type operator()( ASIO_MOVE_ARG(T) t, ASIO_MOVE_ARG(Property) p) const ASIO_NOEXCEPT_IF((- call_traits<T, void(Property)>::is_noexcept))+ call_traits<impl, T, void(Property)>::is_noexcept)) { return ASIO_MOVE_CAST(T)(t).require( ASIO_MOVE_CAST(Property)(p));@@ -299,14 +337,14 @@ template <typename T, typename Property> ASIO_NODISCARD ASIO_CONSTEXPR typename enable_if<- call_traits<T, void(Property)>::overload == call_free,- typename call_traits<T, void(Property)>::result_type+ call_traits<impl, T, void(Property)>::overload == call_free,+ typename call_traits<impl, T, void(Property)>::result_type >::type operator()( ASIO_MOVE_ARG(T) t, ASIO_MOVE_ARG(Property) p) const ASIO_NOEXCEPT_IF((- call_traits<T, void(Property)>::is_noexcept))+ call_traits<impl, T, void(Property)>::is_noexcept)) { return require( ASIO_MOVE_CAST(T)(t),@@ -315,15 +353,15 @@ template <typename T, typename P0, typename P1> ASIO_NODISCARD ASIO_CONSTEXPR typename enable_if<- call_traits<T, void(P0, P1)>::overload == two_props,- typename call_traits<T, void(P0, P1)>::result_type+ call_traits<impl, T, void(P0, P1)>::overload == two_props,+ typename call_traits<impl, T, void(P0, P1)>::result_type >::type operator()( ASIO_MOVE_ARG(T) t, ASIO_MOVE_ARG(P0) p0, ASIO_MOVE_ARG(P1) p1) const ASIO_NOEXCEPT_IF((- call_traits<T, void(P0, P1)>::is_noexcept))+ call_traits<impl, T, void(P0, P1)>::is_noexcept)) { return (*this)( (*this)(@@ -335,8 +373,10 @@ template <typename T, typename P0, typename P1, typename ASIO_ELLIPSIS PN> ASIO_NODISCARD ASIO_CONSTEXPR typename enable_if<- call_traits<T, void(P0, P1, PN ASIO_ELLIPSIS)>::overload == n_props,- typename call_traits<T, void(P0, P1, PN ASIO_ELLIPSIS)>::result_type+ call_traits<impl, T,+ void(P0, P1, PN ASIO_ELLIPSIS)>::overload == n_props,+ typename call_traits<impl, T,+ void(P0, P1, PN ASIO_ELLIPSIS)>::result_type >::type operator()( ASIO_MOVE_ARG(T) t,@@ -344,7 +384,7 @@ ASIO_MOVE_ARG(P1) p1, ASIO_MOVE_ARG(PN) ASIO_ELLIPSIS pn) const ASIO_NOEXCEPT_IF((- call_traits<T, void(P0, P1, PN ASIO_ELLIPSIS)>::is_noexcept))+ call_traits<impl, T, void(P0, P1, PN ASIO_ELLIPSIS)>::is_noexcept)) { return (*this)( (*this)(@@ -373,13 +413,16 @@ } // namespace +typedef asio_require_fn::impl require_t;+ #if defined(ASIO_HAS_VARIADIC_TEMPLATES) template <typename T, typename... Properties> struct can_require : integral_constant<bool,- asio_require_fn::call_traits<T, void(Properties...)>::overload- != asio_require_fn::ill_formed>+ asio_require_fn::call_traits<+ require_t, T, void(Properties...)>::overload+ != asio_require_fn::ill_formed> { }; @@ -389,7 +432,7 @@ typename P1 = void, typename P2 = void> struct can_require : integral_constant<bool,- asio_require_fn::call_traits<T, void(P0, P1, P2)>::overload+ asio_require_fn::call_traits<require_t, T, void(P0, P1, P2)>::overload != asio_require_fn::ill_formed> { };@@ -397,7 +440,7 @@ template <typename T, typename P0, typename P1> struct can_require<T, P0, P1> : integral_constant<bool,- asio_require_fn::call_traits<T, void(P0, P1)>::overload+ asio_require_fn::call_traits<require_t, T, void(P0, P1)>::overload != asio_require_fn::ill_formed> { };@@ -405,7 +448,7 @@ template <typename T, typename P0> struct can_require<T, P0> : integral_constant<bool,- asio_require_fn::call_traits<T, void(P0)>::overload+ asio_require_fn::call_traits<require_t, T, void(P0)>::overload != asio_require_fn::ill_formed> { };@@ -431,7 +474,8 @@ template <typename T, typename... Properties> struct is_nothrow_require : integral_constant<bool,- asio_require_fn::call_traits<T, void(Properties...)>::is_noexcept>+ asio_require_fn::call_traits<+ require_t, T, void(Properties...)>::is_noexcept> { }; @@ -441,21 +485,24 @@ typename P1 = void, typename P2 = void> struct is_nothrow_require : integral_constant<bool,- asio_require_fn::call_traits<T, void(P0, P1, P2)>::is_noexcept>+ asio_require_fn::call_traits<+ require_t, T, void(P0, P1, P2)>::is_noexcept> { }; template <typename T, typename P0, typename P1> struct is_nothrow_require<T, P0, P1> : integral_constant<bool,- asio_require_fn::call_traits<T, void(P0, P1)>::is_noexcept>+ asio_require_fn::call_traits<+ require_t, T, void(P0, P1)>::is_noexcept> { }; template <typename T, typename P0> struct is_nothrow_require<T, P0> : integral_constant<bool,- asio_require_fn::call_traits<T, void(P0)>::is_noexcept>+ asio_require_fn::call_traits<+ require_t, T, void(P0)>::is_noexcept> { }; @@ -481,7 +528,7 @@ struct require_result { typedef typename asio_require_fn::call_traits<- T, void(Properties...)>::result_type type;+ require_t, T, void(Properties...)>::result_type type; }; #else // defined(ASIO_HAS_VARIADIC_TEMPLATES)@@ -491,21 +538,21 @@ struct require_result { typedef typename asio_require_fn::call_traits<- T, void(P0, P1, P2)>::result_type type;+ require_t, T, void(P0, P1, P2)>::result_type type; }; template <typename T, typename P0, typename P1> struct require_result<T, P0, P1> { typedef typename asio_require_fn::call_traits<- T, void(P0, P1)>::result_type type;+ require_t, T, void(P0, P1)>::result_type type; }; template <typename T, typename P0> struct require_result<T, P0> { typedef typename asio_require_fn::call_traits<- T, void(P0)>::result_type type;+ require_t, T, void(P0)>::result_type type; }; template <typename T>
link/modules/asio-standalone/asio/include/asio/require_concept.hpp view
@@ -2,7 +2,7 @@ // require_concept.hpp // ~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -107,6 +107,7 @@ namespace asio_require_concept_fn { +using asio::conditional; using asio::decay; using asio::declval; using asio::enable_if;@@ -125,7 +126,8 @@ ill_formed }; -template <typename T, typename Properties, typename = void>+template <typename Impl, typename T, typename Properties, typename = void,+ typename = void, typename = void, typename = void, typename = void> struct call_traits { ASIO_STATIC_CONSTEXPR(overload_type, overload = ill_formed);@@ -133,19 +135,19 @@ typedef void result_type; }; -template <typename T, typename Property>-struct call_traits<T, void(Property),+template <typename Impl, typename T, typename Property>+struct call_traits<Impl, T, void(Property), typename enable_if<- (- is_applicable_property<- typename decay<T>::type,- typename decay<Property>::type- >::value- &&- decay<Property>::type::is_requirable_concept- &&- static_require_concept<T, Property>::is_valid- )+ is_applicable_property<+ typename decay<T>::type,+ typename decay<Property>::type+ >::value+ >::type,+ typename enable_if<+ decay<Property>::type::is_requirable_concept+ >::type,+ typename enable_if<+ static_require_concept<T, Property>::is_valid >::type> { ASIO_STATIC_CONSTEXPR(overload_type, overload = identity);@@ -153,44 +155,56 @@ typedef ASIO_MOVE_ARG(T) result_type; }; -template <typename T, typename Property>-struct call_traits<T, void(Property),+template <typename Impl, typename T, typename Property>+struct call_traits<Impl, T, void(Property), typename enable_if<- (- is_applicable_property<- typename decay<T>::type,- typename decay<Property>::type- >::value- &&- decay<Property>::type::is_requirable_concept- &&- !static_require_concept<T, Property>::is_valid- &&- require_concept_member<T, Property>::is_valid- )+ is_applicable_property<+ typename decay<T>::type,+ typename decay<Property>::type+ >::value+ >::type,+ typename enable_if<+ decay<Property>::type::is_requirable_concept+ >::type,+ typename enable_if<+ !static_require_concept<T, Property>::is_valid+ >::type,+ typename enable_if<+ require_concept_member<+ typename Impl::template proxy<T>::type,+ Property+ >::is_valid >::type> :- require_concept_member<T, Property>+ require_concept_member<+ typename Impl::template proxy<T>::type,+ Property+ > { ASIO_STATIC_CONSTEXPR(overload_type, overload = call_member); }; -template <typename T, typename Property>-struct call_traits<T, void(Property),+template <typename Impl, typename T, typename Property>+struct call_traits<Impl, T, void(Property), typename enable_if<- (- is_applicable_property<- typename decay<T>::type,- typename decay<Property>::type- >::value- &&- decay<Property>::type::is_requirable_concept- &&- !static_require_concept<T, Property>::is_valid- &&- !require_concept_member<T, Property>::is_valid- &&- require_concept_free<T, Property>::is_valid- )+ is_applicable_property<+ typename decay<T>::type,+ typename decay<Property>::type+ >::value+ >::type,+ typename enable_if<+ decay<Property>::type::is_requirable_concept+ >::type,+ typename enable_if<+ !static_require_concept<T, Property>::is_valid+ >::type,+ typename enable_if<+ !require_concept_member<+ typename Impl::template proxy<T>::type,+ Property+ >::is_valid+ >::type,+ typename enable_if<+ require_concept_free<T, Property>::is_valid >::type> : require_concept_free<T, Property> {@@ -199,30 +213,54 @@ struct impl {+ template <typename T>+ struct proxy+ {+#if defined(ASIO_HAS_DEDUCED_REQUIRE_CONCEPT_MEMBER_TRAIT)+ struct type+ {+ template <typename P>+ auto require_concept(ASIO_MOVE_ARG(P) p)+ noexcept(+ noexcept(+ declval<typename conditional<true, T, P>::type>().require_concept(+ ASIO_MOVE_CAST(P)(p))+ )+ )+ -> decltype(+ declval<typename conditional<true, T, P>::type>().require_concept(+ ASIO_MOVE_CAST(P)(p))+ );+ };+#else // defined(ASIO_HAS_DEDUCED_REQUIRE_CONCEPT_MEMBER_TRAIT)+ typedef T type;+#endif // defined(ASIO_HAS_DEDUCED_REQUIRE_CONCEPT_MEMBER_TRAIT)+ };+ template <typename T, typename Property> ASIO_NODISCARD ASIO_CONSTEXPR typename enable_if<- call_traits<T, void(Property)>::overload == identity,- typename call_traits<T, void(Property)>::result_type+ call_traits<impl, T, void(Property)>::overload == identity,+ typename call_traits<impl, T, void(Property)>::result_type >::type operator()( ASIO_MOVE_ARG(T) t, ASIO_MOVE_ARG(Property)) const ASIO_NOEXCEPT_IF((- call_traits<T, void(Property)>::is_noexcept))+ call_traits<impl, T, void(Property)>::is_noexcept)) { return ASIO_MOVE_CAST(T)(t); } template <typename T, typename Property> ASIO_NODISCARD ASIO_CONSTEXPR typename enable_if<- call_traits<T, void(Property)>::overload == call_member,- typename call_traits<T, void(Property)>::result_type+ call_traits<impl, T, void(Property)>::overload == call_member,+ typename call_traits<impl, T, void(Property)>::result_type >::type operator()( ASIO_MOVE_ARG(T) t, ASIO_MOVE_ARG(Property) p) const ASIO_NOEXCEPT_IF((- call_traits<T, void(Property)>::is_noexcept))+ call_traits<impl, T, void(Property)>::is_noexcept)) { return ASIO_MOVE_CAST(T)(t).require_concept( ASIO_MOVE_CAST(Property)(p));@@ -230,14 +268,14 @@ template <typename T, typename Property> ASIO_NODISCARD ASIO_CONSTEXPR typename enable_if<- call_traits<T, void(Property)>::overload == call_free,- typename call_traits<T, void(Property)>::result_type+ call_traits<impl, T, void(Property)>::overload == call_free,+ typename call_traits<impl, T, void(Property)>::result_type >::type operator()( ASIO_MOVE_ARG(T) t, ASIO_MOVE_ARG(Property) p) const ASIO_NOEXCEPT_IF((- call_traits<T, void(Property)>::is_noexcept))+ call_traits<impl, T, void(Property)>::is_noexcept)) { return require_concept( ASIO_MOVE_CAST(T)(t),@@ -263,11 +301,14 @@ } // namespace +typedef asio_require_concept_fn::impl require_concept_t;+ template <typename T, typename Property> struct can_require_concept : integral_constant<bool,- asio_require_concept_fn::call_traits<T, void(Property)>::overload !=- asio_require_concept_fn::ill_formed>+ asio_require_concept_fn::call_traits<+ require_concept_t, T, void(Property)>::overload !=+ asio_require_concept_fn::ill_formed> { }; @@ -282,7 +323,8 @@ template <typename T, typename Property> struct is_nothrow_require_concept : integral_constant<bool,- asio_require_concept_fn::call_traits<T, void(Property)>::is_noexcept>+ asio_require_concept_fn::call_traits<+ require_concept_t, T, void(Property)>::is_noexcept> { }; @@ -298,7 +340,7 @@ struct require_concept_result { typedef typename asio_require_concept_fn::call_traits<- T, void(Property)>::result_type type;+ require_concept_t, T, void(Property)>::result_type type; }; } // namespace asio
link/modules/asio-standalone/asio/include/asio/serial_port.hpp view
@@ -2,7 +2,7 @@ // serial_port.hpp // ~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // Copyright (c) 2008 Rep Invariant Systems, Inc. (info@repinvariant.com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying
link/modules/asio-standalone/asio/include/asio/serial_port_base.hpp view
@@ -2,7 +2,7 @@ // serial_port_base.hpp // ~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // Copyright (c) 2008 Rep Invariant Systems, Inc. (info@repinvariant.com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying
link/modules/asio-standalone/asio/include/asio/signal_set.hpp view
@@ -2,7 +2,7 @@ // signal_set.hpp // ~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+ link/modules/asio-standalone/asio/include/asio/signal_set_base.hpp view
@@ -0,0 +1,182 @@+//+// signal_set_base.hpp+// ~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com)+//+// Distributed under the Boost Software License, Version 1.0. (See accompanying+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)+//++#ifndef ASIO_SIGNAL_SET_BASE_HPP+#define ASIO_SIGNAL_SET_BASE_HPP++#if defined(_MSC_VER) && (_MSC_VER >= 1200)+# pragma once+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)++#include "asio/detail/config.hpp"+#include "asio/detail/socket_types.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {++/// The signal_set_base class is used as a base for the basic_signal_set class+/// templates so that we have a common place to define the flags enum.+class signal_set_base+{+public:+# if defined(GENERATING_DOCUMENTATION)+ /// Enumeration representing the different types of flags that may specified+ /// when adding a signal to a set.+ enum flags+ {+ /// Bitmask representing no flags.+ none = 0,++ /// Affects the behaviour of interruptible functions such that, if the+ /// function would have failed with error::interrupted when interrupted by+ /// the specified signal, the function shall instead be restarted and not+ /// fail with error::interrupted.+ restart = implementation_defined,++ /// Do not generate SIGCHLD when child processes stop or stopped child+ /// processes continue.+ no_child_stop = implementation_defined,++ /// Do not transform child processes into zombies when they terminate.+ no_child_wait = implementation_defined,++ /// Special value to indicate that the signal registration does not care+ /// which flags are set, and so will not conflict with any prior+ /// registrations of the same signal.+ dont_care = -1+ };++ /// Portability typedef.+ typedef flags flags_t;+#elif defined(ASIO_HAS_ENUM_CLASS)+ enum class flags : int+ {+ none = 0,+ restart = ASIO_OS_DEF(SA_RESTART),+ no_child_stop = ASIO_OS_DEF(SA_NOCLDSTOP),+ no_child_wait = ASIO_OS_DEF(SA_NOCLDWAIT),+ dont_care = -1+ };++ typedef flags flags_t;+#else // defined(ASIO_HAS_ENUM_CLASS)+ struct flags+ {+ enum flags_t+ {+ none = 0,+ restart = ASIO_OS_DEF(SA_RESTART),+ no_child_stop = ASIO_OS_DEF(SA_NOCLDSTOP),+ no_child_wait = ASIO_OS_DEF(SA_NOCLDWAIT),+ dont_care = -1+ };+ };++ typedef flags::flags_t flags_t;+#endif // defined(ASIO_HAS_ENUM_CLASS)++protected:+ /// Protected destructor to prevent deletion through this type.+ ~signal_set_base()+ {+ }+};++/// Negation operator.+/**+ * @relates signal_set_base::flags+ */+inline ASIO_CONSTEXPR bool operator!(signal_set_base::flags_t x)+{+ return static_cast<int>(x) == 0;+}++/// Bitwise and operator.+/**+ * @relates signal_set_base::flags+ */+inline ASIO_CONSTEXPR signal_set_base::flags_t operator&(+ signal_set_base::flags_t x, signal_set_base::flags_t y)+{+ return static_cast<signal_set_base::flags_t>(+ static_cast<int>(x) & static_cast<int>(y));+}++/// Bitwise or operator.+/**+ * @relates signal_set_base::flags+ */+inline ASIO_CONSTEXPR signal_set_base::flags_t operator|(+ signal_set_base::flags_t x, signal_set_base::flags_t y)+{+ return static_cast<signal_set_base::flags_t>(+ static_cast<int>(x) | static_cast<int>(y));+}++/// Bitwise xor operator.+/**+ * @relates signal_set_base::flags+ */+inline ASIO_CONSTEXPR signal_set_base::flags_t operator^(+ signal_set_base::flags_t x, signal_set_base::flags_t y)+{+ return static_cast<signal_set_base::flags_t>(+ static_cast<int>(x) ^ static_cast<int>(y));+}++/// Bitwise negation operator.+/**+ * @relates signal_set_base::flags+ */+inline ASIO_CONSTEXPR signal_set_base::flags_t operator~(+ signal_set_base::flags_t x)+{+ return static_cast<signal_set_base::flags_t>(~static_cast<int>(x));+}++/// Bitwise and-assignment operator.+/**+ * @relates signal_set_base::flags+ */+inline signal_set_base::flags_t& operator&=(+ signal_set_base::flags_t& x, signal_set_base::flags_t y)+{+ x = x & y;+ return x;+}++/// Bitwise or-assignment operator.+/**+ * @relates signal_set_base::flags+ */+inline signal_set_base::flags_t& operator|=(+ signal_set_base::flags_t& x, signal_set_base::flags_t y)+{+ x = x | y;+ return x;+}++/// Bitwise xor-assignment operator.+/**+ * @relates signal_set_base::flags+ */+inline signal_set_base::flags_t& operator^=(+ signal_set_base::flags_t& x, signal_set_base::flags_t y)+{+ x = x ^ y;+ return x;+}++} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // ASIO_SIGNAL_SET_BASE_HPP
link/modules/asio-standalone/asio/include/asio/socket_base.hpp view
@@ -2,7 +2,7 @@ // socket_base.hpp // ~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/spawn.hpp view
@@ -2,7 +2,7 @@ // spawn.hpp // ~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -16,28 +16,162 @@ #endif // defined(_MSC_VER) && (_MSC_VER >= 1200) #include "asio/detail/config.hpp"-#include <boost/coroutine/all.hpp> #include "asio/any_io_executor.hpp"-#include "asio/bind_executor.hpp"+#include "asio/cancellation_signal.hpp"+#include "asio/cancellation_state.hpp"+#include "asio/detail/exception.hpp" #include "asio/detail/memory.hpp" #include "asio/detail/type_traits.hpp"-#include "asio/detail/wrapped_handler.hpp" #include "asio/io_context.hpp" #include "asio/is_executor.hpp" #include "asio/strand.hpp" +#if defined(ASIO_HAS_BOOST_COROUTINE)+# include <boost/coroutine/all.hpp>+#endif // defined(ASIO_HAS_BOOST_COROUTINE)+ #include "asio/detail/push_options.hpp" namespace asio {+namespace detail { -/// Context object the represents the currently executing coroutine.+// Base class for all spawn()-ed thread implementations.+class spawned_thread_base+{+public:+ spawned_thread_base()+ : owner_(0),+ has_context_switched_(false),+ throw_if_cancelled_(false),+ terminal_(false)+ {+ }++ virtual ~spawned_thread_base() {}+ virtual void resume() = 0;+ virtual void suspend_with(void (*fn)(void*), void* arg) = 0;+ virtual void destroy() = 0;++ void attach(spawned_thread_base** owner)+ {+ owner_ = owner;+ *owner_ = this;+ }++ void detach()+ {+ if (owner_)+ *owner_ = 0;+ owner_ = 0;+ }++ void suspend()+ {+ suspend_with(0, 0);+ }++ template <typename F>+ void suspend_with(F f)+ {+ suspend_with(&spawned_thread_base::call<F>, &f);+ }++ cancellation_slot get_cancellation_slot() const ASIO_NOEXCEPT+ {+ return cancellation_state_.slot();+ }++ cancellation_state get_cancellation_state() const ASIO_NOEXCEPT+ {+ return cancellation_state_;+ }++ void reset_cancellation_state()+ {+ cancellation_state_ = cancellation_state(parent_cancellation_slot_);+ }++ template <typename Filter>+ void reset_cancellation_state(Filter filter)+ {+ cancellation_state_ = cancellation_state(+ parent_cancellation_slot_, filter, filter);+ }++ template <typename InFilter, typename OutFilter>+ void reset_cancellation_state(InFilter in_filter, OutFilter out_filter)+ {+ cancellation_state_ = cancellation_state(+ parent_cancellation_slot_, in_filter, out_filter);+ }++ cancellation_type_t cancelled() const ASIO_NOEXCEPT+ {+ return cancellation_state_.cancelled();+ }++ bool has_context_switched() const ASIO_NOEXCEPT+ {+ return has_context_switched_;+ }++ bool throw_if_cancelled() const ASIO_NOEXCEPT+ {+ return throw_if_cancelled_;+ }++ void throw_if_cancelled(bool value) ASIO_NOEXCEPT+ {+ throw_if_cancelled_ = value;+ }++protected:+ spawned_thread_base** owner_; // Points to data member in active handler.+ asio::cancellation_slot parent_cancellation_slot_;+ asio::cancellation_state cancellation_state_;+ bool has_context_switched_;+ bool throw_if_cancelled_;+ bool terminal_;++private:+ // Disallow copying and assignment.+ spawned_thread_base(const spawned_thread_base&) ASIO_DELETED;+ spawned_thread_base& operator=(const spawned_thread_base&) ASIO_DELETED;++ template <typename F>+ static void call(void* f)+ {+ (*static_cast<F*>(f))();+ }+};+++template <typename T>+struct spawn_signature+{+ typedef void type(exception_ptr, T);+};++template <>+struct spawn_signature<void>+{+ typedef void type(exception_ptr);+};++template <typename Executor>+class initiate_spawn;++} // namespace detail++/// A @ref completion_token that represents the currently executing coroutine. /**- * The basic_yield_context class is used to represent the currently executing- * stackful coroutine. A basic_yield_context may be passed as a handler to an- * asynchronous operation. For example:+ * The basic_yield_context class is a completion token type that is used to+ * represent the currently executing stackful coroutine. A basic_yield_context+ * object may be passed as a completion token to an asynchronous operation. For+ * example: *- * @code template <typename Handler>- * void my_coroutine(basic_yield_context<Handler> yield)+ * @code template <typename Executor>+ * void my_coroutine(basic_yield_context<Executor> yield) * { * ... * std::size_t n = my_socket.async_read_some(buffer, yield);@@ -48,69 +182,114 @@ * current coroutine. The coroutine is resumed when the asynchronous operation * completes, and the result of the operation is returned. */-template <typename Handler>+template <typename Executor> class basic_yield_context { public:- /// The coroutine callee type, used by the implementation.+ /// The executor type associated with the yield context.+ typedef Executor executor_type;++ /// The cancellation slot type associated with the yield context.+ typedef cancellation_slot cancellation_slot_type;++ /// Construct a yield context from another yield context type. /**- * When using Boost.Coroutine v1, this type is:- * @code typename coroutine<void()> @endcode- * When using Boost.Coroutine v2 (unidirectional coroutines), this type is:- * @code push_coroutine<void> @endcode+ * Requires that OtherExecutor be convertible to Executor. */-#if defined(GENERATING_DOCUMENTATION)- typedef implementation_defined callee_type;-#elif defined(BOOST_COROUTINES_UNIDIRECT) || defined(BOOST_COROUTINES_V2)- typedef boost::coroutines::push_coroutine<void> callee_type;-#else- typedef boost::coroutines::coroutine<void()> callee_type;-#endif- - /// The coroutine caller type, used by the implementation.+ template <typename OtherExecutor>+ basic_yield_context(const basic_yield_context<OtherExecutor>& other,+ typename constraint<+ is_convertible<OtherExecutor, Executor>::value+ >::type = 0)+ : spawned_thread_(other.spawned_thread_),+ executor_(other.executor_),+ ec_(other.ec_)+ {+ }++ /// Get the executor associated with the yield context.+ executor_type get_executor() const ASIO_NOEXCEPT+ {+ return executor_;+ }++ /// Get the cancellation slot associated with the coroutine.+ cancellation_slot_type get_cancellation_slot() const ASIO_NOEXCEPT+ {+ return spawned_thread_->get_cancellation_slot();+ }++ /// Get the cancellation state associated with the coroutine.+ cancellation_state get_cancellation_state() const ASIO_NOEXCEPT+ {+ return spawned_thread_->get_cancellation_state();+ }++ /// Reset the cancellation state associated with the coroutine. /**- * When using Boost.Coroutine v1, this type is:- * @code typename coroutine<void()>::caller_type @endcode- * When using Boost.Coroutine v2 (unidirectional coroutines), this type is:- * @code pull_coroutine<void> @endcode+ * Let <tt>P</tt> be the cancellation slot associated with the current+ * coroutine's @ref spawn completion handler. Assigns a new+ * asio::cancellation_state object <tt>S</tt>, constructed as+ * <tt>S(P)</tt>, into the current coroutine's cancellation state object. */-#if defined(GENERATING_DOCUMENTATION)- typedef implementation_defined caller_type;-#elif defined(BOOST_COROUTINES_UNIDIRECT) || defined(BOOST_COROUTINES_V2)- typedef boost::coroutines::pull_coroutine<void> caller_type;-#else- typedef boost::coroutines::coroutine<void()>::caller_type caller_type;-#endif+ void reset_cancellation_state() const+ {+ spawned_thread_->reset_cancellation_state();+ } - /// Construct a yield context to represent the specified coroutine.+ /// Reset the cancellation state associated with the coroutine. /**- * Most applications do not need to use this constructor. Instead, the- * spawn() function passes a yield context as an argument to the coroutine- * function.+ * Let <tt>P</tt> be the cancellation slot associated with the current+ * coroutine's @ref spawn completion handler. Assigns a new+ * asio::cancellation_state object <tt>S</tt>, constructed as <tt>S(P,+ * std::forward<Filter>(filter))</tt>, into the current coroutine's+ * cancellation state object. */- basic_yield_context(- const detail::weak_ptr<callee_type>& coro,- caller_type& ca, Handler& handler)- : coro_(coro),- ca_(ca),- handler_(handler),- ec_(0)+ template <typename Filter>+ void reset_cancellation_state(ASIO_MOVE_ARG(Filter) filter) const {+ spawned_thread_->reset_cancellation_state(+ ASIO_MOVE_CAST(Filter)(filter)); } - /// Construct a yield context from another yield context type.+ /// Reset the cancellation state associated with the coroutine. /**- * Requires that OtherHandler be convertible to Handler.+ * Let <tt>P</tt> be the cancellation slot associated with the current+ * coroutine's @ref spawn completion handler. Assigns a new+ * asio::cancellation_state object <tt>S</tt>, constructed as <tt>S(P,+ * std::forward<InFilter>(in_filter),+ * std::forward<OutFilter>(out_filter))</tt>, into the current coroutine's+ * cancellation state object. */- template <typename OtherHandler>- basic_yield_context(const basic_yield_context<OtherHandler>& other)- : coro_(other.coro_),- ca_(other.ca_),- handler_(other.handler_),- ec_(other.ec_)+ template <typename InFilter, typename OutFilter>+ void reset_cancellation_state(ASIO_MOVE_ARG(InFilter) in_filter,+ ASIO_MOVE_ARG(OutFilter) out_filter) const {+ spawned_thread_->reset_cancellation_state(+ ASIO_MOVE_CAST(InFilter)(in_filter),+ ASIO_MOVE_CAST(OutFilter)(out_filter)); } + /// Determine whether the current coroutine has been cancelled.+ cancellation_type_t cancelled() const ASIO_NOEXCEPT+ {+ return spawned_thread_->cancelled();+ }++ /// Determine whether the coroutine throws if trying to suspend when it has+ /// been cancelled.+ bool throw_if_cancelled() const ASIO_NOEXCEPT+ {+ return spawned_thread_->throw_if_cancelled();+ }++ /// Set whether the coroutine throws if trying to suspend when it has been+ /// cancelled.+ void throw_if_cancelled(bool value) const ASIO_NOEXCEPT+ {+ spawned_thread_->throw_if_cancelled(value);+ }+ /// Return a yield context that sets the specified error_code. /** * By default, when a yield context is used with an asynchronous operation, a@@ -118,8 +297,8 @@ * operator may be used to specify an error_code object that should instead be * set with the asynchronous operation's result. For example: *- * @code template <typename Handler>- * void my_coroutine(basic_yield_context<Handler> yield)+ * @code template <typename Executor>+ * void my_coroutine(basic_yield_context<Executor> yield) * { * ... * std::size_t n = my_socket.async_read_some(buffer, yield[ec]);@@ -137,22 +316,25 @@ return tmp; } -#if defined(GENERATING_DOCUMENTATION)-private:-#endif // defined(GENERATING_DOCUMENTATION)- detail::weak_ptr<callee_type> coro_;- caller_type& ca_;- Handler handler_;+#if !defined(GENERATING_DOCUMENTATION)+//private:+ basic_yield_context(detail::spawned_thread_base* spawned_thread,+ const Executor& ex)+ : spawned_thread_(spawned_thread),+ executor_(ex),+ ec_(0)+ {+ }++ detail::spawned_thread_base* spawned_thread_;+ Executor executor_; asio::error_code* ec_;+#endif // !defined(GENERATING_DOCUMENTATION) }; -#if defined(GENERATING_DOCUMENTATION)-/// Context object that represents the currently executing coroutine.-typedef basic_yield_context<unspecified> yield_context;-#else // defined(GENERATING_DOCUMENTATION)-typedef basic_yield_context<- executor_binder<void(*)(), any_io_executor> > yield_context;-#endif // defined(GENERATING_DOCUMENTATION)+/// A @ref completion_token object that represents the currently executing+/// coroutine.+typedef basic_yield_context<any_io_executor> yield_context; /** * @defgroup spawn asio::spawn@@ -163,7 +345,7 @@ * library. This function enables programs to implement asynchronous logic in a * synchronous manner, as illustrated by the following example: *- * @code asio::spawn(my_strand, do_echo);+ * @code asio::spawn(my_strand, do_echo, asio::detached); * * // ... *@@ -190,13 +372,383 @@ */ /*@{*/ -/// Start a new stackful coroutine, calling the specified handler when it-/// completes.+/// Start a new stackful coroutine that executes on a given executor. /**+ * This function is used to launch a new stackful coroutine.+ *+ * @param ex Identifies the executor that will run the stackful coroutine.+ *+ * @param function The coroutine function. The function must be callable the+ * signature:+ * @code void function(basic_yield_context<Executor> yield); @endcode+ *+ * @param token The @ref completion_token that will handle the notification+ * that the coroutine has completed. If the return type @c R of @c function is+ * @c void, the function signature of the completion handler must be:+ *+ * @code void handler(std::exception_ptr); @endcode+ * Otherwise, the function signature of the completion handler must be:+ * @code void handler(std::exception_ptr, R); @endcode+ *+ * @par Completion Signature+ * @code void(std::exception_ptr, R) @endcode+ * where @c R is the return type of the function object.+ *+ * @par Per-Operation Cancellation+ * The new thread of execution is created with a cancellation state that+ * supports @c cancellation_type::terminal values only. To change the+ * cancellation state, call the basic_yield_context member function+ * @c reset_cancellation_state.+ */+template <typename Executor, typename F,+ ASIO_COMPLETION_TOKEN_FOR(typename detail::spawn_signature<+ typename result_of<F(basic_yield_context<Executor>)>::type>::type)+ CompletionToken ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(Executor)>+ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX(CompletionToken,+ typename detail::spawn_signature<+ typename result_of<F(basic_yield_context<Executor>)>::type>::type)+spawn(const Executor& ex, ASIO_MOVE_ARG(F) function,+ ASIO_MOVE_ARG(CompletionToken) token+ ASIO_DEFAULT_COMPLETION_TOKEN(Executor),+#if defined(ASIO_HAS_BOOST_COROUTINE)+ typename constraint<+ !is_same<+ typename decay<CompletionToken>::type,+ boost::coroutines::attributes+ >::value+ >::type = 0,+#endif // defined(ASIO_HAS_BOOST_COROUTINE)+ typename constraint<+ is_executor<Executor>::value || execution::is_executor<Executor>::value+ >::type = 0)+ ASIO_INITFN_AUTO_RESULT_TYPE_SUFFIX((+ async_initiate<CompletionToken,+ typename detail::spawn_signature<+ typename result_of<F(basic_yield_context<Executor>)>::type>::type>(+ declval<detail::initiate_spawn<Executor> >(),+ token, ASIO_MOVE_CAST(F)(function))));++/// Start a new stackful coroutine that executes on a given execution context.+/**+ * This function is used to launch a new stackful coroutine.+ *+ * @param ctx Identifies the execution context that will run the stackful+ * coroutine.+ *+ * @param function The coroutine function. The function must be callable the+ * signature:+ * @code void function(basic_yield_context<Executor> yield); @endcode+ *+ * @param token The @ref completion_token that will handle the notification+ * that the coroutine has completed. If the return type @c R of @c function is+ * @c void, the function signature of the completion handler must be:+ *+ * @code void handler(std::exception_ptr); @endcode+ * Otherwise, the function signature of the completion handler must be:+ * @code void handler(std::exception_ptr, R); @endcode+ *+ * @par Completion Signature+ * @code void(std::exception_ptr, R) @endcode+ * where @c R is the return type of the function object.+ *+ * @par Per-Operation Cancellation+ * The new thread of execution is created with a cancellation state that+ * supports @c cancellation_type::terminal values only. To change the+ * cancellation state, call the basic_yield_context member function+ * @c reset_cancellation_state.+ */+template <typename ExecutionContext, typename F,+ ASIO_COMPLETION_TOKEN_FOR(typename detail::spawn_signature<+ typename result_of<F(basic_yield_context<+ typename ExecutionContext::executor_type>)>::type>::type)+ CompletionToken ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(+ typename ExecutionContext::executor_type)>+ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX(CompletionToken,+ typename detail::spawn_signature<+ typename result_of<F(basic_yield_context<+ typename ExecutionContext::executor_type>)>::type>::type)+spawn(ExecutionContext& ctx, ASIO_MOVE_ARG(F) function,+ ASIO_MOVE_ARG(CompletionToken) token+ ASIO_DEFAULT_COMPLETION_TOKEN(+ typename ExecutionContext::executor_type),+#if defined(ASIO_HAS_BOOST_COROUTINE)+ typename constraint<+ !is_same<+ typename decay<CompletionToken>::type,+ boost::coroutines::attributes+ >::value+ >::type = 0,+#endif // defined(ASIO_HAS_BOOST_COROUTINE)+ typename constraint<+ is_convertible<ExecutionContext&, execution_context&>::value+ >::type = 0)+ ASIO_INITFN_AUTO_RESULT_TYPE_SUFFIX((+ async_initiate<CompletionToken,+ typename detail::spawn_signature<+ typename result_of<F(basic_yield_context<+ typename ExecutionContext::executor_type>)>::type>::type>(+ declval<detail::initiate_spawn<+ typename ExecutionContext::executor_type> >(),+ token, ASIO_MOVE_CAST(F)(function))));++/// Start a new stackful coroutine, inheriting the executor of another.+/**+ * This function is used to launch a new stackful coroutine.+ *+ * @param ctx Identifies the current coroutine as a parent of the new+ * coroutine. This specifies that the new coroutine should inherit the executor+ * of the parent. For example, if the parent coroutine is executing in a+ * particular strand, then the new coroutine will execute in the same strand.+ *+ * @param function The coroutine function. The function must be callable the+ * signature:+ * @code void function(basic_yield_context<Executor> yield); @endcode+ *+ * @param token The @ref completion_token that will handle the notification+ * that the coroutine has completed. If the return type @c R of @c function is+ * @c void, the function signature of the completion handler must be:+ *+ * @code void handler(std::exception_ptr); @endcode+ * Otherwise, the function signature of the completion handler must be:+ * @code void handler(std::exception_ptr, R); @endcode+ *+ * @par Completion Signature+ * @code void(std::exception_ptr, R) @endcode+ * where @c R is the return type of the function object.+ *+ * @par Per-Operation Cancellation+ * The new thread of execution is created with a cancellation state that+ * supports @c cancellation_type::terminal values only. To change the+ * cancellation state, call the basic_yield_context member function+ * @c reset_cancellation_state.+ */+template <typename Executor, typename F,+ ASIO_COMPLETION_TOKEN_FOR(typename detail::spawn_signature<+ typename result_of<F(basic_yield_context<Executor>)>::type>::type)+ CompletionToken ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(Executor)>+ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX(CompletionToken,+ typename detail::spawn_signature<+ typename result_of<F(basic_yield_context<Executor>)>::type>::type)+spawn(const basic_yield_context<Executor>& ctx,+ ASIO_MOVE_ARG(F) function,+ ASIO_MOVE_ARG(CompletionToken) token+ ASIO_DEFAULT_COMPLETION_TOKEN(Executor),+#if defined(ASIO_HAS_BOOST_COROUTINE)+ typename constraint<+ !is_same<+ typename decay<CompletionToken>::type,+ boost::coroutines::attributes+ >::value+ >::type = 0,+#endif // defined(ASIO_HAS_BOOST_COROUTINE)+ typename constraint<+ is_executor<Executor>::value || execution::is_executor<Executor>::value+ >::type = 0)+ ASIO_INITFN_AUTO_RESULT_TYPE_SUFFIX((+ async_initiate<CompletionToken,+ typename detail::spawn_signature<+ typename result_of<F(basic_yield_context<Executor>)>::type>::type>(+ declval<detail::initiate_spawn<Executor> >(),+ token, ASIO_MOVE_CAST(F)(function))));++#if defined(ASIO_HAS_BOOST_CONTEXT_FIBER) \+ || defined(GENERATING_DOCUMENTATION)++/// Start a new stackful coroutine that executes on a given executor.+/**+ * This function is used to launch a new stackful coroutine using the+ * specified stack allocator.+ *+ * @param ex Identifies the executor that will run the stackful coroutine.+ *+ * @param stack_allocator Denotes the allocator to be used to allocate the+ * underlying coroutine's stack. The type must satisfy the stack-allocator+ * concept defined by the Boost.Context library.+ *+ * @param function The coroutine function. The function must be callable the+ * signature:+ * @code void function(basic_yield_context<Executor> yield); @endcode+ *+ * @param token The @ref completion_token that will handle the notification+ * that the coroutine has completed. If the return type @c R of @c function is+ * @c void, the function signature of the completion handler must be:+ *+ * @code void handler(std::exception_ptr); @endcode+ * Otherwise, the function signature of the completion handler must be:+ * @code void handler(std::exception_ptr, R); @endcode+ *+ * @par Completion Signature+ * @code void(std::exception_ptr, R) @endcode+ * where @c R is the return type of the function object.+ *+ * @par Per-Operation Cancellation+ * The new thread of execution is created with a cancellation state that+ * supports @c cancellation_type::terminal values only. To change the+ * cancellation state, call the basic_yield_context member function+ * @c reset_cancellation_state.+ */+template <typename Executor, typename StackAllocator, typename F,+ ASIO_COMPLETION_TOKEN_FOR(typename detail::spawn_signature<+ typename result_of<F(basic_yield_context<Executor>)>::type>::type)+ CompletionToken ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(Executor)>+ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX(CompletionToken,+ typename detail::spawn_signature<+ typename result_of<F(basic_yield_context<Executor>)>::type>::type)+spawn(const Executor& ex, allocator_arg_t,+ ASIO_MOVE_ARG(StackAllocator) stack_allocator,+ ASIO_MOVE_ARG(F) function,+ ASIO_MOVE_ARG(CompletionToken) token+ ASIO_DEFAULT_COMPLETION_TOKEN(Executor),+ typename constraint<+ is_executor<Executor>::value || execution::is_executor<Executor>::value+ >::type = 0)+ ASIO_INITFN_AUTO_RESULT_TYPE_SUFFIX((+ async_initiate<CompletionToken,+ typename detail::spawn_signature<+ typename result_of<F(basic_yield_context<Executor>)>::type>::type>(+ declval<detail::initiate_spawn<Executor> >(),+ token, allocator_arg_t(),+ ASIO_MOVE_CAST(StackAllocator)(stack_allocator),+ ASIO_MOVE_CAST(F)(function))));++/// Start a new stackful coroutine that executes on a given execution context.+/**+ * This function is used to launch a new stackful coroutine.+ *+ * @param ctx Identifies the execution context that will run the stackful+ * coroutine.+ *+ * @param stack_allocator Denotes the allocator to be used to allocate the+ * underlying coroutine's stack. The type must satisfy the stack-allocator+ * concept defined by the Boost.Context library.+ *+ * @param function The coroutine function. The function must be callable the+ * signature:+ * @code void function(basic_yield_context<Executor> yield); @endcode+ *+ * @param token The @ref completion_token that will handle the notification+ * that the coroutine has completed. If the return type @c R of @c function is+ * @c void, the function signature of the completion handler must be:+ *+ * @code void handler(std::exception_ptr); @endcode+ * Otherwise, the function signature of the completion handler must be:+ * @code void handler(std::exception_ptr, R); @endcode+ *+ * @par Completion Signature+ * @code void(std::exception_ptr, R) @endcode+ * where @c R is the return type of the function object.+ *+ * @par Per-Operation Cancellation+ * The new thread of execution is created with a cancellation state that+ * supports @c cancellation_type::terminal values only. To change the+ * cancellation state, call the basic_yield_context member function+ * @c reset_cancellation_state.+ */+template <typename ExecutionContext, typename StackAllocator, typename F,+ ASIO_COMPLETION_TOKEN_FOR(typename detail::spawn_signature<+ typename result_of<F(basic_yield_context<+ typename ExecutionContext::executor_type>)>::type>::type)+ CompletionToken ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(+ typename ExecutionContext::executor_type)>+ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX(CompletionToken,+ typename detail::spawn_signature<+ typename result_of<F(basic_yield_context<+ typename ExecutionContext::executor_type>)>::type>::type)+spawn(ExecutionContext& ctx, allocator_arg_t,+ ASIO_MOVE_ARG(StackAllocator) stack_allocator,+ ASIO_MOVE_ARG(F) function,+ ASIO_MOVE_ARG(CompletionToken) token+ ASIO_DEFAULT_COMPLETION_TOKEN(+ typename ExecutionContext::executor_type),+ typename constraint<+ is_convertible<ExecutionContext&, execution_context&>::value+ >::type = 0)+ ASIO_INITFN_AUTO_RESULT_TYPE_SUFFIX((+ async_initiate<CompletionToken,+ typename detail::spawn_signature<+ typename result_of<F(basic_yield_context<+ typename ExecutionContext::executor_type>)>::type>::type>(+ declval<detail::initiate_spawn<+ typename ExecutionContext::executor_type> >(),+ token, allocator_arg_t(),+ ASIO_MOVE_CAST(StackAllocator)(stack_allocator),+ ASIO_MOVE_CAST(F)(function))));++/// Start a new stackful coroutine, inheriting the executor of another.+/**+ * This function is used to launch a new stackful coroutine using the+ * specified stack allocator.+ *+ * @param ctx Identifies the current coroutine as a parent of the new+ * coroutine. This specifies that the new coroutine should inherit the+ * executor of the parent. For example, if the parent coroutine is executing+ * in a particular strand, then the new coroutine will execute in the same+ * strand.+ *+ * @param stack_allocator Denotes the allocator to be used to allocate the+ * underlying coroutine's stack. The type must satisfy the stack-allocator+ * concept defined by the Boost.Context library.+ *+ * @param function The coroutine function. The function must be callable the+ * signature:+ * @code void function(basic_yield_context<Executor> yield); @endcode+ *+ * @param token The @ref completion_token that will handle the notification+ * that the coroutine has completed. If the return type @c R of @c function is+ * @c void, the function signature of the completion handler must be:+ *+ * @code void handler(std::exception_ptr); @endcode+ * Otherwise, the function signature of the completion handler must be:+ * @code void handler(std::exception_ptr, R); @endcode+ *+ * @par Completion Signature+ * @code void(std::exception_ptr, R) @endcode+ * where @c R is the return type of the function object.+ *+ * @par Per-Operation Cancellation+ * The new thread of execution is created with a cancellation state that+ * supports @c cancellation_type::terminal values only. To change the+ * cancellation state, call the basic_yield_context member function+ * @c reset_cancellation_state.+ */+template <typename Executor, typename StackAllocator, typename F,+ ASIO_COMPLETION_TOKEN_FOR(typename detail::spawn_signature<+ typename result_of<F(basic_yield_context<Executor>)>::type>::type)+ CompletionToken ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(Executor)>+ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX(CompletionToken,+ typename detail::spawn_signature<+ typename result_of<F(basic_yield_context<Executor>)>::type>::type)+spawn(const basic_yield_context<Executor>& ctx, allocator_arg_t,+ ASIO_MOVE_ARG(StackAllocator) stack_allocator,+ ASIO_MOVE_ARG(F) function,+ ASIO_MOVE_ARG(CompletionToken) token+ ASIO_DEFAULT_COMPLETION_TOKEN(Executor),+ typename constraint<+ is_executor<Executor>::value || execution::is_executor<Executor>::value+ >::type = 0)+ASIO_INITFN_AUTO_RESULT_TYPE_SUFFIX((+ async_initiate<CompletionToken,+ typename detail::spawn_signature<+ typename result_of<F(basic_yield_context<Executor>)>::type>::type>(+ declval<detail::initiate_spawn<Executor> >(),+ token, allocator_arg_t(),+ ASIO_MOVE_CAST(StackAllocator)(stack_allocator),+ ASIO_MOVE_CAST(F)(function))));++#endif // defined(ASIO_HAS_BOOST_CONTEXT_FIBER)+ // || defined(GENERATING_DOCUMENTATION)++#if defined(ASIO_HAS_BOOST_COROUTINE) \+ || defined(GENERATING_DOCUMENTATION)++/// (Deprecated: Use overloads with a completion token.) Start a new stackful+/// coroutine, calling the specified handler when it completes.+/** * This function is used to launch a new coroutine. * * @param function The coroutine function. The function must have the signature:- * @code void function(basic_yield_context<Handler> yield); @endcode+ * @code void function(basic_yield_context<Executor> yield); @endcode+ * where Executor is the associated executor type of @c Function. * * @param attributes Boost.Coroutine attributes used to customise the coroutine. */@@ -205,8 +757,8 @@ const boost::coroutines::attributes& attributes = boost::coroutines::attributes()); -/// Start a new stackful coroutine, calling the specified handler when it-/// completes.+/// (Deprecated: Use overloads with a completion token.) Start a new stackful+/// coroutine, calling the specified handler when it completes. /** * This function is used to launch a new coroutine. *@@ -216,7 +768,8 @@ * @code void handler(); @endcode * * @param function The coroutine function. The function must have the signature:- * @code void function(basic_yield_context<Handler> yield); @endcode+ * @code void function(basic_yield_context<Executor> yield); @endcode+ * where Executor is the associated executor type of @c Handler. * * @param attributes Boost.Coroutine attributes used to customise the coroutine. */@@ -225,12 +778,13 @@ ASIO_MOVE_ARG(Function) function, const boost::coroutines::attributes& attributes = boost::coroutines::attributes(),- typename enable_if<+ typename constraint< !is_executor<typename decay<Handler>::type>::value && !execution::is_executor<typename decay<Handler>::type>::value &&- !is_convertible<Handler&, execution_context&>::value>::type* = 0);+ !is_convertible<Handler&, execution_context&>::value>::type = 0); -/// Start a new stackful coroutine, inheriting the execution context of another.+/// (Deprecated: Use overloads with a completion token.) Start a new stackful+/// coroutine, inheriting the execution context of another. /** * This function is used to launch a new coroutine. *@@ -241,22 +795,24 @@ * same strand. * * @param function The coroutine function. The function must have the signature:- * @code void function(basic_yield_context<Handler> yield); @endcode+ * @code void function(basic_yield_context<Executor> yield); @endcode * * @param attributes Boost.Coroutine attributes used to customise the coroutine. */-template <typename Handler, typename Function>-void spawn(basic_yield_context<Handler> ctx,+template <typename Executor, typename Function>+void spawn(basic_yield_context<Executor> ctx, ASIO_MOVE_ARG(Function) function, const boost::coroutines::attributes& attributes = boost::coroutines::attributes()); -/// Start a new stackful coroutine that executes on a given executor.+/// (Deprecated: Use overloads with a completion token.) Start a new stackful+/// coroutine that executes on a given executor. /** * This function is used to launch a new coroutine. * * @param ex Identifies the executor that will run the coroutine. The new- * coroutine is implicitly given its own strand within this executor.+ * coroutine is automatically given its own explicit strand within this+ * executor. * * @param function The coroutine function. The function must have the signature: * @code void function(yield_context yield); @endcode@@ -268,11 +824,12 @@ ASIO_MOVE_ARG(Function) function, const boost::coroutines::attributes& attributes = boost::coroutines::attributes(),- typename enable_if<+ typename constraint< is_executor<Executor>::value || execution::is_executor<Executor>::value- >::type* = 0);+ >::type = 0); -/// Start a new stackful coroutine that executes on a given strand.+/// (Deprecated: Use overloads with a completion token.) Start a new stackful+/// coroutine that executes on a given strand. /** * This function is used to launch a new coroutine. *@@ -291,7 +848,8 @@ #if !defined(ASIO_NO_TS_EXECUTORS) -/// Start a new stackful coroutine that executes in the context of a strand.+/// (Deprecated: Use overloads with a completion token.) Start a new stackful+/// coroutine that executes in the context of a strand. /** * This function is used to launch a new coroutine. *@@ -312,7 +870,8 @@ #endif // !defined(ASIO_NO_TS_EXECUTORS) -/// Start a new stackful coroutine that executes on a given execution context.+/// (Deprecated: Use overloads with a completion token.) Start a new stackful+/// coroutine that executes on a given execution context. /** * This function is used to launch a new coroutine. *@@ -330,8 +889,11 @@ ASIO_MOVE_ARG(Function) function, const boost::coroutines::attributes& attributes = boost::coroutines::attributes(),- typename enable_if<is_convertible<- ExecutionContext&, execution_context&>::value>::type* = 0);+ typename constraint<is_convertible<+ ExecutionContext&, execution_context&>::value>::type = 0);++#endif // defined(ASIO_HAS_BOOST_COROUTINE)+ // || defined(GENERATING_DOCUMENTATION) /*@}*/
link/modules/asio-standalone/asio/include/asio/ssl.hpp view
@@ -2,7 +2,7 @@ // ssl.hpp // ~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/ssl/context.hpp view
@@ -2,7 +2,7 @@ // ssl/context.hpp // ~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -740,6 +740,9 @@ // Helper function to make a BIO from a memory buffer. ASIO_DECL BIO* make_buffer_bio(const const_buffer& b);++ // Translate an SSL error into an error code.+ ASIO_DECL static asio::error_code translate_error(long error); // The underlying native implementation. native_handle_type handle_;
link/modules/asio-standalone/asio/include/asio/ssl/context_base.hpp view
@@ -2,7 +2,7 @@ // ssl/context_base.hpp // ~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -105,60 +105,60 @@ }; /// Bitmask type for SSL options.- typedef long options;+ typedef uint64_t options; #if defined(GENERATING_DOCUMENTATION) /// Implement various bug workarounds.- static const long default_workarounds = implementation_defined;+ static const uint64_t default_workarounds = implementation_defined; /// Always create a new key when using tmp_dh parameters.- static const long single_dh_use = implementation_defined;+ static const uint64_t single_dh_use = implementation_defined; /// Disable SSL v2.- static const long no_sslv2 = implementation_defined;+ static const uint64_t no_sslv2 = implementation_defined; /// Disable SSL v3.- static const long no_sslv3 = implementation_defined;+ static const uint64_t no_sslv3 = implementation_defined; /// Disable TLS v1.- static const long no_tlsv1 = implementation_defined;+ static const uint64_t no_tlsv1 = implementation_defined; /// Disable TLS v1.1.- static const long no_tlsv1_1 = implementation_defined;+ static const uint64_t no_tlsv1_1 = implementation_defined; /// Disable TLS v1.2.- static const long no_tlsv1_2 = implementation_defined;+ static const uint64_t no_tlsv1_2 = implementation_defined; /// Disable TLS v1.3.- static const long no_tlsv1_3 = implementation_defined;+ static const uint64_t no_tlsv1_3 = implementation_defined; /// Disable compression. Compression is disabled by default.- static const long no_compression = implementation_defined;+ static const uint64_t no_compression = implementation_defined; #else- ASIO_STATIC_CONSTANT(long, default_workarounds = SSL_OP_ALL);- ASIO_STATIC_CONSTANT(long, single_dh_use = SSL_OP_SINGLE_DH_USE);- ASIO_STATIC_CONSTANT(long, no_sslv2 = SSL_OP_NO_SSLv2);- ASIO_STATIC_CONSTANT(long, no_sslv3 = SSL_OP_NO_SSLv3);- ASIO_STATIC_CONSTANT(long, no_tlsv1 = SSL_OP_NO_TLSv1);+ ASIO_STATIC_CONSTANT(uint64_t, default_workarounds = SSL_OP_ALL);+ ASIO_STATIC_CONSTANT(uint64_t, single_dh_use = SSL_OP_SINGLE_DH_USE);+ ASIO_STATIC_CONSTANT(uint64_t, no_sslv2 = SSL_OP_NO_SSLv2);+ ASIO_STATIC_CONSTANT(uint64_t, no_sslv3 = SSL_OP_NO_SSLv3);+ ASIO_STATIC_CONSTANT(uint64_t, no_tlsv1 = SSL_OP_NO_TLSv1); # if defined(SSL_OP_NO_TLSv1_1)- ASIO_STATIC_CONSTANT(long, no_tlsv1_1 = SSL_OP_NO_TLSv1_1);+ ASIO_STATIC_CONSTANT(uint64_t, no_tlsv1_1 = SSL_OP_NO_TLSv1_1); # else // defined(SSL_OP_NO_TLSv1_1)- ASIO_STATIC_CONSTANT(long, no_tlsv1_1 = 0x10000000L);+ ASIO_STATIC_CONSTANT(uint64_t, no_tlsv1_1 = 0x10000000L); # endif // defined(SSL_OP_NO_TLSv1_1) # if defined(SSL_OP_NO_TLSv1_2)- ASIO_STATIC_CONSTANT(long, no_tlsv1_2 = SSL_OP_NO_TLSv1_2);+ ASIO_STATIC_CONSTANT(uint64_t, no_tlsv1_2 = SSL_OP_NO_TLSv1_2); # else // defined(SSL_OP_NO_TLSv1_2)- ASIO_STATIC_CONSTANT(long, no_tlsv1_2 = 0x08000000L);+ ASIO_STATIC_CONSTANT(uint64_t, no_tlsv1_2 = 0x08000000L); # endif // defined(SSL_OP_NO_TLSv1_2) # if defined(SSL_OP_NO_TLSv1_3)- ASIO_STATIC_CONSTANT(long, no_tlsv1_3 = SSL_OP_NO_TLSv1_3);+ ASIO_STATIC_CONSTANT(uint64_t, no_tlsv1_3 = SSL_OP_NO_TLSv1_3); # else // defined(SSL_OP_NO_TLSv1_3)- ASIO_STATIC_CONSTANT(long, no_tlsv1_3 = 0x20000000L);+ ASIO_STATIC_CONSTANT(uint64_t, no_tlsv1_3 = 0x20000000L); # endif // defined(SSL_OP_NO_TLSv1_3) # if defined(SSL_OP_NO_COMPRESSION)- ASIO_STATIC_CONSTANT(long, no_compression = SSL_OP_NO_COMPRESSION);+ ASIO_STATIC_CONSTANT(uint64_t, no_compression = SSL_OP_NO_COMPRESSION); # else // defined(SSL_OP_NO_COMPRESSION)- ASIO_STATIC_CONSTANT(long, no_compression = 0x20000L);+ ASIO_STATIC_CONSTANT(uint64_t, no_compression = 0x20000L); # endif // defined(SSL_OP_NO_COMPRESSION) #endif
link/modules/asio-standalone/asio/include/asio/ssl/detail/buffered_handshake_op.hpp view
@@ -2,7 +2,7 @@ // ssl/detail/buffered_handshake_op.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -56,7 +56,7 @@ const asio::error_code& ec, const std::size_t& bytes_transferred) const {- handler(ec, bytes_transferred);+ ASIO_MOVE_OR_LVALUE(Handler)(handler)(ec, bytes_transferred); } private:
link/modules/asio-standalone/asio/include/asio/ssl/detail/engine.hpp view
@@ -2,7 +2,7 @@ // ssl/detail/engine.hpp // ~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -58,6 +58,9 @@ // Construct a new engine for the specified context. ASIO_DECL explicit engine(SSL_CTX* context); + // Construct a new engine for an existing native SSL implementation.+ ASIO_DECL explicit engine(SSL* ssl_impl);+ #if defined(ASIO_HAS_MOVE) // Move construct from another engine. ASIO_DECL engine(engine&& other) ASIO_NOEXCEPT;@@ -65,6 +68,11 @@ // Destructor. ASIO_DECL ~engine();++#if defined(ASIO_HAS_MOVE)+ // Move assign from another engine.+ ASIO_DECL engine& operator=(engine&& other) ASIO_NOEXCEPT;+#endif // defined(ASIO_HAS_MOVE) // Get the underlying implementation in the native type. ASIO_DECL SSL* native_handle();
link/modules/asio-standalone/asio/include/asio/ssl/detail/handshake_op.hpp view
@@ -2,7 +2,7 @@ // ssl/detail/handshake_op.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -51,7 +51,7 @@ const asio::error_code& ec, const std::size_t&) const {- handler(ec);+ ASIO_MOVE_OR_LVALUE(Handler)(handler)(ec); } private:
link/modules/asio-standalone/asio/include/asio/ssl/detail/impl/engine.ipp view
@@ -2,7 +2,7 @@ // ssl/detail/impl/engine.ipp // ~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -55,6 +55,24 @@ ::SSL_set_bio(ssl_, int_bio, int_bio); } +engine::engine(SSL* ssl_impl)+ : ssl_(ssl_impl)+{+#if (OPENSSL_VERSION_NUMBER < 0x10000000L)+ accept_mutex().init();+#endif // (OPENSSL_VERSION_NUMBER < 0x10000000L)++ ::SSL_set_mode(ssl_, SSL_MODE_ENABLE_PARTIAL_WRITE);+ ::SSL_set_mode(ssl_, SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER);+#if defined(SSL_MODE_RELEASE_BUFFERS)+ ::SSL_set_mode(ssl_, SSL_MODE_RELEASE_BUFFERS);+#endif // defined(SSL_MODE_RELEASE_BUFFERS)++ ::BIO* int_bio = 0;+ ::BIO_new_bio_pair(&int_bio, 0, &ext_bio_, 0);+ ::SSL_set_bio(ssl_, int_bio, int_bio);+}+ #if defined(ASIO_HAS_MOVE) engine::engine(engine&& other) ASIO_NOEXCEPT : ssl_(other.ssl_),@@ -79,6 +97,20 @@ if (ssl_) ::SSL_free(ssl_); }++#if defined(ASIO_HAS_MOVE)+engine& engine::operator=(engine&& other) ASIO_NOEXCEPT+{+ if (this != &other)+ {+ ssl_ = other.ssl_;+ ext_bio_ = other.ext_bio_;+ other.ssl_ = 0;+ other.ext_bio_ = 0;+ }+ return *this;+}+#endif // defined(ASIO_HAS_MOVE) SSL* engine::native_handle() {
link/modules/asio-standalone/asio/include/asio/ssl/detail/impl/openssl_init.ipp view
@@ -3,7 +3,7 @@ // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // // Copyright (c) 2005 Voipster / Indrek dot Juhani at voipster dot com-// Copyright (c) 2005-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2005-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -85,9 +85,13 @@ #endif // (OPENSSL_VERSION_NUMBER >= 0x10002000L) // && (OPENSSL_VERSION_NUMBER < 0x10100000L) // && !defined(SSL_OP_NO_COMPRESSION)-#if !defined(OPENSSL_IS_BORINGSSL) && !defined(ASIO_USE_WOLFSSL)+#if !defined(OPENSSL_IS_BORINGSSL) \+ && !defined(ASIO_USE_WOLFSSL) \+ && (OPENSSL_VERSION_NUMBER < 0x30000000L) ::CONF_modules_unload(1);-#endif // !defined(OPENSSL_IS_BORINGSSL) && !defined(ASIO_USE_WOLFSSL)+#endif // !defined(OPENSSL_IS_BORINGSSL)+ // && !defined(ASIO_USE_WOLFSSL)+ // && (OPENSSL_VERSION_NUMBER < 0x30000000L) #if !defined(OPENSSL_NO_ENGINE) \ && (OPENSSL_VERSION_NUMBER < 0x10100000L) ::ENGINE_cleanup();
link/modules/asio-standalone/asio/include/asio/ssl/detail/io.hpp view
@@ -2,7 +2,7 @@ // ssl/detail/io.hpp // ~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -17,6 +17,7 @@ #include "asio/detail/config.hpp" +#include "asio/detail/base_from_cancellation_state.hpp" #include "asio/detail/handler_tracking.hpp" #include "asio/ssl/detail/engine.hpp" #include "asio/ssl/detail/stream_core.hpp"@@ -94,11 +95,13 @@ template <typename Stream, typename Operation, typename Handler> class io_op+ : public asio::detail::base_from_cancellation_state<Handler> { public: io_op(Stream& next_layer, stream_core& core, const Operation& op, Handler& handler)- : next_layer_(next_layer),+ : asio::detail::base_from_cancellation_state<Handler>(handler),+ next_layer_(next_layer), core_(core), op_(op), start_(0),@@ -110,7 +113,8 @@ #if defined(ASIO_HAS_MOVE) io_op(const io_op& other)- : next_layer_(other.next_layer_),+ : asio::detail::base_from_cancellation_state<Handler>(other),+ next_layer_(other.next_layer_), core_(other.core_), op_(other.op_), start_(other.start_),@@ -122,7 +126,11 @@ } io_op(io_op&& other)- : next_layer_(other.next_layer_),+ : asio::detail::base_from_cancellation_state<Handler>(+ ASIO_MOVE_CAST(+ asio::detail::base_from_cancellation_state<Handler>)(+ other)),+ next_layer_(other.next_layer_), core_(other.core_), op_(ASIO_MOVE_CAST(Operation)(other.op_)), start_(other.start_),@@ -262,6 +270,13 @@ // Release any waiting read operations. core_.pending_read_.expires_at(core_.neg_infin()); + // Check for cancellation before continuing.+ if (this->cancelled() != cancellation_type::none)+ {+ ec_ = asio::error::operation_aborted;+ break;+ }+ // Try the operation again. continue; @@ -270,6 +285,13 @@ // Release any waiting write operations. core_.pending_write_.expires_at(core_.neg_infin()); + // Check for cancellation before continuing.+ if (this->cancelled() != cancellation_type::none)+ {+ ec_ = asio::error::operation_aborted;+ break;+ }+ // Try the operation again. continue; @@ -380,31 +402,29 @@ } // namespace detail } // namespace ssl -template <typename Stream, typename Operation,- typename Handler, typename Allocator>-struct associated_allocator<- ssl::detail::io_op<Stream, Operation, Handler>, Allocator>+template <template <typename, typename> class Associator,+ typename Stream, typename Operation,+ typename Handler, typename DefaultCandidate>+struct associator<Associator,+ ssl::detail::io_op<Stream, Operation, Handler>,+ DefaultCandidate>+ : Associator<Handler, DefaultCandidate> {- typedef typename associated_allocator<Handler, Allocator>::type type;-- static type get(const ssl::detail::io_op<Stream, Operation, Handler>& h,- const Allocator& a = Allocator()) ASIO_NOEXCEPT+ static typename Associator<Handler, DefaultCandidate>::type+ get(const ssl::detail::io_op<Stream, Operation, Handler>& h)+ ASIO_NOEXCEPT {- return associated_allocator<Handler, Allocator>::get(h.handler_, a);+ return Associator<Handler, DefaultCandidate>::get(h.handler_); }-}; -template <typename Stream, typename Operation,- typename Handler, typename Executor>-struct associated_executor<- ssl::detail::io_op<Stream, Operation, Handler>, Executor>-{- typedef typename associated_executor<Handler, Executor>::type type;-- static type get(const ssl::detail::io_op<Stream, Operation, Handler>& h,- const Executor& ex = Executor()) ASIO_NOEXCEPT+ static ASIO_AUTO_RETURN_TYPE_PREFIX2(+ typename Associator<Handler, DefaultCandidate>::type)+ get(const ssl::detail::io_op<Stream, Operation, Handler>& h,+ const DefaultCandidate& c) ASIO_NOEXCEPT+ ASIO_AUTO_RETURN_TYPE_SUFFIX((+ Associator<Handler, DefaultCandidate>::get(h.handler_, c))) {- return associated_executor<Handler, Executor>::get(h.handler_, ex);+ return Associator<Handler, DefaultCandidate>::get(h.handler_, c); } };
link/modules/asio-standalone/asio/include/asio/ssl/detail/openssl_init.hpp view
@@ -2,7 +2,7 @@ // ssl/detail/openssl_init.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/ssl/detail/openssl_types.hpp view
@@ -2,7 +2,7 @@ // ssl/detail/openssl_types.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/ssl/detail/password_callback.hpp view
@@ -2,7 +2,7 @@ // ssl/detail/password_callback.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/ssl/detail/read_op.hpp view
@@ -2,7 +2,7 @@ // ssl/detail/read_op.hpp // ~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -56,7 +56,7 @@ const asio::error_code& ec, const std::size_t& bytes_transferred) const {- handler(ec, bytes_transferred);+ ASIO_MOVE_OR_LVALUE(Handler)(handler)(ec, bytes_transferred); } private:
link/modules/asio-standalone/asio/include/asio/ssl/detail/shutdown_op.hpp view
@@ -2,7 +2,7 @@ // ssl/detail/shutdown_op.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -51,11 +51,11 @@ // The engine only generates an eof when the shutdown notification has // been received from the peer. This indicates that the shutdown has // completed successfully, and thus need not be passed on to the handler.- handler(asio::error_code());+ ASIO_MOVE_OR_LVALUE(Handler)(handler)(asio::error_code()); } else {- handler(ec);+ ASIO_MOVE_OR_LVALUE(Handler)(handler)(ec); } } };
link/modules/asio-standalone/asio/include/asio/ssl/detail/stream_core.hpp view
@@ -2,7 +2,7 @@ // ssl/detail/stream_core.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -51,6 +51,20 @@ pending_write_.expires_at(neg_infin()); } + template <typename Executor>+ stream_core(SSL* ssl_impl, const Executor& ex)+ : engine_(ssl_impl),+ pending_read_(ex),+ pending_write_(ex),+ output_buffer_space_(max_tls_record_size),+ output_buffer_(asio::buffer(output_buffer_space_)),+ input_buffer_space_(max_tls_record_size),+ input_buffer_(asio::buffer(input_buffer_space_))+ {+ pending_read_.expires_at(neg_infin());+ pending_write_.expires_at(neg_infin());+ }+ #if defined(ASIO_HAS_MOVE) stream_core(stream_core&& other) : engine_(ASIO_MOVE_CAST(engine)(other.engine_)),@@ -88,6 +102,44 @@ ~stream_core() { }++#if defined(ASIO_HAS_MOVE)+ stream_core& operator=(stream_core&& other)+ {+ if (this != &other)+ {+ engine_ = ASIO_MOVE_CAST(engine)(other.engine_);+#if defined(ASIO_HAS_BOOST_DATE_TIME)+ pending_read_ =+ ASIO_MOVE_CAST(asio::deadline_timer)(+ other.pending_read_);+ pending_write_ =+ ASIO_MOVE_CAST(asio::deadline_timer)(+ other.pending_write_);+#else // defined(ASIO_HAS_BOOST_DATE_TIME)+ pending_read_ =+ ASIO_MOVE_CAST(asio::steady_timer)(+ other.pending_read_);+ pending_write_ =+ ASIO_MOVE_CAST(asio::steady_timer)(+ other.pending_write_);+#endif // defined(ASIO_HAS_BOOST_DATE_TIME)+ output_buffer_space_ =+ ASIO_MOVE_CAST(std::vector<unsigned char>)(+ other.output_buffer_space_);+ output_buffer_ = other.output_buffer_;+ input_buffer_space_ =+ ASIO_MOVE_CAST(std::vector<unsigned char>)(+ other.input_buffer_space_);+ input_buffer_ = other.input_buffer_;+ input_ = other.input_;+ other.output_buffer_ = asio::mutable_buffer(0, 0);+ other.input_buffer_ = asio::mutable_buffer(0, 0);+ other.input_ = asio::const_buffer(0, 0);+ }+ return *this;+ }+#endif // defined(ASIO_HAS_MOVE) // The SSL engine. engine engine_;
link/modules/asio-standalone/asio/include/asio/ssl/detail/verify_callback.hpp view
@@ -2,7 +2,7 @@ // ssl/detail/verify_callback.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/ssl/detail/write_op.hpp view
@@ -2,7 +2,7 @@ // ssl/detail/write_op.hpp // ~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -60,7 +60,7 @@ const asio::error_code& ec, const std::size_t& bytes_transferred) const {- handler(ec, bytes_transferred);+ ASIO_MOVE_OR_LVALUE(Handler)(handler)(ec, bytes_transferred); } private:
link/modules/asio-standalone/asio/include/asio/ssl/error.hpp view
@@ -2,7 +2,7 @@ // ssl/error.hpp // ~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/ssl/host_name_verification.hpp view
@@ -2,7 +2,7 @@ // ssl/host_name_verification.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/ssl/impl/context.hpp view
@@ -3,7 +3,7 @@ // ~~~~~~~~~~~~~~~~~~~~ // // Copyright (c) 2005 Voipster / Indrek dot Juhani at voipster dot com-// Copyright (c) 2005-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2005-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/ssl/impl/context.ipp view
@@ -3,7 +3,7 @@ // ~~~~~~~~~~~~~~~~~~~~ // // Copyright (c) 2005 Voipster / Indrek dot Juhani at voipster dot com-// Copyright (c) 2005-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2005-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -47,6 +47,7 @@ ~evp_pkey_cleanup() { if (p) ::EVP_PKEY_free(p); } }; +#if (OPENSSL_VERSION_NUMBER < 0x30000000L) struct context::rsa_cleanup { RSA* p;@@ -58,6 +59,7 @@ DH* p; ~dh_cleanup() { if (p) ::DH_free(p); } };+#endif // (OPENSSL_VERSION_NUMBER < 0x30000000L) context::context(context::method m) : handle_(0)@@ -357,9 +359,7 @@ if (handle_ == 0) {- asio::error_code ec(- static_cast<int>(::ERR_get_error()),- asio::error::get_ssl_category());+ asio::error_code ec = translate_error(::ERR_get_error()); asio::detail::throw_error(ec, "context"); } @@ -397,7 +397,8 @@ if (handle_) { #if ((OPENSSL_VERSION_NUMBER >= 0x10100000L) \- && !defined(LIBRESSL_VERSION_NUMBER)) \+ && (!defined(LIBRESSL_VERSION_NUMBER) \+ || LIBRESSL_VERSION_NUMBER >= 0x2070000fL)) \ || defined(ASIO_USE_WOLFSSL) void* cb_userdata = ::SSL_CTX_get_default_passwd_cb_userdata(handle_); #else // (OPENSSL_VERSION_NUMBER >= 0x10100000L)@@ -410,7 +411,8 @@ cb_userdata); delete callback; #if ((OPENSSL_VERSION_NUMBER >= 0x10100000L) \- && !defined(LIBRESSL_VERSION_NUMBER)) \+ && (!defined(LIBRESSL_VERSION_NUMBER) \+ || LIBRESSL_VERSION_NUMBER >= 0x2070000fL)) \ || defined(ASIO_USE_WOLFSSL) ::SSL_CTX_set_default_passwd_cb_userdata(handle_, 0); #else // (OPENSSL_VERSION_NUMBER >= 0x10100000L)@@ -543,9 +545,7 @@ if (::SSL_CTX_load_verify_locations(handle_, filename.c_str(), 0) != 1) {- ec = asio::error_code(- static_cast<int>(::ERR_get_error()),- asio::error::get_ssl_category());+ ec = translate_error(::ERR_get_error()); ASIO_SYNC_OP_VOID_RETURN(ec); } @@ -580,17 +580,13 @@ && ERR_GET_REASON(err) == PEM_R_NO_START_LINE) break; - ec = asio::error_code(- static_cast<int>(err),- asio::error::get_ssl_category());+ ec = translate_error(err); ASIO_SYNC_OP_VOID_RETURN(ec); } if (::X509_STORE_add_cert(store, cert.p) != 1) {- ec = asio::error_code(- static_cast<int>(::ERR_get_error()),- asio::error::get_ssl_category());+ ec = translate_error(::ERR_get_error()); ASIO_SYNC_OP_VOID_RETURN(ec); } }@@ -615,9 +611,7 @@ if (::SSL_CTX_set_default_verify_paths(handle_) != 1) {- ec = asio::error_code(- static_cast<int>(::ERR_get_error()),- asio::error::get_ssl_category());+ ec = translate_error(::ERR_get_error()); ASIO_SYNC_OP_VOID_RETURN(ec); } @@ -639,9 +633,7 @@ if (::SSL_CTX_load_verify_locations(handle_, 0, path.c_str()) != 1) {- ec = asio::error_code(- static_cast<int>(::ERR_get_error()),- asio::error::get_ssl_category());+ ec = translate_error(::ERR_get_error()); ASIO_SYNC_OP_VOID_RETURN(ec); } @@ -695,9 +687,7 @@ ASIO_SYNC_OP_VOID_RETURN(ec); } - ec = asio::error_code(- static_cast<int>(::ERR_get_error()),- asio::error::get_ssl_category());+ ec = translate_error(::ERR_get_error()); ASIO_SYNC_OP_VOID_RETURN(ec); } @@ -733,9 +723,7 @@ if (::SSL_CTX_use_certificate_file(handle_, filename.c_str(), file_type) != 1) {- ec = asio::error_code(- static_cast<int>(::ERR_get_error()),- asio::error::get_ssl_category());+ ec = translate_error(::ERR_get_error()); ASIO_SYNC_OP_VOID_RETURN(ec); } @@ -759,7 +747,8 @@ if (bio.p) { #if ((OPENSSL_VERSION_NUMBER >= 0x10100000L) \- && !defined(LIBRESSL_VERSION_NUMBER)) \+ && (!defined(LIBRESSL_VERSION_NUMBER) \+ || LIBRESSL_VERSION_NUMBER >= 0x2070000fL)) \ || defined(ASIO_USE_WOLFSSL) pem_password_cb* callback = ::SSL_CTX_get_default_passwd_cb(handle_); void* cb_userdata = ::SSL_CTX_get_default_passwd_cb_userdata(handle_);@@ -773,22 +762,20 @@ cb_userdata) }; if (!cert.p) {- ec = asio::error_code(ERR_R_PEM_LIB,- asio::error::get_ssl_category());+ ec = translate_error(ERR_R_PEM_LIB); ASIO_SYNC_OP_VOID_RETURN(ec); } int result = ::SSL_CTX_use_certificate(handle_, cert.p); if (result == 0 || ::ERR_peek_error() != 0) {- ec = asio::error_code(- static_cast<int>(::ERR_get_error()),- asio::error::get_ssl_category());+ ec = translate_error(::ERR_get_error()); ASIO_SYNC_OP_VOID_RETURN(ec); } #if ((OPENSSL_VERSION_NUMBER >= 0x10002000L) \- && !defined(LIBRESSL_VERSION_NUMBER)) \+ && (!defined(LIBRESSL_VERSION_NUMBER) \+ || LIBRESSL_VERSION_NUMBER >= 0x2090100fL)) \ || defined(ASIO_USE_WOLFSSL) ::SSL_CTX_clear_chain_certs(handle_); #else@@ -805,9 +792,7 @@ { if (!::SSL_CTX_add_extra_chain_cert(handle_, cacert)) {- ec = asio::error_code(- static_cast<int>(::ERR_get_error()),- asio::error::get_ssl_category());+ ec = translate_error(::ERR_get_error()); ASIO_SYNC_OP_VOID_RETURN(ec); } }@@ -822,9 +807,7 @@ } } - ec = asio::error_code(- static_cast<int>(::ERR_get_error()),- asio::error::get_ssl_category());+ ec = translate_error(::ERR_get_error()); ASIO_SYNC_OP_VOID_RETURN(ec); } @@ -842,9 +825,7 @@ if (::SSL_CTX_use_certificate_chain_file(handle_, filename.c_str()) != 1) {- ec = asio::error_code(- static_cast<int>(::ERR_get_error()),- asio::error::get_ssl_category());+ ec = translate_error(::ERR_get_error()); ASIO_SYNC_OP_VOID_RETURN(ec); } @@ -867,7 +848,8 @@ ::ERR_clear_error(); #if ((OPENSSL_VERSION_NUMBER >= 0x10100000L) \- && !defined(LIBRESSL_VERSION_NUMBER)) \+ && (!defined(LIBRESSL_VERSION_NUMBER) \+ || LIBRESSL_VERSION_NUMBER >= 0x2070000fL)) \ || defined(ASIO_USE_WOLFSSL) pem_password_cb* callback = ::SSL_CTX_get_default_passwd_cb(handle_); void* cb_userdata = ::SSL_CTX_get_default_passwd_cb_userdata(handle_);@@ -907,9 +889,7 @@ } } - ec = asio::error_code(- static_cast<int>(::ERR_get_error()),- asio::error::get_ssl_category());+ ec = translate_error(::ERR_get_error()); ASIO_SYNC_OP_VOID_RETURN(ec); } @@ -936,18 +916,54 @@ ::ERR_clear_error(); #if ((OPENSSL_VERSION_NUMBER >= 0x10100000L) \- && !defined(LIBRESSL_VERSION_NUMBER)) \+ && (!defined(LIBRESSL_VERSION_NUMBER) \+ || LIBRESSL_VERSION_NUMBER >= 0x2070000fL)) \ || defined(ASIO_USE_WOLFSSL)- pem_password_cb* callback = ::SSL_CTX_get_default_passwd_cb(handle_);- void* cb_userdata = ::SSL_CTX_get_default_passwd_cb_userdata(handle_);+ pem_password_cb* callback = ::SSL_CTX_get_default_passwd_cb(handle_);+ void* cb_userdata = ::SSL_CTX_get_default_passwd_cb_userdata(handle_); #else // (OPENSSL_VERSION_NUMBER >= 0x10100000L)- pem_password_cb* callback = handle_->default_passwd_callback;- void* cb_userdata = handle_->default_passwd_callback_userdata;+ pem_password_cb* callback = handle_->default_passwd_callback;+ void* cb_userdata = handle_->default_passwd_callback_userdata; #endif // (OPENSSL_VERSION_NUMBER >= 0x10100000L) bio_cleanup bio = { make_buffer_bio(private_key) }; if (bio.p) {+#if (OPENSSL_VERSION_NUMBER >= 0x30000000L)+ evp_pkey_cleanup evp_private_key = { 0 };+ switch (format)+ {+ case context_base::asn1:+ evp_private_key.p = ::d2i_PrivateKey_bio(bio.p, 0);+ break;+ case context_base::pem:+ evp_private_key.p = ::PEM_read_bio_PrivateKey(+ bio.p, 0, callback,+ cb_userdata);+ break;+ default:+ {+ ec = asio::error::invalid_argument;+ ASIO_SYNC_OP_VOID_RETURN(ec);+ }+ }++ if (evp_private_key.p)+ {+ if (::EVP_PKEY_is_a(evp_private_key.p, "RSA") == 0)+ {+ ec = translate_error(+ ERR_PACK(ERR_LIB_EVP, 0, EVP_R_EXPECTING_AN_RSA_KEY));+ ASIO_SYNC_OP_VOID_RETURN(ec);+ }++ if (::SSL_CTX_use_PrivateKey(handle_, evp_private_key.p) == 1)+ {+ ec = asio::error_code();+ ASIO_SYNC_OP_VOID_RETURN(ec);+ }+ }+#else // (OPENSSL_VERSION_NUMBER >= 0x30000000L) rsa_cleanup rsa_private_key = { 0 }; switch (format) {@@ -974,11 +990,10 @@ ASIO_SYNC_OP_VOID_RETURN(ec); } }+#endif // (OPENSSL_VERSION_NUMBER >= 0x30000000L) } - ec = asio::error_code(- static_cast<int>(::ERR_get_error()),- asio::error::get_ssl_category());+ ec = translate_error(::ERR_get_error()); ASIO_SYNC_OP_VOID_RETURN(ec); } @@ -1006,9 +1021,7 @@ if (::SSL_CTX_use_PrivateKey_file(handle_, filename.c_str(), file_type) != 1) {- ec = asio::error_code(- static_cast<int>(::ERR_get_error()),- asio::error::get_ssl_category());+ ec = translate_error(::ERR_get_error()); ASIO_SYNC_OP_VOID_RETURN(ec); } @@ -1028,6 +1041,53 @@ const std::string& filename, context::file_format format, asio::error_code& ec) {+#if (OPENSSL_VERSION_NUMBER >= 0x30000000L)+ ::ERR_clear_error();++ pem_password_cb* callback = ::SSL_CTX_get_default_passwd_cb(handle_);+ void* cb_userdata = ::SSL_CTX_get_default_passwd_cb_userdata(handle_);++ bio_cleanup bio = { ::BIO_new_file(filename.c_str(), "r") };+ if (bio.p)+ {+ evp_pkey_cleanup evp_private_key = { 0 };+ switch (format)+ {+ case context_base::asn1:+ evp_private_key.p = ::d2i_PrivateKey_bio(bio.p, 0);+ break;+ case context_base::pem:+ evp_private_key.p = ::PEM_read_bio_PrivateKey(+ bio.p, 0, callback,+ cb_userdata);+ break;+ default:+ {+ ec = asio::error::invalid_argument;+ ASIO_SYNC_OP_VOID_RETURN(ec);+ }+ }++ if (evp_private_key.p)+ {+ if (::EVP_PKEY_is_a(evp_private_key.p, "RSA") == 0)+ {+ ec = translate_error(+ ERR_PACK(ERR_LIB_EVP, 0, EVP_R_EXPECTING_AN_RSA_KEY));+ ASIO_SYNC_OP_VOID_RETURN(ec);+ }++ if (::SSL_CTX_use_PrivateKey(handle_, evp_private_key.p) == 1)+ {+ ec = asio::error_code();+ ASIO_SYNC_OP_VOID_RETURN(ec);+ }+ }+ }++ ec = translate_error(::ERR_get_error());+ ASIO_SYNC_OP_VOID_RETURN(ec);+#else // (OPENSSL_VERSION_NUMBER >= 0x30000000L) int file_type; switch (format) {@@ -1049,14 +1109,13 @@ if (::SSL_CTX_use_RSAPrivateKey_file( handle_, filename.c_str(), file_type) != 1) {- ec = asio::error_code(- static_cast<int>(::ERR_get_error()),- asio::error::get_ssl_category());+ ec = translate_error(::ERR_get_error()); ASIO_SYNC_OP_VOID_RETURN(ec); } ec = asio::error_code(); ASIO_SYNC_OP_VOID_RETURN(ec);+#endif // (OPENSSL_VERSION_NUMBER >= 0x30000000L) } void context::use_tmp_dh(const const_buffer& dh)@@ -1077,9 +1136,7 @@ return do_use_tmp_dh(bio.p, ec); } - ec = asio::error_code(- static_cast<int>(::ERR_get_error()),- asio::error::get_ssl_category());+ ec = translate_error(::ERR_get_error()); ASIO_SYNC_OP_VOID_RETURN(ec); } @@ -1101,9 +1158,7 @@ return do_use_tmp_dh(bio.p, ec); } - ec = asio::error_code(- static_cast<int>(::ERR_get_error()),- asio::error::get_ssl_category());+ ec = translate_error(::ERR_get_error()); ASIO_SYNC_OP_VOID_RETURN(ec); } @@ -1112,6 +1167,19 @@ { ::ERR_clear_error(); +#if (OPENSSL_VERSION_NUMBER >= 0x30000000L)+ EVP_PKEY* p = ::PEM_read_bio_Parameters(bio, 0);+ if (p)+ {+ if (::SSL_CTX_set0_tmp_dh_pkey(handle_, p) == 1)+ {+ ec = asio::error_code();+ ASIO_SYNC_OP_VOID_RETURN(ec);+ }+ else+ ::EVP_PKEY_free(p);+ }+#else // (OPENSSL_VERSION_NUMBER >= 0x30000000L) dh_cleanup dh = { ::PEM_read_bio_DHparams(bio, 0, 0, 0) }; if (dh.p) {@@ -1121,10 +1189,9 @@ ASIO_SYNC_OP_VOID_RETURN(ec); } }+#endif // (OPENSSL_VERSION_NUMBER >= 0x30000000L) - ec = asio::error_code(- static_cast<int>(::ERR_get_error()),- asio::error::get_ssl_category());+ ec = translate_error(::ERR_get_error()); ASIO_SYNC_OP_VOID_RETURN(ec); } @@ -1177,7 +1244,8 @@ detail::password_callback_base* callback, asio::error_code& ec) { #if ((OPENSSL_VERSION_NUMBER >= 0x10100000L) \- && !defined(LIBRESSL_VERSION_NUMBER)) \+ && (!defined(LIBRESSL_VERSION_NUMBER) \+ || LIBRESSL_VERSION_NUMBER >= 0x2070000fL)) \ || defined(ASIO_USE_WOLFSSL) void* old_callback = ::SSL_CTX_get_default_passwd_cb_userdata(handle_); ::SSL_CTX_set_default_passwd_cb_userdata(handle_, callback);@@ -1228,6 +1296,21 @@ return ::BIO_new_mem_buf( const_cast<void*>(b.data()), static_cast<int>(b.size()));+}++asio::error_code context::translate_error(long error)+{+#if (OPENSSL_VERSION_NUMBER >= 0x30000000L)+ if (ERR_SYSTEM_ERROR(error))+ {+ return asio::error_code(+ static_cast<int>(ERR_GET_REASON(error)),+ asio::error::get_system_category());+ }+#endif // (OPENSSL_VERSION_NUMBER >= 0x30000000L)++ return asio::error_code(static_cast<int>(error),+ asio::error::get_ssl_category()); } } // namespace ssl
link/modules/asio-standalone/asio/include/asio/ssl/impl/error.ipp view
@@ -2,7 +2,7 @@ // ssl/impl/error.ipp // ~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -35,8 +35,30 @@ std::string message(int value) const {- const char* s = ::ERR_reason_error_string(value);- return s ? s : "asio.ssl error";+ const char* reason = ::ERR_reason_error_string(value);+ if (reason)+ {+ const char* lib = ::ERR_lib_error_string(value);+#if (OPENSSL_VERSION_NUMBER < 0x30000000L)+ const char* func = ::ERR_func_error_string(value);+#else // (OPENSSL_VERSION_NUMBER < 0x30000000L)+ const char* func = 0;+#endif // (OPENSSL_VERSION_NUMBER < 0x30000000L)+ std::string result(reason);+ if (lib || func)+ {+ result += " (";+ if (lib)+ result += lib;+ if (lib && func)+ result += ", ";+ if (func)+ result += func;+ result += ")";+ }+ return result;+ }+ return "asio.ssl error"; } };
link/modules/asio-standalone/asio/include/asio/ssl/impl/host_name_verification.ipp view
@@ -2,7 +2,7 @@ // ssl/impl/host_name_verification.ipp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/ssl/impl/rfc2818_verification.ipp view
@@ -2,7 +2,7 @@ // ssl/impl/rfc2818_verification.ipp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/ssl/impl/src.hpp view
@@ -2,7 +2,7 @@ // impl/ssl/src.hpp // ~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/ssl/rfc2818_verification.hpp view
@@ -2,7 +2,7 @@ // ssl/rfc2818_verification.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/ssl/stream.hpp view
@@ -2,7 +2,7 @@ // ssl/stream.hpp // ~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -65,6 +65,13 @@ public stream_base, private noncopyable {+private:+ class initiate_async_handshake;+ class initiate_async_buffered_handshake;+ class initiate_async_shutdown;+ class initiate_async_write_some;+ class initiate_async_read_some;+ public: /// The native handle type of the SSL stream. typedef SSL* native_handle_type;@@ -100,6 +107,23 @@ core_(ctx.native_handle(), next_layer_.lowest_layer().get_executor()) { }++ /// Construct a stream from an existing native implementation.+ /**+ * This constructor creates a stream and initialises the underlying stream+ * object. On success, ownership of the native implementation is transferred+ * to the stream, and it will be cleaned up when the stream is destroyed.+ *+ * @param arg The argument to be passed to initialise the underlying stream.+ *+ * @param handle An existing native SSL implementation.+ */+ template <typename Arg>+ stream(Arg&& arg, native_handle_type handle)+ : next_layer_(ASIO_MOVE_CAST(Arg)(arg)),+ core_(handle, next_layer_.lowest_layer().get_executor())+ {+ } #else // defined(ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION) template <typename Arg> stream(Arg& arg, context& ctx)@@ -107,6 +131,13 @@ core_(ctx.native_handle(), next_layer_.lowest_layer().get_executor()) { }++ template <typename Arg>+ stream(Arg& arg, native_handle_type handle)+ : next_layer_(arg),+ core_(handle, next_layer_.lowest_layer().get_executor())+ {+ } #endif // defined(ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION) #if defined(ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)@@ -115,13 +146,30 @@ * @param other The other stream object from which the move will occur. Must * have no outstanding asynchronous operations associated with it. Following * the move, @c other has a valid but unspecified state where the only safe- * operation is destruction.+ * operation is destruction, or use as the target of a move assignment. */ stream(stream&& other) : next_layer_(ASIO_MOVE_CAST(Stream)(other.next_layer_)), core_(ASIO_MOVE_CAST(detail::stream_core)(other.core_)) { }++ /// Move-assign a stream from another.+ /**+ * @param other The other stream object from which the move will occur. Must+ * have no outstanding asynchronous operations associated with it. Following+ * the move, @c other has a valid but unspecified state where the only safe+ * operation is destruction, or use as the target of a move assignment.+ */+ stream& operator=(stream&& other)+ {+ if (this != &other)+ {+ next_layer_ = ASIO_MOVE_CAST(Stream)(other.next_layer_);+ core_ = ASIO_MOVE_CAST(detail::stream_core)(other.core_);+ }+ return *this;+ } #endif // defined(ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION) /// Destructor.@@ -433,37 +481,63 @@ /// Start an asynchronous SSL handshake. /** * This function is used to asynchronously perform an SSL handshake on the- * stream. This function call always returns immediately.+ * stream. It is an initiating function for an @ref asynchronous_operation,+ * and always returns immediately. * * @param type The type of handshaking to be performed, i.e. as a client or as * a server. *- * @param handler The handler to be called when the handshake operation- * completes. Copies will be made of the handler as required. The equivalent- * function signature of the handler must be:+ * @param token The @ref completion_token that will be used to produce a+ * completion handler, which will be called when the handshake completes.+ * Potential completion tokens include @ref use_future, @ref use_awaitable,+ * @ref yield_context, or a function object with the correct completion+ * signature. The function signature of the completion handler must be: * @code void handler( * const asio::error_code& error // Result of operation. * ); @endcode+ * Regardless of whether the asynchronous operation completes immediately or+ * not, the completion handler will not be invoked from within this function.+ * On immediate completion, invocation of the handler will be performed in a+ * manner equivalent to using asio::post().+ *+ * @par Completion Signature+ * @code void(asio::error_code) @endcode+ *+ * @par Per-Operation Cancellation+ * This asynchronous operation supports cancellation for the following+ * asio::cancellation_type values:+ *+ * @li @c cancellation_type::terminal+ *+ * @li @c cancellation_type::partial+ *+ * if they are also supported by the @c Stream type's @c async_read_some and+ * @c async_write_some operations. */ template < ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code))- HandshakeHandler+ HandshakeToken ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(executor_type)>- ASIO_INITFN_AUTO_RESULT_TYPE(HandshakeHandler,+ ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX(HandshakeToken, void (asio::error_code)) async_handshake(handshake_type type,- ASIO_MOVE_ARG(HandshakeHandler) handler+ ASIO_MOVE_ARG(HandshakeToken) token ASIO_DEFAULT_COMPLETION_TOKEN(executor_type))+ ASIO_INITFN_AUTO_RESULT_TYPE_SUFFIX((+ async_initiate<HandshakeToken,+ void (asio::error_code)>(+ declval<initiate_async_handshake>(), token, type))) {- return async_initiate<HandshakeHandler,+ return async_initiate<HandshakeToken, void (asio::error_code)>(- initiate_async_handshake(this), handler, type);+ initiate_async_handshake(this), token, type); } /// Start an asynchronous SSL handshake. /** * This function is used to asynchronously perform an SSL handshake on the- * stream. This function call always returns immediately.+ * stream. It is an initiating function for an @ref asynchronous_operation,+ * and always returns immediately. * * @param type The type of handshaking to be performed, i.e. as a client or as * a server.@@ -471,29 +545,53 @@ * @param buffers The buffered data to be reused for the handshake. Although * the buffers object may be copied as necessary, ownership of the underlying * buffers is retained by the caller, which must guarantee that they remain- * valid until the handler is called.+ * valid until the completion handler is called. *- * @param handler The handler to be called when the handshake operation- * completes. Copies will be made of the handler as required. The equivalent- * function signature of the handler must be:+ * @param token The @ref completion_token that will be used to produce a+ * completion handler, which will be called when the handshake completes.+ * Potential completion tokens include @ref use_future, @ref use_awaitable,+ * @ref yield_context, or a function object with the correct completion+ * signature. The function signature of the completion handler must be: * @code void handler( * const asio::error_code& error, // Result of operation. * std::size_t bytes_transferred // Amount of buffers used in handshake. * ); @endcode+ * Regardless of whether the asynchronous operation completes immediately or+ * not, the completion handler will not be invoked from within this function.+ * On immediate completion, invocation of the handler will be performed in a+ * manner equivalent to using asio::post().+ *+ * @par Completion Signature+ * @code void(asio::error_code, std::size_t) @endcode+ *+ * @par Per-Operation Cancellation+ * This asynchronous operation supports cancellation for the following+ * asio::cancellation_type values:+ *+ * @li @c cancellation_type::terminal+ *+ * @li @c cancellation_type::partial+ *+ * if they are also supported by the @c Stream type's @c async_read_some and+ * @c async_write_some operations. */ template <typename ConstBufferSequence, ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code,- std::size_t)) BufferedHandshakeHandler+ std::size_t)) BufferedHandshakeToken ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(executor_type)>- ASIO_INITFN_AUTO_RESULT_TYPE(BufferedHandshakeHandler,+ ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX(BufferedHandshakeToken, void (asio::error_code, std::size_t)) async_handshake(handshake_type type, const ConstBufferSequence& buffers,- ASIO_MOVE_ARG(BufferedHandshakeHandler) handler+ ASIO_MOVE_ARG(BufferedHandshakeToken) token ASIO_DEFAULT_COMPLETION_TOKEN(executor_type))+ ASIO_INITFN_AUTO_RESULT_TYPE_SUFFIX((+ async_initiate<BufferedHandshakeToken,+ void (asio::error_code, std::size_t)>(+ declval<initiate_async_buffered_handshake>(), token, type, buffers))) {- return async_initiate<BufferedHandshakeHandler,+ return async_initiate<BufferedHandshakeToken, void (asio::error_code, std::size_t)>(- initiate_async_buffered_handshake(this), handler, type, buffers);+ initiate_async_buffered_handshake(this), token, type, buffers); } /// Shut down SSL on the stream.@@ -525,29 +623,54 @@ /// Asynchronously shut down SSL on the stream. /**- * This function is used to asynchronously shut down SSL on the stream. This- * function call always returns immediately.+ * This function is used to asynchronously shut down SSL on the stream. It is+ * an initiating function for an @ref asynchronous_operation, and always+ * returns immediately. *- * @param handler The handler to be called when the handshake operation- * completes. Copies will be made of the handler as required. The equivalent- * function signature of the handler must be:+ * @param token The @ref completion_token that will be used to produce a+ * completion handler, which will be called when the shutdown completes.+ * Potential completion tokens include @ref use_future, @ref use_awaitable,+ * @ref yield_context, or a function object with the correct completion+ * signature. The function signature of the completion handler must be: * @code void handler( * const asio::error_code& error // Result of operation. * ); @endcode+ * Regardless of whether the asynchronous operation completes immediately or+ * not, the completion handler will not be invoked from within this function.+ * On immediate completion, invocation of the handler will be performed in a+ * manner equivalent to using asio::post().+ *+ * @par Completion Signature+ * @code void(asio::error_code) @endcode+ *+ * @par Per-Operation Cancellation+ * This asynchronous operation supports cancellation for the following+ * asio::cancellation_type values:+ *+ * @li @c cancellation_type::terminal+ *+ * @li @c cancellation_type::partial+ *+ * if they are also supported by the @c Stream type's @c async_read_some and+ * @c async_write_some operations. */ template < ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code))- ShutdownHandler+ ShutdownToken ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(executor_type)>- ASIO_INITFN_AUTO_RESULT_TYPE(ShutdownHandler,+ ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX(ShutdownToken, void (asio::error_code)) async_shutdown(- ASIO_MOVE_ARG(ShutdownHandler) handler+ ASIO_MOVE_ARG(ShutdownToken) token ASIO_DEFAULT_COMPLETION_TOKEN(executor_type))+ ASIO_INITFN_AUTO_RESULT_TYPE_SUFFIX((+ async_initiate<ShutdownToken,+ void (asio::error_code)>(+ declval<initiate_async_shutdown>(), token))) {- return async_initiate<ShutdownHandler,+ return async_initiate<ShutdownToken, void (asio::error_code)>(- initiate_async_shutdown(this), handler);+ initiate_async_shutdown(this), token); } /// Write some data to the stream.@@ -602,39 +725,64 @@ /// Start an asynchronous write. /** * This function is used to asynchronously write one or more bytes of data to- * the stream. The function call always returns immediately.+ * the stream. It is an initiating function for an @ref+ * asynchronous_operation, and always returns immediately. * * @param buffers The data to be written to the stream. Although the buffers * object may be copied as necessary, ownership of the underlying buffers is * retained by the caller, which must guarantee that they remain valid until- * the handler is called.+ * the completion handler is called. *- * @param handler The handler to be called when the write operation completes.- * Copies will be made of the handler as required. The equivalent function- * signature of the handler must be:+ * @param token The @ref completion_token that will be used to produce a+ * completion handler, which will be called when the write completes.+ * Potential completion tokens include @ref use_future, @ref use_awaitable,+ * @ref yield_context, or a function object with the correct completion+ * signature. The function signature of the completion handler must be: * @code void handler( * const asio::error_code& error, // Result of operation.- * std::size_t bytes_transferred // Number of bytes written.+ * std::size_t bytes_transferred // Number of bytes written. * ); @endcode+ * Regardless of whether the asynchronous operation completes immediately or+ * not, the completion handler will not be invoked from within this function.+ * On immediate completion, invocation of the handler will be performed in a+ * manner equivalent to using asio::post(). *+ * @par Completion Signature+ * @code void(asio::error_code, std::size_t) @endcode+ * * @note The async_write_some operation may not transmit all of the data to * the peer. Consider using the @ref async_write function if you need to * ensure that all data is written before the asynchronous operation * completes.+ *+ * @par Per-Operation Cancellation+ * This asynchronous operation supports cancellation for the following+ * asio::cancellation_type values:+ *+ * @li @c cancellation_type::terminal+ *+ * @li @c cancellation_type::partial+ *+ * if they are also supported by the @c Stream type's @c async_read_some and+ * @c async_write_some operations. */ template <typename ConstBufferSequence, ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code,- std::size_t)) WriteHandler+ std::size_t)) WriteToken ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(executor_type)>- ASIO_INITFN_AUTO_RESULT_TYPE(WriteHandler,+ ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX(WriteToken, void (asio::error_code, std::size_t)) async_write_some(const ConstBufferSequence& buffers,- ASIO_MOVE_ARG(WriteHandler) handler+ ASIO_MOVE_ARG(WriteToken) token ASIO_DEFAULT_COMPLETION_TOKEN(executor_type))+ ASIO_INITFN_AUTO_RESULT_TYPE_SUFFIX((+ async_initiate<WriteToken,+ void (asio::error_code, std::size_t)>(+ declval<initiate_async_write_some>(), token, buffers))) {- return async_initiate<WriteHandler,+ return async_initiate<WriteToken, void (asio::error_code, std::size_t)>(- initiate_async_write_some(this), handler, buffers);+ initiate_async_write_some(this), token, buffers); } /// Read some data from the stream.@@ -689,39 +837,64 @@ /// Start an asynchronous read. /** * This function is used to asynchronously read one or more bytes of data from- * the stream. The function call always returns immediately.+ * the stream. It is an initiating function for an @ref+ * asynchronous_operation, and always returns immediately. * * @param buffers The buffers into which the data will be read. Although the * buffers object may be copied as necessary, ownership of the underlying * buffers is retained by the caller, which must guarantee that they remain- * valid until the handler is called.+ * valid until the completion handler is called. *- * @param handler The handler to be called when the read operation completes.- * Copies will be made of the handler as required. The equivalent function- * signature of the handler must be:+ * @param token The @ref completion_token that will be used to produce a+ * completion handler, which will be called when the read completes.+ * Potential completion tokens include @ref use_future, @ref use_awaitable,+ * @ref yield_context, or a function object with the correct completion+ * signature. The function signature of the completion handler must be: * @code void handler( * const asio::error_code& error, // Result of operation.- * std::size_t bytes_transferred // Number of bytes read.+ * std::size_t bytes_transferred // Number of bytes read. * ); @endcode+ * Regardless of whether the asynchronous operation completes immediately or+ * not, the completion handler will not be invoked from within this function.+ * On immediate completion, invocation of the handler will be performed in a+ * manner equivalent to using asio::post(). *+ * @par Completion Signature+ * @code void(asio::error_code, std::size_t) @endcode+ * * @note The async_read_some operation may not read all of the requested * number of bytes. Consider using the @ref async_read function if you need to * ensure that the requested amount of data is read before the asynchronous * operation completes.+ *+ * @par Per-Operation Cancellation+ * This asynchronous operation supports cancellation for the following+ * asio::cancellation_type values:+ *+ * @li @c cancellation_type::terminal+ *+ * @li @c cancellation_type::partial+ *+ * if they are also supported by the @c Stream type's @c async_read_some and+ * @c async_write_some operations. */ template <typename MutableBufferSequence, ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code,- std::size_t)) ReadHandler+ std::size_t)) ReadToken ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(executor_type)>- ASIO_INITFN_AUTO_RESULT_TYPE(ReadHandler,+ ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX(ReadToken, void (asio::error_code, std::size_t)) async_read_some(const MutableBufferSequence& buffers,- ASIO_MOVE_ARG(ReadHandler) handler+ ASIO_MOVE_ARG(ReadToken) token ASIO_DEFAULT_COMPLETION_TOKEN(executor_type))+ ASIO_INITFN_AUTO_RESULT_TYPE_SUFFIX((+ async_initiate<ReadToken,+ void (asio::error_code, std::size_t)>(+ declval<initiate_async_read_some>(), token, buffers))) {- return async_initiate<ReadHandler,+ return async_initiate<ReadToken, void (asio::error_code, std::size_t)>(- initiate_async_read_some(this), handler, buffers);+ initiate_async_read_some(this), token, buffers); } private:
link/modules/asio-standalone/asio/include/asio/ssl/stream_base.hpp view
@@ -2,7 +2,7 @@ // ssl/stream_base.hpp // ~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/ssl/verify_context.hpp view
@@ -2,7 +2,7 @@ // ssl/verify_context.hpp // ~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/ssl/verify_mode.hpp view
@@ -2,7 +2,7 @@ // ssl/verify_mode.hpp // ~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/static_thread_pool.hpp view
@@ -2,7 +2,7 @@ // static_thread_pool.hpp // ~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/steady_timer.hpp view
@@ -2,7 +2,7 @@ // steady_timer.hpp // ~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/strand.hpp view
@@ -2,7 +2,7 @@ // strand.hpp // ~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -18,6 +18,7 @@ #include "asio/detail/config.hpp" #include "asio/detail/strand_executor_service.hpp" #include "asio/detail/type_traits.hpp"+#include "asio/execution/blocking.hpp" #include "asio/execution/executor.hpp" #include "asio/is_executor.hpp" @@ -47,13 +48,13 @@ /// Construct a strand for the specified executor. template <typename Executor1> explicit strand(const Executor1& e,- typename enable_if<+ typename constraint< conditional< !is_same<Executor1, strand>::value, is_convertible<Executor1, Executor>, false_type >::type::value- >::type* = 0)+ >::type = 0) : executor_(e), impl_(strand::create_implementation(executor_)) {@@ -157,7 +158,7 @@ /// Forward a query to the underlying executor. /** * Do not call this function directly. It is intended for use with the- * execution::execute customisation point.+ * asio::query customisation point. * * For example: * @code asio::strand<my_executor_type> ex = ...;@@ -166,14 +167,19 @@ * ... @endcode */ template <typename Property>- typename enable_if<+ typename constraint< can_query<const Executor&, Property>::value,- typename query_result<const Executor&, Property>::type+ typename conditional<+ is_convertible<Property, execution::blocking_t>::value,+ execution::blocking_t,+ typename query_result<const Executor&, Property>::type+ >::type >::type query(const Property& p) const ASIO_NOEXCEPT_IF(( is_nothrow_query<const Executor&, Property>::value)) {- return asio::query(executor_, p);+ return this->query_helper(+ is_convertible<Property, execution::blocking_t>(), p); } /// Forward a requirement to the underlying executor.@@ -187,8 +193,9 @@ * asio::execution::blocking.never); @endcode */ template <typename Property>- typename enable_if<- can_require<const Executor&, Property>::value,+ typename constraint<+ can_require<const Executor&, Property>::value+ && !is_convertible<Property, execution::blocking_t::always_t>::value, strand<typename decay< typename require_result<const Executor&, Property>::type >::type>@@ -212,8 +219,9 @@ * asio::execution::blocking.never); @endcode */ template <typename Property>- typename enable_if<- can_prefer<const Executor&, Property>::value,+ typename constraint<+ can_prefer<const Executor&, Property>::value+ && !is_convertible<Property, execution::blocking_t::always_t>::value, strand<typename decay< typename prefer_result<const Executor&, Property>::type >::type>@@ -254,13 +262,6 @@ /// Request the strand to invoke the given function object. /**- * Do not call this function directly. It is intended for use with the- * execution::execute customisation point.- *- * For example:- * @code asio::strand<my_executor_type> ex = ...;- * execution::execute(ex, my_function_object); @endcode- * * This function is used to ask the strand to execute the given function * object on its underlying executor. The function object will be executed * according to the properties of the underlying executor.@@ -270,8 +271,16 @@ * function object must be: @code void function(); @endcode */ template <typename Function>- typename enable_if<- execution::can_execute<const Executor&, Function>::value+ typename constraint<+#if defined(ASIO_NO_DEPRECATED) \+ || defined(GENERATING_DOCUMENTATION)+ traits::execute_member<const Executor&, Function>::is_valid,+#else // defined(ASIO_NO_DEPRECATED)+ // || defined(GENERATING_DOCUMENTATION)+ execution::can_execute<const Executor&, Function>::value,+#endif // defined(ASIO_NO_DEPRECATED)+ // || defined(GENERATING_DOCUMENTATION)+ void >::type execute(ASIO_MOVE_ARG(Function) f) const { detail::strand_executor_service::execute(impl_,@@ -381,9 +390,9 @@ template <typename InnerExecutor> static implementation_type create_implementation(const InnerExecutor& ex,- typename enable_if<+ typename constraint< can_query<InnerExecutor, execution::context_t>::value- >::type* = 0)+ >::type = 0) { return use_service<detail::strand_executor_service>( asio::query(ex, execution::context)).create_implementation();@@ -391,9 +400,9 @@ template <typename InnerExecutor> static implementation_type create_implementation(const InnerExecutor& ex,- typename enable_if<+ typename constraint< !can_query<InnerExecutor, execution::context_t>::value- >::type* = 0)+ >::type = 0) { return use_service<detail::strand_executor_service>( ex.context()).create_implementation();@@ -405,6 +414,21 @@ { } + template <typename Property>+ typename query_result<const Executor&, Property>::type query_helper(+ false_type, const Property& property) const+ {+ return asio::query(executor_, property);+ }++ template <typename Property>+ execution::blocking_t query_helper(true_type, const Property& property) const+ {+ execution::blocking_t result = asio::query(executor_, property);+ return result == execution::blocking.always+ ? execution::blocking.possibly : result;+ }+ Executor executor_; implementation_type impl_; };@@ -417,22 +441,33 @@ /*@{*/ /// Create a @ref strand object for an executor.+/**+ * @param ex An executor.+ *+ * @returns A strand constructed with the specified executor.+ */ template <typename Executor> inline strand<Executor> make_strand(const Executor& ex,- typename enable_if<+ typename constraint< is_executor<Executor>::value || execution::is_executor<Executor>::value- >::type* = 0)+ >::type = 0) { return strand<Executor>(ex); } /// Create a @ref strand object for an execution context.+/**+ * @param ctx An execution context, from which an executor will be obtained.+ *+ * @returns A strand constructed with the execution context's executor, obtained+ * by performing <tt>ctx.get_executor()</tt>.+ */ template <typename ExecutionContext> inline strand<typename ExecutionContext::executor_type> make_strand(ExecutionContext& ctx,- typename enable_if<+ typename constraint< is_convertible<ExecutionContext&, execution_context&>::value- >::type* = 0)+ >::type = 0) { return strand<typename ExecutionContext::executor_type>(ctx.get_executor()); }@@ -457,7 +492,14 @@ #if !defined(ASIO_HAS_DEDUCED_EXECUTE_MEMBER_TRAIT) template <typename Executor, typename Function>-struct execute_member<strand<Executor>, Function>+struct execute_member<strand<Executor>, Function,+ typename enable_if<+#if defined(ASIO_NO_DEPRECATED)+ traits::execute_member<const Executor&, Function>::is_valid+#else // defined(ASIO_NO_DEPRECATED)+ execution::can_execute<const Executor&, Function>::value+#endif // defined(ASIO_NO_DEPRECATED)+ >::type> { ASIO_STATIC_CONSTEXPR(bool, is_valid = true); ASIO_STATIC_CONSTEXPR(bool, is_noexcept = false);@@ -477,7 +519,10 @@ ASIO_STATIC_CONSTEXPR(bool, is_valid = true); ASIO_STATIC_CONSTEXPR(bool, is_noexcept = (is_nothrow_query<Executor, Property>::value));- typedef typename query_result<Executor, Property>::type result_type;+ typedef typename conditional<+ is_convertible<Property, execution::blocking_t>::value,+ execution::blocking_t, typename query_result<Executor, Property>::type+ >::type result_type; }; #endif // !defined(ASIO_HAS_DEDUCED_QUERY_MEMBER_TRAIT)@@ -488,6 +533,7 @@ struct require_member<strand<Executor>, Property, typename enable_if< can_require<const Executor&, Property>::value+ && !is_convertible<Property, execution::blocking_t::always_t>::value >::type> { ASIO_STATIC_CONSTEXPR(bool, is_valid = true);@@ -506,6 +552,7 @@ struct prefer_member<strand<Executor>, Property, typename enable_if< can_prefer<const Executor&, Property>::value+ && !is_convertible<Property, execution::blocking_t::always_t>::value >::type> { ASIO_STATIC_CONSTEXPR(bool, is_valid = true);
+ link/modules/asio-standalone/asio/include/asio/stream_file.hpp view
@@ -0,0 +1,35 @@+//+// stream_file.hpp+// ~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com)+//+// Distributed under the Boost Software License, Version 1.0. (See accompanying+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)+//++#ifndef ASIO_STREAM_FILE_HPP+#define ASIO_STREAM_FILE_HPP++#if defined(_MSC_VER) && (_MSC_VER >= 1200)+# pragma once+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)++#include "asio/detail/config.hpp"++#if defined(ASIO_HAS_FILE) \+ || defined(GENERATING_DOCUMENTATION)++#include "asio/basic_stream_file.hpp"++namespace asio {++/// Typedef for the typical usage of a stream-oriented file.+typedef basic_stream_file<> stream_file;++} // namespace asio++#endif // defined(ASIO_HAS_FILE)+ // || defined(GENERATING_DOCUMENTATION)++#endif // ASIO_STREAM_FILE_HPP
link/modules/asio-standalone/asio/include/asio/streambuf.hpp view
@@ -2,7 +2,7 @@ // streambuf.hpp // ~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/system_context.hpp view
@@ -2,7 +2,7 @@ // system_context.hpp // ~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/system_error.hpp view
@@ -2,7 +2,7 @@ // system_error.hpp // ~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/system_executor.hpp view
@@ -2,7 +2,7 @@ // system_executor.hpp // ~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -44,6 +44,12 @@ { } +#if !defined(GENERATING_DOCUMENTATION)+private:+ friend struct asio_require_fn::impl;+ friend struct asio_prefer_fn::impl;+#endif // !defined(GENERATING_DOCUMENTATION)+ /// Obtain an executor with the @c blocking.possibly property. /** * Do not call this function directly. It is intended for use with the@@ -169,6 +175,15 @@ Relationship, std::allocator<void> >(); } +#if !defined(GENERATING_DOCUMENTATION)+private:+ friend struct asio_query_fn::impl;+ friend struct asio::execution::detail::blocking_t<0>;+ friend struct asio::execution::detail::mapping_t<0>;+ friend struct asio::execution::detail::outstanding_work_t<0>;+ friend struct asio::execution::detail::relationship_t<0>;+#endif // !defined(GENERATING_DOCUMENTATION)+ /// Query the current value of the @c mapping property. /** * Do not call this function directly. It is intended for use with the@@ -278,6 +293,7 @@ */ std::size_t query(execution::occupancy_t) const ASIO_NOEXCEPT; +public: /// Compare two executors for equality. /** * Two executors are equal if they refer to the same underlying io_context.@@ -299,14 +315,6 @@ } /// Execution function.- /**- * Do not call this function directly. It is intended for use with the- * execution::execute customisation point.- *- * For example:- * @code asio::system_executor ex;- * execution::execute(ex, my_function_object); @endcode- */ template <typename Function> void execute(ASIO_MOVE_ARG(Function) f) const {@@ -314,6 +322,7 @@ } #if !defined(ASIO_NO_TS_EXECUTORS)+public: /// Obtain the underlying execution context. system_context& context() const ASIO_NOEXCEPT;
link/modules/asio-standalone/asio/include/asio/system_timer.hpp view
@@ -2,7 +2,7 @@ // system_timer.hpp // ~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/this_coro.hpp view
@@ -2,7 +2,7 @@ // this_coro.hpp // ~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -16,6 +16,7 @@ #endif // defined(_MSC_VER) && (_MSC_VER >= 1200) #include "asio/detail/config.hpp"+#include "asio/detail/type_traits.hpp" #include "asio/detail/push_options.hpp" @@ -36,6 +37,240 @@ #elif defined(ASIO_MSVC) __declspec(selectany) executor_t executor; #endif++/// Awaitable type that returns the cancellation state of the current coroutine.+struct cancellation_state_t+{+ ASIO_CONSTEXPR cancellation_state_t()+ {+ }+};++/// Awaitable object that returns the cancellation state of the current+/// coroutine.+/**+ * @par Example+ * @code asio::awaitable<void> my_coroutine()+ * {+ * asio::cancellation_state cs+ * = co_await asio::this_coro::cancellation_state;+ *+ * // ...+ *+ * if (cs.cancelled() != asio::cancellation_type::none)+ * // ...+ * } @endcode+ */+#if defined(ASIO_HAS_CONSTEXPR) || defined(GENERATING_DOCUMENTATION)+constexpr cancellation_state_t cancellation_state;+#elif defined(ASIO_MSVC)+__declspec(selectany) cancellation_state_t cancellation_state;+#endif++#if defined(GENERATING_DOCUMENTATION)++/// Returns an awaitable object that may be used to reset the cancellation state+/// of the current coroutine.+/**+ * Let <tt>P</tt> be the cancellation slot associated with the current+ * coroutine's @ref co_spawn completion handler. Assigns a new+ * asio::cancellation_state object <tt>S</tt>, constructed as+ * <tt>S(P)</tt>, into the current coroutine's cancellation state object.+ *+ * @par Example+ * @code asio::awaitable<void> my_coroutine()+ * {+ * co_await asio::this_coro::reset_cancellation_state();+ *+ * // ...+ * } @endcode+ *+ * @note The cancellation state is shared by all coroutines in the same "thread+ * of execution" that was created using asio::co_spawn.+ */+ASIO_NODISCARD ASIO_CONSTEXPR unspecified+reset_cancellation_state();++/// Returns an awaitable object that may be used to reset the cancellation state+/// of the current coroutine.+/**+ * Let <tt>P</tt> be the cancellation slot associated with the current+ * coroutine's @ref co_spawn completion handler. Assigns a new+ * asio::cancellation_state object <tt>S</tt>, constructed as <tt>S(P,+ * std::forward<Filter>(filter))</tt>, into the current coroutine's+ * cancellation state object.+ *+ * @par Example+ * @code asio::awaitable<void> my_coroutine()+ * {+ * co_await asio::this_coro::reset_cancellation_state(+ * asio::enable_partial_cancellation());+ *+ * // ...+ * } @endcode+ *+ * @note The cancellation state is shared by all coroutines in the same "thread+ * of execution" that was created using asio::co_spawn.+ */+template <typename Filter>+ASIO_NODISCARD ASIO_CONSTEXPR unspecified+reset_cancellation_state(ASIO_MOVE_ARG(Filter) filter);++/// Returns an awaitable object that may be used to reset the cancellation state+/// of the current coroutine.+/**+ * Let <tt>P</tt> be the cancellation slot associated with the current+ * coroutine's @ref co_spawn completion handler. Assigns a new+ * asio::cancellation_state object <tt>S</tt>, constructed as <tt>S(P,+ * std::forward<InFilter>(in_filter),+ * std::forward<OutFilter>(out_filter))</tt>, into the current coroutine's+ * cancellation state object.+ *+ * @par Example+ * @code asio::awaitable<void> my_coroutine()+ * {+ * co_await asio::this_coro::reset_cancellation_state(+ * asio::enable_partial_cancellation(),+ * asio::disable_cancellation());+ *+ * // ...+ * } @endcode+ *+ * @note The cancellation state is shared by all coroutines in the same "thread+ * of execution" that was created using asio::co_spawn.+ */+template <typename InFilter, typename OutFilter>+ASIO_NODISCARD ASIO_CONSTEXPR unspecified+reset_cancellation_state(+ ASIO_MOVE_ARG(InFilter) in_filter,+ ASIO_MOVE_ARG(OutFilter) out_filter);++/// Returns an awaitable object that may be used to determine whether the+/// coroutine throws if trying to suspend when it has been cancelled.+/**+ * @par Example+ * @code asio::awaitable<void> my_coroutine()+ * {+ * if (co_await asio::this_coro::throw_if_cancelled)+ * // ...+ *+ * // ...+ * } @endcode+ */+ASIO_NODISCARD ASIO_CONSTEXPR unspecified+throw_if_cancelled();++/// Returns an awaitable object that may be used to specify whether the+/// coroutine throws if trying to suspend when it has been cancelled.+/**+ * @par Example+ * @code asio::awaitable<void> my_coroutine()+ * {+ * co_await asio::this_coro::throw_if_cancelled(false);+ *+ * // ...+ * } @endcode+ */+ASIO_NODISCARD ASIO_CONSTEXPR unspecified+throw_if_cancelled(bool value);++#else // defined(GENERATING_DOCUMENTATION)++struct reset_cancellation_state_0_t+{+ ASIO_CONSTEXPR reset_cancellation_state_0_t()+ {+ }+};++ASIO_NODISCARD inline ASIO_CONSTEXPR reset_cancellation_state_0_t+reset_cancellation_state()+{+ return reset_cancellation_state_0_t();+}++template <typename Filter>+struct reset_cancellation_state_1_t+{+ template <typename F>+ explicit ASIO_CONSTEXPR reset_cancellation_state_1_t(+ ASIO_MOVE_ARG(F) filt)+ : filter(ASIO_MOVE_CAST(F)(filt))+ {+ }++ Filter filter;+};++template <typename Filter>+ASIO_NODISCARD inline ASIO_CONSTEXPR reset_cancellation_state_1_t<+ typename decay<Filter>::type>+reset_cancellation_state(ASIO_MOVE_ARG(Filter) filter)+{+ return reset_cancellation_state_1_t<typename decay<Filter>::type>(+ ASIO_MOVE_CAST(Filter)(filter));+}++template <typename InFilter, typename OutFilter>+struct reset_cancellation_state_2_t+{+ template <typename F1, typename F2>+ ASIO_CONSTEXPR reset_cancellation_state_2_t(+ ASIO_MOVE_ARG(F1) in_filt, ASIO_MOVE_ARG(F2) out_filt)+ : in_filter(ASIO_MOVE_CAST(F1)(in_filt)),+ out_filter(ASIO_MOVE_CAST(F2)(out_filt))+ {+ }++ InFilter in_filter;+ OutFilter out_filter;+};++template <typename InFilter, typename OutFilter>+ASIO_NODISCARD inline ASIO_CONSTEXPR reset_cancellation_state_2_t<+ typename decay<InFilter>::type,+ typename decay<OutFilter>::type>+reset_cancellation_state(+ ASIO_MOVE_ARG(InFilter) in_filter,+ ASIO_MOVE_ARG(OutFilter) out_filter)+{+ return reset_cancellation_state_2_t<+ typename decay<InFilter>::type,+ typename decay<OutFilter>::type>(+ ASIO_MOVE_CAST(InFilter)(in_filter),+ ASIO_MOVE_CAST(OutFilter)(out_filter));+}++struct throw_if_cancelled_0_t+{+ ASIO_CONSTEXPR throw_if_cancelled_0_t()+ {+ }+};++ASIO_NODISCARD inline ASIO_CONSTEXPR throw_if_cancelled_0_t+throw_if_cancelled()+{+ return throw_if_cancelled_0_t();+}++struct throw_if_cancelled_1_t+{+ explicit ASIO_CONSTEXPR throw_if_cancelled_1_t(bool val)+ : value(val)+ {+ }++ bool value;+};++ASIO_NODISCARD inline ASIO_CONSTEXPR throw_if_cancelled_1_t+throw_if_cancelled(bool value)+{+ return throw_if_cancelled_1_t(value);+}++#endif // defined(GENERATING_DOCUMENTATION) } // namespace this_coro } // namespace asio
link/modules/asio-standalone/asio/include/asio/thread.hpp view
@@ -2,7 +2,7 @@ // thread.hpp // ~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/thread_pool.hpp view
@@ -2,7 +2,7 @@ // thread_pool.hpp // ~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -165,8 +165,10 @@ class thread_pool::basic_executor_type : detail::thread_pool_bits { public:- /// The sender type, when this type is used as a scheduler.+#if !defined(ASIO_NO_DEPRECATED)+ /// (Deprecated.) The sender type, when this type is used as a scheduler. typedef basic_executor_type sender_type;+#endif // !defined(ASIO_NO_DEPRECATED) /// The bulk execution shape type. typedef std::size_t shape_type;@@ -230,6 +232,12 @@ basic_executor_type&& other) ASIO_NOEXCEPT; #endif // defined(ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION) +#if !defined(GENERATING_DOCUMENTATION)+private:+ friend struct asio_require_fn::impl;+ friend struct asio_prefer_fn::impl;+#endif // !defined(GENERATING_DOCUMENTATION)+ /// Obtain an executor with the @c blocking.possibly property. /** * Do not call this function directly. It is intended for use with the@@ -390,7 +398,15 @@ pool_, std::allocator<void>(), bits_); } - /// Query the current value of the @c bulk_guarantee property.+#if !defined(GENERATING_DOCUMENTATION)+private:+ friend struct asio_query_fn::impl;+ friend struct asio::execution::detail::mapping_t<0>;+ friend struct asio::execution::detail::outstanding_work_t<0>;+#endif // !defined(GENERATING_DOCUMENTATION)++#if !defined(ASIO_NO_DEPRECATED)+ /// (Deprecated.) Query the current value of the @c bulk_guarantee property. /** * Do not call this function directly. It is intended for use with the * asio::query customisation point.@@ -406,6 +422,7 @@ { return execution::bulk_guarantee.parallel; }+#endif // !defined(ASIO_NO_DEPRECATED) /// Query the current value of the @c mapping property. /**@@ -546,6 +563,7 @@ return static_cast<std::size_t>(pool_->num_threads_); } +public: /// Determine whether the thread pool is running in the current thread. /** * @return @c true if the current thread is running the thread pool. Otherwise@@ -578,14 +596,6 @@ } /// Execution function.- /**- * Do not call this function directly. It is intended for use with the- * execution::execute customisation point.- *- * For example:- * @code auto ex = my_thread_pool.executor();- * execution::execute(ex, my_function_object); @endcode- */ template <typename Function> void execute(ASIO_MOVE_ARG(Function) f) const {@@ -593,7 +603,9 @@ integral_constant<bool, (Bits & blocking_always) != 0>()); } - /// Bulk execution function.+public:+#if !defined(ASIO_NO_DEPRECATED)+ /// (Deprecated.) Bulk execution function. template <typename Function> void bulk_execute(ASIO_MOVE_ARG(Function) f, std::size_t n) const {@@ -601,7 +613,7 @@ integral_constant<bool, (Bits & blocking_always) != 0>()); } - /// Schedule function.+ /// (Deprecated.) Schedule function. /** * Do not call this function directly. It is intended for use with the * execution::schedule customisation point.@@ -613,7 +625,7 @@ return *this; } - /// Connect function.+ /// (Deprecated.) Connect function. /** * Do not call this function directly. It is intended for use with the * execution::connect customisation point.@@ -632,6 +644,7 @@ return execution::detail::as_operation<basic_executor_type, Receiver>( *this, ASIO_MOVE_CAST(Receiver)(r)); }+#endif // !defined(ASIO_NO_DEPRECATED) #if !defined(ASIO_NO_TS_EXECUTORS) /// Obtain the underlying execution context.@@ -798,6 +811,8 @@ #if !defined(ASIO_HAS_DEDUCED_SCHEDULE_MEMBER_TRAIT) +#if !defined(ASIO_NO_DEPRECATED)+ template <typename Allocator, unsigned int Bits> struct schedule_member< const asio::thread_pool::basic_executor_type<Allocator, Bits>@@ -809,10 +824,14 @@ Allocator, Bits> result_type; }; +#endif // !defined(ASIO_NO_DEPRECATED)+ #endif // !defined(ASIO_HAS_DEDUCED_SCHEDULE_MEMBER_TRAIT) #if !defined(ASIO_HAS_DEDUCED_CONNECT_MEMBER_TRAIT) +#if !defined(ASIO_NO_DEPRECATED)+ template <typename Allocator, unsigned int Bits, typename Receiver> struct connect_member< const asio::thread_pool::basic_executor_type<Allocator, Bits>,@@ -826,6 +845,8 @@ Receiver> result_type; }; +#endif // !defined(ASIO_NO_DEPRECATED)+ #endif // !defined(ASIO_HAS_DEDUCED_CONNECT_MEMBER_TRAIT) #if !defined(ASIO_HAS_DEDUCED_REQUIRE_MEMBER_TRAIT)@@ -943,6 +964,8 @@ #if !defined(ASIO_HAS_DEDUCED_QUERY_STATIC_CONSTEXPR_MEMBER_TRAIT) +#if !defined(ASIO_NO_DEPRECATED)+ template <typename Allocator, unsigned int Bits, typename Property> struct query_static_constexpr_member< asio::thread_pool::basic_executor_type<Allocator, Bits>,@@ -965,6 +988,8 @@ } }; +#endif // !defined(ASIO_NO_DEPRECATED)+ template <typename Allocator, unsigned int Bits, typename Property> struct query_static_constexpr_member< asio::thread_pool::basic_executor_type<Allocator, Bits>,@@ -1096,6 +1121,15 @@ #endif // !defined(ASIO_HAS_DEDUCED_QUERY_MEMBER_TRAIT) } // namespace traits++namespace execution {++template <>+struct is_executor<thread_pool> : false_type+{+};++} // namespace execution #endif // !defined(GENERATING_DOCUMENTATION)
link/modules/asio-standalone/asio/include/asio/time_traits.hpp view
@@ -2,7 +2,7 @@ // time_traits.hpp // ~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/traits/bulk_execute_free.hpp view
@@ -2,7 +2,7 @@ // traits/bulk_execute_free.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/traits/bulk_execute_member.hpp view
@@ -2,7 +2,7 @@ // traits/bulk_execute_member.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/traits/connect_free.hpp view
@@ -2,7 +2,7 @@ // traits/connect_free.hpp // ~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/traits/connect_member.hpp view
@@ -2,7 +2,7 @@ // traits/connect_member.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/traits/equality_comparable.hpp view
@@ -2,7 +2,7 @@ // traits/equality_comparable.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -55,8 +55,12 @@ struct equality_comparable_trait<T, typename void_type< decltype(- static_cast<bool>(declval<const T>() == declval<const T>()),- static_cast<bool>(declval<const T>() != declval<const T>())+ static_cast<void>(+ static_cast<bool>(declval<const T>() == declval<const T>())+ ),+ static_cast<void>(+ static_cast<bool>(declval<const T>() != declval<const T>())+ ) ) >::type> {
link/modules/asio-standalone/asio/include/asio/traits/execute_free.hpp view
@@ -2,7 +2,7 @@ // traits/execute_free.hpp // ~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/traits/execute_member.hpp view
@@ -2,7 +2,7 @@ // traits/execute_member.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/traits/prefer_free.hpp view
@@ -2,7 +2,7 @@ // traits/prefer_free.hpp // ~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/traits/prefer_member.hpp view
@@ -2,7 +2,7 @@ // traits/prefer_member.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/traits/query_free.hpp view
@@ -2,7 +2,7 @@ // traits/query_free.hpp // ~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/traits/query_member.hpp view
@@ -2,7 +2,7 @@ // traits/query_member.hpp // ~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/traits/query_static_constexpr_member.hpp view
@@ -2,7 +2,7 @@ // traits/query_static_constexpr_member.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/traits/require_concept_free.hpp view
@@ -2,7 +2,7 @@ // traits/require_concept_free.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/traits/require_concept_member.hpp view
@@ -2,7 +2,7 @@ // traits/require_concept_member.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/traits/require_free.hpp view
@@ -2,7 +2,7 @@ // traits/require_free.hpp // ~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/traits/require_member.hpp view
@@ -2,7 +2,7 @@ // traits/require_member.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/traits/schedule_free.hpp view
@@ -2,7 +2,7 @@ // traits/schedule_free.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/traits/schedule_member.hpp view
@@ -2,7 +2,7 @@ // traits/schedule_member.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/traits/set_done_free.hpp view
@@ -2,7 +2,7 @@ // traits/set_done_free.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/traits/set_done_member.hpp view
@@ -2,7 +2,7 @@ // traits/set_done_member.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/traits/set_error_free.hpp view
@@ -2,7 +2,7 @@ // traits/set_error_free.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/traits/set_error_member.hpp view
@@ -2,7 +2,7 @@ // traits/set_error_member.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/traits/set_value_free.hpp view
@@ -2,7 +2,7 @@ // traits/set_value_free.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/traits/set_value_member.hpp view
@@ -2,7 +2,7 @@ // traits/set_value_member.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/traits/start_free.hpp view
@@ -2,7 +2,7 @@ // traits/start_free.hpp // ~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/traits/start_member.hpp view
@@ -2,7 +2,7 @@ // traits/start_member.hpp // ~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/traits/static_query.hpp view
@@ -2,7 +2,7 @@ // traits/static_query.hpp // ~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/traits/static_require.hpp view
@@ -2,7 +2,7 @@ // traits/static_require.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/traits/static_require_concept.hpp view
@@ -2,7 +2,7 @@ // traits/static_require_concept.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -91,7 +91,8 @@ template <typename T, typename Property> struct static_require_concept_trait<T, Property, typename enable_if<- has_static_require_concept<T, typename decay<Property>::type>::value+ has_static_require_concept<typename decay<T>::type,+ typename decay<Property>::type>::value >::type> { ASIO_STATIC_CONSTEXPR(bool, is_valid = true);
link/modules/asio-standalone/asio/include/asio/traits/submit_free.hpp view
@@ -2,7 +2,7 @@ // traits/submit_free.hpp // ~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/traits/submit_member.hpp view
@@ -2,7 +2,7 @@ // traits/submit_member.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/ts/buffer.hpp view
@@ -2,7 +2,7 @@ // ts/buffer.hpp // ~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/ts/executor.hpp view
@@ -2,7 +2,7 @@ // ts/executor.hpp // ~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/ts/internet.hpp view
@@ -2,7 +2,7 @@ // ts/internet.hpp // ~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/ts/io_context.hpp view
@@ -2,7 +2,7 @@ // ts/io_context.hpp // ~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/ts/net.hpp view
@@ -2,7 +2,7 @@ // ts/net.hpp // ~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/ts/netfwd.hpp view
@@ -2,7 +2,7 @@ // ts/netfwd.hpp // ~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -45,7 +45,7 @@ #if !defined(ASIO_EXECUTOR_WORK_GUARD_DECL) #define ASIO_EXECUTOR_WORK_GUARD_DECL -template <typename Executor, typename = void>+template <typename Executor, typename = void, typename = void> class executor_work_guard; #endif // !defined(ASIO_EXECUTOR_WORK_GUARD_DECL)@@ -90,15 +90,7 @@ } // namespace execution -typedef execution::any_executor<- execution::context_as_t<execution_context&>,- execution::blocking_t::never_t,- execution::prefer_only<execution::blocking_t::possibly_t>,- execution::prefer_only<execution::outstanding_work_t::tracked_t>,- execution::prefer_only<execution::outstanding_work_t::untracked_t>,- execution::prefer_only<execution::relationship_t::fork_t>,- execution::prefer_only<execution::relationship_t::continuation_t>- > any_io_executor;+class any_io_executor; #endif // defined(ASIO_USE_TS_EXECUTOR_AS_DEFAULT)
link/modules/asio-standalone/asio/include/asio/ts/socket.hpp view
@@ -2,7 +2,7 @@ // ts/socket.hpp // ~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/ts/timer.hpp view
@@ -2,7 +2,7 @@ // ts/timer.hpp // ~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/unyield.hpp view
@@ -2,7 +2,7 @@ // unyield.hpp // ~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/use_awaitable.hpp view
@@ -2,7 +2,7 @@ // use_awaitable.hpp // ~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -32,7 +32,7 @@ namespace asio { -/// A completion token that represents the currently executing coroutine.+/// A @ref completion_token that represents the currently executing coroutine. /** * The @c use_awaitable_t class, with its value @c use_awaitable, is used to * represent the currently executing coroutine. This completion token may be@@ -99,18 +99,15 @@ typedef use_awaitable_t default_completion_token_type; /// Construct the adapted executor from the inner executor type.- executor_with_default(const InnerExecutor& ex) ASIO_NOEXCEPT- : InnerExecutor(ex)- {- }-- /// Convert the specified executor to the inner executor type, then use- /// that to construct the adapted executor.- template <typename OtherExecutor>- executor_with_default(const OtherExecutor& ex,- typename enable_if<- is_convertible<OtherExecutor, InnerExecutor>::value- >::type* = 0) ASIO_NOEXCEPT+ template <typename InnerExecutor1>+ executor_with_default(const InnerExecutor1& ex,+ typename constraint<+ conditional<+ !is_same<InnerExecutor1, executor_with_default>::value,+ is_convertible<InnerExecutor1, InnerExecutor>,+ false_type+ >::type::value+ >::type = 0) ASIO_NOEXCEPT : InnerExecutor(ex) { }@@ -146,7 +143,8 @@ #endif // defined(ASIO_ENABLE_HANDLER_TRACKING) }; -/// A completion token object that represents the currently executing coroutine.+/// A @ref completion_token object that represents the currently executing+/// coroutine. /** * See the documentation for asio::use_awaitable_t for a usage example. */
link/modules/asio-standalone/asio/include/asio/use_future.hpp view
@@ -2,7 +2,7 @@ // use_future.hpp // ~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -37,12 +37,14 @@ } // namespace detail -/// Class used to specify that an asynchronous operation should return a future.+/// A @ref completion_token type that causes an asynchronous operation to return+/// a future. /**- * The use_future_t class is used to indicate that an asynchronous operation- * should return a std::future object. A use_future_t object may be passed as a- * handler to an asynchronous operation, typically using the special value @c- * asio::use_future. For example:+ * The use_future_t class is a completion token type that is used to indicate+ * that an asynchronous operation should return a std::future object. A+ * use_future_t object may be passed as a completion token to an asynchronous+ * operation, typically using the special value @c asio::use_future. For+ * example: * * @code std::future<std::size_t> my_future * = my_socket.async_read_some(my_buffer, asio::use_future); @endcode@@ -138,7 +140,8 @@ std_allocator_void, Allocator>::type allocator_; }; -/// A special value, similar to std::nothrow.+/// A @ref completion_token object that causes an asynchronous operation to+/// return a future. /** * See the documentation for asio::use_future_t for a usage example. */
link/modules/asio-standalone/asio/include/asio/uses_executor.hpp view
@@ -2,7 +2,7 @@ // uses_executor.hpp // ~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/version.hpp view
@@ -2,7 +2,7 @@ // version.hpp // ~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -18,6 +18,6 @@ // ASIO_VERSION % 100 is the sub-minor version // ASIO_VERSION / 100 % 1000 is the minor version // ASIO_VERSION / 100000 is the major version-#define ASIO_VERSION 101700 // 1.17.0+#define ASIO_VERSION 102800 // 1.28.0 #endif // ASIO_VERSION_HPP
link/modules/asio-standalone/asio/include/asio/wait_traits.hpp view
@@ -2,7 +2,7 @@ // wait_traits.hpp // ~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/windows/basic_object_handle.hpp view
@@ -2,7 +2,7 @@ // windows/basic_object_handle.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // Copyright (c) 2011 Boris Schaeling (boris@highscore.de) // // Distributed under the Boost Software License, Version 1.0. (See accompanying@@ -50,6 +50,9 @@ template <typename Executor = any_io_executor> class basic_object_handle {+private:+ class initiate_async_wait;+ public: /// The type of the executor associated with the object. typedef Executor executor_type;@@ -82,7 +85,7 @@ * object handle. */ explicit basic_object_handle(const executor_type& ex)- : impl_(ex)+ : impl_(0, ex) { } @@ -96,11 +99,11 @@ */ template <typename ExecutionContext> explicit basic_object_handle(ExecutionContext& context,- typename enable_if<+ typename constraint< is_convertible<ExecutionContext&, execution_context&>::value,- basic_object_handle- >::type* = 0)- : impl_(context)+ defaulted_constraint+ >::type = defaulted_constraint())+ : impl_(0, 0, context) { } @@ -119,7 +122,7 @@ */ basic_object_handle(const executor_type& ex, const native_handle_type& native_handle)- : impl_(ex)+ : impl_(0, ex) { asio::error_code ec; impl_.get_service().assign(impl_.get_implementation(), native_handle, ec);@@ -142,10 +145,10 @@ template <typename ExecutionContext> basic_object_handle(ExecutionContext& context, const native_handle_type& native_handle,- typename enable_if<+ typename constraint< is_convertible<ExecutionContext&, execution_context&>::value- >::type* = 0)- : impl_(context)+ >::type = 0)+ : impl_(0, 0, context) { asio::error_code ec; impl_.get_service().assign(impl_.get_implementation(), native_handle, ec);@@ -185,10 +188,56 @@ impl_ = std::move(other.impl_); return *this; }++ // All handles have access to each other's implementations.+ template <typename Executor1>+ friend class basic_object_handle;++ /// Move-construct an object handle from a handle of another executor type.+ /**+ * This constructor moves an object handle from one object to another.+ *+ * @param other The other object handle object from which the move will+ * occur.+ *+ * @note Following the move, the moved-from object is in the same state as if+ * constructed using the @c basic_object_handle(const executor_type&)+ * constructor.+ */+ template<typename Executor1>+ basic_object_handle(basic_object_handle<Executor1>&& other,+ typename constraint<+ is_convertible<Executor1, Executor>::value,+ defaulted_constraint+ >::type = defaulted_constraint())+ : impl_(std::move(other.impl_))+ {+ }++ /// Move-assign an object handle from a handle of another executor type.+ /**+ * This assignment operator moves an object handle from one object to another.+ *+ * @param other The other object handle object from which the move will+ * occur.+ *+ * @note Following the move, the moved-from object is in the same state as if+ * constructed using the @c basic_object_handle(const executor_type&)+ * constructor.+ */+ template<typename Executor1>+ typename constraint<+ is_convertible<Executor1, Executor>::value,+ basic_object_handle&+ >::type operator=(basic_object_handle<Executor1>&& other)+ {+ impl_ = std::move(other.impl_);+ return *this;+ } #endif // defined(ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION) /// Get the executor associated with the object.- executor_type get_executor() ASIO_NOEXCEPT+ const executor_type& get_executor() ASIO_NOEXCEPT { return impl_.get_executor(); }@@ -357,30 +406,39 @@ /// Start an asynchronous wait on the object handle. /** * This function is be used to initiate an asynchronous wait against the- * object handle. It always returns immediately.+ * object handle. It is an initiating function for an @ref+ * asynchronous_operation, and always returns immediately. *- * @param handler The handler to be called when the object handle is set to- * the signalled state. Copies will be made of the handler as required. The- * function signature of the handler must be:+ * @param token The @ref completion_token that will be used to produce a+ * completion handler, which will be called when the wait completes.+ * Potential completion tokens include @ref use_future, @ref use_awaitable,+ * @ref yield_context, or a function object with the correct completion+ * signature. The function signature of the completion handler must be: * @code void handler( * const asio::error_code& error // Result of operation. * ); @endcode * Regardless of whether the asynchronous operation completes immediately or- * not, the handler will not be invoked from within this function. On- * immediate completion, invocation of the handler will be performed in a+ * not, the completion handler will not be invoked from within this function.+ * On immediate completion, invocation of the handler will be performed in a * manner equivalent to using asio::post().+ *+ * @par Completion Signature+ * @code void(asio::error_code) @endcode */ template < ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code))- WaitHandler ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(executor_type)>- ASIO_INITFN_AUTO_RESULT_TYPE(WaitHandler,+ WaitToken ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(executor_type)>+ ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX(WaitToken, void (asio::error_code)) async_wait(- ASIO_MOVE_ARG(WaitHandler) handler+ ASIO_MOVE_ARG(WaitToken) token ASIO_DEFAULT_COMPLETION_TOKEN(executor_type))+ ASIO_INITFN_AUTO_RESULT_TYPE_SUFFIX((+ async_initiate<WaitToken, void (asio::error_code)>(+ declval<initiate_async_wait>(), token))) {- return async_initiate<WaitHandler, void (asio::error_code)>(- initiate_async_wait(this), handler);+ return async_initiate<WaitToken, void (asio::error_code)>(+ initiate_async_wait(this), token); } private:@@ -398,7 +456,7 @@ { } - executor_type get_executor() const ASIO_NOEXCEPT+ const executor_type& get_executor() const ASIO_NOEXCEPT { return self_->get_executor(); }
link/modules/asio-standalone/asio/include/asio/windows/basic_overlapped_handle.hpp view
@@ -2,7 +2,7 @@ // windows/basic_overlapped_handle.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -85,7 +85,7 @@ * overlapped handle. */ explicit basic_overlapped_handle(const executor_type& ex)- : impl_(ex)+ : impl_(0, ex) { } @@ -99,11 +99,11 @@ */ template <typename ExecutionContext> explicit basic_overlapped_handle(ExecutionContext& context,- typename enable_if<+ typename constraint< is_convertible<ExecutionContext&, execution_context&>::value,- basic_overlapped_handle- >::type* = 0)- : impl_(context)+ defaulted_constraint+ >::type = defaulted_constraint())+ : impl_(0, 0, context) { } @@ -122,7 +122,7 @@ */ basic_overlapped_handle(const executor_type& ex, const native_handle_type& native_handle)- : impl_(ex)+ : impl_(0, ex) { asio::error_code ec; impl_.get_service().assign(impl_.get_implementation(), native_handle, ec);@@ -145,10 +145,10 @@ template <typename ExecutionContext> basic_overlapped_handle(ExecutionContext& context, const native_handle_type& native_handle,- typename enable_if<+ typename constraint< is_convertible<ExecutionContext&, execution_context&>::value- >::type* = 0)- : impl_(context)+ >::type = 0)+ : impl_(0, 0, context) { asio::error_code ec; impl_.get_service().assign(impl_.get_implementation(), native_handle, ec);@@ -188,10 +188,57 @@ impl_ = std::move(other.impl_); return *this; }++ // All overlapped handles have access to each other's implementations.+ template <typename Executor1>+ friend class basic_overlapped_handle;++ /// Move-construct an overlapped handle from a handle of another executor+ /// type.+ /**+ * This constructor moves a handle from one object to another.+ *+ * @param other The other overlapped handle object from which the move will+ * occur.+ *+ * @note Following the move, the moved-from object is in the same state as if+ * constructed using the @c overlapped_handle(const executor_type&)+ * constructor.+ */+ template<typename Executor1>+ basic_overlapped_handle(basic_overlapped_handle<Executor1>&& other,+ typename constraint<+ is_convertible<Executor1, Executor>::value,+ defaulted_constraint+ >::type = defaulted_constraint())+ : impl_(std::move(other.impl_))+ {+ }++ /// Move-assign an overlapped handle from a handle of another executor type.+ /**+ * This assignment operator moves a handle from one object to another.+ *+ * @param other The other overlapped handle object from which the move will+ * occur.+ *+ * @note Following the move, the moved-from object is in the same state as if+ * constructed using the @c overlapped_handle(const executor_type&)+ * constructor.+ */+ template<typename Executor1>+ typename constraint<+ is_convertible<Executor1, Executor>::value,+ basic_overlapped_handle&+ >::type operator=(basic_overlapped_handle<Executor1>&& other)+ {+ impl_ = std::move(other.impl_);+ return *this;+ } #endif // defined(ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION) /// Get the executor associated with the object.- executor_type get_executor() ASIO_NOEXCEPT+ const executor_type& get_executor() ASIO_NOEXCEPT { return impl_.get_executor(); }@@ -287,6 +334,58 @@ { impl_.get_service().close(impl_.get_implementation(), ec); ASIO_SYNC_OP_VOID_RETURN(ec);+ }++ /// Release ownership of the underlying native handle.+ /**+ * This function causes all outstanding asynchronous operations to finish+ * immediately, and the handlers for cancelled operations will be passed the+ * asio::error::operation_aborted error. Ownership of the native handle+ * is then transferred to the caller.+ *+ * @throws asio::system_error Thrown on failure.+ *+ * @note This function is unsupported on Windows versions prior to Windows+ * 8.1, and will fail with asio::error::operation_not_supported on+ * these platforms.+ */+#if defined(ASIO_MSVC) && (ASIO_MSVC >= 1400) \+ && (!defined(_WIN32_WINNT) || _WIN32_WINNT < 0x0603)+ __declspec(deprecated("This function always fails with "+ "operation_not_supported when used on Windows versions "+ "prior to Windows 8.1."))+#endif+ native_handle_type release()+ {+ asio::error_code ec;+ native_handle_type s = impl_.get_service().release(+ impl_.get_implementation(), ec);+ asio::detail::throw_error(ec, "release");+ return s;+ }++ /// Release ownership of the underlying native handle.+ /**+ * This function causes all outstanding asynchronous operations to finish+ * immediately, and the handlers for cancelled operations will be passed the+ * asio::error::operation_aborted error. Ownership of the native handle+ * is then transferred to the caller.+ *+ * @param ec Set to indicate what error occurred, if any.+ *+ * @note This function is unsupported on Windows versions prior to Windows+ * 8.1, and will fail with asio::error::operation_not_supported on+ * these platforms.+ */+#if defined(ASIO_MSVC) && (ASIO_MSVC >= 1400) \+ && (!defined(_WIN32_WINNT) || _WIN32_WINNT < 0x0603)+ __declspec(deprecated("This function always fails with "+ "operation_not_supported when used on Windows versions "+ "prior to Windows 8.1."))+#endif+ native_handle_type release(asio::error_code& ec)+ {+ return impl_.get_service().release(impl_.get_implementation(), ec); } /// Get the native handle representation.
link/modules/asio-standalone/asio/include/asio/windows/basic_random_access_handle.hpp view
@@ -2,7 +2,7 @@ // windows/basic_random_access_handle.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -39,6 +39,10 @@ class basic_random_access_handle : public basic_overlapped_handle<Executor> {+private:+ class initiate_async_write_some_at;+ class initiate_async_read_some_at;+ public: /// The type of the executor associated with the object. typedef Executor executor_type;@@ -75,8 +79,8 @@ /// Construct a random-access handle without opening it. /** * This constructor creates a random-access handle without opening it. The- * handle needs to be opened or assigned before data can be sent or received- * on it.+ * handle needs to be opened or assigned before data can be written to or read+ * from it. * * @param context An execution context which provides the I/O executor that * the random-access handle will use, by default, to dispatch handlers for any@@ -84,10 +88,10 @@ */ template <typename ExecutionContext> explicit basic_random_access_handle(ExecutionContext& context,- typename enable_if<+ typename constraint< is_convertible<ExecutionContext&, execution_context&>::value,- basic_random_access_handle- >::type* = 0)+ defaulted_constraint+ >::type = defaulted_constraint()) : basic_overlapped_handle<Executor>(context) { }@@ -127,9 +131,9 @@ template <typename ExecutionContext> basic_random_access_handle(ExecutionContext& context, const native_handle_type& handle,- typename enable_if<+ typename constraint< is_convertible<ExecutionContext&, execution_context&>::value- >::type* = 0)+ >::type = 0) : basic_overlapped_handle<Executor>(context, handle) { }@@ -168,6 +172,51 @@ basic_overlapped_handle<Executor>::operator=(std::move(other)); return *this; }++ /// Move-construct a random-access handle from a handle of another executor+ /// type.+ /**+ * This constructor moves a random-access handle from one object to another.+ *+ * @param other The other random-access handle object from which the+ * move will occur.+ *+ * @note Following the move, the moved-from object is in the same state as if+ * constructed using the @c basic_random_access_handle(const executor_type&)+ * constructor.+ */+ template<typename Executor1>+ basic_random_access_handle(basic_random_access_handle<Executor1>&& other,+ typename constraint<+ is_convertible<Executor1, Executor>::value,+ defaulted_constraint+ >::type = defaulted_constraint())+ : basic_overlapped_handle<Executor>(std::move(other))+ {+ }++ /// Move-assign a random-access handle from a handle of another executor+ /// type.+ /**+ * This assignment operator moves a random-access handle from one object to+ * another.+ *+ * @param other The other random-access handle object from which the+ * move will occur.+ *+ * @note Following the move, the moved-from object is in the same state as if+ * constructed using the @c basic_random_access_handle(const executor_type&)+ * constructor.+ */+ template<typename Executor1>+ typename constraint<+ is_convertible<Executor1, Executor>::value,+ basic_random_access_handle&+ >::type operator=(basic_random_access_handle<Executor1>&& other)+ {+ basic_overlapped_handle<Executor>::operator=(std::move(other));+ return *this;+ } #endif // defined(ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION) /// Write some data to the handle at the specified offset.@@ -239,27 +288,33 @@ /// Start an asynchronous write at the specified offset. /** * This function is used to asynchronously write data to the random-access- * handle. The function call always returns immediately.+ * handle. It is an initiating function for an @ref asynchronous_operation,+ * and always returns immediately. * * @param offset The offset at which the data will be written. * * @param buffers One or more data buffers to be written to the handle. * Although the buffers object may be copied as necessary, ownership of the * underlying memory blocks is retained by the caller, which must guarantee- * that they remain valid until the handler is called.+ * that they remain valid until the completion handler is called. *- * @param handler The handler to be called when the write operation completes.- * Copies will be made of the handler as required. The function signature of- * the handler must be:+ * @param token The @ref completion_token that will be used to produce a+ * completion handler, which will be called when the write completes.+ * Potential completion tokens include @ref use_future, @ref use_awaitable,+ * @ref yield_context, or a function object with the correct completion+ * signature. The function signature of the completion handler must be: * @code void handler( * const asio::error_code& error, // Result of operation.- * std::size_t bytes_transferred // Number of bytes written.+ * std::size_t bytes_transferred // Number of bytes written. * ); @endcode * Regardless of whether the asynchronous operation completes immediately or- * not, the handler will not be invoked from within this function. On- * immediate completion, invocation of the handler will be performed in a+ * not, the completion handler will not be invoked from within this function.+ * On immediate completion, invocation of the handler will be performed in a * manner equivalent to using asio::post(). *+ * @par Completion Signature+ * @code void(asio::error_code, std::size_t) @endcode+ * * @note The write operation may not transmit all of the data to the peer. * Consider using the @ref async_write_at function if you need to ensure that * all data is written before the asynchronous operation completes.@@ -272,21 +327,35 @@ * See the @ref buffer documentation for information on writing multiple * buffers in one go, and how to use it with arrays, boost::array or * std::vector.+ *+ * @par Per-Operation Cancellation+ * This asynchronous operation supports cancellation for the following+ * asio::cancellation_type values:+ *+ * @li @c cancellation_type::terminal+ *+ * @li @c cancellation_type::partial+ *+ * @li @c cancellation_type::total */ template <typename ConstBufferSequence, ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code,- std::size_t)) WriteHandler+ std::size_t)) WriteToken ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(executor_type)>- ASIO_INITFN_AUTO_RESULT_TYPE(WriteHandler,+ ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX(WriteToken, void (asio::error_code, std::size_t)) async_write_some_at(uint64_t offset, const ConstBufferSequence& buffers,- ASIO_MOVE_ARG(WriteHandler) handler+ ASIO_MOVE_ARG(WriteToken) token ASIO_DEFAULT_COMPLETION_TOKEN(executor_type))+ ASIO_INITFN_AUTO_RESULT_TYPE_SUFFIX((+ async_initiate<WriteToken,+ void (asio::error_code, std::size_t)>(+ declval<initiate_async_write_some_at>(), token, offset, buffers))) {- return async_initiate<WriteHandler,+ return async_initiate<WriteToken, void (asio::error_code, std::size_t)>(- initiate_async_write_some_at(this), handler, offset, buffers);+ initiate_async_write_some_at(this), token, offset, buffers); } /// Read some data from the handle at the specified offset.@@ -360,27 +429,33 @@ /// Start an asynchronous read at the specified offset. /** * This function is used to asynchronously read data from the random-access- * handle. The function call always returns immediately.+ * handle. It is an initiating function for an @ref asynchronous_operation,+ * and always returns immediately. * * @param offset The offset at which the data will be read. * * @param buffers One or more buffers into which the data will be read. * Although the buffers object may be copied as necessary, ownership of the * underlying memory blocks is retained by the caller, which must guarantee- * that they remain valid until the handler is called.+ * that they remain valid until the completion handler is called. *- * @param handler The handler to be called when the read operation completes.- * Copies will be made of the handler as required. The function signature of- * the handler must be:+ * @param token The @ref completion_token that will be used to produce a+ * completion handler, which will be called when the read completes.+ * Potential completion tokens include @ref use_future, @ref use_awaitable,+ * @ref yield_context, or a function object with the correct completion+ * signature. The function signature of the completion handler must be: * @code void handler( * const asio::error_code& error, // Result of operation.- * std::size_t bytes_transferred // Number of bytes read.+ * std::size_t bytes_transferred // Number of bytes read. * ); @endcode * Regardless of whether the asynchronous operation completes immediately or- * not, the handler will not be invoked from within this function. On- * immediate completion, invocation of the handler will be performed in a+ * not, the completion handler will not be invoked from within this function.+ * On immediate completion, invocation of the handler will be performed in a * manner equivalent to using asio::post(). *+ * @par Completion Signature+ * @code void(asio::error_code, std::size_t) @endcode+ * * @note The read operation may not read all of the requested number of bytes. * Consider using the @ref async_read_at function if you need to ensure that * the requested amount of data is read before the asynchronous operation@@ -394,21 +469,35 @@ * See the @ref buffer documentation for information on reading into multiple * buffers in one go, and how to use it with arrays, boost::array or * std::vector.+ *+ * @par Per-Operation Cancellation+ * This asynchronous operation supports cancellation for the following+ * asio::cancellation_type values:+ *+ * @li @c cancellation_type::terminal+ *+ * @li @c cancellation_type::partial+ *+ * @li @c cancellation_type::total */ template <typename MutableBufferSequence, ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code,- std::size_t)) ReadHandler+ std::size_t)) ReadToken ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(executor_type)>- ASIO_INITFN_AUTO_RESULT_TYPE(ReadHandler,+ ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX(ReadToken, void (asio::error_code, std::size_t)) async_read_some_at(uint64_t offset, const MutableBufferSequence& buffers,- ASIO_MOVE_ARG(ReadHandler) handler+ ASIO_MOVE_ARG(ReadToken) token ASIO_DEFAULT_COMPLETION_TOKEN(executor_type))+ ASIO_INITFN_AUTO_RESULT_TYPE_SUFFIX((+ async_initiate<ReadToken,+ void (asio::error_code, std::size_t)>(+ declval<initiate_async_read_some_at>(), token, offset, buffers))) {- return async_initiate<ReadHandler,+ return async_initiate<ReadToken, void (asio::error_code, std::size_t)>(- initiate_async_read_some_at(this), handler, offset, buffers);+ initiate_async_read_some_at(this), token, offset, buffers); } private:@@ -422,7 +511,7 @@ { } - executor_type get_executor() const ASIO_NOEXCEPT+ const executor_type& get_executor() const ASIO_NOEXCEPT { return self_->get_executor(); }@@ -455,7 +544,7 @@ { } - executor_type get_executor() const ASIO_NOEXCEPT+ const executor_type& get_executor() const ASIO_NOEXCEPT { return self_->get_executor(); }
link/modules/asio-standalone/asio/include/asio/windows/basic_stream_handle.hpp view
@@ -2,7 +2,7 @@ // windows/basic_stream_handle.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -42,6 +42,10 @@ class basic_stream_handle : public basic_overlapped_handle<Executor> {+private:+ class initiate_async_write_some;+ class initiate_async_read_some;+ public: /// The type of the executor associated with the object. typedef Executor executor_type;@@ -78,7 +82,8 @@ /// Construct a stream handle without opening it. /** * This constructor creates a stream handle without opening it. The handle- * needs to be opened or assigned before data can be sent or received on it.+ * needs to be opened or assigned before data can be written to or read from+ * it. * * @param context An execution context which provides the I/O executor that * the stream handle will use, by default, to dispatch handlers for any@@ -86,10 +91,10 @@ */ template <typename ExecutionContext> explicit basic_stream_handle(ExecutionContext& context,- typename enable_if<+ typename constraint< is_convertible<ExecutionContext&, execution_context&>::value,- basic_stream_handle- >::type* = 0)+ defaulted_constraint+ >::type = defaulted_constraint()) : basic_overlapped_handle<Executor>(context) { }@@ -128,9 +133,9 @@ template <typename ExecutionContext> basic_stream_handle(ExecutionContext& context, const native_handle_type& handle,- typename enable_if<+ typename constraint< is_convertible<ExecutionContext&, execution_context&>::value- >::type* = 0)+ >::type = 0) : basic_overlapped_handle<Executor>(context, handle) { }@@ -168,6 +173,48 @@ basic_overlapped_handle<Executor>::operator=(std::move(other)); return *this; }++ /// Move-construct a stream handle from a handle of another executor type.+ /**+ * This constructor moves a stream handle from one object to another.+ *+ * @param other The other stream handle object from which the move+ * will occur.+ *+ * @note Following the move, the moved-from object is in the same state as if+ * constructed using the @c basic_stream_handle(const executor_type&)+ * constructor.+ */+ template<typename Executor1>+ basic_stream_handle(basic_stream_handle<Executor1>&& other,+ typename constraint<+ is_convertible<Executor1, Executor>::value,+ defaulted_constraint+ >::type = defaulted_constraint())+ : basic_overlapped_handle<Executor>(std::move(other))+ {+ }++ /// Move-assign a stream handle from a handle of another executor type.+ /**+ * This assignment operator moves a stream handle from one object to+ * another.+ *+ * @param other The other stream handle object from which the move will occur.+ *+ * @note Following the move, the moved-from object is in the same state as if+ * constructed using the @c basic_stream_handle(const executor_type&)+ * constructor.+ */+ template<typename Executor1>+ typename constraint<+ is_convertible<Executor1, Executor>::value,+ basic_stream_handle&+ >::type operator=(basic_stream_handle<Executor1>&& other)+ {+ basic_overlapped_handle<Executor>::operator=(std::move(other));+ return *this;+ } #endif // defined(ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION) /// Write some data to the handle.@@ -234,25 +281,31 @@ /// Start an asynchronous write. /** * This function is used to asynchronously write data to the stream handle.- * The function call always returns immediately.+ * It is an initiating function for an @ref asynchronous_operation, and always+ * returns immediately. * * @param buffers One or more data buffers to be written to the handle. * Although the buffers object may be copied as necessary, ownership of the * underlying memory blocks is retained by the caller, which must guarantee- * that they remain valid until the handler is called.+ * that they remain valid until the completion handler is called. *- * @param handler The handler to be called when the write operation completes.- * Copies will be made of the handler as required. The function signature of- * the handler must be:+ * @param token The @ref completion_token that will be used to produce a+ * completion handler, which will be called when the write completes.+ * Potential completion tokens include @ref use_future, @ref use_awaitable,+ * @ref yield_context, or a function object with the correct completion+ * signature. The function signature of the completion handler must be: * @code void handler( * const asio::error_code& error, // Result of operation.- * std::size_t bytes_transferred // Number of bytes written.+ * std::size_t bytes_transferred // Number of bytes written. * ); @endcode * Regardless of whether the asynchronous operation completes immediately or- * not, the handler will not be invoked from within this function. On- * immediate completion, invocation of the handler will be performed in a+ * not, the completion handler will not be invoked from within this function.+ * On immediate completion, invocation of the handler will be performed in a * manner equivalent to using asio::post(). *+ * @par Completion Signature+ * @code void(asio::error_code, std::size_t) @endcode+ * * @note The write operation may not transmit all of the data to the peer. * Consider using the @ref async_write function if you need to ensure that all * data is written before the asynchronous operation completes.@@ -265,20 +318,34 @@ * See the @ref buffer documentation for information on writing multiple * buffers in one go, and how to use it with arrays, boost::array or * std::vector.+ *+ * @par Per-Operation Cancellation+ * This asynchronous operation supports cancellation for the following+ * asio::cancellation_type values:+ *+ * @li @c cancellation_type::terminal+ *+ * @li @c cancellation_type::partial+ *+ * @li @c cancellation_type::total */ template <typename ConstBufferSequence, ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code,- std::size_t)) WriteHandler+ std::size_t)) WriteToken ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(executor_type)>- ASIO_INITFN_AUTO_RESULT_TYPE(WriteHandler,+ ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX(WriteToken, void (asio::error_code, std::size_t)) async_write_some(const ConstBufferSequence& buffers,- ASIO_MOVE_ARG(WriteHandler) handler+ ASIO_MOVE_ARG(WriteToken) token ASIO_DEFAULT_COMPLETION_TOKEN(executor_type))+ ASIO_INITFN_AUTO_RESULT_TYPE_SUFFIX((+ async_initiate<WriteToken,+ void (asio::error_code, std::size_t)>(+ declval<initiate_async_write_some>(), token, buffers))) {- return async_initiate<WriteHandler,+ return async_initiate<WriteToken, void (asio::error_code, std::size_t)>(- initiate_async_write_some(this), handler, buffers);+ initiate_async_write_some(this), token, buffers); } /// Read some data from the handle.@@ -347,25 +414,31 @@ /// Start an asynchronous read. /** * This function is used to asynchronously read data from the stream handle.- * The function call always returns immediately.+ * It is an initiating function for an @ref asynchronous_operation, and always+ * returns immediately. * * @param buffers One or more buffers into which the data will be read. * Although the buffers object may be copied as necessary, ownership of the * underlying memory blocks is retained by the caller, which must guarantee- * that they remain valid until the handler is called.+ * that they remain valid until the completion handler is called. *- * @param handler The handler to be called when the read operation completes.- * Copies will be made of the handler as required. The function signature of- * the handler must be:+ * @param token The @ref completion_token that will be used to produce a+ * completion handler, which will be called when the read completes.+ * Potential completion tokens include @ref use_future, @ref use_awaitable,+ * @ref yield_context, or a function object with the correct completion+ * signature. The function signature of the completion handler must be: * @code void handler( * const asio::error_code& error, // Result of operation.- * std::size_t bytes_transferred // Number of bytes read.+ * std::size_t bytes_transferred // Number of bytes read. * ); @endcode * Regardless of whether the asynchronous operation completes immediately or- * not, the handler will not be invoked from within this function. On- * immediate completion, invocation of the handler will be performed in a+ * not, the completion handler will not be invoked from within this function.+ * On immediate completion, invocation of the handler will be performed in a * manner equivalent to using asio::post(). *+ * @par Completion Signature+ * @code void(asio::error_code, std::size_t) @endcode+ * * @note The read operation may not read all of the requested number of bytes. * Consider using the @ref async_read function if you need to ensure that the * requested amount of data is read before the asynchronous operation@@ -379,20 +452,34 @@ * See the @ref buffer documentation for information on reading into multiple * buffers in one go, and how to use it with arrays, boost::array or * std::vector.+ *+ * @par Per-Operation Cancellation+ * This asynchronous operation supports cancellation for the following+ * asio::cancellation_type values:+ *+ * @li @c cancellation_type::terminal+ *+ * @li @c cancellation_type::partial+ *+ * @li @c cancellation_type::total */ template <typename MutableBufferSequence, ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code,- std::size_t)) ReadHandler+ std::size_t)) ReadToken ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(executor_type)>- ASIO_INITFN_AUTO_RESULT_TYPE(ReadHandler,+ ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX(ReadToken, void (asio::error_code, std::size_t)) async_read_some(const MutableBufferSequence& buffers,- ASIO_MOVE_ARG(ReadHandler) handler+ ASIO_MOVE_ARG(ReadToken) token ASIO_DEFAULT_COMPLETION_TOKEN(executor_type))+ ASIO_INITFN_AUTO_RESULT_TYPE_SUFFIX((+ async_initiate<ReadToken,+ void (asio::error_code, std::size_t)>(+ declval<initiate_async_read_some>(), token, buffers))) {- return async_initiate<ReadHandler,+ return async_initiate<ReadToken, void (asio::error_code, std::size_t)>(- initiate_async_read_some(this), handler, buffers);+ initiate_async_read_some(this), token, buffers); } private:@@ -406,7 +493,7 @@ { } - executor_type get_executor() const ASIO_NOEXCEPT+ const executor_type& get_executor() const ASIO_NOEXCEPT { return self_->get_executor(); }@@ -439,7 +526,7 @@ { } - executor_type get_executor() const ASIO_NOEXCEPT+ const executor_type& get_executor() const ASIO_NOEXCEPT { return self_->get_executor(); }
link/modules/asio-standalone/asio/include/asio/windows/object_handle.hpp view
@@ -2,7 +2,7 @@ // windows/object_handle.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // Copyright (c) 2011 Boris Schaeling (boris@highscore.de) // // Distributed under the Boost Software License, Version 1.0. (See accompanying
link/modules/asio-standalone/asio/include/asio/windows/overlapped_handle.hpp view
@@ -2,7 +2,7 @@ // windows/overlapped_handle.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/windows/overlapped_ptr.hpp view
@@ -2,7 +2,7 @@ // windows/overlapped_ptr.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -52,9 +52,9 @@ template <typename ExecutionContext, typename Handler> explicit overlapped_ptr(ExecutionContext& context, ASIO_MOVE_ARG(Handler) handler,- typename enable_if<+ typename constraint< is_convertible<ExecutionContext&, execution_context&>::value- >::type* = 0)+ >::type = 0) : impl_(context.get_executor(), ASIO_MOVE_CAST(Handler)(handler)) { }@@ -63,10 +63,10 @@ template <typename Executor, typename Handler> explicit overlapped_ptr(const Executor& ex, ASIO_MOVE_ARG(Handler) handler,- typename enable_if<+ typename constraint< execution::is_executor<Executor>::value || is_executor<Executor>::value- >::type* = 0)+ >::type = 0) : impl_(ex, ASIO_MOVE_CAST(Handler)(handler)) { }@@ -86,9 +86,9 @@ /// object. template <typename ExecutionContext, typename Handler> void reset(ExecutionContext& context, ASIO_MOVE_ARG(Handler) handler,- typename enable_if<+ typename constraint< is_convertible<ExecutionContext&, execution_context&>::value- >::type* = 0)+ >::type = 0) { impl_.reset(context.get_executor(), ASIO_MOVE_CAST(Handler)(handler)); }@@ -97,10 +97,10 @@ /// object. template <typename Executor, typename Handler> void reset(const Executor& ex, ASIO_MOVE_ARG(Handler) handler,- typename enable_if<+ typename constraint< execution::is_executor<Executor>::value || is_executor<Executor>::value- >::type* = 0)+ >::type = 0) { impl_.reset(ex, ASIO_MOVE_CAST(Handler)(handler)); }
link/modules/asio-standalone/asio/include/asio/windows/random_access_handle.hpp view
@@ -2,7 +2,7 @@ // windows/random_access_handle.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/windows/stream_handle.hpp view
@@ -2,7 +2,7 @@ // windows/stream_handle.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+ link/modules/asio-standalone/asio/include/asio/writable_pipe.hpp view
@@ -0,0 +1,35 @@+//+// writable_pipe.hpp+// ~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com)+//+// Distributed under the Boost Software License, Version 1.0. (See accompanying+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)+//++#ifndef ASIO_WRITABLE_PIPE_HPP+#define ASIO_WRITABLE_PIPE_HPP++#if defined(_MSC_VER) && (_MSC_VER >= 1200)+# pragma once+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)++#include "asio/detail/config.hpp"++#if defined(ASIO_HAS_PIPE) \+ || defined(GENERATING_DOCUMENTATION)++#include "asio/basic_writable_pipe.hpp"++namespace asio {++/// Typedef for the typical usage of a writable pipe.+typedef basic_writable_pipe<> writable_pipe;++} // namespace asio++#endif // defined(ASIO_HAS_PIPE)+ // || defined(GENERATING_DOCUMENTATION)++#endif // ASIO_WRITABLE_PIPE_HPP
link/modules/asio-standalone/asio/include/asio/write.hpp view
@@ -2,7 +2,7 @@ // write.hpp // ~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -19,6 +19,7 @@ #include <cstddef> #include "asio/async_result.hpp" #include "asio/buffer.hpp"+#include "asio/completion_condition.hpp" #include "asio/error.hpp" #if !defined(ASIO_NO_EXTENSIONS)@@ -28,7 +29,16 @@ #include "asio/detail/push_options.hpp" namespace asio {+namespace detail { +template <typename> class initiate_async_write;+#if !defined(ASIO_NO_DYNAMIC_BUFFER_V1)+template <typename> class initiate_async_write_dynbuf_v1;+#endif // !defined(ASIO_NO_DYNAMIC_BUFFER_V1)+template <typename> class initiate_async_write_dynbuf_v2;++} // namespace detail+ /** * @defgroup write asio::write *@@ -75,9 +85,9 @@ */ template <typename SyncWriteStream, typename ConstBufferSequence> std::size_t write(SyncWriteStream& s, const ConstBufferSequence& buffers,- typename enable_if<+ typename constraint< is_const_buffer_sequence<ConstBufferSequence>::value- >::type* = 0);+ >::type = 0); /// Write all of the supplied data to a stream before returning. /**@@ -118,9 +128,9 @@ template <typename SyncWriteStream, typename ConstBufferSequence> std::size_t write(SyncWriteStream& s, const ConstBufferSequence& buffers, asio::error_code& ec,- typename enable_if<+ typename constraint< is_const_buffer_sequence<ConstBufferSequence>::value- >::type* = 0);+ >::type = 0); /// Write a certain amount of data to a stream before returning. /**@@ -172,9 +182,9 @@ typename CompletionCondition> std::size_t write(SyncWriteStream& s, const ConstBufferSequence& buffers, CompletionCondition completion_condition,- typename enable_if<+ typename constraint< is_const_buffer_sequence<ConstBufferSequence>::value- >::type* = 0);+ >::type = 0); /// Write a certain amount of data to a stream before returning. /**@@ -219,9 +229,9 @@ typename CompletionCondition> std::size_t write(SyncWriteStream& s, const ConstBufferSequence& buffers, CompletionCondition completion_condition, asio::error_code& ec,- typename enable_if<+ typename constraint< is_const_buffer_sequence<ConstBufferSequence>::value- >::type* = 0);+ >::type = 0); #if !defined(ASIO_NO_DYNAMIC_BUFFER_V1) @@ -255,10 +265,12 @@ template <typename SyncWriteStream, typename DynamicBuffer_v1> std::size_t write(SyncWriteStream& s, ASIO_MOVE_ARG(DynamicBuffer_v1) buffers,- typename enable_if<+ typename constraint< is_dynamic_buffer_v1<typename decay<DynamicBuffer_v1>::type>::value- && !is_dynamic_buffer_v2<typename decay<DynamicBuffer_v1>::type>::value- >::type* = 0);+ >::type = 0,+ typename constraint<+ !is_dynamic_buffer_v2<typename decay<DynamicBuffer_v1>::type>::value+ >::type = 0); /// Write all of the supplied data to a stream before returning. /**@@ -291,10 +303,12 @@ std::size_t write(SyncWriteStream& s, ASIO_MOVE_ARG(DynamicBuffer_v1) buffers, asio::error_code& ec,- typename enable_if<+ typename constraint< is_dynamic_buffer_v1<typename decay<DynamicBuffer_v1>::type>::value- && !is_dynamic_buffer_v2<typename decay<DynamicBuffer_v1>::type>::value- >::type* = 0);+ >::type = 0,+ typename constraint<+ !is_dynamic_buffer_v2<typename decay<DynamicBuffer_v1>::type>::value+ >::type = 0); /// Write a certain amount of data to a stream before returning. /**@@ -337,10 +351,12 @@ std::size_t write(SyncWriteStream& s, ASIO_MOVE_ARG(DynamicBuffer_v1) buffers, CompletionCondition completion_condition,- typename enable_if<+ typename constraint< is_dynamic_buffer_v1<typename decay<DynamicBuffer_v1>::type>::value- && !is_dynamic_buffer_v2<typename decay<DynamicBuffer_v1>::type>::value- >::type* = 0);+ >::type = 0,+ typename constraint<+ !is_dynamic_buffer_v2<typename decay<DynamicBuffer_v1>::type>::value+ >::type = 0); /// Write a certain amount of data to a stream before returning. /**@@ -384,10 +400,12 @@ std::size_t write(SyncWriteStream& s, ASIO_MOVE_ARG(DynamicBuffer_v1) buffers, CompletionCondition completion_condition, asio::error_code& ec,- typename enable_if<+ typename constraint< is_dynamic_buffer_v1<typename decay<DynamicBuffer_v1>::type>::value- && !is_dynamic_buffer_v2<typename decay<DynamicBuffer_v1>::type>::value- >::type* = 0);+ >::type = 0,+ typename constraint<+ !is_dynamic_buffer_v2<typename decay<DynamicBuffer_v1>::type>::value+ >::type = 0); #if !defined(ASIO_NO_EXTENSIONS) #if !defined(ASIO_NO_IOSTREAM)@@ -565,9 +583,9 @@ */ template <typename SyncWriteStream, typename DynamicBuffer_v2> std::size_t write(SyncWriteStream& s, DynamicBuffer_v2 buffers,- typename enable_if<+ typename constraint< is_dynamic_buffer_v2<DynamicBuffer_v2>::value- >::type* = 0);+ >::type = 0); /// Write all of the supplied data to a stream before returning. /**@@ -599,9 +617,9 @@ template <typename SyncWriteStream, typename DynamicBuffer_v2> std::size_t write(SyncWriteStream& s, DynamicBuffer_v2 buffers, asio::error_code& ec,- typename enable_if<+ typename constraint< is_dynamic_buffer_v2<DynamicBuffer_v2>::value- >::type* = 0);+ >::type = 0); /// Write a certain amount of data to a stream before returning. /**@@ -643,9 +661,9 @@ typename CompletionCondition> std::size_t write(SyncWriteStream& s, DynamicBuffer_v2 buffers, CompletionCondition completion_condition,- typename enable_if<+ typename constraint< is_dynamic_buffer_v2<DynamicBuffer_v2>::value- >::type* = 0);+ >::type = 0); /// Write a certain amount of data to a stream before returning. /**@@ -688,9 +706,9 @@ typename CompletionCondition> std::size_t write(SyncWriteStream& s, DynamicBuffer_v2 buffers, CompletionCondition completion_condition, asio::error_code& ec,- typename enable_if<+ typename constraint< is_dynamic_buffer_v2<DynamicBuffer_v2>::value- >::type* = 0);+ >::type = 0); /*@}*/ /**@@ -705,9 +723,9 @@ /// stream. /** * This function is used to asynchronously write a certain number of bytes of- * data to a stream. The function call always returns immediately. The- * asynchronous operation will continue until one of the following conditions- * is true:+ * data to a stream. It is an initiating function for an @ref+ * asynchronous_operation, and always returns immediately. The asynchronous+ * operation will continue until one of the following conditions is true: * * @li All of the data in the supplied buffers has been written. That is, the * bytes transferred is equal to the sum of the buffer sizes.@@ -726,24 +744,29 @@ * @param buffers One or more buffers containing the data to be written. * Although the buffers object may be copied as necessary, ownership of the * underlying memory blocks is retained by the caller, which must guarantee- * that they remain valid until the handler is called.+ * that they remain valid until the completion handler is called. *- * @param handler The handler to be called when the write operation completes.- * Copies will be made of the handler as required. The function signature of- * the handler must be:+ * @param token The @ref completion_token that will be used to produce a+ * completion handler, which will be called when the write completes.+ * Potential completion tokens include @ref use_future, @ref use_awaitable,+ * @ref yield_context, or a function object with the correct completion+ * signature. The function signature of the completion handler must be: * @code void handler(- * const asio::error_code& error, // Result of operation.+ * // Result of operation.+ * const asio::error_code& error, *- * std::size_t bytes_transferred // Number of bytes written from the- * // buffers. If an error occurred,- * // this will be less than the sum- * // of the buffer sizes.+ * // Number of bytes written from the buffers. If an error+ * // occurred, this will be less than the sum of the buffer sizes.+ * std::size_t bytes_transferred * ); @endcode * Regardless of whether the asynchronous operation completes immediately or- * not, the handler will not be invoked from within this function. On- * immediate completion, invocation of the handler will be performed in a+ * not, the completion handler will not be invoked from within this function.+ * On immediate completion, invocation of the handler will be performed in a * manner equivalent to using asio::post(). *+ * @par Completion Signature+ * @code void(asio::error_code, std::size_t) @endcode+ * * @par Example * To write a single data buffer use the @ref buffer function as follows: * @code@@ -752,29 +775,45 @@ * See the @ref buffer documentation for information on writing multiple * buffers in one go, and how to use it with arrays, boost::array or * std::vector.+ *+ * @par Per-Operation Cancellation+ * This asynchronous operation supports cancellation for the following+ * asio::cancellation_type values:+ *+ * @li @c cancellation_type::terminal+ *+ * @li @c cancellation_type::partial+ *+ * if they are also supported by the @c AsyncWriteStream type's+ * @c async_write_some operation. */ template <typename AsyncWriteStream, typename ConstBufferSequence, ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code,- std::size_t)) WriteHandler+ std::size_t)) WriteToken ASIO_DEFAULT_COMPLETION_TOKEN_TYPE( typename AsyncWriteStream::executor_type)>-ASIO_INITFN_AUTO_RESULT_TYPE(WriteHandler,+ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX(WriteToken, void (asio::error_code, std::size_t)) async_write(AsyncWriteStream& s, const ConstBufferSequence& buffers,- ASIO_MOVE_ARG(WriteHandler) handler+ ASIO_MOVE_ARG(WriteToken) token ASIO_DEFAULT_COMPLETION_TOKEN( typename AsyncWriteStream::executor_type),- typename enable_if<+ typename constraint< is_const_buffer_sequence<ConstBufferSequence>::value- >::type* = 0);+ >::type = 0)+ ASIO_INITFN_AUTO_RESULT_TYPE_SUFFIX((+ async_initiate<WriteToken,+ void (asio::error_code, std::size_t)>(+ declval<detail::initiate_async_write<AsyncWriteStream> >(),+ token, buffers, transfer_all()))); /// Start an asynchronous operation to write a certain amount of data to a /// stream. /** * This function is used to asynchronously write a certain number of bytes of- * data to a stream. The function call always returns immediately. The- * asynchronous operation will continue until one of the following conditions- * is true:+ * data to a stream. It is an initiating function for an @ref+ * asynchronous_operation, and always returns immediately. The asynchronous+ * operation will continue until one of the following conditions is true: * * @li All of the data in the supplied buffers has been written. That is, the * bytes transferred is equal to the sum of the buffer sizes.@@ -793,7 +832,7 @@ * @param buffers One or more buffers containing the data to be written. * Although the buffers object may be copied as necessary, ownership of the * underlying memory blocks is retained by the caller, which must guarantee- * that they remain valid until the handler is called.+ * that they remain valid until the completion handler is called. * * @param completion_condition The function object to be called to determine * whether the write operation is complete. The signature of the function object@@ -809,22 +848,27 @@ * non-zero return value indicates the maximum number of bytes to be written on * the next call to the stream's async_write_some function. *- * @param handler The handler to be called when the write operation completes.- * Copies will be made of the handler as required. The function signature of the- * handler must be:+ * @param token The @ref completion_token that will be used to produce a+ * completion handler, which will be called when the write completes.+ * Potential completion tokens include @ref use_future, @ref use_awaitable,+ * @ref yield_context, or a function object with the correct completion+ * signature. The function signature of the completion handler must be: * @code void handler(- * const asio::error_code& error, // Result of operation.+ * // Result of operation.+ * const asio::error_code& error, *- * std::size_t bytes_transferred // Number of bytes written from the- * // buffers. If an error occurred,- * // this will be less than the sum- * // of the buffer sizes.+ * // Number of bytes written from the buffers. If an error+ * // occurred, this will be less than the sum of the buffer sizes.+ * std::size_t bytes_transferred * ); @endcode * Regardless of whether the asynchronous operation completes immediately or- * not, the handler will not be invoked from within this function. On- * immediate completion, invocation of the handler will be performed in a+ * not, the completion handler will not be invoked from within this function.+ * On immediate completion, invocation of the handler will be performed in a * manner equivalent to using asio::post(). *+ * @par Completion Signature+ * @code void(asio::error_code, std::size_t) @endcode+ * * @par Example * To write a single data buffer use the @ref buffer function as follows: * @code asio::async_write(s,@@ -834,19 +878,36 @@ * See the @ref buffer documentation for information on writing multiple * buffers in one go, and how to use it with arrays, boost::array or * std::vector.+ *+ * @par Per-Operation Cancellation+ * This asynchronous operation supports cancellation for the following+ * asio::cancellation_type values:+ *+ * @li @c cancellation_type::terminal+ *+ * @li @c cancellation_type::partial+ *+ * if they are also supported by the @c AsyncWriteStream type's+ * @c async_write_some operation. */ template <typename AsyncWriteStream, typename ConstBufferSequence, typename CompletionCondition, ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code,- std::size_t)) WriteHandler>-ASIO_INITFN_AUTO_RESULT_TYPE(WriteHandler,+ std::size_t)) WriteToken>+ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX(WriteToken, void (asio::error_code, std::size_t)) async_write(AsyncWriteStream& s, const ConstBufferSequence& buffers, CompletionCondition completion_condition,- ASIO_MOVE_ARG(WriteHandler) handler,- typename enable_if<+ ASIO_MOVE_ARG(WriteToken) token,+ typename constraint< is_const_buffer_sequence<ConstBufferSequence>::value- >::type* = 0);+ >::type = 0)+ ASIO_INITFN_AUTO_RESULT_TYPE_SUFFIX((+ async_initiate<WriteToken,+ void (asio::error_code, std::size_t)>(+ declval<detail::initiate_async_write<AsyncWriteStream> >(),+ token, buffers,+ ASIO_MOVE_CAST(CompletionCondition)(completion_condition)))); #if !defined(ASIO_NO_DYNAMIC_BUFFER_V1) @@ -854,9 +915,9 @@ /// stream. /** * This function is used to asynchronously write a certain number of bytes of- * data to a stream. The function call always returns immediately. The- * asynchronous operation will continue until one of the following conditions- * is true:+ * data to a stream. It is an initiating function for an @ref+ * asynchronous_operation, and always returns immediately. The asynchronous+ * operation will continue until one of the following conditions is true: * * @li All of the data in the supplied dynamic buffer sequence has been written. *@@ -874,49 +935,73 @@ * @param buffers The dynamic buffer sequence from which data will be written. * Although the buffers object may be copied as necessary, ownership of the * underlying memory blocks is retained by the caller, which must guarantee- * that they remain valid until the handler is called. Successfully written- * data is automatically consumed from the buffers.+ * that they remain valid until the completion handler is called. Successfully+ * written data is automatically consumed from the buffers. *- * @param handler The handler to be called when the write operation completes.- * Copies will be made of the handler as required. The function signature of the- * handler must be:+ * @param token The @ref completion_token that will be used to produce a+ * completion handler, which will be called when the write completes.+ * Potential completion tokens include @ref use_future, @ref use_awaitable,+ * @ref yield_context, or a function object with the correct completion+ * signature. The function signature of the completion handler must be: * @code void handler(- * const asio::error_code& error, // Result of operation.+ * // Result of operation.+ * const asio::error_code& error, *- * std::size_t bytes_transferred // Number of bytes written from the- * // buffers. If an error occurred,- * // this will be less than the sum- * // of the buffer sizes.+ * // Number of bytes written from the buffers. If an error+ * // occurred, this will be less than the sum of the buffer sizes.+ * std::size_t bytes_transferred * ); @endcode * Regardless of whether the asynchronous operation completes immediately or- * not, the handler will not be invoked from within this function. On- * immediate completion, invocation of the handler will be performed in a+ * not, the completion handler will not be invoked from within this function.+ * On immediate completion, invocation of the handler will be performed in a * manner equivalent to using asio::post().+ *+ * @par Completion Signature+ * @code void(asio::error_code, std::size_t) @endcode+ *+ * @par Per-Operation Cancellation+ * This asynchronous operation supports cancellation for the following+ * asio::cancellation_type values:+ *+ * @li @c cancellation_type::terminal+ *+ * @li @c cancellation_type::partial+ *+ * if they are also supported by the @c AsyncWriteStream type's+ * @c async_write_some operation. */ template <typename AsyncWriteStream, typename DynamicBuffer_v1, ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code,- std::size_t)) WriteHandler+ std::size_t)) WriteToken ASIO_DEFAULT_COMPLETION_TOKEN_TYPE( typename AsyncWriteStream::executor_type)>-ASIO_INITFN_AUTO_RESULT_TYPE(WriteHandler,+ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX(WriteToken, void (asio::error_code, std::size_t)) async_write(AsyncWriteStream& s, ASIO_MOVE_ARG(DynamicBuffer_v1) buffers,- ASIO_MOVE_ARG(WriteHandler) handler+ ASIO_MOVE_ARG(WriteToken) token ASIO_DEFAULT_COMPLETION_TOKEN( typename AsyncWriteStream::executor_type),- typename enable_if<+ typename constraint< is_dynamic_buffer_v1<typename decay<DynamicBuffer_v1>::type>::value- && !is_dynamic_buffer_v2<typename decay<DynamicBuffer_v1>::type>::value- >::type* = 0);+ >::type = 0,+ typename constraint<+ !is_dynamic_buffer_v2<typename decay<DynamicBuffer_v1>::type>::value+ >::type = 0)+ ASIO_INITFN_AUTO_RESULT_TYPE_SUFFIX((+ async_initiate<WriteToken,+ void (asio::error_code, std::size_t)>(+ declval<detail::initiate_async_write_dynbuf_v1<AsyncWriteStream> >(),+ token, ASIO_MOVE_CAST(DynamicBuffer_v1)(buffers),+ transfer_all()))); /// Start an asynchronous operation to write a certain amount of data to a /// stream. /** * This function is used to asynchronously write a certain number of bytes of- * data to a stream. The function call always returns immediately. The- * asynchronous operation will continue until one of the following conditions- * is true:+ * data to a stream. It is an initiating function for an @ref+ * asynchronous_operation, and always returns immediately. The asynchronous+ * operation will continue until one of the following conditions is true: * * @li All of the data in the supplied dynamic buffer sequence has been written. *@@ -934,8 +1019,8 @@ * @param buffers The dynamic buffer sequence from which data will be written. * Although the buffers object may be copied as necessary, ownership of the * underlying memory blocks is retained by the caller, which must guarantee- * that they remain valid until the handler is called. Successfully written- * data is automatically consumed from the buffers.+ * that they remain valid until the completion handler is called. Successfully+ * written data is automatically consumed from the buffers. * * @param completion_condition The function object to be called to determine * whether the write operation is complete. The signature of the function object@@ -951,36 +1036,60 @@ * non-zero return value indicates the maximum number of bytes to be written on * the next call to the stream's async_write_some function. *- * @param handler The handler to be called when the write operation completes.- * Copies will be made of the handler as required. The function signature of the- * handler must be:+ * @param token The @ref completion_token that will be used to produce a+ * completion handler, which will be called when the write completes.+ * Potential completion tokens include @ref use_future, @ref use_awaitable,+ * @ref yield_context, or a function object with the correct completion+ * signature. The function signature of the completion handler must be: * @code void handler(- * const asio::error_code& error, // Result of operation.+ * // Result of operation.+ * const asio::error_code& error, *- * std::size_t bytes_transferred // Number of bytes written from the- * // buffers. If an error occurred,- * // this will be less than the sum- * // of the buffer sizes.+ * // Number of bytes written from the buffers. If an error+ * // occurred, this will be less than the sum of the buffer sizes.+ * std::size_t bytes_transferred * ); @endcode * Regardless of whether the asynchronous operation completes immediately or- * not, the handler will not be invoked from within this function. On- * immediate completion, invocation of the handler will be performed in a+ * not, the completion handler will not be invoked from within this function.+ * On immediate completion, invocation of the handler will be performed in a * manner equivalent to using asio::post().+ *+ * @par Completion Signature+ * @code void(asio::error_code, std::size_t) @endcode+ *+ * @par Per-Operation Cancellation+ * This asynchronous operation supports cancellation for the following+ * asio::cancellation_type values:+ *+ * @li @c cancellation_type::terminal+ *+ * @li @c cancellation_type::partial+ *+ * if they are also supported by the @c AsyncWriteStream type's+ * @c async_write_some operation. */ template <typename AsyncWriteStream, typename DynamicBuffer_v1, typename CompletionCondition, ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code,- std::size_t)) WriteHandler>-ASIO_INITFN_AUTO_RESULT_TYPE(WriteHandler,+ std::size_t)) WriteToken>+ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX(WriteToken, void (asio::error_code, std::size_t)) async_write(AsyncWriteStream& s, ASIO_MOVE_ARG(DynamicBuffer_v1) buffers, CompletionCondition completion_condition,- ASIO_MOVE_ARG(WriteHandler) handler,- typename enable_if<+ ASIO_MOVE_ARG(WriteToken) token,+ typename constraint< is_dynamic_buffer_v1<typename decay<DynamicBuffer_v1>::type>::value- && !is_dynamic_buffer_v2<typename decay<DynamicBuffer_v1>::type>::value- >::type* = 0);+ >::type = 0,+ typename constraint<+ !is_dynamic_buffer_v2<typename decay<DynamicBuffer_v1>::type>::value+ >::type = 0)+ ASIO_INITFN_AUTO_RESULT_TYPE_SUFFIX((+ async_initiate<WriteToken,+ void (asio::error_code, std::size_t)>(+ declval<detail::initiate_async_write_dynbuf_v1<AsyncWriteStream> >(),+ token, ASIO_MOVE_CAST(DynamicBuffer_v1)(buffers),+ ASIO_MOVE_CAST(CompletionCondition)(completion_condition)))); #if !defined(ASIO_NO_EXTENSIONS) #if !defined(ASIO_NO_IOSTREAM)@@ -989,9 +1098,9 @@ /// stream. /** * This function is used to asynchronously write a certain number of bytes of- * data to a stream. The function call always returns immediately. The- * asynchronous operation will continue until one of the following conditions- * is true:+ * data to a stream. It is an initiating function for an @ref+ * asynchronous_operation, and always returns immediately. The asynchronous+ * operation will continue until one of the following conditions is true: * * @li All of the data in the supplied basic_streambuf has been written. *@@ -1008,43 +1117,62 @@ * * @param b A basic_streambuf object from which data will be written. Ownership * of the streambuf is retained by the caller, which must guarantee that it- * remains valid until the handler is called.+ * remains valid until the completion handler is called. *- * @param handler The handler to be called when the write operation completes.- * Copies will be made of the handler as required. The function signature of the- * handler must be:+ * @param token The @ref completion_token that will be used to produce a+ * completion handler, which will be called when the write completes.+ * Potential completion tokens include @ref use_future, @ref use_awaitable,+ * @ref yield_context, or a function object with the correct completion+ * signature. The function signature of the completion handler must be: * @code void handler(- * const asio::error_code& error, // Result of operation.+ * // Result of operation.+ * const asio::error_code& error, *- * std::size_t bytes_transferred // Number of bytes written from the- * // buffers. If an error occurred,- * // this will be less than the sum- * // of the buffer sizes.+ * // Number of bytes written from the buffers. If an error+ * // occurred, this will be less than the sum of the buffer sizes.+ * std::size_t bytes_transferred * ); @endcode * Regardless of whether the asynchronous operation completes immediately or- * not, the handler will not be invoked from within this function. On- * immediate completion, invocation of the handler will be performed in a+ * not, the completion handler will not be invoked from within this function.+ * On immediate completion, invocation of the handler will be performed in a * manner equivalent to using asio::post().+ *+ * @par Completion Signature+ * @code void(asio::error_code, std::size_t) @endcode+ *+ * @par Per-Operation Cancellation+ * This asynchronous operation supports cancellation for the following+ * asio::cancellation_type values:+ *+ * @li @c cancellation_type::terminal+ *+ * @li @c cancellation_type::partial+ *+ * if they are also supported by the @c AsyncWriteStream type's+ * @c async_write_some operation. */ template <typename AsyncWriteStream, typename Allocator, ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code,- std::size_t)) WriteHandler+ std::size_t)) WriteToken ASIO_DEFAULT_COMPLETION_TOKEN_TYPE( typename AsyncWriteStream::executor_type)>-ASIO_INITFN_AUTO_RESULT_TYPE(WriteHandler,+ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX(WriteToken, void (asio::error_code, std::size_t)) async_write(AsyncWriteStream& s, basic_streambuf<Allocator>& b,- ASIO_MOVE_ARG(WriteHandler) handler+ ASIO_MOVE_ARG(WriteToken) token ASIO_DEFAULT_COMPLETION_TOKEN(- typename AsyncWriteStream::executor_type));+ typename AsyncWriteStream::executor_type))+ ASIO_INITFN_AUTO_RESULT_TYPE_SUFFIX((+ async_write(s, basic_streambuf_ref<Allocator>(b),+ ASIO_MOVE_CAST(WriteToken)(token)))); /// Start an asynchronous operation to write a certain amount of data to a /// stream. /** * This function is used to asynchronously write a certain number of bytes of- * data to a stream. The function call always returns immediately. The- * asynchronous operation will continue until one of the following conditions- * is true:+ * data to a stream. It is an initiating function for an @ref+ * asynchronous_operation, and always returns immediately. The asynchronous+ * operation will continue until one of the following conditions is true: * * @li All of the data in the supplied basic_streambuf has been written. *@@ -1061,7 +1189,7 @@ * * @param b A basic_streambuf object from which data will be written. Ownership * of the streambuf is retained by the caller, which must guarantee that it- * remains valid until the handler is called.+ * remains valid until the completion handler is called. * * @param completion_condition The function object to be called to determine * whether the write operation is complete. The signature of the function object@@ -1077,31 +1205,51 @@ * non-zero return value indicates the maximum number of bytes to be written on * the next call to the stream's async_write_some function. *- * @param handler The handler to be called when the write operation completes.- * Copies will be made of the handler as required. The function signature of the- * handler must be:+ * @param token The @ref completion_token that will be used to produce a+ * completion handler, which will be called when the write completes.+ * Potential completion tokens include @ref use_future, @ref use_awaitable,+ * @ref yield_context, or a function object with the correct completion+ * signature. The function signature of the completion handler must be: * @code void handler(- * const asio::error_code& error, // Result of operation.+ * // Result of operation.+ * const asio::error_code& error, *- * std::size_t bytes_transferred // Number of bytes written from the- * // buffers. If an error occurred,- * // this will be less than the sum- * // of the buffer sizes.+ * // Number of bytes written from the buffers. If an error+ * // occurred, this will be less than the sum of the buffer sizes.+ * std::size_t bytes_transferred * ); @endcode * Regardless of whether the asynchronous operation completes immediately or- * not, the handler will not be invoked from within this function. On- * immediate completion, invocation of the handler will be performed in a+ * not, the completion handler will not be invoked from within this function.+ * On immediate completion, invocation of the handler will be performed in a * manner equivalent to using asio::post().+ *+ * @par Completion Signature+ * @code void(asio::error_code, std::size_t) @endcode+ *+ * @par Per-Operation Cancellation+ * This asynchronous operation supports cancellation for the following+ * asio::cancellation_type values:+ *+ * @li @c cancellation_type::terminal+ *+ * @li @c cancellation_type::partial+ *+ * if they are also supported by the @c AsyncWriteStream type's+ * @c async_write_some operation. */ template <typename AsyncWriteStream, typename Allocator, typename CompletionCondition, ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code,- std::size_t)) WriteHandler>-ASIO_INITFN_AUTO_RESULT_TYPE(WriteHandler,+ std::size_t)) WriteToken>+ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX(WriteToken, void (asio::error_code, std::size_t)) async_write(AsyncWriteStream& s, basic_streambuf<Allocator>& b, CompletionCondition completion_condition,- ASIO_MOVE_ARG(WriteHandler) handler);+ ASIO_MOVE_ARG(WriteToken) token)+ ASIO_INITFN_AUTO_RESULT_TYPE_SUFFIX((+ async_write(s, basic_streambuf_ref<Allocator>(b),+ ASIO_MOVE_CAST(CompletionCondition)(completion_condition),+ ASIO_MOVE_CAST(WriteToken)(token)))); #endif // !defined(ASIO_NO_IOSTREAM) #endif // !defined(ASIO_NO_EXTENSIONS)@@ -1111,9 +1259,9 @@ /// stream. /** * This function is used to asynchronously write a certain number of bytes of- * data to a stream. The function call always returns immediately. The- * asynchronous operation will continue until one of the following conditions- * is true:+ * data to a stream. It is an initiating function for an @ref+ * asynchronous_operation, and always returns immediately. The asynchronous+ * operation will continue until one of the following conditions is true: * * @li All of the data in the supplied dynamic buffer sequence has been written. *@@ -1131,47 +1279,69 @@ * @param buffers The dynamic buffer sequence from which data will be written. * Although the buffers object may be copied as necessary, ownership of the * underlying memory blocks is retained by the caller, which must guarantee- * that they remain valid until the handler is called. Successfully written- * data is automatically consumed from the buffers.+ * that they remain valid until the completion handler is called. Successfully+ * written data is automatically consumed from the buffers. *- * @param handler The handler to be called when the write operation completes.- * Copies will be made of the handler as required. The function signature of the- * handler must be:+ * @param token The @ref completion_token that will be used to produce a+ * completion handler, which will be called when the write completes.+ * Potential completion tokens include @ref use_future, @ref use_awaitable,+ * @ref yield_context, or a function object with the correct completion+ * signature. The function signature of the completion handler must be: * @code void handler(- * const asio::error_code& error, // Result of operation.+ * // Result of operation.+ * const asio::error_code& error, *- * std::size_t bytes_transferred // Number of bytes written from the- * // buffers. If an error occurred,- * // this will be less than the sum- * // of the buffer sizes.+ * // Number of bytes written from the buffers. If an error+ * // occurred, this will be less than the sum of the buffer sizes.+ * std::size_t bytes_transferred * ); @endcode * Regardless of whether the asynchronous operation completes immediately or- * not, the handler will not be invoked from within this function. On- * immediate completion, invocation of the handler will be performed in a+ * not, the completion handler will not be invoked from within this function.+ * On immediate completion, invocation of the handler will be performed in a * manner equivalent to using asio::post().+ *+ * @par Completion Signature+ * @code void(asio::error_code, std::size_t) @endcode+ *+ * @par Per-Operation Cancellation+ * This asynchronous operation supports cancellation for the following+ * asio::cancellation_type values:+ *+ * @li @c cancellation_type::terminal+ *+ * @li @c cancellation_type::partial+ *+ * if they are also supported by the @c AsyncWriteStream type's+ * @c async_write_some operation. */ template <typename AsyncWriteStream, typename DynamicBuffer_v2, ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code,- std::size_t)) WriteHandler+ std::size_t)) WriteToken ASIO_DEFAULT_COMPLETION_TOKEN_TYPE( typename AsyncWriteStream::executor_type)>-ASIO_INITFN_AUTO_RESULT_TYPE(WriteHandler,+ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX(WriteToken, void (asio::error_code, std::size_t)) async_write(AsyncWriteStream& s, DynamicBuffer_v2 buffers,- ASIO_MOVE_ARG(WriteHandler) handler+ ASIO_MOVE_ARG(WriteToken) token ASIO_DEFAULT_COMPLETION_TOKEN( typename AsyncWriteStream::executor_type),- typename enable_if<+ typename constraint< is_dynamic_buffer_v2<DynamicBuffer_v2>::value- >::type* = 0);+ >::type = 0)+ ASIO_INITFN_AUTO_RESULT_TYPE_SUFFIX((+ async_initiate<WriteToken,+ void (asio::error_code, std::size_t)>(+ declval<detail::initiate_async_write_dynbuf_v2<AsyncWriteStream> >(),+ token, ASIO_MOVE_CAST(DynamicBuffer_v2)(buffers),+ transfer_all()))); /// Start an asynchronous operation to write a certain amount of data to a /// stream. /** * This function is used to asynchronously write a certain number of bytes of- * data to a stream. The function call always returns immediately. The- * asynchronous operation will continue until one of the following conditions- * is true:+ * data to a stream. It is an initiating function for an @ref+ * asynchronous_operation, and always returns immediately. The asynchronous+ * operation will continue until one of the following conditions is true: * * @li All of the data in the supplied dynamic buffer sequence has been written. *@@ -1189,8 +1359,8 @@ * @param buffers The dynamic buffer sequence from which data will be written. * Although the buffers object may be copied as necessary, ownership of the * underlying memory blocks is retained by the caller, which must guarantee- * that they remain valid until the handler is called. Successfully written- * data is automatically consumed from the buffers.+ * that they remain valid until the completion handler is called. Successfully+ * written data is automatically consumed from the buffers. * * @param completion_condition The function object to be called to determine * whether the write operation is complete. The signature of the function object@@ -1206,34 +1376,56 @@ * non-zero return value indicates the maximum number of bytes to be written on * the next call to the stream's async_write_some function. *- * @param handler The handler to be called when the write operation completes.- * Copies will be made of the handler as required. The function signature of the- * handler must be:+ * @param token The @ref completion_token that will be used to produce a+ * completion handler, which will be called when the write completes.+ * Potential completion tokens include @ref use_future, @ref use_awaitable,+ * @ref yield_context, or a function object with the correct completion+ * signature. The function signature of the completion handler must be: * @code void handler(- * const asio::error_code& error, // Result of operation.+ * // Result of operation.+ * const asio::error_code& error, *- * std::size_t bytes_transferred // Number of bytes written from the- * // buffers. If an error occurred,- * // this will be less than the sum- * // of the buffer sizes.+ * // Number of bytes written from the buffers. If an error+ * // occurred, this will be less than the sum of the buffer sizes.+ * std::size_t bytes_transferred * ); @endcode * Regardless of whether the asynchronous operation completes immediately or- * not, the handler will not be invoked from within this function. On- * immediate completion, invocation of the handler will be performed in a+ * not, the completion handler will not be invoked from within this function.+ * On immediate completion, invocation of the handler will be performed in a * manner equivalent to using asio::post().+ *+ * @par Completion Signature+ * @code void(asio::error_code, std::size_t) @endcode+ *+ * @par Per-Operation Cancellation+ * This asynchronous operation supports cancellation for the following+ * asio::cancellation_type values:+ *+ * @li @c cancellation_type::terminal+ *+ * @li @c cancellation_type::partial+ *+ * if they are also supported by the @c AsyncWriteStream type's+ * @c async_write_some operation. */ template <typename AsyncWriteStream, typename DynamicBuffer_v2, typename CompletionCondition, ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code,- std::size_t)) WriteHandler>-ASIO_INITFN_AUTO_RESULT_TYPE(WriteHandler,+ std::size_t)) WriteToken>+ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX(WriteToken, void (asio::error_code, std::size_t)) async_write(AsyncWriteStream& s, DynamicBuffer_v2 buffers, CompletionCondition completion_condition,- ASIO_MOVE_ARG(WriteHandler) handler,- typename enable_if<+ ASIO_MOVE_ARG(WriteToken) token,+ typename constraint< is_dynamic_buffer_v2<DynamicBuffer_v2>::value- >::type* = 0);+ >::type = 0)+ ASIO_INITFN_AUTO_RESULT_TYPE_SUFFIX((+ async_initiate<WriteToken,+ void (asio::error_code, std::size_t)>(+ declval<detail::initiate_async_write_dynbuf_v2<AsyncWriteStream> >(),+ token, ASIO_MOVE_CAST(DynamicBuffer_v2)(buffers),+ ASIO_MOVE_CAST(CompletionCondition)(completion_condition)))); /*@}*/
link/modules/asio-standalone/asio/include/asio/write_at.hpp view
@@ -2,7 +2,7 @@ // write_at.hpp // ~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -18,6 +18,7 @@ #include "asio/detail/config.hpp" #include <cstddef> #include "asio/async_result.hpp"+#include "asio/completion_condition.hpp" #include "asio/detail/cstdint.hpp" #include "asio/error.hpp" @@ -28,7 +29,15 @@ #include "asio/detail/push_options.hpp" namespace asio {+namespace detail { +template <typename> class initiate_async_write_at;+#if !defined(ASIO_NO_IOSTREAM)+template <typename> class initiate_async_write_at_streambuf;+#endif // !defined(ASIO_NO_IOSTREAM)++} // namespace detail+ /** * @defgroup write_at asio::write_at *@@ -403,9 +412,10 @@ /// specified offset. /** * This function is used to asynchronously write a certain number of bytes of- * data to a random access device at a specified offset. The function call- * always returns immediately. The asynchronous operation will continue until- * one of the following conditions is true:+ * data to a random access device at a specified offset. It is an initiating+ * function for an @ref asynchronous_operation, and always returns immediately.+ * The asynchronous operation will continue until one of the following+ * conditions is true: * * @li All of the data in the supplied buffers has been written. That is, the * bytes transferred is equal to the sum of the buffer sizes.@@ -428,11 +438,13 @@ * @param buffers One or more buffers containing the data to be written. * Although the buffers object may be copied as necessary, ownership of the * underlying memory blocks is retained by the caller, which must guarantee- * that they remain valid until the handler is called.+ * that they remain valid until the completion handler is called. *- * @param handler The handler to be called when the write operation completes.- * Copies will be made of the handler as required. The function signature of- * the handler must be:+ * @param token The @ref completion_token that will be used to produce a+ * completion handler, which will be called when the write completes.+ * Potential completion tokens include @ref use_future, @ref use_awaitable,+ * @ref yield_context, or a function object with the correct completion+ * signature. The function signature of the completion handler must be: * @code void handler( * // Result of operation. * const asio::error_code& error,@@ -442,10 +454,13 @@ * std::size_t bytes_transferred * ); @endcode * Regardless of whether the asynchronous operation completes immediately or- * not, the handler will not be invoked from within this function. On- * immediate completion, invocation of the handler will be performed in a+ * not, the completion handler will not be invoked from within this function.+ * On immediate completion, invocation of the handler will be performed in a * manner equivalent to using asio::post(). *+ * @par Completion Signature+ * @code void(asio::error_code, std::size_t) @endcode+ * * @par Example * To write a single data buffer use the @ref buffer function as follows: * @code@@ -454,27 +469,45 @@ * See the @ref buffer documentation for information on writing multiple * buffers in one go, and how to use it with arrays, boost::array or * std::vector.+ *+ * @par Per-Operation Cancellation+ * This asynchronous operation supports cancellation for the following+ * asio::cancellation_type values:+ *+ * @li @c cancellation_type::terminal+ *+ * @li @c cancellation_type::partial+ *+ * if they are also supported by the @c AsyncRandomAccessWriteDevice type's+ * async_write_some_at operation. */ template <typename AsyncRandomAccessWriteDevice, typename ConstBufferSequence, ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code,- std::size_t)) WriteHandler+ std::size_t)) WriteToken ASIO_DEFAULT_COMPLETION_TOKEN_TYPE( typename AsyncRandomAccessWriteDevice::executor_type)>-ASIO_INITFN_AUTO_RESULT_TYPE(WriteHandler,+ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX(WriteToken, void (asio::error_code, std::size_t)) async_write_at(AsyncRandomAccessWriteDevice& d, uint64_t offset, const ConstBufferSequence& buffers,- ASIO_MOVE_ARG(WriteHandler) handler+ ASIO_MOVE_ARG(WriteToken) token ASIO_DEFAULT_COMPLETION_TOKEN(- typename AsyncRandomAccessWriteDevice::executor_type));+ typename AsyncRandomAccessWriteDevice::executor_type))+ ASIO_INITFN_AUTO_RESULT_TYPE_SUFFIX((+ async_initiate<WriteToken,+ void (asio::error_code, std::size_t)>(+ declval<detail::initiate_async_write_at<+ AsyncRandomAccessWriteDevice> >(),+ token, offset, buffers, transfer_all()))); /// Start an asynchronous operation to write a certain amount of data at the /// specified offset. /** * This function is used to asynchronously write a certain number of bytes of- * data to a random access device at a specified offset. The function call- * always returns immediately. The asynchronous operation will continue until- * one of the following conditions is true:+ * data to a random access device at a specified offset. It is an initiating+ * function for an @ref asynchronous_operation, and always returns immediately.+ * The asynchronous operation will continue until one of the following+ * conditions is true: * * @li All of the data in the supplied buffers has been written. That is, the * bytes transferred is equal to the sum of the buffer sizes.@@ -497,7 +530,7 @@ * @param buffers One or more buffers containing the data to be written. * Although the buffers object may be copied as necessary, ownership of the * underlying memory blocks is retained by the caller, which must guarantee- * that they remain valid until the handler is called.+ * that they remain valid until the completion handler is called. * * @param completion_condition The function object to be called to determine * whether the write operation is complete. The signature of the function object@@ -513,9 +546,11 @@ * non-zero return value indicates the maximum number of bytes to be written on * the next call to the device's async_write_some_at function. *- * @param handler The handler to be called when the write operation completes.- * Copies will be made of the handler as required. The function signature of the- * handler must be:+ * @param token The @ref completion_token that will be used to produce a+ * completion handler, which will be called when the write completes.+ * Potential completion tokens include @ref use_future, @ref use_awaitable,+ * @ref yield_context, or a function object with the correct completion+ * signature. The function signature of the completion handler must be: * @code void handler( * // Result of operation. * const asio::error_code& error,@@ -525,10 +560,13 @@ * std::size_t bytes_transferred * ); @endcode * Regardless of whether the asynchronous operation completes immediately or- * not, the handler will not be invoked from within this function. On- * immediate completion, invocation of the handler will be performed in a+ * not, the completion handler will not be invoked from within this function.+ * On immediate completion, invocation of the handler will be performed in a * manner equivalent to using asio::post(). *+ * @par Completion Signature+ * @code void(asio::error_code, std::size_t) @endcode+ * * @par Example * To write a single data buffer use the @ref buffer function as follows: * @code asio::async_write_at(d, 42,@@ -538,21 +576,39 @@ * See the @ref buffer documentation for information on writing multiple * buffers in one go, and how to use it with arrays, boost::array or * std::vector.+ *+ * @par Per-Operation Cancellation+ * This asynchronous operation supports cancellation for the following+ * asio::cancellation_type values:+ *+ * @li @c cancellation_type::terminal+ *+ * @li @c cancellation_type::partial+ *+ * if they are also supported by the @c AsyncRandomAccessWriteDevice type's+ * async_write_some_at operation. */ template <typename AsyncRandomAccessWriteDevice, typename ConstBufferSequence, typename CompletionCondition, ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code,- std::size_t)) WriteHandler+ std::size_t)) WriteToken ASIO_DEFAULT_COMPLETION_TOKEN_TYPE( typename AsyncRandomAccessWriteDevice::executor_type)>-ASIO_INITFN_AUTO_RESULT_TYPE(WriteHandler,+ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX(WriteToken, void (asio::error_code, std::size_t)) async_write_at(AsyncRandomAccessWriteDevice& d, uint64_t offset, const ConstBufferSequence& buffers, CompletionCondition completion_condition,- ASIO_MOVE_ARG(WriteHandler) handler+ ASIO_MOVE_ARG(WriteToken) token ASIO_DEFAULT_COMPLETION_TOKEN(- typename AsyncRandomAccessWriteDevice::executor_type));+ typename AsyncRandomAccessWriteDevice::executor_type))+ ASIO_INITFN_AUTO_RESULT_TYPE_SUFFIX((+ async_initiate<WriteToken,+ void (asio::error_code, std::size_t)>(+ declval<detail::initiate_async_write_at<+ AsyncRandomAccessWriteDevice> >(),+ token, offset, buffers,+ ASIO_MOVE_CAST(CompletionCondition)(completion_condition)))); #if !defined(ASIO_NO_EXTENSIONS) #if !defined(ASIO_NO_IOSTREAM)@@ -561,9 +617,10 @@ /// specified offset. /** * This function is used to asynchronously write a certain number of bytes of- * data to a random access device at a specified offset. The function call- * always returns immediately. The asynchronous operation will continue until- * one of the following conditions is true:+ * data to a random access device at a specified offset. It is an initiating+ * function for an @ref asynchronous_operation, and always returns immediately.+ * The asynchronous operation will continue until one of the following+ * conditions is true: * * @li All of the data in the supplied basic_streambuf has been written. *@@ -584,11 +641,13 @@ * * @param b A basic_streambuf object from which data will be written. Ownership * of the streambuf is retained by the caller, which must guarantee that it- * remains valid until the handler is called.+ * remains valid until the completion handler is called. *- * @param handler The handler to be called when the write operation completes.- * Copies will be made of the handler as required. The function signature of the- * handler must be:+ * @param token The @ref completion_token that will be used to produce a+ * completion handler, which will be called when the write completes.+ * Potential completion tokens include @ref use_future, @ref use_awaitable,+ * @ref yield_context, or a function object with the correct completion+ * signature. The function signature of the completion handler must be: * @code void handler( * // Result of operation. * const asio::error_code& error,@@ -598,30 +657,51 @@ * std::size_t bytes_transferred * ); @endcode * Regardless of whether the asynchronous operation completes immediately or- * not, the handler will not be invoked from within this function. On- * immediate completion, invocation of the handler will be performed in a+ * not, the completion handler will not be invoked from within this function.+ * On immediate completion, invocation of the handler will be performed in a * manner equivalent to using asio::post().+ *+ * @par Completion Signature+ * @code void(asio::error_code, std::size_t) @endcode+ *+ * @par Per-Operation Cancellation+ * This asynchronous operation supports cancellation for the following+ * asio::cancellation_type values:+ *+ * @li @c cancellation_type::terminal+ *+ * @li @c cancellation_type::partial+ *+ * if they are also supported by the @c AsyncRandomAccessWriteDevice type's+ * async_write_some_at operation. */ template <typename AsyncRandomAccessWriteDevice, typename Allocator, ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code,- std::size_t)) WriteHandler+ std::size_t)) WriteToken ASIO_DEFAULT_COMPLETION_TOKEN_TYPE( typename AsyncRandomAccessWriteDevice::executor_type)>-ASIO_INITFN_AUTO_RESULT_TYPE(WriteHandler,+ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX(WriteToken, void (asio::error_code, std::size_t)) async_write_at(AsyncRandomAccessWriteDevice& d, uint64_t offset, basic_streambuf<Allocator>& b,- ASIO_MOVE_ARG(WriteHandler) handler+ ASIO_MOVE_ARG(WriteToken) token ASIO_DEFAULT_COMPLETION_TOKEN(- typename AsyncRandomAccessWriteDevice::executor_type));+ typename AsyncRandomAccessWriteDevice::executor_type))+ ASIO_INITFN_AUTO_RESULT_TYPE_SUFFIX((+ async_initiate<WriteToken,+ void (asio::error_code, std::size_t)>(+ declval<detail::initiate_async_write_at_streambuf<+ AsyncRandomAccessWriteDevice> >(),+ token, offset, &b, transfer_all()))); /// Start an asynchronous operation to write a certain amount of data at the /// specified offset. /** * This function is used to asynchronously write a certain number of bytes of- * data to a random access device at a specified offset. The function call- * always returns immediately. The asynchronous operation will continue until- * one of the following conditions is true:+ * data to a random access device at a specified offset. It is an initiating+ * function for an @ref asynchronous_operation, and always returns immediately.+ * The asynchronous operation will continue until one of the following+ * conditions is true: * * @li All of the data in the supplied basic_streambuf has been written. *@@ -642,7 +722,7 @@ * * @param b A basic_streambuf object from which data will be written. Ownership * of the streambuf is retained by the caller, which must guarantee that it- * remains valid until the handler is called.+ * remains valid until the completion handler is called. * * @param completion_condition The function object to be called to determine * whether the write operation is complete. The signature of the function object@@ -658,9 +738,11 @@ * non-zero return value indicates the maximum number of bytes to be written on * the next call to the device's async_write_some_at function. *- * @param handler The handler to be called when the write operation completes.- * Copies will be made of the handler as required. The function signature of the- * handler must be:+ * @param token The @ref completion_token that will be used to produce a+ * completion handler, which will be called when the write completes.+ * Potential completion tokens include @ref use_future, @ref use_awaitable,+ * @ref yield_context, or a function object with the correct completion+ * signature. The function signature of the completion handler must be: * @code void handler( * // Result of operation. * const asio::error_code& error,@@ -670,23 +752,44 @@ * std::size_t bytes_transferred * ); @endcode * Regardless of whether the asynchronous operation completes immediately or- * not, the handler will not be invoked from within this function. On- * immediate completion, invocation of the handler will be performed in a+ * not, the completion handler will not be invoked from within this function.+ * On immediate completion, invocation of the handler will be performed in a * manner equivalent to using asio::post().+ *+ * @par Completion Signature+ * @code void(asio::error_code, std::size_t) @endcode+ *+ * @par Per-Operation Cancellation+ * This asynchronous operation supports cancellation for the following+ * asio::cancellation_type values:+ *+ * @li @c cancellation_type::terminal+ *+ * @li @c cancellation_type::partial+ *+ * if they are also supported by the @c AsyncRandomAccessWriteDevice type's+ * async_write_some_at operation. */ template <typename AsyncRandomAccessWriteDevice, typename Allocator, typename CompletionCondition, ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code,- std::size_t)) WriteHandler+ std::size_t)) WriteToken ASIO_DEFAULT_COMPLETION_TOKEN_TYPE( typename AsyncRandomAccessWriteDevice::executor_type)>-ASIO_INITFN_AUTO_RESULT_TYPE(WriteHandler,+ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX(WriteToken, void (asio::error_code, std::size_t)) async_write_at(AsyncRandomAccessWriteDevice& d, uint64_t offset, basic_streambuf<Allocator>& b, CompletionCondition completion_condition,- ASIO_MOVE_ARG(WriteHandler) handler+ ASIO_MOVE_ARG(WriteToken) token ASIO_DEFAULT_COMPLETION_TOKEN(- typename AsyncRandomAccessWriteDevice::executor_type));+ typename AsyncRandomAccessWriteDevice::executor_type))+ ASIO_INITFN_AUTO_RESULT_TYPE_SUFFIX((+ async_initiate<WriteToken,+ void (asio::error_code, std::size_t)>(+ declval<detail::initiate_async_write_at_streambuf<+ AsyncRandomAccessWriteDevice> >(),+ token, offset, &b,+ ASIO_MOVE_CAST(CompletionCondition)(completion_condition)))); #endif // !defined(ASIO_NO_IOSTREAM) #endif // !defined(ASIO_NO_EXTENSIONS)
link/modules/asio-standalone/asio/include/asio/yield.hpp view
@@ -2,7 +2,7 @@ // yield.hpp // ~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/src/examples/cpp03/chat/chat_message.hpp view
@@ -2,7 +2,7 @@ // chat_message.hpp // ~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -18,8 +18,11 @@ class chat_message { public:- enum { header_length = 4 };- enum { max_body_length = 512 };+ enum+ {+ header_length = 4,+ max_body_length = 512+ }; chat_message() : body_length_(0)
link/modules/asio-standalone/asio/src/examples/cpp03/http/server/connection.hpp view
@@ -2,7 +2,7 @@ // connection.hpp // ~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/src/examples/cpp03/http/server/connection_manager.hpp view
@@ -2,7 +2,7 @@ // connection_manager.hpp // ~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/src/examples/cpp03/http/server/header.hpp view
@@ -2,7 +2,7 @@ // header.hpp // ~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/src/examples/cpp03/http/server/mime_types.hpp view
@@ -2,7 +2,7 @@ // mime_types.hpp // ~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/src/examples/cpp03/http/server/reply.hpp view
@@ -2,7 +2,7 @@ // reply.hpp // ~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/src/examples/cpp03/http/server/request.hpp view
@@ -2,7 +2,7 @@ // request.hpp // ~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/src/examples/cpp03/http/server/request_handler.hpp view
@@ -2,7 +2,7 @@ // request_handler.hpp // ~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/src/examples/cpp03/http/server/request_parser.hpp view
@@ -2,7 +2,7 @@ // request_parser.hpp // ~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/src/examples/cpp03/http/server/server.hpp view
@@ -2,7 +2,7 @@ // server.hpp // ~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/src/examples/cpp03/http/server2/connection.hpp view
@@ -2,7 +2,7 @@ // connection.hpp // ~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/src/examples/cpp03/http/server2/header.hpp view
@@ -2,7 +2,7 @@ // header.hpp // ~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/src/examples/cpp03/http/server2/io_context_pool.hpp view
@@ -2,7 +2,7 @@ // io_context_pool.hpp // ~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -39,12 +39,14 @@ private: typedef boost::shared_ptr<asio::io_context> io_context_ptr;+ typedef asio::executor_work_guard<+ asio::io_context::executor_type> io_context_work; /// The pool of io_contexts. std::vector<io_context_ptr> io_contexts_; - /// The work-tracking executors that keep the io_contexts running.- std::list<asio::any_io_executor> work_;+ /// The work that keeps the io_contexts running.+ std::list<io_context_work> work_; /// The next io_context to use for a connection. std::size_t next_io_context_;
link/modules/asio-standalone/asio/src/examples/cpp03/http/server2/mime_types.hpp view
@@ -2,7 +2,7 @@ // mime_types.hpp // ~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/src/examples/cpp03/http/server2/reply.hpp view
@@ -2,7 +2,7 @@ // reply.hpp // ~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/src/examples/cpp03/http/server2/request.hpp view
@@ -2,7 +2,7 @@ // request.hpp // ~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/src/examples/cpp03/http/server2/request_handler.hpp view
@@ -2,7 +2,7 @@ // request_handler.hpp // ~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/src/examples/cpp03/http/server2/request_parser.hpp view
@@ -2,7 +2,7 @@ // request_parser.hpp // ~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/src/examples/cpp03/http/server2/server.hpp view
@@ -2,7 +2,7 @@ // server.hpp // ~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/src/examples/cpp03/http/server3/connection.hpp view
@@ -2,7 +2,7 @@ // connection.hpp // ~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/src/examples/cpp03/http/server3/header.hpp view
@@ -2,7 +2,7 @@ // header.hpp // ~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/src/examples/cpp03/http/server3/mime_types.hpp view
@@ -2,7 +2,7 @@ // mime_types.hpp // ~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/src/examples/cpp03/http/server3/reply.hpp view
@@ -2,7 +2,7 @@ // reply.hpp // ~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/src/examples/cpp03/http/server3/request.hpp view
@@ -2,7 +2,7 @@ // request.hpp // ~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/src/examples/cpp03/http/server3/request_handler.hpp view
@@ -2,7 +2,7 @@ // request_handler.hpp // ~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/src/examples/cpp03/http/server3/request_parser.hpp view
@@ -2,7 +2,7 @@ // request_parser.hpp // ~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/src/examples/cpp03/http/server3/server.hpp view
@@ -2,7 +2,7 @@ // server.hpp // ~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/src/examples/cpp03/http/server4/file_handler.hpp view
@@ -2,7 +2,7 @@ // file_handler.hpp // ~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/src/examples/cpp03/http/server4/header.hpp view
@@ -2,7 +2,7 @@ // header.hpp // ~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/src/examples/cpp03/http/server4/mime_types.hpp view
@@ -2,7 +2,7 @@ // mime_types.hpp // ~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/src/examples/cpp03/http/server4/reply.hpp view
@@ -2,7 +2,7 @@ // reply.hpp // ~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/src/examples/cpp03/http/server4/request.hpp view
@@ -2,7 +2,7 @@ // request.hpp // ~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/src/examples/cpp03/http/server4/request_parser.hpp view
@@ -2,7 +2,7 @@ // request_parser.hpp // ~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/src/examples/cpp03/http/server4/server.hpp view
@@ -2,7 +2,7 @@ // server.hpp // ~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/src/examples/cpp03/icmp/icmp_header.hpp view
@@ -2,7 +2,7 @@ // icmp_header.hpp // ~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/src/examples/cpp03/icmp/ipv4_header.hpp view
@@ -2,7 +2,7 @@ // ipv4_header.hpp // ~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/src/examples/cpp03/porthopper/protocol.hpp view
@@ -2,7 +2,7 @@ // protocol.hpp // ~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/src/examples/cpp03/serialization/connection.hpp view
@@ -2,7 +2,7 @@ // connection.hpp // ~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/src/examples/cpp03/serialization/stock.hpp view
@@ -2,7 +2,7 @@ // stock.hpp // ~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/src/examples/cpp03/services/basic_logger.hpp view
@@ -2,7 +2,7 @@ // basic_logger.hpp // ~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/src/examples/cpp03/services/logger.hpp view
@@ -2,7 +2,7 @@ // logger.hpp // ~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/src/examples/cpp03/services/logger_service.hpp view
@@ -2,7 +2,7 @@ // logger_service.hpp // ~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -44,8 +44,7 @@ logger_service(asio::execution_context& context) : asio::execution_context::service(context), work_io_context_(),- work_(asio::require(work_io_context_.get_executor(),- asio::execution::outstanding_work.tracked)),+ work_(asio::make_work_guard(work_io_context_)), work_thread_(new asio::thread( boost::bind(&asio::io_context::run, &work_io_context_))) {@@ -56,7 +55,7 @@ { /// Indicate that we have finished with the private io_context. Its /// io_context::run() function will exit once all other work has completed.- work_ = asio::any_io_executor();+ work_.reset(); if (work_thread_) work_thread_->join(); }@@ -128,10 +127,11 @@ /// Private io_context used for performing logging operations. asio::io_context work_io_context_; - /// A work-tracking executor giving work for the private io_context to- /// perform. If we do not give the io_context some work to do then the- /// io_context::run() function will exit immediately.- asio::any_io_executor work_;+ /// Work for the private io_context to perform. If we do not give the+ /// io_context some work to do then the io_context::run() function will exit+ /// immediately.+ asio::executor_work_guard<+ asio::io_context::executor_type> work_; /// Thread used for running the work io_context's run loop. boost::scoped_ptr<asio::thread> work_thread_;
link/modules/asio-standalone/asio/src/examples/cpp03/socks4/socks4.hpp view
@@ -2,7 +2,7 @@ // socks4.hpp // ~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/src/examples/cpp11/chat/chat_message.hpp view
@@ -2,7 +2,7 @@ // chat_message.hpp // ~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -18,8 +18,8 @@ class chat_message { public:- enum { header_length = 4 };- enum { max_body_length = 512 };+ static constexpr std::size_t header_length = 4;+ static constexpr std::size_t max_body_length = 512; chat_message() : body_length_(0)
link/modules/asio-standalone/asio/src/examples/cpp11/handler_tracking/custom_tracking.hpp view
@@ -2,7 +2,7 @@ // custom_tracking.hpp // ~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/src/examples/cpp11/http/server/connection.hpp view
@@ -2,7 +2,7 @@ // connection.hpp // ~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/src/examples/cpp11/http/server/connection_manager.hpp view
@@ -2,7 +2,7 @@ // connection_manager.hpp // ~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/src/examples/cpp11/http/server/header.hpp view
@@ -2,7 +2,7 @@ // header.hpp // ~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/src/examples/cpp11/http/server/mime_types.hpp view
@@ -2,7 +2,7 @@ // mime_types.hpp // ~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/src/examples/cpp11/http/server/reply.hpp view
@@ -2,7 +2,7 @@ // reply.hpp // ~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/src/examples/cpp11/http/server/request.hpp view
@@ -2,7 +2,7 @@ // request.hpp // ~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/src/examples/cpp11/http/server/request_handler.hpp view
@@ -2,7 +2,7 @@ // request_handler.hpp // ~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/src/examples/cpp11/http/server/request_parser.hpp view
@@ -2,7 +2,7 @@ // request_parser.hpp // ~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/src/examples/cpp11/http/server/server.hpp view
@@ -2,7 +2,7 @@ // server.hpp // ~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/src/examples/cpp11/socks4/socks4.hpp view
@@ -2,7 +2,7 @@ // socks4.hpp // ~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+ link/modules/asio-standalone/asio/src/examples/cpp11/type_erasure/line_reader.hpp view
@@ -0,0 +1,48 @@+//+// line_reader.hpp+// ~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com)+//+// Distributed under the Boost Software License, Version 1.0. (See accompanying+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)+//++#ifndef LINE_READER_HPP+#define LINE_READER_HPP++#include <asio/any_completion_handler.hpp>+#include <asio/async_result.hpp>+#include <asio/error.hpp>+#include <string>++class line_reader+{+private:+ virtual void async_read_line_impl(std::string prompt,+ asio::any_completion_handler<void(asio::error_code, std::string)> handler) = 0;++ struct initiate_read_line+ {+ template <typename Handler>+ void operator()(Handler handler, line_reader* self, std::string prompt)+ {+ self->async_read_line_impl(std::move(prompt), std::move(handler));+ }+ };++public:+ virtual ~line_reader() {}++ template <typename CompletionToken>+ auto async_read_line(std::string prompt, CompletionToken&& token)+ -> decltype(+ asio::async_initiate<CompletionToken, void(asio::error_code, std::string)>(+ initiate_read_line(), token, this, prompt))+ {+ return asio::async_initiate<CompletionToken, void(asio::error_code, std::string)>(+ initiate_read_line(), token, this, prompt);+ }+};++#endif // LINE_READER_HPP
+ link/modules/asio-standalone/asio/src/examples/cpp11/type_erasure/sleep.hpp view
@@ -0,0 +1,35 @@+//+// sleep.hpp+// ~~~~~~~~~+//+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com)+//+// Distributed under the Boost Software License, Version 1.0. (See accompanying+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)+//++#ifndef SLEEP_HPP+#define SLEEP_HPP++#include <asio/any_completion_handler.hpp>+#include <asio/any_io_executor.hpp>+#include <asio/async_result.hpp>+#include <asio/error.hpp>+#include <chrono>++void async_sleep_impl(+ asio::any_completion_handler<void(std::error_code)> handler,+ asio::any_io_executor ex, std::chrono::nanoseconds duration);++template <typename CompletionToken>+inline auto async_sleep(asio::any_io_executor ex,+ std::chrono::nanoseconds duration, CompletionToken&& token)+ -> decltype(+ asio::async_initiate<CompletionToken, void(std::error_code)>(+ async_sleep_impl, token, std::move(ex), duration))+{+ return asio::async_initiate<CompletionToken, void(std::error_code)>(+ async_sleep_impl, token, std::move(ex), duration);+}++#endif // SLEEP_HPP
+ link/modules/asio-standalone/asio/src/examples/cpp11/type_erasure/stdin_line_reader.hpp view
@@ -0,0 +1,30 @@+//+// stdin_line_reader.hpp+// ~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com)+//+// Distributed under the Boost Software License, Version 1.0. (See accompanying+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)+//++#ifndef STDIN_LINE_READER_HPP+#define STDIN_LINE_READER_HPP++#include "line_reader.hpp"+#include <asio/posix/stream_descriptor.hpp>++class stdin_line_reader : public line_reader+{+public:+ explicit stdin_line_reader(asio::any_io_executor ex);++private:+ void async_read_line_impl(std::string prompt,+ asio::any_completion_handler<void(asio::error_code, std::string)> handler) override;++ asio::posix::stream_descriptor stdin_;+ std::string buffer_;+};++#endif
+ link/modules/asio-standalone/asio/src/examples/cpp20/type_erasure/line_reader.hpp view
@@ -0,0 +1,39 @@+//+// line_reader.hpp+// ~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com)+//+// Distributed under the Boost Software License, Version 1.0. (See accompanying+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)+//++#ifndef LINE_READER_HPP+#define LINE_READER_HPP++#include <asio/any_completion_handler.hpp>+#include <asio/async_result.hpp>+#include <asio/error.hpp>+#include <string>++class line_reader+{+public:+ virtual ~line_reader() {}++ template <typename CompletionToken>+ auto async_read_line(std::string prompt, CompletionToken&& token)+ {+ return asio::async_initiate<CompletionToken, void(asio::error_code, std::string)>(+ [](auto handler, line_reader* self, std::string prompt)+ {+ self->async_read_line_impl(std::move(prompt), std::move(handler));+ }, token, this, prompt);+ }++private:+ virtual void async_read_line_impl(std::string prompt,+ asio::any_completion_handler<void(asio::error_code, std::string)> handler) = 0;+};++#endif // LINE_READER_HPP
+ link/modules/asio-standalone/asio/src/examples/cpp20/type_erasure/sleep.hpp view
@@ -0,0 +1,32 @@+//+// sleep.hpp+// ~~~~~~~~~+//+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com)+//+// Distributed under the Boost Software License, Version 1.0. (See accompanying+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)+//++#ifndef SLEEP_HPP+#define SLEEP_HPP++#include <asio/any_completion_handler.hpp>+#include <asio/any_io_executor.hpp>+#include <asio/async_result.hpp>+#include <asio/error.hpp>+#include <chrono>++void async_sleep_impl(+ asio::any_completion_handler<void(std::error_code)> handler,+ asio::any_io_executor ex, std::chrono::nanoseconds duration);++template <typename CompletionToken>+inline auto async_sleep(asio::any_io_executor ex,+ std::chrono::nanoseconds duration, CompletionToken&& token)+{+ return asio::async_initiate<CompletionToken, void(std::error_code)>(+ async_sleep_impl, token, std::move(ex), duration);+}++#endif // SLEEP_HPP
+ link/modules/asio-standalone/asio/src/examples/cpp20/type_erasure/stdin_line_reader.hpp view
@@ -0,0 +1,30 @@+//+// stdin_line_reader.hpp+// ~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com)+//+// Distributed under the Boost Software License, Version 1.0. (See accompanying+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)+//++#ifndef STDIN_LINE_READER_HPP+#define STDIN_LINE_READER_HPP++#include "line_reader.hpp"+#include <asio/posix/stream_descriptor.hpp>++class stdin_line_reader : public line_reader+{+public:+ explicit stdin_line_reader(asio::any_io_executor ex);++private:+ void async_read_line_impl(std::string prompt,+ asio::any_completion_handler<void(asio::error_code, std::string)> handler) override;++ asio::posix::stream_descriptor stdin_;+ std::string buffer_;+};++#endif
link/modules/asio-standalone/asio/src/tests/latency/allocator.hpp view
@@ -2,7 +2,7 @@ // allocator.hpp // ~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/src/tests/latency/high_res_clock.hpp view
@@ -2,7 +2,7 @@ // high_res_clock.hpp // ~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/src/tests/performance/handler_allocator.hpp view
@@ -2,7 +2,7 @@ // handler_allocator.cpp // ~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/src/tests/unit/archetypes/async_ops.hpp view
@@ -2,7 +2,7 @@ // async_ops.hpp // ~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/src/tests/unit/archetypes/async_result.hpp view
@@ -2,7 +2,7 @@ // async_result.hpp // ~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -12,9 +12,14 @@ #define ARCHETYPES_ASYNC_RESULT_HPP #include <asio/async_result.hpp>+#include <asio/system_executor.hpp> namespace archetypes { +struct immediate_handler+{+};+ struct lazy_handler { };@@ -25,7 +30,7 @@ template <typename R, typename Arg1> struct concrete_handler<R(Arg1)> {- concrete_handler(lazy_handler)+ concrete_handler() { } @@ -43,31 +48,88 @@ template <typename R, typename Arg1, typename Arg2> struct concrete_handler<R(Arg1, Arg2)> {- concrete_handler(lazy_handler)+ concrete_handler() { } - void operator()(typename asio::decay<Arg1>::type, typename asio::decay<Arg2>::type)+ void operator()(typename asio::decay<Arg1>::type,+ typename asio::decay<Arg2>::type) { }+}; +template <typename Signature>+struct immediate_concrete_handler : concrete_handler<Signature>+{+ typedef asio::system_executor immediate_executor_type;++ immediate_concrete_handler(immediate_handler)+ {+ }++ immediate_executor_type get_immediate_executor() const ASIO_NOEXCEPT+ {+ return immediate_executor_type();+ }+ #if defined(ASIO_HAS_MOVE)- concrete_handler(concrete_handler&&) {}+ immediate_concrete_handler(immediate_concrete_handler&&) {} private:- concrete_handler(const concrete_handler&);+ immediate_concrete_handler(const immediate_concrete_handler&); #endif // defined(ASIO_HAS_MOVE) }; +template <typename Signature>+struct lazy_concrete_handler : concrete_handler<Signature>+{+ lazy_concrete_handler(lazy_handler)+ {+ }++#if defined(ASIO_HAS_MOVE)+ lazy_concrete_handler(lazy_concrete_handler&&) {}+private:+ lazy_concrete_handler(const lazy_concrete_handler&);+#endif // defined(ASIO_HAS_MOVE)+};+ } // namespace archetypes namespace asio { template <typename Signature>+class async_result<archetypes::immediate_handler, Signature>+{+public:+ // The concrete completion handler type.+ typedef archetypes::immediate_concrete_handler<Signature>+ completion_handler_type;++ // The return type of the initiating function.+ typedef void return_type;++ // Construct an async_result from a given handler.+ explicit async_result(completion_handler_type&)+ {+ }++ // Obtain the value to be returned from the initiating function.+ void get()+ {+ }++private:+ // Disallow copying and assignment.+ async_result(const async_result&) ASIO_DELETED;+ async_result& operator=(const async_result&) ASIO_DELETED;+};++template <typename Signature> class async_result<archetypes::lazy_handler, Signature> { public: // The concrete completion handler type.- typedef archetypes::concrete_handler<Signature> completion_handler_type;+ typedef archetypes::lazy_concrete_handler<Signature> completion_handler_type; // The return type of the initiating function. typedef int return_type;
link/modules/asio-standalone/asio/src/tests/unit/archetypes/gettable_socket_option.hpp view
@@ -2,7 +2,7 @@ // gettable_socket_option.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/src/tests/unit/archetypes/io_control_command.hpp view
@@ -2,7 +2,7 @@ // io_control_command.hpp // ~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/src/tests/unit/archetypes/settable_socket_option.hpp view
@@ -2,7 +2,7 @@ // settable_socket_option.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/src/tests/unit/unit_test.hpp view
@@ -2,7 +2,7 @@ // unit_test.hpp // ~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
tidal-link.cabal view
@@ -1,6 +1,6 @@ cabal-version: 2.4 name: tidal-link-version: 1.0.1+version: 1.0.2 synopsis: Ableton Link integration for Tidal -- description: homepage: http://tidalcycles.org/@@ -39,7 +39,7 @@ winmm ws2_32 cxx-options:- -DLINK_PLATFORM_WINDOWS=1 -Wno-multichar -Wno-subobject-linkage+ -DLINK_PLATFORM_WINDOWS=1 -Wno-multichar elif os(darwin) cxx-options: -DLINK_PLATFORM_MACOSX=1 -std=c++14 -Wno-multichar -Wno-subobject-linkage